Merge pull request 'master' (#68) from master into release
All checks were successful
SHS Gitea/libs/pipeline/head This commit looks good

Reviewed-on: https://git.shs.tools/SHS/libs/pulls/68
This commit was merged in pull request #68.
This commit is contained in:
2020-08-31 18:53:02 +03:00
101 changed files with 10672 additions and 10747 deletions

View File

@@ -9,15 +9,81 @@ project(libs)
set(PIP_CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/pip/cmake")
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}" "${PIP_CMAKE_MODULE_PATH}" "${CMAKE_CURRENT_SOURCE_DIR}/qad/cmake")
set(LIBPROJECT 1)
set(_qt_libs )
set(_qt_apps )
set(_qt_plugs)
include(GenerateExportHeader)
include(SDKMacros)
include(QADMacros)
include(DeployMacros)
if(NOT DEFINED BUILD_NUMBER)
set(BUILD_NUMBER 9999)
endif()
if("x${BUILD_NUMBER}" STREQUAL "x")
set(BUILD_NUMBER 0)
endif()
if(STATIC_LIB)
set(QAD_LIB_TYPE STATIC)
add_definitions(-DQAD_STATIC_DEFINE)
set(QAD_LIB_TYPE_MSG "Static")
else()
set(QAD_LIB_TYPE SHARED)
set(QAD_LIB_TYPE_MSG "Shared")
endif()
set(_QAD_MAJOR 1)
set(_QAD_MINOR 9)
set(_QAD_REVISION 0)
set(_QAD_SUFFIX )
set(_QAD_COMPANY SHS)
set(_QAD_DOMAIN org.SHS)
set(QAD_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/qad/qad_version.h")
set_version(QAD
MAJOR "${_QAD_MAJOR}"
MINOR "${_QAD_MINOR}"
REVISION "${_QAD_REVISION}"
BUILD "${BUILD_NUMBER}"
SUFFIX "${_QAD_SUFFIX}"
OUTPUT "${QAD_VERSION_FILE}")
set_deploy_property(QAD ${QAD_LIB_TYPE}
FULLNAME "${_QAD_DOMAIN}.*"
COMPANY "${_QAD_COMPANY}")
if(STATIC_LIB)
set(PIQt_LIB_TYPE STATIC)
add_definitions(-DPIQt_STATIC_DEFINE)
set(PIQt_LIB_TYPE_MSG "Static")
else()
set(PIQt_LIB_TYPE SHARED)
set(PIQt_LIB_TYPE_MSG "Shared")
endif()
set(_PIQt_MAJOR 1)
set(_PIQt_MINOR 0)
set(_PIQt_REVISION 0)
set(_PIQt_SUFFIX )
set(_PIQt_COMPANY SHS)
set(_PIQt_DOMAIN org.SHS)
if(NOT DEFINED BUILD_NUMBER)
set(BUILD_NUMBER 9999)
endif()
set(PIQt_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/piqt/piqt_version.h")
set_version(PIQt
MAJOR "${_PIQt_MAJOR}"
MINOR "${_PIQt_MINOR}"
REVISION "${_PIQt_REVISION}"
BUILD "${BUILD_NUMBER}"
SUFFIX "${_PIQt_SUFFIX}"
OUTPUT "${PIQt_VERSION_FILE}")
set_deploy_property(PIQt ${_PIQt_LIB_TYPE}
FULLNAME "${_PIQt_DOMAIN}.*"
COMPANY "${_PIQt_COMPANY}")
include_directories(${CMAKE_CURRENT_BINARY_DIR}/pip)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/qad)
include_directories(${CMAKE_CURRENT_BINARY_DIR}/piqt)
@@ -141,11 +207,11 @@ else()
endif()
endforeach()
if(UTILS)
message(STATUS "Building with utils")
else()
message(STATUS "Building only libraries")
endif()
#if(UTILS)
# message(STATUS "Building with utils")
#else()
# message(STATUS "Building only libraries")
#endif()
add_subdirectory(pip)
foreach(F ${PIP_MAIN_FOLDERS})
@@ -155,7 +221,7 @@ else()
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/cd_utils" "${CMAKE_CURRENT_BINARY_DIR}/cd_utils")
set(_DIRS)
if (SomeQtFound)
message(STATUS "Building Qt-derived targets for ${QtVersions}")
#message(STATUS "Building Qt-derived targets for ${QtVersions}")
add_subdirectory(qad)
include_directories(${qad_includes})
add_subdirectory(piqt)
@@ -173,6 +239,52 @@ else()
list(APPEND QT_MULTILIB_LIST ${_D})
add_subdirectory(${_D})
endforeach(_D)
macro(align_list _list _out)
set(_max_len 0)
foreach(_m ${_list})
string(LENGTH "${_m}" _clen)
if (_clen GREATER _max_len)
set(_max_len ${_clen})
endif()
endforeach()
set(${_out})
foreach(_m ${_list})
set(_am "${_m}")
while(TRUE)
string(LENGTH "${_am}" _clen)
if (_clen GREATER_EQUAL ${_max_len})
break()
endif()
string(APPEND _am " ")
endwhile()
list(APPEND ${_out} "${_am}")
endforeach()
endmacro()
macro(print_list _list _name)
if (NOT "x${_list}" STREQUAL "x")
message("")
message(" ${_name}:")
#align_list("${_list}" _alist)
foreach(_m ${_list})
message(" * ${_m}")
endforeach()
endif()
endmacro()
message("----------QAD-----------")
message(" Build for ${QtVersions}")
message(" QAD Version: ${QAD_VERSION}")
message(" QAD Linkage: ${QAD_LIB_TYPE_MSG}")
message(" PIQt Version: ${PIQt_VERSION}")
message(" PIQt Linkage: ${PIQt_LIB_TYPE_MSG}")
print_list("${_qt_libs}" "Libraries")
print_list("${_qt_apps}" "Applications")
print_list("${_qt_plugs}" "Plugins")
message("-----------------------")
message("")
else()
message(STATUS "None of Qt found, skip Qt-derived targets")
endif()

View File

@@ -1,99 +1,107 @@
macro(sdk_install _DIR IS_APP _TARGET _H_FILES _QM_FILES)
#message("QM=${_QM_FILES}")
if((NOT ${IS_APP}) AND (NOT "${_H_FILES}" STREQUAL ""))
if(LIB)
if(WIN32)
install(FILES ${_H_FILES} DESTINATION ${MINGW_INCLUDE}/${_DIR})
else()
install(FILES ${_H_FILES} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/${_DIR})
endif()
else()
install(FILES ${_H_FILES} DESTINATION include/${_DIR})
endif()
endif()
if (NOT "${_TARGET}" STREQUAL "")
if(LIB)
if(WIN32)
if (${IS_APP})
qt_install(TARGETS ${_TARGET} DESTINATION ${MINGW_BIN})
qt_install(TARGETS ${_TARGET} DESTINATION QtBin)
else()
qt_install(TARGETS ${_TARGET} ARCHIVE DESTINATION ${MINGW_LIB})
qt_install(TARGETS ${_TARGET} RUNTIME DESTINATION ${MINGW_BIN})
qt_install(TARGETS ${_TARGET} RUNTIME DESTINATION QtBin)
endif()
else()
if (${IS_APP})
qt_install(TARGETS ${_TARGET} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
else()
qt_install(TARGETS ${_TARGET} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib)
endif()
endif()
if(NOT "x${_QM_FILES}" STREQUAL "x")
qt_install(LANG ${_QM_FILES} DESTINATION QtLang)
endif()
else()
if(${IS_APP})
qt_install(TARGETS ${_TARGET} DESTINATION bin)
else()
if(WIN32)
qt_install(TARGETS ${_TARGET} RUNTIME DESTINATION bin)
qt_install(TARGETS ${_TARGET} ARCHIVE DESTINATION lib)
else()
qt_install(TARGETS ${_TARGET} DESTINATION lib)
endif()
endif()
if(NOT "x${_QM_FILES}" STREQUAL "x")
qt_install(LANG ${_QM_FILES} DESTINATION lang)
endif()
endif()
endif()
endmacro()
macro(add_directories_with_include multilib_prefix)
set(DIRS)
file(GLOB _dl "[^.]*")
foreach(_d ${_dl})
if(IS_DIRECTORY ${_d})
list(APPEND DIRS ${_d})
endif()
endforeach()
set(inc_var ${multilib_prefix}includes)
set(${inc_var})
foreach(_d ${DIRS})
get_filename_component(_dname "${_d}" NAME)
list(APPEND QT_MULTILIB_LIST ${multilib_prefix}${_dname})
list(APPEND ${inc_var} "${_d}")
list(APPEND ${inc_var} "${CMAKE_CURRENT_BINARY_DIR}/${_dname}")
endforeach()
include_directories(${${inc_var}})
foreach(_d ${DIRS})
add_subdirectory(${_d})
endforeach()
set(QT_MULTILIB_LIST ${QT_MULTILIB_LIST} PARENT_SCOPE)
set(${inc_var} ${${inc_var}} PARENT_SCOPE)
if (LIB)
set(_ALL_TARGETS ${_ALL_TARGETS} PARENT_SCOPE)
endif()
endmacro()
macro(add_directories multilib_prefix)
include_directories(${${multilib_prefix}includes})
file(GLOB _dl "[^.]*")
foreach(_d ${_dl})
if(IS_DIRECTORY ${_d})
add_subdirectory(${_d})
endif()
endforeach()
if (LIB)
set(_ALL_TARGETS ${_ALL_TARGETS} PARENT_SCOPE)
endif()
endmacro()
macro(sdk_install _DIR IS_APP _TARGET _H_FILES _QM_FILES)
#message("QM=${_QM_FILES}")
if((NOT ${IS_APP}) AND (NOT "${_H_FILES}" STREQUAL ""))
if(LIB)
if(WIN32)
install(FILES ${_H_FILES} DESTINATION ${MINGW_INCLUDE}/${_DIR})
else()
install(FILES ${_H_FILES} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/${_DIR})
endif()
else()
install(FILES ${_H_FILES} DESTINATION include/${_DIR})
endif()
endif()
if (NOT "${_TARGET}" STREQUAL "")
if(LIB)
if(WIN32)
if (${IS_APP})
qt_install(TARGETS ${_TARGET} DESTINATION ${MINGW_BIN})
qt_install(TARGETS ${_TARGET} DESTINATION QtBin)
else()
qt_install(TARGETS ${_TARGET} ARCHIVE DESTINATION ${MINGW_LIB})
qt_install(TARGETS ${_TARGET} RUNTIME DESTINATION ${MINGW_BIN})
qt_install(TARGETS ${_TARGET} RUNTIME DESTINATION QtBin)
endif()
else()
if (${IS_APP})
qt_install(TARGETS ${_TARGET} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
else()
qt_install(TARGETS ${_TARGET} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib)
endif()
endif()
if(NOT "x${_QM_FILES}" STREQUAL "x")
qt_install(LANG ${_QM_FILES} DESTINATION QtLang)
endif()
else()
if(${IS_APP})
qt_install(TARGETS ${_TARGET} DESTINATION bin)
else()
if(WIN32)
qt_install(TARGETS ${_TARGET} RUNTIME DESTINATION bin)
qt_install(TARGETS ${_TARGET} ARCHIVE DESTINATION lib)
else()
qt_install(TARGETS ${_TARGET} DESTINATION lib)
endif()
endif()
if(NOT "x${_QM_FILES}" STREQUAL "x")
qt_install(LANG ${_QM_FILES} DESTINATION lang)
endif()
endif()
endif()
endmacro()
macro(copy_to_parent _inc_var)
set(QT_MULTILIB_LIST ${QT_MULTILIB_LIST} PARENT_SCOPE)
set(_qt_libs ${_qt_libs} PARENT_SCOPE)
set(_qt_apps ${_qt_apps} PARENT_SCOPE)
set(_qt_plugs ${_qt_plugs} PARENT_SCOPE)
if (NOT "x${_inc_var}" STREQUAL "x")
set(${_inc_var} ${${_inc_var}} PARENT_SCOPE)
endif()
if (LIB)
set(_ALL_TARGETS ${_ALL_TARGETS} PARENT_SCOPE)
endif()
endmacro()
macro(add_directories_with_include multilib_prefix)
set(DIRS)
file(GLOB _dl "[^.]*")
foreach(_d ${_dl})
if(IS_DIRECTORY ${_d})
list(APPEND DIRS ${_d})
endif()
endforeach()
set(inc_var ${multilib_prefix}includes)
set(${inc_var})
foreach(_d ${DIRS})
get_filename_component(_dname "${_d}" NAME)
list(APPEND QT_MULTILIB_LIST ${multilib_prefix}${_dname})
list(APPEND ${inc_var} "${_d}")
list(APPEND ${inc_var} "${CMAKE_CURRENT_BINARY_DIR}/${_dname}")
endforeach()
include_directories(${${inc_var}})
foreach(_d ${DIRS})
add_subdirectory(${_d})
endforeach()
copy_to_parent(${inc_var})
endmacro()
macro(add_directories multilib_prefix)
include_directories(${${multilib_prefix}includes})
file(GLOB _dl "[^.]*")
foreach(_d ${_dl})
if(IS_DIRECTORY ${_d})
add_subdirectory(${_d})
endif()
endforeach()
copy_to_parent(${multilib_prefix}includes)
endmacro()

View File

@@ -1,37 +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()
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()

View File

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

View File

@@ -1,41 +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]);
}
}
#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]);
}
}

View File

@@ -1,46 +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
/*
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

@@ -1,606 +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);
}
#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

@@ -1,147 +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
/*
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

@@ -1,217 +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);
}
#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

@@ -1,96 +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
/*
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

@@ -1,20 +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));
}
#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));
}

View File

@@ -1,47 +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
/*
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

@@ -1,22 +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);
}
#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);
}

View File

@@ -1,56 +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
/*
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

@@ -1,196 +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);
}
#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

@@ -1,39 +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
/*
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

@@ -1,73 +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
/*
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

@@ -1,762 +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;
}
#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

@@ -1,193 +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
/*
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

@@ -1,55 +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();
}
#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();
}

View File

@@ -1,57 +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
/*
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

@@ -1,97 +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;
}
#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;
}

0
cmake_android.sh Executable file → Normal file
View File

View File

@@ -1,76 +1,76 @@
cmake_minimum_required(VERSION 3.0)
project(kx_utils)
if (POLICY CMP0017)
cmake_policy(SET CMP0017 NEW)
endif()
if (NOT LIBPROJECT)
find_package(PIP REQUIRED)
endif ()
if (MINGW)
find_package(MinGW REQUIRED)
endif()
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${PIP_INCLUDES})
set(KX_PULT_NAME "kx_pult")
option(KX_PULT "Build ${KX_PULT_NAME}" 1)
option(LIB "System install" 1)
option(DEBUG "Build with -g3" 0)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -Wall")
if (DEBUG)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3")
endif()
set(CPPS_UTILS "kx_coeffs.cpp" "piprotocol.cpp")
set(HDRS_UTILS "kx_coeffs.h" "kx_protocol_x.h" "kx_protocol_c.h" "piprotocol.h")
if (DEFINED ENV{QNX_HOST})
add_library(${PROJECT_NAME} STATIC ${CPPS_UTILS})
else()
add_library(${PROJECT_NAME} SHARED ${CPPS_UTILS})
endif()
target_link_libraries(${PROJECT_NAME} ${PIP_LIBRARY})
message(STATUS "Building ${PROJECT_NAME}")
if (NOT DEFINED ENV{QNX_HOST})
if (KX_PULT)
find_package(Qt4 REQUIRED)
find_package(QAD REQUIRED)
find_package(OpenGL REQUIRED)
include_directories(${QT_INCLUDES} ${QAD_INCLUDES})
set(CPPS "kx_pult.cpp" "kx_pult.h" "kx_pult.ui" "main_kx_pult.cpp")
set(MOCS "kx_pult.h")
file(GLOB UIS "*.ui")
file(GLOB RES "*.qrc")
qt4_wrap_cpp(CMOCS ${MOCS} OPTIONS -nw)
qt4_wrap_ui(CUIS ${UIS})
qt4_add_resources(RESS ${RES})
add_executable(${KX_PULT_NAME} WIN32 ${CPPS} ${CMOCS} ${CUIS} ${RESS} ${MOCS})
set(LIBS ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${QT_QTOPENGL_LIBRARY} ${OPENGL_LIBRARIES} ${PIP_LIBRARY} qad_graphic4 qad_utils4 qad_widgets4)
target_link_libraries(${KX_PULT_NAME} ${LIBS} ${PROJECT_NAME})
endif()
endif()
if (LIB)
list(APPEND _ALL_TARGETS ${PROJECT_NAME})
set(_ALL_TARGETS ${_ALL_TARGETS} PARENT_SCOPE)
if (WIN32)
set(CMAKE_INSTALL_PREFIX ${MINGW_DIR})
install(FILES ${HDRS_UTILS} DESTINATION ${MINGW_INCLUDE})
install(TARGETS ${PROJECT_NAME} DESTINATION ${MINGW_LIB})
install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION ${MINGW_BIN})
else()
if (DEFINED ANDROID_PLATFORM)
set(CMAKE_INSTALL_PREFIX ${ANDROID_SYSTEM_LIBRARY_PATH}/usr)
else()
set(CMAKE_INSTALL_PREFIX /usr/local)
endif()
install(FILES ${HDRS_UTILS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include)
install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib)
endif()
message(STATUS "Install ${PROJECT_NAME} to system \"${CMAKE_INSTALL_PREFIX}\"")
else()
install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin)
install(TARGETS ${PROJECT_NAME} DESTINATION lib)
install(FILES ${HDRS_UTILS} DESTINATION include)
message(STATUS "Install ${PROJECT_NAME} to local \"bin\", \"lib\" and \"include\"")
endif()
if (NOT DEFINED ENV{QNX_HOST})
if (KX_PULT)
install(TARGETS ${KX_PULT_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
endif()
endif()
cmake_minimum_required(VERSION 3.0)
project(kx_utils)
if (POLICY CMP0017)
cmake_policy(SET CMP0017 NEW)
endif()
if (NOT LIBPROJECT)
find_package(PIP REQUIRED)
endif ()
if (MINGW)
find_package(MinGW REQUIRED)
endif()
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${PIP_INCLUDES})
set(KX_PULT_NAME "kx_pult")
option(KX_PULT "Build ${KX_PULT_NAME}" 1)
option(LIB "System install" 1)
option(DEBUG "Build with -g3" 0)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -Wall")
if (DEBUG)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3")
endif()
set(CPPS_UTILS "kx_coeffs.cpp" "piprotocol.cpp")
set(HDRS_UTILS "kx_coeffs.h" "kx_protocol_x.h" "kx_protocol_c.h" "piprotocol.h")
if (DEFINED ENV{QNX_HOST})
add_library(${PROJECT_NAME} STATIC ${CPPS_UTILS})
else()
add_library(${PROJECT_NAME} SHARED ${CPPS_UTILS})
endif()
target_link_libraries(${PROJECT_NAME} ${PIP_LIBRARY})
message(STATUS "Building ${PROJECT_NAME}")
if (NOT DEFINED ENV{QNX_HOST})
if (KX_PULT)
find_package(Qt4 REQUIRED)
find_package(QAD REQUIRED)
find_package(OpenGL REQUIRED)
include_directories(${QT_INCLUDES} ${QAD_INCLUDES})
set(CPPS "kx_pult.cpp" "kx_pult.h" "kx_pult.ui" "main_kx_pult.cpp")
set(MOCS "kx_pult.h")
file(GLOB UIS "*.ui")
file(GLOB RES "*.qrc")
qt4_wrap_cpp(CMOCS ${MOCS} OPTIONS -nw)
qt4_wrap_ui(CUIS ${UIS})
qt4_add_resources(RESS ${RES})
add_executable(${KX_PULT_NAME} WIN32 ${CPPS} ${CMOCS} ${CUIS} ${RESS} ${MOCS})
set(LIBS ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${QT_QTOPENGL_LIBRARY} ${OPENGL_LIBRARIES} ${PIP_LIBRARY} qad_graphic4 qad_utils4 qad_widgets4)
target_link_libraries(${KX_PULT_NAME} ${LIBS} ${PROJECT_NAME})
endif()
endif()
if (LIB)
list(APPEND _ALL_TARGETS ${PROJECT_NAME})
set(_ALL_TARGETS ${_ALL_TARGETS} PARENT_SCOPE)
if (WIN32)
set(CMAKE_INSTALL_PREFIX ${MINGW_DIR})
install(FILES ${HDRS_UTILS} DESTINATION ${MINGW_INCLUDE})
install(TARGETS ${PROJECT_NAME} DESTINATION ${MINGW_LIB})
install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION ${MINGW_BIN})
else()
if (DEFINED ANDROID_PLATFORM)
set(CMAKE_INSTALL_PREFIX ${ANDROID_SYSTEM_LIBRARY_PATH}/usr)
else()
set(CMAKE_INSTALL_PREFIX /usr/local)
endif()
install(FILES ${HDRS_UTILS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include)
install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib)
endif()
message(STATUS "Install ${PROJECT_NAME} to system \"${CMAKE_INSTALL_PREFIX}\"")
else()
install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin)
install(TARGETS ${PROJECT_NAME} DESTINATION lib)
install(FILES ${HDRS_UTILS} DESTINATION include)
message(STATUS "Install ${PROJECT_NAME} to local \"bin\", \"lib\" and \"include\"")
endif()
if (NOT DEFINED ENV{QNX_HOST})
if (KX_PULT)
install(TARGETS ${KX_PULT_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
endif()
endif()

View File

@@ -1,848 +1,848 @@
#include <QScrollBar>
#include <QMessageBox>
#include <math.h>
#include "kx_pult.h"
#include "ui_kx_pult.h"
#include "piqt.h"
#include "qpiconfig.h"
bool isNormalDouble(const double & v) {
#ifdef WINDOWS
return true;
#else
return !isnan(v) && !isinf(v);
#endif
}
XCheck::XCheck(int index): QWidget() {
index_ = index;
setProperty("index", index);
setMouseTracking(true);
check.setText(QString::number(index + 1) + " ");
check.setAutoFillBackground(true);
spin.setMaximum(KX_X_COUNT - 1);
QBoxLayout * l = new QBoxLayout(QBoxLayout::LeftToRight);
l->setMargin(0);
l->setSpacing(2);
l->addWidget(&check);
l->addWidget(&spin);
setLayout(l);
//check.installEventFilter(this);
//spin.installEventFilter(this);
connect(&spin, SIGNAL(valueChanged(int)), this, SLOT(spinChanged(int)));
connect(&check, SIGNAL(toggled(bool)), this, SLOT(checkChanged_(bool)));
}
bool XCheck::eventFilter(QObject * o, QEvent * e) {
if (e->type() == QEvent::Enter)
qApp->postEvent(this, new QEvent(e->type()));
return QWidget::eventFilter(o, e);
}
KX_Pult::KX_Pult(): QMainWindow(), config_("kx_pult.conf"), name_x("x"), name_c("c"),
config(piqt(config_), QIODevice::ReadWrite), coeffs(config_, "k", true) {
//cout << sizeof(coeffsK.k_protocol->to_k) << endl;
ui = new Ui::KX_Pult();
ui->setupUi(this);
ui->configWidget->setQPIConfig(&config);
ui->configWidget->expandAll();
ui->list->viewport()->installEventFilter(this);
ui->treeK->viewport()->installEventFilter(this);
ui->scrollArea->setAutoFillBackground(false);
ui->scrollAreaWidgetContents->setAutoFillBackground(false);
ui->widget->setAutoFillBackground(false);
ui->label_17->setFixedSize(preferredIconSize(1.25, this));
log_menu.addAction(ui->actionClear);
prot_x = 0;
prot_c = 0;
show_x = config.getValue("show_x", true);
if (!show_x)
ui->tabWidget->removeTab(1);
session.setFile("session_KX_Pult.conf");
session.addEntry(this);
session.addEntry(ui->tabWidget);
session.addEntry(ui->checkKHideEmpty);
session.addEntry(ui->checkKHideNormal);
session.addEntry(ui->checkKHideExpressions);
session.addEntry(ui->checkKAutoCalculate);
needWrite = isPause = false;
timer = 0;
//x.resize(KX_X_PACKET_NUM);
//k.resize(K_NUM);
QPalette pal = palette();
QColor col;
ui->graphic->setGraphicsCount(0);
for (int i = 0; i < KX_X_PACKET_NUM; ++i) {
XCheck * xc = new XCheck(i);
xc->installEventFilter(this);
connect(xc, SIGNAL(valueChanged(int, int)), this, SLOT(changedX(int,int)));
connect(xc, SIGNAL(checkChanged(int, bool)), this, SLOT(toggledX(int, bool)));
col = QColor::fromHsv(360 / KX_X_PACKET_NUM * i, 255, 200);
pal.setColor(QPalette::Button, col);
pal.setColor(QPalette::Window, col);
pal.setColor(QPalette::WindowText, invertColor(col));
xc->check.setPalette(pal);
ui->graphic->addGraphic(QString::number(i), col);
ui->graphic->setGraphicVisible(false, i);
checks << xc;
((QGridLayout * )(ui->widgetChecks->layout()))->addWidget(xc, (i / 10) * 2, i % 10);
QLabel * lbl = new QLabel("0"); lbl->setAlignment(Qt::AlignVCenter | Qt::AlignLeft);
values << lbl;
((QGridLayout * )(ui->widgetChecks->layout()))->addWidget(lbl, (i / 10) * 2 + 1, i % 10);
//xc->show();
}
renew();
icon_record = QIcon(":/icons/media-record.png");
icon_stop = QIcon(":/icons/media-playback-stop.png");
outdir = dir.absolutePath();
if (!dir.exists()) dir.mkdir(outdir);
outdir += "/";
ui->treeK->setColumnWidth(0, 60);
ui->treeK->setColumnWidth(1, 250);
ui->treeK->setColumnWidth(3, 100);
ui->treeK->setColumnWidth(4, 100);
//ui->table->setK(coeffsK.k()->data(), coeffsK.count());
ui->spinSize->setValue(K.size_s());
addToList(trUtf8("Read K file \"%1\": %2 coeffs, %3 bytes").arg(PI2QString(coeffs.fileName())).arg(K.size_s()).arg(coeffs.k_content.size_s()), Qt::darkMagenta);
CONNECT(void, &coeffs, sendFailed, this, pip_sendFailed);
CONNECT(void, &coeffs, sendSucceed, this, pip_sendSucceed);
CONNECT(void, &coeffs, receiveFailed, this, pip_receiveFailed);
CONNECT(void, &coeffs, receiveSucceed, this, pip_receiveSucceed);
connect(this, SIGNAL(q_k_sendFailed()), this, SLOT(k_sendFailed()), Qt::QueuedConnection);
connect(this, SIGNAL(q_k_sendSucceed()), this, SLOT(k_sendSucceed()), Qt::QueuedConnection);
connect(this, SIGNAL(q_k_receiveFailed()), this, SLOT(k_receiveFailed()), Qt::QueuedConnection);
connect(this, SIGNAL(q_k_receiveSucceed()), this, SLOT(k_receiveSucceed()), Qt::QueuedConnection);
connect(&timer_diag, SIGNAL(timeout()), this, SLOT(updateDiag()));
connect(&session, SIGNAL(loading(QPIConfig&)), this, SLOT(loading(QPIConfig&)));
connect(&session, SIGNAL(saving(QPIConfig&)), this, SLOT(saving(QPIConfig&)));
connect(ui->checkKHideEmpty, SIGNAL(toggled(bool)), this, SLOT(filterTree()));
connect(ui->checkKHideNormal, SIGNAL(toggled(bool)), this, SLOT(filterTree()));
connect(ui->checkKHideExpressions, SIGNAL(toggled(bool)), this, SLOT(filterTree()));
connect(ui->lineKSearch, SIGNAL(textChanged(QString)), this, SLOT(filterTree()));
session.load();
updateKDesc();
updateCDesc();
timer_diag.start(40);
timer_update = startTimer(25);
}
KX_Pult::~KX_Pult() {
session.save();
}
void KX_Pult::loading(QPIConfig & conf) {
kdesc_file = conf.getValue("kdesc_file").stringValue();
cdesc_file = conf.getValue("cdesc_file").stringValue();
}
void KX_Pult::saving(QPIConfig & conf) {
conf.setValue("kdesc_file", kdesc_file);
conf.setValue("cdesc_file", cdesc_file);
}
bool KX_Pult::eventFilter(QObject * o, QEvent * e) {
if (o == ui->list->viewport()) {
if (e->type() == QEvent::ContextMenu) {
clear_target = 0;
log_menu.popup(((QContextMenuEvent*)e)->globalPos());
}
return QMainWindow::eventFilter(o, e);
}
if (o == ui->treeK->viewport()) {
if (e->type() == QEvent::ContextMenu) {
clear_target = 1;
log_menu.popup(((QContextMenuEvent*)e)->globalPos());
}
return QMainWindow::eventFilter(o, e);
}
int ind = o->property("index").toInt();
//qDebug() << "event" << i << e->type();
switch (e->type()) {
case QEvent::Enter:
ui->graphic->setAutoUpdate(false);
for (int i = 0; i < KX_X_PACKET_NUM; ++i)
ui->graphic->setGraphicLineWidth(ind == i ? 3. : 1., i);
ui->graphic->setAutoUpdate(true);
ui->graphic->update();
break;
case QEvent::Leave:
ui->graphic->setAutoUpdate(false);
for (int i = 0; i < KX_X_PACKET_NUM; ++i)
ui->graphic->setGraphicLineWidth(1., i);
ui->graphic->setAutoUpdate(true);
ui->graphic->update();
break;
default: break;
}
return QMainWindow::eventFilter(o, e);
}
void KX_Pult::timerEvent(QTimerEvent * e) {
if (e->timerId() == timer_update) {
if (need_update) {
need_update = false;
ui->graphic->updateGraphics();
}
}
if (e->timerId() == timer) {
static QString sPI = QString::number(atan(1) * 4., 'f', 14).leftJustified(14);
static int cnt = 0;
int si = qMax<int>(cnt - 6, 0);
++cnt;
cnt %= 23;
ui->labelWait->setText(QString(si, QChar(' ')) + sPI.mid(cnt - 6, 6).trimmed());
if (!coeffs.isReady()) return;
//ui->table->setK(coeffsK.k()->data(), coeffsK.count());
//ui->table->showK();
}
}
void KX_Pult::setControlsEnable(bool enable) {
foreach (XCheck * i, checks)
i->setEnabled(enable);
ui->buttonShowAll->setEnabled(enable);
ui->buttonHideAll->setEnabled(enable);
}
void KX_Pult::setX(const KX_X_Data & data) {
if (!show_x) return;
//ui->graphic->lock();
for (int i = 0; i < KX_X_PACKET_NUM; ++i) {
if (!isNormalDouble(data.x_data[i])) continue;
ui->graphic->addPoint(data.x_data[i], i, false);
values[i]->setText(QString("(%1): %2").arg(data.x_num[i]).arg(data.x_data[i]));
}
//ui->graphic->unlock();
if (!isPause) {
need_update = true;
}
if (!needWrite) return;
stream << QString::number(tm.elapsed() / 1000., 'f', 3) << " " << QTime::currentTime().toString("hh:mm:ss") << " " << wcnt++;
for (int i = 0; i < KX_X_PACKET_NUM; ++i)
stream << " " << QString::number(data.x_data[i], 'f', 4);
stream << "\n";
}
void KX_Pult::addToList(const QString & s, const QColor & c) {
ui->list->addItem(QDateTime::currentDateTime().toString("dd/MM/yyyy hh:ss - ") + s);
ui->list->item(ui->list->count() - 1)->setTextColor(c);
ui->list->scrollToBottom();
}
void KX_Pult::on_buttonRecord_clicked() {
static bool isRec = false;
int cinc = 0;
QString str;
isRec = !isRec;
setControlsEnable(!isRec);
if (isRec) {
tm.restart();
file.close();
file.setFileName(outdir + getNewFileName(cinc));
while (file.exists())
file.setFileName(outdir + getNewFileName(cinc++));
file.open(QIODevice::ReadWrite);
stream.setDevice(&file);
stream << "T V C";
for (int i = 0; i < KX_X_PACKET_NUM; ++i)
stream << " X" + QString::number(checks[i]->spin.value());
stream << "\n";
wcnt = 0;
needWrite = true;
ui->buttonRecord->setText(trUtf8("Finish record"));
ui->buttonRecord->setIcon(icon_stop);
emit recordStarted(QFileInfo(file).completeBaseName());
} else {
needWrite = false;
stream.setDevice(0);
file.close();
ui->buttonRecord->setText(trUtf8("Start record"));
ui->buttonRecord->setIcon(icon_record);
emit recordStopped(QFileInfo(file).completeBaseName());
}
}
void KX_Pult::on_actionClear_triggered() {
switch (clear_target) {
case 0:
ui->list->clear();
break;
case 1:
clearSelected();
break;
default: break;
}
}
void KX_Pult::clearSelected() {
QList<QTreeWidgetItem * > si = ui->treeK->selectedItems();
ui->treeK->setUpdatesEnabled(false);
ui->treeK->blockSignals(true);
foreach (QTreeWidgetItem * i, si) {
int ki = i->text(0).toInt();
i->setText(2, "");
coeffs.setFormula(ki, "");
}
ui->treeK->blockSignals(false);
ui->treeK->setUpdatesEnabled(true);
if (ui->checkKAutoCalculate->isChecked()) {
QApplication::processEvents();
calculate();
}
}
QString KX_Pult::typeName(const QString & n) const {
if (n.isEmpty()) return "";
switch (n[0].toLatin1()) {
case 'l': return trUtf8("list"); break;
case 'b': return trUtf8("bool"); break;
case 'n': return trUtf8("int"); break;
case 'f': return trUtf8("double"); break;
case 'c': return trUtf8("color"); break;
case 'r': return trUtf8("rect"); break;
case 'a': return trUtf8("rect"); break;
case 'p': return trUtf8("point"); break;
case 'v': return trUtf8("vector"); break;
case 'i': return trUtf8("IP"); break;
case 'e': return trUtf8("enum"); break;
case 'F': return trUtf8("file"); break;
case 'D': return trUtf8("dir"); break;
}
return "";
}
void KX_Pult::received(bool ok) {
if (!ok) return;
setX(prot_x->from_x);
}
void KX_Pult::on_treeK_itemClicked(QTreeWidgetItem * item, int column) {
Qt::ItemFlags f = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
if (column == 2) f |= Qt::ItemIsEditable;
item->setFlags(f);
}
void KX_Pult::on_treeK_itemChanged(QTreeWidgetItem * item, int column) {
if (column != 2) return;
int ki = item->text(0).toInt();
coeffs.setFormula(ki, piqt(item->text(column)));
if (ui->checkKAutoCalculate->isChecked())
calculate();
}
QString KX_Pult::getNewFileName(int inc) {
dir.refresh();
dir.setNameFilters(QStringList("Experiment_*.txt"));
return "Experiment_" + QDateTime::currentDateTime().toString("dd_MM_yy__hh_mm_ss") + "__" +
QString::number(dir.entryList().count() + inc) + ".txt";
}
void KX_Pult::on_buttonSendK_clicked() {
on_buttonWrite_clicked();
coeffs.sendCoeffs();
if (timer != 0) killTimer(timer);
timer = startTimer(100);
}
void KX_Pult::on_buttonReceiveK_clicked() {
coeffs.receiveCoeffs();
if (timer != 0) killTimer(timer);
timer = startTimer(100);
}
void KX_Pult::on_buttonShowAll_clicked() {
for (int i = 0; i < KX_X_PACKET_NUM; ++i) {
checks[i]->check.setChecked(true);
//ui->graphic->setGraphicVisible(true, i);
}
}
void KX_Pult::on_buttonHideAll_clicked() {
for (int i = 0; i < KX_X_PACKET_NUM; ++i) {
checks[i]->check.setChecked(false);
//ui->graphic->setGraphicVisible(false, i);
}
}
void KX_Pult::on_buttonRead_clicked() {
coeffs.readCoeffs();
addToList(trUtf8("Read K file \"%1\": %2 coeffs, %3 bytes").arg(PI2QString(coeffs.fileName())).arg(K.size_s()).arg(coeffs.k_content.size_s()), Qt::darkMagenta);
updateTree();
}
void KX_Pult::on_buttonWrite_clicked() {
coeffs.writeCoeffs();
addToList(trUtf8("Write K file \"%1\": %2 coeffs, %3 bytes").arg(PI2QString(coeffs.fileName())).arg(K.size_s()).arg(coeffs.k_content.size_s()), Qt::darkMagenta);
}
void KX_Pult::on_buttonResize_clicked() {
K.resize(ui->spinSize->value());
coeffs.formulas.resize(ui->spinSize->value());
ui->spinSize->setStyleSheet("");
updateTree();
}
void KX_Pult::on_buttonSetKDesc_clicked() {
QString ret = QFileDialog::getOpenFileName(this, trUtf8("Select *.h file with K description"), kdesc_file, "C/C++ header files(*.h *.hpp);;All files(*)");
if (ret.isEmpty()) return;
kdesc_file = QDir::current().relativeFilePath(ret);
updateKDesc(true);
}
void KX_Pult::on_buttonSetCDesc_clicked() {
QString ret = QFileDialog::getOpenFileName(this, trUtf8("Select *.h file with C description"), cdesc_file, "C/C++ header files(*.h *.hpp);;All files(*)");
if (ret.isEmpty()) return;
cdesc_file = QDir::current().relativeFilePath(ret);
updateCDesc();
}
void KX_Pult::on_spinSize_valueChanged(int) {
ui->spinSize->setStyleSheet("");
}
void KX_Pult::k_sendFailed() {
stopWait();
addToList(trUtf8("K not sended"), Qt::darkRed);
}
void KX_Pult::k_sendSucceed() {
stopWait();
addToList(trUtf8("K sended"), Qt::darkGreen);
}
void KX_Pult::k_receiveFailed() {
stopWait();
addToList(trUtf8("K not received"), Qt::darkRed);
}
void KX_Pult::k_receiveSucceed() {
stopWait();
addToList(trUtf8("K received"), Qt::darkGreen);
addToList(trUtf8("Write K file \"%1\": %2 coeffs, %3 bytes").arg(PI2QString(coeffs.fileName())).arg(K.size_s()).arg(coeffs.k_content.size_s()), Qt::darkMagenta);
ui->spinSize->setValue(K.size_s());
updateTree();
//ui->table->setK(coeffsK.k()->data(), coeffsK.count());
}
void KX_Pult::on_spinBuffer_editingFinished() {
ui->graphic->setHistorySize(ui->spinBuffer->value());
}
void KX_Pult::stopWait() {
killTimer(timer);
timer = 0;
ui->labelWait->setText(" ");
}
void KX_Pult::updateGraph() {
ui->graphic->updateGraphics();
}
void KX_Pult::updateDiag() {
ui->labelKReceiver->setText(piqt(coeffs.k_protocol->receiverDeviceName() + " - " + coeffs.k_protocol->receiverDeviceState()));
ui->labelKSender->setText(piqt(coeffs.k_protocol->senderDeviceName()));
ui->spinKSended->setValue(coeffs.k_protocol->sendCount());
ui->spinKReceived->setValue(coeffs.k_protocol->receiveCount());
ui->spinKWrong->setValue(coeffs.k_protocol->wrongCount());
ui->spinKMissed->setValue(coeffs.k_protocol->missedCount());
ui->labelKType->setText("0x" + QString::number(coeffs.k_protocol->from_k.type, 16).toUpper().rightJustified(2, '0'));
ui->labelKAddrPult->setText("0x" + QString::number(coeffs.k_protocol->from_k.addr_to, 16).toUpper().rightJustified(2, '0'));
ui->labelKAddr->setText("0x" + QString::number(coeffs.k_protocol->to_k.addr_to, 16).toUpper().rightJustified(2, '0'));
ui->labelXReceiver->setText(piqt(prot_x->receiverDeviceName() + " - " + prot_x->receiverDeviceState()));
ui->labelXSender->setText(piqt(prot_x->senderDeviceName()));
ui->spinXSended->setValue(prot_x->sendCount());
ui->spinXReceived->setValue(prot_x->receiveCount());
ui->spinXWrong->setValue(prot_x->wrongCount());
ui->spinXMissed->setValue(prot_x->missedCount());
ui->labelXType->setText("0x" + QString::number(prot_x->from_x.type, 16).toUpper().rightJustified(2, '0'));
ui->labelXAddrPult->setText("0x" + QString::number(prot_x->from_x.addr_to, 16).toUpper().rightJustified(2, '0'));
ui->labelXAddr->setText("0x" + QString::number(prot_x->to_x.addr_to, 16).toUpper().rightJustified(2, '0'));
ui->labelCReceiver->setText(piqt(prot_c->receiverDeviceName() + " - " + prot_c->receiverDeviceState()));
ui->labelCSender->setText(piqt(prot_c->senderDeviceName()));
ui->spinCSended->setValue(prot_c->sendCount());
ui->spinCReceived->setValue(prot_c->receiveCount());
ui->spinCWrong->setValue(prot_c->wrongCount());
ui->spinCMissed->setValue(prot_c->missedCount());
ui->labelCType->setText("0x" + QString::number(prot_c->from_c.type, 16).toUpper().rightJustified(2, '0'));
ui->labelCAddrPult->setText("0x" + QString::number(prot_c->from_c.addr_to, 16).toUpper().rightJustified(2, '0'));
ui->labelCAddr->setText("0x" + QString::number(prot_c->to_c.addr_to, 16).toUpper().rightJustified(2, '0'));
}
int KX_Pult::parseHeader(const QString & file, QMap<int, KX_Pult::KDesc> & map) {
map.clear();
QFile f(file);
if (!f.open(QIODevice::ReadOnly)) {
updateTree();
addToList(trUtf8("Update descriptions from \"%1\": error").arg(file), Qt::darkRed);
return 0;
}
addToList(trUtf8("Update descriptions from \"%1\"").arg(file), Qt::darkMagenta);
QTextStream s(&f);
int cind = -1;
bool found = false;
//qDebug() << "\nparse" << file;
while (!s.atEnd()) {
QString line = s.readLine().trimmed(), num, name, type, comment;
int i = line.indexOf("//");
if (i >= 0) {
comment = line.right(line.length() - i - 2);
type = comment.left(1);
comment = comment.right(comment.length() - 1).trimmed();
line = line.left(i).trimmed();
}
if (line.isEmpty()) continue;
if (line.contains("enum")) {
found = true;
continue;
}
if (!found) continue;
if (line.contains('}'))
break;
line.remove(',').remove(' ').remove('\t');
i = line.indexOf("=");
if (i >= 0) {
num = line.right(line.length() - i - 1).trimmed();
line = line.left(i).trimmed();
}
name = line;
if (num.isEmpty())
++cind;
else
cind = Q2PIString(num).toInt();
KDesc kd;
kd.index = cind;
kd.name = name;
kd.type = type;
kd.comment = comment;
map[kd.index] = kd;
//qDebug() << name << cind << type << comment;
}
cind++;
return cind;
}
void KX_Pult::updateKDesc(bool ask_move) {
int cind = parseHeader(kdesc_file, kdesc);
if (K.size_s() < cind) {
ui->spinSize->setValue(cind);
ui->spinSize->setStyleSheet("background-color: rgb(220, 220, 255);");
}
bool move = false;
if (ask_move)
move = (QMessageBox::question(this, "KX Pult", "Save values at associated names?", QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) == QMessageBox::Yes);
updateTree(move);
}
void KX_Pult::updateCDesc() {
parseHeader(cdesc_file, cdesc);
updateCommands();
}
bool stringComp(const QString & s1, const QString & s2) {
if (s1.size() != s2.size())
return s1.size() > s2.size();
return s1 > s2;
}
void KX_Pult::updateTree(bool move) {
int sp = ui->treeK->verticalScrollBar()->value();
QApplication::setOverrideCursor(Qt::WaitCursor);
//qDebug() << "fill tree ...";
QMap<QString, QString> prev_val;
if (move) {
for (int i = 0; i < ui->treeK->topLevelItemCount(); ++i) {
QTreeWidgetItem * ti = ui->treeK->topLevelItem(i);
if (!ti->text(1).isEmpty())
prev_val[ti->text(1)] = ti->text(2);
}
}
ui->treeK->clear();
ui->treeK->setUpdatesEnabled(false);
eval.clearCustomVariables();
for (int i = 0; i < K.size_s(); ++i) {
QTreeWidgetItem * ti = new QTreeWidgetItem();
KDesc kd = kdesc[i];
QString kn = QString("k%1").arg(i);
knames[kn] = i;
knames_sort << kn;
if (eval.content.findVariable(kn) < 0)
eval.content.addVariable(kn, 0., false);
if (!kd.name.isEmpty()) {
knames[kd.name] = i;
knames_sort << kd.name;
eval.content.addVariable(kd.name, 0., false);
}
if (move && !kd.name.isEmpty()) {
if (prev_val.contains(kd.name))
coeffs.setFormula(i, Q2PIString(prev_val[kd.name]));
}
ti->setText(0, QString::number(i));
ti->setText(1, kd.name);
ti->setText(2, PI2QString(coeffs.formula(i)));
ti->setText(3, QString::number(K[i]));
ti->setText(4, typeName(kd.type));
ti->setText(5, kd.comment);
ui->treeK->addTopLevelItem(ti);
}
eval.content.sortVariables();
//qDebug() << "fill tree ok";
//qDebug() << "sort ...";
qSort(knames_sort.begin(), knames_sort.end(), stringComp);
//qDebug() << "names" << knames_sort;
//qDebug() << "sort ok";
QApplication::restoreOverrideCursor();
ui->treeK->setUpdatesEnabled(true);
ui->treeK->verticalScrollBar()->setValue(sp);
calculate();
filterTree();
}
void KX_Pult::updateCommands() {
while (ui->layoutCommands->count() > 0)
delete ui->layoutCommands->itemAt(0)->widget();
QMapIterator<int, KDesc> it(cdesc);
while (it.hasNext()) {
it.next();
KDesc kd = it.value();
QPushButton * b = new QPushButton();
QString text = kd.name;
if (!kd.comment.isEmpty())
text += QString("\n(%1)").arg(kd.comment);
b->setText(text);
b->setProperty("_command", kd.index);
connect(b, SIGNAL(clicked()), this, SLOT(commandClicked()));
ui->layoutCommands->addWidget(b);
}
}
void KX_Pult::filterTree() {
bool he = ui->checkKHideEmpty->isChecked();
bool hn = ui->checkKHideNormal->isChecked();
bool hs = ui->checkKHideExpressions->isChecked();
bool ok = false;
QString fl = ui->lineKSearch->text();
int lc = ui->treeK->topLevelItemCount();
for (int i = 0; i < lc; ++i) {
QTreeWidgetItem * ti = ui->treeK->topLevelItem(i);
if (ti->text(1).isEmpty() && he)
ti->setHidden(true);
else
if (fl.isEmpty())
ti->setHidden(false);
else
ti->setHidden(!ti->text(0).contains(fl, Qt::CaseInsensitive) &&
!ti->text(1).contains(fl, Qt::CaseInsensitive) &&
!ti->text(2).contains(fl, Qt::CaseInsensitive) &&
!ti->text(3).contains(fl, Qt::CaseInsensitive) &&
!ti->text(4).contains(fl, Qt::CaseInsensitive));
if (hn)
if (ti->data(0, Qt::UserRole).toBool())
ti->setHidden(true);
if (hs) {
ti->data(2, Qt::DisplayRole).toDouble(&ok);
if (!ok)
ti->setHidden(true);
}
}
}
void KX_Pult::calculate() {
calculated.clear();
ui->treeK->setUpdatesEnabled(false);
ui->treeK->blockSignals(true);
QApplication::setOverrideCursor(Qt::WaitCursor);
progress(0, 100);
ui->buttonCalculate->setEnabled(false);
QApplication::processEvents();
for (int i = 0; i < K.size_s(); ++i) {
ui->treeK->topLevelItem(i)->setToolTip(2, QString());
ui->treeK->topLevelItem(i)->setToolTip(3, QString());
}
for (int i = 0; i < K.size_s(); ++i) {
progress(i, K.size_s());
calculateExpression(i, QVector<int>());
}
ui->buttonCalculate->setEnabled(true);
ui->progress->setValue(100);
QApplication::restoreOverrideCursor();
ui->treeK->blockSignals(false);
ui->treeK->setUpdatesEnabled(true);
}
bool KX_Pult::calculateExpression(int i, QVector<int> trace) {
if (calculated.contains(i)) return true;
trace << i;
QTreeWidgetItem * ti = ui->treeK->topLevelItem(i);
QString expr = ti->text(2);
if (expr.isEmpty() || expr == "0" || expr == "0,00000000" || expr == "0.00000000") {
markNormal(ti);
calculated << i;
K[i] = 0.;
ti->setText(3, "0");
return true;
}
//ti->setToolTip(2, QString());
if (!eval.check(expr)) {
markError(ti, eval.error());
return false;
}
foreach (const QString & n, knames_sort) {
if (expr.contains(n)) {
int ki = knames.value(n, -1);
if (trace.contains(ki)) {
QString strace;
trace << ki;
for (int j = 0; j < trace.size(); ++j) {
//calculated << trace[j];
if (j > 0) strace += " -> ";
strace += "k" + QString::number(trace[j]);
}
for (int j = 0; j < trace.size(); ++j) {
QTreeWidgetItem * pti = ui->treeK->topLevelItem(trace[j]);
markError(pti, QString("Circular dependency: %1!").arg(strace));
}
return false;
}
if (ki < 0) {
markError(ti);
return false;
}
if (calculated.contains(ki)) {
eval.setVariable(n, K[ki]);
} else {
if (calculateExpression(ki, trace))
eval.setVariable(n, K[ki]);
else {
markError(ti);
return false;
}
}
}
}
markNormal(ti);
calculated << i;
complexd ret = eval.evaluate();
K[i] = ret.real();
ti->setText(3, QString::number(K[i]));
return true;
}
void KX_Pult::markError(QTreeWidgetItem * item, const QString & tool_tip) {
int cc = item->columnCount();
for (int i = 0; i < cc; ++i)
item->setBackgroundColor(i, QColor(255, 200, 200));
if (item->toolTip(2).isEmpty())
item->setToolTip(2, tool_tip);
if (item->toolTip(3).isEmpty())
item->setToolTip(3, tool_tip);
item->setData(0, Qt::UserRole, false);
item->setText(3, "Error");
}
void KX_Pult::markNormal(QTreeWidgetItem * item) {
int cc = item->columnCount();
for (int i = 0; i < cc; ++i)
item->setBackground(i, Qt::NoBrush);
item->setToolTip(2, QString());
item->setToolTip(3, QString());
item->setData(0, Qt::UserRole, true);
}
void KX_Pult::progress(int val, int max) {
if (ctm.elapsed() < 50) return;
ctm.restart();
ui->progress->setValue(qRound(val * 100. / max));
QApplication::processEvents();
}
void KX_Pult::renew(bool write) {
addToList(trUtf8("Update settings from \"%1\"").arg(PI2QString(config_)), Qt::darkMagenta);
dir.setPath(config.getValue("x.output_dir", "./Experiments/").stringValue());
setWindowTitle(config.getValue("title", "Noname").stringValue() + trUtf8(" - KX Pult"));
//if (write) ui->configWidget->write();
if (prot_x != 0) {
prot_x->stop();
delete prot_x;
}
if (prot_c != 0) {
prot_c->stop();
delete prot_c;
}
prot_x = new __KX_Protocol_X(config_, name_x);
prot_c = new __KX_Protocol_C(config_, name_c);
ui->graphic->setAutoXIncrement(prot_x->expectedFrequency() > 0. ? 1. / prot_x->expectedFrequency() : 1.);
coeffs.renew();
CONNECT1(void, bool, prot_x, received, this, received);
}
void KX_Pult::toggledX(int index, bool on) {
ui->graphic->setGraphicVisible(on, index);
}
void KX_Pult::changedX(int index, int num) {
prot_x->to_x.x_num[index] = num;
}
void KX_Pult::commandClicked() {
QPushButton * b = qobject_cast<QPushButton*>(sender());
if (!b) return;
prot_c->sendCommand(b->property("_command").toInt());
}
#include <QScrollBar>
#include <QMessageBox>
#include <math.h>
#include "kx_pult.h"
#include "ui_kx_pult.h"
#include "piqt.h"
#include "qpiconfig.h"
bool isNormalDouble(const double & v) {
#ifdef WINDOWS
return true;
#else
return !isnan(v) && !isinf(v);
#endif
}
XCheck::XCheck(int index): QWidget() {
index_ = index;
setProperty("index", index);
setMouseTracking(true);
check.setText(QString::number(index + 1) + " ");
check.setAutoFillBackground(true);
spin.setMaximum(KX_X_COUNT - 1);
QBoxLayout * l = new QBoxLayout(QBoxLayout::LeftToRight);
l->setMargin(0);
l->setSpacing(2);
l->addWidget(&check);
l->addWidget(&spin);
setLayout(l);
//check.installEventFilter(this);
//spin.installEventFilter(this);
connect(&spin, SIGNAL(valueChanged(int)), this, SLOT(spinChanged(int)));
connect(&check, SIGNAL(toggled(bool)), this, SLOT(checkChanged_(bool)));
}
bool XCheck::eventFilter(QObject * o, QEvent * e) {
if (e->type() == QEvent::Enter)
qApp->postEvent(this, new QEvent(e->type()));
return QWidget::eventFilter(o, e);
}
KX_Pult::KX_Pult(): QMainWindow(), config_("kx_pult.conf"), name_x("x"), name_c("c"),
config(piqt(config_), QIODevice::ReadWrite), coeffs(config_, "k", true) {
//cout << sizeof(coeffsK.k_protocol->to_k) << endl;
ui = new Ui::KX_Pult();
ui->setupUi(this);
ui->configWidget->setQPIConfig(&config);
ui->configWidget->expandAll();
ui->list->viewport()->installEventFilter(this);
ui->treeK->viewport()->installEventFilter(this);
ui->scrollArea->setAutoFillBackground(false);
ui->scrollAreaWidgetContents->setAutoFillBackground(false);
ui->widget->setAutoFillBackground(false);
ui->label_17->setFixedSize(preferredIconSize(1.25, this));
log_menu.addAction(ui->actionClear);
prot_x = 0;
prot_c = 0;
show_x = config.getValue("show_x", true);
if (!show_x)
ui->tabWidget->removeTab(1);
session.setFile("session_KX_Pult.conf");
session.addEntry(this);
session.addEntry(ui->tabWidget);
session.addEntry(ui->checkKHideEmpty);
session.addEntry(ui->checkKHideNormal);
session.addEntry(ui->checkKHideExpressions);
session.addEntry(ui->checkKAutoCalculate);
needWrite = isPause = false;
timer = 0;
//x.resize(KX_X_PACKET_NUM);
//k.resize(K_NUM);
QPalette pal = palette();
QColor col;
ui->graphic->setGraphicsCount(0);
for (int i = 0; i < KX_X_PACKET_NUM; ++i) {
XCheck * xc = new XCheck(i);
xc->installEventFilter(this);
connect(xc, SIGNAL(valueChanged(int, int)), this, SLOT(changedX(int,int)));
connect(xc, SIGNAL(checkChanged(int, bool)), this, SLOT(toggledX(int, bool)));
col = QColor::fromHsv(360 / KX_X_PACKET_NUM * i, 255, 200);
pal.setColor(QPalette::Button, col);
pal.setColor(QPalette::Window, col);
pal.setColor(QPalette::WindowText, invertColor(col));
xc->check.setPalette(pal);
ui->graphic->addGraphic(QString::number(i), col);
ui->graphic->setGraphicVisible(false, i);
checks << xc;
((QGridLayout * )(ui->widgetChecks->layout()))->addWidget(xc, (i / 10) * 2, i % 10);
QLabel * lbl = new QLabel("0"); lbl->setAlignment(Qt::AlignVCenter | Qt::AlignLeft);
values << lbl;
((QGridLayout * )(ui->widgetChecks->layout()))->addWidget(lbl, (i / 10) * 2 + 1, i % 10);
//xc->show();
}
renew();
icon_record = QIcon(":/icons/media-record.png");
icon_stop = QIcon(":/icons/media-playback-stop.png");
outdir = dir.absolutePath();
if (!dir.exists()) dir.mkdir(outdir);
outdir += "/";
ui->treeK->setColumnWidth(0, 60);
ui->treeK->setColumnWidth(1, 250);
ui->treeK->setColumnWidth(3, 100);
ui->treeK->setColumnWidth(4, 100);
//ui->table->setK(coeffsK.k()->data(), coeffsK.count());
ui->spinSize->setValue(K.size_s());
addToList(trUtf8("Read K file \"%1\": %2 coeffs, %3 bytes").arg(PI2QString(coeffs.fileName())).arg(K.size_s()).arg(coeffs.k_content.size_s()), Qt::darkMagenta);
CONNECT(void, &coeffs, sendFailed, this, pip_sendFailed);
CONNECT(void, &coeffs, sendSucceed, this, pip_sendSucceed);
CONNECT(void, &coeffs, receiveFailed, this, pip_receiveFailed);
CONNECT(void, &coeffs, receiveSucceed, this, pip_receiveSucceed);
connect(this, SIGNAL(q_k_sendFailed()), this, SLOT(k_sendFailed()), Qt::QueuedConnection);
connect(this, SIGNAL(q_k_sendSucceed()), this, SLOT(k_sendSucceed()), Qt::QueuedConnection);
connect(this, SIGNAL(q_k_receiveFailed()), this, SLOT(k_receiveFailed()), Qt::QueuedConnection);
connect(this, SIGNAL(q_k_receiveSucceed()), this, SLOT(k_receiveSucceed()), Qt::QueuedConnection);
connect(&timer_diag, SIGNAL(timeout()), this, SLOT(updateDiag()));
connect(&session, SIGNAL(loading(QPIConfig&)), this, SLOT(loading(QPIConfig&)));
connect(&session, SIGNAL(saving(QPIConfig&)), this, SLOT(saving(QPIConfig&)));
connect(ui->checkKHideEmpty, SIGNAL(toggled(bool)), this, SLOT(filterTree()));
connect(ui->checkKHideNormal, SIGNAL(toggled(bool)), this, SLOT(filterTree()));
connect(ui->checkKHideExpressions, SIGNAL(toggled(bool)), this, SLOT(filterTree()));
connect(ui->lineKSearch, SIGNAL(textChanged(QString)), this, SLOT(filterTree()));
session.load();
updateKDesc();
updateCDesc();
timer_diag.start(40);
timer_update = startTimer(25);
}
KX_Pult::~KX_Pult() {
session.save();
}
void KX_Pult::loading(QPIConfig & conf) {
kdesc_file = conf.getValue("kdesc_file").stringValue();
cdesc_file = conf.getValue("cdesc_file").stringValue();
}
void KX_Pult::saving(QPIConfig & conf) {
conf.setValue("kdesc_file", kdesc_file);
conf.setValue("cdesc_file", cdesc_file);
}
bool KX_Pult::eventFilter(QObject * o, QEvent * e) {
if (o == ui->list->viewport()) {
if (e->type() == QEvent::ContextMenu) {
clear_target = 0;
log_menu.popup(((QContextMenuEvent*)e)->globalPos());
}
return QMainWindow::eventFilter(o, e);
}
if (o == ui->treeK->viewport()) {
if (e->type() == QEvent::ContextMenu) {
clear_target = 1;
log_menu.popup(((QContextMenuEvent*)e)->globalPos());
}
return QMainWindow::eventFilter(o, e);
}
int ind = o->property("index").toInt();
//qDebug() << "event" << i << e->type();
switch (e->type()) {
case QEvent::Enter:
ui->graphic->setAutoUpdate(false);
for (int i = 0; i < KX_X_PACKET_NUM; ++i)
ui->graphic->setGraphicLineWidth(ind == i ? 3. : 1., i);
ui->graphic->setAutoUpdate(true);
ui->graphic->update();
break;
case QEvent::Leave:
ui->graphic->setAutoUpdate(false);
for (int i = 0; i < KX_X_PACKET_NUM; ++i)
ui->graphic->setGraphicLineWidth(1., i);
ui->graphic->setAutoUpdate(true);
ui->graphic->update();
break;
default: break;
}
return QMainWindow::eventFilter(o, e);
}
void KX_Pult::timerEvent(QTimerEvent * e) {
if (e->timerId() == timer_update) {
if (need_update) {
need_update = false;
ui->graphic->updateGraphics();
}
}
if (e->timerId() == timer) {
static QString sPI = QString::number(atan(1) * 4., 'f', 14).leftJustified(14);
static int cnt = 0;
int si = qMax<int>(cnt - 6, 0);
++cnt;
cnt %= 23;
ui->labelWait->setText(QString(si, QChar(' ')) + sPI.mid(cnt - 6, 6).trimmed());
if (!coeffs.isReady()) return;
//ui->table->setK(coeffsK.k()->data(), coeffsK.count());
//ui->table->showK();
}
}
void KX_Pult::setControlsEnable(bool enable) {
foreach (XCheck * i, checks)
i->setEnabled(enable);
ui->buttonShowAll->setEnabled(enable);
ui->buttonHideAll->setEnabled(enable);
}
void KX_Pult::setX(const KX_X_Data & data) {
if (!show_x) return;
//ui->graphic->lock();
for (int i = 0; i < KX_X_PACKET_NUM; ++i) {
if (!isNormalDouble(data.x_data[i])) continue;
ui->graphic->addPoint(data.x_data[i], i, false);
values[i]->setText(QString("(%1): %2").arg(data.x_num[i]).arg(data.x_data[i]));
}
//ui->graphic->unlock();
if (!isPause) {
need_update = true;
}
if (!needWrite) return;
stream << QString::number(tm.elapsed() / 1000., 'f', 3) << " " << QTime::currentTime().toString("hh:mm:ss") << " " << wcnt++;
for (int i = 0; i < KX_X_PACKET_NUM; ++i)
stream << " " << QString::number(data.x_data[i], 'f', 4);
stream << "\n";
}
void KX_Pult::addToList(const QString & s, const QColor & c) {
ui->list->addItem(QDateTime::currentDateTime().toString("dd/MM/yyyy hh:ss - ") + s);
ui->list->item(ui->list->count() - 1)->setTextColor(c);
ui->list->scrollToBottom();
}
void KX_Pult::on_buttonRecord_clicked() {
static bool isRec = false;
int cinc = 0;
QString str;
isRec = !isRec;
setControlsEnable(!isRec);
if (isRec) {
tm.restart();
file.close();
file.setFileName(outdir + getNewFileName(cinc));
while (file.exists())
file.setFileName(outdir + getNewFileName(cinc++));
file.open(QIODevice::ReadWrite);
stream.setDevice(&file);
stream << "T V C";
for (int i = 0; i < KX_X_PACKET_NUM; ++i)
stream << " X" + QString::number(checks[i]->spin.value());
stream << "\n";
wcnt = 0;
needWrite = true;
ui->buttonRecord->setText(trUtf8("Finish record"));
ui->buttonRecord->setIcon(icon_stop);
emit recordStarted(QFileInfo(file).completeBaseName());
} else {
needWrite = false;
stream.setDevice(0);
file.close();
ui->buttonRecord->setText(trUtf8("Start record"));
ui->buttonRecord->setIcon(icon_record);
emit recordStopped(QFileInfo(file).completeBaseName());
}
}
void KX_Pult::on_actionClear_triggered() {
switch (clear_target) {
case 0:
ui->list->clear();
break;
case 1:
clearSelected();
break;
default: break;
}
}
void KX_Pult::clearSelected() {
QList<QTreeWidgetItem * > si = ui->treeK->selectedItems();
ui->treeK->setUpdatesEnabled(false);
ui->treeK->blockSignals(true);
foreach (QTreeWidgetItem * i, si) {
int ki = i->text(0).toInt();
i->setText(2, "");
coeffs.setFormula(ki, "");
}
ui->treeK->blockSignals(false);
ui->treeK->setUpdatesEnabled(true);
if (ui->checkKAutoCalculate->isChecked()) {
QApplication::processEvents();
calculate();
}
}
QString KX_Pult::typeName(const QString & n) const {
if (n.isEmpty()) return "";
switch (n[0].toLatin1()) {
case 'l': return trUtf8("list"); break;
case 'b': return trUtf8("bool"); break;
case 'n': return trUtf8("int"); break;
case 'f': return trUtf8("double"); break;
case 'c': return trUtf8("color"); break;
case 'r': return trUtf8("rect"); break;
case 'a': return trUtf8("rect"); break;
case 'p': return trUtf8("point"); break;
case 'v': return trUtf8("vector"); break;
case 'i': return trUtf8("IP"); break;
case 'e': return trUtf8("enum"); break;
case 'F': return trUtf8("file"); break;
case 'D': return trUtf8("dir"); break;
}
return "";
}
void KX_Pult::received(bool ok) {
if (!ok) return;
setX(prot_x->from_x);
}
void KX_Pult::on_treeK_itemClicked(QTreeWidgetItem * item, int column) {
Qt::ItemFlags f = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
if (column == 2) f |= Qt::ItemIsEditable;
item->setFlags(f);
}
void KX_Pult::on_treeK_itemChanged(QTreeWidgetItem * item, int column) {
if (column != 2) return;
int ki = item->text(0).toInt();
coeffs.setFormula(ki, piqt(item->text(column)));
if (ui->checkKAutoCalculate->isChecked())
calculate();
}
QString KX_Pult::getNewFileName(int inc) {
dir.refresh();
dir.setNameFilters(QStringList("Experiment_*.txt"));
return "Experiment_" + QDateTime::currentDateTime().toString("dd_MM_yy__hh_mm_ss") + "__" +
QString::number(dir.entryList().count() + inc) + ".txt";
}
void KX_Pult::on_buttonSendK_clicked() {
on_buttonWrite_clicked();
coeffs.sendCoeffs();
if (timer != 0) killTimer(timer);
timer = startTimer(100);
}
void KX_Pult::on_buttonReceiveK_clicked() {
coeffs.receiveCoeffs();
if (timer != 0) killTimer(timer);
timer = startTimer(100);
}
void KX_Pult::on_buttonShowAll_clicked() {
for (int i = 0; i < KX_X_PACKET_NUM; ++i) {
checks[i]->check.setChecked(true);
//ui->graphic->setGraphicVisible(true, i);
}
}
void KX_Pult::on_buttonHideAll_clicked() {
for (int i = 0; i < KX_X_PACKET_NUM; ++i) {
checks[i]->check.setChecked(false);
//ui->graphic->setGraphicVisible(false, i);
}
}
void KX_Pult::on_buttonRead_clicked() {
coeffs.readCoeffs();
addToList(trUtf8("Read K file \"%1\": %2 coeffs, %3 bytes").arg(PI2QString(coeffs.fileName())).arg(K.size_s()).arg(coeffs.k_content.size_s()), Qt::darkMagenta);
updateTree();
}
void KX_Pult::on_buttonWrite_clicked() {
coeffs.writeCoeffs();
addToList(trUtf8("Write K file \"%1\": %2 coeffs, %3 bytes").arg(PI2QString(coeffs.fileName())).arg(K.size_s()).arg(coeffs.k_content.size_s()), Qt::darkMagenta);
}
void KX_Pult::on_buttonResize_clicked() {
K.resize(ui->spinSize->value());
coeffs.formulas.resize(ui->spinSize->value());
ui->spinSize->setStyleSheet("");
updateTree();
}
void KX_Pult::on_buttonSetKDesc_clicked() {
QString ret = QFileDialog::getOpenFileName(this, trUtf8("Select *.h file with K description"), kdesc_file, "C/C++ header files(*.h *.hpp);;All files(*)");
if (ret.isEmpty()) return;
kdesc_file = QDir::current().relativeFilePath(ret);
updateKDesc(true);
}
void KX_Pult::on_buttonSetCDesc_clicked() {
QString ret = QFileDialog::getOpenFileName(this, trUtf8("Select *.h file with C description"), cdesc_file, "C/C++ header files(*.h *.hpp);;All files(*)");
if (ret.isEmpty()) return;
cdesc_file = QDir::current().relativeFilePath(ret);
updateCDesc();
}
void KX_Pult::on_spinSize_valueChanged(int) {
ui->spinSize->setStyleSheet("");
}
void KX_Pult::k_sendFailed() {
stopWait();
addToList(trUtf8("K not sended"), Qt::darkRed);
}
void KX_Pult::k_sendSucceed() {
stopWait();
addToList(trUtf8("K sended"), Qt::darkGreen);
}
void KX_Pult::k_receiveFailed() {
stopWait();
addToList(trUtf8("K not received"), Qt::darkRed);
}
void KX_Pult::k_receiveSucceed() {
stopWait();
addToList(trUtf8("K received"), Qt::darkGreen);
addToList(trUtf8("Write K file \"%1\": %2 coeffs, %3 bytes").arg(PI2QString(coeffs.fileName())).arg(K.size_s()).arg(coeffs.k_content.size_s()), Qt::darkMagenta);
ui->spinSize->setValue(K.size_s());
updateTree();
//ui->table->setK(coeffsK.k()->data(), coeffsK.count());
}
void KX_Pult::on_spinBuffer_editingFinished() {
ui->graphic->setHistorySize(ui->spinBuffer->value());
}
void KX_Pult::stopWait() {
killTimer(timer);
timer = 0;
ui->labelWait->setText(" ");
}
void KX_Pult::updateGraph() {
ui->graphic->updateGraphics();
}
void KX_Pult::updateDiag() {
ui->labelKReceiver->setText(piqt(coeffs.k_protocol->receiverDeviceName() + " - " + coeffs.k_protocol->receiverDeviceState()));
ui->labelKSender->setText(piqt(coeffs.k_protocol->senderDeviceName()));
ui->spinKSended->setValue(coeffs.k_protocol->sendCount());
ui->spinKReceived->setValue(coeffs.k_protocol->receiveCount());
ui->spinKWrong->setValue(coeffs.k_protocol->wrongCount());
ui->spinKMissed->setValue(coeffs.k_protocol->missedCount());
ui->labelKType->setText("0x" + QString::number(coeffs.k_protocol->from_k.type, 16).toUpper().rightJustified(2, '0'));
ui->labelKAddrPult->setText("0x" + QString::number(coeffs.k_protocol->from_k.addr_to, 16).toUpper().rightJustified(2, '0'));
ui->labelKAddr->setText("0x" + QString::number(coeffs.k_protocol->to_k.addr_to, 16).toUpper().rightJustified(2, '0'));
ui->labelXReceiver->setText(piqt(prot_x->receiverDeviceName() + " - " + prot_x->receiverDeviceState()));
ui->labelXSender->setText(piqt(prot_x->senderDeviceName()));
ui->spinXSended->setValue(prot_x->sendCount());
ui->spinXReceived->setValue(prot_x->receiveCount());
ui->spinXWrong->setValue(prot_x->wrongCount());
ui->spinXMissed->setValue(prot_x->missedCount());
ui->labelXType->setText("0x" + QString::number(prot_x->from_x.type, 16).toUpper().rightJustified(2, '0'));
ui->labelXAddrPult->setText("0x" + QString::number(prot_x->from_x.addr_to, 16).toUpper().rightJustified(2, '0'));
ui->labelXAddr->setText("0x" + QString::number(prot_x->to_x.addr_to, 16).toUpper().rightJustified(2, '0'));
ui->labelCReceiver->setText(piqt(prot_c->receiverDeviceName() + " - " + prot_c->receiverDeviceState()));
ui->labelCSender->setText(piqt(prot_c->senderDeviceName()));
ui->spinCSended->setValue(prot_c->sendCount());
ui->spinCReceived->setValue(prot_c->receiveCount());
ui->spinCWrong->setValue(prot_c->wrongCount());
ui->spinCMissed->setValue(prot_c->missedCount());
ui->labelCType->setText("0x" + QString::number(prot_c->from_c.type, 16).toUpper().rightJustified(2, '0'));
ui->labelCAddrPult->setText("0x" + QString::number(prot_c->from_c.addr_to, 16).toUpper().rightJustified(2, '0'));
ui->labelCAddr->setText("0x" + QString::number(prot_c->to_c.addr_to, 16).toUpper().rightJustified(2, '0'));
}
int KX_Pult::parseHeader(const QString & file, QMap<int, KX_Pult::KDesc> & map) {
map.clear();
QFile f(file);
if (!f.open(QIODevice::ReadOnly)) {
updateTree();
addToList(trUtf8("Update descriptions from \"%1\": error").arg(file), Qt::darkRed);
return 0;
}
addToList(trUtf8("Update descriptions from \"%1\"").arg(file), Qt::darkMagenta);
QTextStream s(&f);
int cind = -1;
bool found = false;
//qDebug() << "\nparse" << file;
while (!s.atEnd()) {
QString line = s.readLine().trimmed(), num, name, type, comment;
int i = line.indexOf("//");
if (i >= 0) {
comment = line.right(line.length() - i - 2);
type = comment.left(1);
comment = comment.right(comment.length() - 1).trimmed();
line = line.left(i).trimmed();
}
if (line.isEmpty()) continue;
if (line.contains("enum")) {
found = true;
continue;
}
if (!found) continue;
if (line.contains('}'))
break;
line.remove(',').remove(' ').remove('\t');
i = line.indexOf("=");
if (i >= 0) {
num = line.right(line.length() - i - 1).trimmed();
line = line.left(i).trimmed();
}
name = line;
if (num.isEmpty())
++cind;
else
cind = Q2PIString(num).toInt();
KDesc kd;
kd.index = cind;
kd.name = name;
kd.type = type;
kd.comment = comment;
map[kd.index] = kd;
//qDebug() << name << cind << type << comment;
}
cind++;
return cind;
}
void KX_Pult::updateKDesc(bool ask_move) {
int cind = parseHeader(kdesc_file, kdesc);
if (K.size_s() < cind) {
ui->spinSize->setValue(cind);
ui->spinSize->setStyleSheet("background-color: rgb(220, 220, 255);");
}
bool move = false;
if (ask_move)
move = (QMessageBox::question(this, "KX Pult", "Save values at associated names?", QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) == QMessageBox::Yes);
updateTree(move);
}
void KX_Pult::updateCDesc() {
parseHeader(cdesc_file, cdesc);
updateCommands();
}
bool stringComp(const QString & s1, const QString & s2) {
if (s1.size() != s2.size())
return s1.size() > s2.size();
return s1 > s2;
}
void KX_Pult::updateTree(bool move) {
int sp = ui->treeK->verticalScrollBar()->value();
QApplication::setOverrideCursor(Qt::WaitCursor);
//qDebug() << "fill tree ...";
QMap<QString, QString> prev_val;
if (move) {
for (int i = 0; i < ui->treeK->topLevelItemCount(); ++i) {
QTreeWidgetItem * ti = ui->treeK->topLevelItem(i);
if (!ti->text(1).isEmpty())
prev_val[ti->text(1)] = ti->text(2);
}
}
ui->treeK->clear();
ui->treeK->setUpdatesEnabled(false);
eval.clearCustomVariables();
for (int i = 0; i < K.size_s(); ++i) {
QTreeWidgetItem * ti = new QTreeWidgetItem();
KDesc kd = kdesc[i];
QString kn = QString("k%1").arg(i);
knames[kn] = i;
knames_sort << kn;
if (eval.content.findVariable(kn) < 0)
eval.content.addVariable(kn, 0., false);
if (!kd.name.isEmpty()) {
knames[kd.name] = i;
knames_sort << kd.name;
eval.content.addVariable(kd.name, 0., false);
}
if (move && !kd.name.isEmpty()) {
if (prev_val.contains(kd.name))
coeffs.setFormula(i, Q2PIString(prev_val[kd.name]));
}
ti->setText(0, QString::number(i));
ti->setText(1, kd.name);
ti->setText(2, PI2QString(coeffs.formula(i)));
ti->setText(3, QString::number(K[i]));
ti->setText(4, typeName(kd.type));
ti->setText(5, kd.comment);
ui->treeK->addTopLevelItem(ti);
}
eval.content.sortVariables();
//qDebug() << "fill tree ok";
//qDebug() << "sort ...";
qSort(knames_sort.begin(), knames_sort.end(), stringComp);
//qDebug() << "names" << knames_sort;
//qDebug() << "sort ok";
QApplication::restoreOverrideCursor();
ui->treeK->setUpdatesEnabled(true);
ui->treeK->verticalScrollBar()->setValue(sp);
calculate();
filterTree();
}
void KX_Pult::updateCommands() {
while (ui->layoutCommands->count() > 0)
delete ui->layoutCommands->itemAt(0)->widget();
QMapIterator<int, KDesc> it(cdesc);
while (it.hasNext()) {
it.next();
KDesc kd = it.value();
QPushButton * b = new QPushButton();
QString text = kd.name;
if (!kd.comment.isEmpty())
text += QString("\n(%1)").arg(kd.comment);
b->setText(text);
b->setProperty("_command", kd.index);
connect(b, SIGNAL(clicked()), this, SLOT(commandClicked()));
ui->layoutCommands->addWidget(b);
}
}
void KX_Pult::filterTree() {
bool he = ui->checkKHideEmpty->isChecked();
bool hn = ui->checkKHideNormal->isChecked();
bool hs = ui->checkKHideExpressions->isChecked();
bool ok = false;
QString fl = ui->lineKSearch->text();
int lc = ui->treeK->topLevelItemCount();
for (int i = 0; i < lc; ++i) {
QTreeWidgetItem * ti = ui->treeK->topLevelItem(i);
if (ti->text(1).isEmpty() && he)
ti->setHidden(true);
else
if (fl.isEmpty())
ti->setHidden(false);
else
ti->setHidden(!ti->text(0).contains(fl, Qt::CaseInsensitive) &&
!ti->text(1).contains(fl, Qt::CaseInsensitive) &&
!ti->text(2).contains(fl, Qt::CaseInsensitive) &&
!ti->text(3).contains(fl, Qt::CaseInsensitive) &&
!ti->text(4).contains(fl, Qt::CaseInsensitive));
if (hn)
if (ti->data(0, Qt::UserRole).toBool())
ti->setHidden(true);
if (hs) {
ti->data(2, Qt::DisplayRole).toDouble(&ok);
if (!ok)
ti->setHidden(true);
}
}
}
void KX_Pult::calculate() {
calculated.clear();
ui->treeK->setUpdatesEnabled(false);
ui->treeK->blockSignals(true);
QApplication::setOverrideCursor(Qt::WaitCursor);
progress(0, 100);
ui->buttonCalculate->setEnabled(false);
QApplication::processEvents();
for (int i = 0; i < K.size_s(); ++i) {
ui->treeK->topLevelItem(i)->setToolTip(2, QString());
ui->treeK->topLevelItem(i)->setToolTip(3, QString());
}
for (int i = 0; i < K.size_s(); ++i) {
progress(i, K.size_s());
calculateExpression(i, QVector<int>());
}
ui->buttonCalculate->setEnabled(true);
ui->progress->setValue(100);
QApplication::restoreOverrideCursor();
ui->treeK->blockSignals(false);
ui->treeK->setUpdatesEnabled(true);
}
bool KX_Pult::calculateExpression(int i, QVector<int> trace) {
if (calculated.contains(i)) return true;
trace << i;
QTreeWidgetItem * ti = ui->treeK->topLevelItem(i);
QString expr = ti->text(2);
if (expr.isEmpty() || expr == "0" || expr == "0,00000000" || expr == "0.00000000") {
markNormal(ti);
calculated << i;
K[i] = 0.;
ti->setText(3, "0");
return true;
}
//ti->setToolTip(2, QString());
if (!eval.check(expr)) {
markError(ti, eval.error());
return false;
}
foreach (const QString & n, knames_sort) {
if (expr.contains(n)) {
int ki = knames.value(n, -1);
if (trace.contains(ki)) {
QString strace;
trace << ki;
for (int j = 0; j < trace.size(); ++j) {
//calculated << trace[j];
if (j > 0) strace += " -> ";
strace += "k" + QString::number(trace[j]);
}
for (int j = 0; j < trace.size(); ++j) {
QTreeWidgetItem * pti = ui->treeK->topLevelItem(trace[j]);
markError(pti, QString("Circular dependency: %1!").arg(strace));
}
return false;
}
if (ki < 0) {
markError(ti);
return false;
}
if (calculated.contains(ki)) {
eval.setVariable(n, K[ki]);
} else {
if (calculateExpression(ki, trace))
eval.setVariable(n, K[ki]);
else {
markError(ti);
return false;
}
}
}
}
markNormal(ti);
calculated << i;
complexd ret = eval.evaluate();
K[i] = ret.real();
ti->setText(3, QString::number(K[i]));
return true;
}
void KX_Pult::markError(QTreeWidgetItem * item, const QString & tool_tip) {
int cc = item->columnCount();
for (int i = 0; i < cc; ++i)
item->setBackgroundColor(i, QColor(255, 200, 200));
if (item->toolTip(2).isEmpty())
item->setToolTip(2, tool_tip);
if (item->toolTip(3).isEmpty())
item->setToolTip(3, tool_tip);
item->setData(0, Qt::UserRole, false);
item->setText(3, "Error");
}
void KX_Pult::markNormal(QTreeWidgetItem * item) {
int cc = item->columnCount();
for (int i = 0; i < cc; ++i)
item->setBackground(i, Qt::NoBrush);
item->setToolTip(2, QString());
item->setToolTip(3, QString());
item->setData(0, Qt::UserRole, true);
}
void KX_Pult::progress(int val, int max) {
if (ctm.elapsed() < 50) return;
ctm.restart();
ui->progress->setValue(qRound(val * 100. / max));
QApplication::processEvents();
}
void KX_Pult::renew(bool write) {
addToList(trUtf8("Update settings from \"%1\"").arg(PI2QString(config_)), Qt::darkMagenta);
dir.setPath(config.getValue("x.output_dir", "./Experiments/").stringValue());
setWindowTitle(config.getValue("title", "Noname").stringValue() + trUtf8(" - KX Pult"));
//if (write) ui->configWidget->write();
if (prot_x != 0) {
prot_x->stop();
delete prot_x;
}
if (prot_c != 0) {
prot_c->stop();
delete prot_c;
}
prot_x = new __KX_Protocol_X(config_, name_x);
prot_c = new __KX_Protocol_C(config_, name_c);
ui->graphic->setAutoXIncrement(prot_x->expectedFrequency() > 0. ? 1. / prot_x->expectedFrequency() : 1.);
coeffs.renew();
CONNECT1(void, bool, prot_x, received, this, received);
}
void KX_Pult::toggledX(int index, bool on) {
ui->graphic->setGraphicVisible(on, index);
}
void KX_Pult::changedX(int index, int num) {
prot_x->to_x.x_num[index] = num;
}
void KX_Pult::commandClicked() {
QPushButton * b = qobject_cast<QPushButton*>(sender());
if (!b) return;
prot_c->sendCommand(b->property("_command").toInt());
}

View File

@@ -1,170 +1,170 @@
#ifndef KX_PULT_H
#define KX_PULT_H
#include <QDialog>
#include <QSpinBox>
#include <QFont>
#include <QRect>
#include <QFile>
#include <QVector>
#include <QDir>
#include <QTextStream>
#include <QDebug>
#include <QBoxLayout>
#include <QCheckBox>
#include <QMainWindow>
#include <QTimer>
#include <QTime>
#include <QMenu>
#include <QMetaObject>
#include <QTreeWidgetItem>
#include <QLabel>
#include "kx_coeffs.h"
#include "kx_protocol_x.h"
#include "kx_protocol_c.h"
#include "piqt.h"
#include "session_manager.h"
#include "qpievaluator.h"
class XCheck: public QWidget {
Q_OBJECT
public:
explicit XCheck(int index);
QCheckBox check;
QSpinBox spin;
private:
bool eventFilter(QObject * o, QEvent * e);
int index_;
private slots:
void spinChanged(int value) {check.setChecked(true); emit valueChanged(index_, value);}
void checkChanged_(bool value) {emit checkChanged(index_, value);}
signals:
void valueChanged(int index, int value);
void checkChanged(int index, bool on);
};
namespace Ui {
class KX_Pult;
};
class KX_Pult: public QMainWindow, public PIObject
{
Q_OBJECT
PIOBJECT(KX_Pult)
public:
KX_Pult();
~KX_Pult();
private:
struct KDesc {
KDesc() {index = -1;}
int index;
QString name;
QString type;
QString comment;
QString value;
};
bool eventFilter(QObject * o, QEvent * e);
void timerEvent(QTimerEvent * );
void setControlsEnable(bool enable);
void setX(const KX_X_Data & data);
void addToList(const QString & s, const QColor & c);
QString getNewFileName(int inc);
QColor invertColor(QColor col) {return QColor(255 - col.red(), 255 - col.green(), 255 - col.blue());}
void stopWait();
bool calculateExpression(int i, QVector<int> trace);
void markError(QTreeWidgetItem * item, const QString & tool_tip = QString());
void markNormal(QTreeWidgetItem * item);
void progress(int val, int max);
void clearSelected();
QString typeName(const QString & n) const;
int parseHeader(const QString & file, QMap<int, KDesc> & map);
EVENT_HANDLER1(void, received, bool, ok);
EVENT_HANDLER(void, pip_sendFailed) {emit q_k_sendFailed();}
EVENT_HANDLER(void, pip_sendSucceed) {emit q_k_sendSucceed();}
EVENT_HANDLER(void, pip_receiveFailed) {emit q_k_receiveFailed();}
EVENT_HANDLER(void, pip_receiveSucceed) {emit q_k_receiveSucceed();}
QVector<XCheck * > checks;
QVector<QLabel * > values;
Ui::KX_Pult * ui;
PIString config_, name_x, name_c;
QDir dir;
QString outdir, kdesc_file, cdesc_file;
QFile file;
QTime tm, ctm;
QIcon icon_record, icon_stop;
QTextStream stream;
QTimer timer_diag;
QMap<int, KDesc> kdesc, cdesc;
QMap<QString, int> knames;
QSet<int> calculated;
QStringList knames_sort;
QPIEvaluator eval;
SessionManager session;
QPIConfig config;
QMenu log_menu;
//QVector<float> k, x;
KX_Coefficients coeffs;
__KX_Protocol_X * prot_x;
__KX_Protocol_C * prot_c;
int csize, wcnt, timer, timer_update, clear_target;
bool needWrite, isPause, need_update, show_x;
private slots:
void loading(QPIConfig & conf);
void saving(QPIConfig & conf);
void updateGraph();
void updateDiag();
void updateKDesc(bool ask_move = false);
void updateCDesc();
void updateTree(bool move = false);
void updateCommands();
void filterTree();
void calculate();
void renew(bool write = true);
void toggledX(int index, bool on);
void changedX(int index, int num);
void commandClicked();
void k_sendFailed();
void k_sendSucceed();
void k_receiveFailed();
void k_receiveSucceed();
void on_spinBuffer_editingFinished();
void on_buttonSendK_clicked();
void on_buttonReceiveK_clicked();
void on_buttonShowAll_clicked();
void on_buttonHideAll_clicked();
void on_buttonRead_clicked();
void on_buttonWrite_clicked();
void on_buttonResize_clicked();
void on_buttonSetKDesc_clicked();
void on_buttonReparseKDesc_clicked() {updateKDesc(true);}
void on_buttonSetCDesc_clicked();
void on_buttonReparseCDesc_clicked() {updateCDesc();}
void on_buttonCalculate_clicked() {calculate();}
void on_buttonApply_clicked() {renew();}
void on_spinSize_valueChanged(int);
void on_buttonPause_toggled(bool on) {isPause = on;}
void on_buttonRecord_clicked();
void on_treeK_itemClicked(QTreeWidgetItem * item, int column);
void on_treeK_itemChanged(QTreeWidgetItem * item, int column);
void on_actionClear_triggered();
signals:
void q_k_sendFailed();
void q_k_sendSucceed();
void q_k_receiveFailed();
void q_k_receiveSucceed();
void recordStarted(const QString & fileName);
void recordStopped(const QString & fileName);
};
#endif // KX_PULT_H
#ifndef KX_PULT_H
#define KX_PULT_H
#include <QDialog>
#include <QSpinBox>
#include <QFont>
#include <QRect>
#include <QFile>
#include <QVector>
#include <QDir>
#include <QTextStream>
#include <QDebug>
#include <QBoxLayout>
#include <QCheckBox>
#include <QMainWindow>
#include <QTimer>
#include <QTime>
#include <QMenu>
#include <QMetaObject>
#include <QTreeWidgetItem>
#include <QLabel>
#include "kx_coeffs.h"
#include "kx_protocol_x.h"
#include "kx_protocol_c.h"
#include "piqt.h"
#include "session_manager.h"
#include "qpievaluator.h"
class XCheck: public QWidget {
Q_OBJECT
public:
explicit XCheck(int index);
QCheckBox check;
QSpinBox spin;
private:
bool eventFilter(QObject * o, QEvent * e);
int index_;
private slots:
void spinChanged(int value) {check.setChecked(true); emit valueChanged(index_, value);}
void checkChanged_(bool value) {emit checkChanged(index_, value);}
signals:
void valueChanged(int index, int value);
void checkChanged(int index, bool on);
};
namespace Ui {
class KX_Pult;
};
class KX_Pult: public QMainWindow, public PIObject
{
Q_OBJECT
PIOBJECT(KX_Pult)
public:
KX_Pult();
~KX_Pult();
private:
struct KDesc {
KDesc() {index = -1;}
int index;
QString name;
QString type;
QString comment;
QString value;
};
bool eventFilter(QObject * o, QEvent * e);
void timerEvent(QTimerEvent * );
void setControlsEnable(bool enable);
void setX(const KX_X_Data & data);
void addToList(const QString & s, const QColor & c);
QString getNewFileName(int inc);
QColor invertColor(QColor col) {return QColor(255 - col.red(), 255 - col.green(), 255 - col.blue());}
void stopWait();
bool calculateExpression(int i, QVector<int> trace);
void markError(QTreeWidgetItem * item, const QString & tool_tip = QString());
void markNormal(QTreeWidgetItem * item);
void progress(int val, int max);
void clearSelected();
QString typeName(const QString & n) const;
int parseHeader(const QString & file, QMap<int, KDesc> & map);
EVENT_HANDLER1(void, received, bool, ok);
EVENT_HANDLER(void, pip_sendFailed) {emit q_k_sendFailed();}
EVENT_HANDLER(void, pip_sendSucceed) {emit q_k_sendSucceed();}
EVENT_HANDLER(void, pip_receiveFailed) {emit q_k_receiveFailed();}
EVENT_HANDLER(void, pip_receiveSucceed) {emit q_k_receiveSucceed();}
QVector<XCheck * > checks;
QVector<QLabel * > values;
Ui::KX_Pult * ui;
PIString config_, name_x, name_c;
QDir dir;
QString outdir, kdesc_file, cdesc_file;
QFile file;
QTime tm, ctm;
QIcon icon_record, icon_stop;
QTextStream stream;
QTimer timer_diag;
QMap<int, KDesc> kdesc, cdesc;
QMap<QString, int> knames;
QSet<int> calculated;
QStringList knames_sort;
QPIEvaluator eval;
SessionManager session;
QPIConfig config;
QMenu log_menu;
//QVector<float> k, x;
KX_Coefficients coeffs;
__KX_Protocol_X * prot_x;
__KX_Protocol_C * prot_c;
int csize, wcnt, timer, timer_update, clear_target;
bool needWrite, isPause, need_update, show_x;
private slots:
void loading(QPIConfig & conf);
void saving(QPIConfig & conf);
void updateGraph();
void updateDiag();
void updateKDesc(bool ask_move = false);
void updateCDesc();
void updateTree(bool move = false);
void updateCommands();
void filterTree();
void calculate();
void renew(bool write = true);
void toggledX(int index, bool on);
void changedX(int index, int num);
void commandClicked();
void k_sendFailed();
void k_sendSucceed();
void k_receiveFailed();
void k_receiveSucceed();
void on_spinBuffer_editingFinished();
void on_buttonSendK_clicked();
void on_buttonReceiveK_clicked();
void on_buttonShowAll_clicked();
void on_buttonHideAll_clicked();
void on_buttonRead_clicked();
void on_buttonWrite_clicked();
void on_buttonResize_clicked();
void on_buttonSetKDesc_clicked();
void on_buttonReparseKDesc_clicked() {updateKDesc(true);}
void on_buttonSetCDesc_clicked();
void on_buttonReparseCDesc_clicked() {updateCDesc();}
void on_buttonCalculate_clicked() {calculate();}
void on_buttonApply_clicked() {renew();}
void on_spinSize_valueChanged(int);
void on_buttonPause_toggled(bool on) {isPause = on;}
void on_buttonRecord_clicked();
void on_treeK_itemClicked(QTreeWidgetItem * item, int column);
void on_treeK_itemChanged(QTreeWidgetItem * item, int column);
void on_actionClear_triggered();
signals:
void q_k_sendFailed();
void q_k_sendSucceed();
void q_k_receiveFailed();
void q_k_receiveSucceed();
void recordStarted(const QString & fileName);
void recordStopped(const QString & fileName);
};
#endif // KX_PULT_H

View File

@@ -1,10 +1,10 @@
#include <QtGui/QApplication>
#include "kx_pult.h"
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
KX_Pult w;
w.show();
return a.exec();
}
#include <QtGui/QApplication>
#include "kx_pult.h"
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
KX_Pult w;
w.show();
return a.exec();
}

0
make_libs.sh Executable file → Normal file
View File

2
pip

Submodule pip updated: cc580d9385...a4b3edb3e1

View File

@@ -1,57 +1,21 @@
cmake_minimum_required(VERSION 3.0)
cmake_policy(SET CMP0017 NEW) # need include() with .cmake
set(_PIQt_MAJOR 1)
set(_PIQt_MINOR 0)
set(_PIQt_REVISION 0)
set(_PIQt_SUFFIX )
set(_PIQt_COMPANY SHS)
set(_PIQt_DOMAIN org.SHS)
if(NOT DEFINED BUILD_NUMBER)
set(BUILD_NUMBER 9999)
endif()
include(QADMacros)
if(STATIC_LIB)
set(PIQt_LIB_TYPE STATIC)
add_definitions(-DPIQt_STATIC_DEFINE)
else()
set(PIQt_LIB_TYPE SHARED)
endif()
set(PIQt_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/piqt_version.h")
set_version(PIQt
MAJOR "${_PIQt_MAJOR}"
MINOR "${_PIQt_MINOR}"
REVISION "${_PIQt_REVISION}"
BUILD "${BUILD_NUMBER}"
SUFFIX "${_PIQt_SUFFIX}"
OUTPUT "${PIQt_VERSION_FILE}")
set_deploy_property(PIQt ${_PIQt_LIB_TYPE}
FULLNAME "${_PIQt_DOMAIN}.*"
COMPANY "${_PIQt_COMPANY}")
macro(piqt_library NAME _MODULES _LIBS)
_qt_project(${NAME} FALSE "PIQt" "${_MODULES}" "pip;${_LIBS}" ${ARGN})
_qt_install(${NAME} FALSE "pip" "out_HDR" "out_QM")
endmacro()
macro(piqt_application NAME _MODULES _LIBS)
_qt_project(${NAME} TRUE "PIQt" "${_MODULES}" "pip;${_LIBS}" ${ARGN})
_qt_install(${NAME} TRUE "pip" "" "out_QM")
endmacro()
include_directories(${PIP_INCLUDES})
add_subdirectory(libs)
if (UTILS)
add_subdirectory(utils)
endif()
set(QT_MULTILIB_LIST ${QT_MULTILIB_LIST} PARENT_SCOPE)
set(piqt_includes ${piqt_includes} PARENT_SCOPE)
if (LIB)
set(_ALL_TARGETS ${_ALL_TARGETS} PARENT_SCOPE)
endif()
cmake_minimum_required(VERSION 3.0)
cmake_policy(SET CMP0017 NEW) # need include() with .cmake
macro(piqt_library NAME _MODULES _LIBS)
_qt_project(${NAME} FALSE "PIQt" "${_MODULES}" "pip;${_LIBS}" ${ARGN})
_qt_install(${NAME} FALSE "pip" "out_HDR" "out_QM")
endmacro()
macro(piqt_application NAME _MODULES _LIBS)
_qt_project(${NAME} TRUE "PIQt" "${_MODULES}" "pip;${_LIBS}" ${ARGN})
_qt_install(${NAME} TRUE "pip" "" "out_QM")
endmacro()
include_directories(${PIP_INCLUDES})
add_subdirectory(libs)
if (UTILS)
add_subdirectory(utils)
endif()
copy_to_parent(piqt_includes)

View File

@@ -32,7 +32,7 @@
<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::OnlyExpandY|Graphic::Pause|Graphic::Save</set>
<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>

View File

@@ -1,4 +0,0 @@
<RCC>
<qresource prefix="/">
</qresource>
</RCC>

View File

@@ -7,7 +7,7 @@ else()
set(APP_ICON "icons/qpicalculator.png")
endif()
set(APP_INFO "Small calculator ang grapher")
qad_application(${PROJECT_NAME} "Gui;Widgets" "qad_utils;qad_widgets;qad_graphic")
qad_application(${PROJECT_NAME} "Gui;Widgets" "qad_utils;qad_widgets;qad_graphic;pip;piqt")
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)

View File

Before

Width:  |  Height:  |  Size: 158 KiB

After

Width:  |  Height:  |  Size: 158 KiB

View File

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

View File

@@ -1,4 +1,5 @@
#include "mainwindow.h"
#include "piqt.h"
MainWindow::MainWindow(QWidget * parent): QMainWindow(parent), Ui::MainWindow() {
@@ -62,7 +63,7 @@ void MainWindow::redrawGraphics() {
graphic->setGraphicName(ti->text(1), i);
pol.clear();
if (ti->checkState(0) == Qt::Checked) {
if (evaluator.check(ti->text(1))) {
if (evaluator.check(Q2PIString(ti->text(1)))) {
cx = sx;
while (cx < fx) {
evaluator.setVariable(vi, complexd(cx, 0.));
@@ -140,19 +141,19 @@ void MainWindow::saving(QPIConfig & conf) {
void MainWindow::on_lineInput_textChanged(QString text) {
if (evaluator.check(text)) lineInput->setPalette(npal);
if (evaluator.check(Q2PIString(text))) lineInput->setPalette(npal);
else lineInput->setPalette(epal);
labelParsed->setText(evaluator.expression());
labelError->setText(evaluator.error());
labelParsed->setText(PI2QString(evaluator.expression()));
labelError->setText(PI2QString(evaluator.error()));
}
void MainWindow::on_lineInput_returnPressed() {
bool ret = evaluator.check(lineInput->text());
bool ret = evaluator.check(Q2PIString(lineInput->text()));
if (ret) lineInput->setPalette(npal);
else lineInput->setPalette(epal);
labelParsed->setText(evaluator.expression());
labelError->setText(evaluator.error());
labelParsed->setText(PI2QString(evaluator.expression()));
labelError->setText(PI2QString(evaluator.error()));
if (!ret) return;
complexd val = evaluator.evaluate();
evaluator.setVariable(ans, val);
@@ -182,6 +183,16 @@ void MainWindow::on_lineInput_returnPressed() {
}
void MainWindow::on_treeGraphics_itemSelectionChanged() {
buttonGraphicDel->setDisabled(treeGraphics->selectedItems().isEmpty());
if (treeGraphics->currentItem()) {
int ind = treeGraphics->indexOfTopLevelItem(treeGraphics->currentItem());
if (ind < 0 || ind >= graphic->graphicsCount()) return;
graphic->setCurrentGraphic(ind);
}
}
void MainWindow::on_treeGraphics_itemDoubleClicked(QTreeWidgetItem * item, int column) {
Qt::ItemFlags f = item->flags();
if (column != 1) f &= ~Qt::ItemIsEditable;
@@ -254,7 +265,7 @@ void MainWindow::on_tabWidget_currentChanged(int index) {
vn = treeVariables->topLevelItem(i)->text(0);
vv = treeVariables->topLevelItem(i)->text(1);
eval.check(vv);
evaluator.setVariable(vn, eval.evaluate());
evaluator.setVariable(Q2PIString(vn), eval.evaluate());
}
if (index == 0) on_lineInput_returnPressed();
if (index == 2) redrawGraphics();

View File

@@ -8,7 +8,7 @@
#include <QScrollBar>
#include <QColorDialog>
#include "ui_mainwindow.h"
#include "qpievaluator.h"
#include "pievaluator.h"
#include "session_manager.h"
@@ -26,7 +26,7 @@ private:
void updateGraphics();
void redrawGraphics();
QPIEvaluator evaluator;
PIEvaluator evaluator;
QPalette npal, epal;
SessionManager session;
int ans;
@@ -39,7 +39,7 @@ private slots:
void on_lineInput_returnPressed();
void on_treeHistory_itemDoubleClicked(QTreeWidgetItem * item, int column) {lineInput->setText(item->text(0));}
void on_treeVariables_itemSelectionChanged() {buttonVarDel->setDisabled(treeVariables->selectedItems().isEmpty());}
void on_treeGraphics_itemSelectionChanged() {buttonGraphicDel->setDisabled(treeGraphics->selectedItems().isEmpty());}
void on_treeGraphics_itemSelectionChanged();
void on_treeGraphics_itemChanged(QTreeWidgetItem * , int col) { if (active_) redrawGraphics();}
void on_treeGraphics_itemDoubleClicked(QTreeWidgetItem * item, int column);
void on_buttonVarAdd_clicked();

View File

@@ -1,11 +1,11 @@
{
\"Name\" : \"ProjectFilesystemPlugin\",
\"Version\" : \"1.1.0\",
\"CompatVersion\" : \"1.1.0\",
\"Vendor\" : \"Peri4\",
\"Copyright\" : \"(C) Peri4\",
\"License\" : \"LGPLv3\",
\"Description\" : \"LGPLv3\",
\"Url\" : \"\",
$$dependencyList
}
{
\"Name\" : \"ProjectFilesystemPlugin\",
\"Version\" : \"1.1.0\",
\"CompatVersion\" : \"1.1.0\",
\"Vendor\" : \"Peri4\",
\"Copyright\" : \"(C) Peri4\",
\"License\" : \"LGPLv3\",
\"Description\" : \"LGPLv3\",
\"Url\" : \"\",
$$dependencyList
}

View File

@@ -1,91 +1,91 @@
#include "filterdialog.h"
#include <utils/utilsicons.h>
#include <QDir>
FilterDialog::FilterDialog(QWidget * parent): QDialog(parent) {
setupUi(this);
toolButton->setIcon(Utils::Icons::CLEAN.icon());
toolButton_2->setIcon(Utils::Icons::CLEAN.icon());
toolButton_3->setIcon(Utils::Icons::CLEAN.icon());
toolButton_4->setIcon(Utils::Icons::CLEAN.icon());
}
void FilterDialog::changeEvent(QEvent *e) {
QDialog::changeEvent(e);
switch (e->type()) {
case QEvent::LanguageChange:
retranslateUi(this);
break;
default:
break;
}
}
FilterDialog::Filter FilterDialog::filter() const {
FilterDialog::Filter ret;
ret.files_show = getFilters(lineFilesShow);
ret.files_hide = getFilters(lineFilesHide);
ret.dirs_show = getFilters(lineDirsShow);
ret.dirs_hide = getFilters(lineDirsHide);
return ret;
}
void FilterDialog::setFilter(const FilterDialog::Filter & f) {
setFilters(lineFilesShow, f.files_show);
setFilters(lineFilesHide, f.files_hide);
setFilters(lineDirsShow, f.dirs_show);
setFilters(lineDirsHide, f.dirs_hide);
}
QStringList FilterDialog::getFilters(QLineEdit * le) const {
if (!le) return QStringList();
QStringList ret = le->text().split(",");
for (int i = 0; i < ret.size(); ++i)
ret[i] = ret[i].trimmed();
ret.removeAll("");
return ret;
}
void FilterDialog::setFilters(QLineEdit * le, QStringList f) {
if (!le) return;
le->setText(f.join(","));
}
FilterDialog::Filter::Filter(const QVariant & v) {
QByteArray ba = v.toByteArray();
if (ba.isEmpty()) return;
QDataStream s(ba);
s >> files_show >> files_hide >> dirs_show >> dirs_hide;
}
QVariant FilterDialog::Filter::toVariant() const {
QByteArray ba;
QDataStream s(&ba, QIODevice::ReadWrite);
s << files_show << files_hide << dirs_show << dirs_hide;
return QVariant(ba);
}
bool FilterDialog::Filter::filterLogic(const QStringList & fshow, const QStringList & fhide, const QString & path) const {
if (fshow.isEmpty() && fhide.isEmpty()) return true;
if (!fhide.isEmpty()) {
if (QDir::match(fhide, path))
return false;
else {
if (fshow.isEmpty())
return true;
else
return QDir::match(fshow, path);
}
}
if (!fshow.isEmpty())
return QDir::match(fshow, path);
return true;
}
#include "filterdialog.h"
#include <utils/utilsicons.h>
#include <QDir>
FilterDialog::FilterDialog(QWidget * parent): QDialog(parent) {
setupUi(this);
toolButton->setIcon(Utils::Icons::CLEAN.icon());
toolButton_2->setIcon(Utils::Icons::CLEAN.icon());
toolButton_3->setIcon(Utils::Icons::CLEAN.icon());
toolButton_4->setIcon(Utils::Icons::CLEAN.icon());
}
void FilterDialog::changeEvent(QEvent *e) {
QDialog::changeEvent(e);
switch (e->type()) {
case QEvent::LanguageChange:
retranslateUi(this);
break;
default:
break;
}
}
FilterDialog::Filter FilterDialog::filter() const {
FilterDialog::Filter ret;
ret.files_show = getFilters(lineFilesShow);
ret.files_hide = getFilters(lineFilesHide);
ret.dirs_show = getFilters(lineDirsShow);
ret.dirs_hide = getFilters(lineDirsHide);
return ret;
}
void FilterDialog::setFilter(const FilterDialog::Filter & f) {
setFilters(lineFilesShow, f.files_show);
setFilters(lineFilesHide, f.files_hide);
setFilters(lineDirsShow, f.dirs_show);
setFilters(lineDirsHide, f.dirs_hide);
}
QStringList FilterDialog::getFilters(QLineEdit * le) const {
if (!le) return QStringList();
QStringList ret = le->text().split(",");
for (int i = 0; i < ret.size(); ++i)
ret[i] = ret[i].trimmed();
ret.removeAll("");
return ret;
}
void FilterDialog::setFilters(QLineEdit * le, QStringList f) {
if (!le) return;
le->setText(f.join(","));
}
FilterDialog::Filter::Filter(const QVariant & v) {
QByteArray ba = v.toByteArray();
if (ba.isEmpty()) return;
QDataStream s(ba);
s >> files_show >> files_hide >> dirs_show >> dirs_hide;
}
QVariant FilterDialog::Filter::toVariant() const {
QByteArray ba;
QDataStream s(&ba, QIODevice::ReadWrite);
s << files_show << files_hide << dirs_show << dirs_hide;
return QVariant(ba);
}
bool FilterDialog::Filter::filterLogic(const QStringList & fshow, const QStringList & fhide, const QString & path) const {
if (fshow.isEmpty() && fhide.isEmpty()) return true;
if (!fhide.isEmpty()) {
if (QDir::match(fhide, path))
return false;
else {
if (fshow.isEmpty())
return true;
else
return QDir::match(fshow, path);
}
}
if (!fshow.isEmpty())
return QDir::match(fshow, path);
return true;
}

View File

@@ -1,37 +1,37 @@
#ifndef FILTERDIALOG_H
#define FILTERDIALOG_H
#include "ui_filterdialog.h"
class FilterDialog: public QDialog, private Ui::FilterDialog
{
Q_OBJECT
public:
explicit FilterDialog(QWidget *parent = 0);
struct Filter {
Filter() {}
Filter(const QVariant & v);
QVariant toVariant() const;
bool filterFile(const QString & path) const {return filterLogic(files_show, files_hide, path);}
bool filterDir(const QString & path) const {return filterLogic(dirs_show, dirs_hide, path);}
QStringList files_show;
QStringList files_hide;
QStringList dirs_show;
QStringList dirs_hide;
private:
bool filterLogic(const QStringList & fshow, const QStringList & fhide, const QString & path) const;
};
Filter filter() const;
void setFilter(const Filter & f);
protected:
void changeEvent(QEvent *e);
QStringList getFilters(QLineEdit * le) const;
void setFilters(QLineEdit * le, QStringList f);
};
#endif // FILTERDIALOG_H
#ifndef FILTERDIALOG_H
#define FILTERDIALOG_H
#include "ui_filterdialog.h"
class FilterDialog: public QDialog, private Ui::FilterDialog
{
Q_OBJECT
public:
explicit FilterDialog(QWidget *parent = 0);
struct Filter {
Filter() {}
Filter(const QVariant & v);
QVariant toVariant() const;
bool filterFile(const QString & path) const {return filterLogic(files_show, files_hide, path);}
bool filterDir(const QString & path) const {return filterLogic(dirs_show, dirs_hide, path);}
QStringList files_show;
QStringList files_hide;
QStringList dirs_show;
QStringList dirs_hide;
private:
bool filterLogic(const QStringList & fshow, const QStringList & fhide, const QString & path) const;
};
Filter filter() const;
void setFilter(const Filter & f);
protected:
void changeEvent(QEvent *e);
QStringList getFilters(QLineEdit * le) const;
void setFilters(QLineEdit * le, QStringList f);
};
#endif // FILTERDIALOG_H

View File

@@ -1,226 +1,226 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>FilterDialog</class>
<widget class="QDialog" name="FilterDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>342</width>
<height>250</height>
</rect>
</property>
<property name="windowTitle">
<string>Project filesystem filters</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Input filters, separated by &quot;,&quot;:</string>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="2" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Show dirs:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="lineFilesHide"/>
</item>
<item row="1" column="2">
<widget class="QToolButton" name="toolButton_2"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Hide files:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Show files:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="lineFilesShow"/>
</item>
<item row="0" column="2">
<widget class="QToolButton" name="toolButton"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Hide dirs:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="lineDirsShow"/>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="lineDirsHide"/>
</item>
<item row="2" column="2">
<widget class="QToolButton" name="toolButton_3"/>
</item>
<item row="3" column="2">
<widget class="QToolButton" name="toolButton_4"/>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</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>
<tabstops>
<tabstop>lineFilesShow</tabstop>
<tabstop>lineFilesHide</tabstop>
<tabstop>lineDirsShow</tabstop>
<tabstop>lineDirsHide</tabstop>
<tabstop>toolButton</tabstop>
<tabstop>toolButton_2</tabstop>
<tabstop>toolButton_3</tabstop>
<tabstop>toolButton_4</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>FilterDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>259</x>
<y>238</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>FilterDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>327</x>
<y>238</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>toolButton</sender>
<signal>clicked()</signal>
<receiver>lineFilesShow</receiver>
<slot>clear()</slot>
<hints>
<hint type="sourcelabel">
<x>329</x>
<y>60</y>
</hint>
<hint type="destinationlabel">
<x>269</x>
<y>58</y>
</hint>
</hints>
</connection>
<connection>
<sender>toolButton_2</sender>
<signal>clicked()</signal>
<receiver>lineFilesHide</receiver>
<slot>clear()</slot>
<hints>
<hint type="sourcelabel">
<x>329</x>
<y>93</y>
</hint>
<hint type="destinationlabel">
<x>295</x>
<y>91</y>
</hint>
</hints>
</connection>
<connection>
<sender>toolButton_3</sender>
<signal>clicked()</signal>
<receiver>lineDirsShow</receiver>
<slot>clear()</slot>
<hints>
<hint type="sourcelabel">
<x>329</x>
<y>126</y>
</hint>
<hint type="destinationlabel">
<x>295</x>
<y>124</y>
</hint>
</hints>
</connection>
<connection>
<sender>toolButton_4</sender>
<signal>clicked()</signal>
<receiver>lineDirsHide</receiver>
<slot>clear()</slot>
<hints>
<hint type="sourcelabel">
<x>329</x>
<y>159</y>
</hint>
<hint type="destinationlabel">
<x>295</x>
<y>157</y>
</hint>
</hints>
</connection>
</connections>
</ui>
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>FilterDialog</class>
<widget class="QDialog" name="FilterDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>342</width>
<height>250</height>
</rect>
</property>
<property name="windowTitle">
<string>Project filesystem filters</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Input filters, separated by &quot;,&quot;:</string>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="2" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Show dirs:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="lineFilesHide"/>
</item>
<item row="1" column="2">
<widget class="QToolButton" name="toolButton_2"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Hide files:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Show files:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="lineFilesShow"/>
</item>
<item row="0" column="2">
<widget class="QToolButton" name="toolButton"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Hide dirs:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="lineDirsShow"/>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="lineDirsHide"/>
</item>
<item row="2" column="2">
<widget class="QToolButton" name="toolButton_3"/>
</item>
<item row="3" column="2">
<widget class="QToolButton" name="toolButton_4"/>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</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>
<tabstops>
<tabstop>lineFilesShow</tabstop>
<tabstop>lineFilesHide</tabstop>
<tabstop>lineDirsShow</tabstop>
<tabstop>lineDirsHide</tabstop>
<tabstop>toolButton</tabstop>
<tabstop>toolButton_2</tabstop>
<tabstop>toolButton_3</tabstop>
<tabstop>toolButton_4</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>FilterDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>259</x>
<y>238</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>FilterDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>327</x>
<y>238</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>toolButton</sender>
<signal>clicked()</signal>
<receiver>lineFilesShow</receiver>
<slot>clear()</slot>
<hints>
<hint type="sourcelabel">
<x>329</x>
<y>60</y>
</hint>
<hint type="destinationlabel">
<x>269</x>
<y>58</y>
</hint>
</hints>
</connection>
<connection>
<sender>toolButton_2</sender>
<signal>clicked()</signal>
<receiver>lineFilesHide</receiver>
<slot>clear()</slot>
<hints>
<hint type="sourcelabel">
<x>329</x>
<y>93</y>
</hint>
<hint type="destinationlabel">
<x>295</x>
<y>91</y>
</hint>
</hints>
</connection>
<connection>
<sender>toolButton_3</sender>
<signal>clicked()</signal>
<receiver>lineDirsShow</receiver>
<slot>clear()</slot>
<hints>
<hint type="sourcelabel">
<x>329</x>
<y>126</y>
</hint>
<hint type="destinationlabel">
<x>295</x>
<y>124</y>
</hint>
</hints>
</connection>
<connection>
<sender>toolButton_4</sender>
<signal>clicked()</signal>
<receiver>lineDirsHide</receiver>
<slot>clear()</slot>
<hints>
<hint type="sourcelabel">
<x>329</x>
<y>159</y>
</hint>
<hint type="destinationlabel">
<x>295</x>
<y>157</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -1,6 +1,6 @@
<RCC>
<qresource prefix="/">
<file>icons/edit-find.png</file>
<file>icons/utilities-terminal.png</file>
</qresource>
</RCC>
<RCC>
<qresource prefix="/">
<file>icons/edit-find.png</file>
<file>icons/utilities-terminal.png</file>
</qresource>
</RCC>

View File

@@ -1,89 +1,89 @@
#include "projectfilesystemplugin.h"
#include "projectfilesystempluginconstants.h"
#include "projectfilesystemwidget.h"
#include <coreplugin/icore.h>
#include <coreplugin/icontext.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/coreconstants.h>
#include <utils/macroexpander.h>
#include <QAction>
#include <QMessageBox>
#include <QMainWindow>
#include <QMenu>
#include <QDebug>
namespace ProjectFilesystemPlugin {
namespace Internal {
ProjectFilesystemPluginPlugin::ProjectFilesystemPluginPlugin()
{
// Create your members
}
ProjectFilesystemPluginPlugin::~ProjectFilesystemPluginPlugin()
{
// Unregister objects from the plugin manager's object pool
// Delete members
}
bool ProjectFilesystemPluginPlugin::initialize(const QStringList &arguments, QString *errorString)
{
// Register objects in the plugin manager's object pool
// Load settings
// Add actions to menus
// Connect to other plugins' signals
// In the initialize function, a plugin can be sure that the plugins it
// depends on have initialized their members.
Q_UNUSED(arguments)
Q_UNUSED(errorString)
/*auto action = new QAction(tr("ProjectFilesystemPlugin Action"), this);
Core::Command *cmd = Core::ActionManager::registerAction(action, Constants::ACTION_ID,
Core::Context(Core::Constants::C_GLOBAL));
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Alt+Meta+A")));
connect(action, &QAction::triggered, this, &ProjectFilesystemPluginPlugin::triggerAction);
Core::ActionContainer *menu = Core::ActionManager::createMenu(Constants::MENU_ID);
menu->menu()->setTitle(tr("ProjectFilesystemPlugin"));
menu->addAction(cmd);
Core::ActionManager::actionContainer(Core::Constants::M_TOOLS)->addMenu(menu);
qDebug() << Core::IContext::widget();*/
//addAutoReleasedObject(new ProjectFSWidgetFactory());
(new ProjectFSWidgetFactory())->setParent(this);
return true;
}
void ProjectFilesystemPluginPlugin::extensionsInitialized()
{
Utils::globalMacroExpander()->registerPrefix("ProjectFilesystem", "Project filesystem plugin", [](QString v) -> QString {return v;} );
Utils::globalMacroExpander()->registerFileVariables("ProjectFilesystem", "Selected item",
[]() -> QString { return projectfs_menu_target.absoluteFilePath();});
// Retrieve objects from the plugin manager's object pool
// In the extensionsInitialized function, a plugin can be sure that all
// plugins that depend on it are completely initialized.
}
ExtensionSystem::IPlugin::ShutdownFlag ProjectFilesystemPluginPlugin::aboutToShutdown()
{
// Save settings
// Disconnect from signals that are not needed during shutdown
// Hide UI (if you add UI that is not in the main window directly)
return SynchronousShutdown;
}
void ProjectFilesystemPluginPlugin::triggerAction()
{
QMessageBox::information(Core::ICore::mainWindow(),
tr("Action Triggered"),
tr("This is an action from ProjectFilesystemPlugin."));
}
} // namespace Internal
} // namespace ProjectFilesystemPlugin
#include "projectfilesystemplugin.h"
#include "projectfilesystempluginconstants.h"
#include "projectfilesystemwidget.h"
#include <coreplugin/icore.h>
#include <coreplugin/icontext.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/coreconstants.h>
#include <utils/macroexpander.h>
#include <QAction>
#include <QMessageBox>
#include <QMainWindow>
#include <QMenu>
#include <QDebug>
namespace ProjectFilesystemPlugin {
namespace Internal {
ProjectFilesystemPluginPlugin::ProjectFilesystemPluginPlugin()
{
// Create your members
}
ProjectFilesystemPluginPlugin::~ProjectFilesystemPluginPlugin()
{
// Unregister objects from the plugin manager's object pool
// Delete members
}
bool ProjectFilesystemPluginPlugin::initialize(const QStringList &arguments, QString *errorString)
{
// Register objects in the plugin manager's object pool
// Load settings
// Add actions to menus
// Connect to other plugins' signals
// In the initialize function, a plugin can be sure that the plugins it
// depends on have initialized their members.
Q_UNUSED(arguments)
Q_UNUSED(errorString)
/*auto action = new QAction(tr("ProjectFilesystemPlugin Action"), this);
Core::Command *cmd = Core::ActionManager::registerAction(action, Constants::ACTION_ID,
Core::Context(Core::Constants::C_GLOBAL));
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Alt+Meta+A")));
connect(action, &QAction::triggered, this, &ProjectFilesystemPluginPlugin::triggerAction);
Core::ActionContainer *menu = Core::ActionManager::createMenu(Constants::MENU_ID);
menu->menu()->setTitle(tr("ProjectFilesystemPlugin"));
menu->addAction(cmd);
Core::ActionManager::actionContainer(Core::Constants::M_TOOLS)->addMenu(menu);
qDebug() << Core::IContext::widget();*/
//addAutoReleasedObject(new ProjectFSWidgetFactory());
(new ProjectFSWidgetFactory())->setParent(this);
return true;
}
void ProjectFilesystemPluginPlugin::extensionsInitialized()
{
Utils::globalMacroExpander()->registerPrefix("ProjectFilesystem", "Project filesystem plugin", [](QString v) -> QString {return v;} );
Utils::globalMacroExpander()->registerFileVariables("ProjectFilesystem", "Selected item",
[]() -> QString { return projectfs_menu_target.absoluteFilePath();});
// Retrieve objects from the plugin manager's object pool
// In the extensionsInitialized function, a plugin can be sure that all
// plugins that depend on it are completely initialized.
}
ExtensionSystem::IPlugin::ShutdownFlag ProjectFilesystemPluginPlugin::aboutToShutdown()
{
// Save settings
// Disconnect from signals that are not needed during shutdown
// Hide UI (if you add UI that is not in the main window directly)
return SynchronousShutdown;
}
void ProjectFilesystemPluginPlugin::triggerAction()
{
QMessageBox::information(Core::ICore::mainWindow(),
tr("Action Triggered"),
tr("This is an action from ProjectFilesystemPlugin."));
}
} // namespace Internal
} // namespace ProjectFilesystemPlugin

View File

@@ -1,29 +1,29 @@
#pragma once
#include "projectfilesystemplugin_global.h"
#include "projectfilesystemwidgetplugin.h"
#include <extensionsystem/iplugin.h>
namespace ProjectFilesystemPlugin {
namespace Internal {
class ProjectFilesystemPluginPlugin : public ExtensionSystem::IPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "ProjectFilesystemPlugin.json")
public:
ProjectFilesystemPluginPlugin();
~ProjectFilesystemPluginPlugin();
bool initialize(const QStringList &arguments, QString *errorString);
void extensionsInitialized();
ShutdownFlag aboutToShutdown();
private:
void triggerAction();
};
} // namespace Internal
} // namespace ProjectFilesystemPlugin
#pragma once
#include "projectfilesystemplugin_global.h"
#include "projectfilesystemwidgetplugin.h"
#include <extensionsystem/iplugin.h>
namespace ProjectFilesystemPlugin {
namespace Internal {
class ProjectFilesystemPluginPlugin : public ExtensionSystem::IPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "ProjectFilesystemPlugin.json")
public:
ProjectFilesystemPluginPlugin();
~ProjectFilesystemPluginPlugin();
bool initialize(const QStringList &arguments, QString *errorString);
void extensionsInitialized();
ShutdownFlag aboutToShutdown();
private:
void triggerAction();
};
} // namespace Internal
} // namespace ProjectFilesystemPlugin

View File

@@ -1,61 +1,61 @@
DEFINES += PROJECTFILESYSTEMPLUGIN_LIBRARY
# ProjectFilesystemPlugin files
SOURCES += projectfilesystemplugin.cpp \
projectfilesystemwidget.cpp \
projectfilesystemwidgetplugin.cpp \
filterdialog.cpp
HEADERS += projectfilesystemplugin.h \
projectfilesystemplugin_global.h \
projectfilesystempluginconstants.h \
projectfilesystemwidget.h \
projectfilesystemwidgetplugin.h \
filterdialog.h
FORMS += \
projectfilesystemwidget.ui \
filterdialog.ui
RESOURCES += \
projectfilesystem.qrc
#QT += network
# Qt Creator linking
## Either set the IDE_SOURCE_TREE when running qmake,
## or set the QTC_SOURCE environment variable, to override the default setting
isEmpty(IDE_SOURCE_TREE): IDE_SOURCE_TREE = $$(SDK_QTCREATOR_SRC)
## Either set the IDE_BUILD_TREE when running qmake,
## or set the QTC_BUILD environment variable, to override the default setting
isEmpty(IDE_BUILD_TREE): IDE_BUILD_TREE = $$(SDK_QTCREATOR_BUILD)
## uncomment to build plugin into user config directory
## <localappdata>/plugins/<ideversion>
## where <localappdata> is e.g.
## "%LOCALAPPDATA%\QtProject\qtcreator" on Windows Vista and later
## "$XDG_DATA_HOME/data/QtProject/qtcreator" or "~/.local/share/data/QtProject/qtcreator" on Linux
## "~/Library/Application Support/QtProject/Qt Creator" on OS X
#USE_USER_DESTDIR = yes
###### If the plugin can be depended upon by other plugins, this code needs to be outsourced to
###### <dirname>_dependencies.pri, where <dirname> is the name of the directory containing the
###### plugin's sources.
QTC_PLUGIN_NAME = ProjectFilesystemPlugin
QTC_LIB_DEPENDS += \
# nothing here at this time
QTC_PLUGIN_DEPENDS += \
coreplugin \
projectexplorer
QTC_PLUGIN_RECOMMENDS += \
# optional plugin dependencies. nothing here at this time
###### End _dependencies.pri contents ######
include($$IDE_SOURCE_TREE/src/qtcreatorplugin.pri)
DEFINES += PROJECTFILESYSTEMPLUGIN_LIBRARY
# ProjectFilesystemPlugin files
SOURCES += projectfilesystemplugin.cpp \
projectfilesystemwidget.cpp \
projectfilesystemwidgetplugin.cpp \
filterdialog.cpp
HEADERS += projectfilesystemplugin.h \
projectfilesystemplugin_global.h \
projectfilesystempluginconstants.h \
projectfilesystemwidget.h \
projectfilesystemwidgetplugin.h \
filterdialog.h
FORMS += \
projectfilesystemwidget.ui \
filterdialog.ui
RESOURCES += \
projectfilesystem.qrc
#QT += network
# Qt Creator linking
## Either set the IDE_SOURCE_TREE when running qmake,
## or set the QTC_SOURCE environment variable, to override the default setting
isEmpty(IDE_SOURCE_TREE): IDE_SOURCE_TREE = $$(SDK_QTCREATOR_SRC)
## Either set the IDE_BUILD_TREE when running qmake,
## or set the QTC_BUILD environment variable, to override the default setting
isEmpty(IDE_BUILD_TREE): IDE_BUILD_TREE = $$(SDK_QTCREATOR_BUILD)
## uncomment to build plugin into user config directory
## <localappdata>/plugins/<ideversion>
## where <localappdata> is e.g.
## "%LOCALAPPDATA%\QtProject\qtcreator" on Windows Vista and later
## "$XDG_DATA_HOME/data/QtProject/qtcreator" or "~/.local/share/data/QtProject/qtcreator" on Linux
## "~/Library/Application Support/QtProject/Qt Creator" on OS X
#USE_USER_DESTDIR = yes
###### If the plugin can be depended upon by other plugins, this code needs to be outsourced to
###### <dirname>_dependencies.pri, where <dirname> is the name of the directory containing the
###### plugin's sources.
QTC_PLUGIN_NAME = ProjectFilesystemPlugin
QTC_LIB_DEPENDS += \
# nothing here at this time
QTC_PLUGIN_DEPENDS += \
coreplugin \
projectexplorer
QTC_PLUGIN_RECOMMENDS += \
# optional plugin dependencies. nothing here at this time
###### End _dependencies.pri contents ######
include($$IDE_SOURCE_TREE/src/qtcreatorplugin.pri)

View File

@@ -1,9 +1,9 @@
#pragma once
#include <QtGlobal>
#if defined(PROJECTFILESYSTEMPLUGIN_LIBRARY)
# define PROJECTFILESYSTEMPLUGINSHARED_EXPORT Q_DECL_EXPORT
#else
# define PROJECTFILESYSTEMPLUGINSHARED_EXPORT Q_DECL_IMPORT
#endif
#pragma once
#include <QtGlobal>
#if defined(PROJECTFILESYSTEMPLUGIN_LIBRARY)
# define PROJECTFILESYSTEMPLUGINSHARED_EXPORT Q_DECL_EXPORT
#else
# define PROJECTFILESYSTEMPLUGINSHARED_EXPORT Q_DECL_IMPORT
#endif

View File

@@ -1,10 +1,10 @@
#pragma once
namespace ProjectFilesystemPlugin {
namespace Constants {
const char ACTION_ID[] = "ProjectFilesystemPlugin.Action";
const char MENU_ID[] = "ProjectFilesystemPlugin.Menu";
} // namespace ProjectFilesystemPlugin
} // namespace Constants
#pragma once
namespace ProjectFilesystemPlugin {
namespace Constants {
const char ACTION_ID[] = "ProjectFilesystemPlugin.Action";
const char MENU_ID[] = "ProjectFilesystemPlugin.Menu";
} // namespace ProjectFilesystemPlugin
} // namespace Constants

View File

@@ -1,328 +1,328 @@
#include "projectfilesystemwidget.h"
#include <extensionsystem/pluginmanager.h>
#include <extensionsystem/pluginspec.h>
#include <coreplugin/icore.h>
#include <coreplugin/fileutils.h>
#include <coreplugin/navigationwidget.h>
#include <coreplugin/fileiconprovider.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/editormanager/editormanager.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projecttreewidget.h>
#include <projectexplorer/projecttree.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectnodes.h>
#include <projectexplorer/session.h>
#include <utils/utilsicons.h>
#include <utils/macroexpander.h>
#include <QApplication>
#include <QDesktopServices>
#include <QMessageBox>
#include <QInputDialog>
#include <QScrollBar>
#include <QClipboard>
QFileInfo projectfs_menu_target;
ProjectFilesystemWidget::ProjectFilesystemWidget(QWidget * parent): QWidget(parent) {
setupUi(this);
in_proc = need_rebuild = false;
int is = style()->pixelMetric(QStyle::PM_ButtonIconSize, 0, this);
label->setFixedSize(is, is);
buttonClear->setIcon(Utils::Icons::CLEAN.icon());
buttonExpand->setIcon(Utils::Icons::EXPAND.icon());
buttonCollapse->setIcon(Utils::Icons::COLLAPSE.icon());
actionOpen_here->setIcon(Utils::Icons::OPENFILE.icon());
actionOpen_external->setIcon(Utils::Icons::OPENFILE.icon());
actionShow_external->setIcon(Core::FileIconProvider::icon(QFileIconProvider::Folder));
actionCopy_name->setIcon(Utils::Icons::COPY.icon());
actionCopy_path->setIcon(Utils::Icons::COPY.icon());
popup_menu.addActions(QList<QAction*>() << actionOpen_here << actionOpen_external << actionShow_external << actionOpen_terminal);
popup_menu.addSeparator();
popup_menu.addActions(QList<QAction*>() << actionCopy_name << actionCopy_path);
proj_plug = 0;
//connect(ProjectExplorer::ProjectTree::instance(), SIGNAL(subtreeChanged(ProjectExplorer::FolderNode*)), this, SLOT(projectsChanged()));
connect(ProjectExplorer::SessionManager::instance(), SIGNAL(startupProjectChanged(ProjectExplorer::Project *)), this, SLOT(startupProjectChanged()));
connect(ProjectExplorer::SessionManager::instance(), SIGNAL(projectAdded(ProjectExplorer::Project*)), this, SLOT(projectsChanged()));
connect(ProjectExplorer::SessionManager::instance(), SIGNAL(projectDisplayNameChanged(ProjectExplorer::Project*)), this, SLOT(projectsChanged()));
connect(ProjectExplorer::SessionManager::instance(), SIGNAL(projectRemoved(ProjectExplorer::Project*)), this, SLOT(projectsChanged()));
//connect(ProjectExplorer::SessionManager::instance(), SIGNAL(), this, SLOT(startupProjectChanged()));
connect(Core::EditorManager::instance(), SIGNAL(currentEditorChanged(Core::IEditor*)), this, SLOT(fileChanged()));
projectsChanged();
}
void ProjectFilesystemWidget::setCurrentFilter(const FilterDialog::Filter & v) {
cur_filter = v;
projectsChanged();
}
void ProjectFilesystemWidget::changeEvent(QEvent *e) {
QWidget::changeEvent(e);
switch (e->type()) {
case QEvent::LanguageChange:
retranslateUi(this);
break;
default:
break;
}
}
void ProjectFilesystemWidget::createTree(QTreeWidgetItem * ti, const QString & dir) {
QFileInfoList fl = QDir(dir).entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot, QDir::LocaleAware | QDir::DirsFirst);
checkProcEvents();
for (QFileInfo i: fl) {
QString nit = i.fileName();
if (i.isDir()) {
if (!cur_filter.filterDir(nit))
continue;
} else {
if (!cur_filter.filterFile(nit))
continue;
}
QTreeWidgetItem * ni = new QTreeWidgetItem();
ni->setText(0, nit);
ni->setIcon(0, Core::FileIconProvider::icon(i));
ni->setData(0, Qt::UserRole, i.absoluteFilePath());
ni->setData(0, Qt::UserRole + 1, i.isDir());
item_map[i.absoluteFilePath()] = ni;
if (i.isDir()) {
createTree(ni, dir + QDir::separator() + i.fileName());
}
ti->addChild(ni);
}
//if (ti->childCount() == 0) delete ti;
}
bool ProjectFilesystemWidget::filterTree(QTreeWidgetItem * ti, const QString & filter) {
bool ret = false;
for (int i = 0; i < ti->childCount(); ++i) {
QTreeWidgetItem * ci = ti->child(i);
QString cit = ci->text(0);
if (ci->data(0, Qt::UserRole + 1).toBool()) {
if (!filterTree(ci, filter)) {
ci->setHidden(true);
continue;
}
ci->setHidden(false);
ret = true;
} else {
bool f = false;
if (filter.isEmpty()) {
f = true;
} else {
f = f || cit.contains(filter);
}
ci->setHidden(!f);
if (f) ret = true;
}
}
return ret;
}
void ProjectFilesystemWidget::filter() {
QString f = lineFilter->text();
for (int i = 0; i < tree->topLevelItemCount(); ++i) {
QTreeWidgetItem * ti = tree->topLevelItem(i);
filterTree(ti, f);
}
}
void ProjectFilesystemWidget::rememberExpanded(QTreeWidgetItem * ti) {
//QMessageBox::information(0, ti->data(0, Qt::UserRole).toString(), QString::number(ti->childCount()));
for (int i = 0; i < ti->childCount(); ++i) {
QTreeWidgetItem * ci = ti->child(i);
if (ci->data(0, Qt::UserRole + 1).toBool()) {
if (ci->isExpanded())
last_expanded << ci->data(0, Qt::UserRole).toString();
rememberExpanded(ci);
}
}
}
void ProjectFilesystemWidget::restoreExpanded(QTreeWidgetItem * ti) {
for (int i = 0; i < ti->childCount(); ++i) {
QTreeWidgetItem * ci = ti->child(i);
if (ci->data(0, Qt::UserRole + 1).toBool()) {
if (last_expanded.contains(ci->data(0, Qt::UserRole).toString()))
ci->setExpanded(true);
restoreExpanded(ci);
}
}
}
void ProjectFilesystemWidget::setExtVariable() {
}
void ProjectFilesystemWidget::checkProcEvents() {
if (tm.elapsed() < 10) return;
QApplication::processEvents();
tm.start();
}
void ProjectFilesystemWidget::projectsChanged() {
if (in_proc) {
need_rebuild = true;
return;
}
in_proc = true;
tm.start();
last_expanded.clear();
item_map.clear();
int spos = tree->verticalScrollBar()->value();
rememberExpanded(tree->invisibleRootItem());
tree->clear();
QApplication::setOverrideCursor(Qt::WaitCursor);
QList<ProjectExplorer::Project *> pl = ProjectExplorer::SessionManager::projects();
for (ProjectExplorer::Project * p: pl) {
QTreeWidgetItem * ri = new QTreeWidgetItem();
QString dir = p->projectDirectory().toString();
ri->setText(0, p->displayName());
QFile logo(dir + "/logo.png");
if (logo.exists())
ri->setIcon(0, QIcon(logo.fileName()));
else
ri->setIcon(0, Core::FileIconProvider::icon(QFileIconProvider::Folder));
ri->setData(0, Qt::UserRole, dir);
ri->setData(0, Qt::UserRole + 1, true);
createTree(ri, dir);
tree->addTopLevelItem(ri);
}
startupProjectChanged();
fileChanged();
filter();
restoreExpanded(tree->invisibleRootItem());
QApplication::restoreOverrideCursor();
qApp->processEvents();
tree->verticalScrollBar()->setValue(spos);
in_proc = false;
if (need_rebuild) {
need_rebuild = false;
projectsChanged();
}
}
void ProjectFilesystemWidget::filterClicked() {
filter_dialog.setFilter(cur_filter);
if (filter_dialog.exec() == QDialog::Rejected) return;
setCurrentFilter(filter_dialog.filter());
}
void ProjectFilesystemWidget::fileChanged() {
Core::IDocument * cd = Core::EditorManager::instance()->currentDocument();
if (!cd) return;
QString np = cd->filePath().toString();
QTreeWidgetItem * ti = item_map.value(np);
if (!ti) return;
tree->setCurrentItem(ti);
tree->expandItem(ti);
}
void ProjectFilesystemWidget::startupProjectChanged() {
ProjectExplorer::Project * sp = ProjectExplorer::SessionManager::startupProject();
QFont f(tree->font()), bf(f);
bf.setBold(true);
for (int i = 0; i < tree->topLevelItemCount(); ++i) {
QTreeWidgetItem * ti = tree->topLevelItem(i);
ti->setFont(0, f);
if (!sp) continue;
if (sp->projectDirectory().toString() == ti->data(0, Qt::UserRole).toString())
ti->setFont(0, bf);
}
}
void ProjectFilesystemWidget::on_tree_itemDoubleClicked(QTreeWidgetItem * item, int) {
if (!item) return;
QString afp = item->data(0, Qt::UserRole).toString();
bool dir = item->data(0, Qt::UserRole + 1).toBool();
if (dir) return;
if (afp.isEmpty()) return;
Core::EditorManager::openEditor(afp);
}
void ProjectFilesystemWidget::on_lineFilter_textChanged(const QString & ) {
filter();
}
void ProjectFilesystemWidget::on_tree_itemClicked(QTreeWidgetItem * item, int column) {
projectfs_menu_target = QFileInfo();
if (!item) {
setExtVariable();
return;
}
projectfs_menu_target = QFileInfo(item->data(0, Qt::UserRole).toString());
setExtVariable();
}
void ProjectFilesystemWidget::on_tree_customContextMenuRequested(const QPoint & pos) {
projectfs_menu_target = QFileInfo();
QTreeWidgetItem * item = tree->itemAt(pos);
//QMessageBox::information(this, "", QString::number(index.row()));
if (!item) {
setExtVariable();
return;
}
projectfs_menu_target = QFileInfo(item->data(0, Qt::UserRole).toString());
setExtVariable();
actionOpen_here->setEnabled(!projectfs_menu_target.isDir());
actionOpen_external->setEnabled(!projectfs_menu_target.isDir());
popup_menu.popup(tree->mapToGlobal(pos));
}
void ProjectFilesystemWidget::on_actionOpen_here_triggered() {
if (projectfs_menu_target.path().isEmpty()) return;
Core::EditorManager::openEditor(projectfs_menu_target.absoluteFilePath(), Core::Constants::K_DEFAULT_TEXT_EDITOR_ID);
}
void ProjectFilesystemWidget::on_actionOpen_external_triggered() {
if (projectfs_menu_target.path().isEmpty()) return;
QString wd = QDir::current().absolutePath();
QDir::setCurrent(projectfs_menu_target.absoluteDir().path());
QDesktopServices::openUrl(QUrl::fromLocalFile(projectfs_menu_target.absoluteFilePath()));
QDir::setCurrent(wd);
}
void ProjectFilesystemWidget::on_actionShow_external_triggered() {
if (projectfs_menu_target.path().isEmpty()) return;
Core::FileUtils::showInGraphicalShell(Core::ICore::mainWindow(), projectfs_menu_target.absoluteFilePath());
}
void ProjectFilesystemWidget::on_actionOpen_terminal_triggered() {
if (projectfs_menu_target.path().isEmpty()) return;
Core::FileUtils::openTerminal(QDir(projectfs_menu_target.absoluteFilePath()).path());
}
void ProjectFilesystemWidget::on_actionCopy_name_triggered() {
if (projectfs_menu_target.path().isEmpty()) return;
QApplication::clipboard()->setText(projectfs_menu_target.fileName());
}
void ProjectFilesystemWidget::on_actionCopy_path_triggered() {
if (projectfs_menu_target.path().isEmpty()) return;
QApplication::clipboard()->setText(projectfs_menu_target.absoluteFilePath());
}
#include "projectfilesystemwidget.h"
#include <extensionsystem/pluginmanager.h>
#include <extensionsystem/pluginspec.h>
#include <coreplugin/icore.h>
#include <coreplugin/fileutils.h>
#include <coreplugin/navigationwidget.h>
#include <coreplugin/fileiconprovider.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/editormanager/editormanager.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projecttreewidget.h>
#include <projectexplorer/projecttree.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectnodes.h>
#include <projectexplorer/session.h>
#include <utils/utilsicons.h>
#include <utils/macroexpander.h>
#include <QApplication>
#include <QDesktopServices>
#include <QMessageBox>
#include <QInputDialog>
#include <QScrollBar>
#include <QClipboard>
QFileInfo projectfs_menu_target;
ProjectFilesystemWidget::ProjectFilesystemWidget(QWidget * parent): QWidget(parent) {
setupUi(this);
in_proc = need_rebuild = false;
int is = style()->pixelMetric(QStyle::PM_ButtonIconSize, 0, this);
label->setFixedSize(is, is);
buttonClear->setIcon(Utils::Icons::CLEAN.icon());
buttonExpand->setIcon(Utils::Icons::EXPAND.icon());
buttonCollapse->setIcon(Utils::Icons::COLLAPSE.icon());
actionOpen_here->setIcon(Utils::Icons::OPENFILE.icon());
actionOpen_external->setIcon(Utils::Icons::OPENFILE.icon());
actionShow_external->setIcon(Core::FileIconProvider::icon(QFileIconProvider::Folder));
actionCopy_name->setIcon(Utils::Icons::COPY.icon());
actionCopy_path->setIcon(Utils::Icons::COPY.icon());
popup_menu.addActions(QList<QAction*>() << actionOpen_here << actionOpen_external << actionShow_external << actionOpen_terminal);
popup_menu.addSeparator();
popup_menu.addActions(QList<QAction*>() << actionCopy_name << actionCopy_path);
proj_plug = 0;
//connect(ProjectExplorer::ProjectTree::instance(), SIGNAL(subtreeChanged(ProjectExplorer::FolderNode*)), this, SLOT(projectsChanged()));
connect(ProjectExplorer::SessionManager::instance(), SIGNAL(startupProjectChanged(ProjectExplorer::Project *)), this, SLOT(startupProjectChanged()));
connect(ProjectExplorer::SessionManager::instance(), SIGNAL(projectAdded(ProjectExplorer::Project*)), this, SLOT(projectsChanged()));
connect(ProjectExplorer::SessionManager::instance(), SIGNAL(projectDisplayNameChanged(ProjectExplorer::Project*)), this, SLOT(projectsChanged()));
connect(ProjectExplorer::SessionManager::instance(), SIGNAL(projectRemoved(ProjectExplorer::Project*)), this, SLOT(projectsChanged()));
//connect(ProjectExplorer::SessionManager::instance(), SIGNAL(), this, SLOT(startupProjectChanged()));
connect(Core::EditorManager::instance(), SIGNAL(currentEditorChanged(Core::IEditor*)), this, SLOT(fileChanged()));
projectsChanged();
}
void ProjectFilesystemWidget::setCurrentFilter(const FilterDialog::Filter & v) {
cur_filter = v;
projectsChanged();
}
void ProjectFilesystemWidget::changeEvent(QEvent *e) {
QWidget::changeEvent(e);
switch (e->type()) {
case QEvent::LanguageChange:
retranslateUi(this);
break;
default:
break;
}
}
void ProjectFilesystemWidget::createTree(QTreeWidgetItem * ti, const QString & dir) {
QFileInfoList fl = QDir(dir).entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot, QDir::LocaleAware | QDir::DirsFirst);
checkProcEvents();
for (QFileInfo i: fl) {
QString nit = i.fileName();
if (i.isDir()) {
if (!cur_filter.filterDir(nit))
continue;
} else {
if (!cur_filter.filterFile(nit))
continue;
}
QTreeWidgetItem * ni = new QTreeWidgetItem();
ni->setText(0, nit);
ni->setIcon(0, Core::FileIconProvider::icon(i));
ni->setData(0, Qt::UserRole, i.absoluteFilePath());
ni->setData(0, Qt::UserRole + 1, i.isDir());
item_map[i.absoluteFilePath()] = ni;
if (i.isDir()) {
createTree(ni, dir + QDir::separator() + i.fileName());
}
ti->addChild(ni);
}
//if (ti->childCount() == 0) delete ti;
}
bool ProjectFilesystemWidget::filterTree(QTreeWidgetItem * ti, const QString & filter) {
bool ret = false;
for (int i = 0; i < ti->childCount(); ++i) {
QTreeWidgetItem * ci = ti->child(i);
QString cit = ci->text(0);
if (ci->data(0, Qt::UserRole + 1).toBool()) {
if (!filterTree(ci, filter)) {
ci->setHidden(true);
continue;
}
ci->setHidden(false);
ret = true;
} else {
bool f = false;
if (filter.isEmpty()) {
f = true;
} else {
f = f || cit.contains(filter);
}
ci->setHidden(!f);
if (f) ret = true;
}
}
return ret;
}
void ProjectFilesystemWidget::filter() {
QString f = lineFilter->text();
for (int i = 0; i < tree->topLevelItemCount(); ++i) {
QTreeWidgetItem * ti = tree->topLevelItem(i);
filterTree(ti, f);
}
}
void ProjectFilesystemWidget::rememberExpanded(QTreeWidgetItem * ti) {
//QMessageBox::information(0, ti->data(0, Qt::UserRole).toString(), QString::number(ti->childCount()));
for (int i = 0; i < ti->childCount(); ++i) {
QTreeWidgetItem * ci = ti->child(i);
if (ci->data(0, Qt::UserRole + 1).toBool()) {
if (ci->isExpanded())
last_expanded << ci->data(0, Qt::UserRole).toString();
rememberExpanded(ci);
}
}
}
void ProjectFilesystemWidget::restoreExpanded(QTreeWidgetItem * ti) {
for (int i = 0; i < ti->childCount(); ++i) {
QTreeWidgetItem * ci = ti->child(i);
if (ci->data(0, Qt::UserRole + 1).toBool()) {
if (last_expanded.contains(ci->data(0, Qt::UserRole).toString()))
ci->setExpanded(true);
restoreExpanded(ci);
}
}
}
void ProjectFilesystemWidget::setExtVariable() {
}
void ProjectFilesystemWidget::checkProcEvents() {
if (tm.elapsed() < 10) return;
QApplication::processEvents();
tm.start();
}
void ProjectFilesystemWidget::projectsChanged() {
if (in_proc) {
need_rebuild = true;
return;
}
in_proc = true;
tm.start();
last_expanded.clear();
item_map.clear();
int spos = tree->verticalScrollBar()->value();
rememberExpanded(tree->invisibleRootItem());
tree->clear();
QApplication::setOverrideCursor(Qt::WaitCursor);
QList<ProjectExplorer::Project *> pl = ProjectExplorer::SessionManager::projects();
for (ProjectExplorer::Project * p: pl) {
QTreeWidgetItem * ri = new QTreeWidgetItem();
QString dir = p->projectDirectory().toString();
ri->setText(0, p->displayName());
QFile logo(dir + "/logo.png");
if (logo.exists())
ri->setIcon(0, QIcon(logo.fileName()));
else
ri->setIcon(0, Core::FileIconProvider::icon(QFileIconProvider::Folder));
ri->setData(0, Qt::UserRole, dir);
ri->setData(0, Qt::UserRole + 1, true);
createTree(ri, dir);
tree->addTopLevelItem(ri);
}
startupProjectChanged();
fileChanged();
filter();
restoreExpanded(tree->invisibleRootItem());
QApplication::restoreOverrideCursor();
qApp->processEvents();
tree->verticalScrollBar()->setValue(spos);
in_proc = false;
if (need_rebuild) {
need_rebuild = false;
projectsChanged();
}
}
void ProjectFilesystemWidget::filterClicked() {
filter_dialog.setFilter(cur_filter);
if (filter_dialog.exec() == QDialog::Rejected) return;
setCurrentFilter(filter_dialog.filter());
}
void ProjectFilesystemWidget::fileChanged() {
Core::IDocument * cd = Core::EditorManager::instance()->currentDocument();
if (!cd) return;
QString np = cd->filePath().toString();
QTreeWidgetItem * ti = item_map.value(np);
if (!ti) return;
tree->setCurrentItem(ti);
tree->expandItem(ti);
}
void ProjectFilesystemWidget::startupProjectChanged() {
ProjectExplorer::Project * sp = ProjectExplorer::SessionManager::startupProject();
QFont f(tree->font()), bf(f);
bf.setBold(true);
for (int i = 0; i < tree->topLevelItemCount(); ++i) {
QTreeWidgetItem * ti = tree->topLevelItem(i);
ti->setFont(0, f);
if (!sp) continue;
if (sp->projectDirectory().toString() == ti->data(0, Qt::UserRole).toString())
ti->setFont(0, bf);
}
}
void ProjectFilesystemWidget::on_tree_itemDoubleClicked(QTreeWidgetItem * item, int) {
if (!item) return;
QString afp = item->data(0, Qt::UserRole).toString();
bool dir = item->data(0, Qt::UserRole + 1).toBool();
if (dir) return;
if (afp.isEmpty()) return;
Core::EditorManager::openEditor(afp);
}
void ProjectFilesystemWidget::on_lineFilter_textChanged(const QString & ) {
filter();
}
void ProjectFilesystemWidget::on_tree_itemClicked(QTreeWidgetItem * item, int column) {
projectfs_menu_target = QFileInfo();
if (!item) {
setExtVariable();
return;
}
projectfs_menu_target = QFileInfo(item->data(0, Qt::UserRole).toString());
setExtVariable();
}
void ProjectFilesystemWidget::on_tree_customContextMenuRequested(const QPoint & pos) {
projectfs_menu_target = QFileInfo();
QTreeWidgetItem * item = tree->itemAt(pos);
//QMessageBox::information(this, "", QString::number(index.row()));
if (!item) {
setExtVariable();
return;
}
projectfs_menu_target = QFileInfo(item->data(0, Qt::UserRole).toString());
setExtVariable();
actionOpen_here->setEnabled(!projectfs_menu_target.isDir());
actionOpen_external->setEnabled(!projectfs_menu_target.isDir());
popup_menu.popup(tree->mapToGlobal(pos));
}
void ProjectFilesystemWidget::on_actionOpen_here_triggered() {
if (projectfs_menu_target.path().isEmpty()) return;
Core::EditorManager::openEditor(projectfs_menu_target.absoluteFilePath(), Core::Constants::K_DEFAULT_TEXT_EDITOR_ID);
}
void ProjectFilesystemWidget::on_actionOpen_external_triggered() {
if (projectfs_menu_target.path().isEmpty()) return;
QString wd = QDir::current().absolutePath();
QDir::setCurrent(projectfs_menu_target.absoluteDir().path());
QDesktopServices::openUrl(QUrl::fromLocalFile(projectfs_menu_target.absoluteFilePath()));
QDir::setCurrent(wd);
}
void ProjectFilesystemWidget::on_actionShow_external_triggered() {
if (projectfs_menu_target.path().isEmpty()) return;
Core::FileUtils::showInGraphicalShell(Core::ICore::mainWindow(), projectfs_menu_target.absoluteFilePath());
}
void ProjectFilesystemWidget::on_actionOpen_terminal_triggered() {
if (projectfs_menu_target.path().isEmpty()) return;
Core::FileUtils::openTerminal(QDir(projectfs_menu_target.absoluteFilePath()).path());
}
void ProjectFilesystemWidget::on_actionCopy_name_triggered() {
if (projectfs_menu_target.path().isEmpty()) return;
QApplication::clipboard()->setText(projectfs_menu_target.fileName());
}
void ProjectFilesystemWidget::on_actionCopy_path_triggered() {
if (projectfs_menu_target.path().isEmpty()) return;
QApplication::clipboard()->setText(projectfs_menu_target.absoluteFilePath());
}

View File

@@ -1,68 +1,68 @@
#ifndef PROJECTFILESYSTEMWIDGET_H
#define PROJECTFILESYSTEMWIDGET_H
#include "ui_projectfilesystemwidget.h"
#include "filterdialog.h"
#include <extensionsystem/iplugin.h>
#include <QSortFilterProxyModel>
#include <QFileSystemModel>
#include <QElapsedTimer>
#include <QMenu>
extern QFileInfo projectfs_menu_target;
class ProjectsModel;
class ProjectFilesystemWidget: public QWidget, private Ui::ProjectFilesystemWidget
{
Q_OBJECT
public:
explicit ProjectFilesystemWidget(QWidget * parent = 0);
FilterDialog::Filter currentFilters() const {return cur_filter;}
QString currentSearch() const {return lineFilter->text();}
void setCurrentFilter(const FilterDialog::Filter & v);
void setCurrentSearch(QString v) {lineFilter->setText(v);}
protected:
void changeEvent(QEvent * e);
void createTree(QTreeWidgetItem * ti, const QString & dir);
bool filterTree(QTreeWidgetItem * ti, const QString & filter);
void filter();
void rememberExpanded(QTreeWidgetItem * ti);
void restoreExpanded(QTreeWidgetItem * ti);
void setExtVariable();
void checkProcEvents();
bool in_proc, need_rebuild;
ExtensionSystem::IPlugin * proj_plug;
QMenu popup_menu;
QMap<QString, QTreeWidgetItem*> item_map;
QSet<QString> last_expanded;
FilterDialog filter_dialog;
FilterDialog::Filter cur_filter;
QElapsedTimer tm;
public slots:
void projectsChanged();
void filterClicked();
private slots:
void fileChanged();
void startupProjectChanged();
void on_tree_itemDoubleClicked(QTreeWidgetItem * item, int );
void on_lineFilter_textChanged(const QString &);
void on_tree_itemClicked(QTreeWidgetItem *item, int column);
void on_tree_customContextMenuRequested(const QPoint & pos);
void on_actionOpen_here_triggered();
void on_actionOpen_external_triggered();
void on_actionShow_external_triggered();
void on_actionOpen_terminal_triggered();
void on_actionCopy_name_triggered();
void on_actionCopy_path_triggered();
};
#endif // PROJECTFILESYSTEMWIDGET_H
#ifndef PROJECTFILESYSTEMWIDGET_H
#define PROJECTFILESYSTEMWIDGET_H
#include "ui_projectfilesystemwidget.h"
#include "filterdialog.h"
#include <extensionsystem/iplugin.h>
#include <QSortFilterProxyModel>
#include <QFileSystemModel>
#include <QElapsedTimer>
#include <QMenu>
extern QFileInfo projectfs_menu_target;
class ProjectsModel;
class ProjectFilesystemWidget: public QWidget, private Ui::ProjectFilesystemWidget
{
Q_OBJECT
public:
explicit ProjectFilesystemWidget(QWidget * parent = 0);
FilterDialog::Filter currentFilters() const {return cur_filter;}
QString currentSearch() const {return lineFilter->text();}
void setCurrentFilter(const FilterDialog::Filter & v);
void setCurrentSearch(QString v) {lineFilter->setText(v);}
protected:
void changeEvent(QEvent * e);
void createTree(QTreeWidgetItem * ti, const QString & dir);
bool filterTree(QTreeWidgetItem * ti, const QString & filter);
void filter();
void rememberExpanded(QTreeWidgetItem * ti);
void restoreExpanded(QTreeWidgetItem * ti);
void setExtVariable();
void checkProcEvents();
bool in_proc, need_rebuild;
ExtensionSystem::IPlugin * proj_plug;
QMenu popup_menu;
QMap<QString, QTreeWidgetItem*> item_map;
QSet<QString> last_expanded;
FilterDialog filter_dialog;
FilterDialog::Filter cur_filter;
QElapsedTimer tm;
public slots:
void projectsChanged();
void filterClicked();
private slots:
void fileChanged();
void startupProjectChanged();
void on_tree_itemDoubleClicked(QTreeWidgetItem * item, int );
void on_lineFilter_textChanged(const QString &);
void on_tree_itemClicked(QTreeWidgetItem *item, int column);
void on_tree_customContextMenuRequested(const QPoint & pos);
void on_actionOpen_here_triggered();
void on_actionOpen_external_triggered();
void on_actionShow_external_triggered();
void on_actionOpen_terminal_triggered();
void on_actionCopy_name_triggered();
void on_actionCopy_path_triggered();
};
#endif // PROJECTFILESYSTEMWIDGET_H

View File

@@ -1,183 +1,183 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ProjectFilesystemWidget</class>
<widget class="QWidget" name="ProjectFilesystemWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>386</width>
<height>390</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="pixmap">
<pixmap resource="projectfilesystem.qrc">:/icons/edit-find.png</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineFilter"/>
</item>
<item>
<widget class="QToolButton" name="buttonClear"/>
</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="QToolButton" name="buttonExpand">
<property name="toolTip">
<string>Expand tree</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="buttonCollapse">
<property name="toolTip">
<string>Collapse tree</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QTreeWidget" name="tree">
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="textElideMode">
<enum>Qt::ElideMiddle</enum>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="rootIsDecorated">
<bool>true</bool>
</property>
<property name="uniformRowHeights">
<bool>true</bool>
</property>
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string>Path</string>
</property>
</column>
</widget>
</item>
</layout>
<action name="actionOpen_here">
<property name="text">
<string>Open as plain</string>
</property>
</action>
<action name="actionOpen_external">
<property name="text">
<string>Open external ...</string>
</property>
</action>
<action name="actionShow_external">
<property name="text">
<string>Show external ...</string>
</property>
</action>
<action name="actionCopy_name">
<property name="text">
<string>Copy name</string>
</property>
</action>
<action name="actionCopy_path">
<property name="text">
<string>Copy path</string>
</property>
</action>
<action name="actionOpen_terminal">
<property name="icon">
<iconset resource="projectfilesystem.qrc">
<normaloff>:/icons/utilities-terminal.png</normaloff>:/icons/utilities-terminal.png</iconset>
</property>
<property name="text">
<string>Open terminal ...</string>
</property>
</action>
</widget>
<resources>
<include location="projectfilesystem.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonClear</sender>
<signal>clicked()</signal>
<receiver>lineFilter</receiver>
<slot>clear()</slot>
<hints>
<hint type="sourcelabel">
<x>246</x>
<y>37</y>
</hint>
<hint type="destinationlabel">
<x>212</x>
<y>35</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonExpand</sender>
<signal>clicked()</signal>
<receiver>tree</receiver>
<slot>expandAll()</slot>
<hints>
<hint type="sourcelabel">
<x>263</x>
<y>28</y>
</hint>
<hint type="destinationlabel">
<x>251</x>
<y>58</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonCollapse</sender>
<signal>clicked()</signal>
<receiver>tree</receiver>
<slot>collapseAll()</slot>
<hints>
<hint type="sourcelabel">
<x>307</x>
<y>27</y>
</hint>
<hint type="destinationlabel">
<x>297</x>
<y>71</y>
</hint>
</hints>
</connection>
</connections>
</ui>
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ProjectFilesystemWidget</class>
<widget class="QWidget" name="ProjectFilesystemWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>386</width>
<height>390</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="pixmap">
<pixmap resource="projectfilesystem.qrc">:/icons/edit-find.png</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineFilter"/>
</item>
<item>
<widget class="QToolButton" name="buttonClear"/>
</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="QToolButton" name="buttonExpand">
<property name="toolTip">
<string>Expand tree</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="buttonCollapse">
<property name="toolTip">
<string>Collapse tree</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QTreeWidget" name="tree">
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="textElideMode">
<enum>Qt::ElideMiddle</enum>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="rootIsDecorated">
<bool>true</bool>
</property>
<property name="uniformRowHeights">
<bool>true</bool>
</property>
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string>Path</string>
</property>
</column>
</widget>
</item>
</layout>
<action name="actionOpen_here">
<property name="text">
<string>Open as plain</string>
</property>
</action>
<action name="actionOpen_external">
<property name="text">
<string>Open external ...</string>
</property>
</action>
<action name="actionShow_external">
<property name="text">
<string>Show external ...</string>
</property>
</action>
<action name="actionCopy_name">
<property name="text">
<string>Copy name</string>
</property>
</action>
<action name="actionCopy_path">
<property name="text">
<string>Copy path</string>
</property>
</action>
<action name="actionOpen_terminal">
<property name="icon">
<iconset resource="projectfilesystem.qrc">
<normaloff>:/icons/utilities-terminal.png</normaloff>:/icons/utilities-terminal.png</iconset>
</property>
<property name="text">
<string>Open terminal ...</string>
</property>
</action>
</widget>
<resources>
<include location="projectfilesystem.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonClear</sender>
<signal>clicked()</signal>
<receiver>lineFilter</receiver>
<slot>clear()</slot>
<hints>
<hint type="sourcelabel">
<x>246</x>
<y>37</y>
</hint>
<hint type="destinationlabel">
<x>212</x>
<y>35</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonExpand</sender>
<signal>clicked()</signal>
<receiver>tree</receiver>
<slot>expandAll()</slot>
<hints>
<hint type="sourcelabel">
<x>263</x>
<y>28</y>
</hint>
<hint type="destinationlabel">
<x>251</x>
<y>58</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonCollapse</sender>
<signal>clicked()</signal>
<receiver>tree</receiver>
<slot>collapseAll()</slot>
<hints>
<hint type="sourcelabel">
<x>307</x>
<y>27</y>
</hint>
<hint type="destinationlabel">
<x>297</x>
<y>71</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -1,57 +1,57 @@
#include "projectfilesystemwidgetplugin.h"
#include "projectfilesystemwidget.h"
#include <utils/utilsicons.h>
#include <QToolButton>
#include <QSettings>
#include <QMessageBox>
ProjectFSWidgetFactory::ProjectFSWidgetFactory() {
setDisplayName(QString::fromLatin1("Project filesystem"));
setId("project_filesystem");
}
Core::NavigationView ProjectFSWidgetFactory::createWidget() {
Core::NavigationView view;
view.widget = new ProjectFilesystemWidget();
QToolButton * btn = new QToolButton();
btn->setIcon(Utils::Icons::RELOAD.icon());
btn->setToolTip(tr("Reload tree"));
view.dockToolBarWidgets << btn;
connect(btn, SIGNAL(clicked()), view.widget, SLOT(projectsChanged()));
btn = new QToolButton();
btn->setIcon(Utils::Icons::FILTER.icon());
btn->setToolTip(tr("Setup filters ..."));
view.dockToolBarWidgets << btn;
connect(btn, SIGNAL(clicked()), view.widget, SLOT(filterClicked()));
return view;
}
void ProjectFSWidgetFactory::saveSettings(QSettings * settings, int position, QWidget * widget) {
//QMessageBox::information(0, "", QString::fromLatin1(widget->metaObject()->className()));
ProjectFilesystemWidget * w = qobject_cast<ProjectFilesystemWidget * >(widget);
if (!w) return;
settings->beginGroup("ProjectFilesystem");
settings->beginWriteArray("widget");
settings->setArrayIndex(position);
settings->setValue("filters", w->currentFilters().toVariant());
settings->setValue("search", w->currentSearch());
settings->endArray();
settings->endGroup();
settings->sync();
}
void ProjectFSWidgetFactory::restoreSettings(QSettings * settings, int position, QWidget * widget) {
ProjectFilesystemWidget * w = qobject_cast<ProjectFilesystemWidget * >(widget);
if (!w) return;
settings->beginGroup("ProjectFilesystem");
settings->beginReadArray("widget");
settings->setArrayIndex(position);
w->setCurrentFilter(FilterDialog::Filter(settings->value("filters", FilterDialog::Filter().toVariant())));
w->setCurrentSearch(settings->value("search", QString()).toString());
settings->endArray();
settings->endGroup();
}
#include "projectfilesystemwidgetplugin.h"
#include "projectfilesystemwidget.h"
#include <utils/utilsicons.h>
#include <QToolButton>
#include <QSettings>
#include <QMessageBox>
ProjectFSWidgetFactory::ProjectFSWidgetFactory() {
setDisplayName(QString::fromLatin1("Project filesystem"));
setId("project_filesystem");
}
Core::NavigationView ProjectFSWidgetFactory::createWidget() {
Core::NavigationView view;
view.widget = new ProjectFilesystemWidget();
QToolButton * btn = new QToolButton();
btn->setIcon(Utils::Icons::RELOAD.icon());
btn->setToolTip(tr("Reload tree"));
view.dockToolBarWidgets << btn;
connect(btn, SIGNAL(clicked()), view.widget, SLOT(projectsChanged()));
btn = new QToolButton();
btn->setIcon(Utils::Icons::FILTER.icon());
btn->setToolTip(tr("Setup filters ..."));
view.dockToolBarWidgets << btn;
connect(btn, SIGNAL(clicked()), view.widget, SLOT(filterClicked()));
return view;
}
void ProjectFSWidgetFactory::saveSettings(QSettings * settings, int position, QWidget * widget) {
//QMessageBox::information(0, "", QString::fromLatin1(widget->metaObject()->className()));
ProjectFilesystemWidget * w = qobject_cast<ProjectFilesystemWidget * >(widget);
if (!w) return;
settings->beginGroup("ProjectFilesystem");
settings->beginWriteArray("widget");
settings->setArrayIndex(position);
settings->setValue("filters", w->currentFilters().toVariant());
settings->setValue("search", w->currentSearch());
settings->endArray();
settings->endGroup();
settings->sync();
}
void ProjectFSWidgetFactory::restoreSettings(QSettings * settings, int position, QWidget * widget) {
ProjectFilesystemWidget * w = qobject_cast<ProjectFilesystemWidget * >(widget);
if (!w) return;
settings->beginGroup("ProjectFilesystem");
settings->beginReadArray("widget");
settings->setArrayIndex(position);
w->setCurrentFilter(FilterDialog::Filter(settings->value("filters", FilterDialog::Filter().toVariant())));
w->setCurrentSearch(settings->value("search", QString()).toString());
settings->endArray();
settings->endGroup();
}

View File

@@ -1,18 +1,18 @@
#pragma once
#include <coreplugin/inavigationwidgetfactory.h>
#include <QTableWidget>
class ProjectFSWidgetFactory: public Core::INavigationWidgetFactory
{
public:
ProjectFSWidgetFactory();
~ProjectFSWidgetFactory() {}
Core::NavigationView createWidget();
void saveSettings(QSettings * settings, int position, QWidget * widget);
void restoreSettings(QSettings * settings, int position, QWidget * widget);
};
#pragma once
#include <coreplugin/inavigationwidgetfactory.h>
#include <QTableWidget>
class ProjectFSWidgetFactory: public Core::INavigationWidgetFactory
{
public:
ProjectFSWidgetFactory();
~ProjectFSWidgetFactory() {}
Core::NavigationView createWidget();
void saveSettings(QSettings * settings, int position, QWidget * widget);
void restoreSettings(QSettings * settings, int position, QWidget * widget);
};

View File

@@ -1,89 +1,40 @@
cmake_minimum_required(VERSION 3.0)
cmake_policy(SET CMP0017 NEW) # need include() with .cmake
project(qad)
set(_QAD_MAJOR 1)
set(_QAD_MINOR 7)
set(_QAD_REVISION 0)
set(_QAD_SUFFIX )
set(_QAD_COMPANY SHS)
set(_QAD_DOMAIN org.SHS)
include(QADMacros)
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
if(STATIC_LIB)
set(QAD_LIB_TYPE STATIC)
add_definitions(-DQAD_STATIC_DEFINE)
else()
set(QAD_LIB_TYPE SHARED)
endif()
if (NOT DEFINED ANDROID_PLATFORM)
find_package(OpenGL REQUIRED)
endif()
if (MINGW)
find_package(MinGW REQUIRED)
endif()
# Version
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/qad_version.h")
file(REMOVE "${CMAKE_CURRENT_SOURCE_DIR}/qad_version.h")
endif()
set(QAD_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/qad_version.h")
set_version(QAD
MAJOR "${_QAD_MAJOR}"
MINOR "${_QAD_MINOR}"
REVISION "${_QAD_REVISION}"
BUILD "${BUILD_NUMBER}"
SUFFIX "${_QAD_SUFFIX}"
OUTPUT "${QAD_VERSION_FILE}")
set_deploy_property(QAD ${QAD_LIB_TYPE}
FULLNAME "${_QAD_DOMAIN}.*"
COMPANY "${_QAD_COMPANY}")
message(STATUS "Building QAD version ${QAD_VERSION} (${QAD_LIB_TYPE})")
if (NOT LIBPROJECT)
if (LIB)
if(WIN32)
if(MINGW)
set(CMAKE_INSTALL_PREFIX ${MINGW_DIR})
endif()
else()
if (DEFINED ANDROID_PLATFORM)
set(CMAKE_INSTALL_PREFIX ${ANDROID_SYSTEM_LIBRARY_PATH}/usr)
else()
set(CMAKE_INSTALL_PREFIX /usr/local)
endif()
endif()
message(STATUS "Install ${PROJECT_NAME} to system \"${CMAKE_INSTALL_PREFIX}\"")
else()
message(STATUS "Install ${PROJECT_NAME} to local \"bin\", \"lib\" and \"include\"")
endif()
endif()
file(GLOB CMAKES "cmake/*.cmake" "cmake/*.in")
if (LIB)
install(FILES ${CMAKES} DESTINATION ${CMAKE_ROOT}/Modules)
if (WIN32)
install(FILES ${QAD_VERSION_FILE} DESTINATION ${MINGW_INCLUDE}/qad)
else()
install(FILES ${QAD_VERSION_FILE} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/qad)
endif()
else()
install(FILES ${QAD_VERSION_FILE} DESTINATION include/qad)
endif()
add_subdirectory(libs)
if (UTILS)
add_subdirectory(utils)
endif()
set(QT_MULTILIB_LIST ${QT_MULTILIB_LIST} PARENT_SCOPE)
set(qad_includes ${qad_includes} PARENT_SCOPE)
if (LIB)
set(_ALL_TARGETS ${_ALL_TARGETS} PARENT_SCOPE)
endif()
cmake_minimum_required(VERSION 3.0)
cmake_policy(SET CMP0017 NEW) # need include() with .cmake
project(qad)
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
if (NOT DEFINED ANDROID_PLATFORM)
find_package(OpenGL REQUIRED)
endif()
if (MINGW)
find_package(MinGW REQUIRED)
endif()
# Version
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/qad_version.h")
file(REMOVE "${CMAKE_CURRENT_SOURCE_DIR}/qad_version.h")
endif()
#message(STATUS "Building QAD version ${QAD_VERSION} (${QAD_LIB_TYPE})")
file(GLOB CMAKES "cmake/*.cmake" "cmake/*.in")
if (LIB)
install(FILES ${CMAKES} DESTINATION ${CMAKE_ROOT}/Modules)
if (WIN32)
install(FILES ${QAD_VERSION_FILE} DESTINATION ${MINGW_INCLUDE}/qad)
else()
install(FILES ${QAD_VERSION_FILE} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/qad)
endif()
else()
install(FILES ${QAD_VERSION_FILE} DESTINATION include/qad)
endif()
add_subdirectory(libs)
if (UTILS)
add_subdirectory(utils)
endif()
copy_to_parent(qad_includes)

View File

@@ -4,10 +4,10 @@ macro(_qt_install _TARGET IS_APP _DIR _HDR_VAR _QM_FILES)
endmacro()
macro(qad_plugin NAME _MODULES _LIBS)
macro(_qt_plugin NAME _MODULES _LIBS)
if (NOT STATIC_LIB)
if(DESIGNER_PLUGINS)
set(PROJ_NAME qad_${NAME}_plugin)
set(PROJ_NAME ${NAME}_plugin)
include_directories("..")
add_definitions(-DQT_PLUGIN)
add_definitions(-DQT_NO_DEBUG)
@@ -17,12 +17,14 @@ macro(qad_plugin NAME _MODULES _LIBS)
qt_sources(SRC)
qt_wrap(${SRC} CPPS out_CPP QMS out_QM)
qt_add_library(${PROJ_NAME} SHARED out_CPP)
qt_target_link_libraries(${PROJ_NAME} ${_LIBS} qad_${NAME} ${_${NAME}_PLUGIN_LIBS})
qt_target_link_libraries(${PROJ_NAME} ${_LIBS} ${_${NAME}_PLUGIN_LIBS})
if (WIN32)
qt_install(TARGETS ${PROJ_NAME} RUNTIME DESTINATION QtPlugins/designer)
else()
qt_install(TARGETS ${PROJ_NAME} DESTINATION QtPlugins/designer)
endif()
list(APPEND _qt_plugs ${NAME})
copy_to_parent("")
endif()
endif()
endmacro()
@@ -35,12 +37,14 @@ macro(_qt_project NAME IS_APP DOMAIN _MODULES _LIBS)
import_version(${PROJ_NAME} ${DOMAIN})
import_deploy_properties(${PROJ_NAME} ${DOMAIN})
if (${IS_APP})
list(APPEND _qt_apps ${PROJ_NAME})
set_deploy_property(${PROJ_NAME}
LABEL ${PROJ_NAME}
FULLNAME "${_${DOMAIN}_DOMAIN}.${PROJ_NAME}"
INFO "${APP_INFO}"
ICON "${APP_ICON}")
else()
list(APPEND _qt_libs ${PROJ_NAME})
set_deploy_property(${PROJ_NAME} SHARED
LABEL ${PROJ_NAME}
FULLNAME "${_${DOMAIN}_DOMAIN}.${PROJ_NAME}"
@@ -55,23 +59,17 @@ macro(_qt_project NAME IS_APP DOMAIN _MODULES _LIBS)
if(NOT STATIC_LIB)
qt_target_compile_definitions(${PROJ_NAME} PRIVATE ${DOMAIN}_SHARED_DEFINE)
endif()
qt_get_target(${PROJ_NAME} _some_target)
qt_get_target(${PROJ_NAME} _targets)
foreach(_t ${_targets})
set_target_properties(${_t} PROPERTIES DEFINE_SYMBOL ${PROJ_NAME}_EXPORTS)
endforeach()
set_target_properties(${_some_target} PROPERTIES DEFINE_SYMBOL ${PROJ_NAME}_EXPORTS)
generate_export_header(${_some_target} BASE_NAME "${PROJ_NAME}")
qt_generate_export_header(${PROJ_NAME})
list(APPEND out_HDR "${CMAKE_CURRENT_BINARY_DIR}/${PROJ_NAME}_export.h")
endif()
qt_target_link_libraries(${PROJ_NAME} ${_LIBS})
list(APPEND QT_MULTILIB_LIST ${PROJ_NAME})
set(QT_MULTILIB_LIST ${QT_MULTILIB_LIST} PARENT_SCOPE)
message(STATUS "Building ${PROJ_NAME}")
#message(STATUS "Building ${PROJ_NAME}")
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/plugin")
set(_${NAME}_PLUGIN_LIBS "${_LIBS}")
add_subdirectory(plugin)
endif()
copy_to_parent("")
endmacro()
@@ -85,3 +83,8 @@ macro(qad_application NAME _MODULES _LIBS)
_qt_project(${NAME} TRUE "QAD" "${_MODULES}" "${_LIBS}")
_qt_install(${NAME} TRUE "qad" "" "out_QM")
endmacro()
macro(qad_plugin NAME _MODULES _LIBS)
_qt_plugin(qad_${NAME} "${_MODULES}" "qad_${NAME};${_LIBS}")
endmacro()

View File

@@ -1,793 +1,811 @@
#[[
find_qt([<Module1> <Module2> ...] [Qt4] [Qt5])
Find Qt4 or/and Qt5 packages
If Qt4/5 found, set
* Qt<4/5>_ROOT var to Qt root dir
* Qt<4/5>_BIN var to Qt binary dir
* Qt<4/5>_PLUGINS_DIR var to Qt plugins dir
* Qt<4/5>_LANG_DIR var to Qt translations dir
qt_sources(<src_out_var> [NO_DEFAULT] [DIR <dir>] [<regexp> ...])
Collect all sources, optionally in directory <dir> and
Additional filters <regexp>. By default filter files with regexps
"*.h", "*.hpp", "*.c", "*.cpp", "*.ui", "*.qrc", "*.rc", "*.ts" and "lang/*.ts".
Default filters disabled with option NO_DEFAULT
qt_wrap(<file0> <file1> ... [HDRS <hrd_var>] [CPPS <cpp_var>] [QMS <qm_var>])
Prepare sources for compile
Store headers to <hrd_var>, all wrapped Qt4 files to <cpp_var>_Qt4 and Qt5 files to <cpp_var>_Qt5
version are automatic detected after find_qt() call
qt_add_executable(<name> [WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL] source1 [source2 ...])
Add executables for founded Qt versions, target names is <name><TARGET_SUFFIX_Qt?>
All needed Qt includes automatic added to corresponding targets
<source> cant be CPPS variable passed to qt_wrap() or some list or filename
qt_add_library(<name> [STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL] source1 [source2 ...])
Add library for founded Qt versions, target names is <name><TARGET_SUFFIX_Qt?>
All needed Qt includes automatic added to corresponding targets
<source> cant be CPPS variable passed to qt_wrap() or some list or filename
qt_target_link_libraries(<name> ... <item> ...)
Link targets for founded Qt versions, target names is <name><TARGET_SUFFIX_Qt?>
All needed Qt libraries automatic added to corresponding targets
if QT_MULTILIB_LIST contains some linking library, to it name automatic
add <MULTILIB_SUFFIX_Qt?> or individual <MULTILIB_>libname<_SUFFIX_Qt?>
qt_target_compile_definitions(<name> ...)
Syntax similar to original "target_compile_definitions()"
Specify compile definitions to use when compiling a given <name>
qt_target_include_directories(<name> ...)
Syntax similar to original "target_include_directories()"
Add include directories to a target
qt_install(...)
Syntax similar to original "install()"
Install targets for founded Qt versions
if DESTINATION set to "QtBin" files will be installed
to corresponding Qt binary directory
if DESTINATION set to "QtLang" files will be installed
to corresponding Qt translation directory
if DESTINATION starts with "QtPlugins" files will be installed
to corresponding Qt plugins directory
Add LANG type for first argument - in this case you should
specify variable name, not variable value!
e.g. "qt_install(LANG my_QM DESTINATION QtLang)"
qt_install_lang(<name> DESTINATION <dir> [PATHS <path0> [<path1>] [...] ])
Search Qt translations for all <name> dependencies
in Qt<?>_LANG_DIR for <name>_LANG languages
and install them to <dir>. PATH are additional search paths.
You should use "set_lang()" macro before this action
qt_get_target(<name> <var> [Qt4 | Qt5])
Write real <name> Qt target name to <var>
If Qt4 or Qt5 specified, search for this version,
otherwise returns greatest version
qt_get_targets(<name> <var>)
Write all real <name> Qt target names to <var>
]]
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 (POLICY CMP0057)
cmake_policy(SET CMP0057 NEW) # Support if() IN_LIST
endif()
if (POLICY CMP0074)
cmake_policy(SET CMP0074 OLD) # ignore <PackageName>_ROOT variables
endif()
set(__qt_bug_modules "UiTools")
set(_QT_VERSIONS_ 4 5)
foreach(_v ${_QT_VERSIONS_})
if (NOT DEFINED TARGET_SUFFIX_Qt${_v})
set(TARGET_SUFFIX_Qt${_v} "${_v}")
set(MULTILIB_SUFFIX_Qt${_v} "${_v}")
endif()
set(MOC_INC_Qt${_v})
endforeach()
if (NOT DEFINED QT_MULTILIB_LIST)
set(QT_MULTILIB_LIST)
endif()
#set(TARGET_SUFFIX_Qt4 "")
macro(find_qt)
set(_QCOMP)
foreach(_v ${_QT_VERSIONS_})
set(_NEED${_v} 0)
set(LOCAL_FOUND${_v} 0)
set(MOC_INC_Qt${_v})
set(Qt${_v}_INCLUDES)
set(Qt${_v}_LIBRARIES)
set(Qt${_v}_ROOT)
set(Qt${_v}_BIN)
set(Qt${_v}_PLUGINS_DIR)
set(Qt${_v}_LANG_DIR)
endforeach()
set(_NEED_SOME 0)
set(_QUIET)
foreach(_i ${ARGN})
set(_FOUND_NEED 0)
foreach(_v ${_QT_VERSIONS_})
if ("x${_i}" STREQUAL "xQt${_v}")
set(_NEED${_v} 1)
set(_NEED_SOME 1)
set(_FOUND_NEED 1)
endif()
if ("x${_i}" STREQUAL "xQUIET")
set(_QUIET QUIET)
endif()
endforeach()
if (NOT _FOUND_NEED)
list(APPEND _QCOMP "${_i}")
endif()
endforeach()
if (NOT _NEED_SOME)
foreach(_v ${_QT_VERSIONS_})
set(_NEED${_v} 1)
endforeach()
endif()
list(REMOVE_DUPLICATES _QCOMP)
if (_NEED4)
find_package(Qt4 ${_QUIET})
if (Qt4_FOUND)
set(LOCAL_FOUND4 1)
get_filename_component(Qt4_BIN ${QT_QMAKE_EXECUTABLE} PATH)
set(Qt4_INCLUDES ${QT_INCLUDES})
foreach(m ${_QCOMP})
string(TOUPPER "${m}" _um)
#message("${QT_QT${_um}_FOUND}")
if (${QT_QT${_um}_FOUND})
list(APPEND Qt4_LIBRARIES ${QT_QT${_um}_LIBRARY})
endif()
endforeach()
set(Qt4_PLUGINS_DIR ${QT_PLUGINS_DIR})
set(Qt4_LANG_DIR ${Qt4_BIN}/../translations)
set(Qt4_ROOT "${Qt4_BIN}/../")
endif()
endif()
if (_NEED5)
#set(_MSG 1)
#if (Qt5_FOUND)
# set(_MSG 0)
#endif()
find_package(Qt5 COMPONENTS Core LinguistTools UiPlugin Widgets ${_QCOMP} ${_QUIET})
if (DEFINED ANDROID_PLATFORM)
set(CMAKE_SHARED_MODULE_SUFFIX_CXX ".so")
set(CMAKE_SHARED_LIBRARY_SUFFIX_CXX ".so")
set(CMAKE_SHARED_MODULE_SUFFIX_C ".so")
set(CMAKE_SHARED_LIBRARY_SUFFIX_C ".so")
endif()
if (Qt5_FOUND)
set(LOCAL_FOUND5 1)
set(_Qt5Modules)
foreach(m ${_QCOMP})
if (${Qt5${m}_FOUND})
set(__lib ${Qt5${m}_LIBRARIES})
if (DEFINED ANDROID_PLATFORM)
if (m IN_LIST __qt_bug_modules)
get_target_property(__lib Qt5::${m} LOCATION)
endif()
endif()
list(APPEND _Qt5Modules ${m})
list(APPEND Qt5_INCLUDES ${Qt5${m}_INCLUDE_DIRS})
list(APPEND Qt5_LIBRARIES ${__lib})
endif()
endforeach()
#get_property(_up_dir TARGET Qt5::UiPlugin PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
#message("${_up_dir}")
#if (NOT "x${_up_dir}" STREQUAL "x")
# list(APPEND Qt5_INCLUDES ${_up_dir})
#endif()
get_target_property(_Qt5_qmake Qt5::qmake LOCATION)
get_filename_component(Qt5_BIN ${_Qt5_qmake} PATH)
foreach(_p ${Qt5Gui_PLUGINS})
get_target_property(_l ${_p} LOCATION)
get_filename_component(_l ${_l} DIRECTORY)
string(FIND "${_l}" "/" _ind REVERSE)
string(SUBSTRING "${_l}" 0 ${_ind} _l)
set(Qt5_PLUGINS_DIR ${_l})
#message("Qt5: plugins dir: ${Qt5_PLUGINS_DIR}")
break()
endforeach()
string(FIND "${Qt5_BIN}" "/" _ind REVERSE)
string(SUBSTRING "${Qt5_BIN}" 0 ${_ind} Qt5_ROOT)
if ("x${Qt5_PLUGINS_DIR}" STREQUAL "x")
set(Qt5_PLUGINS_DIR "${Qt5_ROOT}/plugins")
endif()
if (APPLE)
list(APPEND MOC_INC_Qt5 "-F${Qt5_ROOT}/lib")
endif()
set(Qt5_LANG_DIR ${Qt5_BIN}/../translations)
if (NOT _QT5_MSG)
message(STATUS "Found Qt5: ${_Qt5_qmake} (version \"${Qt5_VERSION}\")")
set(_QT5_MSG 1 CACHE BOOL "msg_qt5" FORCE)
#message(STATUS "Found Qt5 modules: ${_Qt5Modules}")
endif()
endif()
endif()
foreach(_v ${_QT_VERSIONS_})
if (LOCAL_FOUND${_v})
foreach(_p ${Qt${_v}_INCLUDES})
list(APPEND MOC_INC_Qt${_v} "-I${_p}")
#message("${_p}")
endforeach()
endif()
#message("${MOC_INC_Qt${_v}}")
endforeach()
endmacro()
macro(qt_sources OUT)
set(${OUT})
set(_DIR "")
set(_IS_DIR 0)
set(_NO_DEFAULT 0)
set(_DEFAULT)
set(_REGEXP)
set(_REGEXP_WD)
foreach(_i ${ARGN})
if (_IS_DIR)
set(_DIR "${_i}")
set(_IS_DIR 0)
elseif ("x${_i}" STREQUAL "xDIR")
set(_IS_DIR 1)
elseif ("x${_i}" STREQUAL "xNO_DEFAULT")
set(_NO_DEFAULT 1)
else()
list(APPEND _REGEXP ${_i})
endif()
endforeach()
if (NOT "x${_DIR}" STREQUAL "x")
#file(TO_CMAKE_PATH "${_DIR}//" _DIR)
string(REPLACE "\\" "/" _DIR "${_DIR}/")
string(REPLACE "//" "/" _DIR "${_DIR}")
endif()
foreach(_i ${_REGEXP})
list(APPEND _REGEXP_WD "${_DIR}${_i}")
endforeach()
if (NOT _NO_DEFAULT)
set(_DEFAULT "${_DIR}*.h" "${_DIR}*.hpp" "${_DIR}*.c" "${_DIR}*.cpp" "${_DIR}*.ui" "${_DIR}*.qrc" "${_DIR}*.rc" "${_DIR}*.ts" "${_DIR}lang/*.ts")
endif()
#message("${_DEFAULT}, ${_REGEXP_WD}")
file(GLOB ${OUT} ${_DEFAULT} ${_REGEXP_WD})
endmacro()
macro(qt_wrap)
set(HDR_VAR)
set(CPP_VAR)
set(QM_VAR)
set(_HDR_ARG 0)
set(_CPP_ARG 0)
set(_QM_ARG 0)
set(WAS_HDR_ARG 0)
set(WAS_CPP_ARG 0)
set(WAS_QM_ARG 0)
set(FILE_LIST)
foreach(_i ${ARGN})
if (_HDR_ARG)
set(HDR_VAR ${_i})
set(WAS_HDR_ARG 1)
set(_HDR_ARG 0)
elseif (_CPP_ARG)
set(CPP_VAR ${_i})
set(WAS_CPP_ARG 1)
set(_CPP_ARG 0)
elseif (_QM_ARG)
set(QM_VAR ${_i})
set(WAS_QM_ARG 1)
set(_QM_ARG 0)
elseif ("x${_i}" STREQUAL "xHDRS")
set(_HDR_ARG 1)
elseif ("x${_i}" STREQUAL "xCPPS")
set(_CPP_ARG 1)
elseif ("x${_i}" STREQUAL "xQMS")
set(_QM_ARG 1)
else()
list(APPEND FILE_LIST "${_i}")
endif()
endforeach()
foreach(_v ${_QT_VERSIONS_})
set(CPP${_v}_VAR)
set(QM${_v}_VAR)
if (LOCAL_FOUND${_v})
if (WAS_CPP_ARG)
set(CPP${_v}_VAR ${CPP_VAR}_Qt${_v})
endif()
if (WAS_QM_ARG)
set(QM${_v}_VAR ${QM_VAR}_Qt${_v})
endif()
endif()
endforeach()
#message("found 4: ${LOCAL_FOUND4}, 5: ${LOCAL_FOUND5}")
#message("has HRDS: ${WAS_HDR_ARG}: ${HDR_VAR}")
#message("has CPPS4: ${WAS_CPP_ARG}: ${CPP4_VAR}")
#message("has CPPS5: ${WAS_CPP_ARG}: ${CPP5_VAR}")
#message("files: ${FILE_LIST}")
set(H_LIST)
set(CPP_LIST)
set(UI_LIST)
set(RES_LIST)
set(RC_LIST)
set(TS_LIST)
foreach(_i ${FILE_LIST})
get_filename_component(_EXT "${_i}" EXT)
#message("${_EXT}")
if (NOT ("x${_EXT}" STREQUAL "x"))
if (("x${_EXT}" STREQUAL "x.h") OR ("x${_EXT}" STREQUAL "x.hpp"))
list(APPEND H_LIST "${_i}")
#message("header")
endif()
if (("x${_EXT}" STREQUAL "x.c") OR ("x${_EXT}" STREQUAL "x.cpp") OR ("x${_EXT}" STREQUAL "x.cxx"))
list(APPEND CPP_LIST "${_i}")
#message("source")
endif()
if ("x${_EXT}" STREQUAL "x.ui")
list(APPEND UI_LIST "${_i}")
endif()
if ("x${_EXT}" STREQUAL "x.qrc")
list(APPEND RES_LIST "${_i}")
endif()
if ("x${_EXT}" STREQUAL "x.rc")
list(APPEND RC_LIST "${_i}")
endif()
if ("x${_EXT}" STREQUAL "x.ts")
list(APPEND TS_LIST "${_i}")
endif()
endif()
endforeach()
if (WAS_HDR_ARG)
set(${HDR_VAR})
list(APPEND ${HDR_VAR} ${H_LIST})
endif()
set(SRC_CMAKE_CURRENT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
foreach(_v ${_QT_VERSIONS_})
if (LOCAL_FOUND${_v} AND WAS_CPP_ARG)
set(CMAKE_CURRENT_BINARY_DIR ${SRC_CMAKE_CURRENT_BINARY_DIR}/qt${_v})
set(${CPP${_v}_VAR})
if (WAS_QM_ARG)
set(${QM${_v}_VAR})
endif()
set(MOCS${_v})
set(CUIS${_v})
set(CRES${_v})
if (${_v} EQUAL 4)
qt4_wrap_cpp(MOCS${_v} ${H_LIST} OPTIONS -nw ${MOC_INC_Qt4})
qt4_wrap_ui(CUIS${_v} ${UI_LIST})
qt4_add_resources(CRES${_v} ${RES_LIST})
if (WAS_QM_ARG)
set(${QM${_v}_VAR} "")
qt4_add_translation(${QM${_v}_VAR} ${TS_LIST})
endif()
elseif (${_v} EQUAL 5)
qt5_wrap_cpp(MOCS${_v} ${H_LIST} OPTIONS -nw ${MOC_INC_Qt5})
qt5_wrap_ui(CUIS${_v} ${UI_LIST})
qt5_add_resources(CRES${_v} ${RES_LIST})
if (WAS_QM_ARG)
set(${QM${_v}_VAR} "")
qt5_add_translation(${QM${_v}_VAR} ${TS_LIST})
endif()
else()
# Qt6 ...
endif()
#message("${${QM${_v}_VAR}}")
list(APPEND ${CPP${_v}_VAR} ${CPP_LIST})
list(APPEND ${CPP${_v}_VAR} ${RC_LIST})
list(APPEND ${CPP${_v}_VAR} ${MOCS${_v}})
list(APPEND ${CPP${_v}_VAR} ${CUIS${_v}})
list(APPEND ${CPP${_v}_VAR} ${CRES${_v}})
if (WAS_QM_ARG)
list(APPEND ${CPP${_v}_VAR} ${${QM${_v}_VAR}})
endif()
#message("${${QM${_v}_VAR}}")
endif()
endforeach()
set(CMAKE_CURRENT_BINARY_DIR ${SRC_CMAKE_CURRENT_BINARY_DIR})
endmacro()
macro(_qt_split_add_args _P _A)
set(${_P})
set(${_A})
foreach(_i ${ARGN})
if (NOT ("x${${_i}_Qt${_v}}" STREQUAL "x"))
list(APPEND ${_A} ${${_i}_Qt${_v}})
elseif (("x${_i}" STREQUAL "xWIN32") OR
("x${_i}" STREQUAL "xMACOSX_BUNDLE") OR
("x${_i}" STREQUAL "xSTATIC") OR
("x${_i}" STREQUAL "xSHARED") OR
("x${_i}" STREQUAL "xMODULE") OR
("x${_i}" STREQUAL "xEXCLUDE_FROM_ALL"))
list(APPEND ${_P} ${_i})
elseif ("x${${_i}}" STREQUAL "x")
list(APPEND ${_A} ${_i})
else()
list(APPEND ${_A} ${${_i}})
endif()
endforeach()
endmacro()
macro(__qt_set_defines _NAME _T)
target_compile_definitions(${_T} PRIVATE "__TARGET_NAME__=\"${_NAME}\"")
target_compile_definitions(${_T} PRIVATE "__TARGET_LABEL__=\"${${_NAME}_LABEL}\"")
target_compile_definitions(${_T} PRIVATE "__TARGET_COMPANY__=\"${${_NAME}_COMPANY}\"")
target_compile_definitions(${_T} PRIVATE "__TARGET_VERSION__=\"${${_NAME}_VERSION}\"")
endmacro()
macro(qt_add_executable _NAME)
foreach(_v ${_QT_VERSIONS_})
if (LOCAL_FOUND${_v})
_qt_split_add_args(_PREF _ARGS ${ARGN})
if(APPLE)
set(_PREV_CIND "${CMAKE_INSTALL_NAME_DIR}")
set(CMAKE_INSTALL_NAME_DIR "@rpath")
else()
if(NOT WIN32)
set(CMAKE_INSTALL_RPATH "\$ORIGIN;\$ORIGIN/lib")
endif()
endif()
set(_TARGET ${_NAME}${TARGET_SUFFIX_Qt${_v}})
add_executable(${_TARGET} ${_PREF} ${_ARGS})
set(_${_NAME}_is_qt 1)
target_include_directories(${_TARGET} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/qt${_v} ${Qt${_v}_INCLUDES})
__qt_set_defines(${_NAME} ${_TARGET})
if(APPLE)
set(CMAKE_INSTALL_NAME_DIR "${_PREV_CIND}")
endif()
# # Apple crosscompiling rpath patch
# if (APPLE AND CMAKE_CROSSCOMPILING AND CMAKE_MACOSX_RPATH)
# foreach(_RP ${CMAKE_INSTALL_RPATH})
# add_custom_command(TARGET ${_TARGET} POST_BUILD
# COMMAND "${CMAKE_INSTALL_NAME_TOOL}"
# "-add_rpath" "${_RP}"
# "$<TARGET_FILE_DIR:${_TARGET}>/$<TARGET_FILE_NAME:${_TARGET}>"
# COMMENT "Add to ${_TARGET} rpath \"${_RP}\"")
# endforeach()
# endif()
#list(APPEND _ALL_TARGETS "${_TARGET}")
#set(_ALL_TARGETS ${_ALL_TARGETS} PARENT_SCOPE)
endif()
endforeach()
endmacro()
macro(qt_add_library _NAME)
foreach(_v ${_QT_VERSIONS_})
if (LOCAL_FOUND${_v})
_qt_split_add_args(_PREF _ARGS ${ARGN})
if(APPLE)
set(_PREV_CIND "${CMAKE_INSTALL_NAME_DIR}")
set(CMAKE_INSTALL_NAME_DIR "@rpath")
else()
if(NOT WIN32)
set(CMAKE_INSTALL_RPATH "\$ORIGIN;\$ORIGIN/lib")
endif()
endif()
set(_TARGET ${_NAME}${TARGET_SUFFIX_Qt${_v}})
add_library(${_TARGET} ${_PREF} ${_ARGS})
set(_${_NAME}_is_qt 1)
target_include_directories(${_TARGET} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/qt${_v} ${Qt${_v}_INCLUDES})
__qt_set_defines(${_NAME} ${_TARGET})
#message("add lib: \"${_TARGET}\"")
if(APPLE)
set(CMAKE_INSTALL_NAME_DIR "${_PREV_CIND}")
endif()
# # Apple crosscompiling rpath patch
# if (APPLE AND CMAKE_CROSSCOMPILING AND CMAKE_MACOSX_RPATH)
# foreach(_RP ${CMAKE_INSTALL_RPATH})
# add_custom_command(TARGET ${_TARGET} POST_BUILD
# COMMAND "${CMAKE_INSTALL_NAME_TOOL}"
# "-add_rpath" "${_RP}"
# "$<TARGET_FILE_DIR:${_TARGET}>/$<TARGET_FILE_NAME:${_TARGET}>"
# COMMENT "Add to ${_TARGET} rpath \"${_RP}\"")
# endforeach()
# endif()
list(APPEND _ALL_TARGETS "${_TARGET}")
set(_ALL_TARGETS ${_ALL_TARGETS} PARENT_SCOPE)
endif()
endforeach()
endmacro()
macro(_qt_multitarget_suffix_ _OUT _IN _v)
string(REPLACE ":" "_" _in_str "${_IN}")
if (NOT "x${MULTILIB_${_in_str}_SUFFIX_Qt${_v}}" STREQUAL "x")
set(${_OUT} "${MULTILIB_${_in_str}_SUFFIX_Qt${_v}}")
else()
set(${_OUT} "${MULTILIB_SUFFIX_Qt${_v}}")
endif()
endmacro()
macro(qt_target_link_libraries _NAME)
foreach(_v ${_QT_VERSIONS_})
if (LOCAL_FOUND${_v})
set(_TARGET ${_NAME}${TARGET_SUFFIX_Qt${_v}})
set(_ARGS)
foreach(_i ${ARGN})
set(_ind -1)
list(FIND QT_MULTILIB_LIST "${_i}" _ind)
if (_ind GREATER -1)
_qt_multitarget_suffix_(_TS ${_i} ${_v})
#message(STATUS "${_i} in MULTILIB_LIST, suffix = ${_TS}")
list(APPEND _ARGS ${_i}${_TS})
else()
list(APPEND _ARGS ${_i})
endif()
endforeach()
target_link_libraries(${_TARGET} ${Qt${_v}_LIBRARIES} ${_ARGS})
#message("link ${_TARGET}: ${Qt${_v}_LIBRARIES} ${_ARGS}")
endif()
endforeach()
endmacro()
macro(qt_target_compile_definitions _NAME)
foreach(_v ${_QT_VERSIONS_})
if (LOCAL_FOUND${_v})
set(_TARGET ${_NAME}${TARGET_SUFFIX_Qt${_v}})
target_compile_definitions(${_TARGET} ${ARGN})
endif()
endforeach()
endmacro()
macro(qt_target_include_directories _NAME)
foreach(_v ${_QT_VERSIONS_})
if (LOCAL_FOUND${_v})
set(_TARGET ${_NAME}${TARGET_SUFFIX_Qt${_v}})
target_include_directories(${_TARGET} ${ARGN})
endif()
endforeach()
endmacro()
macro(qt_install)
set(_prev_inst)
set(__add_args)
#message("command: ${ARGN}")
foreach(_v ${_QT_VERSIONS_})
if (LOCAL_FOUND${_v})
set(_INST_LIST)
set(_IS_TARGET 0)
set(_IS_FILES 0)
set(_IS_DEST 0)
set(_IS_LANG 0)
set(_INVALID 0)
foreach(_i ${ARGN})
if ("x${_i}" STREQUAL "xQtLang")
set(_IS_LANG 1)
endif()
endforeach()
foreach(_i ${ARGN})
if (_IS_TARGET)
set(_IS_TARGET 0)
set(__target ${_i})
if (_${_i}_is_qt)
set(__target ${_i}${TARGET_SUFFIX_Qt${_v}})
endif()
if (DEFINED ANDROID_PLATFORM)
get_target_property(_TT ${__target} TYPE)
if ("x${_TT}" STREQUAL "xEXECUTABLE")
list(APPEND __add_args EXCLUDE_FROM_ALL)
endif()
endif()
list(APPEND _INST_LIST ${__target})
elseif (_IS_FILES)
set(_IS_FILES 0)
if (_IS_LANG)
if (("x${${_i}_Qt${_v}}" STREQUAL "x") OR ("x${_i}" STREQUAL "xDESTINATION"))
set(_INVALID 1)
else()
list(APPEND _INST_LIST ${${_i}_Qt${_v}})
endif()
else()
list(APPEND _INST_LIST ${_i})
endif()
else()
if (_IS_DEST)
set(_IS_DEST 0)
if ("x${_i}" STREQUAL "xQtBin")
list(APPEND _INST_LIST "${Qt${_v}_BIN}")
elseif ("x${_i}" STREQUAL "xQtLang")
list(APPEND _INST_LIST "${Qt${_v}_LANG_DIR}")
else()
set(_ind -1)
string(FIND "${_i}" "QtPlugins" _ind)
if (_ind GREATER -1)
string(REPLACE "QtPlugins" "${Qt${_v}_PLUGINS_DIR}" _o "${_i}")
list(APPEND _INST_LIST "${_o}")
else()
string(REPLACE "\\" "/" _o "${_i}")
list(APPEND _INST_LIST ${_o})
endif()
endif()
else()
set(_ii ${_i})
if ("x${_i}" STREQUAL "xTARGETS")
set(_IS_TARGET 1)
elseif ("x${_i}" STREQUAL "xFILES")
set(_IS_FILES 1)
elseif ("x${_i}" STREQUAL "xDESTINATION")
set(_IS_DEST 1)
elseif ("x${_i}" STREQUAL "xLANG")
set(_IS_FILES 1)
set(_IS_LANG 1)
set(_ii "FILES")
endif()
list(APPEND _INST_LIST ${_ii})
endif()
endif()
endforeach()
if (NOT _INVALID)
if (NOT ("x${_prev_inst}" STREQUAL "x${_INST_LIST}"))
#message("install: ${_INST_LIST}")
install(${_INST_LIST} ${__add_args})
set(_prev_inst "${_INST_LIST}")
endif()
endif()
endif()
endforeach()
endmacro()
macro(qt_install_lang _NAME)
set(_prev_inst)
#message("command: ${ARGN}")
set(_PATHS)
set(_DEST)
if(CMAKE_CROSSCOMPILING)
list(APPEND _PATHS "${CMAKE_PREFIX_PATH}/lang")
endif()
set(_cur_arg)
set(__args "DESTINATION;PATHS")
foreach(_i ${ARGN})
if (_i IN_LIST __args)
set(_cur_arg "${_i}")
elseif("${_cur_arg}" STREQUAL "DESTINATION")
set(_DEST "${_i}")
elseif("${_cur_arg}" STREQUAL "PATHS")
list(APPEND _PATHS "${_i}")
endif()
endforeach()
foreach(_v ${_QT_VERSIONS_})
if (LOCAL_FOUND${_v})
set(_target)
if (_${_NAME}_is_qt)
set(_target ${_NAME}${TARGET_SUFFIX_Qt${_v}})
endif()
get_target_property(_LL ${_target} LINK_LIBRARIES)
foreach (_L ${_LL})
get_filename_component(_libname "${_L}" NAME_WE)
#message("depend on ${_libname}")
if ("${_libname}" MATCHES "Qt${_v}::.*")
string(SUBSTRING "${_libname}" 5 -1 _libname)
string(TOLOWER "${_libname}" _libname)
#message("qt lib \"${_libname}\"")
list(APPEND _qt_libs qt${_libname})
else()
if ("${_libname}" MATCHES "lib.*")
string(LENGTH ${_libname} _sl)
math(EXPR _sl ${_sl}-3)
string(SUBSTRING ${_libname} 3 ${_sl} _libname)
endif()
if ("${_libname}" MATCHES "qad_.*${_v}")
string(LENGTH ${_libname} _sl)
math(EXPR _sl ${_sl}-1)
string(SUBSTRING ${_libname} 0 ${_sl} _libname)
#message("qad lib \"${_libname}\"")
list(APPEND _qt_libs ${_libname})
endif()
endif()
endforeach()
if (NOT "x${_qt_libs}" STREQUAL "x")
list(APPEND _qt_libs "qtbase")
foreach (_i ${${PROJECT_NAME}_LANG})
foreach (_l ${_qt_libs})
unset(_qm_path CACHE)
find_file(_qm_path "${_l}_${_i}.qm" PATHS "${Qt${_v}_LANG_DIR}" ${_PATHS} NO_DEFAULT_PATH)
if (EXISTS "${_qm_path}")
install(FILES ${_qm_path} DESTINATION "${_DEST}")
#message("qm = \"${_qm_path}\"")
endif()
endforeach()
endforeach()
endif()
endif()
endforeach()
endmacro()
macro(qt_get_target _NAME _OUT)
set(${_OUT})
set(_ver)
foreach(_i ${ARGN})
foreach(_v ${_QT_VERSIONS_})
if ("x${_i}" STREQUAL "xQt${_v}")
set(_ver ${_v})
break()
endif()
endforeach()
if (NOT "x${_ver}" STREQUAL "x")
break()
endif()
endforeach()
foreach(_v ${_QT_VERSIONS_})
if (LOCAL_FOUND${_v} AND (("x${_ver}" STREQUAL "x") OR ((NOT "x${_ver}" STREQUAL "x") AND ("x${_ver}" STREQUAL "x${_v}"))))
set(${_OUT} ${_NAME}${TARGET_SUFFIX_Qt${_v}})
endif()
endforeach()
endmacro()
macro(qt_get_targets _NAME _OUT)
set(${_OUT})
foreach(_v ${_QT_VERSIONS_})
if (LOCAL_FOUND${_v})
list(APPEND ${_OUT} ${_NAME}${TARGET_SUFFIX_Qt${_v}})
endif()
endforeach()
endmacro()
#[[
find_qt([<Module1> <Module2> ...] [Qt4] [Qt5])
Find Qt4 or/and Qt5 packages
If Qt4/5 found, set
* Qt<4/5>_ROOT var to Qt root dir
* Qt<4/5>_BIN var to Qt binary dir
* Qt<4/5>_PLUGINS_DIR var to Qt plugins dir
* Qt<4/5>_LANG_DIR var to Qt translations dir
qt_sources(<src_out_var> [NO_DEFAULT] [DIR <dir>] [<regexp> ...])
Collect all sources, optionally in directory <dir> and
Additional filters <regexp>. By default filter files with regexps
"*.h", "*.hpp", "*.c", "*.cpp", "*.ui", "*.qrc", "*.rc", "*.ts" and "lang/*.ts".
Default filters disabled with option NO_DEFAULT
qt_wrap(<file0> <file1> ... [HDRS <hrd_var>] [CPPS <cpp_var>] [QMS <qm_var>])
Prepare sources for compile
Store headers to <hrd_var>, all wrapped Qt4 files to <cpp_var>_Qt4 and Qt5 files to <cpp_var>_Qt5
version are automatic detected after find_qt() call
qt_add_executable(<name> [WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL] source1 [source2 ...])
Add executables for founded Qt versions, target names is <name><TARGET_SUFFIX_Qt?>
All needed Qt includes automatic added to corresponding targets
<source> cant be CPPS variable passed to qt_wrap() or some list or filename
qt_add_library(<name> [STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL] source1 [source2 ...])
Add library for founded Qt versions, target names is <name><TARGET_SUFFIX_Qt?>
All needed Qt includes automatic added to corresponding targets
<source> cant be CPPS variable passed to qt_wrap() or some list or filename
qt_target_link_libraries(<name> ... <item> ...)
Link targets for founded Qt versions, target names is <name><TARGET_SUFFIX_Qt?>
All needed Qt libraries automatic added to corresponding targets
if QT_MULTILIB_LIST contains some linking library, to it name automatic
add <MULTILIB_SUFFIX_Qt?> or individual <MULTILIB_>libname<_SUFFIX_Qt?>
qt_target_compile_definitions(<name> ...)
Syntax similar to original "target_compile_definitions()"
Specify compile definitions to use when compiling a given <name>
qt_target_include_directories(<name> ...)
Syntax similar to original "target_include_directories()"
Add include directories to a target
qt_install(...)
Syntax similar to original "install()"
Install targets for founded Qt versions
if DESTINATION set to "QtBin" files will be installed
to corresponding Qt binary directory
if DESTINATION set to "QtLang" files will be installed
to corresponding Qt translation directory
if DESTINATION starts with "QtPlugins" files will be installed
to corresponding Qt plugins directory
Add LANG type for first argument - in this case you should
specify variable name, not variable value!
e.g. "qt_install(LANG my_QM DESTINATION QtLang)"
qt_install_lang(<name> DESTINATION <dir> [PATHS <path0> [<path1>] [...] ])
Search Qt translations for all <name> dependencies
in Qt<?>_LANG_DIR for <name>_LANG languages
and install them to <dir>. PATH are additional search paths.
You should use "set_lang()" macro before this action
qt_get_target(<name> <var> [Qt4 | Qt5])
Write real <name> Qt target name to <var>
If Qt4 or Qt5 specified, search for this version,
otherwise returns greatest version
qt_get_targets(<name> <var>)
Write all real <name> Qt target names to <var>
qt_generate_export_header(<name> ...)
Call generate_export_header on Qt multitarget
]]
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 (POLICY CMP0057)
cmake_policy(SET CMP0057 NEW) # Support if() IN_LIST
endif()
if (POLICY CMP0074)
cmake_policy(SET CMP0074 OLD) # ignore <PackageName>_ROOT variables
endif()
set(__qt_bug_modules "UiTools")
set(_QT_VERSIONS_ 4 5)
foreach(_v ${_QT_VERSIONS_})
if (NOT DEFINED TARGET_SUFFIX_Qt${_v})
set(TARGET_SUFFIX_Qt${_v} "${_v}")
set(MULTILIB_SUFFIX_Qt${_v} "${_v}")
endif()
set(MOC_INC_Qt${_v})
endforeach()
if (NOT DEFINED QT_MULTILIB_LIST)
set(QT_MULTILIB_LIST)
endif()
#set(TARGET_SUFFIX_Qt4 "")
macro(find_qt)
set(_QCOMP)
foreach(_v ${_QT_VERSIONS_})
set(_NEED${_v} 0)
set(LOCAL_FOUND${_v} 0)
set(MOC_INC_Qt${_v})
set(Qt${_v}_INCLUDES)
set(Qt${_v}_LIBRARIES)
set(Qt${_v}_ROOT)
set(Qt${_v}_BIN)
set(Qt${_v}_PLUGINS_DIR)
set(Qt${_v}_LANG_DIR)
endforeach()
set(_NEED_SOME 0)
set(_QUIET)
foreach(_i ${ARGN})
set(_FOUND_NEED 0)
foreach(_v ${_QT_VERSIONS_})
if ("x${_i}" STREQUAL "xQt${_v}")
set(_NEED${_v} 1)
set(_NEED_SOME 1)
set(_FOUND_NEED 1)
endif()
if ("x${_i}" STREQUAL "xQUIET")
set(_QUIET QUIET)
endif()
endforeach()
if (NOT _FOUND_NEED)
list(APPEND _QCOMP "${_i}")
endif()
endforeach()
if (NOT _NEED_SOME)
foreach(_v ${_QT_VERSIONS_})
set(_NEED${_v} 1)
endforeach()
endif()
list(REMOVE_DUPLICATES _QCOMP)
if (_NEED4)
find_package(Qt4 ${_QUIET})
if (Qt4_FOUND)
set(LOCAL_FOUND4 1)
get_filename_component(Qt4_BIN ${QT_QMAKE_EXECUTABLE} PATH)
set(Qt4_INCLUDES ${QT_INCLUDES})
foreach(m ${_QCOMP})
string(TOUPPER "${m}" _um)
#message("${QT_QT${_um}_FOUND}")
if (${QT_QT${_um}_FOUND})
list(APPEND Qt4_LIBRARIES ${QT_QT${_um}_LIBRARY})
endif()
endforeach()
set(Qt4_PLUGINS_DIR ${QT_PLUGINS_DIR})
set(Qt4_LANG_DIR ${Qt4_BIN}/../translations)
set(Qt4_ROOT "${Qt4_BIN}/../")
endif()
endif()
if (_NEED5)
#set(_MSG 1)
#if (Qt5_FOUND)
# set(_MSG 0)
#endif()
find_package(Qt5 COMPONENTS Core LinguistTools UiPlugin Widgets ${_QCOMP} ${_QUIET})
if (DEFINED ANDROID_PLATFORM)
set(CMAKE_SHARED_MODULE_SUFFIX_CXX ".so")
set(CMAKE_SHARED_LIBRARY_SUFFIX_CXX ".so")
set(CMAKE_SHARED_MODULE_SUFFIX_C ".so")
set(CMAKE_SHARED_LIBRARY_SUFFIX_C ".so")
endif()
if (Qt5_FOUND)
set(LOCAL_FOUND5 1)
set(_Qt5Modules)
foreach(m ${_QCOMP})
if (${Qt5${m}_FOUND})
set(__lib ${Qt5${m}_LIBRARIES})
if (DEFINED ANDROID_PLATFORM)
if (m IN_LIST __qt_bug_modules)
get_target_property(__lib Qt5::${m} LOCATION)
endif()
endif()
list(APPEND _Qt5Modules ${m})
list(APPEND Qt5_INCLUDES ${Qt5${m}_INCLUDE_DIRS})
list(APPEND Qt5_LIBRARIES ${__lib})
endif()
endforeach()
#get_property(_up_dir TARGET Qt5::UiPlugin PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
#message("${_up_dir}")
#if (NOT "x${_up_dir}" STREQUAL "x")
# list(APPEND Qt5_INCLUDES ${_up_dir})
#endif()
get_target_property(_Qt5_qmake Qt5::qmake LOCATION)
get_filename_component(Qt5_BIN ${_Qt5_qmake} PATH)
foreach(_p ${Qt5Gui_PLUGINS})
get_target_property(_l ${_p} LOCATION)
get_filename_component(_l ${_l} DIRECTORY)
string(FIND "${_l}" "/" _ind REVERSE)
string(SUBSTRING "${_l}" 0 ${_ind} _l)
set(Qt5_PLUGINS_DIR ${_l})
#message("Qt5: plugins dir: ${Qt5_PLUGINS_DIR}")
break()
endforeach()
string(FIND "${Qt5_BIN}" "/" _ind REVERSE)
string(SUBSTRING "${Qt5_BIN}" 0 ${_ind} Qt5_ROOT)
if ("x${Qt5_PLUGINS_DIR}" STREQUAL "x")
set(Qt5_PLUGINS_DIR "${Qt5_ROOT}/plugins")
endif()
if (APPLE)
list(APPEND MOC_INC_Qt5 "-F${Qt5_ROOT}/lib")
endif()
set(Qt5_LANG_DIR ${Qt5_BIN}/../translations)
if (NOT _QT5_MSG)
message(STATUS "Found Qt5: ${_Qt5_qmake} (version \"${Qt5_VERSION}\")")
set(_QT5_MSG 1 CACHE BOOL "msg_qt5" FORCE)
#message(STATUS "Found Qt5 modules: ${_Qt5Modules}")
endif()
endif()
endif()
foreach(_v ${_QT_VERSIONS_})
if (LOCAL_FOUND${_v})
foreach(_p ${Qt${_v}_INCLUDES})
list(APPEND MOC_INC_Qt${_v} "-I${_p}")
#message("${_p}")
endforeach()
endif()
#message("${MOC_INC_Qt${_v}}")
endforeach()
endmacro()
macro(qt_sources OUT)
set(${OUT})
set(_DIR "")
set(_IS_DIR 0)
set(_NO_DEFAULT 0)
set(_DEFAULT)
set(_REGEXP)
set(_REGEXP_WD)
foreach(_i ${ARGN})
if (_IS_DIR)
set(_DIR "${_i}")
set(_IS_DIR 0)
elseif ("x${_i}" STREQUAL "xDIR")
set(_IS_DIR 1)
elseif ("x${_i}" STREQUAL "xNO_DEFAULT")
set(_NO_DEFAULT 1)
else()
list(APPEND _REGEXP ${_i})
endif()
endforeach()
if (NOT "x${_DIR}" STREQUAL "x")
#file(TO_CMAKE_PATH "${_DIR}//" _DIR)
string(REPLACE "\\" "/" _DIR "${_DIR}/")
string(REPLACE "//" "/" _DIR "${_DIR}")
endif()
foreach(_i ${_REGEXP})
list(APPEND _REGEXP_WD "${_DIR}${_i}")
endforeach()
if (NOT _NO_DEFAULT)
set(_DEFAULT "${_DIR}*.h" "${_DIR}*.hpp" "${_DIR}*.c" "${_DIR}*.cpp" "${_DIR}*.ui" "${_DIR}*.qrc" "${_DIR}*.rc" "${_DIR}*.ts" "${_DIR}lang/*.ts")
endif()
#message("${_DEFAULT}, ${_REGEXP_WD}")
file(GLOB ${OUT} ${_DEFAULT} ${_REGEXP_WD})
endmacro()
macro(qt_wrap)
set(HDR_VAR)
set(CPP_VAR)
set(QM_VAR)
set(_HDR_ARG 0)
set(_CPP_ARG 0)
set(_QM_ARG 0)
set(WAS_HDR_ARG 0)
set(WAS_CPP_ARG 0)
set(WAS_QM_ARG 0)
set(FILE_LIST)
foreach(_i ${ARGN})
if (_HDR_ARG)
set(HDR_VAR ${_i})
set(WAS_HDR_ARG 1)
set(_HDR_ARG 0)
elseif (_CPP_ARG)
set(CPP_VAR ${_i})
set(WAS_CPP_ARG 1)
set(_CPP_ARG 0)
elseif (_QM_ARG)
set(QM_VAR ${_i})
set(WAS_QM_ARG 1)
set(_QM_ARG 0)
elseif ("x${_i}" STREQUAL "xHDRS")
set(_HDR_ARG 1)
elseif ("x${_i}" STREQUAL "xCPPS")
set(_CPP_ARG 1)
elseif ("x${_i}" STREQUAL "xQMS")
set(_QM_ARG 1)
else()
list(APPEND FILE_LIST "${_i}")
endif()
endforeach()
foreach(_v ${_QT_VERSIONS_})
set(CPP${_v}_VAR)
set(QM${_v}_VAR)
if (LOCAL_FOUND${_v})
if (WAS_CPP_ARG)
set(CPP${_v}_VAR ${CPP_VAR}_Qt${_v})
endif()
if (WAS_QM_ARG)
set(QM${_v}_VAR ${QM_VAR}_Qt${_v})
endif()
endif()
endforeach()
#message("found 4: ${LOCAL_FOUND4}, 5: ${LOCAL_FOUND5}")
#message("has HRDS: ${WAS_HDR_ARG}: ${HDR_VAR}")
#message("has CPPS4: ${WAS_CPP_ARG}: ${CPP4_VAR}")
#message("has CPPS5: ${WAS_CPP_ARG}: ${CPP5_VAR}")
#message("files: ${FILE_LIST}")
set(H_LIST)
set(CPP_LIST)
set(UI_LIST)
set(RES_LIST)
set(RC_LIST)
set(TS_LIST)
foreach(_i ${FILE_LIST})
get_filename_component(_EXT "${_i}" EXT)
#message("${_EXT}")
if (NOT ("x${_EXT}" STREQUAL "x"))
if (("x${_EXT}" STREQUAL "x.h") OR ("x${_EXT}" STREQUAL "x.hpp"))
list(APPEND H_LIST "${_i}")
#message("header")
endif()
if (("x${_EXT}" STREQUAL "x.c") OR ("x${_EXT}" STREQUAL "x.cpp") OR ("x${_EXT}" STREQUAL "x.cxx"))
list(APPEND CPP_LIST "${_i}")
#message("source")
endif()
if ("x${_EXT}" STREQUAL "x.ui")
list(APPEND UI_LIST "${_i}")
endif()
if ("x${_EXT}" STREQUAL "x.qrc")
list(APPEND RES_LIST "${_i}")
endif()
if ("x${_EXT}" STREQUAL "x.rc")
list(APPEND RC_LIST "${_i}")
endif()
if ("x${_EXT}" STREQUAL "x.ts")
list(APPEND TS_LIST "${_i}")
endif()
endif()
endforeach()
if (WAS_HDR_ARG)
set(${HDR_VAR})
list(APPEND ${HDR_VAR} ${H_LIST})
endif()
set(SRC_CMAKE_CURRENT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
foreach(_v ${_QT_VERSIONS_})
if (LOCAL_FOUND${_v} AND WAS_CPP_ARG)
set(CMAKE_CURRENT_BINARY_DIR ${SRC_CMAKE_CURRENT_BINARY_DIR}/qt${_v})
set(${CPP${_v}_VAR})
if (WAS_QM_ARG)
set(${QM${_v}_VAR})
endif()
set(MOCS${_v})
set(CUIS${_v})
set(CRES${_v})
if (${_v} EQUAL 4)
qt4_wrap_cpp(MOCS${_v} ${H_LIST} OPTIONS -nw ${MOC_INC_Qt4})
qt4_wrap_ui(CUIS${_v} ${UI_LIST})
qt4_add_resources(CRES${_v} ${RES_LIST})
if (WAS_QM_ARG)
set(${QM${_v}_VAR} "")
qt4_add_translation(${QM${_v}_VAR} ${TS_LIST})
endif()
elseif (${_v} EQUAL 5)
qt5_wrap_cpp(MOCS${_v} ${H_LIST} OPTIONS -nw ${MOC_INC_Qt5})
qt5_wrap_ui(CUIS${_v} ${UI_LIST})
qt5_add_resources(CRES${_v} ${RES_LIST})
if (WAS_QM_ARG)
set(${QM${_v}_VAR} "")
qt5_add_translation(${QM${_v}_VAR} ${TS_LIST})
endif()
else()
# Qt6 ...
endif()
#message("${${QM${_v}_VAR}}")
list(APPEND ${CPP${_v}_VAR} ${CPP_LIST})
list(APPEND ${CPP${_v}_VAR} ${RC_LIST})
list(APPEND ${CPP${_v}_VAR} ${MOCS${_v}})
list(APPEND ${CPP${_v}_VAR} ${CUIS${_v}})
list(APPEND ${CPP${_v}_VAR} ${CRES${_v}})
if (WAS_QM_ARG)
list(APPEND ${CPP${_v}_VAR} ${${QM${_v}_VAR}})
endif()
#message("${${QM${_v}_VAR}}")
endif()
endforeach()
set(CMAKE_CURRENT_BINARY_DIR ${SRC_CMAKE_CURRENT_BINARY_DIR})
endmacro()
macro(_qt_split_add_args _P _A)
set(${_P})
set(${_A})
foreach(_i ${ARGN})
if (NOT ("x${${_i}_Qt${_v}}" STREQUAL "x"))
list(APPEND ${_A} ${${_i}_Qt${_v}})
elseif (("x${_i}" STREQUAL "xWIN32") OR
("x${_i}" STREQUAL "xMACOSX_BUNDLE") OR
("x${_i}" STREQUAL "xSTATIC") OR
("x${_i}" STREQUAL "xSHARED") OR
("x${_i}" STREQUAL "xMODULE") OR
("x${_i}" STREQUAL "xEXCLUDE_FROM_ALL"))
list(APPEND ${_P} ${_i})
elseif ("x${${_i}}" STREQUAL "x")
list(APPEND ${_A} ${_i})
else()
list(APPEND ${_A} ${${_i}})
endif()
endforeach()
endmacro()
macro(__qt_set_defines _NAME _T)
target_compile_definitions(${_T} PRIVATE "__TARGET_NAME__=\"${_NAME}\"")
target_compile_definitions(${_T} PRIVATE "__TARGET_LABEL__=\"${${_NAME}_LABEL}\"")
target_compile_definitions(${_T} PRIVATE "__TARGET_COMPANY__=\"${${_NAME}_COMPANY}\"")
target_compile_definitions(${_T} PRIVATE "__TARGET_VERSION__=\"${${_NAME}_VERSION}\"")
endmacro()
macro(qt_add_executable _NAME)
foreach(_v ${_QT_VERSIONS_})
if (LOCAL_FOUND${_v})
_qt_split_add_args(_PREF _ARGS ${ARGN})
if(APPLE)
set(_PREV_CIND "${CMAKE_INSTALL_NAME_DIR}")
set(CMAKE_INSTALL_NAME_DIR "@rpath")
else()
if(NOT WIN32)
set(CMAKE_INSTALL_RPATH "\$ORIGIN;\$ORIGIN/lib")
endif()
endif()
set(_TARGET ${_NAME}${TARGET_SUFFIX_Qt${_v}})
add_executable(${_TARGET} ${_PREF} ${_ARGS})
set(_${_NAME}_is_qt 1)
target_include_directories(${_TARGET} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/qt${_v} ${Qt${_v}_INCLUDES})
__qt_set_defines(${_NAME} ${_TARGET})
if(APPLE)
set(CMAKE_INSTALL_NAME_DIR "${_PREV_CIND}")
endif()
# # Apple crosscompiling rpath patch
# if (APPLE AND CMAKE_CROSSCOMPILING AND CMAKE_MACOSX_RPATH)
# foreach(_RP ${CMAKE_INSTALL_RPATH})
# add_custom_command(TARGET ${_TARGET} POST_BUILD
# COMMAND "${CMAKE_INSTALL_NAME_TOOL}"
# "-add_rpath" "${_RP}"
# "$<TARGET_FILE_DIR:${_TARGET}>/$<TARGET_FILE_NAME:${_TARGET}>"
# COMMENT "Add to ${_TARGET} rpath \"${_RP}\"")
# endforeach()
# endif()
#list(APPEND _ALL_TARGETS "${_TARGET}")
#set(_ALL_TARGETS ${_ALL_TARGETS} PARENT_SCOPE)
endif()
endforeach()
endmacro()
macro(qt_add_library _NAME)
foreach(_v ${_QT_VERSIONS_})
if (LOCAL_FOUND${_v})
_qt_split_add_args(_PREF _ARGS ${ARGN})
if(APPLE)
set(_PREV_CIND "${CMAKE_INSTALL_NAME_DIR}")
set(CMAKE_INSTALL_NAME_DIR "@rpath")
else()
if(NOT WIN32)
set(CMAKE_INSTALL_RPATH "\$ORIGIN;\$ORIGIN/lib")
endif()
endif()
set(_TARGET ${_NAME}${TARGET_SUFFIX_Qt${_v}})
add_library(${_TARGET} ${_PREF} ${_ARGS})
set(_${_NAME}_is_qt 1)
target_include_directories(${_TARGET} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/qt${_v} ${Qt${_v}_INCLUDES})
__qt_set_defines(${_NAME} ${_TARGET})
#message("add lib: \"${_TARGET}\"")
if(APPLE)
set(CMAKE_INSTALL_NAME_DIR "${_PREV_CIND}")
endif()
# # Apple crosscompiling rpath patch
# if (APPLE AND CMAKE_CROSSCOMPILING AND CMAKE_MACOSX_RPATH)
# foreach(_RP ${CMAKE_INSTALL_RPATH})
# add_custom_command(TARGET ${_TARGET} POST_BUILD
# COMMAND "${CMAKE_INSTALL_NAME_TOOL}"
# "-add_rpath" "${_RP}"
# "$<TARGET_FILE_DIR:${_TARGET}>/$<TARGET_FILE_NAME:${_TARGET}>"
# COMMENT "Add to ${_TARGET} rpath \"${_RP}\"")
# endforeach()
# endif()
list(APPEND _ALL_TARGETS "${_TARGET}")
set(_ALL_TARGETS ${_ALL_TARGETS} PARENT_SCOPE)
endif()
endforeach()
endmacro()
macro(_qt_multitarget_suffix_ _OUT _IN _v)
string(REPLACE ":" "_" _in_str "${_IN}")
if (NOT "x${MULTILIB_${_in_str}_SUFFIX_Qt${_v}}" STREQUAL "x")
set(${_OUT} "${MULTILIB_${_in_str}_SUFFIX_Qt${_v}}")
else()
set(${_OUT} "${MULTILIB_SUFFIX_Qt${_v}}")
endif()
endmacro()
macro(qt_target_link_libraries _NAME)
foreach(_v ${_QT_VERSIONS_})
if (LOCAL_FOUND${_v})
set(_TARGET ${_NAME}${TARGET_SUFFIX_Qt${_v}})
set(_ARGS)
foreach(_i ${ARGN})
set(_ind -1)
list(FIND QT_MULTILIB_LIST "${_i}" _ind)
if (_ind GREATER -1)
_qt_multitarget_suffix_(_TS ${_i} ${_v})
#message(STATUS "${_i} in MULTILIB_LIST, suffix = ${_TS}")
list(APPEND _ARGS ${_i}${_TS})
else()
list(APPEND _ARGS ${_i})
endif()
endforeach()
target_link_libraries(${_TARGET} ${Qt${_v}_LIBRARIES} ${_ARGS})
#message("link ${_TARGET}: ${Qt${_v}_LIBRARIES} ${_ARGS}")
endif()
endforeach()
endmacro()
macro(qt_target_compile_definitions _NAME)
foreach(_v ${_QT_VERSIONS_})
if (LOCAL_FOUND${_v})
set(_TARGET ${_NAME}${TARGET_SUFFIX_Qt${_v}})
target_compile_definitions(${_TARGET} ${ARGN})
endif()
endforeach()
endmacro()
macro(qt_target_include_directories _NAME)
foreach(_v ${_QT_VERSIONS_})
if (LOCAL_FOUND${_v})
set(_TARGET ${_NAME}${TARGET_SUFFIX_Qt${_v}})
target_include_directories(${_TARGET} ${ARGN})
endif()
endforeach()
endmacro()
macro(qt_install)
set(_prev_inst)
set(__add_args)
#message("command: ${ARGN}")
foreach(_v ${_QT_VERSIONS_})
if (LOCAL_FOUND${_v})
set(_INST_LIST)
set(_IS_TARGET 0)
set(_IS_FILES 0)
set(_IS_DEST 0)
set(_IS_LANG 0)
set(_INVALID 0)
foreach(_i ${ARGN})
if ("x${_i}" STREQUAL "xQtLang")
set(_IS_LANG 1)
endif()
endforeach()
foreach(_i ${ARGN})
if (_IS_TARGET)
set(_IS_TARGET 0)
set(__target ${_i})
if (_${_i}_is_qt)
set(__target ${_i}${TARGET_SUFFIX_Qt${_v}})
endif()
if (DEFINED ANDROID_PLATFORM)
get_target_property(_TT ${__target} TYPE)
if ("x${_TT}" STREQUAL "xEXECUTABLE")
list(APPEND __add_args EXCLUDE_FROM_ALL)
endif()
endif()
list(APPEND _INST_LIST ${__target})
elseif (_IS_FILES)
set(_IS_FILES 0)
if (_IS_LANG)
if (("x${${_i}_Qt${_v}}" STREQUAL "x") OR ("x${_i}" STREQUAL "xDESTINATION"))
set(_INVALID 1)
else()
list(APPEND _INST_LIST ${${_i}_Qt${_v}})
endif()
else()
list(APPEND _INST_LIST ${_i})
endif()
else()
if (_IS_DEST)
set(_IS_DEST 0)
if ("x${_i}" STREQUAL "xQtBin")
list(APPEND _INST_LIST "${Qt${_v}_BIN}")
elseif ("x${_i}" STREQUAL "xQtLang")
list(APPEND _INST_LIST "${Qt${_v}_LANG_DIR}")
else()
set(_ind -1)
string(FIND "${_i}" "QtPlugins" _ind)
if (_ind GREATER -1)
string(REPLACE "QtPlugins" "${Qt${_v}_PLUGINS_DIR}" _o "${_i}")
list(APPEND _INST_LIST "${_o}")
else()
string(REPLACE "\\" "/" _o "${_i}")
list(APPEND _INST_LIST ${_o})
endif()
endif()
else()
set(_ii ${_i})
if ("x${_i}" STREQUAL "xTARGETS")
set(_IS_TARGET 1)
elseif ("x${_i}" STREQUAL "xFILES")
set(_IS_FILES 1)
elseif ("x${_i}" STREQUAL "xDESTINATION")
set(_IS_DEST 1)
elseif ("x${_i}" STREQUAL "xLANG")
set(_IS_FILES 1)
set(_IS_LANG 1)
set(_ii "FILES")
endif()
list(APPEND _INST_LIST ${_ii})
endif()
endif()
endforeach()
if (NOT _INVALID)
if (NOT ("x${_prev_inst}" STREQUAL "x${_INST_LIST}"))
#message("install: ${_INST_LIST}")
install(${_INST_LIST} ${__add_args})
set(_prev_inst "${_INST_LIST}")
endif()
endif()
endif()
endforeach()
endmacro()
macro(qt_install_lang _NAME)
set(_prev_inst)
#message("command: ${ARGN}")
set(_PATHS)
set(_DEST)
if(CMAKE_CROSSCOMPILING)
list(APPEND _PATHS "${CMAKE_PREFIX_PATH}/lang")
endif()
set(_cur_arg)
set(__args "DESTINATION;PATHS")
foreach(_i ${ARGN})
if (_i IN_LIST __args)
set(_cur_arg "${_i}")
elseif("${_cur_arg}" STREQUAL "DESTINATION")
set(_DEST "${_i}")
elseif("${_cur_arg}" STREQUAL "PATHS")
list(APPEND _PATHS "${_i}")
endif()
endforeach()
foreach(_v ${_QT_VERSIONS_})
if (LOCAL_FOUND${_v})
set(_target)
if (_${_NAME}_is_qt)
set(_target ${_NAME}${TARGET_SUFFIX_Qt${_v}})
endif()
get_target_property(_LL ${_target} LINK_LIBRARIES)
foreach (_L ${_LL})
get_filename_component(_libname "${_L}" NAME_WE)
#message("depend on ${_libname}")
if ("${_libname}" MATCHES "Qt${_v}::.*")
string(SUBSTRING "${_libname}" 5 -1 _libname)
string(TOLOWER "${_libname}" _libname)
#message("qt lib \"${_libname}\"")
list(APPEND _qt_libs qt${_libname})
else()
if ("${_libname}" MATCHES "lib.*")
string(LENGTH ${_libname} _sl)
math(EXPR _sl ${_sl}-3)
string(SUBSTRING ${_libname} 3 ${_sl} _libname)
endif()
if ("${_libname}" MATCHES "qad_.*${_v}")
string(LENGTH ${_libname} _sl)
math(EXPR _sl ${_sl}-1)
string(SUBSTRING ${_libname} 0 ${_sl} _libname)
#message("qad lib \"${_libname}\"")
list(APPEND _qt_libs ${_libname})
endif()
endif()
endforeach()
if (NOT "x${_qt_libs}" STREQUAL "x")
list(APPEND _qt_libs "qtbase")
foreach (_i ${${PROJECT_NAME}_LANG})
foreach (_l ${_qt_libs})
unset(_qm_path CACHE)
find_file(_qm_path "${_l}_${_i}.qm" PATHS "${Qt${_v}_LANG_DIR}" ${_PATHS} NO_DEFAULT_PATH)
if (EXISTS "${_qm_path}")
install(FILES ${_qm_path} DESTINATION "${_DEST}")
#message("qm = \"${_qm_path}\"")
endif()
endforeach()
endforeach()
endif()
endif()
endforeach()
endmacro()
macro(qt_get_target _NAME _OUT)
set(${_OUT})
set(_ver)
foreach(_i ${ARGN})
foreach(_v ${_QT_VERSIONS_})
if ("x${_i}" STREQUAL "xQt${_v}")
set(_ver ${_v})
break()
endif()
endforeach()
if (NOT "x${_ver}" STREQUAL "x")
break()
endif()
endforeach()
foreach(_v ${_QT_VERSIONS_})
if (LOCAL_FOUND${_v} AND (("x${_ver}" STREQUAL "x") OR ((NOT "x${_ver}" STREQUAL "x") AND ("x${_ver}" STREQUAL "x${_v}"))))
set(${_OUT} ${_NAME}${TARGET_SUFFIX_Qt${_v}})
endif()
endforeach()
endmacro()
macro(qt_get_targets _NAME _OUT)
set(${_OUT})
foreach(_v ${_QT_VERSIONS_})
if (LOCAL_FOUND${_v})
list(APPEND ${_OUT} ${_NAME}${TARGET_SUFFIX_Qt${_v}})
endif()
endforeach()
endmacro()
macro(qt_generate_export_header _NAME)
qt_get_target(${_NAME} _some_target)
qt_get_target(${_NAME} _targets)
foreach(_t ${_targets})
set_target_properties(${_t} PROPERTIES DEFINE_SYMBOL ${_NAME}_EXPORTS)
endforeach()
set_target_properties(${_some_target} PROPERTIES DEFINE_SYMBOL ${_NAME}_EXPORTS)
generate_export_header(${_some_target} BASE_NAME "${_NAME}" ${ARGN})
endmacro()

View File

@@ -114,7 +114,7 @@
<string>OK</string>
</property>
<property name="icon">
<iconset resource="../widgets/qad_widgets.qrc">
<iconset resource="qad_application.qrc">
<normaloff>:/icons/dialog-ok-apply.png</normaloff>:/icons/dialog-ok-apply.png</iconset>
</property>
</widget>
@@ -131,7 +131,6 @@
</customwidget>
</customwidgets>
<resources>
<include location="../widgets/qad_widgets.qrc"/>
<include location="qad_application.qrc"/>
</resources>
<connections>

View File

@@ -1,34 +1,17 @@
<RCC>
<qresource prefix="/">
<file>../../icons/application-exit.png</file>
<file>../../icons/dialog-close.png</file>
<file>../../icons/dialog-ok-apply.png</file>
<file>../../icons/configure.png</file>
<file>../../icons/document-edit.png</file>
<file>../../icons/document-new.png</file>
<file>../../icons/document-save.png</file>
<file>../../icons/document-save-all.png</file>
<file>../../icons/document-save-as.png</file>
<file>../../icons/document-open.png</file>
<file>../../icons/document-open-recent.png</file>
<file>../../icons/document-close.png</file>
<file>../../icons/edit-clear.png</file>
<file>../../icons/edit-clear-locationbar-rtl.png</file>
<file>../../icons/edit-find.png</file>
<file>../../icons/list-add.png</file>
<file>../../icons/edit-delete.png</file>
<file>../../icons/edit-copy.png</file>
<file>../../icons/edit-paste.png</file>
<file>../../icons/edit-undo.png</file>
<file>../../icons/edit-redo.png</file>
<file>../../icons/border-line.png</file>
<file>../../icons/edockwidget.png</file>
<file>../../icons/historyview.png</file>
<file>../../icons/logview.png</file>
<file>../../icons/clear-history.png</file>
<file>../../icons/layer-visible-off.png</file>
<file>../../icons/layer-visible-on.png</file>
<file>../../icons/logview.png</file>
<file>../../icons/qt.png</file>
<file>../../icons/select-all.png</file>
<file>../../icons/select-none.png</file>
</qresource>
</RCC>

View File

@@ -194,7 +194,7 @@
<string>Add</string>
</property>
<property name="icon">
<iconset resource="../utils/qad_utils.qrc">
<iconset resource="qad_blockview.qrc">
<normaloff>:/icons/list-add.png</normaloff>:/icons/list-add.png</iconset>
</property>
</widget>
@@ -205,7 +205,7 @@
<string>Clone</string>
</property>
<property name="icon">
<iconset resource="../utils/qad_utils.qrc">
<iconset resource="qad_blockview.qrc">
<normaloff>:/icons/edit-copy.png</normaloff>:/icons/edit-copy.png</iconset>
</property>
</widget>
@@ -232,7 +232,7 @@
<string>Remove selected</string>
</property>
<property name="icon">
<iconset resource="../utils/qad_utils.qrc">
<iconset resource="qad_blockview.qrc">
<normaloff>:/icons/edit-delete.png</normaloff>:/icons/edit-delete.png</iconset>
</property>
</widget>
@@ -243,7 +243,7 @@
<string>Remove all</string>
</property>
<property name="icon">
<iconset resource="../utils/qad_utils.qrc">
<iconset resource="qad_blockview.qrc">
<normaloff>:/icons/edit-clear.png</normaloff>:/icons/edit-clear.png</iconset>
</property>
</widget>
@@ -346,7 +346,7 @@
<string>Save</string>
</property>
<property name="icon">
<iconset resource="../utils/qad_utils.qrc">
<iconset resource="qad_blockview.qrc">
<normaloff>:/icons/document-save.png</normaloff>:/icons/document-save.png</iconset>
</property>
<property name="shortcut">
@@ -376,7 +376,7 @@
<string>Save as ...</string>
</property>
<property name="icon">
<iconset resource="../utils/qad_utils.qrc">
<iconset resource="qad_blockview.qrc">
<normaloff>:/icons/document-save.png</normaloff>:/icons/document-save.png</iconset>
</property>
<property name="shortcut">
@@ -406,7 +406,7 @@
<string>Load ...</string>
</property>
<property name="icon">
<iconset resource="../application/qad_application.qrc">
<iconset resource="qad_blockview.qrc">
<normaloff>:/icons/document-open.png</normaloff>:/icons/document-open.png</iconset>
</property>
<property name="shortcut">
@@ -433,7 +433,7 @@
<string>Clear</string>
</property>
<property name="icon">
<iconset resource="../utils/qad_utils.qrc">
<iconset resource="qad_blockview.qrc">
<normaloff>:/icons/edit-clear.png</normaloff>:/icons/edit-clear.png</iconset>
</property>
</widget>
@@ -443,7 +443,7 @@
</layout>
<action name="actionRemove_items">
<property name="icon">
<iconset resource="../utils/qad_utils.qrc">
<iconset resource="qad_blockview.qrc">
<normaloff>:/icons/edit-delete.png</normaloff>:/icons/edit-delete.png</iconset>
</property>
<property name="text">
@@ -467,8 +467,6 @@
</customwidget>
</customwidgets>
<resources>
<include location="../utils/qad_utils.qrc"/>
<include location="../application/qad_application.qrc"/>
<include location="qad_blockview.qrc"/>
</resources>
<connections>

View File

@@ -94,7 +94,7 @@
<string>Edit text ...</string>
</property>
<property name="icon">
<iconset resource="../application/qad_application.qrc">
<iconset resource="qad_blockview.qrc">
<normaloff>:/icons/document-edit.png</normaloff>:/icons/document-edit.png</iconset>
</property>
<property name="toolButtonStyle">
@@ -591,7 +591,7 @@
<string>Load image ...</string>
</property>
<property name="icon">
<iconset resource="../application/qad_application.qrc">
<iconset resource="qad_blockview.qrc">
<normaloff>:/icons/document-open.png</normaloff>:/icons/document-open.png</iconset>
</property>
</widget>
@@ -814,7 +814,6 @@
</customwidget>
</customwidgets>
<resources>
<include location="../application/qad_application.qrc"/>
<include location="qad_blockview.qrc"/>
</resources>
<connections/>

View File

@@ -1,39 +1,16 @@
<RCC>
<qresource prefix="/">
<file>../../icons/draw-line.png</file>
<file>../../icons/align-hor.png</file>
<file>../../icons/align-ver.png</file>
<file>../../icons/dialog-close.png</file>
<file>../../icons/edit-clear.png</file>
<file>../../icons/edit-guides.png</file>
<file>../../icons/view-grid.png</file>
<file>../../icons/zoom-fit-best.png</file>
<file>../../icons/configure.png</file>
<file>../../icons/document-save.png</file>
<file>../../icons/edit-clear-locationbar-rtl.png</file>
<file>../../icons/edit-find.png</file>
<file>../../icons/list-add.png</file>
<file>../../icons/edit-delete.png</file>
<file>../../icons/item.png</file>
<file>../../icons/node-add.png</file>
<file>../../icons/node.png</file>
<file>../../icons/edit-copy.png</file>
<file>../../icons/edit-paste.png</file>
<file>../../icons/expand_s_x.png</file>
<file>../../icons/expand_s_y.png</file>
<file>../../icons/expand_x.png</file>
<file>../../icons/expand_y.png</file>
<file>../../icons/border-line.png</file>
<file>../../icons/legend.png</file>
<file>../../icons/blockview.png</file>
<file>../../icons/view-fullscreen.png</file>
<file>../../icons/draw-line.png</file>
<file>../../icons/draw-ellipse.png</file>
<file>../../icons/draw-rectangle.png</file>
<file>../../icons/draw-text.png</file>
<file>../../icons/view-preview.png</file>
<file>../../icons/format-fill-color.png</file>
<file>../../icons/format-stroke-color.png</file>
<file>../../icons/document-open.png</file>
<file>../../icons/z-bottom.png</file>
<file>../../icons/z-down.png</file>
<file>../../icons/z-top.png</file>
<file>../../icons/z-up.png</file>
<file>../../icons/align-hor.png</file>
<file>../../icons/align-ver.png</file>
<file>../../icons/align-bottom-center.png</file>
<file>../../icons/align-bottom-left.png</file>
<file>../../icons/align-bottom-right.png</file>
@@ -43,9 +20,15 @@
<file>../../icons/align-top-center.png</file>
<file>../../icons/align-top-left.png</file>
<file>../../icons/align-top-right.png</file>
<file>../../icons/z-bottom.png</file>
<file>../../icons/z-down.png</file>
<file>../../icons/z-top.png</file>
<file>../../icons/z-up.png</file>
<file>../../icons/dialog-close.png</file>
<file>../../icons/edit-clear.png</file>
<file>../../icons/edit-delete.png</file>
<file>../../icons/edit-copy.png</file>
<file>../../icons/document-save.png</file>
<file>../../icons/document-open.png</file>
<file>../../icons/document-edit.png</file>
<file>../../icons/view-preview.png</file>
<file>../../icons/format-fill-color.png</file>
<file>../../icons/format-stroke-color.png</file>
</qresource>
</RCC>

View File

@@ -17,9 +17,11 @@ else()
endif()
find_library(MARKDOWN_LIBRARY markdown)
if (MARKDOWN_LIBRARY)
if(_mkd_header_found)
qad_library(doc "Core" "${MARKDOWN_LIBRARY}")
else()
qad_library(doc "Core" "${MARKDOWN_LIBRARY}")
if(NOT _mkd_header_found)
message(STATUS "Found markdown library, but *.h missing!")
endif()
else()
add_definitions("-DNO_MARKDOWN")
qad_library(doc "Core" "")
endif()

View File

@@ -1,5 +1,6 @@
#include "markdown.h"
#include <QDebug>
#ifndef NO_MARKDOWN
extern "C" {
#include MARKDOWN_HEADER
}
@@ -77,3 +78,10 @@ QString md2html(const QByteArray & src) {
return ret;
}
#else
QString md2html(const QByteArray & src) {
return src;
}
#endif

View File

@@ -8,6 +8,7 @@
#include <QTapAndHoldGesture>
#include <QPanGesture>
#include <QPinchGesture>
#include <QActionGroup>
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
# include <QRandomGenerator>
#endif
@@ -37,6 +38,20 @@ Graphic::Graphic(QWidget * parent): QFrame(parent), canvas(0), line_x_min(this),
#endif
ui = new Ui::Graphic();
ui->setupUi(this);
QActionGroup * agroup = new QActionGroup(this);
agroup->addAction(ui->actionGuidesFree );
agroup->addAction(ui->actionGuidesTraceX);
agroup->addAction(ui->actionGuidesTraceY);
ui->actionGuidesFree ->setProperty("_value", (int)Free );
ui->actionGuidesTraceX->setProperty("_value", (int)TraceX);
ui->actionGuidesTraceY->setProperty("_value", (int)TraceY);
ui->actionGuidesFree->setChecked(true);
connect(agroup, SIGNAL(triggered(QAction*)), this, SLOT(actionGuidesTriggered(QAction*)));
ui->checkGuides->addAction(ui->actionGuidesFree );
ui->checkGuides->addAction(ui->actionGuidesTraceX);
ui->checkGuides->addAction(ui->actionGuidesTraceY);
ui->buttonAutofit->addAction(ui->actionExpandX);
ui->buttonAutofit->addAction(ui->actionExpandY);
line_x_min.setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
line_x_max.setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
((QBoxLayout * )ui->widgetLY->layout())->insertWidget(0, &line_y_min);
@@ -76,6 +91,7 @@ Graphic::Graphic(QWidget * parent): QFrame(parent), canvas(0), line_x_min(this),
emaxx = emaxy = DBL_MIN;
grad_x = grad_y = Auto;
axis_type_x = Numeric;
floating_axis_type = Free;
min_repaint_int = 25;
inc_x = 1.;
buffer = 0;
@@ -374,10 +390,7 @@ void Graphic::canvasMousePressEvent(QMouseEvent * e) {
emit graphicMousePressEvent(canvas2real(QPointF(e->pos())), e->button());
if (!navigation) return;
if (gestures && !need_mouse_pan) return;
#ifdef HAS_GL
canvas_gl->setCursor(guides ? Qt::BlankCursor : Qt::ArrowCursor);
#endif
ui->canvas_raster->setCursor(guides ? Qt::BlankCursor : Qt::ArrowCursor);
setGuidesCursor();
prevpos = e->pos();
startpos = prevpos;
startpos_r = canvas2real(startpos);
@@ -393,7 +406,7 @@ void Graphic::canvasMousePressEvent(QMouseEvent * e) {
return;
} else {
prevaction = curaction;
curaction = gaMove;
setCurrentAction(gaMove);
return;
}
}
@@ -419,10 +432,7 @@ void Graphic::canvasMouseReleaseEvent(QMouseEvent * e) {
if (gestures) return;
need_mouse_pan = false;
if (!navigation) return;
#ifdef HAS_GL
canvas_gl->setCursor(guides ? Qt::BlankCursor : Qt::ArrowCursor);
#endif
ui->canvas_raster->setCursor(guides ? Qt::BlankCursor : Qt::ArrowCursor);
setGuidesCursor();
QPointF tlp, brp;
QRect sr;
sr = QRect(startpos, curpos).normalized();
@@ -585,18 +595,12 @@ void Graphic::setMaxVisibleTime(double val) {
void Graphic::setOnlyExpandY(bool yes) {
only_expand_y = yes;
ui->checkExpandY->blockSignals(true);
ui->checkExpandY->setCheckable(yes);
ui->checkExpandY->blockSignals(false);
ui->actionExpandY->setChecked(yes);
}
void Graphic::setOnlyExpandX(bool yes) {
only_expand_x = yes;
ui->checkExpandX->blockSignals(true);
ui->checkExpandX->setCheckable(yes);
ui->checkExpandX->blockSignals(false);
ui->actionExpandX->setChecked(yes);
}
@@ -647,8 +651,6 @@ void Graphic::setButtons(Graphic::Buttons b) {
ui->buttonAutofit->setVisible(b.testFlag(Autofit));
ui->checkGrid->setVisible(b.testFlag(Grid));
ui->checkGuides->setVisible(b.testFlag(CursorAxis));
ui->checkExpandY->setVisible(b.testFlag(OnlyExpandY));
ui->checkExpandX->setVisible(b.testFlag(OnlyExpandX));
ui->buttonFullscreen->setVisible(b.testFlag(Fullscreen));
ui->checkBorderInputs->setVisible(b.testFlag(BorderInputs));
ui->checkLegend->setVisible(b.testFlag(Legend));
@@ -1149,14 +1151,58 @@ void Graphic::drawGuides() {
painter->resetTransform();
painter->setClipping(true);
painter->setClipRect(QRect(gridborder.x(), 0, wid - gridborder.x(), hei - gridborder.y()));
painter->drawLine(0, curpos.y(), wid, curpos.y());
painter->drawLine(curpos.x(), 0, curpos.x(), hei);
QString str = pointCoords(canvas2real(curpos)) + fp_size;
QPoint apos = curpos;
QPointF rpos = canvas2real(apos);
QString str;
str = pointCoords(rpos) + fp_size;
switch (floating_axis_type) {
case TraceX:
if (curGraphic >= 0 && curGraphic < graphics.size()) {
QPolygonF & pol(pause_ ? graphics[curGraphic].polyline_pause : graphics[curGraphic].polyline);
double cursor = rpos.x(), min_dist = -1, dist = 0.;
int index = -1;
for (int i = 0; i < pol.size(); ++i) {
dist = qAbs<double>(pol[i].x() - cursor);
if (min_dist > dist || min_dist < 0) {
min_dist = dist;
index = i;
}
}
if (index >= 0) {
rpos = pol[index];
apos = real2canvas(rpos).toPoint();
str = pointCoords(pol[index]) + fp_size;
}
}
break;
case TraceY:
if (curGraphic >= 0 && curGraphic < graphics.size()) {
QPolygonF & pol(pause_ ? graphics[curGraphic].polyline_pause : graphics[curGraphic].polyline);
double cursor = rpos.y(), min_dist = -1, dist = 0.;
int index = -1;
for (int i = 0; i < pol.size(); ++i) {
dist = qAbs<double>(pol[i].y() - cursor);
if (min_dist > dist || min_dist < 0) {
min_dist = dist;
index = i;
}
}
if (index >= 0) {
rpos = pol[index];
apos = real2canvas(rpos).toPoint();
str = pointCoords(pol[index]) + fp_size;
}
}
break;
default: break;
}
painter->drawLine(0, apos.y(), wid, apos.y());
painter->drawLine(apos.x(), 0, apos.x(), hei);
QPoint p = apos + QPoint(font_sz.height() / 4., -font_sz.height() / 4.);
QFontMetrics fm(font());
QRect r = fm.boundingRect(str);
QPoint p = curpos + QPoint(font_sz.height() / 4., -font_sz.height() / 4.);
if (r.width() + curpos.x() > wid - font_sz.height() / 2.) p.setX(curpos.x() - r.width() - font_sz.height() / 4.);
if (curpos.y() - r.height() < font_sz.height() / 8.) p.setY(curpos.y() + r.height() - font_sz.height() / 8.);
if (r.width() + apos.x() > wid - font_sz.height() / 2.) p.setX(apos.x() - r.width() - font_sz.height() / 4.);
if (apos.y() - r.height() < font_sz.height() / 8.) p.setY(apos.y() + r.height() - font_sz.height() / 8.);
painter->setPen(text_color);
painter->drawText(p, str);
}
@@ -1287,8 +1333,7 @@ void Graphic::setCurrentAction(GraphicAction action) {
curaction = action;
switch (action) {
case gaNone:
if (guides) setCanvasCursor(Qt::BlankCursor);
else setCanvasCursor(Qt::ArrowCursor);
setGuidesCursor();
break;
case gaZoomInRect:
setCanvasCursor(Qt::CrossCursor);
@@ -1314,6 +1359,14 @@ void Graphic::setCanvasCursor(QCursor cursor) {
}
void Graphic::setGuidesCursor() {
if (guides) {
setCanvasCursor(floating_axis_type == Free ? Qt::BlankCursor : Qt::CrossCursor);
} else
setCanvasCursor(Qt::ArrowCursor);
}
void Graphic::swapToBuffer() {
QImage timg;
#ifdef HAS_GL
@@ -1461,8 +1514,7 @@ void Graphic::on_buttonConfigure_clicked() {
void Graphic::on_checkGuides_toggled(bool checked) {
guides = checked;
if (guides) setCanvasCursor(Qt::BlankCursor);
else setCanvasCursor(Qt::ArrowCursor);
setGuidesCursor();
update();
}
@@ -1733,13 +1785,19 @@ void Graphic::setLegendVisible(bool visible) {
}
void Graphic::on_checkExpandY_toggled(bool checked) {
only_expand_y = checked;
ui->checkExpandY->setIcon(checked ? icon_exp_y : icon_exp_sy);
}
void Graphic::on_checkExpandX_toggled(bool checked) {
void Graphic::on_actionExpandX_triggered(bool checked) {
only_expand_x = checked;
ui->checkExpandX->setIcon(checked ? icon_exp_x : icon_exp_sx);
ui->actionExpandX->setIcon(checked ? icon_exp_x : icon_exp_sx);
}
void Graphic::on_actionExpandY_triggered(bool checked) {
only_expand_y = checked;
ui->actionExpandY->setIcon(checked ? icon_exp_y : icon_exp_sy);
}
void Graphic::actionGuidesTriggered(QAction * a) {
ui->checkGuides->setChecked(true);
setFloatingAxisType((FloatingAxisType)a->property("_value").toInt());
}

View File

@@ -53,7 +53,7 @@ class QAD_GRAPHIC_EXPORT Graphic: public QFrame
{
Q_OBJECT
Q_FLAGS(Buttons)
Q_ENUMS(Alignment Graduation AxisType)
Q_ENUMS(Alignment Graduation AxisType FloatingAxisType)
Q_PROPERTY(QString caption READ caption WRITE setCaption)
Q_PROPERTY(QString labelX READ labelX WRITE setLabelX)
@@ -113,6 +113,7 @@ class QAD_GRAPHIC_EXPORT Graphic: public QFrame
Q_PROPERTY(double graduationStepX READ graduationStepX WRITE setGraduationStepX)
Q_PROPERTY(double graduationStepY READ graduationStepY WRITE setGraduationStepY)
Q_PROPERTY(AxisType axisType READ axisType WRITE setAxisType)
Q_PROPERTY(FloatingAxisType floatingAxisType READ floatingAxisType WRITE setFloatingAxisType)
Q_PROPERTY(Graphic::GraphicsData graphicsData READ graphicsData WRITE setGraphicsData)
Q_PROPERTY(QByteArray graphicsDataRaw READ graphicsDataRaw WRITE setGraphicsDataRaw)
@@ -128,8 +129,6 @@ public:
Autofit = 0x01,
Grid = 0x02,
CursorAxis = 0x04,
OnlyExpandY = 0x08,
OnlyExpandX = 0x10,
Fullscreen = 0x20,
BorderInputs = 0x40,
Legend = 0x80,
@@ -143,6 +142,7 @@ public:
enum Alignment {Left, Right};
enum Graduation {Auto, Fixed};
enum AxisType {Numeric, DateTime};
enum FloatingAxisType {Free, TraceX, TraceY};
Q_DECLARE_FLAGS(Buttons, Button)
QString caption() const;
@@ -200,6 +200,7 @@ public:
double graduationStepX() const {return gridx;}
double graduationStepY() const {return gridy;}
AxisType axisType() const {return axis_type_x;}
FloatingAxisType floatingAxisType() const {return floating_axis_type;}
QVector<QPointF> graphicData(const int index = 0) const {return graphics[index].polyline;}
GraphicsData graphicsData() const;
QByteArray graphicsDataRaw() const;
@@ -294,6 +295,7 @@ public slots:
void setGraduationStepY(double sy) {gridy = sy; if (aupdate) update();}
void setGraduationSteps(double sx, double sy) {gridx = sx; gridy = sy; if (aupdate) update();}
void setAxisType(AxisType t) {axis_type_x = t; if (aupdate) update();}
void setFloatingAxisType(FloatingAxisType t) {floating_axis_type = t; setGuidesCursor(); if (aupdate) update();}
void addPoint(const QPointF & p, int graphic, bool update_ = true);
void addPoint(const QPointF & p, bool update = true) {addPoint(p, curGraphic, update);}
@@ -346,6 +348,7 @@ protected:
void updateLegend(bool es = true);
void updateLegendChecks();
void setCanvasCursor(QCursor cursor);
void setGuidesCursor();
void swapToBuffer();
void swapToNormal() {bufferActive = false;}
void setRectToLines();
@@ -388,6 +391,7 @@ protected:
QImage icon_pause_b, icon_pause_f;
Graduation grad_x, grad_y;
AxisType axis_type_x;
FloatingAxisType floating_axis_type;
double gridx, gridy, history, visible_time, inc_x, grid_numbers_x, grid_numbers_y, LN10;
double eminx, eminy, emaxx, emaxy, pause_phase, gesture_angle;
int lastw, lasth, min_repaint_int, timer_pause, thick;
@@ -417,11 +421,12 @@ protected slots:
void on_buttonSave_clicked() {saveImage();}
void on_checkGrid_toggled(bool checked) {grid = checked; update();}
void on_checkGuides_toggled(bool checked);
void on_checkExpandY_toggled(bool checked);
void on_checkExpandX_toggled(bool checked);
void on_actionExpandX_triggered(bool checked);
void on_actionExpandY_triggered(bool checked);
void on_checkBorderInputs_toggled(bool checked) {setBorderInputsVisible(checked);}
void on_checkLegend_toggled(bool checked) {setLegendVisible(checked);}
void on_checkPause_toggled(bool checked) {setPaused(checked);}
void actionGuidesTriggered(QAction * a);
void enterFullscreen();
void leaveFullscreen();
@@ -436,7 +441,6 @@ signals:
void cleared();
void visualRectChanged();
void graphicSettingsChanged();
};

View File

@@ -64,7 +64,7 @@
<string>Grid</string>
</property>
<property name="icon">
<iconset resource="../widgets/qad_widgets.qrc">
<iconset resource="qad_graphic.qrc">
<normaloff>:/icons/view-grid.png</normaloff>:/icons/view-grid.png</iconset>
</property>
<property name="checkable">
@@ -81,7 +81,7 @@
<string>Cursor axis</string>
</property>
<property name="icon">
<iconset resource="../widgets/qad_widgets.qrc">
<iconset resource="qad_graphic.qrc">
<normaloff>:/icons/edit-guides.png</normaloff>:/icons/edit-guides.png</iconset>
</property>
<property name="checkable">
@@ -89,41 +89,13 @@
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="checkExpandY">
<property name="toolTip">
<string>Only expand Y</string>
</property>
<property name="icon">
<iconset resource="../widgets/qad_widgets.qrc">
<normaloff>:/icons/expand_s_y.png</normaloff>:/icons/expand_s_y.png</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="checkExpandX">
<property name="toolTip">
<string>Only expand X</string>
</property>
<property name="icon">
<iconset resource="../widgets/qad_widgets.qrc">
<normaloff>:/icons/expand_s_x.png</normaloff>:/icons/expand_s_x.png</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="buttonFullscreen">
<property name="toolTip">
<string>Fullscreen</string>
</property>
<property name="icon">
<iconset resource="../blockview/qad_blockview.qrc">
<iconset resource="qad_graphic.qrc">
<normaloff>:/icons/view-fullscreen.png</normaloff>:/icons/view-fullscreen.png</iconset>
</property>
</widget>
@@ -134,7 +106,7 @@
<string>Border inputs</string>
</property>
<property name="icon">
<iconset resource="../widgets/qad_widgets.qrc">
<iconset resource="qad_graphic.qrc">
<normaloff>:/icons/border-line.png</normaloff>:/icons/border-line.png</iconset>
</property>
<property name="checkable">
@@ -151,7 +123,7 @@
<string>Legend</string>
</property>
<property name="icon">
<iconset resource="../widgets/qad_widgets.qrc">
<iconset resource="qad_graphic.qrc">
<normaloff>:/icons/legend.png</normaloff>:/icons/legend.png</iconset>
</property>
<property name="checkable">
@@ -182,7 +154,7 @@
<string>Configure ...</string>
</property>
<property name="icon">
<iconset resource="../widgets/qad_widgets.qrc">
<iconset resource="qad_graphic.qrc">
<normaloff>:/icons/configure.png</normaloff>:/icons/configure.png</iconset>
</property>
</widget>
@@ -193,7 +165,7 @@
<string>Save image ...</string>
</property>
<property name="icon">
<iconset resource="../utils/qad_utils.qrc">
<iconset resource="qad_graphic.qrc">
<normaloff>:/icons/document-save.png</normaloff>:/icons/document-save.png</iconset>
</property>
</widget>
@@ -220,7 +192,7 @@
<string>Clear</string>
</property>
<property name="icon">
<iconset resource="../utils/qad_utils.qrc">
<iconset resource="qad_graphic.qrc">
<normaloff>:/icons/edit-clear.png</normaloff>:/icons/edit-clear.png</iconset>
</property>
</widget>
@@ -231,7 +203,7 @@
<string>Close</string>
</property>
<property name="icon">
<iconset resource="../widgets/qad_widgets.qrc">
<iconset resource="qad_graphic.qrc">
<normaloff>:/icons/dialog-close.png</normaloff>:/icons/dialog-close.png</iconset>
</property>
</widget>
@@ -425,6 +397,49 @@
</widget>
</item>
</layout>
<action name="actionGuidesFree">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Free</string>
</property>
</action>
<action name="actionGuidesTraceX">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Trace X</string>
</property>
</action>
<action name="actionGuidesTraceY">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Trace Y</string>
</property>
</action>
<action name="actionExpandX">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Only expand X</string>
</property>
</action>
<action name="actionExpandY">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Only expand Y</string>
</property>
<property name="toolTip">
<string>Only expand Y</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>
@@ -434,9 +449,6 @@
</customwidget>
</customwidgets>
<resources>
<include location="../utils/qad_utils.qrc"/>
<include location="../widgets/qad_widgets.qrc"/>
<include location="../blockview/qad_blockview.qrc"/>
<include location="qad_graphic.qrc"/>
</resources>
<connections/>

View File

@@ -1,28 +1,22 @@
<RCC>
<qresource prefix="/">
<file>../../icons/expand_s_x.png</file>
<file>../../icons/expand_s_y.png</file>
<file>../../icons/expand_x.png</file>
<file>../../icons/expand_y.png</file>
<file>../../icons/pause-back.png</file>
<file>../../icons/pause-front.png</file>
<file>../../icons/media-playback-pause.png</file>
<file>../../icons/dialog-close.png</file>
<file>../../icons/edit-clear.png</file>
<file>../../icons/edit-guides.png</file>
<file>../../icons/view-grid.png</file>
<file>../../icons/view-autofit.png</file>
<file>../../icons/view-fullscreen.png</file>
<file>../../icons/configure.png</file>
<file>../../icons/document-save.png</file>
<file>../../icons/edit-clear-locationbar-rtl.png</file>
<file>../../icons/edit-find.png</file>
<file>../../icons/list-add.png</file>
<file>../../icons/edit-delete.png</file>
<file>../../icons/edit-copy.png</file>
<file>../../icons/edit-paste.png</file>
<file>../../icons/expand_s_x.png</file>
<file>../../icons/expand_s_y.png</file>
<file>../../icons/expand_x.png</file>
<file>../../icons/expand_y.png</file>
<file>../../icons/border-line.png</file>
<file>../../icons/legend.png</file>
<file>../../icons/graphic.png</file>
<file>../../icons/view-fullscreen.png</file>
<file>../../icons/pause-back.png</file>
<file>../../icons/pause-front.png</file>
</qresource>
</RCC>

View File

@@ -1,26 +1,11 @@
<RCC>
<qresource prefix="/">
<file>../../icons/edit-table-insert-row-below.png</file>
<file>../../icons/dialog-close.png</file>
<file>../../icons/edit-clear.png</file>
<file>../../icons/edit-guides.png</file>
<file>../../icons/view-grid.png</file>
<file>../../icons/zoom-fit-best.png</file>
<file>../../icons/configure.png</file>
<file>../../icons/document-save.png</file>
<file>../../icons/edit-clear-locationbar-rtl.png</file>
<file>../../icons/edit-find.png</file>
<file>../../icons/list-add.png</file>
<file>../../icons/edit-delete.png</file>
<file>../../icons/item.png</file>
<file>../../icons/node-add.png</file>
<file>../../icons/node.png</file>
<file>../../icons/edit-copy.png</file>
<file>../../icons/edit-paste.png</file>
<file>../../icons/expand_s_x.png</file>
<file>../../icons/expand_s_y.png</file>
<file>../../icons/expand_x.png</file>
<file>../../icons/expand_y.png</file>
<file>../../icons/sql_table.png</file>
<file>../../icons/configure.png</file>
<file>../../icons/edit-delete.png</file>
<file>../../icons/edit-table-insert-row-below.png</file>
<file>../../icons/edit-find.png</file>
<file>../../icons/edit-clear.png</file>
<file>../../icons/list-add.png</file>
</qresource>
</RCC>

View File

@@ -1,17 +0,0 @@
<RCC>
<qresource prefix="/">
<file>../../icons/edit-clear.png</file>
<file>../../icons/document-save.png</file>
<file>../../icons/edit-clear-locationbar-rtl.png</file>
<file>../../icons/edit-find.png</file>
<file>../../icons/list-add.png</file>
<file>../../icons/edit-delete.png</file>
<file>../../icons/item-add.png</file>
<file>../../icons/item.png</file>
<file>../../icons/node-add.png</file>
<file>../../icons/node.png</file>
<file>../../icons/edit-copy.png</file>
<file>../../icons/edit-paste.png</file>
<file>../../icons/document-open_16.png</file>
</qresource>
</RCC>

View File

@@ -14,8 +14,8 @@
<string>Choose symbol</string>
</property>
<property name="windowIcon">
<iconset resource="mbricks.qrc">
<normaloff>:/icons/icons/mbricks_128.png</normaloff>:/icons/icons/mbricks_128.png</iconset>
<iconset resource="qad_widgets.qrc">
<normaloff>:/icons/chardialog.png</normaloff>:/icons/chardialog.png</iconset>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="margin">
@@ -86,7 +86,7 @@
</layout>
</widget>
<resources>
<include location="mbricks.qrc"/>
<include location="qad_widgets.qrc"/>
</resources>
<connections/>
</ui>

View File

@@ -39,7 +39,7 @@ QString ImageViewPlugin::group() const {
QIcon ImageViewPlugin::icon() const {
return QIcon(/*":/icons/spinslider.png"*/);
return QIcon(":/icons/view-preview.png");
}

View File

@@ -39,7 +39,7 @@ QString QPointEditPlugin::group() const {
QIcon QPointEditPlugin::icon() const {
return QIcon(":/icons/qpointedit.png");
return QIcon();
}

View File

@@ -39,7 +39,7 @@ QString QRectEditPlugin::group() const {
QIcon QRectEditPlugin::icon() const {
return QIcon(":/icons/qrectedit.png");
return QIcon();
}

View File

@@ -1,46 +1,35 @@
<RCC>
<qresource prefix="/">
<file>../../icons/go-next.png</file>
<file>../../icons/go-previous.png</file>
<file>../../icons/dialog-close.png</file>
<file>../../icons/edit-clear.png</file>
<file>../../icons/edit-guides.png</file>
<file>../../icons/view-grid.png</file>
<file>../../icons/zoom-fit-best.png</file>
<file>../../icons/configure.png</file>
<file>../../icons/alpha.png</file>
<file>../../icons/document-save.png</file>
<file>../../icons/edit-clear-locationbar-rtl.png</file>
<file>../../icons/edit-find.png</file>
<file>../../icons/list-add.png</file>
<file>../../icons/edit-delete.png</file>
<file>../../icons/item-add.png</file>
<file>../../icons/item.png</file>
<file>../../icons/node-add.png</file>
<file>../../icons/node.png</file>
<file>../../icons/edit-copy.png</file>
<file>../../icons/edit-paste.png</file>
<file>../../icons/expand_s_x.png</file>
<file>../../icons/expand_s_y.png</file>
<file>../../icons/expand_x.png</file>
<file>../../icons/expand_y.png</file>
<file>../../icons/border-line.png</file>
<file>../../icons/legend.png</file>
<file>../../icons/chardialog.png</file>
<file>../../icons/clineedit.png</file>
<file>../../icons/colorbutton.png</file>
<file>../../icons/ecombobox.png</file>
<file>../../icons/qpiconsole.png</file>
<file>../../icons/spinslider.png</file>
<file>../../icons/etabwidget.png</file>
<file>../../icons/qcodeedit.png</file>
<file>../../icons/qvariantedit.png</file>
<file>../../icons/code-word.png</file>
<file>../../icons/f1.png</file>
<file>../../icons/dialog-ok-apply.png</file>
<file>../../icons/dialog-warning.png</file>
<file>../../icons/tools-wizard.png</file>
<file>../../icons/evalspinbox.png</file>
<file>../../icons/scroll_spin.png</file>
</qresource>
<qresource prefix="/">
<file>../../icons/edit-clear-locationbar-rtl.png</file>
<file>../../icons/edit-copy.png</file>
<file>../../icons/edit-paste.png</file>
<file>../../icons/edit-find.png</file>
<file>../../icons/edit-delete.png</file>
<file>../../icons/edit-clear.png</file>
<file>../../icons/dialog-ok-apply.png</file>
<file>../../icons/dialog-warning.png</file>
<file>../../icons/tools-wizard.png</file>
<file>../../icons/go-next.png</file>
<file>../../icons/go-previous.png</file>
<file>../../icons/item.png</file>
<file>../../icons/item-add.png</file>
<file>../../icons/node.png</file>
<file>../../icons/node-add.png</file>
<file>../../icons/list-add.png</file>
<file>../../icons/document-save.png</file>
<file>../../icons/document-open.png</file>
<file>../../icons/alpha.png</file>
<file>../../icons/chardialog.png</file>
<file>../../icons/clineedit.png</file>
<file>../../icons/colorbutton.png</file>
<file>../../icons/ecombobox.png</file>
<file>../../icons/evalspinbox.png</file>
<file>../../icons/qcodeedit.png</file>
<file>../../icons/qpiconsole.png</file>
<file>../../icons/qvariantedit.png</file>
<file>../../icons/spinslider.png</file>
<file>../../icons/code-word.png</file>
<file>../../icons/f1.png</file>
<file>../../icons/scroll_spin.png</file>
</qresource>
</RCC>

View File

@@ -178,7 +178,7 @@
<string>Previous</string>
</property>
<property name="icon">
<iconset resource="../../../SHS/src/designers/SH_designer/SH_designer.qrc">
<iconset resource="qad_widgets.qrc">
<normaloff>:/icons/go-previous.png</normaloff>:/icons/go-previous.png</iconset>
</property>
</widget>
@@ -195,7 +195,7 @@
<string>Next</string>
</property>
<property name="icon">
<iconset resource="../../../SHS/src/designers/SH_designer/SH_designer.qrc">
<iconset resource="qad_widgets.qrc">
<normaloff>:/icons/go-next.png</normaloff>:/icons/go-next.png</iconset>
</property>
</widget>
@@ -311,7 +311,9 @@
<header>ecombobox.h</header>
</customwidget>
</customwidgets>
<resources/>
<resources>
<include location="qad_widgets.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonSearchNext</sender>

View File

@@ -64,7 +64,9 @@
<header>evalspinbox.h</header>
</customwidget>
</customwidgets>
<resources/>
<resources>
<include location="qad_widgets.qrc"/>
</resources>
<connections/>
<slots>
<slot>mapChanged()</slot>

View File

@@ -1,92 +1,55 @@
cmake_minimum_required(VERSION 3.0)
project(qglengine)
find_package(QAD REQUIRED)
set(_DOMAIN "org.SHS")
set(_COMPANY "SHS")
find_qt(Qt5 Core Gui OpenGL Xml)
if (NOT Qt5)
message(WARNING "Building ${PROJECT_NAME} available only on Qt5!")
else()
if (LIBPROJECT)
include(SDKMacros)
else()
option(LIB "System install" 0)
option(DEBUG "Build with -g3" 0)
option(DESIGNER_PLUGINS "Build qt designer plugins" 1)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -Wall")
if (DEBUG)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3")
endif()
include(DeployMacros)
endif()
if (MINGW)
find_package(MinGW REQUIRED)
endif()
find_package(OpenGL REQUIRED)
set_version(qglengine
MAJOR 1
MINOR 0
REVISION 0
BUILD "${BUILD_NUMBER}"
SUFFIX rc
OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/core/qglengine_version.h")
qt_sources(SRC)
qt_sources(FSRC DIR "formats")
list(APPEND SRC ${FSRC})
qt_sources(FSRC DIR "core")
list(APPEND SRC ${FSRC})
qt_wrap(${SRC} HDRS out_HDR CPPS out_CPP QMS out_QM)
file(GLOB PHS "*_p.h" "formats/*_p.h" "core/*_p.h")
list(REMOVE_ITEM out_HDR "${PHS}")
import_version(qglengine_core qglengine)
set_deploy_property(qglengine_core SHARED
LABEL "QGLEngine core library"
FULLNAME "${_DOMAIN}.qglengine_core"
COMPANY "${_COMPANY}"
INFO "QGLEngine core library")
make_rc(qglengine_core _RC)
qt_add_library(qglengine_core SHARED out_CPP ${_RC})
qt_target_include_directories(qglengine_core PRIVATE ${QAD_INCLUDES} "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/core")
qt_target_link_libraries(qglengine_core qad_utils qad_widgets assimp ${OPENGL_LIBRARIES})
message(STATUS "Building QGLEngine version ${qglengine_VERSION} (SHARED)")
list(APPEND QT_MULTILIB_LIST qglengine_core)
add_subdirectory(widgets)
set(QT_MULTILIB_LIST ${QT_MULTILIB_LIST} PARENT_SCOPE)
if (LIBPROJECT)
sdk_install("qglengine" FALSE "qglengine_core" "${out_HDR}" "${out_QM}")
else()
if (LIB)
if (WIN32)
qt_install(FILES ${out_HDR} DESTINATION ${MINGW_INCLUDE}/qglengine)
qt_install(TARGETS qglengine_core ARCHIVE DESTINATION ${MINGW_LIB})
qt_install(TARGETS qglengine_core RUNTIME DESTINATION ${MINGW_BIN})
qt_install(TARGETS qglengine_core RUNTIME DESTINATION QtBin)
else()
qt_install(FILES ${out_HDR} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/qglengine)
qt_install(TARGETS qglengine_core DESTINATION ${CMAKE_INSTALL_PREFIX}/lib)
endif()
message(STATUS "Install qglengine_core to system \"${CMAKE_INSTALL_PREFIX}\"")
else()
if(WIN32)
qt_install(TARGETS qglengine_core RUNTIME DESTINATION bin)
qt_install(TARGETS qglengine_core ARCHIVE DESTINATION lib)
else()
qt_install(TARGETS qglengine_core DESTINATION bin/lib)
endif()
qt_install(FILES ${out_HDR} DESTINATION include/qglengine)
message(STATUS "Install qglengine_core to local \"bin\", \"lib\" and \"include\"")
endif()
endif()
if (NOT DEFINED ANDROID_PLATFORM)
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/plugin")
#add_subdirectory(plugin)
endif()
endif()
qt_sources(test_SRC DIR "qglview_test")
qt_wrap(${test_SRC} CPPS test_CPP)
qt_add_executable(qglengine_test test_CPP)
qt_target_link_libraries(qglengine_test qglengine_core qglengine_widgets)
qt_target_include_directories(qglengine_test PRIVATE ${QAD_INCLUDES} "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/core" "${CMAKE_CURRENT_SOURCE_DIR}/widgets")
endif()
cmake_minimum_required(VERSION 3.0)
project(qglengine)
find_package(QAD REQUIRED)
set(_DOMAIN "org.SHS")
set(_COMPANY "SHS")
find_qt(Qt5 Core Gui OpenGL Xml)
if (NOT Qt5)
message(WARNING "Building ${PROJECT_NAME} available only on Qt5!")
else()
find_package(OpenGL REQUIRED)
set_version(qglengine
MAJOR 1
MINOR 0
REVISION 0
BUILD "${BUILD_NUMBER}"
SUFFIX rc
OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/core/qglengine_version.h")
qt_sources(SRC)
qt_sources(FSRC DIR "formats")
list(APPEND SRC ${FSRC})
qt_sources(FSRC DIR "core")
list(APPEND SRC ${FSRC})
qt_wrap(${SRC} HDRS out_HDR CPPS out_CPP QMS out_QM)
file(GLOB PHS "*_p.h" "formats/*_p.h" "core/*_p.h")
list(REMOVE_ITEM out_HDR "${PHS}")
import_version(qglengine_core qglengine)
set_deploy_property(qglengine_core SHARED
LABEL "QGLEngine core library"
FULLNAME "${_DOMAIN}.qglengine_core"
COMPANY "${_COMPANY}"
INFO "QGLEngine core library")
make_rc(qglengine_core _RC)
qt_add_library(qglengine_core SHARED out_CPP ${_RC})
qt_generate_export_header(qglengine_core)
list(APPEND out_HDR "${CMAKE_CURRENT_BINARY_DIR}/qglengine_core_export.h")
qt_target_include_directories(qglengine_core PRIVATE ${QAD_INCLUDES} "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/core")
qt_target_link_libraries(qglengine_core qad_utils qad_widgets assimp ${OPENGL_LIBRARIES})
message(STATUS "Building QGLEngine version ${qglengine_VERSION} (SHARED)")
list(APPEND QT_MULTILIB_LIST qglengine_core)
add_subdirectory(widgets)
copy_to_parent("")
sdk_install("qglengine" FALSE "qglengine_core" "${out_HDR}" "${out_QM}")
if (NOT DEFINED ANDROID_PLATFORM)
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/plugin")
#add_subdirectory(plugin)
endif()
endif()
qt_sources(test_SRC DIR "qglview_test")
qt_wrap(${test_SRC} CPPS test_CPP)
qt_add_executable(qglengine_test test_CPP)
qt_target_link_libraries(qglengine_test qglengine_core qglengine_widgets)
qt_target_include_directories(qglengine_test PRIVATE ${QAD_INCLUDES} "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/core" "${CMAKE_CURRENT_SOURCE_DIR}/widgets")
endif()

View File

@@ -1,240 +1,240 @@
/*
QGL GLWidget
Ivan Pelipenko peri4ko@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/>.
*/
#include "glwidget.h"
#include "qglview.h"
#include <QVBoxLayout>
GLWidget::GLWidget(QWidget *parent) : QWidget(parent) {
view_ = new QGLView();
view_->setFlags(windowFlags() | Qt::FramelessWindowHint);
container = QWidget::createWindowContainer(view_, this);
lay = new QVBoxLayout(this);
lay->addWidget(container);
lay->setContentsMargins(0, 0, 0, 0);
lay->setSpacing(0);
setMouseTracking(true);
setWindowIcon(QIcon("://icons/qglview.png"));
connect(view_, &QGLView::doubleClick, this, &GLWidget::viewDoubleClicked);
}
QColor GLWidget::backColor() const {
return view_->backColor();
}
qreal GLWidget::lineWidth() const {
return view_->lineWidth();
}
qreal GLWidget::FOV() const {
return view_->FOV();
}
qreal GLWidget::depthStart() const {
return view_->depthStart();
}
QColor GLWidget::ambientColor() const {
return view_->ambientColor();
}
bool GLWidget::isLightEnabled() const {
return view_->isLightEnabled();
}
bool GLWidget::isGrabMouseEnabled() const {
return view_->isGrabMouseEnabled();
}
bool GLWidget::isMouseRotateEnabled() const {
return view_->isMouseRotateEnabled();
}
bool GLWidget::isMouseSelectionEnabled() const {
return view_->isMouseSelectionEnabled();
}
bool GLWidget::isCameraOrbit() const
{
return view_->isCameraOrbit();
}
bool GLWidget::isHoverHaloEnabled() const {
return view_->isHoverHaloEnabled();
}
QColor GLWidget::hoverHaloColor() const {
return view_->hoverHaloColor();
}
qreal GLWidget::hoverHaloFillAlpha() const {
return view_->hoverHaloFillAlpha();
}
bool GLWidget::isSelectionHaloEnabled() const {
return view_->isSelectionHaloEnabled();
}
QColor GLWidget::selectionHaloColor() const {
return view_->selectionHaloColor();
}
qreal GLWidget::selectionHaloFillAlpha() const {
return view_->selectionHaloFillAlpha();
}
Scene * GLWidget::scene() {
return view_->scene();
}
void GLWidget::addObject(ObjectBase * o) {
view_->scene()->addObject(o);
}
QByteArray GLWidget::saveCamera() {
return view_->saveCamera();
}
void GLWidget::restoreCamera(const QByteArray &ba) {
view_->restoreCamera(ba);
}
void GLWidget::stop() {
view_->stop();
}
void GLWidget::start(float freq) {
view_->start(freq);
}
void GLWidget::setBackColor(const QColor & c) {
view_->setBackColor(c);
}
void GLWidget::setLineWidth(const qreal & arg) {
view_->setLineWidth(arg);
}
void GLWidget::setFOV(const qreal & arg) {
view_->setFOV(arg);
}
void GLWidget::setDepthStart(const qreal & arg) {
view_->setDepthStart(arg);
}
void GLWidget::setAmbientColor(const QColor & arg) {
view_->setAmbientColor(arg);
}
void GLWidget::setLightEnabled(const bool & arg) {
view_->setLightEnabled(arg);
}
void GLWidget::setGrabMouseEnabled(const bool & arg) {
view_->setGrabMouseEnabled(arg);
}
void GLWidget::setMouseRotateEnabled(const bool & arg) {
view_->setMouseRotateEnabled(arg);
}
void GLWidget::setMouseSelectionEnabled(const bool & arg) {
view_->setMouseSelectionEnabled(arg);
}
void GLWidget::setCameraOrbit(const bool & arg) {
view_->setCameraOrbit(arg);
}
void GLWidget::setHoverHaloEnabled(const bool & arg) {
view_->setHoverHaloEnabled(arg);
}
void GLWidget::setHoverHaloColor(const QColor & arg) {
view_->setHoverHaloColor(arg);
}
void GLWidget::setHoverHaloFillAlpha(const qreal & arg) {
view_->setHoverHaloFillAlpha(arg);
}
void GLWidget::setSelectionHaloEnabled(const bool & arg) {
view_->setSelectionHaloEnabled(arg);
}
void GLWidget::setSelectionHaloColor(const QColor & arg) {
view_->setSelectionHaloColor(arg);
}
void GLWidget::setSelectionHaloFillAlpha(const qreal & arg) {
view_->setSelectionHaloFillAlpha(arg);
}
void GLWidget::viewDoubleClicked() {
if (view_->windowState() == Qt::WindowFullScreen) {
view_->showNormal();
container = QWidget::createWindowContainer(view_, this);
lay->addWidget(container);
container->show();
} else {
view_->setParent(nullptr);
view_->showFullScreen();
lay->removeWidget(container);
}
}
/*
QGL GLWidget
Ivan Pelipenko peri4ko@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/>.
*/
#include "glwidget.h"
#include "qglview.h"
#include <QVBoxLayout>
GLWidget::GLWidget(QWidget *parent) : QWidget(parent) {
view_ = new QGLView();
view_->setFlags(windowFlags() | Qt::FramelessWindowHint);
container = QWidget::createWindowContainer(view_, this);
lay = new QVBoxLayout(this);
lay->addWidget(container);
lay->setContentsMargins(0, 0, 0, 0);
lay->setSpacing(0);
setMouseTracking(true);
setWindowIcon(QIcon("://icons/qglview.png"));
connect(view_, &QGLView::doubleClick, this, &GLWidget::viewDoubleClicked);
}
QColor GLWidget::backColor() const {
return view_->backColor();
}
qreal GLWidget::lineWidth() const {
return view_->lineWidth();
}
qreal GLWidget::FOV() const {
return view_->FOV();
}
qreal GLWidget::depthStart() const {
return view_->depthStart();
}
QColor GLWidget::ambientColor() const {
return view_->ambientColor();
}
bool GLWidget::isLightEnabled() const {
return view_->isLightEnabled();
}
bool GLWidget::isGrabMouseEnabled() const {
return view_->isGrabMouseEnabled();
}
bool GLWidget::isMouseRotateEnabled() const {
return view_->isMouseRotateEnabled();
}
bool GLWidget::isMouseSelectionEnabled() const {
return view_->isMouseSelectionEnabled();
}
bool GLWidget::isCameraOrbit() const
{
return view_->isCameraOrbit();
}
bool GLWidget::isHoverHaloEnabled() const {
return view_->isHoverHaloEnabled();
}
QColor GLWidget::hoverHaloColor() const {
return view_->hoverHaloColor();
}
qreal GLWidget::hoverHaloFillAlpha() const {
return view_->hoverHaloFillAlpha();
}
bool GLWidget::isSelectionHaloEnabled() const {
return view_->isSelectionHaloEnabled();
}
QColor GLWidget::selectionHaloColor() const {
return view_->selectionHaloColor();
}
qreal GLWidget::selectionHaloFillAlpha() const {
return view_->selectionHaloFillAlpha();
}
Scene * GLWidget::scene() {
return view_->scene();
}
void GLWidget::addObject(ObjectBase * o) {
view_->scene()->addObject(o);
}
QByteArray GLWidget::saveCamera() {
return view_->saveCamera();
}
void GLWidget::restoreCamera(const QByteArray &ba) {
view_->restoreCamera(ba);
}
void GLWidget::stop() {
view_->stop();
}
void GLWidget::start(float freq) {
view_->start(freq);
}
void GLWidget::setBackColor(const QColor & c) {
view_->setBackColor(c);
}
void GLWidget::setLineWidth(const qreal & arg) {
view_->setLineWidth(arg);
}
void GLWidget::setFOV(const qreal & arg) {
view_->setFOV(arg);
}
void GLWidget::setDepthStart(const qreal & arg) {
view_->setDepthStart(arg);
}
void GLWidget::setAmbientColor(const QColor & arg) {
view_->setAmbientColor(arg);
}
void GLWidget::setLightEnabled(const bool & arg) {
view_->setLightEnabled(arg);
}
void GLWidget::setGrabMouseEnabled(const bool & arg) {
view_->setGrabMouseEnabled(arg);
}
void GLWidget::setMouseRotateEnabled(const bool & arg) {
view_->setMouseRotateEnabled(arg);
}
void GLWidget::setMouseSelectionEnabled(const bool & arg) {
view_->setMouseSelectionEnabled(arg);
}
void GLWidget::setCameraOrbit(const bool & arg) {
view_->setCameraOrbit(arg);
}
void GLWidget::setHoverHaloEnabled(const bool & arg) {
view_->setHoverHaloEnabled(arg);
}
void GLWidget::setHoverHaloColor(const QColor & arg) {
view_->setHoverHaloColor(arg);
}
void GLWidget::setHoverHaloFillAlpha(const qreal & arg) {
view_->setHoverHaloFillAlpha(arg);
}
void GLWidget::setSelectionHaloEnabled(const bool & arg) {
view_->setSelectionHaloEnabled(arg);
}
void GLWidget::setSelectionHaloColor(const QColor & arg) {
view_->setSelectionHaloColor(arg);
}
void GLWidget::setSelectionHaloFillAlpha(const qreal & arg) {
view_->setSelectionHaloFillAlpha(arg);
}
void GLWidget::viewDoubleClicked() {
if (view_->windowState() == Qt::WindowFullScreen) {
view_->showNormal();
container = QWidget::createWindowContainer(view_, this);
lay->addWidget(container);
container->show();
} else {
view_->setParent(nullptr);
view_->showFullScreen();
lay->removeWidget(container);
}
}

View File

@@ -1,104 +1,104 @@
/*
QGL GLWidget
Ivan Pelipenko peri4ko@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 GLWIDGET_H
#define GLWIDGET_H
#include <QWidget>
class QGLView;
class ObjectBase;
class Scene;
class GLWidget : public QWidget
{
Q_OBJECT
Q_PROPERTY (QColor backColor READ backColor WRITE setBackColor)
Q_PROPERTY (qreal lineWidth READ lineWidth WRITE setLineWidth)
Q_PROPERTY (qreal FOV READ FOV WRITE setFOV)
Q_PROPERTY (qreal depthStart READ depthStart WRITE setDepthStart)
Q_PROPERTY (QColor ambientColor READ ambientColor WRITE setAmbientColor)
Q_PROPERTY (bool grabMouse READ isGrabMouseEnabled WRITE setGrabMouseEnabled)
Q_PROPERTY (bool mouseRotate READ isMouseRotateEnabled WRITE setMouseRotateEnabled)
Q_PROPERTY (bool mouseSelection READ isMouseSelectionEnabled WRITE setMouseSelectionEnabled)
Q_PROPERTY (bool cameraOrbit READ isCameraOrbit WRITE setCameraOrbit)
Q_PROPERTY (bool hoverHalo READ isHoverHaloEnabled WRITE setHoverHaloEnabled)
Q_PROPERTY (QColor hoverHaloColor READ hoverHaloColor WRITE setHoverHaloColor)
Q_PROPERTY (qreal hoverHaloFillAlpha READ hoverHaloFillAlpha WRITE setHoverHaloFillAlpha)
Q_PROPERTY (bool selectionHalo READ isSelectionHaloEnabled WRITE setSelectionHaloEnabled)
Q_PROPERTY (QColor selectionHaloColor READ selectionHaloColor WRITE setSelectionHaloColor)
Q_PROPERTY (qreal selectionHaloFillAlpha READ selectionHaloFillAlpha WRITE setSelectionHaloFillAlpha)
public:
explicit GLWidget(QWidget *parent = nullptr);
QGLView * view() {return view_;}
QColor backColor() const;
qreal lineWidth() const;
qreal FOV() const;
qreal depthStart() const;
QColor ambientColor() const;
bool isLightEnabled() const;
bool isGrabMouseEnabled() const;
bool isMouseRotateEnabled() const;
bool isMouseSelectionEnabled() const;
bool isCameraOrbit() const;
bool isHoverHaloEnabled() const;
QColor hoverHaloColor() const;
qreal hoverHaloFillAlpha() const;
bool isSelectionHaloEnabled() const;
QColor selectionHaloColor() const;
qreal selectionHaloFillAlpha() const;
Scene * scene();
void addObject(ObjectBase * o);
QByteArray saveCamera();
void restoreCamera(const QByteArray & ba);
public slots:
void stop();
void start(float freq = 60.0);
void setBackColor(const QColor & c);
void setLineWidth(const qreal & arg);
void setFOV(const qreal & arg);
void setDepthStart(const qreal & arg);
void setAmbientColor(const QColor & arg);
void setLightEnabled(const bool & arg);
void setGrabMouseEnabled(const bool & arg);
void setMouseRotateEnabled(const bool & arg);
void setMouseSelectionEnabled(const bool & arg);
void setCameraOrbit(const bool & arg);
void setHoverHaloEnabled(const bool & arg);
void setHoverHaloColor(const QColor & arg);
void setHoverHaloFillAlpha(const qreal & arg);
void setSelectionHaloEnabled(const bool & arg);
void setSelectionHaloColor(const QColor & arg);
void setSelectionHaloFillAlpha(const qreal & arg);
private slots:
void viewDoubleClicked();
private:
QWidget * container;
QGLView * view_;
QLayout * lay;
signals:
};
#endif // GLWIDGET_H
/*
QGL GLWidget
Ivan Pelipenko peri4ko@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 GLWIDGET_H
#define GLWIDGET_H
#include <QWidget>
class QGLView;
class ObjectBase;
class Scene;
class GLWidget : public QWidget
{
Q_OBJECT
Q_PROPERTY (QColor backColor READ backColor WRITE setBackColor)
Q_PROPERTY (qreal lineWidth READ lineWidth WRITE setLineWidth)
Q_PROPERTY (qreal FOV READ FOV WRITE setFOV)
Q_PROPERTY (qreal depthStart READ depthStart WRITE setDepthStart)
Q_PROPERTY (QColor ambientColor READ ambientColor WRITE setAmbientColor)
Q_PROPERTY (bool grabMouse READ isGrabMouseEnabled WRITE setGrabMouseEnabled)
Q_PROPERTY (bool mouseRotate READ isMouseRotateEnabled WRITE setMouseRotateEnabled)
Q_PROPERTY (bool mouseSelection READ isMouseSelectionEnabled WRITE setMouseSelectionEnabled)
Q_PROPERTY (bool cameraOrbit READ isCameraOrbit WRITE setCameraOrbit)
Q_PROPERTY (bool hoverHalo READ isHoverHaloEnabled WRITE setHoverHaloEnabled)
Q_PROPERTY (QColor hoverHaloColor READ hoverHaloColor WRITE setHoverHaloColor)
Q_PROPERTY (qreal hoverHaloFillAlpha READ hoverHaloFillAlpha WRITE setHoverHaloFillAlpha)
Q_PROPERTY (bool selectionHalo READ isSelectionHaloEnabled WRITE setSelectionHaloEnabled)
Q_PROPERTY (QColor selectionHaloColor READ selectionHaloColor WRITE setSelectionHaloColor)
Q_PROPERTY (qreal selectionHaloFillAlpha READ selectionHaloFillAlpha WRITE setSelectionHaloFillAlpha)
public:
explicit GLWidget(QWidget *parent = nullptr);
QGLView * view() {return view_;}
QColor backColor() const;
qreal lineWidth() const;
qreal FOV() const;
qreal depthStart() const;
QColor ambientColor() const;
bool isLightEnabled() const;
bool isGrabMouseEnabled() const;
bool isMouseRotateEnabled() const;
bool isMouseSelectionEnabled() const;
bool isCameraOrbit() const;
bool isHoverHaloEnabled() const;
QColor hoverHaloColor() const;
qreal hoverHaloFillAlpha() const;
bool isSelectionHaloEnabled() const;
QColor selectionHaloColor() const;
qreal selectionHaloFillAlpha() const;
Scene * scene();
void addObject(ObjectBase * o);
QByteArray saveCamera();
void restoreCamera(const QByteArray & ba);
public slots:
void stop();
void start(float freq = 60.0);
void setBackColor(const QColor & c);
void setLineWidth(const qreal & arg);
void setFOV(const qreal & arg);
void setDepthStart(const qreal & arg);
void setAmbientColor(const QColor & arg);
void setLightEnabled(const bool & arg);
void setGrabMouseEnabled(const bool & arg);
void setMouseRotateEnabled(const bool & arg);
void setMouseSelectionEnabled(const bool & arg);
void setCameraOrbit(const bool & arg);
void setHoverHaloEnabled(const bool & arg);
void setHoverHaloColor(const QColor & arg);
void setHoverHaloFillAlpha(const qreal & arg);
void setSelectionHaloEnabled(const bool & arg);
void setSelectionHaloColor(const QColor & arg);
void setSelectionHaloFillAlpha(const qreal & arg);
private slots:
void viewDoubleClicked();
private:
QWidget * container;
QGLView * view_;
QLayout * lay;
signals:
};
#endif // GLWIDGET_H

View File

@@ -1,289 +1,289 @@
/*
QGL MouseController
Ivan Pelipenko peri4ko@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/>.
*/
#include "mouse_controller.h"
#include "glmesh.h"
#include "qglview.h"
#include <qad_types.h>
#include <QApplication>
#include <QKeyEvent>
using namespace QGLEngineShaders;
MouseController::MouseController(QGLView * view_): view(view_) {
app_scale = 1;
lastPos = QPoint(-1, -1);
cur_action = RendererService::haNoAction;
sel_button = Qt::LeftButton;
sel_mod = Qt::ControlModifier;
mouse_first = mouseSelect_ = mouseRotate_ = cameraOrbit_ = canSelect_ = true;
grabMouse_ = mouse_sec = selecting_ = customMouseMove_ = false;
}
MouseController::~MouseController() {
}
void MouseController::resize() {
mouse_first = true;
app_scale = appScale();
}
void MouseController::mouseReleaseEvent(QMouseEvent * e) {
if (cur_action != RendererService::haNoAction) {
mouseMoveEvent(e);
return;
}
bool add_ts = e->modifiers().testFlag(sel_mod);
if (selecting_) {
selecting_ = false;
canSelect_ = true;
view->renderer_.mouse_rect = QRect();
view->scene_->selectObjects(hov_objects.toList(), add_ts);
return;
}
if (canSelect_ && mouseSelect_) {
if ((lastPos - downPos).manhattanLength() < QApplication::startDragDistance()) {
if (e->button() == Qt::LeftButton) {
//qDebug() << hov_objects << hov_aims;
if (hov_objects.isEmpty() && hov_aims.isEmpty()) {
view->scene()->clearSelection();
} else {
if (!hov_objects.isEmpty())
view->scene_->selectObject(hov_objects[0], add_ts);
if (!hov_aims.isEmpty()) {
view->scene_->selectObject(hov_aims[0], add_ts);
hov_aims[0]->selected_aim = true;
}
}
}
if (e->button() == Qt::RightButton) {
if (view->renderer_.edit_mode && !view->scene()->selectedObjects().isEmpty())
view->context_menu.popup(e->globalPos());
}
}
}
canSelect_ = e->buttons() == 0;
emit view->glMouseReleaseEvent(e);
}
void MouseController::mousePressEvent(QMouseEvent * e) {
downPos = e->pos();
if (cur_action != RendererService::haNoAction && e->buttons() == Qt::LeftButton) {
return;
}
if (selecting_) {
selecting_ = false;
view->renderer_.mouse_rect = QRect();
return;
}
if (!QRect(QPoint(), view->size()).contains(e->pos())) return;
lastPos = e->pos();
downPos = e->pos();
emit view->glMousePressEvent(e);
}
void MouseController::mouseMoveEvent(QMouseEvent * e) {
QPoint cpos = e->pos();
if (cur_action != RendererService::haNoAction && (e->buttons() == Qt::LeftButton)) {
RendererService & rs(view->renderer_.rend_service);
ObjectBaseList objects = view->scene_->selectedObjects(true);
QVector<int> axis;
switch (cur_action) {
case RendererService::haMove:
if (cur_handle.testFlag(RendererService::hmMoveX)) axis << 0;
if (cur_handle.testFlag(RendererService::hmMoveY)) axis << 1;
if (cur_handle.testFlag(RendererService::hmMoveZ)) axis << 2;
break;
case RendererService::haRotate:
if (cur_handle.testFlag(RendererService::hmRotateX)) axis << 0;
if (cur_handle.testFlag(RendererService::hmRotateY)) axis << 1;
if (cur_handle.testFlag(RendererService::hmRotateZ)) axis << 2;
break;
case RendererService::haScale:
if (cur_handle.testFlag(RendererService::hmScaleX)) axis << 0;
if (cur_handle.testFlag(RendererService::hmScaleY)) axis << 1;
if (cur_handle.testFlag(RendererService::hmScaleZ)) axis << 2;
break;
default: break;
}
QVector<QVector3D> scales;
foreach (int a, axis) {
QVector3D axe_vector; axe_vector[a] = 1.;
QMatrix4x4 axis_mat = view->camera()->fullViewMatrix() * rs.axis_mat;
QVector3D center_screen = axis_mat * rs.selection_center;
QVector3D axe_screen = ((axis_mat * (rs.selection_center + axe_vector)) - center_screen).normalized();
QVector3D mouse_vector(cpos - lastPos);
mouse_vector[1] *= -1.;
if (cur_action == RendererService::haMove) {
double len_scl = 1. / QVector3D(axe_screen.x(), axe_screen.y(), 1.E-6).length();
mouse_vector /= QVector3D(view->width(), view->height(), 1);
mouse_vector *= -center_screen.z() * len_scl;
axe_vector *= QVector3D::dotProduct(axe_screen, mouse_vector);
QMatrix4x4 pmat;
foreach (ObjectBase * o, objects) {
pmat.setToIdentity();
if (o->parent())
pmat = o->parent()->worldTransform().inverted();
QVector3D dv = pmat.mapVector(axe_vector);
if (o->selected_aim) {
AimedObject * ao = (AimedObject*)o;
ao->setAim(ao->aim() + dv);
} else
o->move(dv);
}
}
if (cur_action == RendererService::haRotate) {
axe_screen.setZ(0.);
axe_screen.normalize();
QVector3D norm = QVector3D(axe_screen.y(), -axe_screen.x(), 0.);
axe_vector *= QVector3D::dotProduct(mouse_vector, norm) / 2. / app_scale;
foreach (ObjectBase * o, objects)
o->setRotation(o->rotation() + axe_vector);
}
if (cur_action == RendererService::haScale) {
mouse_vector /= QVector3D(view->width(), view->height(), 1);
mouse_vector *= 3. / app_scale;
axe_vector *= QVector3D::dotProduct(axe_screen, mouse_vector);
scales << axe_vector;
}
}
//if (cur_handle >= RendererService::htScaleX && cur_handle <= RendererService::htScaleZ ) cs = Qt::SplitHCursor;
if (cur_action == RendererService::haScale) {
double sc = 0., max = 0.;
foreach (const QVector3D & s, scales) {
double v = QVector3D::dotProduct(s, QVector3D(1,1,1));
sc += v;
max = qMax(max, qAbs(v));
}
sc = max * (sc > 0. ? 1. : -1);
QVector3D axe_vector;
foreach (int a, axis)
axe_vector[a] = 1.;
foreach (ObjectBase * o, objects)
o->scale(QVector3D(1,1,1) + (axe_vector * sc));
QCursor::setPos(view->mapToGlobal(downPos));
} else
lastPos = e->pos();
emit view->objectsPositionChanged();
return;
}
if (selecting_) {
view->renderer_.mouse_rect = QRect(downPos, cpos).normalized();
return;
}
if (e->buttons().testFlag(Qt::LeftButton)) {
if ((cpos - downPos).manhattanLength() >= QApplication::startDragDistance()) {
selecting_ = true;
canSelect_ = false;
}
return;
}
QRect g_rect(QPoint(), view->size());
if (mouseRotate_) {
float dx = e->x() - lastPos.x();
float dy = e->y() - lastPos.y();
if (e->buttons().testFlag(Qt::MidButton)) {
if (cameraOrbit_) {
view->camera()->orbitZ (dx / 4.f);
view->camera()->orbitXY(dy / 4.f);
} else {
view->camera()->rotateZ(-dx / 4.f);
view->camera()->rotateX(-dy / 4.f);
}
emit view->cameraPosChanged(view->camera()->pos());
} else if (e->buttons().testFlag(Qt::RightButton)) {
float ad = view->camera()->distance();
view->camera()->moveLeft(dx / 1000.f * ad);
view->camera()->moveUp (dy / 1000.f * ad);
emit view->cameraPosChanged(view->camera()->pos());
}
}
if (customMouseMove_) emit view->customMouseMoveEvent(e->pos(), lastPos, e->buttons());
lastPos = e->pos();
if (e->buttons() == 0) {
cur_handle = 0;
cur_action = RendererService::haNoAction;
Qt::CursorShape cs = Qt::CrossCursor;
if (view->renderer_.edit_mode) {
uint hid = view->renderer_.rend_selection.id_hover;
cur_handle = (RendererService::HandleMesh)hid;
if (hid >= RendererService::hmMoveX && hid <= RendererService::hmMaxMove ) {
cur_action = RendererService::haMove;
cs = Qt::SizeAllCursor;
}
if (hid >= RendererService::hmRotateX && hid <= RendererService::hmMaxRotate) {
cur_action = RendererService::haRotate;
cs = Qt::PointingHandCursor;
}
if (hid >= RendererService::hmScaleX && hid <= RendererService::hmMaxScale ) {
cur_action = RendererService::haScale;
cs = Qt::SplitHCursor;
}
}
if (cur_action == RendererService::haNoAction)
cur_handle = 0;
view->setCursor(cs);
view->renderer_.rend_service.current_handle = cur_handle;
}
if (grabMouse_) {
QCursor::setPos(view->mapToGlobal(QRect(QPoint(), view->size()).center()));
if (mouse_sec) {
mouse_sec = false;
return;
}
if (mouse_first) {
mouse_first = false;
mouse_sec = true;
return;
}
lastPos = g_rect.center();
int dx = e->x() - lastPos.x();
int dy = e->y() - lastPos.y();
emit view->glMouseMoveEvent(new QMouseEvent(QEvent::MouseMove, QPoint(dx, dy), e->button(), e->buttons(), e->modifiers()));
return;
}
emit view->glMouseMoveEvent(e);
}
void MouseController::wheelEvent(QWheelEvent * e) {
if (mouseRotate_) {
if (e->delta() > 0) view->camera()->flyCloser(0.1f);
if (e->delta() < 0) view->camera()->flyFarer(0.1f);
emit view->cameraPosChanged(view->camera()->pos());
}
emit view->glWheelEvent(e);
}
void MouseController::leaveEvent(QEvent * ) {
lastPos = QPoint(-1, -1);
//qDebug() << lastPos;
}
void MouseController::mouseDoubleClickEvent(QMouseEvent * e) {
if (e->buttons().testFlag(Qt::MidButton))
emit view->doubleClick();
}
/*
QGL MouseController
Ivan Pelipenko peri4ko@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/>.
*/
#include "mouse_controller.h"
#include "glmesh.h"
#include "qglview.h"
#include <qad_types.h>
#include <QApplication>
#include <QKeyEvent>
using namespace QGLEngineShaders;
MouseController::MouseController(QGLView * view_): view(view_) {
app_scale = 1;
lastPos = QPoint(-1, -1);
cur_action = RendererService::haNoAction;
sel_button = Qt::LeftButton;
sel_mod = Qt::ControlModifier;
mouse_first = mouseSelect_ = mouseRotate_ = cameraOrbit_ = canSelect_ = true;
grabMouse_ = mouse_sec = selecting_ = customMouseMove_ = false;
}
MouseController::~MouseController() {
}
void MouseController::resize() {
mouse_first = true;
app_scale = appScale();
}
void MouseController::mouseReleaseEvent(QMouseEvent * e) {
if (cur_action != RendererService::haNoAction) {
mouseMoveEvent(e);
return;
}
bool add_ts = e->modifiers().testFlag(sel_mod);
if (selecting_) {
selecting_ = false;
canSelect_ = true;
view->renderer_.mouse_rect = QRect();
view->scene_->selectObjects(hov_objects.toList(), add_ts);
return;
}
if (canSelect_ && mouseSelect_) {
if ((lastPos - downPos).manhattanLength() < QApplication::startDragDistance()) {
if (e->button() == Qt::LeftButton) {
//qDebug() << hov_objects << hov_aims;
if (hov_objects.isEmpty() && hov_aims.isEmpty()) {
view->scene()->clearSelection();
} else {
if (!hov_objects.isEmpty())
view->scene_->selectObject(hov_objects[0], add_ts);
if (!hov_aims.isEmpty()) {
view->scene_->selectObject(hov_aims[0], add_ts);
hov_aims[0]->selected_aim = true;
}
}
}
if (e->button() == Qt::RightButton) {
if (view->renderer_.edit_mode && !view->scene()->selectedObjects().isEmpty())
view->context_menu.popup(e->globalPos());
}
}
}
canSelect_ = e->buttons() == 0;
emit view->glMouseReleaseEvent(e);
}
void MouseController::mousePressEvent(QMouseEvent * e) {
downPos = e->pos();
if (cur_action != RendererService::haNoAction && e->buttons() == Qt::LeftButton) {
return;
}
if (selecting_) {
selecting_ = false;
view->renderer_.mouse_rect = QRect();
return;
}
if (!QRect(QPoint(), view->size()).contains(e->pos())) return;
lastPos = e->pos();
downPos = e->pos();
emit view->glMousePressEvent(e);
}
void MouseController::mouseMoveEvent(QMouseEvent * e) {
QPoint cpos = e->pos();
if (cur_action != RendererService::haNoAction && (e->buttons() == Qt::LeftButton)) {
RendererService & rs(view->renderer_.rend_service);
ObjectBaseList objects = view->scene_->selectedObjects(true);
QVector<int> axis;
switch (cur_action) {
case RendererService::haMove:
if (cur_handle.testFlag(RendererService::hmMoveX)) axis << 0;
if (cur_handle.testFlag(RendererService::hmMoveY)) axis << 1;
if (cur_handle.testFlag(RendererService::hmMoveZ)) axis << 2;
break;
case RendererService::haRotate:
if (cur_handle.testFlag(RendererService::hmRotateX)) axis << 0;
if (cur_handle.testFlag(RendererService::hmRotateY)) axis << 1;
if (cur_handle.testFlag(RendererService::hmRotateZ)) axis << 2;
break;
case RendererService::haScale:
if (cur_handle.testFlag(RendererService::hmScaleX)) axis << 0;
if (cur_handle.testFlag(RendererService::hmScaleY)) axis << 1;
if (cur_handle.testFlag(RendererService::hmScaleZ)) axis << 2;
break;
default: break;
}
QVector<QVector3D> scales;
foreach (int a, axis) {
QVector3D axe_vector; axe_vector[a] = 1.;
QMatrix4x4 axis_mat = view->camera()->fullViewMatrix() * rs.axis_mat;
QVector3D center_screen = axis_mat * rs.selection_center;
QVector3D axe_screen = ((axis_mat * (rs.selection_center + axe_vector)) - center_screen).normalized();
QVector3D mouse_vector(cpos - lastPos);
mouse_vector[1] *= -1.;
if (cur_action == RendererService::haMove) {
double len_scl = 1. / QVector3D(axe_screen.x(), axe_screen.y(), 1.E-6).length();
mouse_vector /= QVector3D(view->width(), view->height(), 1);
mouse_vector *= -center_screen.z() * len_scl;
axe_vector *= QVector3D::dotProduct(axe_screen, mouse_vector);
QMatrix4x4 pmat;
foreach (ObjectBase * o, objects) {
pmat.setToIdentity();
if (o->parent())
pmat = o->parent()->worldTransform().inverted();
QVector3D dv = pmat.mapVector(axe_vector);
if (o->selected_aim) {
AimedObject * ao = (AimedObject*)o;
ao->setAim(ao->aim() + dv);
} else
o->move(dv);
}
}
if (cur_action == RendererService::haRotate) {
axe_screen.setZ(0.);
axe_screen.normalize();
QVector3D norm = QVector3D(axe_screen.y(), -axe_screen.x(), 0.);
axe_vector *= QVector3D::dotProduct(mouse_vector, norm) / 2. / app_scale;
foreach (ObjectBase * o, objects)
o->setRotation(o->rotation() + axe_vector);
}
if (cur_action == RendererService::haScale) {
mouse_vector /= QVector3D(view->width(), view->height(), 1);
mouse_vector *= 3. / app_scale;
axe_vector *= QVector3D::dotProduct(axe_screen, mouse_vector);
scales << axe_vector;
}
}
//if (cur_handle >= RendererService::htScaleX && cur_handle <= RendererService::htScaleZ ) cs = Qt::SplitHCursor;
if (cur_action == RendererService::haScale) {
double sc = 0., max = 0.;
foreach (const QVector3D & s, scales) {
double v = QVector3D::dotProduct(s, QVector3D(1,1,1));
sc += v;
max = qMax(max, qAbs(v));
}
sc = max * (sc > 0. ? 1. : -1);
QVector3D axe_vector;
foreach (int a, axis)
axe_vector[a] = 1.;
foreach (ObjectBase * o, objects)
o->scale(QVector3D(1,1,1) + (axe_vector * sc));
QCursor::setPos(view->mapToGlobal(downPos));
} else
lastPos = e->pos();
emit view->objectsPositionChanged();
return;
}
if (selecting_) {
view->renderer_.mouse_rect = QRect(downPos, cpos).normalized();
return;
}
if (e->buttons().testFlag(Qt::LeftButton)) {
if ((cpos - downPos).manhattanLength() >= QApplication::startDragDistance()) {
selecting_ = true;
canSelect_ = false;
}
return;
}
QRect g_rect(QPoint(), view->size());
if (mouseRotate_) {
float dx = e->x() - lastPos.x();
float dy = e->y() - lastPos.y();
if (e->buttons().testFlag(Qt::MidButton)) {
if (cameraOrbit_) {
view->camera()->orbitZ (dx / 4.f);
view->camera()->orbitXY(dy / 4.f);
} else {
view->camera()->rotateZ(-dx / 4.f);
view->camera()->rotateX(-dy / 4.f);
}
emit view->cameraPosChanged(view->camera()->pos());
} else if (e->buttons().testFlag(Qt::RightButton)) {
float ad = view->camera()->distance();
view->camera()->moveLeft(dx / 1000.f * ad);
view->camera()->moveUp (dy / 1000.f * ad);
emit view->cameraPosChanged(view->camera()->pos());
}
}
if (customMouseMove_) emit view->customMouseMoveEvent(e->pos(), lastPos, e->buttons());
lastPos = e->pos();
if (e->buttons() == 0) {
cur_handle = 0;
cur_action = RendererService::haNoAction;
Qt::CursorShape cs = Qt::CrossCursor;
if (view->renderer_.edit_mode) {
uint hid = view->renderer_.rend_selection.id_hover;
cur_handle = (RendererService::HandleMesh)hid;
if (hid >= RendererService::hmMoveX && hid <= RendererService::hmMaxMove ) {
cur_action = RendererService::haMove;
cs = Qt::SizeAllCursor;
}
if (hid >= RendererService::hmRotateX && hid <= RendererService::hmMaxRotate) {
cur_action = RendererService::haRotate;
cs = Qt::PointingHandCursor;
}
if (hid >= RendererService::hmScaleX && hid <= RendererService::hmMaxScale ) {
cur_action = RendererService::haScale;
cs = Qt::SplitHCursor;
}
}
if (cur_action == RendererService::haNoAction)
cur_handle = 0;
view->setCursor(cs);
view->renderer_.rend_service.current_handle = cur_handle;
}
if (grabMouse_) {
QCursor::setPos(view->mapToGlobal(QRect(QPoint(), view->size()).center()));
if (mouse_sec) {
mouse_sec = false;
return;
}
if (mouse_first) {
mouse_first = false;
mouse_sec = true;
return;
}
lastPos = g_rect.center();
int dx = e->x() - lastPos.x();
int dy = e->y() - lastPos.y();
emit view->glMouseMoveEvent(new QMouseEvent(QEvent::MouseMove, QPoint(dx, dy), e->button(), e->buttons(), e->modifiers()));
return;
}
emit view->glMouseMoveEvent(e);
}
void MouseController::wheelEvent(QWheelEvent * e) {
if (mouseRotate_) {
if (e->delta() > 0) view->camera()->flyCloser(0.1f);
if (e->delta() < 0) view->camera()->flyFarer(0.1f);
emit view->cameraPosChanged(view->camera()->pos());
}
emit view->glWheelEvent(e);
}
void MouseController::leaveEvent(QEvent * ) {
lastPos = QPoint(-1, -1);
//qDebug() << lastPos;
}
void MouseController::mouseDoubleClickEvent(QMouseEvent * e) {
if (e->buttons().testFlag(Qt::MidButton))
emit view->doubleClick();
}

View File

@@ -1,84 +1,84 @@
/*
QGL MouseController
Ivan Pelipenko peri4ko@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 MOUSE_CONTROLLER_H
#define MOUSE_CONTROLLER_H
#include "glprimitives.h"
#include "glcamera.h"
#include "renderer_service.h"
#include <QMouseEvent>
#include <QTime>
class MouseController: public QObject
{
friend class QGLView;
friend class RendererSelection;
Q_OBJECT
public:
MouseController(QGLView * view_);
virtual ~MouseController();
bool isGrabMouseEnabled() const {return grabMouse_;}
bool isMouseRotateEnabled() const {return mouseRotate_;}
bool isMouseSelectionEnabled() const {return mouseSelect_;}
bool isCameraOrbit() const {return cameraOrbit_;}
Qt::MouseButton selectionButton() const {return sel_button;}
Qt::KeyboardModifier selectionModifier() const {return sel_mod;}
void setSelectionButton(Qt::MouseButton v) {sel_button = v;}
void setSelectionModifier(Qt::KeyboardModifier v) {sel_mod = v;}
protected:
void resize();
void mousePressEvent(QMouseEvent * e);
void mouseMoveEvent(QMouseEvent * e);
void mouseReleaseEvent(QMouseEvent * e);
void wheelEvent(QWheelEvent * e);
void leaveEvent(QEvent * );
void mouseDoubleClickEvent(QMouseEvent * e);
private:
QGLView * view;
QPoint lastPos, downPos;
QSet<int> keys_;
QVector<ObjectBase * > hov_objects, hov_aims;
Qt::MouseButton sel_button;
Qt::KeyboardModifier sel_mod;
RendererService::HandleAction cur_action;
QFlags<RendererService::HandleMesh> cur_handle;
float app_scale;
bool grabMouse_, mouse_first, mouseRotate_, mouseSelect_, customMouseMove_, canSelect_;
bool cameraOrbit_, selecting_, mouse_sec;
private slots:
public slots:
void setGrabMouseEnabled(const bool & arg) {grabMouse_ = arg; mouse_first = true;}
void setMouseRotateEnabled(const bool & arg) {mouseRotate_ = arg;}
void setMouseSelectionEnabled(const bool & arg) {mouseSelect_ = arg;}
void setCustomMouseMove(const bool & arg) {customMouseMove_ = arg;}
void setCameraOrbit(const bool & arg) {cameraOrbit_ = arg;}
signals:
};
#endif // QGLVIEW_H
/*
QGL MouseController
Ivan Pelipenko peri4ko@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 MOUSE_CONTROLLER_H
#define MOUSE_CONTROLLER_H
#include "glprimitives.h"
#include "glcamera.h"
#include "renderer_service.h"
#include <QMouseEvent>
#include <QTime>
class MouseController: public QObject
{
friend class QGLView;
friend class RendererSelection;
Q_OBJECT
public:
MouseController(QGLView * view_);
virtual ~MouseController();
bool isGrabMouseEnabled() const {return grabMouse_;}
bool isMouseRotateEnabled() const {return mouseRotate_;}
bool isMouseSelectionEnabled() const {return mouseSelect_;}
bool isCameraOrbit() const {return cameraOrbit_;}
Qt::MouseButton selectionButton() const {return sel_button;}
Qt::KeyboardModifier selectionModifier() const {return sel_mod;}
void setSelectionButton(Qt::MouseButton v) {sel_button = v;}
void setSelectionModifier(Qt::KeyboardModifier v) {sel_mod = v;}
protected:
void resize();
void mousePressEvent(QMouseEvent * e);
void mouseMoveEvent(QMouseEvent * e);
void mouseReleaseEvent(QMouseEvent * e);
void wheelEvent(QWheelEvent * e);
void leaveEvent(QEvent * );
void mouseDoubleClickEvent(QMouseEvent * e);
private:
QGLView * view;
QPoint lastPos, downPos;
QSet<int> keys_;
QVector<ObjectBase * > hov_objects, hov_aims;
Qt::MouseButton sel_button;
Qt::KeyboardModifier sel_mod;
RendererService::HandleAction cur_action;
QFlags<RendererService::HandleMesh> cur_handle;
float app_scale;
bool grabMouse_, mouse_first, mouseRotate_, mouseSelect_, customMouseMove_, canSelect_;
bool cameraOrbit_, selecting_, mouse_sec;
private slots:
public slots:
void setGrabMouseEnabled(const bool & arg) {grabMouse_ = arg; mouse_first = true;}
void setMouseRotateEnabled(const bool & arg) {mouseRotate_ = arg;}
void setMouseSelectionEnabled(const bool & arg) {mouseSelect_ = arg;}
void setCustomMouseMove(const bool & arg) {customMouseMove_ = arg;}
void setCameraOrbit(const bool & arg) {cameraOrbit_ = arg;}
signals:
};
#endif // QGLVIEW_H

View File

@@ -1,113 +1,113 @@
/*
QGL OpenGLWindow
Ivan Pelipenko peri4ko@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/>.
*/
#include "openglwindow.h"
#include <QCoreApplication>
#include <QOpenGLContext>
#include <QOpenGLPaintDevice>
#include <QPainter>
OpenGLWindow::OpenGLWindow(QWindow *parent)
: QWindow(parent)
, m_context(nullptr)
, m_device(nullptr)
{
setFlags(flags() | Qt::FramelessWindowHint);
setSurfaceType(QWindow::OpenGLSurface);
QSurfaceFormat format = QSurfaceFormat::defaultFormat();
// qDebug() << format;
#ifdef QT_OPENGL_ES_2
format.setRenderableType(QSurfaceFormat::OpenGLES);
#else
if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) {
format.setVersion(4, 0);
format.setProfile(QSurfaceFormat::CoreProfile);
}
#endif
format.setDepthBufferSize(24);
format.setSamples(8);
// format.setStencilBufferSize(8);
setFormat(format);
QSurfaceFormat::setDefaultFormat(format);
}
OpenGLWindow::~OpenGLWindow() {
delete m_device;
}
void OpenGLWindow::render(QPainter *painter) {
}
void OpenGLWindow::initialize() {
}
void OpenGLWindow::render() {
// if (!m_device) m_device = new QOpenGLPaintDevice;
// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// m_device->setSize(size() * devicePixelRatio());
// m_device->setDevicePixelRatio(devicePixelRatio());
// QPainter painter(m_device);
// render(&painter);
}
void OpenGLWindow::renderLater() {
requestUpdate();
}
bool OpenGLWindow::event(QEvent *event) {
switch (event->type()) {
case QEvent::UpdateRequest:
renderNow();
return true;
default:
return QWindow::event(event);
}
}
void OpenGLWindow::exposeEvent(QExposeEvent *event) {
if (isExposed()) renderNow();
}
void OpenGLWindow::renderNow() {
if (!isExposed())
return;
bool needsInitialize = false;
if (!m_context) {
m_context = new QOpenGLContext(this);
m_context->setFormat(requestedFormat());
m_context->create();
needsInitialize = true;
}
m_context->makeCurrent(this);
if (needsInitialize) {
initializeOpenGLFunctions();
initialize();
}
render();
m_context->swapBuffers(this);
}
/*
QGL OpenGLWindow
Ivan Pelipenko peri4ko@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/>.
*/
#include "openglwindow.h"
#include <QCoreApplication>
#include <QOpenGLContext>
#include <QOpenGLPaintDevice>
#include <QPainter>
OpenGLWindow::OpenGLWindow(QWindow *parent)
: QWindow(parent)
, m_context(nullptr)
, m_device(nullptr)
{
setFlags(flags() | Qt::FramelessWindowHint);
setSurfaceType(QWindow::OpenGLSurface);
QSurfaceFormat format = QSurfaceFormat::defaultFormat();
// qDebug() << format;
#ifdef QT_OPENGL_ES_2
format.setRenderableType(QSurfaceFormat::OpenGLES);
#else
if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) {
format.setVersion(4, 0);
format.setProfile(QSurfaceFormat::CoreProfile);
}
#endif
format.setDepthBufferSize(24);
format.setSamples(8);
// format.setStencilBufferSize(8);
setFormat(format);
QSurfaceFormat::setDefaultFormat(format);
}
OpenGLWindow::~OpenGLWindow() {
delete m_device;
}
void OpenGLWindow::render(QPainter *painter) {
}
void OpenGLWindow::initialize() {
}
void OpenGLWindow::render() {
// if (!m_device) m_device = new QOpenGLPaintDevice;
// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// m_device->setSize(size() * devicePixelRatio());
// m_device->setDevicePixelRatio(devicePixelRatio());
// QPainter painter(m_device);
// render(&painter);
}
void OpenGLWindow::renderLater() {
requestUpdate();
}
bool OpenGLWindow::event(QEvent *event) {
switch (event->type()) {
case QEvent::UpdateRequest:
renderNow();
return true;
default:
return QWindow::event(event);
}
}
void OpenGLWindow::exposeEvent(QExposeEvent *event) {
if (isExposed()) renderNow();
}
void OpenGLWindow::renderNow() {
if (!isExposed())
return;
bool needsInitialize = false;
if (!m_context) {
m_context = new QOpenGLContext(this);
m_context->setFormat(requestedFormat());
m_context->create();
needsInitialize = true;
}
m_context->makeCurrent(this);
if (needsInitialize) {
initializeOpenGLFunctions();
initialize();
}
render();
m_context->swapBuffers(this);
}

View File

@@ -1,54 +1,54 @@
/*
QGL OpenGLWindow
Ivan Pelipenko peri4ko@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/>.
*/
#include <QWindow>
#include <QOpenGLExtraFunctions>
class QPainter;
class QOpenGLContext;
class QOpenGLPaintDevice;
class OpenGLWindow: public QWindow, protected QOpenGLExtraFunctions
{
Q_OBJECT
public:
explicit OpenGLWindow(QWindow *parent = nullptr);
~OpenGLWindow();
virtual void render(QPainter *painter);
virtual void render();
virtual void initialize();
QOpenGLContext * context() {return m_context;}
public slots:
void renderLater();
void renderNow();
protected:
bool event(QEvent *event) override;
void exposeEvent(QExposeEvent *event) override;
private:
QOpenGLContext *m_context;
QOpenGLPaintDevice *m_device;
};
/*
QGL OpenGLWindow
Ivan Pelipenko peri4ko@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/>.
*/
#include <QWindow>
#include <QOpenGLExtraFunctions>
class QPainter;
class QOpenGLContext;
class QOpenGLPaintDevice;
class OpenGLWindow: public QWindow, protected QOpenGLExtraFunctions
{
Q_OBJECT
public:
explicit OpenGLWindow(QWindow *parent = nullptr);
~OpenGLWindow();
virtual void render(QPainter *painter);
virtual void render();
virtual void initialize();
QOpenGLContext * context() {return m_context;}
public slots:
void renderLater();
void renderNow();
protected:
bool event(QEvent *event) override;
void exposeEvent(QExposeEvent *event) override;
private:
QOpenGLContext *m_context;
QOpenGLPaintDevice *m_device;
};

View File

@@ -1,18 +1,18 @@
if (DESIGNER_PLUGINS)
if (NOT Qt5)
message(WARNING "Building ${PROJECT_NAME} available only on Qt5!")
else()
project(qglengine_plugin)
include_directories("..")
add_definitions(-DQT_PLUGIN)
add_definitions(-DQT_NO_DEBUG)
add_definitions(-DQT_SHARED)
add_definitions(-DQDESIGNER_EXPORT_WIDGETS)
find_qt(Qt5 Core Designer Gui Widgets OpenGL)
qt_sources(SRC)
qt_wrap(${SRC} CPPS out_CPP QMS out_QM)
qt_add_library(${PROJECT_NAME} SHARED out_CPP)
qt_target_link_libraries(${PROJECT_NAME} qglengine)
qt_install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION QtPlugins/designer)
endif()
endif()
if (DESIGNER_PLUGINS)
if (NOT Qt5)
message(WARNING "Building ${PROJECT_NAME} available only on Qt5!")
else()
project(qglengine_plugin)
include_directories("..")
add_definitions(-DQT_PLUGIN)
add_definitions(-DQT_NO_DEBUG)
add_definitions(-DQT_SHARED)
add_definitions(-DQDESIGNER_EXPORT_WIDGETS)
find_qt(Qt5 Core Designer Gui Widgets OpenGL)
qt_sources(SRC)
qt_wrap(${SRC} CPPS out_CPP QMS out_QM)
qt_add_library(${PROJECT_NAME} SHARED out_CPP)
qt_target_link_libraries(${PROJECT_NAME} qglengine)
qt_install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION QtPlugins/designer)
endif()
endif()

View File

@@ -1,299 +1,299 @@
/*
QGLView
Ivan Pelipenko peri4ko@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/>.
*/
#include "qglview.h"
#include "glmesh.h"
#include "gltexture_manager.h"
#include <chunkstream.h>
#include <qad_types.h>
#include <QApplication>
#include <QOpenGLTexture>
#include <QKeyEvent>
using namespace QGLEngineShaders;
QGLView::QGLView(): OpenGLWindow(), renderer_(this), mouse(this) {
setIcon(QIcon(":/icons/qglview.png"));
deleting_ = false;
timer = 0;
need_init_ = is_first_draw = true;
backColor_ = Qt::darkGray;
hoverHaloColor_ = QColor(195, 140, 255);
selectionHaloColor_ = QColor(175, 255, 140);
ambientColor_ = QColor(10, 10, 10);
lineWidth_ = 1.;
max_anisotropic = 1;
max_texture_chanels = 8;
lightEnabled_ = true;
shaders_supported = false;
fps_cnt = 0;
fps_tm = fps_ = 0.;
fogColor_ = Qt::darkGray;
fogDensity_ = 0.;
fogDecay_ = 10.;
hoverHaloFill_ = selectionHaloFill_ = 0.15f;
//lmode = Simple;
setFeature(qglFXAA, false);
setFeature(qglAnisotropicLevel, 8);
setFeature(qglEyeAccomodationEnabled, false);
setFeature(qglEyeAccomodationTime, 16.);
setFeature(qglEyeAccomodationMaxSpeed, 0.2);
setFeature(qglBloomEnabled, false);
setFeature(qglBloomThreshold, 0.9);
setFeature(qglBloomFactor, 1.);
setFeature(qglBloomRadius, 8);
setFeature(qglMotionBlurEnabled, false);
setFeature(qglMotionBlurFactor, 1.);
setFeature(qglMotionBlurSteps, 8);
setFeature(qglShadowsEnabled, false);
setFeature(qglShadowsMapSize, 512);
setFeature(qglShadowsSoftEnabled, true);
setFeature(qglReflectionsEnabled, false);
setFeature(qglReflectionsBlur, true);
setFeature(qglSSAOEnabled, false);
setFeature(qglSSAORadius, 5);
setFeature(qglDepthOfFieldEnabled, false);
setFeature(qglDepthOfFieldAutoFocusEnabled, true);
setFeature(qglDepthOfFieldAutoFocusSpeed, 0.1);
setFeature(qglDepthOfFieldFocus, 1.);
setFeature(qglDepthOfFieldDiaphragm, 8.);
hoverHalo_ = selectionHalo_ = true;
fogEnabled_ = is_init = shaders_bind = changed_ = false;
rmode = ObjectBase::Fill;
// sel_pen = QPen(Qt::black, 1, Qt::DashLine);
// sel_brush = QBrush(QColor(170, 100, 255, 120));
scene_ = new Scene();
connect(scene_, SIGNAL(selectionChanged()), this, SIGNAL(selectionChanged()));
connect(scene_, SIGNAL(__destroyed()), this, SLOT(__destroyed()));
connect(scene_, SIGNAL(__objectDeleted(ObjectBase*)), this, SLOT(__objectDeleted(ObjectBase*)));
default_camera = new Camera();
default_camera->setPos(QVector3D(2, 2, 2));
default_camera->setAim(QVector3D());
camera_ = default_camera;
// qDebug() << camera_->aim();
default_camera->setName("Camera");
emit cameraPosChanged(default_camera->pos());
//camera().aim_ = camera().pos_;
ktm_.restart();
//Mesh * m = Primitive::torus(100, 40, 1., 0.4, 360);
Mesh * m = Primitive::cube(10, 10, 10);
m->flipNormals();
//QMatrix4x4 mat;
//mat.rotate(90, 0,1,0);
//mat.translate(0, 0, 2);
//mat.rotate(180, 1,0,0);
//m->transformPoints(mat);
ObjectBase * o = new ObjectBase(m);
o->setColor(Qt::cyan);
scene()->addObject(o);
delete m;
}
QGLView::~QGLView() {
deleting_ = true;
stop();
scene_->clear();
delete scene_;
delete default_camera;
}
void QGLView::stop() {
if (timer) killTimer(timer);
}
void QGLView::start(float freq) {
timer = startTimer(freq <= 0.f ? 0 : int(1000.f / freq));
}
QList<Light * > QGLView::selectedLights() const {
QList<Light * > ret;
ObjectBaseList sol = scene_->selectedObjects();
foreach (ObjectBase * o, sol)
if (o->type() == ObjectBase::glLight)
ret << (Light*)o;
return ret;
}
QList<Camera * > QGLView::selectedCameras() const {
QList<Camera * > ret;
ObjectBaseList sol = scene_->selectedObjects();
foreach (ObjectBase * o, sol)
if (o->type() == ObjectBase::glCamera)
ret << (Camera*)o;
return ret;
}
void QGLView::resizeEvent(QResizeEvent * e) {
renderLater();
mouse.resize();
}
void QGLView::timerEvent(QTimerEvent *) {
renderNow();
//if (ktm_.elapsed() < QApplication::keyboardInputInterval()) return;
Qt::KeyboardModifiers km = QApplication::keyboardModifiers();
foreach (int i, keys_)
emit keyEvent((Qt::Key)i, km);
}
void QGLView::render() {
resizeGL(width(), height());
emit glBeginPaint();
renderer_.mouse_pos = mapFromGlobal(QCursor::pos());
renderer_.renderScene();
emit glEndPaint();
fps_tm += time.elapsed();
time.restart();
fps_cnt++;
if (fps_tm < 1000.) return;
fps_ = fps_cnt / fps_tm * 1000.;
fps_tm = 0.;
fps_cnt = 0;
}
void QGLView::initialize() {
checkCaps();
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glDisable(GL_MULTISAMPLE);
glDisable(GL_BLEND);
glEnable(GL_TEXTURE_2D);
glEnable(GL_TEXTURE_CUBE_MAP);
glEnable(GL_TEXTURE_MAX_ANISOTROPY_EXT);
glEnable(GL_CULL_FACE);
glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
glCullFace(GL_BACK);
renderer_.reloadShaders();
renderer_.init(width(), height());
is_init = true;
need_init_ = false;
emit glInitializeDone();
}
void QGLView::checkCaps() {
glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &max_anisotropic);
shaders_supported = QOpenGLShaderProgram::hasOpenGLShaderPrograms();
}
void QGLView::__destroyed() {
renderer_.rend_mat.mat_thumbnails.clear();
mouse.hov_objects.clear();
}
void QGLView::__objectDeleted(ObjectBase * o) {
if (o == camera_)
setDefaultCamera();
}
void QGLView::resizeGL(int width, int height) {
if (!is_init) return;
if (width <= 0 || height <= 0) return;
if (prev_size == QSize(width, height)) return;
prev_size = QSize(width, height);
aspect = float(width) / float(height);
renderer_.resize(width, height);
//qDebug() << "resize" << width << height;
iaspect = (aspect == 0.f) ? 0. : 1 / aspect;
glViewport(0, 0, width, height);
emit glResize(width, height);
}
void QGLView::keyPressEvent(QKeyEvent * e) {
emit glKeyPressEvent(e);
if (e->key() > 0) keys_.insert(e->key());
if (e->key() == Qt::Key_F11) {
emit doubleClick();
}
}
void QGLView::keyReleaseEvent(QKeyEvent * e) {
emit glKeyReleaseEvent(e);
keys_.remove(e->key());
}
void QGLView::focusOutEvent(QFocusEvent *) {
keys_.clear();
}
void QGLView::focusOn(const Box3D & bb) {
if (bb.isEmpty() || !camera()) return;
double size = qMax(qMax(bb.width, bb.length), bb.height);
camera()->setAim(bb.center());
camera()->flyToDistance(size * 1.25);
}
QByteArray QGLView::saveCamera() {
ChunkStream cs;
const Camera * c = camera();
cs.add(1, c->pos()).add(2, c->aim()).add(3, c->rotation()).add(4, c->FOV());
return cs.data();
}
void QGLView::restoreCamera(const QByteArray & ba) {
if (ba.isEmpty()) return;
Camera * c = camera();
QVector3D pos(c->pos()), aim(c->aim()), ang(c->rotation());
float fov(c->FOV());
ChunkStream cs(ba);
cs.readAll();
cs.get(1, pos).get(2, aim).get(3, ang).get(4, fov);
camera()->setPos(pos);
camera()->setAim(aim);
camera()->setAngles(ang);
camera()->setFOV(fov);
}
QByteArray QGLView::saveFeatures() {
QByteArray ba;
QDataStream ds(&ba, QIODevice::WriteOnly);
ds << features_;
return ba;
}
void QGLView::restoreFeatures(const QByteArray & ba) {
QHash<int, QVariant> f;
QDataStream ds(ba);
ds >> f;
features_ = f;
}
/*
QGLView
Ivan Pelipenko peri4ko@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/>.
*/
#include "qglview.h"
#include "glmesh.h"
#include "gltexture_manager.h"
#include <chunkstream.h>
#include <qad_types.h>
#include <QApplication>
#include <QOpenGLTexture>
#include <QKeyEvent>
using namespace QGLEngineShaders;
QGLView::QGLView(): OpenGLWindow(), renderer_(this), mouse(this) {
setIcon(QIcon(":/icons/qglview.png"));
deleting_ = false;
timer = 0;
need_init_ = is_first_draw = true;
backColor_ = Qt::darkGray;
hoverHaloColor_ = QColor(195, 140, 255);
selectionHaloColor_ = QColor(175, 255, 140);
ambientColor_ = QColor(10, 10, 10);
lineWidth_ = 1.;
max_anisotropic = 1;
max_texture_chanels = 8;
lightEnabled_ = true;
shaders_supported = false;
fps_cnt = 0;
fps_tm = fps_ = 0.;
fogColor_ = Qt::darkGray;
fogDensity_ = 0.;
fogDecay_ = 10.;
hoverHaloFill_ = selectionHaloFill_ = 0.15f;
//lmode = Simple;
setFeature(qglFXAA, false);
setFeature(qglAnisotropicLevel, 8);
setFeature(qglEyeAccomodationEnabled, false);
setFeature(qglEyeAccomodationTime, 16.);
setFeature(qglEyeAccomodationMaxSpeed, 0.2);
setFeature(qglBloomEnabled, false);
setFeature(qglBloomThreshold, 0.9);
setFeature(qglBloomFactor, 1.);
setFeature(qglBloomRadius, 8);
setFeature(qglMotionBlurEnabled, false);
setFeature(qglMotionBlurFactor, 1.);
setFeature(qglMotionBlurSteps, 8);
setFeature(qglShadowsEnabled, false);
setFeature(qglShadowsMapSize, 512);
setFeature(qglShadowsSoftEnabled, true);
setFeature(qglReflectionsEnabled, false);
setFeature(qglReflectionsBlur, true);
setFeature(qglSSAOEnabled, false);
setFeature(qglSSAORadius, 5);
setFeature(qglDepthOfFieldEnabled, false);
setFeature(qglDepthOfFieldAutoFocusEnabled, true);
setFeature(qglDepthOfFieldAutoFocusSpeed, 0.1);
setFeature(qglDepthOfFieldFocus, 1.);
setFeature(qglDepthOfFieldDiaphragm, 8.);
hoverHalo_ = selectionHalo_ = true;
fogEnabled_ = is_init = shaders_bind = changed_ = false;
rmode = ObjectBase::Fill;
// sel_pen = QPen(Qt::black, 1, Qt::DashLine);
// sel_brush = QBrush(QColor(170, 100, 255, 120));
scene_ = new Scene();
connect(scene_, SIGNAL(selectionChanged()), this, SIGNAL(selectionChanged()));
connect(scene_, SIGNAL(__destroyed()), this, SLOT(__destroyed()));
connect(scene_, SIGNAL(__objectDeleted(ObjectBase*)), this, SLOT(__objectDeleted(ObjectBase*)));
default_camera = new Camera();
default_camera->setPos(QVector3D(2, 2, 2));
default_camera->setAim(QVector3D());
camera_ = default_camera;
// qDebug() << camera_->aim();
default_camera->setName("Camera");
emit cameraPosChanged(default_camera->pos());
//camera().aim_ = camera().pos_;
ktm_.restart();
//Mesh * m = Primitive::torus(100, 40, 1., 0.4, 360);
Mesh * m = Primitive::cube(10, 10, 10);
m->flipNormals();
//QMatrix4x4 mat;
//mat.rotate(90, 0,1,0);
//mat.translate(0, 0, 2);
//mat.rotate(180, 1,0,0);
//m->transformPoints(mat);
ObjectBase * o = new ObjectBase(m);
o->setColor(Qt::cyan);
scene()->addObject(o);
delete m;
}
QGLView::~QGLView() {
deleting_ = true;
stop();
scene_->clear();
delete scene_;
delete default_camera;
}
void QGLView::stop() {
if (timer) killTimer(timer);
}
void QGLView::start(float freq) {
timer = startTimer(freq <= 0.f ? 0 : int(1000.f / freq));
}
QList<Light * > QGLView::selectedLights() const {
QList<Light * > ret;
ObjectBaseList sol = scene_->selectedObjects();
foreach (ObjectBase * o, sol)
if (o->type() == ObjectBase::glLight)
ret << (Light*)o;
return ret;
}
QList<Camera * > QGLView::selectedCameras() const {
QList<Camera * > ret;
ObjectBaseList sol = scene_->selectedObjects();
foreach (ObjectBase * o, sol)
if (o->type() == ObjectBase::glCamera)
ret << (Camera*)o;
return ret;
}
void QGLView::resizeEvent(QResizeEvent * e) {
renderLater();
mouse.resize();
}
void QGLView::timerEvent(QTimerEvent *) {
renderNow();
//if (ktm_.elapsed() < QApplication::keyboardInputInterval()) return;
Qt::KeyboardModifiers km = QApplication::keyboardModifiers();
foreach (int i, keys_)
emit keyEvent((Qt::Key)i, km);
}
void QGLView::render() {
resizeGL(width(), height());
emit glBeginPaint();
renderer_.mouse_pos = mapFromGlobal(QCursor::pos());
renderer_.renderScene();
emit glEndPaint();
fps_tm += time.elapsed();
time.restart();
fps_cnt++;
if (fps_tm < 1000.) return;
fps_ = fps_cnt / fps_tm * 1000.;
fps_tm = 0.;
fps_cnt = 0;
}
void QGLView::initialize() {
checkCaps();
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glDisable(GL_MULTISAMPLE);
glDisable(GL_BLEND);
glEnable(GL_TEXTURE_2D);
glEnable(GL_TEXTURE_CUBE_MAP);
glEnable(GL_TEXTURE_MAX_ANISOTROPY_EXT);
glEnable(GL_CULL_FACE);
glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
glCullFace(GL_BACK);
renderer_.reloadShaders();
renderer_.init(width(), height());
is_init = true;
need_init_ = false;
emit glInitializeDone();
}
void QGLView::checkCaps() {
glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &max_anisotropic);
shaders_supported = QOpenGLShaderProgram::hasOpenGLShaderPrograms();
}
void QGLView::__destroyed() {
renderer_.rend_mat.mat_thumbnails.clear();
mouse.hov_objects.clear();
}
void QGLView::__objectDeleted(ObjectBase * o) {
if (o == camera_)
setDefaultCamera();
}
void QGLView::resizeGL(int width, int height) {
if (!is_init) return;
if (width <= 0 || height <= 0) return;
if (prev_size == QSize(width, height)) return;
prev_size = QSize(width, height);
aspect = float(width) / float(height);
renderer_.resize(width, height);
//qDebug() << "resize" << width << height;
iaspect = (aspect == 0.f) ? 0. : 1 / aspect;
glViewport(0, 0, width, height);
emit glResize(width, height);
}
void QGLView::keyPressEvent(QKeyEvent * e) {
emit glKeyPressEvent(e);
if (e->key() > 0) keys_.insert(e->key());
if (e->key() == Qt::Key_F11) {
emit doubleClick();
}
}
void QGLView::keyReleaseEvent(QKeyEvent * e) {
emit glKeyReleaseEvent(e);
keys_.remove(e->key());
}
void QGLView::focusOutEvent(QFocusEvent *) {
keys_.clear();
}
void QGLView::focusOn(const Box3D & bb) {
if (bb.isEmpty() || !camera()) return;
double size = qMax(qMax(bb.width, bb.length), bb.height);
camera()->setAim(bb.center());
camera()->flyToDistance(size * 1.25);
}
QByteArray QGLView::saveCamera() {
ChunkStream cs;
const Camera * c = camera();
cs.add(1, c->pos()).add(2, c->aim()).add(3, c->rotation()).add(4, c->FOV());
return cs.data();
}
void QGLView::restoreCamera(const QByteArray & ba) {
if (ba.isEmpty()) return;
Camera * c = camera();
QVector3D pos(c->pos()), aim(c->aim()), ang(c->rotation());
float fov(c->FOV());
ChunkStream cs(ba);
cs.readAll();
cs.get(1, pos).get(2, aim).get(3, ang).get(4, fov);
camera()->setPos(pos);
camera()->setAim(aim);
camera()->setAngles(ang);
camera()->setFOV(fov);
}
QByteArray QGLView::saveFeatures() {
QByteArray ba;
QDataStream ds(&ba, QIODevice::WriteOnly);
ds << features_;
return ba;
}
void QGLView::restoreFeatures(const QByteArray & ba) {
QHash<int, QVariant> f;
QDataStream ds(ba);
ds >> f;
features_ = f;
}

View File

@@ -1,293 +1,293 @@
/*
QGLView
Ivan Pelipenko peri4ko@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 QGLVIEW_H
#define QGLVIEW_H
#include "openglwindow.h"
#include "glframebuffer.h"
#include "glprimitives.h"
#include "glcamera.h"
#include "glrendererbase.h"
#include "glscene.h"
#include "renderer.h"
#include "mouse_controller.h"
#include <QTime>
#include <QMenu>
class QGLView: public OpenGLWindow
{
friend class MouseController;
friend class GLRendererBase;
friend class TextureManager;
friend class ObjectBase;
friend class Scene;
friend class RendererBase;
friend class Renderer;
friend class RendererMaterial;
friend class RendererService;
friend class RendererSelection;
friend class TonemappingProc;
Q_OBJECT
Q_PROPERTY (QColor backColor READ backColor WRITE setBackColor)
Q_PROPERTY (float lineWidth READ lineWidth WRITE setLineWidth)
Q_PROPERTY (float FOV READ FOV WRITE setFOV)
Q_PROPERTY (float depthStart READ depthStart WRITE setDepthStart)
Q_PROPERTY (float gamma READ gamma WRITE setGamma)
Q_PROPERTY (bool autoExposure READ autoExposure WRITE setAutoExposure)
Q_PROPERTY (QColor ambientColor READ ambientColor WRITE setAmbientColor)
Q_PROPERTY (QColor fogColor READ fogColor WRITE setFogColor)
Q_PROPERTY (bool fogEnabled READ isFogEnabled WRITE setFogEnabled)
Q_PROPERTY (float fogDensity READ fogDensity WRITE setFogDensity)
Q_PROPERTY (float fogDecay READ fogDecay WRITE setFogDecay)
Q_PROPERTY (int renderMode READ renderMode WRITE setRenderMode)
Q_PROPERTY (bool grabMouse READ isGrabMouseEnabled WRITE setGrabMouseEnabled)
Q_PROPERTY (bool mouseRotate READ isMouseRotateEnabled WRITE setMouseRotateEnabled)
Q_PROPERTY (bool mouseSelection READ isMouseSelectionEnabled WRITE setMouseSelectionEnabled)
Q_PROPERTY (bool cameraOrbit READ isCameraOrbit WRITE setCameraOrbit)
Q_PROPERTY (bool hoverHalo READ isHoverHaloEnabled WRITE setHoverHaloEnabled)
Q_PROPERTY (QColor hoverHaloColor READ hoverHaloColor WRITE setHoverHaloColor)
Q_PROPERTY (float hoverHaloFillAlpha READ hoverHaloFillAlpha WRITE setHoverHaloFillAlpha)
Q_PROPERTY (bool selectionHalo READ isSelectionHaloEnabled WRITE setSelectionHaloEnabled)
Q_PROPERTY (QColor selectionHaloColor READ selectionHaloColor WRITE setSelectionHaloColor)
Q_PROPERTY (float selectionHaloFillAlpha READ selectionHaloFillAlpha WRITE setSelectionHaloFillAlpha)
Q_PROPERTY (Qt::MouseButton selectionButton READ selectionButton WRITE setSelectionButton)
Q_PROPERTY (Qt::KeyboardModifier selectionModifier READ selectionModifier WRITE setSelectionModifier)
Q_PROPERTY (Scene::SelectionMode selectionMode READ selectionMode WRITE setSelectionMode)
public:
QGLView();
virtual ~QGLView();
enum CameraLightMode {
clmOff,
clmAuto,
clmOn,
};
enum Feature {
qglFXAA,
qglAnisotropicLevel,
qglEyeAccomodationEnabled,
qglEyeAccomodationTime,
qglEyeAccomodationMaxSpeed,
qglBloomEnabled,
qglBloomThreshold,
qglBloomFactor,
qglBloomRadius,
qglMotionBlurEnabled,
qglMotionBlurFactor,
qglMotionBlurSteps,
qglShadowsEnabled,
qglShadowsMapSize,
qglShadowsSoftEnabled,
qglReflectionsEnabled,
qglReflectionsBlur,
qglSSAOEnabled,
qglSSAORadius,
qglDepthOfFieldEnabled,
qglDepthOfFieldAutoFocusEnabled,
qglDepthOfFieldAutoFocusSpeed,
qglDepthOfFieldFocus,
qglDepthOfFieldDiaphragm
};
Q_ENUM(CameraLightMode)
void stop();
void start(float freq = 60.);
QColor backColor() const {return backColor_;}
float lineWidth() const {return lineWidth_;}
float FOV() const {return camera()->fov_;}
float depthStart() const {return camera()->depth_start;}
float currentFPS() const {return fps_;}
float gamma() const {return renderer_.gamma_;}
bool autoExposure() const {return renderer_.tone_proc.enabled;}
int maxAnisotropicLevel() const {return max_anisotropic;}
QString environmentMapFile() const {return renderer_.tex_env.fileHDR();}
QColor ambientColor() const {return ambientColor_;}
QColor fogColor() const {return fogColor_;}
float fogDensity() const {return fogDensity_;}
float fogDecay() const {return fogDecay_;}
bool isFogEnabled() const {return fogEnabled_;}
bool isLightEnabled() const {return lightEnabled_;}
bool isGrabMouseEnabled() const {return mouse.isGrabMouseEnabled();}
bool isMouseRotateEnabled() const {return mouse.isMouseRotateEnabled();}
bool isMouseSelectionEnabled() const {return mouse.isMouseSelectionEnabled();}
bool isCameraOrbit() const {return mouse.isCameraOrbit();}
bool isHoverHaloEnabled() const {return hoverHalo_;}
QColor hoverHaloColor() const {return hoverHaloColor_;}
float hoverHaloFillAlpha() const {return hoverHaloFill_;}
bool isSelectionHaloEnabled() const {return selectionHalo_;}
QColor selectionHaloColor() const {return selectionHaloColor_;}
float selectionHaloFillAlpha() const {return selectionHaloFill_;}
QVariant feature(Feature f) const {return features_.value(int(f));}
QVariant setFeature(Feature f, const QVariant & value) {QVariant ret = features_.value(int(f)); features_[int(f)] = value; return ret;}
bool isFeatureEnabled(Feature f) const {return features_[int(f)].toBool();}
int renderMode() const {return (int)rmode;}
void setRenderMode(int mode) {rmode = (ObjectBase::RenderMode)mode;}
bool isServiceMode() const {return renderer_.edit_mode;}
void setServiceMode(bool yes) {renderer_.edit_mode = yes;}
Scene::SelectionMode selectionMode() const {return scene_->selectionMode();}
Qt::MouseButton selectionButton() const {return mouse.selectionButton();}
Qt::KeyboardModifier selectionModifier() const {return mouse.selectionModifier();}
void setSelectionMode(Scene::SelectionMode m) {scene_->setSelectionMode(m);}
void setSelectionButton(Qt::MouseButton v) {mouse.setSelectionButton(v);}
void setSelectionModifier(Qt::KeyboardModifier v) {mouse.setSelectionModifier(v);}
void selectObject(ObjectBase * o, bool add_to_selection = false) {scene_->selectObject(o, add_to_selection);}
void clearSelection() {scene_->clearSelection();}
ObjectBaseList selectedObjects(bool top_only = false) const {return scene_->selectedObjects(top_only);}
QList<Light * > selectedLights() const;
QList<Camera * > selectedCameras() const;
ObjectBase * selectedObject() const {return scene_->selectedObject();}
TextureManager * textureManager() {return renderer_.textures_manager;}
void reloadTextures() {renderer_.markReloadTextures();}
Scene * scene() {return scene_;}
void focusOn(const Box3D & bb);
void setCameraLightMode(CameraLightMode m) {renderer_.setCameraLightMode(m);}
CameraLightMode cameraLightMode() const {return (CameraLightMode)renderer_.cameraLightMode();}
Camera * camera() {return camera_;}
const Camera * camera() const {return camera_;}
void setCamera(Camera * camera) {camera_ = camera;}
void setDefaultCamera() {camera_ = default_camera;}
QByteArray saveCamera();
void restoreCamera(const QByteArray & ba);
QByteArray saveFeatures();
void restoreFeatures(const QByteArray & ba);
QImage materialThumbnail(Material * m) {return renderer_.materialThumbnail(m);}
void setCurrentAction(RendererService::HandleAction ha) {renderer_.rend_service.setCurrentAction(ha);}
void setContextActions(QList<QAction*> al) {context_menu.clear(); context_menu.addActions(al);}
GLfloat aspect, iaspect;
Renderer renderer_;
protected:
void render();
void resizeEvent(QResizeEvent * e);
void timerEvent(QTimerEvent * );
void initialize();
void resizeGL(int width, int height);
void mousePressEvent(QMouseEvent * e) {mouse.mousePressEvent(e);}
void mouseMoveEvent(QMouseEvent * e) {mouse.mouseMoveEvent(e);}
void mouseReleaseEvent(QMouseEvent * e) {mouse.mouseReleaseEvent(e);}
void wheelEvent(QWheelEvent * e) {mouse.wheelEvent(e);}
void mouseDoubleClickEvent(QMouseEvent * e) {mouse.mouseDoubleClickEvent(e);}
void leaveEvent(QEvent * );
void keyPressEvent(QKeyEvent * e);
void keyReleaseEvent(QKeyEvent * e);
void focusOutEvent(QFocusEvent *);
void checkCaps();
private:
void processKeys();
bool setupViewport();
Scene * scene_;
Camera * camera_, * default_camera;
MouseController mouse;
QMenu context_menu;
QSet<int> keys_;
QColor backColor_, fogColor_, ambientColor_, hoverHaloColor_, selectionHaloColor_;
QTime time, ktm_;
GLint max_anisotropic, max_texture_chanels;
ObjectBase::RenderMode rmode;
GLRendererBase::RenderingParameters start_rp;
QHash<int, QVariant> features_;
QSize prev_size;
float lineWidth_;
float fps_, fps_tm, fogDensity_, fogDecay_;
float hoverHaloFill_, selectionHaloFill_, m_motionBlurFactor;
int timer, fps_cnt, sh_id_loc, deleting_;
bool is_first_draw, is_init, fogEnabled_, lightEnabled_;
bool shaders_supported, changed_, need_init_;
bool hoverHalo_, selectionHalo_, shaders_bind;
private slots:
void __destroyed();
void __objectDeleted(ObjectBase * o);
public slots:
void setBackColor(const QColor & arg) {backColor_ = arg;}
void setLineWidth(const float & arg) {lineWidth_ = arg;}
void setFOV(const float & arg) {camera()->fov_ = arg;}
void setDepthStart(const float & arg) {camera()->depth_start = arg;}
void setGamma(const float & arg) {renderer_.gamma_ = arg;}
void setAutoExposure(bool arg) {renderer_.tone_proc.enabled = arg;}
void setAmbientColor(const QColor & arg) {ambientColor_ = arg;}
void setEnvironmentMapFile(QString file) {renderer_.tex_env.setFileHDR(file); renderer_.recreateMaterialThumbnails(true);}
void setFogColor(const QColor & arg) {fogColor_ = arg;}
void setFogDensity(const float & arg) {fogDensity_ = arg;}
void setFogDecay(const float & arg) {fogDecay_ = arg;}
void setFogEnabled(const bool & arg) {fogEnabled_ = arg;}
void setLightEnabled(const bool & arg) {lightEnabled_ = arg;}
void setGrabMouseEnabled(const bool & arg) {mouse.setGrabMouseEnabled(arg);}
void setMouseRotateEnabled(const bool & arg) {mouse.setMouseRotateEnabled(arg);}
void setMouseSelectionEnabled(const bool & arg) {mouse.setMouseSelectionEnabled(arg);}
void setCustomMouseMove(const bool & arg) {mouse.setCustomMouseMove(arg);}
void setCameraOrbit(const bool & arg) {mouse.setCameraOrbit(arg);}
void setHoverHaloEnabled(const bool & arg) {hoverHalo_ = arg;}
void setHoverHaloColor(const QColor & arg) {hoverHaloColor_ = arg;}
void setHoverHaloFillAlpha(const float & arg) {hoverHaloFill_ = arg;}
void setSelectionHaloEnabled(const bool & arg) {selectionHalo_ = arg;}
void setSelectionHaloColor(const QColor & arg) {selectionHaloColor_ = arg;}
void setSelectionHaloFillAlpha(const float & arg) {selectionHaloFill_ = arg;}
void reloadShaders() {renderer_.reloadShaders();}
signals:
void glBeginPaint();
void glEndPaint();
void glKeyPressEvent(QKeyEvent * e);
void glKeyReleaseEvent(QKeyEvent * e);
void glMousePressEvent(QMouseEvent * e);
void glMouseMoveEvent(QMouseEvent * e);
void glMouseReleaseEvent(QMouseEvent * e);
void glWheelEvent(QWheelEvent * e);
void glResize(int, int);
void glInitializeDone();
void cameraPosChanged(QVector3D pos);
void keyEvent(Qt::Key key, Qt::KeyboardModifiers mod);
void customMouseMoveEvent(QPoint curpos, QPoint lastpos, Qt::MouseButtons buttons);
void hoverChanged(ObjectBase * cur, ObjectBase * prev);
void selectionChanged();
void objectsPositionChanged();
void materialsChanged();
void materialThumbnailCreated(Material*);
void doubleClick();
};
#endif // QGLVIEW_H
/*
QGLView
Ivan Pelipenko peri4ko@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 QGLVIEW_H
#define QGLVIEW_H
#include "openglwindow.h"
#include "glframebuffer.h"
#include "glprimitives.h"
#include "glcamera.h"
#include "glrendererbase.h"
#include "glscene.h"
#include "renderer.h"
#include "mouse_controller.h"
#include <QTime>
#include <QMenu>
class QGLView: public OpenGLWindow
{
friend class MouseController;
friend class GLRendererBase;
friend class TextureManager;
friend class ObjectBase;
friend class Scene;
friend class RendererBase;
friend class Renderer;
friend class RendererMaterial;
friend class RendererService;
friend class RendererSelection;
friend class TonemappingProc;
Q_OBJECT
Q_PROPERTY (QColor backColor READ backColor WRITE setBackColor)
Q_PROPERTY (float lineWidth READ lineWidth WRITE setLineWidth)
Q_PROPERTY (float FOV READ FOV WRITE setFOV)
Q_PROPERTY (float depthStart READ depthStart WRITE setDepthStart)
Q_PROPERTY (float gamma READ gamma WRITE setGamma)
Q_PROPERTY (bool autoExposure READ autoExposure WRITE setAutoExposure)
Q_PROPERTY (QColor ambientColor READ ambientColor WRITE setAmbientColor)
Q_PROPERTY (QColor fogColor READ fogColor WRITE setFogColor)
Q_PROPERTY (bool fogEnabled READ isFogEnabled WRITE setFogEnabled)
Q_PROPERTY (float fogDensity READ fogDensity WRITE setFogDensity)
Q_PROPERTY (float fogDecay READ fogDecay WRITE setFogDecay)
Q_PROPERTY (int renderMode READ renderMode WRITE setRenderMode)
Q_PROPERTY (bool grabMouse READ isGrabMouseEnabled WRITE setGrabMouseEnabled)
Q_PROPERTY (bool mouseRotate READ isMouseRotateEnabled WRITE setMouseRotateEnabled)
Q_PROPERTY (bool mouseSelection READ isMouseSelectionEnabled WRITE setMouseSelectionEnabled)
Q_PROPERTY (bool cameraOrbit READ isCameraOrbit WRITE setCameraOrbit)
Q_PROPERTY (bool hoverHalo READ isHoverHaloEnabled WRITE setHoverHaloEnabled)
Q_PROPERTY (QColor hoverHaloColor READ hoverHaloColor WRITE setHoverHaloColor)
Q_PROPERTY (float hoverHaloFillAlpha READ hoverHaloFillAlpha WRITE setHoverHaloFillAlpha)
Q_PROPERTY (bool selectionHalo READ isSelectionHaloEnabled WRITE setSelectionHaloEnabled)
Q_PROPERTY (QColor selectionHaloColor READ selectionHaloColor WRITE setSelectionHaloColor)
Q_PROPERTY (float selectionHaloFillAlpha READ selectionHaloFillAlpha WRITE setSelectionHaloFillAlpha)
Q_PROPERTY (Qt::MouseButton selectionButton READ selectionButton WRITE setSelectionButton)
Q_PROPERTY (Qt::KeyboardModifier selectionModifier READ selectionModifier WRITE setSelectionModifier)
Q_PROPERTY (Scene::SelectionMode selectionMode READ selectionMode WRITE setSelectionMode)
public:
QGLView();
virtual ~QGLView();
enum CameraLightMode {
clmOff,
clmAuto,
clmOn,
};
enum Feature {
qglFXAA,
qglAnisotropicLevel,
qglEyeAccomodationEnabled,
qglEyeAccomodationTime,
qglEyeAccomodationMaxSpeed,
qglBloomEnabled,
qglBloomThreshold,
qglBloomFactor,
qglBloomRadius,
qglMotionBlurEnabled,
qglMotionBlurFactor,
qglMotionBlurSteps,
qglShadowsEnabled,
qglShadowsMapSize,
qglShadowsSoftEnabled,
qglReflectionsEnabled,
qglReflectionsBlur,
qglSSAOEnabled,
qglSSAORadius,
qglDepthOfFieldEnabled,
qglDepthOfFieldAutoFocusEnabled,
qglDepthOfFieldAutoFocusSpeed,
qglDepthOfFieldFocus,
qglDepthOfFieldDiaphragm
};
Q_ENUM(CameraLightMode)
void stop();
void start(float freq = 60.);
QColor backColor() const {return backColor_;}
float lineWidth() const {return lineWidth_;}
float FOV() const {return camera()->fov_;}
float depthStart() const {return camera()->depth_start;}
float currentFPS() const {return fps_;}
float gamma() const {return renderer_.gamma_;}
bool autoExposure() const {return renderer_.tone_proc.enabled;}
int maxAnisotropicLevel() const {return max_anisotropic;}
QString environmentMapFile() const {return renderer_.tex_env.fileHDR();}
QColor ambientColor() const {return ambientColor_;}
QColor fogColor() const {return fogColor_;}
float fogDensity() const {return fogDensity_;}
float fogDecay() const {return fogDecay_;}
bool isFogEnabled() const {return fogEnabled_;}
bool isLightEnabled() const {return lightEnabled_;}
bool isGrabMouseEnabled() const {return mouse.isGrabMouseEnabled();}
bool isMouseRotateEnabled() const {return mouse.isMouseRotateEnabled();}
bool isMouseSelectionEnabled() const {return mouse.isMouseSelectionEnabled();}
bool isCameraOrbit() const {return mouse.isCameraOrbit();}
bool isHoverHaloEnabled() const {return hoverHalo_;}
QColor hoverHaloColor() const {return hoverHaloColor_;}
float hoverHaloFillAlpha() const {return hoverHaloFill_;}
bool isSelectionHaloEnabled() const {return selectionHalo_;}
QColor selectionHaloColor() const {return selectionHaloColor_;}
float selectionHaloFillAlpha() const {return selectionHaloFill_;}
QVariant feature(Feature f) const {return features_.value(int(f));}
QVariant setFeature(Feature f, const QVariant & value) {QVariant ret = features_.value(int(f)); features_[int(f)] = value; return ret;}
bool isFeatureEnabled(Feature f) const {return features_[int(f)].toBool();}
int renderMode() const {return (int)rmode;}
void setRenderMode(int mode) {rmode = (ObjectBase::RenderMode)mode;}
bool isServiceMode() const {return renderer_.edit_mode;}
void setServiceMode(bool yes) {renderer_.edit_mode = yes;}
Scene::SelectionMode selectionMode() const {return scene_->selectionMode();}
Qt::MouseButton selectionButton() const {return mouse.selectionButton();}
Qt::KeyboardModifier selectionModifier() const {return mouse.selectionModifier();}
void setSelectionMode(Scene::SelectionMode m) {scene_->setSelectionMode(m);}
void setSelectionButton(Qt::MouseButton v) {mouse.setSelectionButton(v);}
void setSelectionModifier(Qt::KeyboardModifier v) {mouse.setSelectionModifier(v);}
void selectObject(ObjectBase * o, bool add_to_selection = false) {scene_->selectObject(o, add_to_selection);}
void clearSelection() {scene_->clearSelection();}
ObjectBaseList selectedObjects(bool top_only = false) const {return scene_->selectedObjects(top_only);}
QList<Light * > selectedLights() const;
QList<Camera * > selectedCameras() const;
ObjectBase * selectedObject() const {return scene_->selectedObject();}
TextureManager * textureManager() {return renderer_.textures_manager;}
void reloadTextures() {renderer_.markReloadTextures();}
Scene * scene() {return scene_;}
void focusOn(const Box3D & bb);
void setCameraLightMode(CameraLightMode m) {renderer_.setCameraLightMode(m);}
CameraLightMode cameraLightMode() const {return (CameraLightMode)renderer_.cameraLightMode();}
Camera * camera() {return camera_;}
const Camera * camera() const {return camera_;}
void setCamera(Camera * camera) {camera_ = camera;}
void setDefaultCamera() {camera_ = default_camera;}
QByteArray saveCamera();
void restoreCamera(const QByteArray & ba);
QByteArray saveFeatures();
void restoreFeatures(const QByteArray & ba);
QImage materialThumbnail(Material * m) {return renderer_.materialThumbnail(m);}
void setCurrentAction(RendererService::HandleAction ha) {renderer_.rend_service.setCurrentAction(ha);}
void setContextActions(QList<QAction*> al) {context_menu.clear(); context_menu.addActions(al);}
GLfloat aspect, iaspect;
Renderer renderer_;
protected:
void render();
void resizeEvent(QResizeEvent * e);
void timerEvent(QTimerEvent * );
void initialize();
void resizeGL(int width, int height);
void mousePressEvent(QMouseEvent * e) {mouse.mousePressEvent(e);}
void mouseMoveEvent(QMouseEvent * e) {mouse.mouseMoveEvent(e);}
void mouseReleaseEvent(QMouseEvent * e) {mouse.mouseReleaseEvent(e);}
void wheelEvent(QWheelEvent * e) {mouse.wheelEvent(e);}
void mouseDoubleClickEvent(QMouseEvent * e) {mouse.mouseDoubleClickEvent(e);}
void leaveEvent(QEvent * );
void keyPressEvent(QKeyEvent * e);
void keyReleaseEvent(QKeyEvent * e);
void focusOutEvent(QFocusEvent *);
void checkCaps();
private:
void processKeys();
bool setupViewport();
Scene * scene_;
Camera * camera_, * default_camera;
MouseController mouse;
QMenu context_menu;
QSet<int> keys_;
QColor backColor_, fogColor_, ambientColor_, hoverHaloColor_, selectionHaloColor_;
QTime time, ktm_;
GLint max_anisotropic, max_texture_chanels;
ObjectBase::RenderMode rmode;
GLRendererBase::RenderingParameters start_rp;
QHash<int, QVariant> features_;
QSize prev_size;
float lineWidth_;
float fps_, fps_tm, fogDensity_, fogDecay_;
float hoverHaloFill_, selectionHaloFill_, m_motionBlurFactor;
int timer, fps_cnt, sh_id_loc, deleting_;
bool is_first_draw, is_init, fogEnabled_, lightEnabled_;
bool shaders_supported, changed_, need_init_;
bool hoverHalo_, selectionHalo_, shaders_bind;
private slots:
void __destroyed();
void __objectDeleted(ObjectBase * o);
public slots:
void setBackColor(const QColor & arg) {backColor_ = arg;}
void setLineWidth(const float & arg) {lineWidth_ = arg;}
void setFOV(const float & arg) {camera()->fov_ = arg;}
void setDepthStart(const float & arg) {camera()->depth_start = arg;}
void setGamma(const float & arg) {renderer_.gamma_ = arg;}
void setAutoExposure(bool arg) {renderer_.tone_proc.enabled = arg;}
void setAmbientColor(const QColor & arg) {ambientColor_ = arg;}
void setEnvironmentMapFile(QString file) {renderer_.tex_env.setFileHDR(file); renderer_.recreateMaterialThumbnails(true);}
void setFogColor(const QColor & arg) {fogColor_ = arg;}
void setFogDensity(const float & arg) {fogDensity_ = arg;}
void setFogDecay(const float & arg) {fogDecay_ = arg;}
void setFogEnabled(const bool & arg) {fogEnabled_ = arg;}
void setLightEnabled(const bool & arg) {lightEnabled_ = arg;}
void setGrabMouseEnabled(const bool & arg) {mouse.setGrabMouseEnabled(arg);}
void setMouseRotateEnabled(const bool & arg) {mouse.setMouseRotateEnabled(arg);}
void setMouseSelectionEnabled(const bool & arg) {mouse.setMouseSelectionEnabled(arg);}
void setCustomMouseMove(const bool & arg) {mouse.setCustomMouseMove(arg);}
void setCameraOrbit(const bool & arg) {mouse.setCameraOrbit(arg);}
void setHoverHaloEnabled(const bool & arg) {hoverHalo_ = arg;}
void setHoverHaloColor(const QColor & arg) {hoverHaloColor_ = arg;}
void setHoverHaloFillAlpha(const float & arg) {hoverHaloFill_ = arg;}
void setSelectionHaloEnabled(const bool & arg) {selectionHalo_ = arg;}
void setSelectionHaloColor(const QColor & arg) {selectionHaloColor_ = arg;}
void setSelectionHaloFillAlpha(const float & arg) {selectionHaloFill_ = arg;}
void reloadShaders() {renderer_.reloadShaders();}
signals:
void glBeginPaint();
void glEndPaint();
void glKeyPressEvent(QKeyEvent * e);
void glKeyReleaseEvent(QKeyEvent * e);
void glMousePressEvent(QMouseEvent * e);
void glMouseMoveEvent(QMouseEvent * e);
void glMouseReleaseEvent(QMouseEvent * e);
void glWheelEvent(QWheelEvent * e);
void glResize(int, int);
void glInitializeDone();
void cameraPosChanged(QVector3D pos);
void keyEvent(Qt::Key key, Qt::KeyboardModifiers mod);
void customMouseMoveEvent(QPoint curpos, QPoint lastpos, Qt::MouseButtons buttons);
void hoverChanged(ObjectBase * cur, ObjectBase * prev);
void selectionChanged();
void objectsPositionChanged();
void materialsChanged();
void materialThumbnailCreated(Material*);
void doubleClick();
};
#endif // QGLVIEW_H

View File

@@ -1,19 +1,19 @@
<RCC>
<qresource prefix="/">
<file>shaders/ds_final.glsl</file>
<file>shaders/ds_geom.glsl</file>
<file>shaders/ds_light.glsl</file>
<file>shaders/ds_tonemap.glsl</file>
<file>shaders/fxaa.frag</file>
<file>shaders/fxaa.vert</file>
<file>shaders/fxaa_v3.h</file>
<file>shaders/selection.glsl</file>
<file>shaders/selection_apply.glsl</file>
<file>shaders/selection_frame.glsl</file>
<file>shaders/selection_halo.glsl</file>
<file>shaders/service_fill.glsl</file>
<file>shaders/service_frame.glsl</file>
<file>shaders/service_line.glsl</file>
<file>shaders/sum.glsl</file>
</qresource>
</RCC>
<RCC>
<qresource prefix="/">
<file>shaders/ds_final.glsl</file>
<file>shaders/ds_geom.glsl</file>
<file>shaders/ds_light.glsl</file>
<file>shaders/ds_tonemap.glsl</file>
<file>shaders/fxaa.frag</file>
<file>shaders/fxaa.vert</file>
<file>shaders/fxaa_v3.h</file>
<file>shaders/selection.glsl</file>
<file>shaders/selection_apply.glsl</file>
<file>shaders/selection_frame.glsl</file>
<file>shaders/selection_halo.glsl</file>
<file>shaders/service_fill.glsl</file>
<file>shaders/service_frame.glsl</file>
<file>shaders/service_line.glsl</file>
<file>shaders/sum.glsl</file>
</qresource>
</RCC>

View File

@@ -1,49 +1,26 @@
cmake_minimum_required(VERSION 3.0)
project(qglengine_widgets)
if (POLICY CMP0017)
cmake_policy(SET CMP0017 NEW)
endif()
find_qt(Qt5 Core Gui Widgets)
qt_sources(SRC)
qt_wrap(${SRC} HDRS out_HDR CPPS out_CPP QMS out_QM)
file(GLOB PHS "*_p.h")
list(REMOVE_ITEM out_HDR "${PHS}")
import_version(${PROJECT_NAME} qglengine)
set_deploy_property(${PROJECT_NAME} SHARED
LABEL "QGLEngine widgets library"
FULLNAME "${_DOMAIN}.${PROJECT_NAME}"
COMPANY "${_COMPANY}"
INFO "QGLEngine widgets library")
make_rc(${PROJECT_NAME} _RC)
qt_add_library(${PROJECT_NAME} SHARED out_CPP ${_RC})
qt_target_link_libraries(${PROJECT_NAME} qad_utils qad_widgets qglengine_core)
qt_target_include_directories(${PROJECT_NAME} PRIVATE ${QAD_INCLUDES} "${CMAKE_CURRENT_SOURCE_DIR}/../" "${CMAKE_CURRENT_SOURCE_DIR}/../core")
list(APPEND QT_MULTILIB_LIST ${PROJECT_NAME})
set(QT_MULTILIB_LIST ${QT_MULTILIB_LIST} PARENT_SCOPE)
#message(STATUS "Building ${PROJECT_NAME}")
if (LIBPROJECT)
sdk_install("qglengine" FALSE "${PROJECT_NAME}" "${out_HDR}" "${out_QM}")
else()
if (LIB)
if (WIN32)
qt_install(FILES ${out_HDR} DESTINATION ${MINGW_INCLUDE}/qglengine)
qt_install(TARGETS ${PROJECT_NAME} DESTINATION ${MINGW_LIB})
qt_install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION ${MINGW_BIN})
qt_install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION QtBin)
else()
qt_install(FILES ${out_HDR} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/qglengine)
qt_install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib)
endif()
message(STATUS "Install ${PROJECT_NAME} to system \"${CMAKE_INSTALL_PREFIX}\"")
else()
if(WIN32)
qt_install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin)
qt_install(TARGETS ${PROJECT_NAME} ARCHIVE DESTINATION lib)
else()
qt_install(TARGETS ${PROJECT_NAME} DESTINATION bin/lib)
endif()
qt_install(TARGETS ${PROJECT_NAME} DESTINATION lib)
qt_install(FILES ${H} DESTINATION include/qglengine)
message(STATUS "Install ${PROJECT_NAME} to local \"bin\", \"lib\" and \"include\"")
endif()
endif()
cmake_minimum_required(VERSION 3.0)
project(qglengine_widgets)
if (POLICY CMP0017)
cmake_policy(SET CMP0017 NEW)
endif()
find_qt(Qt5 Core Gui Widgets)
qt_sources(SRC)
qt_wrap(${SRC} HDRS out_HDR CPPS out_CPP QMS out_QM)
file(GLOB PHS "*_p.h")
list(REMOVE_ITEM out_HDR "${PHS}")
import_version(${PROJECT_NAME} qglengine)
set_deploy_property(${PROJECT_NAME} SHARED
LABEL "QGLEngine widgets library"
FULLNAME "${_DOMAIN}.${PROJECT_NAME}"
COMPANY "${_COMPANY}"
INFO "QGLEngine widgets library")
make_rc(${PROJECT_NAME} _RC)
qt_add_library(${PROJECT_NAME} SHARED out_CPP ${_RC})
qt_generate_export_header(${PROJECT_NAME})
list(APPEND out_HDR "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}_export.h")
qt_target_link_libraries(${PROJECT_NAME} qad_utils qad_widgets qglengine_core)
qt_target_include_directories(${PROJECT_NAME} PRIVATE ${QAD_INCLUDES} "${CMAKE_CURRENT_SOURCE_DIR}/../" "${CMAKE_CURRENT_SOURCE_DIR}/../core")
list(APPEND QT_MULTILIB_LIST ${PROJECT_NAME})
copy_to_parent("")
#message(STATUS "Building ${PROJECT_NAME}")
sdk_install("qglengine" FALSE "${PROJECT_NAME}" "${out_HDR}" "${out_QM}")

View File

@@ -1,259 +1,259 @@
/*
QGL PrimitiveEditor
Ivan Pelipenko peri4ko@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/>.
*/
#include "primitiveeditor.h"
#include "ui_primitiveeditor.h"
#include <QMetaEnum>
#include "glprimitives.h"
#include "glmesh.h"
PrimitiveEditor::PrimitiveEditor(QWidget *parent) : QWidget(parent), ui(new Ui::PrimitiveEditor) {
view = 0;
can_replace = false;
ui->setupUi(this);
#if QT_VERSION >= QT_VERSION_CHECK(5,12,0)
ui->spinSegments->setStepType(QAbstractSpinBox::AdaptiveDecimalStepType);
ui->spinSegments2->setStepType(QAbstractSpinBox::AdaptiveDecimalStepType);
#endif
editors[Plane] << ui->widgetWidth;
editors[Plane] << ui->widgetLength;
editors[Cube] << ui->widgetWidth;
editors[Cube] << ui->widgetLength;
editors[Cube] << ui->widgetHeight;
editors[Ellipsoid] << ui->widgetRadius1;
editors[Ellipsoid] << ui->widgetSegments;
editors[Ellipsoid] << ui->widgetSegments2;
editors[Ellipsoid] << ui->widgetAngle;
editors[Disc] << ui->widgetRadius1;
editors[Disc] << ui->widgetSegments;
editors[Disc] << ui->widgetAngle;
editors[Cone] << ui->widgetRadius1;
editors[Cone] << ui->widgetHeight;
editors[Cone] << ui->widgetSegments;
editors[Cylinder] << ui->widgetRadius1;
editors[Cylinder] << ui->widgetHeight;
editors[Cylinder] << ui->widgetSegments;
editors[Cylinder] << ui->widgetAngle;
editors[Torus] << ui->widgetRadius1;
editors[Torus] << ui->widgetRadius2;
editors[Torus] << ui->widgetSegments;
editors[Torus] << ui->widgetSegments2;
editors[Torus] << ui->widgetAngle;
QSet<QWidget *> all;
QMetaEnum me = metaObject()->enumerator(0);
for (int i=0; i<me.keyCount(); ++i) {
ui->comboPrimitives->addItem(me.key(i));
all.unite(editors[(PrimitiveType)me.value(i)].toSet());
}
all_editors = all.toList();
foreach (QWidget * w, all_editors) {
if (w->layout()) w->layout()->setContentsMargins(0, layout()->spacing(), 0, 0);
}
ui->comboPrimitives->setCurrentIndex(Plane);
on_comboPrimitives_currentIndexChanged(ui->comboPrimitives->currentIndex());
}
PrimitiveEditor::~PrimitiveEditor() {
delete ui;
}
void PrimitiveEditor::assignQGLView(QGLView * v) {
view = v;
connect(view, SIGNAL(selectionChanged()), this, SLOT(selectionChanged()));
selectionChanged();
}
Mesh * PrimitiveEditor::createMesh(QVariantList & params) {
Mesh * m = 0;
PrimitiveType pt = (PrimitiveType)ui->comboPrimitives->currentIndex();
params << pt;
switch (pt) {
case Plane:
m = Primitive::plane(ui->spinWidth->value(),
ui->spinLength->value());
params << ui->spinWidth->value()
<< ui->spinLength->value();
break;
case Cube:
m = Primitive::cube(ui->spinWidth->value(),
ui->spinLength->value(),
ui->spinHeight->value());
params << ui->spinWidth->value()
<< ui->spinLength->value()
<< ui->spinHeight->value();
break;
case Ellipsoid:
m = Primitive::ellipsoid(ui->spinSegments->value(),
ui->spinSegments2->value(),
ui->spinRadius->value(),
ui->spinAngle->value());
params << ui->spinSegments->value()
<< ui->spinSegments2->value()
<< ui->spinRadius->value()
<< ui->spinAngle->value();
break;
case Disc:
m = Primitive::disc(ui->spinSegments->value(),
ui->spinRadius->value(),
ui->spinAngle->value());
params << ui->spinSegments->value()
<< ui->spinRadius->value()
<< ui->spinAngle->value();
break;
case Cone:
m = Primitive::cone(ui->spinSegments->value(),
ui->spinRadius->value(),
ui->spinHeight->value());
params << ui->spinSegments->value()
<< ui->spinRadius->value()
<< ui->spinHeight->value();
break;
case Cylinder:
m = Primitive::cylinder(ui->spinSegments->value(),
ui->spinRadius->value(),
ui->spinHeight->value(),
ui->spinAngle->value());
params << ui->spinSegments->value()
<< ui->spinRadius->value()
<< ui->spinHeight->value()
<< ui->spinAngle->value();
break;
case Torus:
m = Primitive::torus(ui->spinSegments->value(),
ui->spinSegments2->value(),
ui->spinRadius->value(),
ui->spinRadius2->value(),
ui->spinAngle->value());
params << ui->spinSegments->value()
<< ui->spinSegments2->value()
<< ui->spinRadius->value()
<< ui->spinRadius2->value()
<< ui->spinAngle->value();
break;
default: return 0;
}
params << ui->flipNormals->isChecked();
params << ui->colorButton->color();
if (ui->flipNormals->isChecked())
m->flipNormals();
return m;
}
void PrimitiveEditor::showEditors() {
foreach (QWidget * w, all_editors) w->hide();
PrimitiveType pt = (PrimitiveType)ui->comboPrimitives->currentIndex();
QList<QWidget *> wds = editors[pt];
foreach (QWidget * w, wds) w->show();
}
void PrimitiveEditor::selectionChanged() {
ObjectBase * so = view->selectedObject();\
can_replace = false;
if (so) {
QVariantList vl = so->property("primitive", &can_replace).toList();
if (can_replace && !vl.isEmpty()) {
PrimitiveType pt = (PrimitiveType)vl.takeFirst().toInt();
ui->comboPrimitives->setCurrentIndex(pt);
switch (pt) {
case Plane:
ui->spinWidth->setValue(vl.takeFirst().toDouble());
ui->spinLength->setValue(vl.takeFirst().toDouble());
break;
case Cube:
ui->spinWidth->setValue(vl.takeFirst().toDouble());
ui->spinLength->setValue(vl.takeFirst().toDouble());
ui->spinHeight->setValue(vl.takeFirst().toDouble());
break;
case Ellipsoid:
ui->spinSegments->setValue(vl.takeFirst().toDouble());
ui->spinSegments2->setValue(vl.takeFirst().toDouble());
ui->spinRadius->setValue(vl.takeFirst().toDouble());
ui->spinAngle->setValue(vl.takeFirst().toDouble());
break;
case Disc:
ui->spinSegments->setValue(vl.takeFirst().toDouble());
ui->spinRadius->setValue(vl.takeFirst().toDouble());
ui->spinAngle->setValue(vl.takeFirst().toDouble());
break;
case Cone:
ui->spinSegments->setValue(vl.takeFirst().toDouble());
ui->spinRadius->setValue(vl.takeFirst().toDouble());
ui->spinHeight->setValue(vl.takeFirst().toDouble());
break;
case Cylinder:
ui->spinSegments->setValue(vl.takeFirst().toDouble());
ui->spinRadius->setValue(vl.takeFirst().toDouble());
ui->spinHeight->setValue(vl.takeFirst().toDouble());
ui->spinAngle->setValue(vl.takeFirst().toDouble());
break;
case Torus:
ui->spinSegments->setValue(vl.takeFirst().toDouble());
ui->spinSegments2->setValue(vl.takeFirst().toDouble());
ui->spinRadius->setValue(vl.takeFirst().toDouble());
ui->spinRadius2->setValue(vl.takeFirst().toDouble());
ui->spinAngle->setValue(vl.takeFirst().toDouble());
break;
}
ui->flipNormals->setChecked(vl.takeFirst().toBool());
ui->colorButton->setColor(vl.takeFirst().value<QColor>());
}
}
}
void PrimitiveEditor::replaceMesh() {
if (!view) return;
if (!can_replace) return;
ObjectBase * so = view->selectedObject();
if (!so) return;
QVariantList params;
Mesh * m = createMesh(params);
if (!m) return;
so->setMesh(m);
so->setColor(ui->colorButton->color());
so->setName(ui->comboPrimitives->currentText());
so->setProperty("primitive", params);
delete m;
}
void PrimitiveEditor::on_buttonAdd_clicked() {
if (!view) return;
QVariantList params;
Mesh * m = createMesh(params);
if (!m) return;
ObjectBase * o = new ObjectBase(m);
o->setColor(ui->colorButton->color());
o->setName(ui->comboPrimitives->currentText());
o->setProperty("primitive", params);
view->scene()->addObject(o);
view->scene()->selectObject(o);
delete m;
}
void PrimitiveEditor::on_comboPrimitives_currentIndexChanged(int index) {
showEditors();
}
/*
QGL PrimitiveEditor
Ivan Pelipenko peri4ko@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/>.
*/
#include "primitiveeditor.h"
#include "ui_primitiveeditor.h"
#include <QMetaEnum>
#include "glprimitives.h"
#include "glmesh.h"
PrimitiveEditor::PrimitiveEditor(QWidget *parent) : QWidget(parent), ui(new Ui::PrimitiveEditor) {
view = 0;
can_replace = false;
ui->setupUi(this);
#if QT_VERSION >= QT_VERSION_CHECK(5,12,0)
ui->spinSegments->setStepType(QAbstractSpinBox::AdaptiveDecimalStepType);
ui->spinSegments2->setStepType(QAbstractSpinBox::AdaptiveDecimalStepType);
#endif
editors[Plane] << ui->widgetWidth;
editors[Plane] << ui->widgetLength;
editors[Cube] << ui->widgetWidth;
editors[Cube] << ui->widgetLength;
editors[Cube] << ui->widgetHeight;
editors[Ellipsoid] << ui->widgetRadius1;
editors[Ellipsoid] << ui->widgetSegments;
editors[Ellipsoid] << ui->widgetSegments2;
editors[Ellipsoid] << ui->widgetAngle;
editors[Disc] << ui->widgetRadius1;
editors[Disc] << ui->widgetSegments;
editors[Disc] << ui->widgetAngle;
editors[Cone] << ui->widgetRadius1;
editors[Cone] << ui->widgetHeight;
editors[Cone] << ui->widgetSegments;
editors[Cylinder] << ui->widgetRadius1;
editors[Cylinder] << ui->widgetHeight;
editors[Cylinder] << ui->widgetSegments;
editors[Cylinder] << ui->widgetAngle;
editors[Torus] << ui->widgetRadius1;
editors[Torus] << ui->widgetRadius2;
editors[Torus] << ui->widgetSegments;
editors[Torus] << ui->widgetSegments2;
editors[Torus] << ui->widgetAngle;
QSet<QWidget *> all;
QMetaEnum me = metaObject()->enumerator(0);
for (int i=0; i<me.keyCount(); ++i) {
ui->comboPrimitives->addItem(me.key(i));
all.unite(editors[(PrimitiveType)me.value(i)].toSet());
}
all_editors = all.toList();
foreach (QWidget * w, all_editors) {
if (w->layout()) w->layout()->setContentsMargins(0, layout()->spacing(), 0, 0);
}
ui->comboPrimitives->setCurrentIndex(Plane);
on_comboPrimitives_currentIndexChanged(ui->comboPrimitives->currentIndex());
}
PrimitiveEditor::~PrimitiveEditor() {
delete ui;
}
void PrimitiveEditor::assignQGLView(QGLView * v) {
view = v;
connect(view, SIGNAL(selectionChanged()), this, SLOT(selectionChanged()));
selectionChanged();
}
Mesh * PrimitiveEditor::createMesh(QVariantList & params) {
Mesh * m = 0;
PrimitiveType pt = (PrimitiveType)ui->comboPrimitives->currentIndex();
params << pt;
switch (pt) {
case Plane:
m = Primitive::plane(ui->spinWidth->value(),
ui->spinLength->value());
params << ui->spinWidth->value()
<< ui->spinLength->value();
break;
case Cube:
m = Primitive::cube(ui->spinWidth->value(),
ui->spinLength->value(),
ui->spinHeight->value());
params << ui->spinWidth->value()
<< ui->spinLength->value()
<< ui->spinHeight->value();
break;
case Ellipsoid:
m = Primitive::ellipsoid(ui->spinSegments->value(),
ui->spinSegments2->value(),
ui->spinRadius->value(),
ui->spinAngle->value());
params << ui->spinSegments->value()
<< ui->spinSegments2->value()
<< ui->spinRadius->value()
<< ui->spinAngle->value();
break;
case Disc:
m = Primitive::disc(ui->spinSegments->value(),
ui->spinRadius->value(),
ui->spinAngle->value());
params << ui->spinSegments->value()
<< ui->spinRadius->value()
<< ui->spinAngle->value();
break;
case Cone:
m = Primitive::cone(ui->spinSegments->value(),
ui->spinRadius->value(),
ui->spinHeight->value());
params << ui->spinSegments->value()
<< ui->spinRadius->value()
<< ui->spinHeight->value();
break;
case Cylinder:
m = Primitive::cylinder(ui->spinSegments->value(),
ui->spinRadius->value(),
ui->spinHeight->value(),
ui->spinAngle->value());
params << ui->spinSegments->value()
<< ui->spinRadius->value()
<< ui->spinHeight->value()
<< ui->spinAngle->value();
break;
case Torus:
m = Primitive::torus(ui->spinSegments->value(),
ui->spinSegments2->value(),
ui->spinRadius->value(),
ui->spinRadius2->value(),
ui->spinAngle->value());
params << ui->spinSegments->value()
<< ui->spinSegments2->value()
<< ui->spinRadius->value()
<< ui->spinRadius2->value()
<< ui->spinAngle->value();
break;
default: return 0;
}
params << ui->flipNormals->isChecked();
params << ui->colorButton->color();
if (ui->flipNormals->isChecked())
m->flipNormals();
return m;
}
void PrimitiveEditor::showEditors() {
foreach (QWidget * w, all_editors) w->hide();
PrimitiveType pt = (PrimitiveType)ui->comboPrimitives->currentIndex();
QList<QWidget *> wds = editors[pt];
foreach (QWidget * w, wds) w->show();
}
void PrimitiveEditor::selectionChanged() {
ObjectBase * so = view->selectedObject();\
can_replace = false;
if (so) {
QVariantList vl = so->property("primitive", &can_replace).toList();
if (can_replace && !vl.isEmpty()) {
PrimitiveType pt = (PrimitiveType)vl.takeFirst().toInt();
ui->comboPrimitives->setCurrentIndex(pt);
switch (pt) {
case Plane:
ui->spinWidth->setValue(vl.takeFirst().toDouble());
ui->spinLength->setValue(vl.takeFirst().toDouble());
break;
case Cube:
ui->spinWidth->setValue(vl.takeFirst().toDouble());
ui->spinLength->setValue(vl.takeFirst().toDouble());
ui->spinHeight->setValue(vl.takeFirst().toDouble());
break;
case Ellipsoid:
ui->spinSegments->setValue(vl.takeFirst().toDouble());
ui->spinSegments2->setValue(vl.takeFirst().toDouble());
ui->spinRadius->setValue(vl.takeFirst().toDouble());
ui->spinAngle->setValue(vl.takeFirst().toDouble());
break;
case Disc:
ui->spinSegments->setValue(vl.takeFirst().toDouble());
ui->spinRadius->setValue(vl.takeFirst().toDouble());
ui->spinAngle->setValue(vl.takeFirst().toDouble());
break;
case Cone:
ui->spinSegments->setValue(vl.takeFirst().toDouble());
ui->spinRadius->setValue(vl.takeFirst().toDouble());
ui->spinHeight->setValue(vl.takeFirst().toDouble());
break;
case Cylinder:
ui->spinSegments->setValue(vl.takeFirst().toDouble());
ui->spinRadius->setValue(vl.takeFirst().toDouble());
ui->spinHeight->setValue(vl.takeFirst().toDouble());
ui->spinAngle->setValue(vl.takeFirst().toDouble());
break;
case Torus:
ui->spinSegments->setValue(vl.takeFirst().toDouble());
ui->spinSegments2->setValue(vl.takeFirst().toDouble());
ui->spinRadius->setValue(vl.takeFirst().toDouble());
ui->spinRadius2->setValue(vl.takeFirst().toDouble());
ui->spinAngle->setValue(vl.takeFirst().toDouble());
break;
}
ui->flipNormals->setChecked(vl.takeFirst().toBool());
ui->colorButton->setColor(vl.takeFirst().value<QColor>());
}
}
}
void PrimitiveEditor::replaceMesh() {
if (!view) return;
if (!can_replace) return;
ObjectBase * so = view->selectedObject();
if (!so) return;
QVariantList params;
Mesh * m = createMesh(params);
if (!m) return;
so->setMesh(m);
so->setColor(ui->colorButton->color());
so->setName(ui->comboPrimitives->currentText());
so->setProperty("primitive", params);
delete m;
}
void PrimitiveEditor::on_buttonAdd_clicked() {
if (!view) return;
QVariantList params;
Mesh * m = createMesh(params);
if (!m) return;
ObjectBase * o = new ObjectBase(m);
o->setColor(ui->colorButton->color());
o->setName(ui->comboPrimitives->currentText());
o->setProperty("primitive", params);
view->scene()->addObject(o);
view->scene()->selectObject(o);
delete m;
}
void PrimitiveEditor::on_comboPrimitives_currentIndexChanged(int index) {
showEditors();
}

View File

@@ -1,68 +1,68 @@
/*
QGL PrimitiveEditor
Ivan Pelipenko peri4ko@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 PRIMITIVEEDITOR_H
#define PRIMITIVEEDITOR_H
#include <QWidget>
#include "qglview.h"
namespace Ui {
class PrimitiveEditor;
}
class PrimitiveEditor : public QWidget {
Q_OBJECT
public:
enum PrimitiveType {
Plane,
Cube,
Ellipsoid,
Disc,
Cone,
Cylinder,
Torus
};
Q_ENUMS(PrimitiveType)
explicit PrimitiveEditor(QWidget *parent = nullptr);
~PrimitiveEditor();
void assignQGLView(QGLView * v);
protected:
Mesh * createMesh(QVariantList & params);
void showEditors();
Ui::PrimitiveEditor *ui;
QGLView * view;
QMap<PrimitiveType, QList<QWidget *> > editors;
QList<QWidget *> all_editors;
bool can_replace;
private slots:
void selectionChanged();
void replaceMesh();
void on_buttonAdd_clicked();
void on_comboPrimitives_currentIndexChanged(int index);
};
#endif // PRIMITIVEEDITOR_H
/*
QGL PrimitiveEditor
Ivan Pelipenko peri4ko@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 PRIMITIVEEDITOR_H
#define PRIMITIVEEDITOR_H
#include <QWidget>
#include "qglview.h"
namespace Ui {
class PrimitiveEditor;
}
class PrimitiveEditor : public QWidget {
Q_OBJECT
public:
enum PrimitiveType {
Plane,
Cube,
Ellipsoid,
Disc,
Cone,
Cylinder,
Torus
};
Q_ENUMS(PrimitiveType)
explicit PrimitiveEditor(QWidget *parent = nullptr);
~PrimitiveEditor();
void assignQGLView(QGLView * v);
protected:
Mesh * createMesh(QVariantList & params);
void showEditors();
Ui::PrimitiveEditor *ui;
QGLView * view;
QMap<PrimitiveType, QList<QWidget *> > editors;
QList<QWidget *> all_editors;
bool can_replace;
private slots:
void selectionChanged();
void replaceMesh();
void on_buttonAdd_clicked();
void on_comboPrimitives_currentIndexChanged(int index);
};
#endif // PRIMITIVEEDITOR_H

View File

@@ -1,597 +1,597 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PrimitiveEditor</class>
<widget class="QWidget" name="PrimitiveEditor">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>360</width>
<height>536</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<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="EComboBox" name="comboPrimitives"/>
</item>
<item>
<widget class="QWidget" name="widgetRows" native="true">
<layout class="QVBoxLayout" name="verticalLayout">
<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="QWidget" name="widgetWidth" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="leftMargin">
<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>Width:</string>
</property>
</widget>
</item>
<item>
<widget class="ScrollSpinBox" name="spinWidth">
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="widgetLength" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Length:</string>
</property>
</widget>
</item>
<item>
<widget class="ScrollSpinBox" name="spinLength">
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="widgetHeight" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="leftMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Height</string>
</property>
</widget>
</item>
<item>
<widget class="ScrollSpinBox" name="spinHeight">
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="widgetRadius1" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<property name="leftMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_6">
<property name="text">
<string>Radius 1:</string>
</property>
</widget>
</item>
<item>
<widget class="ScrollSpinBox" name="spinRadius">
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="widgetRadius2" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_6">
<property name="leftMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_7">
<property name="text">
<string>Radius 2:</string>
</property>
</widget>
</item>
<item>
<widget class="ScrollSpinBox" name="spinRadius2">
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="widgetAngle" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_7">
<property name="leftMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_8">
<property name="text">
<string>Angle:</string>
</property>
</widget>
</item>
<item>
<widget class="SpinSlider" name="spinAngle">
<property name="maximum">
<double>360.000000000000000</double>
</property>
<property name="value">
<double>360.000000000000000</double>
</property>
<property name="singleStep">
<double>4.500000000000000</double>
</property>
<property name="pageStep">
<double>90.000000000000000</double>
</property>
<property name="suffix">
<string>°</string>
</property>
<property name="tickPosition">
<enum>QSlider::TicksAbove</enum>
</property>
<property name="tickInterval">
<number>90</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="widgetSegments" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_8">
<property name="leftMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>Segments:</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinSegments">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>1000</number>
</property>
<property name="singleStep">
<number>1</number>
</property>
<property name="value">
<number>16</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="widgetSegments2" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_9">
<property name="leftMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_9">
<property name="text">
<string>Segments 2:</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinSegments2">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>1000</number>
</property>
<property name="singleStep">
<number>1</number>
</property>
<property name="value">
<number>16</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="widgetColor" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_10">
<property name="leftMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_10">
<property name="text">
<string>Color:</string>
</property>
</widget>
</item>
<item>
<widget class="ColorButton" name="colorButton">
<property name="color">
<color>
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QCheckBox" name="flipNormals">
<property name="text">
<string>Flip normals</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>176</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="buttonAdd">
<property name="text">
<string>Add</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>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>SpinSlider</class>
<extends>QWidget</extends>
<header>spinslider.h</header>
</customwidget>
<customwidget>
<class>ColorButton</class>
<extends>QPushButton</extends>
<header>colorbutton.h</header>
</customwidget>
<customwidget>
<class>EComboBox</class>
<extends>QComboBox</extends>
<header>ecombobox.h</header>
</customwidget>
<customwidget>
<class>ScrollSpinBox</class>
<extends>QWidget</extends>
<header>scroll_spin_box.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="../../qad/utils/qad_utils.qrc"/>
</resources>
<connections>
<connection>
<sender>spinWidth</sender>
<signal>valueChanged(double)</signal>
<receiver>PrimitiveEditor</receiver>
<slot>replaceMesh()</slot>
<hints>
<hint type="sourcelabel">
<x>331</x>
<y>51</y>
</hint>
<hint type="destinationlabel">
<x>368</x>
<y>45</y>
</hint>
</hints>
</connection>
<connection>
<sender>spinLength</sender>
<signal>valueChanged(double)</signal>
<receiver>PrimitiveEditor</receiver>
<slot>replaceMesh()</slot>
<hints>
<hint type="sourcelabel">
<x>330</x>
<y>84</y>
</hint>
<hint type="destinationlabel">
<x>369</x>
<y>82</y>
</hint>
</hints>
</connection>
<connection>
<sender>spinHeight</sender>
<signal>valueChanged(double)</signal>
<receiver>PrimitiveEditor</receiver>
<slot>replaceMesh()</slot>
<hints>
<hint type="sourcelabel">
<x>334</x>
<y>116</y>
</hint>
<hint type="destinationlabel">
<x>366</x>
<y>114</y>
</hint>
</hints>
</connection>
<connection>
<sender>spinRadius</sender>
<signal>valueChanged(double)</signal>
<receiver>PrimitiveEditor</receiver>
<slot>replaceMesh()</slot>
<hints>
<hint type="sourcelabel">
<x>332</x>
<y>144</y>
</hint>
<hint type="destinationlabel">
<x>370</x>
<y>145</y>
</hint>
</hints>
</connection>
<connection>
<sender>spinRadius2</sender>
<signal>valueChanged(double)</signal>
<receiver>PrimitiveEditor</receiver>
<slot>replaceMesh()</slot>
<hints>
<hint type="sourcelabel">
<x>334</x>
<y>186</y>
</hint>
<hint type="destinationlabel">
<x>371</x>
<y>181</y>
</hint>
</hints>
</connection>
<connection>
<sender>spinAngle</sender>
<signal>valueChanged(double)</signal>
<receiver>PrimitiveEditor</receiver>
<slot>replaceMesh()</slot>
<hints>
<hint type="sourcelabel">
<x>335</x>
<y>210</y>
</hint>
<hint type="destinationlabel">
<x>372</x>
<y>213</y>
</hint>
</hints>
</connection>
<connection>
<sender>spinSegments</sender>
<signal>valueChanged(int)</signal>
<receiver>PrimitiveEditor</receiver>
<slot>replaceMesh()</slot>
<hints>
<hint type="sourcelabel">
<x>329</x>
<y>246</y>
</hint>
<hint type="destinationlabel">
<x>370</x>
<y>247</y>
</hint>
</hints>
</connection>
<connection>
<sender>spinSegments2</sender>
<signal>valueChanged(int)</signal>
<receiver>PrimitiveEditor</receiver>
<slot>replaceMesh()</slot>
<hints>
<hint type="sourcelabel">
<x>336</x>
<y>284</y>
</hint>
<hint type="destinationlabel">
<x>372</x>
<y>279</y>
</hint>
</hints>
</connection>
<connection>
<sender>flipNormals</sender>
<signal>toggled(bool)</signal>
<receiver>PrimitiveEditor</receiver>
<slot>replaceMesh()</slot>
<hints>
<hint type="sourcelabel">
<x>70</x>
<y>344</y>
</hint>
<hint type="destinationlabel">
<x>370</x>
<y>341</y>
</hint>
</hints>
</connection>
<connection>
<sender>comboPrimitives</sender>
<signal>currentIndexChanged(int)</signal>
<receiver>PrimitiveEditor</receiver>
<slot>replaceMesh()</slot>
<hints>
<hint type="sourcelabel">
<x>348</x>
<y>9</y>
</hint>
<hint type="destinationlabel">
<x>367</x>
<y>9</y>
</hint>
</hints>
</connection>
<connection>
<sender>colorButton</sender>
<signal>colorChanged(QColor)</signal>
<receiver>PrimitiveEditor</receiver>
<slot>replaceMesh()</slot>
<hints>
<hint type="sourcelabel">
<x>271</x>
<y>285</y>
</hint>
<hint type="destinationlabel">
<x>179</x>
<y>267</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>replaceMesh()</slot>
</slots>
</ui>
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PrimitiveEditor</class>
<widget class="QWidget" name="PrimitiveEditor">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>360</width>
<height>536</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<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="EComboBox" name="comboPrimitives"/>
</item>
<item>
<widget class="QWidget" name="widgetRows" native="true">
<layout class="QVBoxLayout" name="verticalLayout">
<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="QWidget" name="widgetWidth" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="leftMargin">
<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>Width:</string>
</property>
</widget>
</item>
<item>
<widget class="ScrollSpinBox" name="spinWidth">
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="widgetLength" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Length:</string>
</property>
</widget>
</item>
<item>
<widget class="ScrollSpinBox" name="spinLength">
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="widgetHeight" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="leftMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Height</string>
</property>
</widget>
</item>
<item>
<widget class="ScrollSpinBox" name="spinHeight">
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="widgetRadius1" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<property name="leftMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_6">
<property name="text">
<string>Radius 1:</string>
</property>
</widget>
</item>
<item>
<widget class="ScrollSpinBox" name="spinRadius">
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="widgetRadius2" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_6">
<property name="leftMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_7">
<property name="text">
<string>Radius 2:</string>
</property>
</widget>
</item>
<item>
<widget class="ScrollSpinBox" name="spinRadius2">
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="widgetAngle" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_7">
<property name="leftMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_8">
<property name="text">
<string>Angle:</string>
</property>
</widget>
</item>
<item>
<widget class="SpinSlider" name="spinAngle">
<property name="maximum">
<double>360.000000000000000</double>
</property>
<property name="value">
<double>360.000000000000000</double>
</property>
<property name="singleStep">
<double>4.500000000000000</double>
</property>
<property name="pageStep">
<double>90.000000000000000</double>
</property>
<property name="suffix">
<string>°</string>
</property>
<property name="tickPosition">
<enum>QSlider::TicksAbove</enum>
</property>
<property name="tickInterval">
<number>90</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="widgetSegments" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_8">
<property name="leftMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>Segments:</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinSegments">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>1000</number>
</property>
<property name="singleStep">
<number>1</number>
</property>
<property name="value">
<number>16</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="widgetSegments2" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_9">
<property name="leftMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_9">
<property name="text">
<string>Segments 2:</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinSegments2">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>1000</number>
</property>
<property name="singleStep">
<number>1</number>
</property>
<property name="value">
<number>16</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="widgetColor" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_10">
<property name="leftMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_10">
<property name="text">
<string>Color:</string>
</property>
</widget>
</item>
<item>
<widget class="ColorButton" name="colorButton">
<property name="color">
<color>
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QCheckBox" name="flipNormals">
<property name="text">
<string>Flip normals</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>176</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="buttonAdd">
<property name="text">
<string>Add</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>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>SpinSlider</class>
<extends>QWidget</extends>
<header>spinslider.h</header>
</customwidget>
<customwidget>
<class>ColorButton</class>
<extends>QPushButton</extends>
<header>colorbutton.h</header>
</customwidget>
<customwidget>
<class>EComboBox</class>
<extends>QComboBox</extends>
<header>ecombobox.h</header>
</customwidget>
<customwidget>
<class>ScrollSpinBox</class>
<extends>QWidget</extends>
<header>scroll_spin_box.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="../../qad/utils/qad_utils.qrc"/>
</resources>
<connections>
<connection>
<sender>spinWidth</sender>
<signal>valueChanged(double)</signal>
<receiver>PrimitiveEditor</receiver>
<slot>replaceMesh()</slot>
<hints>
<hint type="sourcelabel">
<x>331</x>
<y>51</y>
</hint>
<hint type="destinationlabel">
<x>368</x>
<y>45</y>
</hint>
</hints>
</connection>
<connection>
<sender>spinLength</sender>
<signal>valueChanged(double)</signal>
<receiver>PrimitiveEditor</receiver>
<slot>replaceMesh()</slot>
<hints>
<hint type="sourcelabel">
<x>330</x>
<y>84</y>
</hint>
<hint type="destinationlabel">
<x>369</x>
<y>82</y>
</hint>
</hints>
</connection>
<connection>
<sender>spinHeight</sender>
<signal>valueChanged(double)</signal>
<receiver>PrimitiveEditor</receiver>
<slot>replaceMesh()</slot>
<hints>
<hint type="sourcelabel">
<x>334</x>
<y>116</y>
</hint>
<hint type="destinationlabel">
<x>366</x>
<y>114</y>
</hint>
</hints>
</connection>
<connection>
<sender>spinRadius</sender>
<signal>valueChanged(double)</signal>
<receiver>PrimitiveEditor</receiver>
<slot>replaceMesh()</slot>
<hints>
<hint type="sourcelabel">
<x>332</x>
<y>144</y>
</hint>
<hint type="destinationlabel">
<x>370</x>
<y>145</y>
</hint>
</hints>
</connection>
<connection>
<sender>spinRadius2</sender>
<signal>valueChanged(double)</signal>
<receiver>PrimitiveEditor</receiver>
<slot>replaceMesh()</slot>
<hints>
<hint type="sourcelabel">
<x>334</x>
<y>186</y>
</hint>
<hint type="destinationlabel">
<x>371</x>
<y>181</y>
</hint>
</hints>
</connection>
<connection>
<sender>spinAngle</sender>
<signal>valueChanged(double)</signal>
<receiver>PrimitiveEditor</receiver>
<slot>replaceMesh()</slot>
<hints>
<hint type="sourcelabel">
<x>335</x>
<y>210</y>
</hint>
<hint type="destinationlabel">
<x>372</x>
<y>213</y>
</hint>
</hints>
</connection>
<connection>
<sender>spinSegments</sender>
<signal>valueChanged(int)</signal>
<receiver>PrimitiveEditor</receiver>
<slot>replaceMesh()</slot>
<hints>
<hint type="sourcelabel">
<x>329</x>
<y>246</y>
</hint>
<hint type="destinationlabel">
<x>370</x>
<y>247</y>
</hint>
</hints>
</connection>
<connection>
<sender>spinSegments2</sender>
<signal>valueChanged(int)</signal>
<receiver>PrimitiveEditor</receiver>
<slot>replaceMesh()</slot>
<hints>
<hint type="sourcelabel">
<x>336</x>
<y>284</y>
</hint>
<hint type="destinationlabel">
<x>372</x>
<y>279</y>
</hint>
</hints>
</connection>
<connection>
<sender>flipNormals</sender>
<signal>toggled(bool)</signal>
<receiver>PrimitiveEditor</receiver>
<slot>replaceMesh()</slot>
<hints>
<hint type="sourcelabel">
<x>70</x>
<y>344</y>
</hint>
<hint type="destinationlabel">
<x>370</x>
<y>341</y>
</hint>
</hints>
</connection>
<connection>
<sender>comboPrimitives</sender>
<signal>currentIndexChanged(int)</signal>
<receiver>PrimitiveEditor</receiver>
<slot>replaceMesh()</slot>
<hints>
<hint type="sourcelabel">
<x>348</x>
<y>9</y>
</hint>
<hint type="destinationlabel">
<x>367</x>
<y>9</y>
</hint>
</hints>
</connection>
<connection>
<sender>colorButton</sender>
<signal>colorChanged(QColor)</signal>
<receiver>PrimitiveEditor</receiver>
<slot>replaceMesh()</slot>
<hints>
<hint type="sourcelabel">
<x>271</x>
<y>285</y>
</hint>
<hint type="destinationlabel">
<x>179</x>
<y>267</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>replaceMesh()</slot>
</slots>
</ui>

View File

@@ -1,70 +1,8 @@
cmake_minimum_required(VERSION 3.0)
project(qglview)
if (IBPROJECT)
include(SDKMacros)
else()
option(LIB "System install" 0)
option(DEBUG "Build with -g3" 0)
option(DESIGNER_PLUGINS "Build qt designer plugins" 1)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -Wall")
if (DEBUG)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3")
endif()
endif()
if (MINGW)
find_package(MinGW REQUIRED)
endif()
find_package(QAD REQUIRED)
find_package(OpenGL REQUIRED)
include_directories(${QAD_INCLUDES})
find_qt(Qt5 Core Gui OpenGL Xml)
if (NOT Qt5)
message(WARNING "Building ${PROJECT_NAME} available only on Qt5!")
else()
qt_sources(SRC)
qt_wrap(${SRC} HDRS out_HDR CPPS out_CPP QMS out_QM)
qt_add_library(${PROJECT_NAME} SHARED out_CPP)
qt_target_link_libraries(${PROJECT_NAME} qad_utils qad_widgets ${OPENGL_LIBRARIES})
qt_target_include_directories(${PROJECT_NAME} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}")
message(STATUS "Building ${PROJECT_NAME}")
if (LIBPROJECT)
sdk_install("qad" FALSE "${PROJECT_NAME}" "${out_HDR}" "${out_QM}")
else()
if (LIB)
if (WIN32)
qt_install(FILES ${H} DESTINATION ${MINGW_INCLUDE}/qad)
qt_install(TARGETS ${PROJECT_NAME} ARCHIVE DESTINATION ${MINGW_LIB})
qt_install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION ${MINGW_BIN})
qt_install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION QtBin)
else()
qt_install(FILES ${H} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/qad)
qt_install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib)
endif()
message(STATUS "Install ${PROJECT_NAME} to system \"${CMAKE_INSTALL_PREFIX}\"")
else()
if(WIN32)
qt_install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin)
qt_install(TARGETS ${PROJECT_NAME} ARCHIVE DESTINATION lib)
else()
qt_install(TARGETS ${PROJECT_NAME} DESTINATION lib)
endif()
qt_install(FILES ${H} DESTINATION include/qad)
message(STATUS "Install ${PROJECT_NAME} to local \"bin\", \"lib\" and \"include\"")
endif()
endif()
foreach(_v ${_QT_VERSIONS_})
set(MULTILIB_qglview_SUFFIX_Qt${_v} ${_v})
set(MULTILIB_qglview_SUFFIX_Qt${_v} ${_v} PARENT_SCOPE)
endforeach()
list(APPEND QT_MULTILIB_LIST qglview)
if (NOT DEFINED ANDROID_PLATFORM)
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/plugin")
add_subdirectory(plugin)
endif()
endif()
qt_sources(test_SRC DIR "qglview_test")
qt_wrap(${test_SRC} CPPS test_CPP)
qt_add_executable(qglview_test test_CPP)
qt_target_link_libraries(qglview_test ${PROJECT_NAME})
endif()
find_package(OpenGL REQUIRED)
_qt_project(qglview FALSE "QAD" "Gui;OpenGL;Xml" "qad_widgets;qad_utils;${OPENGL_LIBRARIES}")
_qt_install(qglview FALSE "qad" "out_HDR" "out_QM")
qt_sources(test_SRC DIR "qglview_test")
qt_wrap(${test_SRC} CPPS test_CPP)
qt_add_executable(qglview_test test_CPP)
qt_target_link_libraries(qglview_test qglview)

View File

@@ -1,236 +1,236 @@
#include "glwidget.h"
#include "renderer_simple.h"
#include "renderer_deferred_shading.h"
#include <QVBoxLayout>
GLWidget::GLWidget(QWidget *parent) : QWidget(parent) {
view_ = new QGLView();
view_->setFlags(windowFlags() | Qt::FramelessWindowHint);
container = QWidget::createWindowContainer(view_, this);
lay = new QVBoxLayout(this);
lay->addWidget(container);
lay->setContentsMargins(0, 0, 0, 0);
lay->setSpacing(0);
setMouseTracking(true);
setWindowIcon(QIcon("://icons/qglview.png"));
connect(view_, &QGLView::doubleClick, this, &GLWidget::viewDoubleClicked);
}
QColor GLWidget::backColor() const {
return view_->backColor();
}
qreal GLWidget::lineWidth() const {
return view_->lineWidth();
}
qreal GLWidget::FOV() const {
return view_->FOV();
}
qreal GLWidget::depthStart() const {
return view_->depthStart();
}
qreal GLWidget::depthEnd() const {
return view_->depthEnd();
}
QColor GLWidget::ambientColor() const {
return view_->ambientColor();
}
bool GLWidget::isLightEnabled() const {
return view_->isLightEnabled();
}
bool GLWidget::isGrabMouseEnabled() const {
return view_->isGrabMouseEnabled();
}
bool GLWidget::isMouseRotateEnabled() const {
return view_->isMouseRotateEnabled();
}
bool GLWidget::isMouseSelectionEnabled() const {
return view_->isMouseSelectionEnabled();
}
bool GLWidget::isCameraOrbit() const
{
return view_->isCameraOrbit();
}
bool GLWidget::isHoverHaloEnabled() const {
return view_->isHoverHaloEnabled();
}
QColor GLWidget::hoverHaloColor() const {
return view_->hoverHaloColor();
}
qreal GLWidget::hoverHaloFillAlpha() const {
return view_->hoverHaloFillAlpha();
}
bool GLWidget::isSelectionHaloEnabled() const {
return view_->isSelectionHaloEnabled();
}
QColor GLWidget::selectionHaloColor() const {
return view_->selectionHaloColor();
}
qreal GLWidget::selectionHaloFillAlpha() const {
return view_->selectionHaloFillAlpha();
}
void GLWidget::addObject(GLObjectBase * o) {
view_->addObject(o);
}
QByteArray GLWidget::saveCamera() {
return view_->saveCamera();
}
void GLWidget::restoreCamera(const QByteArray &ba) {
view_->restoreCamera(ba);
}
void GLWidget::stop() {
view_->stop();
}
void GLWidget::start(float freq, GLRendererBase * r) {
if (r == nullptr) r = new RendererSimple(view_);
GLRendererBase * pr = nullptr;
view_->setRenderer(r, &pr);
if (pr != nullptr && pr != r) delete pr;
view_->start(freq);
}
void GLWidget::setBackColor(const QColor & c) {
view_->setBackColor(c);
}
void GLWidget::setLineWidth(const qreal & arg) {
view_->setLineWidth(arg);
}
void GLWidget::setFOV(const qreal & arg) {
view_->setFOV(arg);
}
void GLWidget::setDepthStart(const qreal & arg) {
view_->setDepthStart(arg);
}
void GLWidget::setDepthEnd(const qreal & arg) {
view_->setDepthEnd(arg);
}
void GLWidget::setAmbientColor(const QColor & arg) {
view_->setAmbientColor(arg);
}
void GLWidget::setLightEnabled(const bool & arg) {
view_->setLightEnabled(arg);
}
void GLWidget::setGrabMouseEnabled(const bool & arg) {
view_->setGrabMouseEnabled(arg);
}
void GLWidget::setMouseRotateEnabled(const bool & arg) {
view_->setMouseRotateEnabled(arg);
}
void GLWidget::setMouseSelectionEnabled(const bool & arg) {
view_->setMouseSelectionEnabled(arg);
}
void GLWidget::setCameraOrbit(const bool & arg) {
view_->setCameraOrbit(arg);
}
void GLWidget::setHoverHaloEnabled(const bool & arg) {
view_->setHoverHaloEnabled(arg);
}
void GLWidget::setHoverHaloColor(const QColor & arg) {
view_->setHoverHaloColor(arg);
}
void GLWidget::setHoverHaloFillAlpha(const qreal & arg) {
view_->setHoverHaloFillAlpha(arg);
}
void GLWidget::setSelectionHaloEnabled(const bool & arg) {
view_->setSelectionHaloEnabled(arg);
}
void GLWidget::setSelectionHaloColor(const QColor & arg) {
view_->setSelectionHaloColor(arg);
}
void GLWidget::setSelectionHaloFillAlpha(const qreal & arg) {
view_->setSelectionHaloFillAlpha(arg);
}
void GLWidget::viewDoubleClicked() {
// qDebug() << "click widget!!";
if (view_->windowState() == Qt::WindowFullScreen) {
// view_->hide();
container = QWidget::createWindowContainer(view_, this);
lay->addWidget(container);
container->show();
// show();
} else {
// hide();
view_->setParent(nullptr);
view_->showFullScreen();
lay->removeWidget(container);
}
// qDebug() << "click widge done!";
}
#include "glwidget.h"
#include "renderer_simple.h"
#include "renderer_deferred_shading.h"
#include <QVBoxLayout>
GLWidget::GLWidget(QWidget *parent) : QWidget(parent) {
view_ = new QGLView();
view_->setFlags(windowFlags() | Qt::FramelessWindowHint);
container = QWidget::createWindowContainer(view_, this);
lay = new QVBoxLayout(this);
lay->addWidget(container);
lay->setContentsMargins(0, 0, 0, 0);
lay->setSpacing(0);
setMouseTracking(true);
setWindowIcon(QIcon("://icons/qglview.png"));
connect(view_, &QGLView::doubleClick, this, &GLWidget::viewDoubleClicked);
}
QColor GLWidget::backColor() const {
return view_->backColor();
}
qreal GLWidget::lineWidth() const {
return view_->lineWidth();
}
qreal GLWidget::FOV() const {
return view_->FOV();
}
qreal GLWidget::depthStart() const {
return view_->depthStart();
}
qreal GLWidget::depthEnd() const {
return view_->depthEnd();
}
QColor GLWidget::ambientColor() const {
return view_->ambientColor();
}
bool GLWidget::isLightEnabled() const {
return view_->isLightEnabled();
}
bool GLWidget::isGrabMouseEnabled() const {
return view_->isGrabMouseEnabled();
}
bool GLWidget::isMouseRotateEnabled() const {
return view_->isMouseRotateEnabled();
}
bool GLWidget::isMouseSelectionEnabled() const {
return view_->isMouseSelectionEnabled();
}
bool GLWidget::isCameraOrbit() const
{
return view_->isCameraOrbit();
}
bool GLWidget::isHoverHaloEnabled() const {
return view_->isHoverHaloEnabled();
}
QColor GLWidget::hoverHaloColor() const {
return view_->hoverHaloColor();
}
qreal GLWidget::hoverHaloFillAlpha() const {
return view_->hoverHaloFillAlpha();
}
bool GLWidget::isSelectionHaloEnabled() const {
return view_->isSelectionHaloEnabled();
}
QColor GLWidget::selectionHaloColor() const {
return view_->selectionHaloColor();
}
qreal GLWidget::selectionHaloFillAlpha() const {
return view_->selectionHaloFillAlpha();
}
void GLWidget::addObject(GLObjectBase * o) {
view_->addObject(o);
}
QByteArray GLWidget::saveCamera() {
return view_->saveCamera();
}
void GLWidget::restoreCamera(const QByteArray &ba) {
view_->restoreCamera(ba);
}
void GLWidget::stop() {
view_->stop();
}
void GLWidget::start(float freq, GLRendererBase * r) {
if (r == nullptr) r = new RendererSimple(view_);
GLRendererBase * pr = nullptr;
view_->setRenderer(r, &pr);
if (pr != nullptr && pr != r) delete pr;
view_->start(freq);
}
void GLWidget::setBackColor(const QColor & c) {
view_->setBackColor(c);
}
void GLWidget::setLineWidth(const qreal & arg) {
view_->setLineWidth(arg);
}
void GLWidget::setFOV(const qreal & arg) {
view_->setFOV(arg);
}
void GLWidget::setDepthStart(const qreal & arg) {
view_->setDepthStart(arg);
}
void GLWidget::setDepthEnd(const qreal & arg) {
view_->setDepthEnd(arg);
}
void GLWidget::setAmbientColor(const QColor & arg) {
view_->setAmbientColor(arg);
}
void GLWidget::setLightEnabled(const bool & arg) {
view_->setLightEnabled(arg);
}
void GLWidget::setGrabMouseEnabled(const bool & arg) {
view_->setGrabMouseEnabled(arg);
}
void GLWidget::setMouseRotateEnabled(const bool & arg) {
view_->setMouseRotateEnabled(arg);
}
void GLWidget::setMouseSelectionEnabled(const bool & arg) {
view_->setMouseSelectionEnabled(arg);
}
void GLWidget::setCameraOrbit(const bool & arg) {
view_->setCameraOrbit(arg);
}
void GLWidget::setHoverHaloEnabled(const bool & arg) {
view_->setHoverHaloEnabled(arg);
}
void GLWidget::setHoverHaloColor(const QColor & arg) {
view_->setHoverHaloColor(arg);
}
void GLWidget::setHoverHaloFillAlpha(const qreal & arg) {
view_->setHoverHaloFillAlpha(arg);
}
void GLWidget::setSelectionHaloEnabled(const bool & arg) {
view_->setSelectionHaloEnabled(arg);
}
void GLWidget::setSelectionHaloColor(const QColor & arg) {
view_->setSelectionHaloColor(arg);
}
void GLWidget::setSelectionHaloFillAlpha(const qreal & arg) {
view_->setSelectionHaloFillAlpha(arg);
}
void GLWidget::viewDoubleClicked() {
// qDebug() << "click widget!!";
if (view_->windowState() == Qt::WindowFullScreen) {
// view_->hide();
container = QWidget::createWindowContainer(view_, this);
lay->addWidget(container);
container->show();
// show();
} else {
// hide();
view_->setParent(nullptr);
view_->showFullScreen();
lay->removeWidget(container);
}
// qDebug() << "click widge done!";
}

View File

@@ -1,88 +1,88 @@
#ifndef GLWIDGET_H
#define GLWIDGET_H
#include <QWidget>
class QGLView;
class GLRendererBase;
class GLObjectBase;
class GLWidget : public QWidget
{
Q_OBJECT
Q_PROPERTY (QColor backColor READ backColor WRITE setBackColor)
Q_PROPERTY (qreal lineWidth READ lineWidth WRITE setLineWidth)
Q_PROPERTY (qreal FOV READ FOV WRITE setFOV)
Q_PROPERTY (qreal depthStart READ depthStart WRITE setDepthStart)
Q_PROPERTY (qreal depthEnd READ depthEnd WRITE setDepthEnd)
Q_PROPERTY (QColor ambientColor READ ambientColor WRITE setAmbientColor)
Q_PROPERTY (bool grabMouse READ isGrabMouseEnabled WRITE setGrabMouseEnabled)
Q_PROPERTY (bool mouseRotate READ isMouseRotateEnabled WRITE setMouseRotateEnabled)
Q_PROPERTY (bool mouseSelection READ isMouseSelectionEnabled WRITE setMouseSelectionEnabled)
Q_PROPERTY (bool cameraOrbit READ isCameraOrbit WRITE setCameraOrbit)
Q_PROPERTY (bool hoverHalo READ isHoverHaloEnabled WRITE setHoverHaloEnabled)
Q_PROPERTY (QColor hoverHaloColor READ hoverHaloColor WRITE setHoverHaloColor)
Q_PROPERTY (qreal hoverHaloFillAlpha READ hoverHaloFillAlpha WRITE setHoverHaloFillAlpha)
Q_PROPERTY (bool selectionHalo READ isSelectionHaloEnabled WRITE setSelectionHaloEnabled)
Q_PROPERTY (QColor selectionHaloColor READ selectionHaloColor WRITE setSelectionHaloColor)
Q_PROPERTY (qreal selectionHaloFillAlpha READ selectionHaloFillAlpha WRITE setSelectionHaloFillAlpha)
public:
explicit GLWidget(QWidget *parent = nullptr);
QGLView * view() {return view_;}
QColor backColor() const;
qreal lineWidth() const;
qreal FOV() const;
qreal depthStart() const;
qreal depthEnd() const;
QColor ambientColor() const;
bool isLightEnabled() const;
bool isGrabMouseEnabled() const;
bool isMouseRotateEnabled() const;
bool isMouseSelectionEnabled() const;
bool isCameraOrbit() const;
bool isHoverHaloEnabled() const;
QColor hoverHaloColor() const;
qreal hoverHaloFillAlpha() const;
bool isSelectionHaloEnabled() const;
QColor selectionHaloColor() const;
qreal selectionHaloFillAlpha() const;
void addObject(GLObjectBase * o);
QByteArray saveCamera();
void restoreCamera(const QByteArray & ba);
public slots:
void stop();
void start(float freq = 60.0, GLRendererBase * r = nullptr);
void setBackColor(const QColor & c);
void setLineWidth(const qreal & arg);
void setFOV(const qreal & arg);
void setDepthStart(const qreal & arg);
void setDepthEnd(const qreal & arg);
void setAmbientColor(const QColor & arg);
void setLightEnabled(const bool & arg);
void setGrabMouseEnabled(const bool & arg);
void setMouseRotateEnabled(const bool & arg);
void setMouseSelectionEnabled(const bool & arg);
void setCameraOrbit(const bool & arg);
void setHoverHaloEnabled(const bool & arg);
void setHoverHaloColor(const QColor & arg);
void setHoverHaloFillAlpha(const qreal & arg);
void setSelectionHaloEnabled(const bool & arg);
void setSelectionHaloColor(const QColor & arg);
void setSelectionHaloFillAlpha(const qreal & arg);
private slots:
void viewDoubleClicked();
private:
QWidget * container;
QGLView * view_;
QLayout * lay;
signals:
};
#endif // GLWIDGET_H
#ifndef GLWIDGET_H
#define GLWIDGET_H
#include <QWidget>
class QGLView;
class GLRendererBase;
class GLObjectBase;
class GLWidget : public QWidget
{
Q_OBJECT
Q_PROPERTY (QColor backColor READ backColor WRITE setBackColor)
Q_PROPERTY (qreal lineWidth READ lineWidth WRITE setLineWidth)
Q_PROPERTY (qreal FOV READ FOV WRITE setFOV)
Q_PROPERTY (qreal depthStart READ depthStart WRITE setDepthStart)
Q_PROPERTY (qreal depthEnd READ depthEnd WRITE setDepthEnd)
Q_PROPERTY (QColor ambientColor READ ambientColor WRITE setAmbientColor)
Q_PROPERTY (bool grabMouse READ isGrabMouseEnabled WRITE setGrabMouseEnabled)
Q_PROPERTY (bool mouseRotate READ isMouseRotateEnabled WRITE setMouseRotateEnabled)
Q_PROPERTY (bool mouseSelection READ isMouseSelectionEnabled WRITE setMouseSelectionEnabled)
Q_PROPERTY (bool cameraOrbit READ isCameraOrbit WRITE setCameraOrbit)
Q_PROPERTY (bool hoverHalo READ isHoverHaloEnabled WRITE setHoverHaloEnabled)
Q_PROPERTY (QColor hoverHaloColor READ hoverHaloColor WRITE setHoverHaloColor)
Q_PROPERTY (qreal hoverHaloFillAlpha READ hoverHaloFillAlpha WRITE setHoverHaloFillAlpha)
Q_PROPERTY (bool selectionHalo READ isSelectionHaloEnabled WRITE setSelectionHaloEnabled)
Q_PROPERTY (QColor selectionHaloColor READ selectionHaloColor WRITE setSelectionHaloColor)
Q_PROPERTY (qreal selectionHaloFillAlpha READ selectionHaloFillAlpha WRITE setSelectionHaloFillAlpha)
public:
explicit GLWidget(QWidget *parent = nullptr);
QGLView * view() {return view_;}
QColor backColor() const;
qreal lineWidth() const;
qreal FOV() const;
qreal depthStart() const;
qreal depthEnd() const;
QColor ambientColor() const;
bool isLightEnabled() const;
bool isGrabMouseEnabled() const;
bool isMouseRotateEnabled() const;
bool isMouseSelectionEnabled() const;
bool isCameraOrbit() const;
bool isHoverHaloEnabled() const;
QColor hoverHaloColor() const;
qreal hoverHaloFillAlpha() const;
bool isSelectionHaloEnabled() const;
QColor selectionHaloColor() const;
qreal selectionHaloFillAlpha() const;
void addObject(GLObjectBase * o);
QByteArray saveCamera();
void restoreCamera(const QByteArray & ba);
public slots:
void stop();
void start(float freq = 60.0, GLRendererBase * r = nullptr);
void setBackColor(const QColor & c);
void setLineWidth(const qreal & arg);
void setFOV(const qreal & arg);
void setDepthStart(const qreal & arg);
void setDepthEnd(const qreal & arg);
void setAmbientColor(const QColor & arg);
void setLightEnabled(const bool & arg);
void setGrabMouseEnabled(const bool & arg);
void setMouseRotateEnabled(const bool & arg);
void setMouseSelectionEnabled(const bool & arg);
void setCameraOrbit(const bool & arg);
void setHoverHaloEnabled(const bool & arg);
void setHoverHaloColor(const QColor & arg);
void setHoverHaloFillAlpha(const qreal & arg);
void setSelectionHaloEnabled(const bool & arg);
void setSelectionHaloColor(const QColor & arg);
void setSelectionHaloFillAlpha(const qreal & arg);
private slots:
void viewDoubleClicked();
private:
QWidget * container;
QGLView * view_;
QLayout * lay;
signals:
};
#endif // GLWIDGET_H

View File

@@ -1,96 +1,96 @@
#include "openglwindow.h"
#include <QCoreApplication>
#include <QOpenGLContext>
#include <QOpenGLPaintDevice>
#include <QPainter>
#include <qopenglext.h>
OpenGLWindow::OpenGLWindow(QWindow *parent)
: QWindow(parent)
, m_context(nullptr)
, m_device(nullptr)
{
setFlags(flags() | Qt::FramelessWindowHint);
setSurfaceType(QWindow::OpenGLSurface);
QSurfaceFormat format = QSurfaceFormat::defaultFormat();
// qDebug() << format;
#ifdef QT_OPENGL_ES_2
format.setRenderableType(QSurfaceFormat::OpenGLES);
#else
if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) {
format.setVersion(2, 0);
format.setProfile(QSurfaceFormat::NoProfile);
}
#endif
format.setDepthBufferSize(24);
format.setSamples(8);
// format.setStencilBufferSize(8);
setFormat(format);
QSurfaceFormat::setDefaultFormat(format);
}
OpenGLWindow::~OpenGLWindow() {
delete m_device;
}
void OpenGLWindow::render(QPainter *painter) {
}
void OpenGLWindow::initialize() {
}
void OpenGLWindow::render() {
// if (!m_device) m_device = new QOpenGLPaintDevice;
// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// m_device->setSize(size() * devicePixelRatio());
// m_device->setDevicePixelRatio(devicePixelRatio());
// QPainter painter(m_device);
// render(&painter);
}
void OpenGLWindow::renderLater() {
requestUpdate();
}
bool OpenGLWindow::event(QEvent *event) {
switch (event->type()) {
case QEvent::UpdateRequest:
renderNow();
return true;
default:
return QWindow::event(event);
}
}
void OpenGLWindow::exposeEvent(QExposeEvent *event) {
if (isExposed()) renderNow();
}
void OpenGLWindow::renderNow() {
if (!isExposed())
return;
bool needsInitialize = false;
if (!m_context) {
m_context = new QOpenGLContext(this);
m_context->setFormat(requestedFormat());
m_context->create();
needsInitialize = true;
}
m_context->makeCurrent(this);
if (needsInitialize) {
initializeOpenGLFunctions();
initialize();
}
render();
m_context->swapBuffers(this);
}
#include "openglwindow.h"
#include <QCoreApplication>
#include <QOpenGLContext>
#include <QOpenGLPaintDevice>
#include <QPainter>
#include <qopenglext.h>
OpenGLWindow::OpenGLWindow(QWindow *parent)
: QWindow(parent)
, m_context(nullptr)
, m_device(nullptr)
{
setFlags(flags() | Qt::FramelessWindowHint);
setSurfaceType(QWindow::OpenGLSurface);
QSurfaceFormat format = QSurfaceFormat::defaultFormat();
// qDebug() << format;
#ifdef QT_OPENGL_ES_2
format.setRenderableType(QSurfaceFormat::OpenGLES);
#else
if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) {
format.setVersion(2, 0);
format.setProfile(QSurfaceFormat::NoProfile);
}
#endif
format.setDepthBufferSize(24);
format.setSamples(8);
// format.setStencilBufferSize(8);
setFormat(format);
QSurfaceFormat::setDefaultFormat(format);
}
OpenGLWindow::~OpenGLWindow() {
delete m_device;
}
void OpenGLWindow::render(QPainter *painter) {
}
void OpenGLWindow::initialize() {
}
void OpenGLWindow::render() {
// if (!m_device) m_device = new QOpenGLPaintDevice;
// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// m_device->setSize(size() * devicePixelRatio());
// m_device->setDevicePixelRatio(devicePixelRatio());
// QPainter painter(m_device);
// render(&painter);
}
void OpenGLWindow::renderLater() {
requestUpdate();
}
bool OpenGLWindow::event(QEvent *event) {
switch (event->type()) {
case QEvent::UpdateRequest:
renderNow();
return true;
default:
return QWindow::event(event);
}
}
void OpenGLWindow::exposeEvent(QExposeEvent *event) {
if (isExposed()) renderNow();
}
void OpenGLWindow::renderNow() {
if (!isExposed())
return;
bool needsInitialize = false;
if (!m_context) {
m_context = new QOpenGLContext(this);
m_context->setFormat(requestedFormat());
m_context->create();
needsInitialize = true;
}
m_context->makeCurrent(this);
if (needsInitialize) {
initializeOpenGLFunctions();
initialize();
}
render();
m_context->swapBuffers(this);
}

View File

@@ -1,36 +1,36 @@
#include <QWindow>
#include <QOpenGLFunctions>
class QPainter;
class QOpenGLContext;
class QOpenGLPaintDevice;
class OpenGLWindow : public QWindow, protected QOpenGLFunctions
{
Q_OBJECT
public:
explicit OpenGLWindow(QWindow *parent = nullptr);
~OpenGLWindow();
virtual void render(QPainter *painter);
virtual void render();
virtual void initialize();
QOpenGLContext * context() {return m_context;}
public slots:
void renderLater();
void renderNow();
protected:
bool event(QEvent *event) override;
void exposeEvent(QExposeEvent *event) override;
private:
QOpenGLContext *m_context;
QOpenGLPaintDevice *m_device;
};
#include <QWindow>
#include <QOpenGLFunctions>
class QPainter;
class QOpenGLContext;
class QOpenGLPaintDevice;
class OpenGLWindow : public QWindow, protected QOpenGLFunctions
{
Q_OBJECT
public:
explicit OpenGLWindow(QWindow *parent = nullptr);
~OpenGLWindow();
virtual void render(QPainter *painter);
virtual void render();
virtual void initialize();
QOpenGLContext * context() {return m_context;}
public slots:
void renderLater();
void renderNow();
protected:
bool event(QEvent *event) override;
void exposeEvent(QExposeEvent *event) override;
private:
QOpenGLContext *m_context;
QOpenGLPaintDevice *m_device;
};

View File

@@ -1,18 +1 @@
if (DESIGNER_PLUGINS)
if (NOT Qt5)
message(WARNING "Building ${PROJECT_NAME} available only on Qt5!")
else()
project(qglview_plugin)
include_directories("..")
add_definitions(-DQT_PLUGIN)
add_definitions(-DQT_NO_DEBUG)
add_definitions(-DQT_SHARED)
add_definitions(-DQDESIGNER_EXPORT_WIDGETS)
find_qt(Qt5 Core Designer Gui Widgets OpenGL)
qt_sources(SRC)
qt_wrap(${SRC} CPPS out_CPP QMS out_QM)
qt_add_library(${PROJECT_NAME} SHARED out_CPP)
qt_target_link_libraries(${PROJECT_NAME} qglview)
qt_install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION QtPlugins/designer)
endif()
endif()
_qt_plugin(qglview "Gui;Widgets;OpenGL" "qglview")

View File

@@ -1,846 +1,846 @@
/*
QGLView
Ivan Pelipenko peri4ko@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/>.
*/
#include "qglview.h"
#include <QApplication>
#include <QKeyEvent>
QGLView::QGLView(): OpenGLWindow(), fbo_selection(3) {
// setFrameShape(QFrame::NoFrame);
// setViewportUpdateMode(FullViewportUpdate);
// setCacheMode(CacheNone);
// setMouseTracking(true);
// setFocusPolicy(Qt::WheelFocus);
// setScene(new QGraphicsScene());
// setInteractive(true);
setIcon(QIcon("://icons/qglview.png"));
deleting_ = false;
timer = 0;
need_init_ = is_first_draw = true;
objects_.is_root = true;
objects_.view_ = this;
backColor_ = Qt::darkGray;
hoverHaloColor_ = QColor(195, 140, 255, 96);
selectionHaloColor_ = QColor(175, 255, 140);
ambientColor_ = QColor(10, 10, 10);
lastPos = QPoint(-1, -1);
lineWidth_ = 1.;
max_anisotropic = 1;
max_texture_chanels = 8;
cameraOrbit_ = lightEnabled_ = true;
shaders_supported = selecting_ = customMouseMove_ = false;
sel_button = Qt::LeftButton;
sel_mod = Qt::NoModifier;
renderer_ = nullptr;
fps_cnt = 0;
fps_tm = fps_ = 0.;
sel_obj = hov_obj = nullptr;
fogDensity_ = fogEnd_ = 1.;
fogStart_ = 0.;
fogMode_ = Exp;
hoverHaloFill_ = 0.333f;
selectionHaloFill_ = 0.5f;
//lmode = Simple;
shader_select = shader_halo = nullptr;
setFeature(qglMSAA, false);
setFeature(qglFXAA, false);
setFeature(qglLinearFiltering, true);
setFeature(qglAnisotropicLevel, 8);
setFeature(qglHDR, false);
setFeature(qglEyeAccomodationEnabled, false);
setFeature(qglEyeAccomodationTime, 16.);
setFeature(qglEyeAccomodationMaxSpeed, 0.2);
setFeature(qglBloomEnabled, false);
setFeature(qglBloomThreshold, 0.9);
setFeature(qglBloomFactor, 1.);
setFeature(qglBloomRadius, 8);
setFeature(qglMotionBlurEnabled, false);
setFeature(qglMotionBlurFactor, 1.);
setFeature(qglMotionBlurSteps, 8);
setFeature(qglShadowsEnabled, false);
setFeature(qglShadowsMapSize, 512);
setFeature(qglShadowsSoftEnabled, true);
setFeature(qglReflectionsEnabled, false);
setFeature(qglReflectionsBlur, true);
setFeature(qglSSAOEnabled, false);
setFeature(qglSSAORadius, 5);
setFeature(qglDepthOfFieldEnabled, false);
setFeature(qglDepthOfFieldAutoFocusEnabled, true);
setFeature(qglDepthOfFieldAutoFocusSpeed, 0.1);
setFeature(qglDepthOfFieldFocus, 1.);
setFeature(qglDepthOfFieldDiaphragm, 8.);
mouse_first = mouseSelect_ = hoverHalo_ = selectionHalo_ = true;
mouseRotate_ = true;
fogEnabled_ = is_init = grabMouse_ = shaders_bind = changed_ = false;
rmode = GLObjectBase::Fill;
sel_mode = QGLView::SingleSelection;
// sel_pen = QPen(Qt::black, 1, Qt::DashLine);
// sel_brush = QBrush(QColor(170, 100, 255, 120));
camera()->setAim(QVector3D());
camera()->setPos(QVector3D(2, 2, 2));
camera()->setName("Camera");
addObject(camera());
emit cameraPosChanged(camera()->pos());
//camera().aim_ = camera().pos_;
ktm_.restart();
}
QGLView::~QGLView() {
stop();
if (shader_select) delete shader_select;
if (shader_halo) delete shader_halo;
deleting_ = true;
}
void QGLView::stop() {
if (timer) killTimer(timer);
timer = 0;
}
void QGLView::start(float freq) {
stop();
timer = startTimer(freq <= 0.f ? 0 : int(1000.f / freq));
}
GLRendererBase * QGLView::renderer() {
return renderer_;
}
void QGLView::setRenderer(GLRendererBase * r, GLRendererBase ** prev) {
if (prev != nullptr) *prev = renderer_;
renderer_ = r;
}
void QGLView::addObject(GLObjectBase * o) {
objects_.addChild(o);
o->setView(this);
collectLights();
QList<GLObjectBase*> cl = o->children(true);
cl << o;
foreach (GLObjectBase * i, cl) {
emit objectAdded(i);
}
if (is_init) {
o->init();
}
}
int QGLView::objectsCount(bool all) {
if (!all) return objects_.childCount();
int cnt = 0;
objectsCountInternal(&cnt, &objects_);
return cnt;
}
void QGLView::removeObject(GLObjectBase * o, bool inChildren) {
o->setView(nullptr);
if (inChildren)
removeObjectInternal(o, &objects_);
else
objects_.removeChild(o);
objectDeleted(o);
}
void QGLView::removeObject(GLObjectBase & o, bool inChildren) {
removeObject(&o, inChildren);
}
void QGLView::clearObjects(bool deleteAll) {
removeObject(camera_);
objects_.clearChildren(deleteAll);
addObject(camera());
selectObject(nullptr);
hov_obj = nullptr;
}
QList<GLObjectBase *> QGLView::objects(bool all) {
return objects_.children(all);
}
int QGLView::lightsCount() const {
return lights_.size();
}
void QGLView::removeLight(int index) {
removeObject(lights_.at(index));
lights_.removeAt(index);
}
void QGLView::removeLight(Light * l) {
foreach (Light * i, lights_)
if (i == l) removeObject(i);
lights_.removeAll(l);
}
void QGLView::clearLights(bool deleteAll) {
if (deleteAll)
foreach (Light * i, lights_) delete i;
lights_.clear();
}
void QGLView::addTexture(const QString & path) {
textures_manager->addTexture(path);
}
void QGLView::addAnimation(const QString & dir, const QString & name) {
textures_manager->addAnimation(dir, name);
}
Light * QGLView::light(int index) {
return lights_[index];
}
Light * QGLView::light(const QString & name) {
foreach (Light * i, lights_)
if (i->name_ == name) return i;
return nullptr;
}
void QGLView::selectObject(GLObjectBase * o) {
if (o == sel_obj) return;
GLObjectBase * pso = sel_obj;
sel_obj = o;
emit selectionChanged(sel_obj, pso);
}
void QGLView::resizeEvent(QResizeEvent * e) {
renderLater();
}
void QGLView::timerEvent(QTimerEvent *) {
renderNow();
if (ktm_.elapsed() < QApplication::keyboardInputInterval()) return;
Qt::KeyboardModifiers km = QApplication::keyboardModifiers();
foreach (int i, keys_)
emit keyEvent((Qt::Key)i, km);
}
void QGLView::render() {
if (!isVisible()) return;
resizeGL(width(), height());
QRect g_rect(QPoint(), size());
emit glBeforePaint();
//qDebug() << "paintGL";
//QMutexLocker ml_v(&v_mutex);
glEnable(GL_CULL_FACE);
//glDisable(GL_CULL_FACE);
camera()->apply(aspect);
//objects_.preparePos(camera());
start_rp.cam_offset_matrix = camera()->offsetMatrix();
start_rp.proj_matrix = getGLMatrix(GL_PROJECTION_MATRIX);
start_rp.view_matrix = getGLMatrix(GL_MODELVIEW_MATRIX);
//objects_.buildTransform();
/// Selection detect
//glClearFramebuffer(QColor(100, 0, 0, 0));
if (mouseSelect_) {
glReleaseTextures();
glEnableDepth();
glDisable(GL_TEXTURE_1D);
glDisable(GL_TEXTURE_2D);
glDisable(GL_TEXTURE_CUBE_MAP);
glDisable(GL_MULTISAMPLE);
glDisable(GL_LIGHTING);
glDisable(GL_BLEND);
glDisable(GL_ALPHA_TEST);
glDisable(GL_RESCALE_NORMAL);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
fbo_selection.bind();
fbo_selection.setWriteBuffer(0);
glClearFramebuffer(QColor(0, 0, 0, 0));
if (shaders_supported && shader_select->isLinked()) shader_select->bind();
renderSelection();
if (shaders_supported && shader_select->isLinked()) shader_select->release();
uchar cgid[4] = {0, 0, 0, 0};
uint iid = 0;
GLObjectBase * so = nullptr;
if (!g_rect.contains(lastPos)) {
if (hov_obj != nullptr) {
hov_obj = nullptr;
emit hoverChanged(nullptr, hov_obj);
}
} else {
glReadPixels(lastPos.x(), height() - lastPos.y(), 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, cgid);
iid = uint(cgid[0] << 24) | uint(cgid[1] << 16) | uint(cgid[2] << 8) | cgid[3];
so = ids.value(iid, nullptr);
//qDebug() <<cgid[0]<<cgid[1]<<cgid[2]<<cgid[3]<< iid;
if (so != hov_obj) {
emit hoverChanged(so, hov_obj);
hov_obj = so;
}
//if (so != 0) qDebug() << sel_obj->name() << cgid[3];
}
if (selectionHalo_ && sel_obj) {
fbo_selection.setWriteBuffer(2);
renderHalo(sel_obj, qHash((quint64)sel_obj), selectionHaloColor_, selectionHaloFill_);
}
if (hoverHalo_ && hov_obj) {
fbo_selection.setWriteBuffer(1);
renderHalo(hov_obj, iid, hoverHaloColor_, hoverHaloFill_);
}
fbo_selection.release();
glEnableDepth();
/*glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);*/
}
camera()->apply(aspect);
start_rp.cam_offset_matrix = camera()->offsetMatrix();
cur_mvpm = start_rp.proj_matrix * start_rp.view_matrix * start_rp.cam_offset_matrix;
//objects_.preparePos(camera());
static GLRendererBase * prev_rend = nullptr;
glShadeModel(GL_SMOOTH);
if (prev_rend != renderer_) {
prev_rend = renderer_;
if (renderer_ != nullptr) {
renderer_->init(width(), height());
renderer_->resize(width(), height());
renderer_->reloadShaders();
}
}
emit glBeginPaint();
if (renderer_ != nullptr) {
renderer_->rp.prepare();
renderer_->prepareScene();
renderer_->renderScene();
}
emit glPainting();
glUseProgram(0);
if (selectionHalo_ || hoverHalo_) {
glReleaseTextures();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
//glClearFramebuffer(Qt::black, false);
glActiveTexture(GL_TEXTURE0);
glEnable(GL_BLEND);
glDisable(GL_TEXTURE_CUBE_MAP);
glDisable(GL_LIGHTING);
glDisableDepth();
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
if (selectionHalo_ && sel_obj) {
glBindTexture(GL_TEXTURE_2D, fbo_selection.colorTexture(2));
//qDebug() << "draw sel";
glDrawQuad();
}
if (hoverHalo_ && hov_obj) {
glBindTexture(GL_TEXTURE_2D, fbo_selection.colorTexture(1));
//qDebug() << "draw hover";
//glBindTexture(GL_TEXTURE_2D, textures_manager->loadTexture("batt_pn.jpg"));
glDrawQuad();
}
}
glResetAllTransforms();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glUseProgram(0);
//glDisable(GL_BLEND);
//glDisable(GL_LIGHTING);
//glActiveTexture(GL_TEXTURE0);
//glBindTexture(GL_TEXTURE_2D, textures_manager->loadTexture("batt_pn.jpg"));
//glDrawQuad();
emit glEndPaint();
/*releaseShaders();
glActiveTextureChannel(0);
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glColor4f(0.3, 0.5, 0.8, 0.5);
glResetAllTransforms();
glBegin(GL_QUADS);
glTexCoord2f(0.f, 0.f); glVertex2f(-1.f, -1.f);
glTexCoord2f(1.f, 0.f); glVertex2f(1.f, -1.);
glTexCoord2f(1.f, 1.f); glVertex2f(1.f, 1.f);
glTexCoord2f(0.f, 1.f); glVertex2f(-1.f, 1.f);
glEnd();*/
/*
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glDisable(GL_LIGHTING);
glActiveTextureChannel(0);
glBindTexture(GL_TEXTURE_2D, fbo->texture());
glDisable(GL_DEPTH_TEST);
glBegin(GL_QUADS);
glColor3f(1.f, 1.f, 1.f);
glTexCoord2f(0.f, 0.f); glVertex2f(-1.f, -1.f);
glTexCoord2f(0.f, 1.f); glVertex2f(-1.f, 1.f);
glTexCoord2f(1.f, 1.f); glVertex2f(1.f, 1.f);
glTexCoord2f(1.f, 0.f); glVertex2f(1.f, -1.);
glEnd();
glEnable(GL_DEPTH_TEST);*/
fps_tm += time.elapsed();
time.restart();
fps_cnt++;
if (fps_tm < 1000.) return;
fps_ = fps_cnt / fps_tm * 1000.;
fps_tm = 0.;
fps_cnt = 0;
}
void QGLView::initialize() {
//initializeOpenGLFunctions();
glEnable(GL_TEXTURE_MAX_ANISOTROPY_EXT);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glEnableDepth();
glEnable(GL_CULL_FACE);
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
glActiveTexture(GL_TEXTURE0 + 3);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
glEnable(GL_TEXTURE_GEN_R);
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glActiveTexture(GL_TEXTURE0);
glShadeModel(GL_SMOOTH);
glCullFace(GL_BACK);
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT, GL_DIFFUSE);
textures_manager->loadTextures();
objects_.initInternal();
checkCaps();
shader_select = new QOpenGLShaderProgram(context());
shader_halo = new QOpenGLShaderProgram(context());
reloadThisShaders();
is_init = true;
//resizeGL(width(), height());
need_init_ = false;
emit glInitializeDone();
}
void QGLView::renderHalo(const GLObjectBase * obj, const uint iid, const QColor & color, const float & fill) {
if (!shaders_supported) return;
if (!shader_halo) return;
if (!shader_halo->isLinked()) return;
if (obj) {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, fbo_selection.colorTexture());
shader_halo->bind();
shader_halo->setUniformValue("qgl_ModelViewProjectionMatrix", QMatrix4x4());
shader_halo->setUniformValue("t0", 0);
shader_halo->setUniformValue("dt", QVector2D(1.f / width(), 1.f / height()));
shader_halo->setUniformValue("selected", QVector4D(float((iid >> 24) & 0xFF) / 255.f,
float((iid >> 16) & 0xFF) / 255.f,
float((iid >> 8) & 0xFF) / 255.f,
float( iid & 0xFF) / 255.f));
shader_halo->setUniformValue("color", color);
shader_halo->setUniformValue("fill", GLfloat(fill));
//qDebug() << "render halo" << iid << shader_halo->log() << shader_halo->programId();
glDisableDepth();
//glClearFramebuffer(color);
glDrawQuad(shader_halo);
glDepthMask(GL_TRUE);
//glFlush();
shader_halo->release();
} else {
glClearFramebuffer(Qt::black, false);
}
}
void QGLView::renderSelection() {
// cid = 1;
ids.clear();
if (shaders_supported) {
if (shader_select) {
if (shader_select->isLinked()) {
sh_id_loc = shader_select->uniformLocation("id");
shader_select->setUniformValue("z_far", GLfloat(depthEnd()));
shader_select->setUniformValue("z_near", GLfloat(depthStart()));
}
}
}
//qDebug() << sh_id_loc;
start_rp.view_matrix = getGLMatrix(GL_MODELVIEW_MATRIX);
glPushMatrix();
renderSingleSelection(objects_);
glPopMatrix();
}
void QGLView::renderSingleSelection(GLObjectBase & o) {
if (!o.isInit()) {
o.init();
o.loadTextures();
}
if (!o.visible_ || !o.select_) return;
QMatrix4x4 curview = start_rp.view_matrix * start_rp.cam_offset_matrix * o.itransform_;
uint id = qHash((quint64)&o);
ids.insert(id, &o);
glLineWidth(o.line_width > 0.f ? o.line_width : lineWidth_);
glPointSize(o.line_width > 0.f ? o.line_width : lineWidth_);
if (shaders_supported){
if (shader_select) {
if (shader_select->isLinked()) {
setUniformMatrices(shader_select, start_rp.proj_matrix, curview);
shader_select->setUniformValue(sh_id_loc, QVector4D(float((id >> 24) & 0xFF) / 255.f,
float((id >> 16) & 0xFF) / 255.f,
float((id >> 8) & 0xFF) / 255.f,
float(id & 0xFF) / 255.f));
}
}
} else {
setGLMatrix(curview);
glColor4f(float((id >> 24) & 0xFF) / 255.f,
float((id >> 16) & 0xFF) / 255.f,
float((id >> 8) & 0xFF) / 255.f,
float(id & 0xFF) / 255.f);
}
//qDebug() << o.name() << "assign to" << sh_id_loc << cid;
//glColor4f(float((cid >> 24) & 0xFF) / 255.f, float((cid >> 16) & 0xFF) / 255.f, float((cid >> 8) & 0xFF) / 255.f, float(cid & 0xFF) / 255.f);
// ++cid;
o.draw(nullptr, true);
foreach (GLObjectBase * i, o.children_)
renderSingleSelection(*i);
}
void QGLView::collectLights() {
lights_.clear();
collectObjectLights(&objects_);
}
void QGLView::objectDeleted(GLObjectBase * o) {
if (deleting_) return;
//qDebug() << "del" << o;
if (sel_obj == o) selectObject(nullptr);
if (hov_obj == o) hov_obj = nullptr;
collectLights();
}
void QGLView::collectObjectLights(GLObjectBase * o) {
if (o->type_ == GLObjectBase::glLight) {
lights_ << globject_cast<Light * >(o);
o->view_ = this;
}
foreach (GLObjectBase * i, o->children())
collectObjectLights(i);
}
void QGLView::objectsCountInternal(int * cnt, GLObjectBase * where) {
++(*cnt);
foreach (GLObjectBase * i, where->children_)
objectsCountInternal(cnt, i);
}
void QGLView::removeObjectInternal(GLObjectBase * o, GLObjectBase * where) {
foreach (GLObjectBase * i, where->children_) {
if (o == i)
where->removeChild(i);
else
removeObjectInternal(o, i);
objectDeleted(i);
}
}
void QGLView::checkCaps() {
glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &max_anisotropic);
//glGetIntegerv(GL_MAX_TEXTURE_UNITS, &max_texture_chanels);
//qDebug() << max_texture_chanels;
//qDebug() << max_texture_chanels;
shaders_supported = QOpenGLShaderProgram::hasOpenGLShaderPrograms();
}
void QGLView::reloadThisShaders() {
if (!shaders_supported) return;
loadShaders(shader_select, "selection", "://shaders");
loadShaders(shader_halo, "selection_halo", "://shaders");
//loadShaders(shader_rope, "rope", "://shaders");
}
void QGLView::glReleaseTextures(int channels) {
for (int i = channels - 1; i >= 0; --i) {
glActiveTexture(GL_TEXTURE0 + i);
glBindTexture(GL_TEXTURE_2D, 0);
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
}
}
void QGLView::applyFog() {
GLfloat fog_col[4] = {float(fogColor_.redF()), float(fogColor_.greenF()), float(fogColor_.blueF()), .0f};
if (fogEnabled_) {
glEnable(GL_FOG);
glFogf(GL_FOG_DENSITY, fogDensity_);
glFogf(GL_FOG_START, fogStart_);
glFogf(GL_FOG_END, fogEnd_);
glFogi(GL_FOG_MODE, fogMode_);
fog_col[0] = fogColor_.redF();
fog_col[1] = fogColor_.greenF();
fog_col[2] = fogColor_.blueF();
glFogfv(GL_FOG_COLOR, fog_col);
} else glDisable(GL_FOG);
}
void QGLView::resizeGL(int width, int height) {
if (!is_init) return;
if (width <= 0 || height <= 0) return;
if (prev_size == QSize(width, height)) return;
prev_size = QSize(width, height);
aspect = float(width) / float(height);
if (renderer_) renderer_->resize(width, height);
mouse_first = true;
//qDebug() << "resize" << width << height;
fbo_selection.resize(width, height);
iaspect = (aspect == 0.f) ? 0. : 1 / aspect;
glViewport(0, 0, width, height);
emit glResize(width, height);
}
void QGLView::mouseReleaseEvent(QMouseEvent * e) {
// qDebug() << "mouseReleaseEvent" << e << isActive();
// QGraphicsView::mouseReleaseEvent(e);
//setCursor(QCursor(Qt::ArrowCursor));
selecting_ = false;
if (mouseSelect_ && e->button() == Qt::LeftButton) {
if ((lastPos - downPos).manhattanLength() < 8) {
if (sel_obj != hov_obj)
selectObject(hov_obj);
}
}
emit glMouseReleaseEvent(e);
}
void QGLView::mousePressEvent(QMouseEvent * e) {
// qDebug() << "mousePressEvent" << e << isActive();
// QGraphicsView::mousePressEvent(e);
// mouseThis_ = (scene()->itemAt(mapToScene(e->pos()) , QTransform() ) == 0);
selecting_ = false;
if (!QRect(QPoint(), size()).contains(e->pos())) return;
/// TODO select by rect
//if (e->button() == sel_button && e->modifiers() == sel_mod)
// selecting_ = true;
lastPos = e->pos();
downPos = lastPos;
//qDebug() << mouseThis_;
emit glMousePressEvent(e);
}
void QGLView::mouseMoveEvent(QMouseEvent * e) {
// qDebug() << "mouseMoveEvent" << e << isActive();
// QGraphicsView::mouseMoveEvent(e);
//lastPos = e->pos();
if (selecting_) {
return;
}
// if (!QRect(QPoint(), size()).contains(e->pos())) return;
//if (scene()->itemAt(mapToScene(e->pos())) != 0) return;
///qDebug() << e->x() << e->y();
QRect g_rect(QPoint(), size());
if (mouseRotate_) {
float dx = e->x() - lastPos.x();
float dy = e->y() - lastPos.y();
if (e->buttons() & Qt::LeftButton) {
//camera().angle_z += dx / 4.;
//camera().angle_xy += dy / 4.;
if (cameraOrbit_) {
camera()->orbitZ(dx / 4.f);
camera()->orbitXY(dy / 4.f);
} else {
camera()->rotateZ(dx / 4.f);
camera()->rotateXY(dy / 4.f);
}
emit cameraPosChanged(camera()->pos());
} else if (e->buttons() & Qt::RightButton) {
float ad = camera()->distance();
camera()->moveLeft(dx / 1000.f * ad);
camera()->moveUp(dy / 1000.f * ad);
//camera().pos.setX(camera().pos.x() + camera().pos.z() * dx / 500.);
//camera().pos.setY(camera().pos.y() - camera().pos.z() * dy / 500.);
emit cameraPosChanged(camera()->pos());
}
//lights[0]->pos_ = camera().pos();
}
if (customMouseMove_) emit customMouseMoveEvent(e->pos(), lastPos, e->buttons());
lastPos = e->pos();
if (grabMouse_) {
//if (!isrunning) return;
QCursor::setPos(mapToGlobal(QRect(QPoint(), size()).center()));
static bool mouse_sec = false;
if (mouse_sec) {
mouse_sec = false;
return;
}
if (mouse_first) {
mouse_first = false;
mouse_sec = true;
//qDebug() << "first" << e->pos();
return;
}
lastPos = g_rect.center();
int dx = e->x() - lastPos.x();
int dy = e->y() - lastPos.y();
emit glMouseMoveEvent(new QMouseEvent(QEvent::MouseMove, QPoint(dx, dy), e->button(), e->buttons(), e->modifiers()));
return;
}
emit glMouseMoveEvent(e);
}
void QGLView::wheelEvent(QWheelEvent * e) {
if (mouseRotate_) {
if (e->delta() > 0) camera()->flyCloser(0.1f); //camera().pos.setZ(camera().pos.z() - 0.1 * camera().pos.z());
if (e->delta() < 0) camera()->flyFarer(0.1f); //camera().pos.setZ(camera().pos.z() + 0.1 * camera().pos.z());
emit cameraPosChanged(camera()->pos());
}
emit glWheelEvent(e);
}
void QGLView::leaveEvent(QEvent * ) {
lastPos = QPoint(-1, -1);
//qDebug() << lastPos;
}
void QGLView::keyPressEvent(QKeyEvent * e) {
emit glKeyPressEvent(e);
if (e->key() > 0) keys_.insert(e->key());
if (e->key() == Qt::Key_F11) {
emit doubleClick();
}
}
void QGLView::keyReleaseEvent(QKeyEvent * e) {
emit glKeyReleaseEvent(e);
keys_.remove(e->key());
}
void QGLView::focusOutEvent(QFocusEvent *) {
keys_.clear();
}
void QGLView::mouseDoubleClickEvent(QMouseEvent * e) {
if (e->buttons().testFlag(Qt::MidButton))
emit doubleClick();
}
QByteArray QGLView::saveCamera() {
ChunkStream cs;
const Camera * c = camera();
cs.add(1, c->posX());
cs.add(2, c->posY());
cs.add(3, c->posZ());
cs.add(4, c->aim().x());
cs.add(5, c->aim().y());
cs.add(6, c->aim().z());
cs.add(7, c->angleZ());
cs.add(8, c->angleXY());
cs.add(9, c->angleRoll());
cs.add(10, c->FOV());
return cs.data();
}
void QGLView::restoreCamera(const QByteArray &ba) {
if (ba.isEmpty()) return;
ChunkStream cs(ba);
QVector3D pos, aim, ang;
while (!cs.atEnd()) {
switch (cs.read()) {
case 1: pos.setX(cs.getData<float>()); break;
case 2: pos.setY(cs.getData<float>()); break;
case 3: pos.setZ(cs.getData<float>()); break;
case 4: aim.setX(cs.getData<float>()); break;
case 5: aim.setY(cs.getData<float>()); break;
case 6: aim.setZ(cs.getData<float>()); break;
case 7: ang.setZ(cs.getData<float>()); break;
case 8: ang.setY(cs.getData<float>()); break;
case 9: ang.setX(cs.getData<float>()); break;
case 10: setFOV(cs.getData<float>()); break;
default: break;
}
}
camera()->setPos(pos);
camera()->setAim(aim);
camera()->setAngles(ang);
}
QByteArray QGLView::saveFeatures() {
QByteArray ba;
QDataStream ds(&ba, QIODevice::WriteOnly);
ds << features_;
return ba;
}
void QGLView::restoreFeatures(const QByteArray & ba) {
QHash<int, QVariant> f;
QDataStream ds(ba);
ds >> f;
features_ = f;
}
/*
QGLView
Ivan Pelipenko peri4ko@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/>.
*/
#include "qglview.h"
#include <QApplication>
#include <QKeyEvent>
QGLView::QGLView(): OpenGLWindow(), fbo_selection(3) {
// setFrameShape(QFrame::NoFrame);
// setViewportUpdateMode(FullViewportUpdate);
// setCacheMode(CacheNone);
// setMouseTracking(true);
// setFocusPolicy(Qt::WheelFocus);
// setScene(new QGraphicsScene());
// setInteractive(true);
setIcon(QIcon("://icons/qglview.png"));
deleting_ = false;
timer = 0;
need_init_ = is_first_draw = true;
objects_.is_root = true;
objects_.view_ = this;
backColor_ = Qt::darkGray;
hoverHaloColor_ = QColor(195, 140, 255, 96);
selectionHaloColor_ = QColor(175, 255, 140);
ambientColor_ = QColor(10, 10, 10);
lastPos = QPoint(-1, -1);
lineWidth_ = 1.;
max_anisotropic = 1;
max_texture_chanels = 8;
cameraOrbit_ = lightEnabled_ = true;
shaders_supported = selecting_ = customMouseMove_ = false;
sel_button = Qt::LeftButton;
sel_mod = Qt::NoModifier;
renderer_ = nullptr;
fps_cnt = 0;
fps_tm = fps_ = 0.;
sel_obj = hov_obj = nullptr;
fogDensity_ = fogEnd_ = 1.;
fogStart_ = 0.;
fogMode_ = Exp;
hoverHaloFill_ = 0.333f;
selectionHaloFill_ = 0.5f;
//lmode = Simple;
shader_select = shader_halo = nullptr;
setFeature(qglMSAA, false);
setFeature(qglFXAA, false);
setFeature(qglLinearFiltering, true);
setFeature(qglAnisotropicLevel, 8);
setFeature(qglHDR, false);
setFeature(qglEyeAccomodationEnabled, false);
setFeature(qglEyeAccomodationTime, 16.);
setFeature(qglEyeAccomodationMaxSpeed, 0.2);
setFeature(qglBloomEnabled, false);
setFeature(qglBloomThreshold, 0.9);
setFeature(qglBloomFactor, 1.);
setFeature(qglBloomRadius, 8);
setFeature(qglMotionBlurEnabled, false);
setFeature(qglMotionBlurFactor, 1.);
setFeature(qglMotionBlurSteps, 8);
setFeature(qglShadowsEnabled, false);
setFeature(qglShadowsMapSize, 512);
setFeature(qglShadowsSoftEnabled, true);
setFeature(qglReflectionsEnabled, false);
setFeature(qglReflectionsBlur, true);
setFeature(qglSSAOEnabled, false);
setFeature(qglSSAORadius, 5);
setFeature(qglDepthOfFieldEnabled, false);
setFeature(qglDepthOfFieldAutoFocusEnabled, true);
setFeature(qglDepthOfFieldAutoFocusSpeed, 0.1);
setFeature(qglDepthOfFieldFocus, 1.);
setFeature(qglDepthOfFieldDiaphragm, 8.);
mouse_first = mouseSelect_ = hoverHalo_ = selectionHalo_ = true;
mouseRotate_ = true;
fogEnabled_ = is_init = grabMouse_ = shaders_bind = changed_ = false;
rmode = GLObjectBase::Fill;
sel_mode = QGLView::SingleSelection;
// sel_pen = QPen(Qt::black, 1, Qt::DashLine);
// sel_brush = QBrush(QColor(170, 100, 255, 120));
camera()->setAim(QVector3D());
camera()->setPos(QVector3D(2, 2, 2));
camera()->setName("Camera");
addObject(camera());
emit cameraPosChanged(camera()->pos());
//camera().aim_ = camera().pos_;
ktm_.restart();
}
QGLView::~QGLView() {
stop();
if (shader_select) delete shader_select;
if (shader_halo) delete shader_halo;
deleting_ = true;
}
void QGLView::stop() {
if (timer) killTimer(timer);
timer = 0;
}
void QGLView::start(float freq) {
stop();
timer = startTimer(freq <= 0.f ? 0 : int(1000.f / freq));
}
GLRendererBase * QGLView::renderer() {
return renderer_;
}
void QGLView::setRenderer(GLRendererBase * r, GLRendererBase ** prev) {
if (prev != nullptr) *prev = renderer_;
renderer_ = r;
}
void QGLView::addObject(GLObjectBase * o) {
objects_.addChild(o);
o->setView(this);
collectLights();
QList<GLObjectBase*> cl = o->children(true);
cl << o;
foreach (GLObjectBase * i, cl) {
emit objectAdded(i);
}
if (is_init) {
o->init();
}
}
int QGLView::objectsCount(bool all) {
if (!all) return objects_.childCount();
int cnt = 0;
objectsCountInternal(&cnt, &objects_);
return cnt;
}
void QGLView::removeObject(GLObjectBase * o, bool inChildren) {
o->setView(nullptr);
if (inChildren)
removeObjectInternal(o, &objects_);
else
objects_.removeChild(o);
objectDeleted(o);
}
void QGLView::removeObject(GLObjectBase & o, bool inChildren) {
removeObject(&o, inChildren);
}
void QGLView::clearObjects(bool deleteAll) {
removeObject(camera_);
objects_.clearChildren(deleteAll);
addObject(camera());
selectObject(nullptr);
hov_obj = nullptr;
}
QList<GLObjectBase *> QGLView::objects(bool all) {
return objects_.children(all);
}
int QGLView::lightsCount() const {
return lights_.size();
}
void QGLView::removeLight(int index) {
removeObject(lights_.at(index));
lights_.removeAt(index);
}
void QGLView::removeLight(Light * l) {
foreach (Light * i, lights_)
if (i == l) removeObject(i);
lights_.removeAll(l);
}
void QGLView::clearLights(bool deleteAll) {
if (deleteAll)
foreach (Light * i, lights_) delete i;
lights_.clear();
}
void QGLView::addTexture(const QString & path) {
textures_manager->addTexture(path);
}
void QGLView::addAnimation(const QString & dir, const QString & name) {
textures_manager->addAnimation(dir, name);
}
Light * QGLView::light(int index) {
return lights_[index];
}
Light * QGLView::light(const QString & name) {
foreach (Light * i, lights_)
if (i->name_ == name) return i;
return nullptr;
}
void QGLView::selectObject(GLObjectBase * o) {
if (o == sel_obj) return;
GLObjectBase * pso = sel_obj;
sel_obj = o;
emit selectionChanged(sel_obj, pso);
}
void QGLView::resizeEvent(QResizeEvent * e) {
renderLater();
}
void QGLView::timerEvent(QTimerEvent *) {
renderNow();
if (ktm_.elapsed() < QApplication::keyboardInputInterval()) return;
Qt::KeyboardModifiers km = QApplication::keyboardModifiers();
foreach (int i, keys_)
emit keyEvent((Qt::Key)i, km);
}
void QGLView::render() {
if (!isVisible()) return;
resizeGL(width(), height());
QRect g_rect(QPoint(), size());
emit glBeforePaint();
//qDebug() << "paintGL";
//QMutexLocker ml_v(&v_mutex);
glEnable(GL_CULL_FACE);
//glDisable(GL_CULL_FACE);
camera()->apply(aspect);
//objects_.preparePos(camera());
start_rp.cam_offset_matrix = camera()->offsetMatrix();
start_rp.proj_matrix = getGLMatrix(GL_PROJECTION_MATRIX);
start_rp.view_matrix = getGLMatrix(GL_MODELVIEW_MATRIX);
//objects_.buildTransform();
/// Selection detect
//glClearFramebuffer(QColor(100, 0, 0, 0));
if (mouseSelect_) {
glReleaseTextures();
glEnableDepth();
glDisable(GL_TEXTURE_1D);
glDisable(GL_TEXTURE_2D);
glDisable(GL_TEXTURE_CUBE_MAP);
glDisable(GL_MULTISAMPLE);
glDisable(GL_LIGHTING);
glDisable(GL_BLEND);
glDisable(GL_ALPHA_TEST);
glDisable(GL_RESCALE_NORMAL);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
fbo_selection.bind();
fbo_selection.setWriteBuffer(0);
glClearFramebuffer(QColor(0, 0, 0, 0));
if (shaders_supported && shader_select->isLinked()) shader_select->bind();
renderSelection();
if (shaders_supported && shader_select->isLinked()) shader_select->release();
uchar cgid[4] = {0, 0, 0, 0};
uint iid = 0;
GLObjectBase * so = nullptr;
if (!g_rect.contains(lastPos)) {
if (hov_obj != nullptr) {
hov_obj = nullptr;
emit hoverChanged(nullptr, hov_obj);
}
} else {
glReadPixels(lastPos.x(), height() - lastPos.y(), 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, cgid);
iid = uint(cgid[0] << 24) | uint(cgid[1] << 16) | uint(cgid[2] << 8) | cgid[3];
so = ids.value(iid, nullptr);
//qDebug() <<cgid[0]<<cgid[1]<<cgid[2]<<cgid[3]<< iid;
if (so != hov_obj) {
emit hoverChanged(so, hov_obj);
hov_obj = so;
}
//if (so != 0) qDebug() << sel_obj->name() << cgid[3];
}
if (selectionHalo_ && sel_obj) {
fbo_selection.setWriteBuffer(2);
renderHalo(sel_obj, qHash((quint64)sel_obj), selectionHaloColor_, selectionHaloFill_);
}
if (hoverHalo_ && hov_obj) {
fbo_selection.setWriteBuffer(1);
renderHalo(hov_obj, iid, hoverHaloColor_, hoverHaloFill_);
}
fbo_selection.release();
glEnableDepth();
/*glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);*/
}
camera()->apply(aspect);
start_rp.cam_offset_matrix = camera()->offsetMatrix();
cur_mvpm = start_rp.proj_matrix * start_rp.view_matrix * start_rp.cam_offset_matrix;
//objects_.preparePos(camera());
static GLRendererBase * prev_rend = nullptr;
glShadeModel(GL_SMOOTH);
if (prev_rend != renderer_) {
prev_rend = renderer_;
if (renderer_ != nullptr) {
renderer_->init(width(), height());
renderer_->resize(width(), height());
renderer_->reloadShaders();
}
}
emit glBeginPaint();
if (renderer_ != nullptr) {
renderer_->rp.prepare();
renderer_->prepareScene();
renderer_->renderScene();
}
emit glPainting();
glUseProgram(0);
if (selectionHalo_ || hoverHalo_) {
glReleaseTextures();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
//glClearFramebuffer(Qt::black, false);
glActiveTexture(GL_TEXTURE0);
glEnable(GL_BLEND);
glDisable(GL_TEXTURE_CUBE_MAP);
glDisable(GL_LIGHTING);
glDisableDepth();
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
if (selectionHalo_ && sel_obj) {
glBindTexture(GL_TEXTURE_2D, fbo_selection.colorTexture(2));
//qDebug() << "draw sel";
glDrawQuad();
}
if (hoverHalo_ && hov_obj) {
glBindTexture(GL_TEXTURE_2D, fbo_selection.colorTexture(1));
//qDebug() << "draw hover";
//glBindTexture(GL_TEXTURE_2D, textures_manager->loadTexture("batt_pn.jpg"));
glDrawQuad();
}
}
glResetAllTransforms();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glUseProgram(0);
//glDisable(GL_BLEND);
//glDisable(GL_LIGHTING);
//glActiveTexture(GL_TEXTURE0);
//glBindTexture(GL_TEXTURE_2D, textures_manager->loadTexture("batt_pn.jpg"));
//glDrawQuad();
emit glEndPaint();
/*releaseShaders();
glActiveTextureChannel(0);
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glColor4f(0.3, 0.5, 0.8, 0.5);
glResetAllTransforms();
glBegin(GL_QUADS);
glTexCoord2f(0.f, 0.f); glVertex2f(-1.f, -1.f);
glTexCoord2f(1.f, 0.f); glVertex2f(1.f, -1.);
glTexCoord2f(1.f, 1.f); glVertex2f(1.f, 1.f);
glTexCoord2f(0.f, 1.f); glVertex2f(-1.f, 1.f);
glEnd();*/
/*
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glDisable(GL_LIGHTING);
glActiveTextureChannel(0);
glBindTexture(GL_TEXTURE_2D, fbo->texture());
glDisable(GL_DEPTH_TEST);
glBegin(GL_QUADS);
glColor3f(1.f, 1.f, 1.f);
glTexCoord2f(0.f, 0.f); glVertex2f(-1.f, -1.f);
glTexCoord2f(0.f, 1.f); glVertex2f(-1.f, 1.f);
glTexCoord2f(1.f, 1.f); glVertex2f(1.f, 1.f);
glTexCoord2f(1.f, 0.f); glVertex2f(1.f, -1.);
glEnd();
glEnable(GL_DEPTH_TEST);*/
fps_tm += time.elapsed();
time.restart();
fps_cnt++;
if (fps_tm < 1000.) return;
fps_ = fps_cnt / fps_tm * 1000.;
fps_tm = 0.;
fps_cnt = 0;
}
void QGLView::initialize() {
//initializeOpenGLFunctions();
glEnable(GL_TEXTURE_MAX_ANISOTROPY_EXT);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glEnableDepth();
glEnable(GL_CULL_FACE);
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
glActiveTexture(GL_TEXTURE0 + 3);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
glEnable(GL_TEXTURE_GEN_R);
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glActiveTexture(GL_TEXTURE0);
glShadeModel(GL_SMOOTH);
glCullFace(GL_BACK);
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT, GL_DIFFUSE);
textures_manager->loadTextures();
objects_.initInternal();
checkCaps();
shader_select = new QOpenGLShaderProgram(context());
shader_halo = new QOpenGLShaderProgram(context());
reloadThisShaders();
is_init = true;
//resizeGL(width(), height());
need_init_ = false;
emit glInitializeDone();
}
void QGLView::renderHalo(const GLObjectBase * obj, const uint iid, const QColor & color, const float & fill) {
if (!shaders_supported) return;
if (!shader_halo) return;
if (!shader_halo->isLinked()) return;
if (obj) {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, fbo_selection.colorTexture());
shader_halo->bind();
shader_halo->setUniformValue("qgl_ModelViewProjectionMatrix", QMatrix4x4());
shader_halo->setUniformValue("t0", 0);
shader_halo->setUniformValue("dt", QVector2D(1.f / width(), 1.f / height()));
shader_halo->setUniformValue("selected", QVector4D(float((iid >> 24) & 0xFF) / 255.f,
float((iid >> 16) & 0xFF) / 255.f,
float((iid >> 8) & 0xFF) / 255.f,
float( iid & 0xFF) / 255.f));
shader_halo->setUniformValue("color", color);
shader_halo->setUniformValue("fill", GLfloat(fill));
//qDebug() << "render halo" << iid << shader_halo->log() << shader_halo->programId();
glDisableDepth();
//glClearFramebuffer(color);
glDrawQuad(shader_halo);
glDepthMask(GL_TRUE);
//glFlush();
shader_halo->release();
} else {
glClearFramebuffer(Qt::black, false);
}
}
void QGLView::renderSelection() {
// cid = 1;
ids.clear();
if (shaders_supported) {
if (shader_select) {
if (shader_select->isLinked()) {
sh_id_loc = shader_select->uniformLocation("id");
shader_select->setUniformValue("z_far", GLfloat(depthEnd()));
shader_select->setUniformValue("z_near", GLfloat(depthStart()));
}
}
}
//qDebug() << sh_id_loc;
start_rp.view_matrix = getGLMatrix(GL_MODELVIEW_MATRIX);
glPushMatrix();
renderSingleSelection(objects_);
glPopMatrix();
}
void QGLView::renderSingleSelection(GLObjectBase & o) {
if (!o.isInit()) {
o.init();
o.loadTextures();
}
if (!o.visible_ || !o.select_) return;
QMatrix4x4 curview = start_rp.view_matrix * start_rp.cam_offset_matrix * o.itransform_;
uint id = qHash((quint64)&o);
ids.insert(id, &o);
glLineWidth(o.line_width > 0.f ? o.line_width : lineWidth_);
glPointSize(o.line_width > 0.f ? o.line_width : lineWidth_);
if (shaders_supported){
if (shader_select) {
if (shader_select->isLinked()) {
setUniformMatrices(shader_select, start_rp.proj_matrix, curview);
shader_select->setUniformValue(sh_id_loc, QVector4D(float((id >> 24) & 0xFF) / 255.f,
float((id >> 16) & 0xFF) / 255.f,
float((id >> 8) & 0xFF) / 255.f,
float(id & 0xFF) / 255.f));
}
}
} else {
setGLMatrix(curview);
glColor4f(float((id >> 24) & 0xFF) / 255.f,
float((id >> 16) & 0xFF) / 255.f,
float((id >> 8) & 0xFF) / 255.f,
float(id & 0xFF) / 255.f);
}
//qDebug() << o.name() << "assign to" << sh_id_loc << cid;
//glColor4f(float((cid >> 24) & 0xFF) / 255.f, float((cid >> 16) & 0xFF) / 255.f, float((cid >> 8) & 0xFF) / 255.f, float(cid & 0xFF) / 255.f);
// ++cid;
o.draw(nullptr, true);
foreach (GLObjectBase * i, o.children_)
renderSingleSelection(*i);
}
void QGLView::collectLights() {
lights_.clear();
collectObjectLights(&objects_);
}
void QGLView::objectDeleted(GLObjectBase * o) {
if (deleting_) return;
//qDebug() << "del" << o;
if (sel_obj == o) selectObject(nullptr);
if (hov_obj == o) hov_obj = nullptr;
collectLights();
}
void QGLView::collectObjectLights(GLObjectBase * o) {
if (o->type_ == GLObjectBase::glLight) {
lights_ << globject_cast<Light * >(o);
o->view_ = this;
}
foreach (GLObjectBase * i, o->children())
collectObjectLights(i);
}
void QGLView::objectsCountInternal(int * cnt, GLObjectBase * where) {
++(*cnt);
foreach (GLObjectBase * i, where->children_)
objectsCountInternal(cnt, i);
}
void QGLView::removeObjectInternal(GLObjectBase * o, GLObjectBase * where) {
foreach (GLObjectBase * i, where->children_) {
if (o == i)
where->removeChild(i);
else
removeObjectInternal(o, i);
objectDeleted(i);
}
}
void QGLView::checkCaps() {
glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &max_anisotropic);
//glGetIntegerv(GL_MAX_TEXTURE_UNITS, &max_texture_chanels);
//qDebug() << max_texture_chanels;
//qDebug() << max_texture_chanels;
shaders_supported = QOpenGLShaderProgram::hasOpenGLShaderPrograms();
}
void QGLView::reloadThisShaders() {
if (!shaders_supported) return;
loadShaders(shader_select, "selection", "://shaders");
loadShaders(shader_halo, "selection_halo", "://shaders");
//loadShaders(shader_rope, "rope", "://shaders");
}
void QGLView::glReleaseTextures(int channels) {
for (int i = channels - 1; i >= 0; --i) {
glActiveTexture(GL_TEXTURE0 + i);
glBindTexture(GL_TEXTURE_2D, 0);
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
}
}
void QGLView::applyFog() {
GLfloat fog_col[4] = {float(fogColor_.redF()), float(fogColor_.greenF()), float(fogColor_.blueF()), .0f};
if (fogEnabled_) {
glEnable(GL_FOG);
glFogf(GL_FOG_DENSITY, fogDensity_);
glFogf(GL_FOG_START, fogStart_);
glFogf(GL_FOG_END, fogEnd_);
glFogi(GL_FOG_MODE, fogMode_);
fog_col[0] = fogColor_.redF();
fog_col[1] = fogColor_.greenF();
fog_col[2] = fogColor_.blueF();
glFogfv(GL_FOG_COLOR, fog_col);
} else glDisable(GL_FOG);
}
void QGLView::resizeGL(int width, int height) {
if (!is_init) return;
if (width <= 0 || height <= 0) return;
if (prev_size == QSize(width, height)) return;
prev_size = QSize(width, height);
aspect = float(width) / float(height);
if (renderer_) renderer_->resize(width, height);
mouse_first = true;
//qDebug() << "resize" << width << height;
fbo_selection.resize(width, height);
iaspect = (aspect == 0.f) ? 0. : 1 / aspect;
glViewport(0, 0, width, height);
emit glResize(width, height);
}
void QGLView::mouseReleaseEvent(QMouseEvent * e) {
// qDebug() << "mouseReleaseEvent" << e << isActive();
// QGraphicsView::mouseReleaseEvent(e);
//setCursor(QCursor(Qt::ArrowCursor));
selecting_ = false;
if (mouseSelect_ && e->button() == Qt::LeftButton) {
if ((lastPos - downPos).manhattanLength() < 8) {
if (sel_obj != hov_obj)
selectObject(hov_obj);
}
}
emit glMouseReleaseEvent(e);
}
void QGLView::mousePressEvent(QMouseEvent * e) {
// qDebug() << "mousePressEvent" << e << isActive();
// QGraphicsView::mousePressEvent(e);
// mouseThis_ = (scene()->itemAt(mapToScene(e->pos()) , QTransform() ) == 0);
selecting_ = false;
if (!QRect(QPoint(), size()).contains(e->pos())) return;
/// TODO select by rect
//if (e->button() == sel_button && e->modifiers() == sel_mod)
// selecting_ = true;
lastPos = e->pos();
downPos = lastPos;
//qDebug() << mouseThis_;
emit glMousePressEvent(e);
}
void QGLView::mouseMoveEvent(QMouseEvent * e) {
// qDebug() << "mouseMoveEvent" << e << isActive();
// QGraphicsView::mouseMoveEvent(e);
//lastPos = e->pos();
if (selecting_) {
return;
}
// if (!QRect(QPoint(), size()).contains(e->pos())) return;
//if (scene()->itemAt(mapToScene(e->pos())) != 0) return;
///qDebug() << e->x() << e->y();
QRect g_rect(QPoint(), size());
if (mouseRotate_) {
float dx = e->x() - lastPos.x();
float dy = e->y() - lastPos.y();
if (e->buttons() & Qt::LeftButton) {
//camera().angle_z += dx / 4.;
//camera().angle_xy += dy / 4.;
if (cameraOrbit_) {
camera()->orbitZ(dx / 4.f);
camera()->orbitXY(dy / 4.f);
} else {
camera()->rotateZ(dx / 4.f);
camera()->rotateXY(dy / 4.f);
}
emit cameraPosChanged(camera()->pos());
} else if (e->buttons() & Qt::RightButton) {
float ad = camera()->distance();
camera()->moveLeft(dx / 1000.f * ad);
camera()->moveUp(dy / 1000.f * ad);
//camera().pos.setX(camera().pos.x() + camera().pos.z() * dx / 500.);
//camera().pos.setY(camera().pos.y() - camera().pos.z() * dy / 500.);
emit cameraPosChanged(camera()->pos());
}
//lights[0]->pos_ = camera().pos();
}
if (customMouseMove_) emit customMouseMoveEvent(e->pos(), lastPos, e->buttons());
lastPos = e->pos();
if (grabMouse_) {
//if (!isrunning) return;
QCursor::setPos(mapToGlobal(QRect(QPoint(), size()).center()));
static bool mouse_sec = false;
if (mouse_sec) {
mouse_sec = false;
return;
}
if (mouse_first) {
mouse_first = false;
mouse_sec = true;
//qDebug() << "first" << e->pos();
return;
}
lastPos = g_rect.center();
int dx = e->x() - lastPos.x();
int dy = e->y() - lastPos.y();
emit glMouseMoveEvent(new QMouseEvent(QEvent::MouseMove, QPoint(dx, dy), e->button(), e->buttons(), e->modifiers()));
return;
}
emit glMouseMoveEvent(e);
}
void QGLView::wheelEvent(QWheelEvent * e) {
if (mouseRotate_) {
if (e->delta() > 0) camera()->flyCloser(0.1f); //camera().pos.setZ(camera().pos.z() - 0.1 * camera().pos.z());
if (e->delta() < 0) camera()->flyFarer(0.1f); //camera().pos.setZ(camera().pos.z() + 0.1 * camera().pos.z());
emit cameraPosChanged(camera()->pos());
}
emit glWheelEvent(e);
}
void QGLView::leaveEvent(QEvent * ) {
lastPos = QPoint(-1, -1);
//qDebug() << lastPos;
}
void QGLView::keyPressEvent(QKeyEvent * e) {
emit glKeyPressEvent(e);
if (e->key() > 0) keys_.insert(e->key());
if (e->key() == Qt::Key_F11) {
emit doubleClick();
}
}
void QGLView::keyReleaseEvent(QKeyEvent * e) {
emit glKeyReleaseEvent(e);
keys_.remove(e->key());
}
void QGLView::focusOutEvent(QFocusEvent *) {
keys_.clear();
}
void QGLView::mouseDoubleClickEvent(QMouseEvent * e) {
if (e->buttons().testFlag(Qt::MidButton))
emit doubleClick();
}
QByteArray QGLView::saveCamera() {
ChunkStream cs;
const Camera * c = camera();
cs.add(1, c->posX());
cs.add(2, c->posY());
cs.add(3, c->posZ());
cs.add(4, c->aim().x());
cs.add(5, c->aim().y());
cs.add(6, c->aim().z());
cs.add(7, c->angleZ());
cs.add(8, c->angleXY());
cs.add(9, c->angleRoll());
cs.add(10, c->FOV());
return cs.data();
}
void QGLView::restoreCamera(const QByteArray &ba) {
if (ba.isEmpty()) return;
ChunkStream cs(ba);
QVector3D pos, aim, ang;
while (!cs.atEnd()) {
switch (cs.read()) {
case 1: pos.setX(cs.getData<float>()); break;
case 2: pos.setY(cs.getData<float>()); break;
case 3: pos.setZ(cs.getData<float>()); break;
case 4: aim.setX(cs.getData<float>()); break;
case 5: aim.setY(cs.getData<float>()); break;
case 6: aim.setZ(cs.getData<float>()); break;
case 7: ang.setZ(cs.getData<float>()); break;
case 8: ang.setY(cs.getData<float>()); break;
case 9: ang.setX(cs.getData<float>()); break;
case 10: setFOV(cs.getData<float>()); break;
default: break;
}
}
camera()->setPos(pos);
camera()->setAim(aim);
camera()->setAngles(ang);
}
QByteArray QGLView::saveFeatures() {
QByteArray ba;
QDataStream ds(&ba, QIODevice::WriteOnly);
ds << features_;
return ba;
}
void QGLView::restoreFeatures(const QByteArray & ba) {
QHash<int, QVariant> f;
QDataStream ds(ba);
ds >> f;
features_ = f;
}

Some files were not shown because too many files have changed in this diff Show More