initial commit

This commit is contained in:
2020-09-04 22:21:23 +03:00
commit 5a49104273
68 changed files with 8387 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
/.svn
CMakeLists.txt.user*

2
AUTHORS.txt Normal file
View File

@@ -0,0 +1,2 @@
peri4 = Пелипенко Иван <peri4ko@yandex.ru>
andrey = Бычков Андрей <andrey@signalmodelling.ru>

76
CMakeLists.txt Normal file
View File

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

165
LICENSE.txt Normal file
View File

@@ -0,0 +1,165 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
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.

3
README.md Normal file
View File

@@ -0,0 +1,3 @@
# Control & Debug library
## Introduction

141
cmake/FindCD.cmake Normal file
View File

@@ -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 "")

1
libs/CMakeLists.txt Normal file
View File

@@ -0,0 +1 @@
add_directories_with_include("qad_")

View File

@@ -0,0 +1,37 @@
cmake_minimum_required(VERSION 3.0)
project(cd_utils)
find_package(MinGW REQUIRED)
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${PIP_INCLUDES})
file(GLOB CPPS_UTILS "cdutils_*.cpp")
file(GLOB HDRS_UTILS "cdutils_*.h")
add_library(${PROJECT_NAME} SHARED ${CPPS_UTILS} ${HDRS_UTILS})
target_link_libraries(${PROJECT_NAME} ${PIP_LIBRARY})
generate_export_header(${PROJECT_NAME})
list(APPEND HDRS_UTILS "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}_export.h")
add_executable(cdutilstest "cdutilstest.cpp" "cdtest.h")
target_link_libraries(cdutilstest ${PIP_LIBRARY} ${PROJECT_NAME})
message(STATUS "Building ${PROJECT_NAME}")
if(LIB)
list(APPEND _ALL_TARGETS ${PROJECT_NAME})
set(_ALL_TARGETS ${_ALL_TARGETS} PARENT_SCOPE)
if(WIN32)
install(FILES ${HDRS_UTILS} DESTINATION ${MINGW_INCLUDE})
install(TARGETS ${PROJECT_NAME} ARCHIVE DESTINATION ${MINGW_LIB})
install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION ${MINGW_BIN})
else()
install(FILES ${HDRS_UTILS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include)
install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib)
endif()
#message(STATUS "Install ${PROJECT_NAME} to system \"${CMAKE_INSTALL_PREFIX}\"")
else()
if(WIN32)
install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin)
install(TARGETS ${PROJECT_NAME} ARCHIVE DESTINATION lib)
else()
install(TARGETS ${PROJECT_NAME} DESTINATION lib)
endif()
install(FILES ${HDRS_UTILS} DESTINATION include)
#message(STATUS "Install ${PROJECT_NAME} to local \"bin\"")
endif()

10
libs/cd_utils/cdtest.h Normal file
View File

@@ -0,0 +1,10 @@
#ifndef CDTEST_H
#define CDTEST_H
enum KDescription {
First, //f Первый
Second, //b Второй
};
#endif // CDTEST_H

View File

@@ -0,0 +1,41 @@
#include "cdutils_c.h"
#include "cdutils_core.h"
using namespace CDUtils;
CInterface C;
CInterface::CInterface(): Interface(CDType::cdC) {
}
void CInterface::sendCommand(const CDType & c) {
core->sendCommand(c);
}
void CInterface::connect(const CDType & c, PIObject * o, Handler eh) {
core->registerCHandler(c, o, eh);
}
void CInterface::autoConnect(PIObject * o, const PIString & prefix) {
if (!o) return;
uint cid = o->classNameID();
if (!PIObject::__meta_data().contains(cid)) return;
PIMap<PIString, Handler> eh_map;
PIObject::__MetaData & md(PIObject::__meta_data()[cid]);
PIMap<const void * , __MetaFunc>::const_iterator it;
for (it = md.eh_func.constBegin(); it != md.eh_func.constEnd(); ++it) {
eh_map[it.value().func_name] = (Handler)it.value().addr;
//piCout << "func" << it.value().func_name;
}
PIVector<CDType * > cl = C.root().children();
piForeachC (CDType * c, cl) {
PIString cp = prefix + c->pathString().join("_");
if (cp.isEmpty()) continue;
if (!eh_map.contains(cp)) continue;
connect(*c, o, eh_map[cp]);
}
}

46
libs/cd_utils/cdutils_c.h Normal file
View File

@@ -0,0 +1,46 @@
/*
CD Utils - Control-Debug utilites
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CDUTILS_C_H
#define CDUTILS_C_H
#include "cdutils_interface.h"
#include "cd_utils_export.h"
namespace CDUtils {
class CD_UTILS_EXPORT CInterface: public Interface
{
PIOBJECT_SUBCLASS(CInterface, Interface)
public:
CInterface();
void sendCommand(const CDType & c);
void connect(const CDType & c, PIObject * o, Handler eh);
void autoConnect(PIObject * o, const PIString & prefix = PIStringAscii("c_"));
};
}
extern CD_UTILS_EXPORT CDUtils::CInterface C;
#endif // CDUTILS_C_H

View File

@@ -0,0 +1,606 @@
#include "cdutils_core.h"
#include "cdutils_parser.h"
#include "piconfig.h"
#include "piiobytearray.h"
#include "piiostring.h"
#include "pifile.h"
using namespace CDUtils;
const char CDCore::app_config[] =
"include = cd_ip.conf\n\
port_rec = 2\n\
port_send = 1\n\
[connection]\n\
device.cd = peer://cd_app:cd_pult #s\n\
[]\n\
connectionmodel = AAAM2Xja7VXLTttAFD12QpsikKjUSixYlLbKEpIUtVIlVEfqhk2FWuiGRRolUYtoHgrmpYiv6IItf8AveMMH9E/YsG6Ph3sde5hGoQoblLGuPHfunTPjc49nADxDA110+LTYC7FrPCAPeAO+vZu+aX7c/8PGd45WCJC0OGcfT6FDnmfSTPtwhZFt3HjgDs/Qtu5jPbZHtI/x50XfIzMQbdwEolbg9INP4ku++myPaUtCHYRaT2j1ldIh3VP60/Qff8vSfXLu9BP6JX9K/0TVH6jqVe22P1X/fao/oddWu/paDs1vBf9Jv/EZ91clbyHqv7BL6sscDOd4v4WTqs6jzaHGJ8QJerxlpJSpdZ7IWFJvDW7I2JxZqIM62k6A57RZmMQGmlyrxdV+WGBnmR01mXPI267hBKwp4FeBeo9VPtssxyb7rzHg1B7T9nCMU45U8BZlWuVWtIcD/CRGOqtsbW09851tXsHN0UTlLIAdASjSXnLyLn+H7L2+xbGYvC63Ezqg543egkLmn8qnRF6USbM4Qp9godkhzI777Ne5bCIt/5UtGz2o/yGby0nKpjqmbOa1ynkjmyzIrzvIZUeBPjvlUmbh32EFJbGyJZhR8YcvlS+3TpjhqeWSyvUkpbI9plSWtcKLcsK05beOJVEnhaEFfHEH+RwpeMcpn1JKGqWMNOL+G6wZyahlpdVOtufKfbDS+guLke9O\n\
";
const char CDCore::pult_config[] =
"include = cd_ip.conf\n\
port_rec = 1\n\
port_send = 2\n\
[connection]\n\
device.cd = peer://cd_pult:cd_app #s\n\
[]\n\
connectionmodel = AAAM2Xja7VXLTttAFD12QpsikKjUSixYlLbKEpIUtVIlVEfqhk2FWuiGRRolUYtoHgrmpYiv6IItf8AveMMH9E/YsG6Ph3sde5hGoQoblLGuPHfunTPjc49nADxDA110+LTYC7FrPCAPeAO+vZu+aX7c/8PGd45WCJC0OGcfT6FDnmfSTPtwhZFt3HjgDs/Qtu5jPbZHtI/x50XfIzMQbdwEolbg9INP4ku++myPaUtCHYRaT2j1ldIh3VP60/Qff8vSfXLu9BP6JX9K/0TVH6jqVe22P1X/fao/oddWu/paDs1vBf9Jv/EZ91clbyHqv7BL6sscDOd4v4WTqs6jzaHGJ8QJerxlpJSpdZ7IWFJvDW7I2JxZqIM62k6A57RZmMQGmlyrxdV+WGBnmR01mXPI267hBKwp4FeBeo9VPtssxyb7rzHg1B7T9nCMU45U8BZlWuVWtIcD/CRGOqtsbW09851tXsHN0UTlLIAdASjSXnLyLn+H7L2+xbGYvC63Ezqg543egkLmn8qnRF6USbM4Qp9godkhzI777Ne5bCIt/5UtGz2o/yGby0nKpjqmbOa1ynkjmyzIrzvIZUeBPjvlUmbh32EFJbGyJZhR8YcvlS+3TpjhqeWSyvUkpbI9plSWtcKLcsK05beOJVEnhaEFfHEH+RwpeMcpn1JKGqWMNOL+G6wZyahlpdVOtufKfbDS+guLke9O\n\
";
int __Core_Initializer__::count_(0);
CDCore * __Core_Initializer__::__instance__(0);
const uchar header_direct = 0x80;
const uchar header_transfer = 0x81;
__Core_Initializer__::__Core_Initializer__() {
count_++;
if (count_ > 1) return;
__instance__ = new CDCore();
}
__Core_Initializer__::~__Core_Initializer__() {
count_--;
if (count_ < 0) {
count_ = 0;
return;
}
if (count_ > 0) return;
if (__instance__) {
delete __instance__;
__instance__ = 0;
}
}
CDCore::CDCore() {
setName("CDCore");
x_timer.setName("__S__.CDCore.x_timer");
datatr.setPacketSize(960);
CONNECTU(&connection, dataReceivedEvent, this, dataReceived);
CONNECTU(PICout::Notifier::object(), finished, this, piCoutFinished);
/*PIString s(app_config);
connection.configureFromString(&s);
connection.start();*/
need_rebuild_x = x_pult_side = false;
k_.cd_type_ = CDType::cdK;
x_.cd_type_ = CDType::cdX;
c_.cd_type_ = CDType::cdC;
m_.cd_type_ = CDType::cdM;
initRoot(&k_);
initRoot(&x_);
initRoot(&c_);
initRoot(&m_);
CONNECTU(&sendt, started, this, sendThread)
CONNECTU(&datatr, sendRequest, this, dtSendRequest)
CONNECTU(&datatr, receiveFinished, this, dtReceiveFinished)
CONNECTU(&x_timer, tickEvent, this, xTimerTick)
/*k_[1] = KType(1, "123", "120+3", "comment");
k_[2] = KType(2, "1", "2", "comm");
k_[4] = KType(4, "-0.6", "-6/10", "mment");
k_.section(10)[5] = KType(5, "8", "2*2*2", "88");
k_.section(10).section(50)[100] = KType(100, "8", "2*2*2", "88");
k_.section(11)[3] = KType(3, "1", "1", "88");
k_.section(11)[4] = KType(4, "0", "0", "88");
k_.section(11)[6] = KType(6, "0", "0", "88");*/
//piCout << s;
}
CDCore::~CDCore() {
x_timer.stop(true);
datatr.stop();
sendt.stop();
sendt.waitForFinish(10);
connection.stop();
}
void CDCore::cd_write(CDSection * cd, PIIODevice * d) {
cd->write(d, PIString());
}
void CDCore::cd_read(CDSection * cd, PIIODevice * d) {
PIConfig conf(d, PIIODevice::ReadOnly);
cd->read(&(conf.rootEntry()));
if (cd->cd_type_ == CDType::cdX)
x_selected = cd->collectX();
initRoot(cd);
raiseChangedGlobal(cd->cd_type_);
/*PIVector<PIIODevice * > ds = connection.allDevices();
piForeach(PIIODevice * d, ds) {
if (d)
piCoutObj << d->constructFullPath() << d->isOpened();
}*/
}
void CDCore::cd_parse(CDSection * cd, PIIODevice * d) {
*cd = CDParser::parse(d, cd->cd_type_);
initRoot(cd);
raiseChangedGlobal(cd->cd_type_);
}
void CDCore::cd_update(CDSection * cd, PIIODevice * d, UpdateModeFlags mode) {
CDSection ucd = *cd;
cd_parse(cd, d);
/*bool kn = true;
if (!ucd.isEmpty())
if (!ucd.isSameStructure(k_)) {
piCout << "ask for save names";
K_KeepNamesRequest(&kn);
}*/
ucd.update(*cd, mode);
//piCout << k_.count() << ucd.count();
*cd = ucd;
initRoot(cd);
raiseChangedGlobal(cd->cd_type_);
}
void CDCore::cd_calculate(CDSection * cd) {
cd->calculate();
raiseChangedGlobal(cd->cd_type_);
}
void CDCore::cd_send(CDSection * cd, CDPacketType pt, bool direct) {
if (!cd) return;
PIByteArray ba, sba;
PIIOByteArray iob(&ba, PIIODevice::ReadWrite);
cd_write(cd, &iob);
//piCoutObj << PIString(ba);
sba = makeHeader(pt, 0);
sba << ba;
if (direct)
sendDirect(sba);
else
sendThreaded(sba);
}
void CDCore::send(CDType::cdT cdt) {
CDPacketType pt = CD_Ping;
switch (cdt) {
case CDType::cdK: pt = CD_KSend; break;
case CDType::cdX: pt = CD_XSend; break;
case CDType::cdC: pt = CD_CSend; break;
case CDType::cdM: pt = CD_MSend; break;
default: break;
}
piCoutObj << "send" << typeLetter(cdt);
cd_send(root(cdt), pt);
}
void CDCore::request(CDType::cdT cdt) {
CDPacketType pt = CD_Ping;
switch (cdt) {
case CDType::cdK: pt = CD_KQuery; break;
case CDType::cdX: pt = CD_XQuery; break;
case CDType::cdC: pt = CD_CQuery; break;
case CDType::cdM: pt = CD_MQuery; break;
default: break;
}
piCoutObj << "request" << typeLetter(cdt);
PIByteArray sba = makeHeader(pt, 0);
sendThreaded(sba);
}
void CDCore::initApp() {
init(appConfig(), false);
}
void CDCore::initPult() {
init(pultConfig(), true);
}
void CDCore::init(const PIString & configuration, bool pult) {
PIString c = configuration;
//piCoutObj << "init" << c;
connection.stop();
connection.removeAllDevices();
connection.configureFromString(&c);
connection.start();
x_pult_side = pult;
}
void CDCore::stop() {
x_timer.stop();
x_timer.waitForFinish(1000);
connection.stop();
}
void CDCore::release() {
stop();
connection.removeAllDevices();
}
void CDCore::startX(double freq) {
//piCout << "start x" << x_timer.isRunning() << freq;
if (!x_timer.isRunning())
x_timer.start(1000. / piMaxd(freq, 0.01));
}
void CDCore::stopX() {
x_timer.stop();
x_timer.waitForFinish(1000);
}
void CDCore::sendCommand(const CDType & c) {
//piCoutObj << "C_sendCommand" << c;
PIByteArray sba = makeHeader(CD_Command, 0);
sba << c.path();
sendDirect(sba);
}
void CDCore::registerCHandler(const CDType & c, PIObject * o, Handler h) {
PIString sp = pathToString(c.path());
if (sp.isEmpty() || !h) return;
//piCout << "register" << sp;
c_handlers[sp] = OHPair(o, h);
}
void CDCore::sendMessage(const CDType & m, MessageType mt, const PIString & msg) {
if (msg.isEmpty() || (m.cd_type() != CDType::cdM)) return;
PIByteArray sba = makeHeader(CD_Message, 0);
sba << m.path() << int(mt) << msg;
sendDirect(sba);
}
CDSection * CDCore::root(CDType::cdT cdt) {
switch (cdt) {
case CDType::cdK: return &k_; break;
case CDType::cdX: return &x_; break;
case CDType::cdC: return &c_; break;
case CDType::cdM: return &m_; break;
default: break;
}
return 0;
}
PIString CDCore::typeLetter(CDType::cdT cdt) {
switch (cdt) {
case CDType::cdK: return PIStringAscii("k"); break;
case CDType::cdX: return PIStringAscii("x"); break;
case CDType::cdC: return PIStringAscii("c"); break;
case CDType::cdM: return PIStringAscii("m"); break;
default: break;
}
return PIString();
}
CDCore * CDCore::instance() {
/*static CDCore * ret = new CDCore();
return ret;*/
return __Core_Initializer__::__instance__;
}
bool CDCore::destroy() {
if (!__Core_Initializer__::__instance__) return false;
// piCout << "delete Core ...";
delete __Core_Initializer__::__instance__;
// piCout << "delete Core ok";
__Core_Initializer__::__instance__ = 0;
__Core_Initializer__::count_ = 0;
return true;
}
void CDUtils::CDCore::K_DirectChange(PIDeque<int> path, PIString value) {
// piCoutObj << "K_DirectChange";
PacketKDirectChange p;
p.path = path;
p.value = value;
PIByteArray sba = makeHeader(CD_KDirectChange, 0);
sba << p;
sendDirect(sba);
}
void CDCore::sendThread() {
if (send_data.size_s() < 4) return;
PacketHeader h;
memcpy(&h, send_data.data(), sizeof(h));
bool ok = datatr.send(send_data);
switch (h.type) {
case CD_KSend:
if (ok) K_Sended();
else K_SendFail();
break;
case CD_KQuery:
if (!ok) K_ReceiveFail();
break;
case CD_XSend:
if (ok) X_Sended();
else X_SendFail();
break;
case CD_XQuery:
if (!ok) X_ReceiveFail();
break;
case CD_CSend:
if (ok) C_Sended();
else C_SendFail();
break;
case CD_CQuery:
if (!ok) C_ReceiveFail();
break;
case CD_MSend:
if (ok) M_Sended();
else M_SendFail();
break;
case CD_MQuery:
if (!ok) M_ReceiveFail();
break;
default: break;
}
}
void CDCore::xTimerTick() {
//piCout << "x tick" << x_pult_side;
PIByteArray ba;
x_mutex.lock();
if (x_pult_side) {
ba = makeHeader(CD_XRequest, 0);
if (need_rebuild_x) {
x_selected = x_.collectX();
//piCout << "collectX" << x_selected.size();
need_rebuild_x = false;
}
ba << x_selected;
//piCout << "x pult send" << x_selected.size();
} else {
ba = makeHeader(CD_XValues, 0);
ba << x_selected;
piForeachC (PIDeque<int> & p, x_selected) {
x_[p].writeX(ba);
}
//piCout << "x app" << x_selected.size();
}
x_mutex.unlock();
sendDirect(ba);
}
void CDCore::piCoutFinished(int id, PIString * buffer) {
if (!buffer || !(id == 1)) return;
PIString sp = buffer->takeRange("[", "]");
PIDeque<int> p = CDCore::stringToPath(sp);
sendMessage(m_[p], Log, *buffer);
delete buffer;
}
void CDCore::initRoot(CDSection * r) {
r->name = "__root__";
r->alias = "root";
r->makePath();
r->calculate();
}
PIByteArray CDCore::makeHeader(CDPacketType type, int session_id) const {
PacketHeader h;
h.type = type;
h.session_id = session_id;
PIByteArray ret; ret << h;
return ret;
}
void CDCore::sendDirect(PIByteArray & ba) {
ba.push_front(header_direct);
connection.writeByName("cd", ba);
}
void CDCore::sendThreaded(PIByteArray & ba) {
if (sendt.isRunning()) {
piCoutObj << "Send in process, abort";
return;
}
send_data = ba;
sendt.startOnce();
}
void CDCore::procReceivedPacket(PIByteArray & ba) {
PacketHeader h;
ba >> h;
switch(h.type) {
case CD_Ping:
//piCoutObj << "ping";
break;
case CD_KQuery:
send(CDType::cdK);
break;
case CD_KSend: {
PIByteArray k;
ba >> k;
k << uchar(0);
PIString s = PIString::fromUTF8((const char *)k.data());
PIIOString ios(&s);
cd_read(&k_, &ios);
K_Received();
piCoutObj << "K received";
} break;
case CD_KDirectChange: {
PacketKDirectChange p;
ba >> p;
k_[p.path].setValue(p.value);
} break;
case CD_XQuery:
send(CDType::cdX);
break;
case CD_XSend: {
PIByteArray x;
ba >> x;
x << uchar(0);
PIString s = PIString::fromUTF8((const char *)x.data());
PIIOString ios(&s);
cd_read(&x_, &ios);
x_selected = x_.collectX();
X_Received();
piCoutObj << "X received";
} break;
case CD_XRequest: {
if (x_pult_side) break;
//break;
x_mutex.lock();
x_selected.clear();
ba >> x_selected;
//piCout << "X req" << x_selected.size();
x_.setSelectedX(false);
piForeachC (PIDeque<int> & p, x_selected) {
x_[p].x_enabled = true;
}
x_mutex.unlock();
} break;
case CD_XValues: {
if (!x_pult_side) break;
PIVector<PIDeque<int> > x_vals;
ba >> x_vals;
x_mutex.lock();
piForeachC (PIDeque<int> & p, x_vals) {
x_[p].readX(ba);
}
x_mutex.unlock();
X_ReceivedX(x_vals);
} break;
case CD_CQuery:
send(CDType::cdC);
break;
case CD_CSend: {
piCoutObj << "C received";
PIByteArray c;
ba >> c;
c << uchar(0);
PIString s = PIString::fromUTF8((const char *)c.data());
PIIOString ios(&s);
cd_read(&c_, &ios);
C_Received();
} break;
case CD_Command: {
piCoutObj << "C command";
PIDeque<int> p;
ba >> p;
if (p.isEmpty()) return;
PIString sp = pathToString(p);
OHPair h = c_handlers.value(sp, OHPair(0, 0));
//piCoutObj << "found" << sp << h.first;
if (h.first && h.second) h.second(h.first);
} break;
case CD_MQuery:
send(CDType::cdM);
break;
case CD_MSend: {
piCoutObj << "M received";
PIByteArray c;
ba >> c;
c << uchar(0);
PIString s = PIString::fromUTF8((const char *)c.data());
PIIOString ios(&s);
cd_read(&m_, &ios);
M_Received();
} break;
case CD_Message: {
PIDeque<int> p;
ba >> p;
piCoutObj << "M message" << p;
if (p.isEmpty()) return;
int t = 0;
PIString msg;
ba >> t >> msg;
//piCoutObj << "found" << sp << h.first;
//piCoutObj << "M message invoke";
M_Message(p, t, msg);
} break;
default: break;
}
}
void CDCore::raiseChangedGlobal(CDType::cdT cdt) {
switch (cdt) {
case CDType::cdK: K_ChangedGlobal(); break;
case CDType::cdX: X_ChangedGlobal(); break;
case CDType::cdC: C_ChangedGlobal(); break;
case CDType::cdM: M_ChangedGlobal(); break;
default: break;
}
}
PIString CDCore::pathToString(const PIDeque<int> & p) {
PIString ret;
for (int i = 0; i < p.size_s(); ++i) {
if (!ret.isEmpty()) ret += ".";
ret << p[i];
}
return ret;
}
PIDeque<int> CDCore::stringToPath(const PIString & p) {
PIDeque<int> ret;
PIStringList sl = p.split(".");
piForeachC (PIString & s, sl)
ret << s.toInt();
return ret;
}
void CDUtils::CDCore::dataReceived(const PIString & from, const PIByteArray & data) {
//piCoutObj << "dataReceived" << from << data.size();
PIIODevice * d = connection.deviceByName("cd");
if (d && d == connection.deviceByFullPath(from)) {
if (data.size() >= sizeof(4)) {
PIByteArray ba = data;
uchar header = ba.take_front();
if (header == header_transfer) {
datatr.received(ba);
}
if (header == header_direct) {
procReceivedPacket(ba);
}
}
}
}
void CDCore::dtSendRequest(PIByteArray & data) {
data.push_front(header_transfer);
connection.writeByName("cd", data);
//piCoutObj << "send" << data.size() << ret;
}
void CDCore::dtReceiveFinished(bool ok) {
if (!ok) return;
PIByteArray ba = datatr.data();
procReceivedPacket(ba);
}

View File

@@ -0,0 +1,147 @@
/*
CD Utils - Control-Debug utilites
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CDUTILS_CORE_H
#define CDUTILS_CORE_H
#include "cdutils_types.h"
#include "cdutils_protocol.h"
#include "piconnection.h"
#include "pidatatransfer.h"
#include "cd_utils_export.h"
namespace CDUtils {
class CDCore;
class CD_UTILS_EXPORT __Core_Initializer__ {
public:
__Core_Initializer__();
~__Core_Initializer__();
static int count_;
static CDCore * __instance__;
};
class CD_UTILS_EXPORT CDCore: public PIObject
{
PIOBJECT(CDUtils::CDCore)
friend class __Core_Initializer__;
friend class CDSection;
friend class Interface;
friend class XInterface;
public:
static CDCore * instance();
static bool destroy();
EVENT(K_Sended)
EVENT(K_SendFail)
EVENT(K_Received)
EVENT(K_ReceiveFail)
EVENT(K_ChangedGlobal)
EVENT_HANDLER2(void, K_DirectChange, PIDeque<int>, path, PIString, value);
EVENT(X_Sended)
EVENT(X_SendFail)
EVENT(X_Received)
EVENT(X_ReceiveFail)
EVENT(X_ChangedGlobal)
EVENT1(X_ReceivedX, PIVector<PIDeque<int> >, pathes)
EVENT(C_Sended)
EVENT(C_SendFail)
EVENT(C_Received)
EVENT(C_ReceiveFail)
EVENT(C_ChangedGlobal)
EVENT(M_Sended)
EVENT(M_SendFail)
EVENT(M_Received)
EVENT(M_ReceiveFail)
EVENT(M_ChangedGlobal)
EVENT3(M_Message, PIDeque<int>, path, int, type, PIString, msg)
void cd_write (CDSection * cd, PIIODevice * d);
void cd_read (CDSection * cd, PIIODevice * d);
void cd_parse (CDSection * cd, PIIODevice * d);
void cd_update (CDSection * cd, PIIODevice * d, UpdateModeFlags mode);
void cd_calculate(CDSection * cd);
void cd_send (CDSection * cd, CDPacketType pt, bool direct = false);
void send(CDType::cdT cdt);
void request(CDType::cdT cdt);
void initApp();
void initPult();
void init(const PIString & configuration, bool pult = false);
void stop();
void release();
void startX(double freq = 20.);
void stopX();
void sendCommand(const CDType & c);
void registerCHandler(const CDType & c, PIObject * o, Handler h);
bool inProgress() {return sendt.isRunning();}
void sendMessage(const CDType & m, MessageType mt, const PIString & msg);
CDSection * root(CDType::cdT cdt);
PIString typeLetter(CDType::cdT cdt);
static PIString pathToString(const PIDeque<int> & p);
static PIDeque<int> stringToPath(const PIString & p);
static PIString pultConfig() {return PIString(pult_config);}
static PIString appConfig() {return PIString(app_config);}
private:
CDCore();
~CDCore();
EVENT_HANDLER2(void, dataReceived, const PIString &, from, const PIByteArray &, data);
EVENT_HANDLER1(void, dtSendRequest, PIByteArray &, data);
EVENT_HANDLER1(void, dtReceiveFinished, bool, ok);
EVENT_HANDLER(void, sendThread);
EVENT_HANDLER(void, xTimerTick);
EVENT_HANDLER2(void, piCoutFinished, int, id, PIString*, buffer);
void initRoot(CDSection * r);
PIByteArray makeHeader(CDPacketType type, int session_id = 0) const;
void sendDirect(PIByteArray & ba);
void sendThreaded(PIByteArray & ba);
void procReceivedPacket(PIByteArray & ba);
void raiseChangedGlobal(CDType::cdT cdt);
typedef PIPair<PIObject * , Handler> OHPair;
static const char app_config[], pult_config[];
PIConnection connection;
PIDataTransfer datatr;
PIByteArray send_data;
PIThread sendt;
PITimer x_timer;
CDSection k_, x_, c_, m_;
PIMutex x_mutex;
PIVector<PIDeque<int> > x_selected;
PIMap<PIString, OHPair> c_handlers;
bool need_rebuild_x, x_pult_side;
};
static __Core_Initializer__ __Core_initializer__;
}
#endif // CDUTILS_CORE_H

View File

@@ -0,0 +1,217 @@
#include "cdutils_interface.h"
#include "cdutils_core.h"
#include "piconfig.h"
#include "pifile.h"
using namespace CDUtils;
Interface::Interface(CDType::cdT type_) {
core = CDCore::instance();
s = core->root(type_);
type = type_;
//piCoutObj << (void*)this << core;
file_ = core->typeLetter(type_) + PIStringAscii(".dat");
file_size = 0;
switch (type) {
case CDType::cdK:
CONNECTU(core, K_Sended, this, sended);
CONNECTU(core, K_SendFail, this, sendFailed);
CONNECTU(core, K_Received, this, received);
CONNECTU(core, K_ReceiveFail, this, receiveFailed);
CONNECTU(core, K_ChangedGlobal, this, changedGlobal);
break;
case CDType::cdX:
CONNECTU(core, X_Sended, this, sended);
CONNECTU(core, X_SendFail, this, sendFailed);
CONNECTU(core, X_Received, this, received);
CONNECTU(core, X_ReceiveFail, this, receiveFailed);
CONNECTU(core, X_ChangedGlobal, this, changedGlobal);
break;
case CDType::cdC:
CONNECTU(core, C_Sended, this, sended);
CONNECTU(core, C_SendFail, this, sendFailed);
CONNECTU(core, C_Received, this, received);
CONNECTU(core, C_ReceiveFail, this, receiveFailed);
CONNECTU(core, C_ChangedGlobal, this, changedGlobal);
break;
case CDType::cdM:
CONNECTU(core, M_Sended, this, sended);
CONNECTU(core, M_SendFail, this, sendFailed);
CONNECTU(core, M_Received, this, received);
CONNECTU(core, M_ReceiveFail, this, receiveFailed);
CONNECTU(core, M_ChangedGlobal, this, changedGlobal);
break;
default: break;
}
}
bool Interface::test(int v) {
return s->test(v);
}
CDType & Interface::operator [](const PIString & name_) {
return (*s)[name_];
}
const CDType Interface::operator [](const PIString & name_) const {
return (*s)[name_];
}
CDType & Interface::operator [](const PIDeque<int> & path_) {
return (*s)[path_];
}
const CDType Interface::operator [](const PIDeque<int> & path_) const {
return (*s)[path_];
}
CDType & Interface::operator [](int v) {
//piCout << (void*)this << "[]" << core;
return (*s)[v];
}
const CDType Interface::operator [](int v) const {
//piCout << (void*)this << "[]" << core;
return (*s)[v];
}
CDSection & Interface::section(int v) {
// CDSection & ret = s->section(v);
// piCout << "[get section]" << v << ret.name;
return s->section(v);
}
const CDSection Interface::section(int v) const {
return s->section(v);
}
CDSection & Interface::section(const PIDeque<int> &path) {
PIDeque<int> spath = path;
CDSection * rs = s;
while (!spath.isEmpty()) {
rs = &(rs->section(spath.take_front()));
}
return *rs;
}
CDSection & Interface::root() {
return *s;
}
const CDSection & Interface::root() const {
return *s;
}
int Interface::count(bool recursive) const {
return s->count(recursive);
}
bool Interface::exists(PIDeque<int> path) const {
return s->exists(path);
}
void Interface::setFileName(const PIString & _file) {
file_ = _file;
}
bool Interface::configure(const PIString & config) {
PIConfig conf(config, PIIODevice::ReadOnly);
PIConfig::Entry & e(conf.getValue(core->typeLetter(s->cd_type_)));
bool ret = false;
setFileName(e.getValue("file", file(), &ret).toString());
return ret;
}
void Interface::reinitConnection(const PIString & configuration) {
core->init(configuration);
}
void Interface::releaseConnection() {
core->release();
}
void Interface::write(PIIODevice * d) {
core->cd_write(s, d);
}
void Interface::read(PIIODevice * d) {
core->cd_read(s, d);
}
void Interface::parse(PIIODevice * d) {
core->cd_parse(s, d);
}
void Interface::update(PIIODevice * d, UpdateModeFlags mode) {
core->cd_update(s, d, mode);
}
void Interface::calculate() {
core->cd_calculate(s);
}
PIString Interface::appConfig() {
return core->appConfig();
}
PIString Interface::pultConfig() {
return core->pultConfig();
}
void Interface::readFile() {
if (file_.isEmpty()) return;
PIFile f(file_, PIIODevice::ReadOnly);
read(&f);
file_size = f.size();
}
void Interface::writeFile() {
if (file_.isEmpty()) return;
PIFile f(file_, PIIODevice::ReadWrite);
f.clear();
write(&f);
file_size = f.size();
}
bool Interface::inProgress() {
return core->inProgress();
}
void Interface::send() {
core->send(type);
}
void Interface::request() {
core->request(type);
}

View File

@@ -0,0 +1,96 @@
/*
CD Utils - Control-Debug utilites
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CDUTILS_INTERFACE_H
#define CDUTILS_INTERFACE_H
#include "cdutils_types.h"
#include "piobject.h"
#include "cd_utils_export.h"
namespace CDUtils {
class CDCore;
class CD_UTILS_EXPORT Interface: public PIObject
{
PIOBJECT(CDUtils::Interface)
public:
Interface(CDType::cdT type_);
bool test(int v);
CDType & operator [](int v);
const CDType operator [](int v) const;
CDType & operator [](const PIString & name_);
const CDType operator [](const PIString & name_) const;
CDType & operator [](const PIDeque<int> & path_);
const CDType operator [](const PIDeque<int> & path_) const;
CDSection & section(int v);
const CDSection section(int v) const;
CDSection & section(const PIDeque<int> & path);
CDSection & root();
const CDSection & root() const;
int count(bool recursive = true) const;
const PIString file() const {return file_;}
int fileSize() const {return file_size;}
CDType::cdT cdType() const {return type;}
bool exists(PIDeque<int> path) const;
void setFileName(const PIString & _file);
bool configure(const PIString & config);
void reinitConnection(const PIString & configuration);
void releaseConnection();
void write(PIIODevice * d);
void read(PIIODevice * d);
void parse(PIIODevice * d);
void update(PIIODevice * d, UpdateModeFlags mode = SaveByName);
void calculate();
PIString appConfig();
PIString pultConfig();
void readFile();
void writeFile();
bool inProgress();
EVENT(sended)
EVENT(sendFailed)
EVENT(received)
EVENT(receiveFailed)
EVENT(changedGlobal)
EVENT_HANDLER(void, send);
EVENT_HANDLER(void, request);
protected:
CDCore * core;
CDSection * s;
CDType::cdT type;
PIString file_;
int file_size;
};
}
#endif // CDUTILS_INTERFACE_H

View File

@@ -0,0 +1,20 @@
#include "cdutils_k.h"
#include "cdutils_core.h"
using namespace CDUtils;
KInterface K;
KInterface::KInterface(): Interface(CDType::cdK) {
}
void KInterface::directChange(const CDType & k) {
core->K_DirectChange(k.path(), k.value());
}
void KInterface::directChange(const CDType & k, double v) {
core->K_DirectChange(k.path(), PIString::fromNumber(v));
}

47
libs/cd_utils/cdutils_k.h Normal file
View File

@@ -0,0 +1,47 @@
/*
CD Utils - Control-Debug utilites
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CDUTILS_K_H
#define CDUTILS_K_H
#include "cdutils_interface.h"
#include "cd_utils_export.h"
namespace CDUtils {
class CD_UTILS_EXPORT KInterface: public Interface
{
PIOBJECT_SUBCLASS(KInterface, Interface)
public:
KInterface();
EVENT1(keepNamesRequest, bool*, kn)
void directChange(const CDType & k);
void directChange(const CDType & k, double v);
};
}
extern CD_UTILS_EXPORT CDUtils::KInterface K;
#endif // CDUTILS_K_H

View File

@@ -0,0 +1,22 @@
#include "cdutils_m.h"
#include "cdutils_core.h"
using namespace CDUtils;
MInterface M;
MInterface::MInterface(): Interface(CDType::cdM) {
CONNECTU(core, M_Message, this, messageReceived);
}
void MInterface::messageBox(const CDType & m, const PIString & msg) {
core->sendMessage(m, MessageBox, msg);
}
PICout MInterface::createPICout(const CDType & m) const {
PIString * buff = new PIString("[" + CDCore::pathToString(m.path()) + "]");
return PICout(buff, 1);
}

56
libs/cd_utils/cdutils_m.h Normal file
View File

@@ -0,0 +1,56 @@
/*
CD Utils - Control-Debug utilites
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CDUTILS_M_H
#define CDUTILS_M_H
#include "cdutils_interface.h"
#include "cd_utils_export.h"
namespace CDUtils {
class CD_UTILS_EXPORT MInterface: public Interface
{
PIOBJECT_SUBCLASS(MInterface, Interface)
public:
MInterface();
PICout operator [](int v) {return createPICout((*s)[v]);}
PICout operator [](int v) const {return createPICout((*s)[v]);}
PICout operator [](const PIString & name_) {return createPICout((*s)[name_]);}
PICout operator [](const PIString & name_) const {return createPICout((*s)[name_]);}
PICout operator [](const PIDeque<int> & path_) {return createPICout((*s)[path_]);}
PICout operator [](const PIDeque<int> & path_) const {return createPICout((*s)[path_]);}
void messageBox(const CDType & m, const PIString & msg);
EVENT3(messageReceived, PIDeque<int>, path, int, type, PIString, msg)
private:
PICout createPICout(const CDType & m) const;
};
}
extern CD_UTILS_EXPORT CDUtils::MInterface M;
#endif // CDUTILS_M_H

View File

@@ -0,0 +1,196 @@
#include "cdutils_parser.h"
#include "cdutils_types.h"
#include "piiostring.h"
#include "piiobytearray.h"
#include "pifile.h"
using namespace CDUtils;
enum Phase {
eName = 1,
eBracketOpen,
eBracketClose,
eMemberName,
eMemberEqual,
eMemberValue,
eMemberComma,
eComment,
eMultiComment
};
void removeComment(PIString & line, PIString * type, PIString * comment) {
int ci = line.find("//");
if (ci >= 0) {
if (comment) *comment = line.right(line.size_s() - ci - 2);
line.cutRight(line.size_s() - ci).trim();
if (type && comment && !line.isEmpty()) {
*type = comment->takeLeft(1);
comment->trim();
}
}
}
void parseEnumLine(PIString & line, int * value, PIString * type, PIString * comment) {
removeComment(line, type, comment);
int ci = line.find("=");
if (ci >= 0) {
if (value) *value = line.right(line.size_s() - ci - 1).trim().toInt();
line.cutRight(line.size_s() - ci).trim();
}
if (line.trim().endsWith(",")) line.cutRight(1);
}
void parseInsert(PIString line, PIString & alias, PIStringList & out) {
out.clear();
int ci = line.find("=");
if (ci < 0) return;
alias = line.right(line.size_s() - ci - 1).trim();
line.cutRight(line.size_s() - ci).trim();
while (line.find("[") > 0) {
int is = line.find("["), ie = line.find("]");
PIString arr = line.mid(is + 1, ie - is - 1);
out << arr;
line.cutMid(is, ie - is + 1);
}
if (!line.isEmpty()) out.insert(0, line);
}
PIVector<int> enumValues(const PIString & e, const PIMap<PIString, CDSection> & sections, PIStringList & enames) {
PIVector<int> ret;
enames.clear();
if (sections.contains(e)) {
ret = sections[e].indexes();
enames = sections[e].index_names();
} else {
int v = e.toInt();
if (v < 2) return ret;
for (int i = 0; i < v; ++i) {
ret << i;
enames << "";//PIString::fromNumber(i);
}
}
return ret;
}
CDSection CDParser::parse(PIIODevice * d, int cdsection_type) {
CDType::cdT et = (CDType::cdT)cdsection_type;
if (!d) return CDSection(et);
if (!d->canRead()) return CDSection(et);
//piCout << "[CDSection] parse start";
CDSection cs(et);
CDType ck;
PIMap<PIString, CDSection> sections;
PIMap<PIString, int> enum_values;
PIString content, line, alias, type, comment;
PIStringList iarr;
if (PIStringAscii(d->className()) == PIStringAscii("PIFile")) {
PIByteArray c = ((PIFile*)d)->readAll();
c << uchar(0);
content = PIString::fromUTF8((const char *)c.data());
}
if (PIStringAscii(d->className()) == PIStringAscii("PIIOString")) content = *(((PIIOString*)d)->string());
if (PIStringAscii(d->className()) == PIStringAscii("PIIOByteArray")) content = PIString(*(((PIIOByteArray*)d)->byteArray()));
PIIOString ios(&content);
//int phase = 0;
int cind = -1;
while ((cind = content.find("enum", cind)) >= 0) {
ios.seek(cind);
line = ios.readLine().trim();
type.clear();
comment.clear();
removeComment(line, &type, &comment);
if (line.find("{") < 0) {
cind += 4;
continue;
}
line.cutLeft(line.find("enum") + 4).trim();
line.cutRight(line.size_s() - line.find("{")).trim();
if (line.isEmpty()) {
cind += 4;
continue;
}
cs = CDSection(et);
cs.name = line;
//piCout << "enum" << cs.name;
int cev = 0;
// cevalues.clear();
while (!ios.isEnd()) {
line = ios.readLine().trim();
comment.clear();
removeComment(line, &type, &comment);
if (line.find("}") >= 0) break;
if (line.isEmpty()) {
if (comment.find("=") >= 0) {
parseInsert(comment, alias, iarr);
if (!iarr.isEmpty()) {
// piCout << "#" << enum_values;
if (!enum_values.contains(alias)) {
piCout << "Parse error: can`t find section alias \"" << alias << "\"!";
return CDSection(et);
}
if (!sections.contains(iarr.front())) {
piCout << "Parse error: can`t find section \"" << iarr.front() << "\"!";
return CDSection(et);
}
//piCout << "insert" << alias << iarr;
int aval = enum_values.value(alias);
CDSection is = sections.value(iarr.take_front()), ts;
int ibpos = is.name.size_s();
piForeachRC (PIString & a, iarr) {
PIStringList enames;
PIVector<int> evals = enumValues(a, sections, enames);
//piCout << a << evals;
for (int i = 0; i < evals.size_s(); ++i) {
ts.section(evals[i]) = is;
ts.section(evals[i]).alias = enames[i];
}
ts.name = is.name;
ts.name.insert(ibpos, PIString("[") << a << "]");
is = ts;
ts = CDSection(et);
}
is.alias = alias;
cs.section(aval) = is;
}
}
} else {
parseEnumLine(line, &cev, &type, &comment);
//piCout << line << "=" << cev << "//" << type << comment;
ck = CDType(cev, line, type, "", "", comment, et);
if (type == "e") {
if (comment.startsWith("${")) {
comment.cutLeft(1);
PIString en = comment.inBrackets('{', '}');
comment.cutLeft(en.size_s() + 2).trim();
ck.setEnumValues(sections.value(en).enumValues());
ck.setComment(comment);
//piCout << "enum" << en << ck.enumValues();
}
}
cs[cev] = ck;
//cevalues[line] = cev;
enum_values[line] = cev;
++cev;
}
}
//piCout << cs.name << cs.k;
sections[cs.name] = cs;
// piCout << "#" << cevalues;
// enum_values << cevalues;
cind += 4;
}
// piCout << "[CDSection] parse end";
switch (et) {
case CDType::cdK: return sections.value("KDescription");
case CDType::cdX: return sections.value("XDescription");
case CDType::cdC: return sections.value("CDescription");
case CDType::cdM: return sections.value("MDescription");
default: return CDSection(et);
}
return CDSection(et);
}

View File

@@ -0,0 +1,39 @@
/*
CD Utils - Control-Debug utilites
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CDUTILS_PARSER_H
#define CDUTILS_PARSER_H
#include "cd_utils_export.h"
class PIIODevice;
namespace CDUtils {
class CDSection;
namespace CDParser {
CD_UTILS_EXPORT CDSection parse(PIIODevice * d, int cdsection_type);
}
}
#endif // CDUTILS_PARSER_H

View File

@@ -0,0 +1,73 @@
/*
CD Utils - Control-Debug utilites
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CDUTILS_PROTOCOL_H
#define CDUTILS_PROTOCOL_H
#include "pistring.h"
#include "cd_utils_export.h"
namespace CDUtils {
enum CDPacketType {
CD_Ping,
CD_Pong,
CD_KQuery,
CD_KSend,
CD_KDirectChange,
CD_XQuery,
CD_XSend,
CD_XRequest,
CD_XValues,
CD_CQuery,
CD_CSend,
CD_Command,
CD_MQuery,
CD_MSend,
CD_Message,
};
# pragma pack(push,1)
struct CD_UTILS_EXPORT PacketHeader {
int type; // CDPacketType
int session_id;
};
struct CD_UTILS_EXPORT PacketKDirectChange {
PIDeque<int> path;
PIString value;
};
# pragma pack(pop)
inline PIByteArray & operator <<(PIByteArray & s, const PacketHeader & v) {s << v.type << v.session_id; return s;}
inline PIByteArray & operator >>(PIByteArray & s, PacketHeader & v) {s >> v.type >> v.session_id; return s;}
inline PIByteArray & operator <<(PIByteArray & s, const PacketKDirectChange & v) {s << v.path << v.value; return s;}
inline PIByteArray & operator >>(PIByteArray & s, PacketKDirectChange & v) {s >> v.path >> v.value; return s;}
}
#endif // CDUTILS_PROTOCOL_H

View File

@@ -0,0 +1,762 @@
#include "cdutils_types.h"
#include "piconfig.h"
#include "pifile.h"
#include "pievaluator.h"
#include "cdutils_core.h"
using namespace CDUtils;
//int cdtype_debug_cnt = 1;
const int cd_x_history_max_size = 4000;
CDType::CDType() {
index_ = -1;
value_d = 0.;
value_i = 0;
value_b = calculated = x_enabled = false;
cd_type_ = cdNull;
parent = 0;
avg_size = 1;
mode_ = rmode_ = X_Current;
// debug_cnt = cdtype_debug_cnt;
// cdtype_debug_cnt++;
// piCout << "[CDType]" << "create Null" << debug_cnt;
}
CDType::CDType(int i, const PIString & n, const PIString & t, const PIString & v, const PIString & f, const PIString & c, cdT cd_t) {
index_ = i;
name_ = n.trimmed();
type_ = t.trimmed();
value_s = v.trimmed();
formula_ = f.trimmed();
comment_ = c.trimmed();
value_d = v.toDouble();
value_i = v.toInt();
value_b = v.toBool();
cd_type_ = cd_t;
calculated = x_enabled = false;
parent = 0;
avg_size = 1;
mode_ = rmode_ = X_Current;
if (type_ == "e") {
enum_values = parseEnumComment(comment_);
// piCout << enum_values.size() << enum_values;
}
// piCout << type_.size() << type_.toUTF8();
// piCout << formula_.size() << formula_.toUTF8();
// piCout << comment_.size() << comment_.toUTF8();
// debug_cnt = cdtype_debug_cnt;
// cdtype_debug_cnt++;
// piCout << "[CDType] create" << name_ << ":" << type_ << ":" << value_s << ":" << value_d << ":" << formula_ << ":" << comment_ << ":" << (cd_type_ == cdK);
}
CDType & CDType::operator =(double x) {
value_d = x;
value_i = x;
value_b = x > 0.;
if (mode_ == X_All_Avg) {
avg_h << x;
double val = 0;
if (avg_h.size_s() >= avg_size) {
for (int i = 0; i < avg_h.size_s(); i++)
val += avg_h[i];
val /= avg_h.size();
avg_h.clear();
if (history.size() < cd_x_history_max_size)
history << val;
}
}
return *this;
}
PIString CDType::type() const {
if (type_.trimmed().isEmpty()) return "f";
// piCout << "type =" << type_.trimmed() << ";" << type_ << "#";
return type_;
}
PIString CDType::value() const {
if (type_ == "b") return PIString::fromBool(value_b);
return value_s;
}
PIVariant CDType::variantValue() const {
if (type_.isEmpty()) return PIVariant(value());
switch (type_[0].toAscii()) {
case 'b': return PIVariant(toBool()); break;
case 'n': return PIVariant(toInt()); break;
case 'f': return PIVariant(toDouble()); break;
case 'c': return PIVariant(PIVariantTypes::Color(toInt())); break;
case 'e': {
PIVariantTypes::Enum e = enum_values;
e.selectValue(toInt());
return PIVariant(e);
break;
}
default: break;
}
return PIVariant(value());
}
void CDType::setValue(const PIString & value_) {
formula_ = value_;
value_d = formula_.toDouble();
value_i = formula_.toInt();
value_b = formula_.toBool();
}
void CDType::setVariantValue(const PIVariant & value_) {
setValue(PIString::fromNumber(value_.toDouble()));
}
void CDType::setFormula(const PIString & f) {
formula_ = f;
calculated = false;
//PIEvaluator e;
//calculate(&e);
}
PIStringList CDType::pathString() const {
PIStringList ret;
CDSection * ps = CDCore::instance()->root(cd_type_);
if (!ps) return ret;
for (int i = 0; i < path_.size_s() - 1; ++i) {
ps = &(ps->section(path_[i]));
if (!ps->alias.isEmpty()) ret << ps->alias;
else ret << PIString::fromNumber(path_[i]);
}
if (!name_.isEmpty()) ret << name_;
else ret << PIString::fromNumber(index_);
return ret;
}
void CDType::readX(PIByteArray & ba) {
if (ba.size() < 5) return;
uchar t(0); ba >> t;
rmode_ = (XMode)t;
switch (rmode_) {
case X_Current:
ba >> value_d;
break;
case X_All_Avg: {
PIVector<double> ah;
ba >> ah;
history << ah;
if (!history.isEmpty())
value_d = history.back();
} break;
default: break;
}
value_i = value_d;
value_b = value_d > 0.;
}
void CDType::writeX(PIByteArray & ba) {
ba << uchar(mode_);
switch (mode_) {
case X_Current:
ba << value_d;
break;
case X_All_Avg:
ba << history;
history.clear();
break;
default: break;
}
}
bool CDType::calculate(PIEvaluator * e, PIVector<const CDType * > stack) {
if (stack.contains(this)) {
error_ = "Circular dependencies: ";
piForeachC (CDType * k, stack)
error_ << k->name() << " -> ";
error_ << name();
//piCout << error_;
return false;
}
stack << this;
if (calculated) return true;
calculated = true;
error_.clear();
if (!parent) return true;
//piCout << "calc" << name_ << (parent ? parent->alias : "root");
value_s = formula_.trimmed();
for (;;) {
int ki = value_s.find("K[");
if (ki < 0) break;
int ke = value_s.find("]", ki + 2);
if (ke < 0) break;
PIString kp = value_s.mid(ki + 2, ke - ki - 2);
//piCout << kp;
CDType & k((*parent)[kp]);
k.calculate(e, stack);
value_s.replace(ki, ke - ki + 1, PIString::fromNumber(k.value_d));
}
value_d = formula_.toDouble();
value_i = formula_.toInt();
value_b = formula_.toBool();
double ev = 0.;
if (!e->check(value_s) && value_d == 0. && value_i == 0 && !value_b) {
PIString f = formula_.trimmed().toLowerCase();
if (f != "off" && f != "false" && f != "no" && !value_b) {
error_ = e->error();
return false;
}
} else
if (e->isCorrect())
ev = e->evaluate().real();
//piCout << value_s << value_i << value_d << ev;
//if ((value_d == 0.) || (piAbsd(value_d) < piAbsd(ev))) value_d = ev;
//if ((value_i == 0) || (piAbsd(value_i) < piAbsd(ev))) value_i = int(ev);
if ((value_d == 0.) || (ev != 0.)) value_d = ev;
if ((value_i == 0) || (ev != 0.)) value_i = int(ev);
value_b = value_b || (ev > 0.);
if (value_i != 0) {
if (value_d == 0.) value_d = value_i;
value_b = value_i > 0;
}
if (value_d != 0.) {
if (value_i == 0) value_i = value_d;
value_b = value_d > 0.;
}
if (value_b) {
if (value_d == 0.) value_d = 1.;
if (value_i == 0) value_i = 1;
}
value_s = PIString::fromNumber(value_d);
return true;
}
PIVariantTypes::Enum CDType::parseEnumComment(PIString c) {
PIVariantTypes::Enum ret;
if (c.isEmpty()) return ret;
if (type_ == "e") {
PIStringList sl = c.inBrackets('{', '}').split(",");
int cval = 0;
piForeach (PIString & s, sl) {
s.trim();
if (s.isEmpty()) continue;
if (s[0].isDigit()) {
int ind = s.find("-");
if (ind > 0) {
cval = s.left(ind).toInt();
s.cutLeft(ind + 1).trim();
}
}
ret << PIVariantTypes::Enumerator(cval, s);
++cval;
}
}
//piCout << c << "=" << ret;
return ret;
}
//CDType::CDType(const CDType &cdt) {
// index_ = cdt.index_;
// name_ = cdt.name_;
// type_ = cdt.type_;
// value_s = cdt.value_s;
// formula_ = cdt.formula_;
// comment_ = cdt.comment_;
// value_d = cdt.value_d;
// value_i = cdt.value_i;
// value_b = cdt.value_b;
// cd_type_ = cdt.cd_type_;
// debug_cnt = cdtype_debug_cnt;
// cdtype_debug_cnt++;
// piCout << "[CDType] copy" << debug_cnt << "->" << cdt.debug_cnt << index_ << ":" << name_ << ":" << type_ << ":" << value_s << ":" << value_d << ":" << formula_ << ":" << comment_ << ":" << (cd_type_ == cdK);
//}
//CDType &CDType::operator =(const CDType &cdt) {
// index_ = cdt.index_;
// name_ = cdt.name_;
// type_ = cdt.type_;
// value_s = cdt.value_s;
// formula_ = cdt.formula_;
// comment_ = cdt.comment_;
// value_d = cdt.value_d;
// value_i = cdt.value_i;
// value_b = cdt.value_b;
// cd_type_ = cdt.cd_type_;
// piCout << "[CDType] assign" << debug_cnt << "=" << cdt.debug_cnt << index_ << ":" << name_ << ":" << type_ << ":" << value_s << ":" << value_d << ":" << formula_ << ":" << comment_ << ":" << (cd_type_ == cdK);
// //debug_cnt = cdt.debug_cnt;
// return *this;
//}
//CDType::~CDType() {
// piCout << "[CDType] delete" << debug_cnt << index_ << ":" << name_ << ":" << type_ << ":" << value_s << ":" << value_d << ":" << formula_ << ":" << comment_ << ":" << (cd_type_ == cdK);
//}
CDSection::CDSection(CDType::cdT type_) {
cd_type_ = type_;
null.cd_type_ = type_;
}
CDSection & CDSection::section(int v) {
CDSection & ret(s[v]);
ret.cd_type_ = cd_type_;
return ret;
}
const CDSection CDSection::section(int v) const {
CDSection & ret(s[v]);
ret.cd_type_ = cd_type_;
return s[v];
}
bool CDSection::exists(PIDeque<int> path) const {
if (path.isEmpty()) return false;
if (path.size_s() == 1) return cd.contains(path[0]);
int si = path[0];
if (!s.contains(si)) return false;
path.remove(0, 1);
return s[si].exists(path);
}
int CDSection::count(bool recursive) const {
int ret = cd.size_s();
if (recursive) {
PIMap<int, CDSection>::const_iterator i;
for (i = s.constBegin(); i != s.constEnd(); ++i)
ret += i->second.count(recursive);
}
return ret;
}
int CDSection::sectionsCount() const {
return s.size();
}
PIStringList CDSection::index_names() const {
PIStringList ret;
auto i = cd.makeIterator();
while (i.next())
ret << i.value().name();
return ret;
}
void CDSection::calculate() {
prepareCalculate();
if (cd_type_ != CDType::cdK) return;
PIEvaluator e;
calculateRecursive(&e);
}
CDType & CDSection::getByName(const PIString & name_) {
PIStringList np = name_.split(".");
if (np.isEmpty()) return null;
//piCout << np;
CDSection * cs = this, * ns = 0;
if (np.front().isEmpty()) {
if (np.size_s() < 2) return null;
cs = CDCore::instance()->root(cd_type_);
np.pop_front();
}
for (int i = 0; i < np.size_s() - 1; ++i) {
if (np[i].isEmpty()) return null;
bool isd = np[i][0].isDigit() || (np[i][0] == '-');
int dv = 0;
if (isd) dv = np[i].toInt();
ns = 0;
auto it = cs->s.makeIterator();
while (it.next()) {
bool f = false;
if (isd) f = (dv == it.key());
else f = (np[i] == it.value().alias);
//piCout << "s..." << it.key() << it.value().alias << f;
if (f) {
ns = &(it.valueRef());
break;
}
}
//piCout << ns;
if (!ns) return null;
cs = ns;
}
if (np.back().isEmpty()) return null;
bool isd = np.back()[0].isDigit() || (np.back()[0] == '-');
int dv = 0;
if (isd) dv = np.back().toInt();
//piCout << np.back() << isd << dv;
auto it = cs->cd.makeIterator();
while (it.next()) {
bool f = false;
if (isd) f = (dv == it.key());
else f = (np.back() == it.value().name());
//piCout << "k..." << it.key() << it.value().name() << f;
if (f)
return cs->cd[it.key()];
}
return null;
}
CDType & CDSection::getByPath(const PIDeque<int> & path_) {
if (path_.isEmpty()) return null;
CDSection * s = this;
for (int i = 0; i < path_.size_s() - 1; ++i)
s = &(s->section(path_[i]));
if (!s) return null;
return (*s)[path_.back()];
}
void CDSection::write(PIIODevice * d, const PIString & prefix) {
if (!d) return;
if (cd.isEmpty() && s.isEmpty()) return;
// piCout << "[CDSection] write start";
PIString l;
PIStringList cdtl;
cdtl << "null" << "k" << "x" << "c" << "m";
if (prefix.isEmpty()) l = "[" + cdtl[cd_type_] + "]";
else l = "[" + prefix + "." + cdtl[cd_type_] + "]";
l += "\n";
d->write(l.toUTF8());
l = "name = " + name + " \n";
d->write(l.toUTF8());
l = "alias = " + alias + " \n";
d->write(l.toUTF8());
auto i = cd.makeIterator();
while (i.next()) {
const CDType & ck(i.value());
if (ck.cd_type() != cd_type_) continue;
switch (cd_type_) {
case CDType::cdNull: break;
case CDType::cdK:
l.clear(); l << ck.index() << ".f = " << ck.formula() << " #s " << ck.comment() << " \n";
d->write(l.toUTF8());
l.clear(); l << ck.index() << ".v = " << ck.value() << " #" << ck.type() << " " << ck.name() << " \n";
d->write(l.toUTF8());
if (!ck.enumValues().enum_list.isEmpty()) {
l.clear(); l << ck.index() << ".ev = {";
//PIVector<CDType::Enumerator> el = ck.enumValues();
piForeachC (PIVariantTypes::Enumerator & e, ck.enumValues().enum_list)
l << e.value << " - " << e.name << ", ";
l.cutRight(2);
l << "} \n";
d->write(l.toUTF8());
}
break;
case CDType::cdX:
l.clear(); l << ck.index() << ".name = " << ck.name() << " #s " << ck.comment() << " \n";
d->write(l.toUTF8());
l.clear(); l << ck.index() << ".mode = " << ck.xmode() << " #e (0 - cur, 1 - all_avg) " << "\n";
d->write(l.toUTF8());
l.clear(); l << ck.index() << ".avg = " << ck.avg() << " #n " << "\n";
d->write(l.toUTF8());
l.clear(); l << ck.index() << ".sel = " << (ck.isSelectedX() ? "1" : "0") << " #n " << "\n";
d->write(l.toUTF8());
break;
case CDType::cdC:
case CDType::cdM:
l.clear(); l << ck.index() << ".name = " << ck.name() << " #s " << ck.comment() << " \n";
d->write(l.toUTF8());
break;
}
}
if (!s.isEmpty()) {
if (prefix.isEmpty()) l = "s";
else l = prefix + ".s";
auto j = s.makeIterator();
while (j.next()) {
j.valueRef().write(d, l + "." + PIString::fromNumber(j.key()));
}
}
if (prefix.isEmpty()) {
l = "[]\n";
d->write(l.toUTF8());
}
// piCout << "[CDSection] write end";
}
void CDSection::read(const void * ep) {
// piCout << "[CDSection] read start";
PIStringList cdtl;
cdtl << "null" << "k" << "x" << "c" << "m";
cd.clear();
s.clear();
PIConfig::Entry & e(*(PIConfig::Entry*)ep);
name = e.getValue(cdtl[cd_type_] + ".name").value();
alias = e.getValue(cdtl[cd_type_] + ".alias").value();
PIConfig::Entry & cdl = e.getValue(cdtl[cd_type_]);
for (int i = 0; i < cdl.childCount(); ++i) {
const PIConfig::Entry * e(cdl.child(i));
bool ok = false;
int id = e->name().toInt(-1, &ok);
// piCout << "[read]" << ke->name() << ke->value() << ok;
// PIString n = ke->getValue("v").comment();
// PIString t = n.takeLeft(1);
if (ok) {
CDType c;
PIString ev;
switch (cd_type_) {
case CDType::cdNull: break;
case CDType::cdK:
c = CDType(id, e->getValue("v").comment(), e->getValue("v").type(), e->getValue("v").value(), e->getValue("f").value(), e->getValue("f").comment(), cd_type_);
ev = e->getValue("ev", "").value();
if (!ev.isEmpty())
c.enum_values = c.parseEnumComment(ev);
break;
case CDType::cdX:
c = CDType(id, e->getValue("name").value(), PIString(), PIString(), PIString() , e->getValue("name").comment(), cd_type_);
c.setXMode((CDType::XMode)e->getValue("mode", int(CDType::X_Current)).value().toInt());
c.setAvg((CDType::XMode)e->getValue("avg", 1).value().toInt());
c.x_enabled = e->getValue("sel", false).value().toBool();
break;
case CDType::cdC:
case CDType::cdM:
c = CDType(id, e->getValue("name").value(), PIString(), PIString(), PIString() , e->getValue("name").comment(), cd_type_);
break;
}
cd[id] = c;
}
}
PIConfig::Entry & sl = e.getValue("s");
for (int i = 0; i < sl.childCount(); ++i) {
const PIConfig::Entry * se(sl.child(i));
int sid = se->name().toInt();
CDSection & rs(s[sid]);
rs.cd_type_ = cd_type_;
rs.read(se);
}
// piCout << "[CDSection] read end";
}
void CDSection::update(CDSection & v, UpdateModeFlags mode) {
if (mode[SaveByIndex] && mode[SaveByName]) {
piCout << "[CDSection] update error: SaveByIndex | SaveByName mode is denied!";
return;
}
//piCout << "[CDSection] update start";
//piCout << "before" << k.size() << v.k.size();
PIMap<int, PIString> prev_cd_f_bi;
PIMap<PIString, PIString> prev_cd_f_bn;
PIMap<int, CDType>::iterator i;
if (mode[SaveByIndex]) {
for (i = cd.begin(); i != cd.end(); ++i)
prev_cd_f_bi[i.key()] = i.value().formula();
}
if (mode[SaveByName]) {
for (i = cd.begin(); i != cd.end(); ++i)
prev_cd_f_bn[i.value().name_] = i.value().formula();
}
if (!mode[Merge])
cd.clear();
for (i = v.cd.begin(); i != v.cd.end(); ++i) {
int id = i.key();
PIString n = i.value().name();
cd[id] = i.value();
if (mode[SaveByIndex]) {
if (prev_cd_f_bi.contains(id))
cd[id].setFormula(prev_cd_f_bi[id]);
}
if (mode[SaveByName]) {
if (prev_cd_f_bn.contains(n))
cd[id].setFormula(prev_cd_f_bn[n]);
}
}
PIMap<int, CDSection> prev_s_bi;
PIMap<PIString, CDSection> prev_s_bn;
PIMap<int, CDSection>::iterator j;
if (mode[SaveByIndex]) {
for (j = s.begin(); j != s.end(); ++j)
prev_s_bi[j.key()] = j.value();
}
if (mode[SaveByName]) {
for (j = s.begin(); j != s.end(); ++j)
prev_s_bn[j.value().alias] = j.value();
}
if (!mode[Merge])
s.clear();
for (j = v.s.begin(); j != v.s.end(); ++j) {
int id = j.key();
PIString n = j.value().alias;
s[id] = j.value();
if (mode[SaveByIndex]) {
if (prev_s_bi.contains(id))
s[id] = prev_s_bi[id];
}
if (mode[SaveByName]) {
if (prev_s_bn.contains(n))
s[id] = prev_s_bn[n];
}
s[id].update(j.value(), mode);
}
/*PISet<int> used;
for (i = k.begin(); i != k.end(); ++i) {
if (v.k.contains(i.key())) {
PIString f = k[i.key()].formula_;
CDType & cdt = v.k[i.key()];
cdt.formula_ = f;
k[i.key()] = cdt;
used << i.key();
}
if (mode) {
CDType & ck(k[i.key()]);
if (prev_k_f_bn.contains(ck.name_))
ck.setFormula(prev_k_f_bn[ck.name_]);
}
}
//piCout << " after" << k.size();
for (i = v.k.begin(); i != v.k.end(); ++i) {
if (!used.contains(i.key()))
k[i.key()] = i.value();
CDType & ck(k[i.key()]);
ck.setFormula(prev_k_f_bn.value(ck.name_));
}
used.clear();
PIMap<int, CDSection>::iterator j;
for (j = s.begin(); j != s.end(); ++j) {
if (v.s.contains(j.key()))
j.value().update(v.s[j.key()], mode);
used << j.key();
}
for (j = v.s.begin(); j != v.s.end(); ++j) {
if (!used.contains(j.key()))
s[j.key()] = j.value();
}*/
// piCout << "[CDSection] update end";
}
bool CDSection::isSameStructure(CDSection & v) {
PIMap<PIString, int> cd_ids;
PIMap<int, CDType>::iterator i;
for (i = cd.begin(); i != cd.end(); ++i)
cd_ids[i.value().name()] = i.key();
for (i = v.cd.begin(); i != v.cd.end(); ++i) {
if (!cd_ids.contains(i.value().name())) continue;
//piCout << i.key() << k[i.key()].name() << i.value().name();
if (cd[cd_ids[i.value().name()]].index() != i.key())
return false;
}
PIMap<int, CDSection>::iterator j;
for (j = v.s.begin(); j != v.s.end(); ++j) {
if (!s.contains(j.key())) continue;
if (!s[j.key()].isSameStructure(j.value()))
return false;
}
return true;
}
void CDSection::prepareCalculate() {
PIMap<int, CDType>::iterator i;
for (i = cd.begin(); i != cd.end(); ++i) {
i.value().parent = this;
i.value().calculated = false;
}
PIMap<int, CDSection>::iterator j;
for (j = s.begin(); j != s.end(); ++j)
j.value().prepareCalculate();
}
void CDSection::calculateRecursive(PIEvaluator * e) {
PIMap<int, CDType>::iterator i;
for (i = cd.begin(); i != cd.end(); ++i)
i.value().calculate(e);
PIMap<int, CDSection>::iterator j;
for (j = s.begin(); j != s.end(); ++j)
j.value().calculateRecursive(e);
}
void CDSection::setSelectedX(bool yes) {
PIMap<int, CDType>::iterator i;
for (i = cd.begin(); i != cd.end(); ++i)
i.value().x_enabled = yes;
PIMap<int, CDSection>::iterator j;
for (j = s.begin(); j != s.end(); ++j)
j.value().setSelectedX(yes);
}
PIVector<PIDeque<int> > CDSection::collectX() const {
PIVector<PIDeque<int> > ret;
PIMap<int, CDType>::const_iterator i;
for (i = cd.begin(); i != cd.end(); ++i) {
if (i.value().x_enabled)
ret << i.value().path();
}
PIMap<int, CDSection>::const_iterator j;
for (j = s.constBegin(); j != s.constEnd(); ++j)
ret << j.value().collectX();
return ret;
}
void CDSection::makePath(PIDeque<int> p) {
PIDeque<int> tp;
PIMap<int, CDType>::iterator i;
for (i = cd.begin(); i != cd.end(); ++i) {
tp = p;
tp << i.key();
i.value().path_ = tp;
//piCout << "path for" << i.value().name() << tp;
}
PIMap<int, CDSection>::iterator j;
for (j = s.begin(); j != s.end(); ++j) {
tp = p;
tp << j.key();
j.value().makePath(tp);
}
}
PIVector<CDType * > CDSection::children(bool recursive) const {
PIVector<CDType * > ret;
PIMap<int, CDType>::const_iterator i;
for (i = cd.begin(); i != cd.end(); ++i)
ret << const_cast<CDType * >(&(i.value()));
if (!recursive) return ret;
PIMap<int, CDSection>::const_iterator j;
for (j = s.constBegin(); j != s.constEnd(); ++j)
ret << j.value().children(true);
return ret;
}
PIVariantTypes::Enum CDSection::enumValues() const {
PIVariantTypes::Enum ret;
PIMap<int, CDType>::const_iterator i;
for (i = cd.constBegin(); i != cd.constEnd(); ++i)
ret << PIVariantTypes::Enumerator(i.key(), i.value().name());
return ret;
}

View File

@@ -0,0 +1,193 @@
/*
CD Utils - Control-Debug utilites
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CDUTILS_TYPES_H
#define CDUTILS_TYPES_H
#include "pistring.h"
#include "pimap.h"
#include "pivariant.h"
#include "cd_utils_export.h"
class PIIODevice;
class PIEvaluator;
class CD_Pult;
class CDItem;
class CDItemModel;
namespace CDUtils {
class CDSection;
enum UpdateMode {
SaveByIndex = 0x01,
SaveByName = 0x02,
Merge = 0x04
};
enum MessageType {
Log = 1,
MessageBox,
};
typedef PIFlags<UpdateMode> UpdateModeFlags;
class CD_UTILS_EXPORT CDType {
friend class CDSection;
friend class CDCore;
friend class Interface;
friend class XInterface;
public:
enum cdT {cdNull, cdK, cdX, cdC, cdM};
enum XMode {X_Current, X_All_Avg};
CDType();
CDType(int i, const PIString & n, const PIString & t, const PIString & v, const PIString & f, const PIString & c, cdT cd_t);
CDType & operator =(double x);
int index() const {return index_;}
PIString name() const {return name_;}
PIString type() const;
PIString value() const;
PIVariant variantValue() const;
PIString formula() const {return formula_;}
PIString comment() const {return comment_;}
double toDouble() const {return value_d;}
int toInt() const {return value_i;}
bool toBool() const {return value_b;}
cdT cd_type() const {return cd_type_;}
void setValue(const PIString & value_);
void setVariantValue(const PIVariant & value_);
void setFormula(const PIString & formula);
void setComment(const PIString & comment) {comment_ = comment;}
operator double() const {return value_d;}
const PIVariantTypes::Enum & enumValues() const {return enum_values;}
void setEnumValues(const PIVariantTypes::Enum & ev) {enum_values = ev;}
const PIString & errorString() const {return error_;}
PIDeque<int> path() const {return path_;}
PIStringList pathString() const;
void setXMode(XMode mode) {mode_ = mode;}
void setAvg(int avg) {avg_size = avg;}
XMode xmode() const {return mode_;}
XMode xmode_rec() const {return rmode_;}
int avg() const {return avg_size;}
bool isSelectedX() const {return x_enabled;}
void readX(PIByteArray & ba);
void writeX(PIByteArray & ba);
PIVector<double> history;
protected:
bool calculate(PIEvaluator * e, PIVector<const CDType * > stack = PIVector<const CDType * >());
PIVariantTypes::Enum parseEnumComment(PIString c);
cdT cd_type_;
int index_;
PIString name_, type_;
PIString value_s, formula_, comment_, error_;
PIVariantTypes::Enum enum_values;
CDSection * parent;
PIDeque<int> path_;
double value_d;
int value_i;
bool value_b, calculated, x_enabled;
PIVector<double> avg_h;
int avg_size;
XMode mode_, rmode_;
};
class CD_UTILS_EXPORT CDSection {
friend class CDCore;
friend class Interface;
friend class XInterface;
friend class ::CD_Pult;
friend class ::CDItem;
friend class ::CDItemModel;
public:
CDSection(CDType::cdT type_ = CDType::cdNull);
bool test(int v) {return cd.value(v).toBool();}
// CDType & operator [](int v) {if (!k.contains(v)) k[v].index_ = v; return k[v];}
CDType & operator [](int v) {return cd[v];}
const CDType operator [](int v) const {return cd[v];}
CDType & operator [](const PIString & name_) {return getByName(name_);}
const CDType operator [](const PIString & name_) const {return const_cast<CDSection*>(this)->getByName(name_);}
CDType & operator [](const PIDeque<int> & path_) {return getByPath(path_);}
const CDType operator [](const PIDeque<int> & path_) const {return const_cast<CDSection*>(this)->getByPath(path_);}
CDSection & section(int v);
const CDSection section(int v) const;
bool isEmpty() const {return cd.isEmpty() && s.isEmpty();}
bool exists(PIDeque<int> path) const;
int count(bool recursive = true) const;
int sectionsCount() const;
PIVector<int> indexes() const {return cd.keys();}
PIStringList index_names() const;
void calculate();
void makePath(PIDeque<int> p = PIDeque<int>());
PIVector<CDType * > children(bool recursive = true) const;
PIVariantTypes::Enum enumValues() const;
PIString name;
PIString alias;
protected:
CDSection(PIMap<int, CDType> k_, PIMap<int, CDSection> s_) {
cd = k_;
s = s_;
}
CDType & getByName(const PIString & name_);
CDType & getByPath(const PIDeque<int> & path_);
void write(PIIODevice * d, const PIString & prefix = PIString());
void read(const void * ep);
void update(CDSection & v, UpdateModeFlags mode = SaveByName);
bool isSameStructure(CDSection & v);
void prepareCalculate();
void calculateRecursive(PIEvaluator * e);
void setSelectedX(bool yes);
PIVector<PIDeque<int> > collectX() const;
PIMap<int, CDType> cd;
mutable PIMap<int, CDSection> s;
CDType null;
CDType::cdT cd_type_;
};
}
inline PICout operator <<(PICout s, const CDUtils::CDType & v) {
s.space();
s.setControl(0, true);
switch (v.cd_type()) {
case CDUtils::CDType::cdK : s << "K["; break;
case CDUtils::CDType::cdX : s << "X["; break;
case CDUtils::CDType::cdC : s << "C["; break;
case CDUtils::CDType::cdM : s << "M["; break;
default : s << "Null["; break;
}
s << v.name() << "(" << v.index() << ")] = " << v.value();
s.restoreControl();
return s;
}
#endif // CDUTILS_TYPES_H

View File

@@ -0,0 +1,55 @@
#include "cdutils_x.h"
#include "cdutils_core.h"
using namespace CDUtils;
XInterface X;
XInterface::XInterface(): Interface(CDType::cdX) {
CONNECTU(core, X_ReceivedX, this, receivedX);
}
void XInterface::setEnabled(const CDType & x, bool en) {
core->x_mutex.lock();
CDType & t((*s)[x.path()]);
if (t.cd_type() != CDType::cdX) {
core->x_mutex.unlock();
return;
}
t.x_enabled = en;
//piCout << t << "x_enabled" << en;
core->need_rebuild_x = true;
core->x_mutex.unlock();
}
PIVector<PIDeque<int> > XInterface::enabledList() const {
return CDCore::instance()->x_selected;
}
void XInterface::setEnabledList(const PIVector<PIDeque<int> > & l) {
CDCore::instance()->x_selected = l;
}
void XInterface::lock() {
CDCore::instance()->x_mutex.lock();
}
void XInterface::unlock() {
CDCore::instance()->x_mutex.unlock();
}
void XInterface::start(double freq) {
core->startX(freq);
}
void XInterface::stop() {
core->stopX();
}

57
libs/cd_utils/cdutils_x.h Normal file
View File

@@ -0,0 +1,57 @@
/*
CD Utils - Control-Debug utilites
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CDUTILS_X_H
#define CDUTILS_X_H
#include "cdutils_interface.h"
#include "cd_utils_export.h"
namespace CDUtils {
class CD_UTILS_EXPORT XInterface: public Interface
{
PIOBJECT_SUBCLASS(XInterface, Interface)
public:
XInterface();
EVENT1(keepNamesRequest, bool*, xn)
EVENT1(receivedX, PIVector<PIDeque<int> >, pathes)
void enable(const CDType & x) {setEnabled(x, true);}
void disable(const CDType & x) {setEnabled(x, false);}
void setEnabled(const CDType & x, bool en);
void setDisabled(const CDType & x, bool dis) {setEnabled(x, !dis);}
PIVector<PIDeque<int> > enabledList() const;
void setEnabledList(const PIVector<PIDeque<int> > & l);
void lock();
void unlock();
void start(double freq = 20.);
void stop();
};
}
extern CD_UTILS_EXPORT CDUtils::XInterface X;
#endif // CDUTILS_X_H

View File

@@ -0,0 +1,97 @@
#include "cdutils_k.h"
#include "cdutils_x.h"
#include "cdutils_c.h"
#include "cdutils_m.h"
#include "cdutils_core.h"
#include "cdtest.h"
#include "pip.h"
#include "k_description.h"
using namespace CDUtils;
class Core : public PIObject
{
PIOBJECT(Core)
public:
Core() {
CDCore::instance()->initApp();
// piCout << "testCore";
CONNECTU(&timer, tickEvent, this, timerDone);
CONNECTU(&X, received, this, xrecv);
CONNECTU(&C, received, this, crecv);
t = 0.;
}
void load() {
rf.open("k.dat", PIIODevice::ReadWrite);
K.read(&rf);
rf.close();
}
void save() {
rf.open("k_out.txt", PIIODevice::ReadWrite);
rf.resize(0);
K.write(&rf);
rf.close();
// rf.open("k_out.txt", PIIODevice::ReadWrite);
// K.read(&rf);
// rf.close();
// rf.open("k_out2.txt", PIIODevice::ReadWrite);
// rf.resize(0);
// K.write(&rf);
// rf.close();
// rf.open("k_out2.txt", PIIODevice::ReadWrite);
// K.read(&rf);
// rf.close();
// rf.open("k_out3.txt", PIIODevice::ReadWrite);
// rf.resize(0);
// K.write(&rf);
// rf.close();
}
void test() {
X.lock();
X[KD::Frequency] = 100;
X.section(KD::Spectrometer)[KD::Temperature_default] = sin(t);
t += 0.01;
X.unlock();
/*piCout << "count" << K.count();
piCout << K[First];
piCout << K[Second];*/
}
EVENT_HANDLER(void, ksend) {piCout << "sended k";}
EVENT_HANDLER(void, crecv) {
piCout << "received c";
C.connect(C.section(KD::Logs).section(KD::Spec).section(KD::Formats)[KD::Binary], this, HANDLER(cmd));
C.autoConnect(this);
}
EVENT_HANDLER(void, xrecv) {
piCout << "received x";
if (!timer.isRunning()) timer.start(10);
X.start();
}
EVENT_HANDLER(void, timerDone) {test();}
EVENT_HANDLER(void, cmd) {piCout << "command cmd";}
EVENT_HANDLER(void, c_Pause) {
piCout << "command pause";
M[KD::Main] << "rec command" << C[KD::Pause];
M.messageBox(M.root()[KD::Core], "init successfull");
}
EVENT_HANDLER(void, c_Spectrometer_Connection) {piCout << "command spec_conn";}
private:
PIFile rf;
PITimer timer;
double t;
};
int main(int argc, char *argv[]) {
X.start();
piSleep(1);
//CDCore::instance()->destroy();
piCout << "DELETED";
return 0;
}

View File

@@ -0,0 +1,147 @@
#ifndef K_DESCRIPTION_H
#define K_DESCRIPTION_H
namespace KD {
enum Sections {
Startup,
Spectrometer,
Switch,
Formats,
Logs,
Detector,
CoreOutput,
};
enum LogFormat {
Text, //b text
Binary, //b binary
};
enum LogType {
Data, //b write data logs
Spec, //b write spectrogram logs
ARINC, //b ARINC
};
enum KLogConfig {
// LogFormat = Formats
StartupWrite, //b
ApplyBinaryLogHeader, //b Apply settings under ID = 255 for binary log
MaximumWriteFrequency, //f Maximum frequency for log in Hz, or 0 for unlimited
};
enum SwitchType {
BaySpec,
DiCon,
};
enum SpectrometerConnection {
TCP,
USB,
};
enum PeakSearchMode {
Left,
Max,
Right,
};
enum CoreMode {
ModeSpectrometer,
ModePlayer,
ModePeaks,
};
enum KSpectrometer {
Connection, //e ${SpectrometerConnection}
Temperature_compensation, //b Use temperature sensor or default temperature witout compensation
Temperature_default, //f Default temperature using if compensation disabled
};
enum KSwitch {
Enabled, //b 0 or 1 Use optical switch or not
Wait, //n Delay after switching channel, ms
Autoscan, //e {0 - scan with our forces, 1 - SDK autoscan}
Autoscan_offset, //n Offset for SDK autoscan
Type, //e ${SwitchType}
};
enum KDetector {
Threshold_Min, //f
Threshold_Max, //f
SideSize, //f
SideOffset, //f
PeaksSearch, //e ${PeakSearchMode}
};
enum KCoreOutput {
SendSpectrum, //b Send spectrum data or empty vector
SendOnlyCurrentValue, //b Send current values or all stored in 20Hz
};
enum CoreOutputChannel {
GUI,
SecGUI,
ThirdGUI,
};
enum KDescription {
// KSpectrometer = Spectrometer
// KSwitch = Switch
// KDetector = Detector
// KCoreOutput[CoreOutputChannel] = CoreOutput
// KLogConfig[LogType] = Logs
Gratings_history, //n Gratings peak values history, count
Amplitude_history_size, //n Count of history values to calculate sensors amplitude
Fourier_enabled, //b Global fourier enable flag
Fourier_size, //n Size of fourier window, in counts
Fourier_YScale, //f scale for fourier amplitude
Fourier_Max_or_Density, //n 0 - Maximum in fourier window, 1 - Density of fourier window
Mode, //e ${CoreMode} Work mode
SynchronizationEnabled, //b When enabled, start logs and reset time when sync signal received
SynchronizationMode, //e {0 - disabled, 1 - new file, 2 - column in log}
LambdasAutoReset, //b Set lambdas_0 to grating values on first data receive
Gauss_size, //n
//Peak_max_offset, //f in pixels
//Peak_LF_coeff, //f 1. - no filtering
GratingOverloadMax, //n
GratingOverloadMin, //n
SendLED, //b Send to LED Arduino serial port current state
SynchronizationClearValues, //b clear gratings and sensors values and history on sync
PeaksModeFrequency, //f
PeaksModeAdditionNm_1, //f Addition nm to peaks in ModePeaks, channel 1
PeaksModeAdditionNm_2, //f Addition nm to peaks in ModePeaks, channel 2
PeaksModeAdditionNm_3, //f Addition nm to peaks in ModePeaks, channel 3
PeaksModeAdditionNm_4, //f Addition nm to peaks in ModePeaks, channel 4
};
enum XDescription {
// KSpectrometer = Spectrometer
// KSwitch = Switch
// KDetector = Detector
// KCoreOutput[CoreOutputChannel] = CoreOutput
// KLogConfig[LogType] = Logs
State, //b
Frequency, //n cur freq
//Fourier_enabled, //b Global fourier enable flag
};
enum CDescription {
// KSpectrometer = Spectrometer
// KCoreOutput[CoreOutputChannel] = CoreOutput
// KLogConfig[LogType] = Logs
Halt, //b
Reboot, //n cur freq
Pause, //b Global fourier enable flag
};
enum MDescription {
Main, //b
Core, //s
Warnings, //b Global fourier enable flag
};
}
#endif // K_DESCRIPTION_H

View File

@@ -0,0 +1 @@
piqt_library(qcd_utils "Gui" "pip;qad_utils;qad_widgets;qad_graphic;cd_utils;piqt")

297
libs/qcd_utils/qcd_core.cpp Normal file
View File

@@ -0,0 +1,297 @@
#include "qcd_core.h"
#include "cdutils_k.h"
#include "cdutils_core.h"
#include "piqt.h"
#include <QWidget>
#include <QCheckBox>
#include <QGroupBox>
#include <QSpinBox>
#include <QSlider>
#include <QScrollBar>
#include <QDoubleSpinBox>
#include <QLineEdit>
#include <spinslider.h>
#include <clineedit.h>
#include <evalspinbox.h>
#include <qvariantedit.h>
#include <qcd_view.h>
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<PIDeque<int> > pathes = binded_widgets.values(w);
foreach (const PIDeque<int> & 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<PIDeque<int> > pathes = binded_widgets.values(w);
foreach (const PIDeque<int> & path, pathes)
K[path].setValue(PIString::fromNumber(v));
finishEdit(pathes);
}
void QCDCore::slotDouble(double v) {
QWidget * w = (QWidget*)sender();
if (!w || updating) return;
QList<PIDeque<int> > pathes = binded_widgets.values(w);
foreach (const PIDeque<int> & path, pathes)
K[path].setValue(PIString::fromNumber(v));
finishEdit(pathes);
}
void QCDCore::slotText(QString v) {
QWidget * w = (QWidget*)sender();
if (!w || updating) return;
QList<PIDeque<int> > pathes = binded_widgets.values(w);
foreach (const PIDeque<int> & path, pathes)
K[path].setValue(Q2PIString(v));
finishEdit(pathes);
}
void QCDCore::slotVariant(QVariant v) {
QWidget * w = (QWidget*)sender();
if (!w || updating) return;
QList<PIDeque<int> > pathes = binded_widgets.values(w);
foreach (const PIDeque<int> & 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<QWidget * >());
}
int QCDCore::bindWidgets(QList<QWidget * > 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<CDType * > 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<QWidget * , PIDeque<int> > 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<CDView * >(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<QCheckBox*>(w)->setChecked(k.toBool());
if (cn == "QGroupBox") qobject_cast<QGroupBox*>(w)->setChecked(k.toBool());
if (cn == "QSpinBox") qobject_cast<QSpinBox*>(w)->setValue(k.toInt());
if (cn == "QSlider") qobject_cast<QSlider*>(w)->setValue(k.toInt());
if (cn == "QScrollBar") qobject_cast<QScrollBar*>(w)->setValue(k.toInt());
if (cn == "QDoubleSpinBox") qobject_cast<QDoubleSpinBox*>(w)->setValue(k.toDouble());
if (cn == "SpinSlider") qobject_cast<SpinSlider*>(w)->setValue(k.toDouble());
if (cn == "QLineEdit") qobject_cast<QLineEdit*>(w)->setText(PI2QString(k.value()));
if (cn == "CLineEdit") qobject_cast<CLineEdit*>(w)->setText(PI2QString(k.value()));
if (cn == "EvalSpinBox") qobject_cast<EvalSpinBox*>(w)->setValue(k.toDouble());
if (cn == "QVariantEdit") qobject_cast<QVariantEdit*>(w)->setValue(PI2QVariant(k.variantValue()));
}
void QCDCore::finishEdit(const QList<PIDeque<int> > & pathes) {
K.calculate();
if (direct_on) {
foreach (const PIDeque<int> & path, pathes)
K.directChange(K[path]);
}
emit updateViewRequest();
}
int QCDCore::unbindWindow(QWidget * wnd) {
if (!wnd) return 0;
return unbindWidgets(wnd->findChildren<QWidget * >());
}
int QCDCore::unbindWidgets(QList<QWidget * > 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<QWidget * , PIDeque<int> > bwm = binded_widgets;
QMapIterator<QWidget * , PIDeque<int> > it(bwm);
while (it.hasNext()) {
QWidget * w = it.next().key();
unbindWidget(w);
}
binded_widgets.clear();
}
void QCDCore::updateBindedWidget(const CDType & k_) {
QMapIterator<QWidget * , PIDeque<int> > 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;
}

97
libs/qcd_utils/qcd_core.h Normal file
View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef QCD_CORE_H
#define QCD_CORE_H
#include <QObject>
#include <QMultiMap>
#include <QVariant>
#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<QWidget * > wl);
bool bindWidget(QWidget * w);
bool bindWidget(QWidget * w, const CDUtils::CDType & k);
int unbindWindow(QWidget * wnd);
int unbindWidgets(QList<QWidget * > 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<PIDeque<int> > & pathes);
EVENT_HANDLER(void, K_ChangedGlobal);
QMultiMap<QWidget * , PIDeque<int> > 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

View File

@@ -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;
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef QCD_GRAPHIC_H
#define QCD_GRAPHIC_H
#include <QWidget>
#include <evalspinbox.h>
#include <pistring.h>
#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

View File

@@ -0,0 +1,169 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CDGraphicWidget</class>
<widget class="QWidget" name="CDGraphicWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>470</width>
<height>380</height>
</rect>
</property>
<property name="windowTitle">
<string>CD Pult</string>
</property>
<layout class="QVBoxLayout" name="layoutMain">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="Graphic" name="graphic">
<property name="buttons">
<set>Graphic::Autofit|Graphic::BorderInputs|Graphic::Clear|Graphic::Configure|Graphic::CursorAxis|Graphic::Fullscreen|Graphic::Legend|Graphic::Pause|Graphic::Save</set>
</property>
<property name="borderInputsVisible">
<bool>false</bool>
</property>
<property name="statusVisible">
<bool>false</bool>
</property>
<property name="historySize">
<double>100.000000000000000</double>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="widgetConfig" native="true">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>History:</string>
</property>
</widget>
</item>
<item>
<widget class="EvalSpinBox" name="evalHistory">
<property name="value">
<double>100.000000000000000</double>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>1</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Visible:</string>
</property>
</widget>
</item>
<item>
<widget class="EvalSpinBox" name="evalVisible">
<property name="value">
<double>-1.000000000000000</double>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>1</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>Graphic</class>
<extends>QFrame</extends>
<header>graphic.h</header>
</customwidget>
<customwidget>
<class>EvalSpinBox</class>
<extends>QWidget</extends>
<header>evalspinbox.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
<sender>evalHistory</sender>
<signal>valueChanged(double)</signal>
<receiver>graphic</receiver>
<slot>setHistorySize(double)</slot>
<hints>
<hint type="sourcelabel">
<x>148</x>
<y>363</y>
</hint>
<hint type="destinationlabel">
<x>156</x>
<y>297</y>
</hint>
</hints>
</connection>
<connection>
<sender>evalVisible</sender>
<signal>valueChanged(double)</signal>
<receiver>graphic</receiver>
<slot>setMaxVisibleTime(double)</slot>
<hints>
<hint type="sourcelabel">
<x>345</x>
<y>361</y>
</hint>
<hint type="destinationlabel">
<x>342</x>
<y>337</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -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);
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef QCD_MODEDIALOG_H
#define QCD_MODEDIALOG_H
#include <QDialog>
#include <cdutils_types.h>
#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

View File

@@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QCDModeDialog</class>
<widget class="QDialog" name="QCDModeDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>251</width>
<height>152</height>
</rect>
</property>
<property name="windowTitle">
<string>Update description mode</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QCheckBox" name="checkSaveIndex">
<property name="text">
<string>Save by index</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkSaveName">
<property name="text">
<string>Save by name</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkMerge">
<property name="text">
<string>Merge</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>1</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>QCDModeDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>106</x>
<y>131</y>
</hint>
<hint type="destinationlabel">
<x>101</x>
<y>146</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>QCDModeDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>182</x>
<y>127</y>
</hint>
<hint type="destinationlabel">
<x>169</x>
<y>146</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -0,0 +1,460 @@
#include "qcd_model.h"
#include "cdutils_interface.h"
#include "cdutils_core.h"
#include "cdutils_x.h"
#include "piqt.h"
#include <QDebug>
#include <QBrush>
#include <QColor>
#include <QMimeData>
#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<int> 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<QAD::Enum>(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<int> CDItem::buildPath() const {
PIDeque<int> 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<QVariantEdit*>(editor);
edit->setValue(index.model()->data(index, Qt::EditRole));
}
void CDDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const {
QVariantEdit *edit = static_cast<QVariantEdit*>(editor);
QVariant v = edit->value();
if (v.canConvert<QAD::Enum>()) {
QAD::Enum et = v.value<QAD::Enum>();
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<CDItem*>(index.internalPointer());
if (item) return item;
}
return root;
}
QModelIndex CDItemModel::indexByPath(const PIDeque<int> & 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;
}

133
libs/qcd_utils/qcd_model.h Normal file
View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef QCD_MODEL_H
#define QCD_MODEL_H
#include <QAbstractItemModel>
#include <QItemDelegate>
#include <QStyledItemDelegate>
#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<int> 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<CDItem *> 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<int> & 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

371
libs/qcd_utils/qcd_view.cpp Normal file
View File

@@ -0,0 +1,371 @@
#include <QDir>
#include <QMouseEvent>
#include <QSortFilterProxyModel>
#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<PIDeque<int> > xl = X.enabledList();
//piCout << "X" << xl.size();
piForeachC (PIDeque<int> & 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<int> 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)));
}

113
libs/qcd_utils/qcd_view.h Normal file
View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef QCD_VIEW_H
#define QCD_VIEW_H
#include <QTreeView>
#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<int>, 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

BIN
logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

1
utils/CMakeLists.txt Normal file
View File

@@ -0,0 +1 @@
add_directories("qad_")

View File

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

312
utils/cd_pult/cddirectk.cpp Normal file
View File

@@ -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 <QFormLayout>
#include <QMimeData>
#include <QDragEnterEvent>
#include <QDragMoveEvent>
#include <QDropEvent>
#include <QMainWindow>
#include <QDockWidget>
#include <QInputDialog>
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<int> 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<PIDeque<int> > list;
QVector<CDDirectKTypeDialog::TypeInfo> ilist;
while (!cs.atEnd()) {
switch (cs.read()) {
case 1: setWindowTitle(cs.getData<QString>()); break;
case 2: list = setList(cs.getData<QStringList>()); break;
case 3: ilist = cs.getData<QVector<CDDirectKTypeDialog::TypeInfo> >(); 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<QLabel*>(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<QAction * >(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<QByteArray> 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<int>();
piForTimes (s)
addArea();
} break;
case 2: {
QVector<QByteArray> dstates = cs.getData<QVector<QByteArray> >();
for (int i = 0; i < piMini(dstates.size(), docks.size()); ++i)
docks[i]->load(dstates[i]);
} break;
case 3: da->restoreState(cs.getData<QByteArray>()); 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<KDockWidget * >(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();
}

77
utils/cd_pult/cddirectk.h Normal file
View File

@@ -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<QAction*> dactions;
QMainWindow * da;
CDDirectKTypeDialog * type_dialog;
PIVector<PIDeque<int> > k_list;
QVector<CDDirectKTypeDialog::TypeInfo> 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<KDockWidget * > docks;
QMainWindow * da;
public slots:
void changedGlobal();
private slots:
void removeArea();
void on_buttonAdd_clicked();
void on_buttonRemoveAll_clicked();
signals:
};
#endif // CDDIRECTK_H

View File

@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CDDirectK</class>
<widget class="QWidget" name="CDDirectK">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>624</width>
<height>411</height>
</rect>
</property>
<property name="windowTitle">
<string>CD Pult</string>
</property>
<layout class="QVBoxLayout" name="layoutMain" stretch="0">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="topMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QToolButton" name="buttonAdd">
<property name="toolTip">
<string>Add new</string>
</property>
<property name="icon">
<iconset resource="../../qad/application/qad_application.qrc">
<normaloff>:/icons/list-add.png</normaloff>:/icons/list-add.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="buttonRemoveAll">
<property name="toolTip">
<string>Remove all</string>
</property>
<property name="icon">
<iconset resource="../../qad/application/qad_application.qrc">
<normaloff>:/icons/edit-delete.png</normaloff>:/icons/edit-delete.png</iconset>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>1</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../../qad/application/qad_application.qrc"/>
</resources>
<connections/>
</ui>

View File

@@ -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();
}

View File

@@ -0,0 +1,44 @@
#ifndef CDDIRECTK_TYPE_DIALOG_H
#define CDDIRECTK_TYPE_DIALOG_H
#include <QDialog>
#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<double> params_d;
QVector<QString> 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

View File

@@ -0,0 +1,232 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CDDirectKTypeDialog</class>
<widget class="QDialog" name="CDDirectKTypeDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>275</width>
<height>310</height>
</rect>
</property>
<property name="windowTitle">
<string>CD Pult</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Custom</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QWidget" name="widget" native="true">
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<property name="labelAlignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Type:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="comboType">
<item>
<property name="text">
<string>Spin</string>
</property>
</item>
<item>
<property name="text">
<string>Slider</string>
</property>
</item>
<item>
<property name="text">
<string>SpinSlider</string>
</property>
</item>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Min:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="EvalSpinBox" name="evalMin"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Max:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="EvalSpinBox" name="evalMax">
<property name="value">
<double>100.000000000000000</double>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Decimals:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QSpinBox" name="spinDecimals"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Single step:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="EvalSpinBox" name="evalStep">
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Prefix:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="CLineEdit" name="linePrefix"/>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Suffix:</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="CLineEdit" name="lineSuffix"/>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>1</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>CLineEdit</class>
<extends>QLineEdit</extends>
<header>clineedit.h</header>
</customwidget>
<customwidget>
<class>EvalSpinBox</class>
<extends>QWidget</extends>
<header>evalspinbox.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
<sender>groupBox</sender>
<signal>toggled(bool)</signal>
<receiver>widget</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>86</x>
<y>49</y>
</hint>
<hint type="destinationlabel">
<x>94</x>
<y>91</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>CDDirectKTypeDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>297</x>
<y>285</y>
</hint>
<hint type="destinationlabel">
<x>315</x>
<y>280</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>CDDirectKTypeDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>281</x>
<y>290</y>
</hint>
<hint type="destinationlabel">
<x>283</x>
<y>307</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -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 <QMimeData>
#include <QDragEnterEvent>
#include <QDragMoveEvent>
#include <QDropEvent>
#include <QMainWindow>
#include <QDockWidget>
#include <QInputDialog>
using namespace CDUtils;
QStringList CDUtils::getList(const PIVector<PIDeque<int> > & x_list) {
QStringList ret;
piForeachC (PIDeque<int> & p, x_list)
ret << PI2QString(CDCore::pathToString(p));
return ret;
}
PIVector<PIDeque<int> > CDUtils::setList(const QStringList & l) {
PIVector<PIDeque<int> > 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<int> 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<PIString, PIVector<double> > & data) {
for (int i = 0; i < x_list.size_s(); ++i) {
PIString sp = CDCore::pathToString(x_list[i]);
const PIVector<double> & 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<QString>()); break;
case 2: x_list = setList(cs.getData<QStringList>()); break;
case 3: graphic->graphic()->load(cs.getData<QByteArray>()); break;
case 4: graphic->evalSpinBoxHistory()->setExpression(cs.getData<QString>()); break;
case 5: graphic->evalSpinBoxVisible()->setExpression(cs.getData<QString>()); 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<CDGraphicWidget*>(o) && o)
o = o->parent();
return qobject_cast<CDGraphicWidget*>(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<QAction * >(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<QByteArray> 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<int>();
piForTimes (s)
addGraphic();
} break;
case 2: {
QVector<QByteArray> dstates = cs.getData<QVector<QByteArray> >();
for (int i = 0; i < piMini(dstates.size(), docks.size()); ++i)
docks[i]->load(dstates[i]);
} break;
case 3: da->restoreState(cs.getData<QByteArray>()); break;
case 4:
X.lock();
X.setEnabledList(setList(cs.getData<QStringList>()));
X.unlock();
break;
case 5:
buttonConfigVisible->setChecked(cs.getData<bool>());
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<PIString, PIVector<double> > data;
X.lock();
PIVector<PIDeque<int> > x_list = X.enabledList();
PIVector<double> ch;
piForeachC (PIDeque<int> & 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<GDockWidget * >(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();
}

View File

@@ -0,0 +1,92 @@
#ifndef CDGRAPHICS_H
#define CDGRAPHICS_H
#include <QWidget>
#include <QDockWidget>
#include <QMenu>
#include "ui_cdgraphics.h"
#include "qcd_graphic.h"
#include <pistring.h>
namespace CDUtils {
class CDType;
class CDSection;
QStringList getList(const PIVector<PIDeque<int> > & x_list);
PIVector<PIDeque<int> > 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<PIString, PIVector<double> > & 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<QAction*> dactions;
QMainWindow * da;
PIVector<PIDeque<int> > 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<GDockWidget * > 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

168
utils/cd_pult/cdgraphics.ui Normal file
View File

@@ -0,0 +1,168 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CDGraphics</class>
<widget class="QWidget" name="CDGraphics">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>624</width>
<height>411</height>
</rect>
</property>
<property name="windowTitle">
<string>CD Pult</string>
</property>
<layout class="QVBoxLayout" name="layoutMain" stretch="0">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="topMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QToolButton" name="buttonAdd">
<property name="toolTip">
<string>Add new</string>
</property>
<property name="icon">
<iconset resource="../../qad/utils/qad_utils.qrc">
<normaloff>:/icons/list-add.png</normaloff>:/icons/list-add.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="buttonClear">
<property name="toolTip">
<string>Clear all</string>
</property>
<property name="icon">
<iconset resource="../../qad/utils/qad_utils.qrc">
<normaloff>:/icons/edit-clear.png</normaloff>:/icons/edit-clear.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="buttonRemoveAll">
<property name="toolTip">
<string>Remove all</string>
</property>
<property name="icon">
<iconset resource="../../qad/utils/qad_utils.qrc">
<normaloff>:/icons/edit-delete.png</normaloff>:/icons/edit-delete.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="buttonConfigVisible">
<property name="toolTip">
<string>Remove all</string>
</property>
<property name="icon">
<iconset resource="../../qad/application/qad_application.qrc">
<normaloff>:/icons/layer-visible-off.png</normaloff>
<normalon>:/icons/layer-visible-on.png</normalon>:/icons/layer-visible-off.png</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="buttonLegendVisible">
<property name="toolTip">
<string>Remove all</string>
</property>
<property name="icon">
<iconset resource="../../qad/widgets/qad_widgets.qrc">
<normaloff>:/icons/legend.png</normaloff>:/icons/legend.png</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="buttonPause">
<property name="toolTip">
<string>Remove all</string>
</property>
<property name="icon">
<iconset resource="../../qad/graphic/qad_graphic.qrc">
<normaloff>:/icons/media-playback-pause.png</normaloff>:/icons/media-playback-pause.png</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="buttonBorderInputsVisible">
<property name="toolTip">
<string>Remove all</string>
</property>
<property name="icon">
<iconset resource="../../qad/widgets/qad_widgets.qrc">
<normaloff>:/icons/border-line.png</normaloff>:/icons/border-line.png</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>1</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../../qad/utils/qad_utils.qrc"/>
<include location="../../qad/widgets/qad_widgets.qrc"/>
<include location="../../qad/application/qad_application.qrc"/>
<include location="../../qad/graphic/qad_graphic.qrc"/>
</resources>
<connections/>
</ui>

10
utils/cd_pult/cdpult.qrc Normal file
View File

@@ -0,0 +1,10 @@
<RCC>
<qresource prefix="/">
<file>icons/db-export.png</file>
<file>icons/db-import.png</file>
<file>icons/timer.png</file>
<file>icons/flame.png</file>
<file>icons/accessories-calculator.png</file>
<file>icons/accessories-text-editor.png</file>
</qresource>
</RCC>

View File

@@ -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 <QFileDialog>
#include <QScrollBar>
#include <QImageReader>
#include <QMessageBox>
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<QAD::File>().file);
widgetX->setFile(editFileX->value().value<QAD::File>().file);
widgetC->setFile(editFileC->value().value<QAD::File>().file);
widgetM->setFile(editFileM->value().value<QAD::File>().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<PIDeque<int> > x_list = X.enabledList();
X.unlock();
piForeachC (PIDeque<int> & 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<QAD::File>();
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<QAD::File>().file);
conf.setValue("file_x", editFileX->value().value<QAD::File>().file);
conf.setValue("file_c", editFileC->value().value<QAD::File>().file);
conf.setValue("file_m", editFileM->value().value<QAD::File>().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<QAD::File>().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<QAD::File>();
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<QByteArray> 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)));
}

View File

@@ -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<CDViewWidget::LogIcon, QIcon> 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

View File

@@ -0,0 +1,612 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CDPultWindow</class>
<widget class="EMainWindow" name="CDPultWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>798</width>
<height>593</height>
</rect>
</property>
<property name="windowTitle">
<string>CD Pult</string>
</property>
<property name="dockNestingEnabled">
<bool>true</bool>
</property>
<property name="dockOptions">
<set>QMainWindow::AllowNestedDocks|QMainWindow::AllowTabbedDocks|QMainWindow::AnimatedDocks</set>
</property>
<widget class="QWidget" name="central"/>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>798</width>
<height>24</height>
</rect>
</property>
<widget class="QMenu" name="menuMain">
<property name="title">
<string>Main</string>
</property>
<widget class="QMenu" name="menuOpen_recent">
<property name="title">
<string>Open recent</string>
</property>
<property name="icon">
<iconset resource="../../qad/application/qad_application.qrc">
<normaloff>:/icons/document-open-recent.png</normaloff>:/icons/document-open-recent.png</iconset>
</property>
</widget>
<addaction name="actionOpen"/>
<addaction name="menuOpen_recent"/>
<addaction name="actionSave"/>
<addaction name="actionSaveAs"/>
</widget>
<addaction name="menuMain"/>
</widget>
<widget class="EDockWidget" name="dockCDKView">
<property name="windowIcon">
<iconset resource="../../qad/application/qad_application.qrc">
<normaloff>:/icons/document-edit.png</normaloff>:/icons/document-edit.png</iconset>
</property>
<property name="windowTitle">
<string>K</string>
</property>
<attribute name="dockWidgetArea">
<number>1</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents">
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="CDViewWidget" name="widgetK" native="true"/>
</item>
</layout>
</widget>
</widget>
<widget class="EDockWidget" name="dockLog">
<property name="windowIcon">
<iconset resource="cdpult.qrc">
<normaloff>:/icons/dialog-information.png</normaloff>:/icons/dialog-information.png</iconset>
</property>
<property name="windowTitle">
<string>Log</string>
</property>
<attribute name="dockWidgetArea">
<number>8</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_2">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QListWidget" name="listLog">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="showDropIndicator" stdset="0">
<bool>false</bool>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="horizontalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="EDockWidget" name="dockCDXView">
<property name="windowIcon">
<iconset resource="../../qad/widgets/qad_widgets.qrc">
<normaloff>:/icons/qvariantedit.png</normaloff>:/icons/qvariantedit.png</iconset>
</property>
<property name="windowTitle">
<string>X</string>
</property>
<attribute name="dockWidgetArea">
<number>1</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_3">
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="CDViewWidget" name="widgetX" native="true"/>
</item>
</layout>
</widget>
</widget>
<widget class="EDockWidget" name="dockSession">
<property name="windowIcon">
<iconset resource="../../qad/application/qad_application.qrc">
<normaloff>:/icons/configure.png</normaloff>:/icons/configure.png</iconset>
</property>
<property name="windowTitle">
<string>Session</string>
</property>
<attribute name="dockWidgetArea">
<number>2</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_4">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QPushButton" name="buttonSessionApply">
<property name="text">
<string>Apply</string>
</property>
<property name="icon">
<iconset resource="../../qad/widgets/qad_widgets.qrc">
<normaloff>:/icons/dialog-ok-apply.png</normaloff>:/icons/dialog-ok-apply.png</iconset>
</property>
</widget>
</item>
<item>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<property name="labelAlignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Name:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="CLineEdit" name="lineSessionName"/>
</item>
<item>
<widget class="QPushButton" name="buttonIcon">
<property name="toolTip">
<string>Select icon...</string>
</property>
<property name="icon">
<iconset resource="../../qad/blockview/qad_blockview.qrc">
<normaloff>:/icons/view-preview.png</normaloff>:/icons/view-preview.png</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>K file:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QVariantEdit" name="editFileK"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>X file:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QVariantEdit" name="editFileX"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>C file:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QVariantEdit" name="editFileC"/>
</item>
<item row="5" column="0" colspan="2">
<widget class="QCheckBox" name="checkSyncFiles">
<property name="text">
<string>Sync files</string>
</property>
</widget>
</item>
<item row="6" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QCheckBox" name="checkHasK">
<property name="text">
<string>K</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkHasX">
<property name="text">
<string>X</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkHasC">
<property name="text">
<string>C</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkHasM">
<property name="text">
<string>M</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="7" column="0" colspan="2">
<widget class="QCheckBox" name="checkDefaultConfig">
<property name="text">
<string>Default config</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>M file:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QVariantEdit" name="editFileM"/>
</item>
</layout>
</item>
<item>
<widget class="QCodeEdit" name="codeConfig">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>include = ip.conf
[connection]
device.cd = eth://udp:${ip.pult}:27002:${ip.app}:27001 #s
[]
</string>
</property>
<property name="editorFont">
<font>
<family>DejaVu Sans Mono</family>
<pointsize>9</pointsize>
</font>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="EDockWidget" name="dockCDCView">
<property name="windowIcon">
<iconset resource="../../qad/blockview/qad_blockview.qrc">
<normaloff>:/icons/legend.png</normaloff>:/icons/legend.png</iconset>
</property>
<property name="windowTitle">
<string>C</string>
</property>
<attribute name="dockWidgetArea">
<number>1</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_5">
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="CDViewWidget" name="widgetC" native="true"/>
</item>
</layout>
</widget>
</widget>
<widget class="EDockWidget" name="dockGraphics">
<property name="windowIcon">
<iconset resource="../../qad/blockview/qad_blockview.qrc">
<normaloff>:/icons/format-stroke-color.png</normaloff>:/icons/format-stroke-color.png</iconset>
</property>
<property name="windowTitle">
<string>Graphics</string>
</property>
<attribute name="dockWidgetArea">
<number>8</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_6">
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<widget class="CDGraphics" name="widgetGraphics" native="true"/>
</item>
</layout>
</widget>
</widget>
<widget class="EDockWidget" name="dockDirectK">
<property name="windowIcon">
<iconset resource="../../qad/widgets/qad_widgets.qrc">
<normaloff>:/icons/tools-wizard.png</normaloff>:/icons/tools-wizard.png</iconset>
</property>
<property name="windowTitle">
<string>Direct K</string>
</property>
<attribute name="dockWidgetArea">
<number>8</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_7">
<layout class="QVBoxLayout" name="verticalLayout_7">
<item>
<widget class="CDDirectK" name="widgetDirectK" native="true"/>
</item>
</layout>
</widget>
</widget>
<widget class="EDockWidget" name="dockCDMView">
<property name="windowIcon">
<iconset resource="cdpult.qrc">
<normaloff>:/icons/accessories-text-editor.png</normaloff>:/icons/accessories-text-editor.png</iconset>
</property>
<property name="windowTitle">
<string>M</string>
</property>
<attribute name="dockWidgetArea">
<number>1</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_8">
<layout class="QVBoxLayout" name="verticalLayout_8">
<item>
<widget class="CDViewWidget" name="widgetM" native="true"/>
</item>
</layout>
</widget>
</widget>
<action name="actionOpen">
<property name="icon">
<iconset resource="../../qad/application/qad_application.qrc">
<normaloff>:/icons/document-open.png</normaloff>:/icons/document-open.png</iconset>
</property>
<property name="text">
<string>Open...</string>
</property>
<property name="shortcut">
<string>Ctrl+O</string>
</property>
</action>
<action name="actionSave">
<property name="icon">
<iconset resource="../../qad/application/qad_application.qrc">
<normaloff>:/icons/document-save.png</normaloff>:/icons/document-save.png</iconset>
</property>
<property name="text">
<string>Save</string>
</property>
<property name="shortcut">
<string>Ctrl+S</string>
</property>
</action>
<action name="actionSaveAs">
<property name="icon">
<iconset resource="../../qad/application/qad_application.qrc">
<normaloff>:/icons/document-save-as.png</normaloff>:/icons/document-save-as.png</iconset>
</property>
<property name="text">
<string>Save As...</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+S</string>
</property>
</action>
<addaction name="actionOpen"/>
<addaction name="actionSave"/>
<addaction name="actionSaveAs"/>
<addaction name="menuMain"/>
<addaction name="menuOpen_recent"/>
<addaction name="separator"/>
<addaction name="separator"/>
<addaction name="separator"/>
<addaction name="separator"/>
<addaction name="separator"/>
<addaction name="separator"/>
<addaction name="separator"/>
<addaction name="separator"/>
<addaction name="separator"/>
<addaction name="separator"/>
<addaction name="separator"/>
<addaction name="separator"/>
<addaction name="separator"/>
<addaction name="separator"/>
<addaction name="separator"/>
<addaction name="separator"/>
<addaction name="separator"/>
<addaction name="separator"/>
<addaction name="separator"/>
<addaction name="separator"/>
<addaction name="separator"/>
<addaction name="separator"/>
</widget>
<customwidgets>
<customwidget>
<class>EMainWindow</class>
<extends>QMainWindow</extends>
<header>emainwindow.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>CLineEdit</class>
<extends>QLineEdit</extends>
<header>clineedit.h</header>
</customwidget>
<customwidget>
<class>QCodeEdit</class>
<extends>QWidget</extends>
<header>qcodeedit.h</header>
</customwidget>
<customwidget>
<class>QVariantEdit</class>
<extends>QWidget</extends>
<header>qvariantedit.h</header>
</customwidget>
<customwidget>
<class>EDockWidget</class>
<extends>QDockWidget</extends>
<header>edockwidget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>CDViewWidget</class>
<extends>QWidget</extends>
<header>cdviewwidget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>CDGraphics</class>
<extends>QWidget</extends>
<header>cdgraphics.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>CDDirectK</class>
<extends>QWidget</extends>
<header>cddirectk.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="../../qad/application/qad_application.qrc"/>
<include location="../../qad/blockview/qad_blockview.qrc"/>
<include location="../../qad/widgets/qad_widgets.qrc"/>
<include location="cdpult.qrc"/>
</resources>
<connections>
<connection>
<sender>actionSave</sender>
<signal>triggered()</signal>
<receiver>CDPultWindow</receiver>
<slot>saveFile()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>399</x>
<y>299</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionSaveAs</sender>
<signal>triggered()</signal>
<receiver>CDPultWindow</receiver>
<slot>saveAsFile()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>399</x>
<y>299</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionOpen</sender>
<signal>triggered()</signal>
<receiver>CDPultWindow</receiver>
<slot>openFile()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>399</x>
<y>299</y>
</hint>
</hints>
</connection>
<connection>
<sender>checkSyncFiles</sender>
<signal>toggled(bool)</signal>
<receiver>editFileX</receiver>
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>786</x>
<y>220</y>
</hint>
<hint type="destinationlabel">
<x>786</x>
<y>151</y>
</hint>
</hints>
</connection>
<connection>
<sender>checkSyncFiles</sender>
<signal>toggled(bool)</signal>
<receiver>editFileC</receiver>
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>786</x>
<y>220</y>
</hint>
<hint type="destinationlabel">
<x>786</x>
<y>172</y>
</hint>
</hints>
</connection>
<connection>
<sender>checkDefaultConfig</sender>
<signal>toggled(bool)</signal>
<receiver>codeConfig</receiver>
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>786</x>
<y>276</y>
</hint>
<hint type="destinationlabel">
<x>581</x>
<y>304</y>
</hint>
</hints>
</connection>
<connection>
<sender>checkSyncFiles</sender>
<signal>toggled(bool)</signal>
<receiver>editFileM</receiver>
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>767</x>
<y>205</y>
</hint>
<hint type="destinationlabel">
<x>767</x>
<y>187</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -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 <QFileDialog>
CDViewWidget::CDViewWidget(QWidget * parent) : QWidget(parent), Ui::CDViewWidget() {
qRegisterMetaType<CDViewWidget::LogIcon>("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);
}

View File

@@ -0,0 +1,41 @@
#ifndef CDVIEWWIDGET_H
#define CDVIEWWIDGET_H
#include <QWidget>
#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

View File

@@ -0,0 +1,176 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CDViewWidget</class>
<widget class="QWidget" name="CDViewWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>689</width>
<height>459</height>
</rect>
</property>
<property name="windowTitle">
<string>CD Pult</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QPushButton" name="buttonSend">
<property name="text">
<string>Send</string>
</property>
<property name="icon">
<iconset resource="cdpult.qrc">
<normaloff>:/icons/flame.png</normaloff>:/icons/flame.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonReceive">
<property name="text">
<string>Receive</string>
</property>
<property name="icon">
<iconset resource="cdpult.qrc">
<normaloff>:/icons/document-revert.png</normaloff>:/icons/document-revert.png</iconset>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="buttonLoad">
<property name="text">
<string>Load</string>
</property>
<property name="icon">
<iconset resource="../../qad/application/qad_application.qrc">
<normaloff>:/icons/document-open.png</normaloff>:/icons/document-open.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonSave">
<property name="text">
<string>Save</string>
</property>
<property name="icon">
<iconset resource="../../qad/application/qad_application.qrc">
<normaloff>:/icons/document-save.png</normaloff>:/icons/document-save.png</iconset>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="buttonParse">
<property name="text">
<string>Update description ...</string>
</property>
<property name="icon">
<iconset resource="cdpult.qrc">
<normaloff>:/icons/view-refresh.png</normaloff>:/icons/view-refresh.png</iconset>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>1</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="CDView" name="view">
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="editTriggers">
<set>QAbstractItemView::AnyKeyPressed|QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed</set>
</property>
<property name="dragEnabled">
<bool>true</bool>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::DragOnly</enum>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="horizontalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>CDView</class>
<extends>QTreeView</extends>
<header>qcd_view.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="../../qad/application/qad_application.qrc"/>
<include location="cdpult.qrc"/>
</resources>
<connections/>
</ui>

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

373
utils/cd_pult/main.cpp Normal file
View File

@@ -0,0 +1,373 @@
#include <QApplication>
#include "cdpultwindow.h"
template <typename Key, typename T>
class PIHash {
//template <typename Key1, typename T1> friend PIByteArray & operator >>(PIByteArray & s, PIHash<Key1, T1> & v);
//template <typename Key1, typename T1> friend PIByteArray & operator <<(PIByteArray & s, const PIHash<Key1, T1> & v);
public:
PIHash() {;}
PIHash(const PIHash<Key, T> & other) {*this = other;}
virtual ~PIHash() {;}
PIHash<Key, T> & operator =(const PIHash<Key, T> & other) {
if (this == &other) return *this;
clear();
pih_content = other.pih_content;
return *this;
}
typedef T mapped_type;
typedef Key key_type;
typedef PIPair<Key, T> value_type;
/*
class iterator {
friend class PIHash<Key, T>;
private:
iterator(const PIHash<Key, T> * v, ssize_t p): parent(v), pos(p) {}
const PIHash<Key, T> * parent;
ssize_t pos;
public:
iterator(): parent(0), pos(0) {}
const Key & key() const {return const_cast<PIHash<Key, T> * >(parent)->_key(pos);}
T & value() {return const_cast<PIHash<Key, T> * >(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<Key, T>;
private:
reverse_iterator(const PIHash<Key, T> * v, ssize_t p): parent(v), pos(p) {}
const PIHash<Key, T> * parent;
ssize_t pos;
public:
reverse_iterator(): parent(0), pos(0) {}
const Key & key() const {return const_cast<PIHash<Key, T> * >(parent)->_key(pos);}
T & value() const {return const_cast<PIHash<Key, T> * >(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<Key, T>;
private:
const_iterator(const PIHash<Key, T> * 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<Key, T> * 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<PIHash<Key, T> * >(parent)->pih_content[pos][bpos].key;}
const T & value() const {return const_cast<PIHash<Key, T> * >(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<Key, T>;
private:
const_reverse_iterator(const PIHash<Key, T> * v, ssize_t p): parent(v), pos(p) {}
const PIHash<Key, T> * 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<HashEntry> & 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<Key, T> & operator <<(const PIHash<Key, T> & 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<Key, T> & t) const {return (pih_content == t.pih_content);}
bool operator !=(const PIHash<Key, T> & t) const {return (pih_content != t.pih_content);}
bool contains(const Key & key) const {
bool f(false);
_find(key, f);
return f;
}
PIHash<Key, T> & reserve(size_t new_size) {_rehash(new_size); return *this;}
PIHash<Key, T> & remove(const Key & key) {
uint k = piHash(key);
int i = _index(k);
if (i >= pih_content.size_s()) return *this;
PIVector<HashEntry> & 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<Key, T> & erase(const Key & key) {return remove(key);}
PIHash<Key, T> & clear() {pih_content.clear(); return *this;}
void swap(PIHash<Key, T> & other) {
pih_content.swap(other.pih_content);
}
PIHash<Key, T> & 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<HashEntry> & 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<T> values() const {
PIVector<T> 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<Key> keys() const {
PIVector<Key> 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 <typename Key1, typename T1> friend PIByteArray & operator >>(PIByteArray & s, PIDeque<typename PIHash<Key1, T1>::HashEntry> & v);
template <typename Key1, typename T1> friend PIByteArray & operator <<(PIByteArray & s, const PIDeque<typename PIHash<Key1, T1>::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<PIVector<HashEntry> > 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<PIVector<HashEntry> > 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<PIString, PIString> h2;
QMap<PIString, PIString> 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();
}