git-svn-id: svn://db.shs.com.ru/libs@586 a8b55f48-bf90-11e4-a774-851b48703e85

This commit is contained in:
2019-09-02 14:08:38 +00:00
parent f862381b68
commit 3d06d2095e
929 changed files with 66799 additions and 0 deletions

118
test/qad/CMakeLists.txt Normal file
View File

@@ -0,0 +1,118 @@
project(qad)
cmake_minimum_required(VERSION 2.6)
if (POLICY CMP0017)
cmake_policy(SET CMP0017 NEW)
endif()
if (NOT LIBPROJECT)
option(LIB "System install" 1)
option(DEBUG "Build with -g3" 0)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -Wall")
if (DEBUG)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3")
endif ()
endif()
if (NOT DEFINED ANDROID_PLATFORM)
find_package(OpenGL REQUIRED)
endif()
if (MINGW)
find_package(MinGW REQUIRED)
endif()
if (NOT LIBPROJECT)
if (LIB)
if (WIN32)
set(CMAKE_INSTALL_PREFIX ${MINGW_DIR})
else()
if(APPLE)
set(CMAKE_INSTALL_PREFIX /usr/local)
else()
if (DEFINED ANDROID_PLATFORM)
set(CMAKE_INSTALL_PREFIX ${ANDROID_SYSTEM_LIBRARY_PATH}/usr)
else()
set(CMAKE_INSTALL_PREFIX /usr)
endif()
endif()
endif()
message(STATUS "Install ${PROJECT_NAME} to system \"${CMAKE_INSTALL_PREFIX}\"")
else()
message(STATUS "Install ${PROJECT_NAME} to local \"bin\"")
endif()
endif()
set(CMAKES "FindQAD.cmake" "QtWraps.cmake")
install(FILES ${CMAKES} DESTINATION ${CMAKE_ROOT}/Modules)
macro(qad_install _TARGET _H_FILES _QM_FILES)
#message("qad_install ${_TARGET} ${_QM_FILES}")
if (LIBPROJECT)
sdk_install("qad" "${_TARGET}" "${_H_FILES}" "${_QM_FILES}")
else()
if (LIB)
if (WIN32)
if(NOT "x${_H_FILES}" STREQUAL "x")
#message("HFILES ${_H_FILES}")
install(FILES ${_H_FILES} DESTINATION ${MINGW_INCLUDE}/${_DIR})
endif()
qt_install(TARGETS ${_TARGET} DESTINATION ${MINGW_LIB})
qt_install(TARGETS ${_TARGET} DESTINATION ${MINGW_BIN})
qt_install(TARGETS ${_TARGET} DESTINATION QtBin)
qt_install(FILES "${_QM_FILES}" DESTINATION QtLang)
else()
if(NOT _H_FILES STREQUAL "")
install(FILES ${_H_FILES} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/qad)
endif()
qt_install(TARGETS ${_TARGET} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib)
endif()
else()
qt_install(TARGETS ${_TARGET} DESTINATION bin)
endif()
endif()
endmacro()
macro(qad_plugin NAME _MODULES _LIBS)
set(PROJ_NAME qad_${NAME}_plugin)
include_directories("..")
#message(${_${NAME}_PLUGIN_LIBS})
add_definitions(-DQT_PLUGIN)
add_definitions(-DQT_NO_DEBUG)
add_definitions(-DQT_SHARED)
add_definitions(-DQDESIGNER_EXPORT_WIDGETS)
find_qt(${QtVersions} Core Designer ${_MODULES})
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_install(TARGETS ${PROJ_NAME} DESTINATION QtPlugins/designer)
endmacro()
macro(qad_project NAME _MODULES _LIBS)
set(PROJ_NAME qad_${NAME})
find_qt(${QtVersions} Core ${_MODULES})
qt_sources(SRC)
qt_wrap(${SRC} HDRS out_HDR CPPS out_CPP QMS ${PROJ_NAME}_QM)
qt_add_library(${PROJ_NAME} SHARED out_CPP)
qt_target_link_libraries(${PROJ_NAME} ${_LIBS})
qad_install(${PROJ_NAME} "${out_HDR}" ${PROJ_NAME}_QM)
set(${NAME}_UTILS 1)
if (LIBPROJECT)
set(${NAME}_UTILS ${UTILS})
endif()
message(STATUS "Building ${PROJ_NAME}")
if (NOT DEFINED ANDROID_PLATFORM)
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/plugin")
set(_${NAME}_PLUGIN_LIBS "${_LIBS}")
add_subdirectory(plugin)
endif()
endif()
endmacro()
set(DIRS utils widgets application blockview graphic sql_table touch_widgets)
foreach(D ${DIRS})
list(APPEND QT_MULTILIB_LIST qad_${D})
endforeach(D)
set(QT_MULTILIB_LIST ${QT_MULTILIB_LIST} PARENT_SCOPE)
foreach(D ${DIRS})
include_directories(${D})
add_subdirectory(${D})
endforeach(D)

63
test/qad/FindQAD.cmake Normal file
View File

@@ -0,0 +1,63 @@
if (POLICY CMP0017)
cmake_policy(SET CMP0017 NEW)
endif()
if (POLICY CMP0011)
cmake_policy(SET CMP0011 NEW)
endif()
if(NOT LIBPROJECT)
include(QtWraps)
endif()
get_directory_property(hasParent PARENT_DIRECTORY)
set(_SEARCH_DIR)
if(WIN32)
find_package(MinGW REQUIRED)
endif()
if(APPLE)
include_directories(/usr/local/include)
link_directories(/usr/local/lib)
endif()
find_file(QAD_H_INCLUDE "qad_types.h" HINTS ${PIP_DIR}/include/qad ${MINGW_INCLUDE}/qad /usr/include/qad /usr/local/include/qad $ENV{SMSDK_DIR}/include/qad)
if (DEFINED ANDROID_PLATFORM)
set(QAD_INCLUDES ${ANDROID_SYSTEM_LIBRARY_PATH}/usr/include/qad)
else()
get_filename_component(QAD_INCLUDES ${QAD_H_INCLUDE} PATH)
endif()
set(_SEARCH_DIR ${MINGW_LIB} /usr/lib /usr/local/lib $ENV{SMSDK_DIR}/lib)
set(_QAD_LIBS utils widgets application blockview graphic sql_table touch_widgets)
if(LIBPROJECT)
set(QAD_INCLUDES)
endif()
foreach(_Q ${_QAD_LIBS})
string(TOUPPER ${_Q} _QU)
if(LIBPROJECT)
set(QAD_${_QU}_LIBRARY qad_${_Q})
list(APPEND QAD_INCLUDES ${QAD_DIR}/${_Q})
else()
foreach(_v ${_QT_VERSIONS_})
find_library(QAD${_v}_${_QU}_LIBRARY qad_${_Q}${_v} ${_SEARCH_DIR})
set(MULTILIB_${_Q}_SUFFIX_Qt${_v} ${_v})
if(hasParent)
set(MULTILIB_${_Q}_SUFFIX_Qt${_v} ${_v} PARENT_SCOPE)
endif()
endforeach()
endif()
#message(STATUS "Library ${_Q} (${_QU}) -> ${QAD_${_QU}_LIBRARY} found in ${_SEARCH_DIR}")
list(APPEND QT_MULTILIB_LIST qad_${_Q})
endforeach()
list(APPEND QT_MULTILIB_LIST qglview)
foreach(_v ${_QT_VERSIONS_})
find_library(QGLVIEW${_v}_LIBRARY qglview${_v} ${_SEARCH_DIR})
set(MULTILIB_qglview_SUFFIX_Qt${_v} ${_v})
if(hasParent)
set(MULTILIB_qglview_SUFFIX_Qt${_v} ${_v} PARENT_SCOPE)
endif()
endforeach()
if(hasParent)
set(QT_MULTILIB_LIST ${QT_MULTILIB_LIST} PARENT_SCOPE)
endif()
if(NOT LIBPROJECT)
if (NOT _QAD_MSG)
set(_QAD_MSG 1 CACHE BOOL "msg_qad" FORCE)
message(STATUS "Found QAD")
endif()
endif()

1
test/qad/QADConfig.cmake Normal file
View File

@@ -0,0 +1 @@
include(${QAD_DIR}/FindQAD.cmake)

519
test/qad/QtWraps.cmake Normal file
View File

@@ -0,0 +1,519 @@
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 "")
# usage: find_qt([<Module1> <Module2> ...] [Qt4] [Qt5])
# find Qt4 or/and Qt5 packages
# if Qt4/5 found, set
# * Qt<4/5>_BIN var to Qt binary dir
# * Qt<4/5>_PLUGINS_DIR var to Qt plugins dir
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}_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)
endif()
endif()
if (_NEED5)
#set(_MSG 1)
#if (Qt5_FOUND)
# set(_MSG 0)
#endif()
find_package(Qt5 COMPONENTS LinguistTools UiPlugin Widgets ${_QCOMP} ${_QUIET})
if (Qt5_FOUND)
set(LOCAL_FOUND5 1)
set(_Qt5Modules)
foreach(m ${_QCOMP})
if (${Qt5${m}_FOUND})
list(APPEND _Qt5Modules ${m})
list(APPEND Qt5_INCLUDES ${Qt5${m}_INCLUDE_DIRS})
list(APPEND Qt5_LIBRARIES ${Qt5${m}_LIBRARIES})
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} (found version \"${Qt5_VERSION}\")")
set(_QT5_MSG 1 CACHE BOOL "msg_qt5" FORCE)
#message(STATUS "Found Qt5 modules: ${_Qt5Modules}")
endif()
endif()
endif()
# set()
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()
# usage: 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
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)
else()
if ("x${_i}" STREQUAL "xDIR")
set(_IS_DIR 1)
else()
if ("x${_i}" STREQUAL "xNO_DEFAULT")
set(_NO_DEFAULT 1)
else()
list(APPEND _REGEXP ${_i})
endif()
endif()
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()
# usage: 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
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)
else()
if (_CPP_ARG)
set(CPP_VAR ${_i})
set(WAS_CPP_ARG 1)
set(_CPP_ARG 0)
else()
if (_QM_ARG)
set(QM_VAR ${_i})
set(WAS_QM_ARG 1)
set(_QM_ARG 0)
else()
if ("x${_i}" STREQUAL "xHDRS")
set(_HDR_ARG 1)
else()
if ("x${_i}" STREQUAL "xCPPS")
set(_CPP_ARG 1)
else()
if ("x${_i}" STREQUAL "xQMS")
set(_QM_ARG 1)
else()
list(APPEND FILE_LIST "${_i}")
endif()
endif()
endif()
endif()
endif()
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()
else()
if (${_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()
endif()
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}})
else()
if (("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})
else()
if ("x${${_i}}" STREQUAL "x")
list(APPEND ${_A} ${_i})
else()
list(APPEND ${_A} ${${_i}})
endif()
endif()
endif()
endforeach()
endmacro()
# usage: 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
macro(qt_add_executable _NAME)
foreach(_v ${_QT_VERSIONS_})
if (LOCAL_FOUND${_v})
_qt_split_add_args(_PREF _ARGS ${ARGN})
#message("${_PREF}")
#message("${_ARGS}")
set(_TARGET ${_NAME}${TARGET_SUFFIX_Qt${_v}})
add_executable(${_TARGET} ${_PREF} ${_ARGS})
set(_${_NAME}_is_qt 1)
target_include_directories(${_TARGET} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/qt${_v} ${Qt${_v}_INCLUDES})
### add_definitions(${Qt5Widgets_DEFINITIONS})
### target_compile_definitions(${_TARGET} PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/qt${_v} ${Qt${_v}_INCLUDES})
#message("add exe: \"${_TARGET}\", \"${_PREF}\"")
endif()
endforeach()
endmacro()
# usage: 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
macro(qt_add_library _NAME)
foreach(_v ${_QT_VERSIONS_})
if (LOCAL_FOUND${_v})
_qt_split_add_args(_PREF _ARGS ${ARGN})
#message("${_PREF}")
#message("${_ARGS}")
set(_TARGET ${_NAME}${TARGET_SUFFIX_Qt${_v}})
add_library(${_TARGET} ${_PREF} ${_ARGS})
set(_${_NAME}_is_qt 1)
target_include_directories(${_TARGET} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/qt${_v} ${Qt${_v}_INCLUDES})
#message("add lib: \"${_TARGET}\"")
endif()
endforeach()
endmacro()
macro(_qt_multitarget_suffix_ _OUT _IN _v)
if (NOT "x${MULTILIB_${_IN}_SUFFIX_Qt${_v}}" STREQUAL "x")
set(${_OUT} "${MULTILIB_${_IN}_SUFFIX_Qt${_v}}")
else()
set(${_OUT} "${MULTILIB_SUFFIX_Qt${_v}}")
endif()
endmacro()
# usage: qt_target_link_libraries(<target> ... <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?>
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})
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()
# usage: 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
macro(qt_install)
set(_prev_inst)
#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)
if (_${_i}_is_qt)
set(_INST_LIST ${_INST_LIST} ${_i}${TARGET_SUFFIX_Qt${_v}})
else()
set(_INST_LIST ${_INST_LIST} ${_i})
endif()
else()
if (_IS_FILES)
set(_IS_FILES 0)
if (_IS_LANG)
if (("x${${_i}_Qt${_v}}" STREQUAL "x") OR ("x${_i}" STREQUAL "xDESTINATION"))
#return()
set(_INVALID 1)
else()
set(_INST_LIST ${_INST_LIST} ${${_i}_Qt${_v}})
endif()
else()
set(_INST_LIST ${_INST_LIST} ${_i})
endif()
else()
if (_IS_DEST)
set(_IS_DEST 0)
if ("x${_i}" STREQUAL "xQtBin")
set(_INST_LIST ${_INST_LIST} "${Qt${_v}_BIN}")
else()
if ("x${_i}" STREQUAL "xQtLang")
set(_INST_LIST ${_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}")
set(_INST_LIST ${_INST_LIST} "${_o}")
else()
set(_INST_LIST ${_INST_LIST} ${_i})
endif()
endif()
endif()
else()
set(_INST_LIST ${_INST_LIST} ${_i})
if ("x${_i}" STREQUAL "xTARGETS")
set(_IS_TARGET 1)
else()
if ("x${_i}" STREQUAL "xFILES")
set(_IS_FILES 1)
else()
if ("x${_i}" STREQUAL "xDESTINATION")
set(_IS_DEST 1)
endif()
endif()
endif()
endif()
endif()
endif()
endforeach()
if (NOT _INVALID)
if (NOT ("x${_prev_inst}" STREQUAL "x${_INST_LIST}"))
#message("install: ${_INST_LIST}")
install(${_INST_LIST})
set(_prev_inst "${_INST_LIST}")
endif()
endif()
endif()
endforeach()
endmacro()

View File

@@ -0,0 +1 @@
qad_project(application "Gui;Widgets" "qad_widgets")

View File

@@ -0,0 +1,96 @@
#include "edockwidget.h"
#include "qad_types.h"
#include <QEvent>
#include <QStyle>
void EDockWidget::setFeatures(QDockWidget::DockWidgetFeatures features) {
btn_dock->setVisible(features.testFlag(DockWidgetFloatable));
btn_hide->setVisible(features.testFlag(DockWidgetClosable));
QDockWidget::setFeatures(features);
}
void EDockWidget::setWindowTitle(const QString & title) {
lbl_title->setText(title);
QDockWidget::setWindowTitle(title);
}
void EDockWidget::setWindowIcon(const QIcon & icon) {
//#ifndef Q_OS_MACOS
lbl_icon->setPixmap(icon.pixmap(QSize(256, 256)));
QDockWidget::setWindowIcon(icon);
if (!icon.isNull()) {
lbl_icon->setScaledContents(true);
lbl_icon->setFixedSize(preferredIconSize(1.5, this));
}
//#endif
}
bool EDockWidget::event(QEvent * e) {
if (e->type() == QEvent::FontChange || e->type() == QEvent::Polish) {
updateStyle();
}
return QDockWidget::event(e);
}
void EDockWidget::init() {
header = new QFrame();
header->setFrameShape(QFrame::StyledPanel);
QBoxLayout * lay = new QBoxLayout(features().testFlag(QDockWidget::DockWidgetVerticalTitleBar) ? QBoxLayout::TopToBottom : QBoxLayout::LeftToRight);
lay->setContentsMargins(2, 2, 2, 2);
lay->setSpacing(2);
lbl_icon = new QLabel();
//#ifndef Q_OS_MACOS
QIcon wi = windowIcon();
if (!wi.isNull()) {
lbl_icon->setPixmap(wi.pixmap(QSize(256,256)));
/*#if QT_VERSION >= 0x500000
if (lbl_icon->pixmap())
const_cast<QPixmap*>(lbl_icon->pixmap())->setDevicePixelRatio(1.);
#endif*/
//qDebug() << windowTitle() << wi.pixmap(QSize(256,256)).size();
lbl_icon->setScaledContents(true);
}
lbl_icon->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
//#endif
lbl_title = new QLabel(windowTitle());
lbl_title->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
btn_dock = new QToolButton();
//btn_dock->setIconSize(QSize(16, 16));
btn_dock->setAutoRaise(true);
btn_dock->setFocusPolicy(Qt::NoFocus);
btn_dock->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
btn_hide = new QToolButton();
//btn_hide->setIconSize(QSize(16, 16));
btn_hide->setAutoRaise(true);
btn_hide->setFocusPolicy(Qt::NoFocus);
btn_hide->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
connect(btn_dock, SIGNAL(clicked(bool)), this, SLOT(dockClicked()));
connect(btn_hide, SIGNAL(clicked(bool)), this, SLOT(hide()));
lay->addWidget(lbl_icon);
lay->addWidget(lbl_title);
lay->addWidget(btn_dock);
lay->addWidget(btn_hide);
header->setLayout(lay);
updateStyle();
setTitleBarWidget(header);
}
void EDockWidget::updateStyle() {
QSize icon_size = preferredIconSize(0.75, this);
int bm = 2 * style()->pixelMetric(QStyle::PM_DockWidgetTitleBarButtonMargin, 0, this);
QSize btn_size = icon_size;
btn_size += QSize(bm, bm);
btn_dock->setIcon(style()->standardIcon(QStyle::SP_TitleBarNormalButton));
btn_dock->setIconSize(icon_size);
btn_dock->setFixedSize(btn_size);
btn_hide->setIcon(style()->standardIcon(QStyle::SP_TitleBarCloseButton));
btn_hide->setIconSize(icon_size);
btn_hide->setFixedSize(btn_size);
lbl_icon->setFixedSize(preferredIconSize(1.5, this));
}

View File

@@ -0,0 +1,39 @@
#ifndef EDOCKWIDGET_H
#define EDOCKWIDGET_H
#include <QDockWidget>
#include <QLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QIcon>
#include <QToolButton>
#include <QDebug>
class EDockWidget: public QDockWidget
{
Q_OBJECT
public:
explicit EDockWidget(const QString & title, QWidget * parent = 0, Qt::WindowFlags flags = 0): QDockWidget(title, parent, flags) {init();}
explicit EDockWidget(QWidget * parent = 0, Qt::WindowFlags flags = 0): QDockWidget(parent, flags) {init();}
~EDockWidget() {delete btn_hide; delete btn_dock; delete lbl_title; delete lbl_icon; delete header;}
void setFeatures(QDockWidget::DockWidgetFeatures features);
void setWindowTitle(const QString & title);
void setWindowIcon(const QIcon & icon);
private:
bool event(QEvent * e);
void init();
void updateStyle();
QFrame * header;
QLabel * lbl_title, * lbl_icon;
QToolButton * btn_hide, * btn_dock;
private slots:
void dockClicked() {setFloating(!isFloating());}
};
#endif // EDOCKWIDGET_H

View File

@@ -0,0 +1,423 @@
#include "emainwindow.h"
#include <QFileDialog>
#include <QMessageBox>
#include <QMenu>
#include <QLabel>
EMainWindow::EMainWindow(QWidget * parent): QMainWindow(parent), action_show_all_tools(this), action_hide_all_tools(this),
action_show_all_docks(this), action_hide_all_docks(this), first_show(true) {
tid = 0;
menu_recent = 0;
action_clear_recent = new QAction(QIcon(":/icons/edit-clear.png"), tr("Clear recent list"), this);
connect(action_clear_recent, SIGNAL(triggered()), this, SLOT(clearRecent()));
qRegisterMetaType<Qt::DockWidgetArea>("Qt::DockWidgetArea");
action_show_all_tools.setText(trUtf8("Show all"));
action_show_all_docks.setText(trUtf8("Show all"));
action_hide_all_tools.setText(trUtf8("Hide all"));
action_hide_all_docks.setText(trUtf8("Hide all"));
action_show_all_tools.setIcon(QIcon(":/icons/layer-visible-on.png"));
action_show_all_docks.setIcon(QIcon(":/icons/layer-visible-on.png"));
action_hide_all_tools.setIcon(QIcon(":/icons/layer-visible-off.png"));
action_hide_all_docks.setIcon(QIcon(":/icons/layer-visible-off.png"));
max_recent = 8;
setChanged(false);
initMenus();
initSession();
tid = startTimer(200); // bad timer, too much overload
}
EMainWindow::~EMainWindow() {
if (tid > 0) killTimer(tid);
tid = 0;
saveSession();
}
void EMainWindow::setRecentFiles(const QStringList & rl) {
clearRecent();
for (int i = rl.size() - 1; i >= 0; --i)
addToRecent(rl[i]);
}
QStringList EMainWindow::recentFiles() const {
QStringList ret;
foreach (QAction * a, actions_recent)
ret << a->data().toString();
return ret;
}
void EMainWindow::setRecentMenu(QMenu * m) {
menu_recent = m;
prepareRecent();
}
void EMainWindow::showEvent(QShowEvent * e) {
QWidget::showEvent(e);
initMenus();
if (!first_show) return;
first_show = false;
QList<QDockWidget * > docks(findChildren<QDockWidget * >());
foreach (QDockWidget * d, docks) {
connect(d, SIGNAL(dockLocationChanged(Qt::DockWidgetArea)), this, SLOT(changedDock()));
connect(d, SIGNAL(topLevelChanged(bool)), this, SLOT(changedDock()));
}
changedDock();
}
void EMainWindow::closeEvent(QCloseEvent * e) {
if (!checkSave()) e->ignore();
}
bool EMainWindow::eventFilter(QObject * o, QEvent * e) {
//qDebug() << o << e;
if (tbars.contains((QTabBar*)o) && e->type() == QEvent::MouseButtonDblClick) {
int tab = ((QTabBar*)o)->tabAt(((QMouseEvent * )e)->pos());
if (tab >= 0) {
QDockWidget * dock = (QDockWidget * )(((QTabBar*)o)->tabData(tab).toULongLong());
if (dock != 0) {
dock->setFloating(true);
}
}
}
if (e->type() == QEvent::Show || e->type() == QEvent::Hide || e->type() == QEvent::ChildAdded || e->type() == QEvent::ChildRemoved || e->type() == QEvent::MouseButtonPress) {
if (tbars.contains((QTabBar*)o) || tdocks.contains((QDockWidget*)o)) {
if (e->type() == QEvent::MouseButtonPress) {
if (((QMouseEvent*)e)->button() == Qt::RightButton) {
bool popup = tbars.contains((QTabBar*)o);
if (tdocks.contains((QDockWidget*)o))
popup = popup || ((QDockWidget*)o)->titleBarWidget()->geometry().contains(((QMouseEvent*)e)->pos());
if (popup) {
createPopupMenu()->popup(((QMouseEvent*)e)->globalPos());
return true;
}
}
}
if (e->type() == QEvent::Show || e->type() == QEvent::Hide /*|| e->type() == QEvent::ChildAdded || e->type() == QEvent::ChildRemoved*/) {
//qDebug() << "filter";
//QMetaObject::invokeMethod(this, "changedDock", Qt::QueuedConnection);
changedDock();
}
}
}
return QMainWindow::eventFilter(o, e);
}
void EMainWindow::timerEvent(QTimerEvent * e) {
if (e->timerId() == tid) {
changedDock();
return;
}
QMainWindow::timerEvent(e);
}
QMenu * EMainWindow::createPopupMenu() {
QMenu * menuPopup = new QMenu;
QWidgetAction * wa;
QLabel * lbl;
QAction * a;
QFont f;
f.setBold(true);
// Toolbars
QList<QToolBar * > tools = findChildren<QToolBar * >();
if (!tools.isEmpty()) {
wa = new QWidgetAction(menuPopup);
lbl = new QLabel();
lbl->setFrameShape(QFrame::StyledPanel);
lbl->setFrameShadow(QFrame::Sunken);
lbl->setText(trUtf8("Toolbars"));
lbl->setFont(f);
lbl->setAlignment(Qt::AlignCenter);
wa->setDefaultWidget(lbl);
menuPopup->addAction(wa);
foreach (QToolBar * i, tools) {
if (i->property("ribbon").toBool()) continue;
a = new QAction(i->windowTitle(), menuPopup);
a->setCheckable(true);
a->setChecked(!i->isHidden());
a->setIcon(i->windowIcon());
connect(a, SIGNAL(toggled(bool)), i, SLOT(setVisible(bool)));
menuPopup->addAction(a);
}
menuPopup->addSeparator();
menuPopup->addAction(&action_show_all_tools);
menuPopup->addAction(&action_hide_all_tools);
}
// Docks
QList<QDockWidget * > docks = findChildren<QDockWidget * >();
if (!docks.isEmpty()) {
wa = new QWidgetAction(menuPopup);
lbl = new QLabel();
lbl->setFrameShape(QFrame::StyledPanel);
lbl->setFrameShadow(QFrame::Sunken);
lbl->setText(trUtf8("Docks"));
lbl->setFont(f);
lbl->setAlignment(Qt::AlignCenter);
wa->setDefaultWidget(lbl);
menuPopup->addAction(wa);
foreach (QDockWidget * i, docks) {
if (i->property("ribbon").toBool()) continue;
a = new QAction(i->windowTitle(), menuPopup);
a->setCheckable(true);
a->setChecked(!i->isHidden());
a->setIcon(i->windowIcon());
connect(a, SIGNAL(toggled(bool)), i, SLOT(setVisible(bool)));
menuPopup->addAction(a);
}
menuPopup->addSeparator();
menuPopup->addAction(&action_show_all_docks);
menuPopup->addAction(&action_hide_all_docks);
}
return menuPopup;
}
void EMainWindow::addToRecent(const QString & path) {
if (path.isEmpty()) return;
QFileInfo fi(path);
QString fp = fi.absoluteFilePath();
bool insert = true;
for (int i = 0; i < actions_recent.size(); ++i)
if (actions_recent[i]->data().toString() == fp) {
actions_recent.push_front(actions_recent.takeAt(i));
insert = false;
prepareRecent();
break;
}
if (!insert) return;
QAction * a = new QAction(this);
a->setData(fp);
connect(a, SIGNAL(triggered()), this, SLOT(recentTriggered()));
actions_recent.push_front(a);
while (actions_recent.size() > max_recent)
delete actions_recent.takeLast();
prepareRecent();
}
void EMainWindow::prepareRecent() {
for (int i = 0; i < actions_recent.size(); ++i) {
QAction * a = actions_recent[i];
a->setText(QString("&%1 - %2").arg(i + 1).arg(a->data().toString()));
}
if (!menu_recent) return;
menu_recent->clear();
menu_recent->addActions(actions_recent);
menu_recent->addSeparator();
menu_recent->addAction(action_clear_recent);
}
void EMainWindow::initMenus() {
action_show_all_tools.disconnect();
action_hide_all_tools.disconnect();
action_show_all_docks.disconnect();
action_hide_all_docks.disconnect();
QList<QToolBar * > tools = findChildren<QToolBar * >();
foreach (QToolBar * i, tools) {
if (i->property("ribbon").toBool()) continue;
i->toggleViewAction()->setIcon(i->windowIcon());
connect(&action_show_all_tools, SIGNAL(triggered(bool)), i, SLOT(show()));
connect(&action_hide_all_tools, SIGNAL(triggered(bool)), i, SLOT(hide()));
}
QList<QDockWidget * > docks = findChildren<QDockWidget * >();
foreach (QDockWidget * i, docks) {
if (i->property("ribbon").toBool()) continue;
i->toggleViewAction()->setIcon(i->windowIcon());
connect(&action_show_all_docks, SIGNAL(triggered(bool)), i, SLOT(show()));
connect(&action_hide_all_docks, SIGNAL(triggered(bool)), i, SLOT(hide()));
}
QList<QAction * > actions = findChildren<QAction * >();
foreach (QAction * i, actions)
i->setIconVisibleInMenu(true);
addActions(actions);
}
void EMainWindow::initSession() {
connect(&session, SIGNAL(loading(QPIConfig & )), this, SLOT(sessionLoading(QPIConfig & )));
connect(&session, SIGNAL(saving(QPIConfig & )), this, SLOT(sessionSaving(QPIConfig & )));
}
void EMainWindow::saveSession() {
session.save();
}
void EMainWindow::loadSession() {
session.load();
}
bool EMainWindow::checkSave() {
if (!isWindowModified()) return true;
return saveFile(true);
}
void EMainWindow::changedDock() {
if (isHidden()) return;
QList<QTabBar * > tabs(findChildren<QTabBar * >());
QList<QDockWidget * > docks = findChildren<QDockWidget * >();
// QSet<QDockWidget * > docks_tabs;
QDockWidget * dock;
// qDebug() << "### change";
foreach (QTabBar * t, tabs) {
if (!t->objectName().isEmpty() || t->isHidden()) continue;
if (!tbars.contains(t)) {
tbars << t;
connect(t, SIGNAL(tabCloseRequested(int)), this, SLOT(closeDock(int)));
t->installEventFilter(this);
#ifndef Q_OS_MACOS
t->setIconSize(dockTabsIconSize());
#endif
t->setTabsClosable(true);
}
// qDebug() << "tab" << t << t->count();
for (int i = 0; i < t->count(); ++i) {
dock = (QDockWidget * )t->tabData(i).toULongLong();
//qDebug() << i << t->tabData(i);
if (!docks.contains(dock)) continue;
#ifndef Q_OS_MACOS
t->setIconSize(dockTabsIconSize());
#endif
t->setTabIcon(i, dock->windowIcon());
// docks_tabs << dock;
}
}
foreach (QDockWidget * d, docks) {
if (d->titleBarWidget() == 0) continue;
QWidget * ctb = d->titleBarWidget();
if (!d->property("__titleWidget").isValid()) {
d->setProperty("__titleWidget", qulonglong(ctb));
QWidget * ntb = new QWidget();
int m = style()->pixelMetric(QStyle::PM_DockWidgetTitleMargin);
ntb->setLayout(new QBoxLayout(QBoxLayout::BottomToTop));
ntb->layout()->setContentsMargins(m, m, 0, 0);
d->setProperty("__titleEmptyWidget", qulonglong(ntb));
}
if (!tdocks.contains(d)) {
tdocks << d;
// qDebug() << "connect" << d;
// connect(d, SIGNAL(destroyed(QObject*)), this, SLOT(changedDockClose(QObject*)), Qt::UniqueConnection);
d->installEventFilter(this);
}
//d->titleBarWidget()->setHidden(docks_tabs.contains(d));
if (tabifiedDockWidgets(d).isEmpty()) {
if (d->titleBarWidget() != (QWidget * )(d->property("__titleWidget").toULongLong()))
d->setTitleBarWidget((QWidget * )(d->property("__titleWidget").toULongLong()));
} else {
if (d->titleBarWidget() != (QWidget * )(d->property("__titleEmptyWidget").toULongLong())) {
d->setTitleBarWidget((QWidget * )(d->property("__titleEmptyWidget").toULongLong()));
d->layout()->setContentsMargins(0, 20, 0, 0);
}
}
}
}
//void EMainWindow::changedDockClose(QObject * dock) {
// qDebug() << "changedDockClose" << dock;
// if (!dock) return;
// foreach (QTabBar * t, tbars) {
// for (int i = 0; i < t->count(); ++i)
// if (t->tabData(i).toULongLong() == (qulonglong)dock) {
// t->removeTab(i);
// break;
// }
// }
//}
void EMainWindow::closeDock(int index) {
QDockWidget * dock = (QDockWidget * )((QTabBar*)sender())->tabData(index).toULongLong();
if (dock == 0) return;
dock->close();
}
void EMainWindow::recentTriggered() {
QAction * a = qobject_cast<QAction * >(sender());
if (!a) return;
QString path = a->data().toString();
if (path.isEmpty()) return;
if (!checkSave()) return;
if (load(path))
addToRecent(path);
}
void EMainWindow::setMaxRecentItems(int mr) {
max_recent = qMax(0, mr);
for (int i = actions_recent.size() - 1; i >= mr; --i)
delete actions_recent.takeLast();
}
void EMainWindow::newFile() {
if (!checkSave()) return;
reset(true);
setWindowModified(false);
}
void EMainWindow::openFile() {
if (!checkSave()) return;
QString ret = QFileDialog::getOpenFileName(this, trUtf8("Select file to open"), file_name, loadFilter());
if (ret.isEmpty()) return;
if (load(ret))
addToRecent(ret);
}
void EMainWindow::openFiles() {
if (!checkSave()) return;
QStringList ret = QFileDialog::getOpenFileNames(this, trUtf8("Select files to open"), file_name, loadFilter());
foreach (QString s, ret) {
if (load(s))
addToRecent(s);
}
}
bool EMainWindow::saveFile(bool ask) {
if (ask) {
int ret = QMessageBox::question(this, windowTitle(), trUtf8("Save changes%1?").arg(!file_name.isEmpty() ? (trUtf8(" in") + " \"" + file_name + "\"") : ""), QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Save);
if (ret == QMessageBox::Cancel) return false;
if (ret == QMessageBox::Save) return saveFile();
return true;
}
if (file_name.isEmpty()) return saveAsFile();
if (save(file_name))
addToRecent(file_name);
return true;
}
bool EMainWindow::saveAsFile() {
QString ret = QFileDialog::getSaveFileName(this, trUtf8("Select file to save"), file_name, saveFilter());
if (ret.isEmpty()) return false;
if (save(ret))
addToRecent(ret);
return true;
}
void EMainWindow::clearRecent() {
qDeleteAll(actions_recent);
actions_recent.clear();
prepareRecent();
}

View File

@@ -0,0 +1,127 @@
#ifndef EMAINWINDOW_H
#define EMAINWINDOW_H
#include <QTranslator>
#include <QUrl>
#include <QDesktopWidget>
#include <QInputDialog>
#include <QClipboard>
#include <QRadioButton>
#include <QThread>
#include <QColorDialog>
#include <QTime>
#include <QSplitter>
#include "session_manager.h"
#include "ribbon.h"
class UAction: public QAction {
Q_OBJECT
public:
UAction(int ind,const QString & text, QObject * parent): QAction(text, parent) {
index = ind;
connect(this, SIGNAL(triggered()), this, SLOT(triggered()));
connect(this, SIGNAL(toggled(bool)), this, SLOT(toggled(bool)));
connect(this, SIGNAL(hovered()), this, SLOT(hovered()));
}
UAction(int ind, const QIcon & icon, const QString & text, QObject * parent): QAction(icon, text, parent) {
index = ind;
connect(this, SIGNAL(triggered()), this, SLOT(triggered()));
connect(this, SIGNAL(toggled(bool)), this, SLOT(toggled(bool)));
connect(this, SIGNAL(hovered()), this, SLOT(hovered()));
}
public slots:
void show() {setVisible(true);}
void hide() {setVisible(false);}
void setCheckedTrue() {setChecked(true);}
void setCheckedFalse() {setChecked(false);}
private:
int index;
private slots:
void triggered() {emit itriggered(this, index);}
void toggled(bool t) {emit itoggled(t, this, index);}
void hovered() {emit ihovered(this);}
signals:
void itriggered(QAction *, int);
void itoggled(bool, QAction *, int);
void ihovered(QAction * action);
};
class EMainWindow: public QMainWindow
{
Q_OBJECT
Q_PROPERTY(int maxRecentItems READ maxRecentItems WRITE setMaxRecentItems)
public:
EMainWindow(QWidget * parent = 0);
~EMainWindow();
virtual void reset(bool full = false) {}
virtual bool load(const QString & path) {return true;}
virtual bool save(const QString & path) {return true;}
void addSeparator() {}
void setRecentFiles(const QStringList & rl);
QStringList recentFiles() const;
void setRecentMenu(QMenu * m);
int maxRecentItems() const {return max_recent;}
protected:
// Qt`s overloaded
void showEvent(QShowEvent * );
void closeEvent(QCloseEvent * );
bool eventFilter(QObject * o, QEvent * e);
void timerEvent(QTimerEvent * e);
QMenu * createPopupMenu();
void addToRecent(const QString & path);
void prepareRecent();
void init(const QString & config) {session.setFile(config); initMenus(); initSession(); loadSession();} // unusable
void saveSession();
void loadSession();
virtual void savingSession(QPIConfig & conf) {}
virtual void loadingSession(QPIConfig & conf) {}
virtual QSize dockTabsIconSize() const {return iconSize();}
virtual QString loadFilter() {return "All files(*)";}
virtual QString saveFilter() {return "All files(*)";}
bool checkSave();
void setChanged(bool yes = true) {isChanged = yes; setWindowModified(yes);}
void initMenus();
void initSession();
QAction action_show_all_tools, action_hide_all_tools, action_show_all_docks, action_hide_all_docks;
QString file_name;
QList<QTabBar * > tbars;
QList<QDockWidget * > tdocks;
QList<QAction * > actions_recent;
QAction * action_clear_recent;
QMenu * menu_recent;
SessionManager session;
bool isChanged, first_show;
int tid, max_recent;
private slots:
void changedDock();
void sessionLoading(QPIConfig & conf) {loadingSession(conf);}
void sessionSaving(QPIConfig & conf) {savingSession(conf);}
// void changedDockClose(QObject * dock);
void closeDock(int index);
void recentTriggered();
public slots:
void setMaxRecentItems(int mr);
void changed() {setChanged(true);}
void newFile();
void openFile();
void openFiles();
bool saveFile(bool ask = false);
bool saveAsFile();
void clearRecent();
signals:
};
#endif // MAINWINDOW_H

View File

@@ -0,0 +1,104 @@
#include "etabwidget.h"
ETabWidget::ETabWidget(QWidget* parent): QTabWidget(parent) {
tabBar()->setMouseTracking(true);
tabBar()->installEventFilter(this);
}
void ETabWidget::retranslate() {
for (int i = 0; i < buttons.size(); ++i)
buttons[i].toolTip = QApplication::translate("MainWindow", buttons[i].srcToolTip.toUtf8(), 0/*, QCoreApplication::UnicodeUTF8*/);
QList<QToolButton * > bl = findChildren<QToolButton * >();
foreach (QToolButton * i, bl)
i->setToolTip(QApplication::translate("MainWindow", i->property("sourceToolTip").toString().toUtf8(), 0/*, QCoreApplication::UnicodeUTF8*/));
}
int ETabWidget::addTab(QWidget * page, const QIcon & icon, const QString & label) {
int ret = QTabWidget::addTab(page, icon, label);
QWidget * w = new QWidget();
w->setLayout(new QBoxLayout(QBoxLayout::RightToLeft));
w->layout()->setContentsMargins(0, 0, 0, 0);
w->layout()->setSpacing(2);
QToolButton * b;
foreach (const TabButton & i, buttons) {
b = new QToolButton();
b->setToolTip(i.toolTip);
b->setIconSize(QSize(16, 16));
b->setIcon(i.icon);
//b->setFlat(true);
b->setProperty("sourceToolTip", i.toolTip);
b->setProperty("buttonRole", i.role);
connect(b, SIGNAL(clicked(bool)), this, SLOT(buttonClicked()));
w->layout()->addWidget(b);
b->setVisible(i.visible);
}
tabBar()->setTabButton(ret, QTabBar::RightSide, w);
return ret;
}
void ETabWidget::setButtonVisible(int role, bool yes) {
QList<QToolButton * > bl = findChildren<QToolButton * >();
foreach (QToolButton * i, bl)
if (i->property("buttonRole").toInt() == role)
i->setVisible(yes);
QWidget * w;
for (int i = 0; i < buttons.size(); ++i) {
if (buttons[i].role == role)
buttons[i].visible = yes;
w = tabBar()->tabButton(i, QTabBar::RightSide);
if (w != 0) w->adjustSize();
}
tabBar()->adjustSize();
}
/*
void ETabWidget::removeTab(int index) {
tbs.removeAll(qobject_cast<QToolButton * >(tabBar()->tabButton(index, QTabBar::RightSide)->layout()->itemAt(1)->widget()));
tbs.removeAll(qobject_cast<QToolButton * >(tabBar()->tabButton(index, QTabBar::RightSide)->layout()->itemAt(0)->widget()));
QTabWidget::removeTab(index);
}
*/
bool ETabWidget::eventFilter(QObject * o, QEvent * e) {
static int prev = -1;
if (e->type() == QEvent::MouseMove) {
QTabBar * t = qobject_cast<QTabBar * >(o);
if (t == 0) return QTabWidget::eventFilter(o, e);
for (int i = 0; i < count(); ++i)
if (t->tabRect(i).contains(((QMouseEvent * )e)->pos())) {
if (i != prev) {
prev = i;
emit tabHovered(i);
}
return QTabWidget::eventFilter(o, e);
}
if (-1 != prev) {
prev = -1;
emit tabHovered(-1);
}
}
if (e->type() == QEvent::Leave) {
if (-1 != prev) {
prev = -1;
emit tabHovered(-1);
}
}
return QTabWidget::eventFilter(o, e);
}
void ETabWidget::buttonClicked() {
QToolButton * s = qobject_cast<QToolButton * >(sender());
if (s == 0) return;
QWidget * pw = s->parentWidget();
if (pw == 0) return;
for (int i = 0; i < count(); ++i)
if (tabBar()->tabButton(i, QTabBar::RightSide) == pw) {
emit tabButtonClicked(i, s->property("buttonRole").toInt());
return;
}
}

View File

@@ -0,0 +1,54 @@
#ifndef ETABWIDGET_H
#define ETABWIDGET_H
#include <QTabWidget>
#include <QDebug>
#include <QTabBar>
#include <QMouseEvent>
#include <QEvent>
#include <QToolButton>
#include <QPushButton>
#include <QLayout>
#include <QHBoxLayout>
#include <QApplication>
class ETabWidget: public QTabWidget
{
Q_OBJECT
public:
explicit ETabWidget(QWidget * parent = 0);
void retranslate();
void addTabButton(int role, const QIcon & icon, const QString & toolTip = QString()) {buttons << TabButton(role, icon, toolTip);}
int addTab(QWidget * page, const QIcon & icon, const QString & label);
int addTab(QWidget * page, const QString & label) {return addTab(page, QIcon(), label);}
void setButtonVisible(int role, bool yes);
private:
bool eventFilter(QObject * o, QEvent * e);
void tabInserted(int) {emit countChanged();}
void tabRemoved(int) {emit countChanged();}
struct TabButton {
TabButton(int r, const QIcon & i, const QString & t) {role = r; icon = i; visible = true; srcToolTip = t; toolTip = QApplication::translate("MainWindow", t.toUtf8(), 0/*, QCoreApplication::UnicodeUTF8*/);}
int role;
bool visible;
QIcon icon;
QString srcToolTip;
QString toolTip;
};
QList<TabButton> buttons;
private slots:
void buttonClicked();
signals:
void countChanged();
void tabHovered(int tab);
void tabButtonClicked(int tab, int role);
};
#endif // ETABWIDGET_H

View File

@@ -0,0 +1,161 @@
#include "historyview.h"
HistoryView::HistoryView(QWidget* parent): QListWidget(parent) {
setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
setSelectionMode(QAbstractItemView::MultiSelection);
setEditTriggers(NoEditTriggers);
active_ = true;
duplicates_ = false;
index = 0;
setLimit(32);
setHistoryColor(palette().color(QPalette::Highlight));
connect(this, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(itemClicked(QListWidgetItem*)));
connect(this, SIGNAL(itemSelectionChanged()), this, SLOT(itemSelectionChanged()));
registerAction(-1, tr("History cleared"), QImage(":/icons/clear-history.png"));
}
HistoryView::~HistoryView() {
}
QByteArray HistoryView::current() const {
QListWidgetItem * ci = currentItem();
if (!ci) return QByteArray();
int i = row(ci);
if (i < 0 || i >= history_.size()) return QByteArray();
return history_[i].command;
}
void HistoryView::addEntry(int action, int count_, const QString & suffix) {
if (!active_) return;
QByteArray ba;
emit commandRequest(ba);
if (!duplicates_)
if (current() == ba)
return;
int cnt = count();
for (int i = index; i < cnt; ++i)
if (i >= 0) delete takeItem(index);
QListWidgetItem * li = new QListWidgetItem(actions_.value(action).icon, actionText(action, count_) + suffix);
blockSignals(true);
addItem(li);
setCurrentItem(li);
index = count();
history_.resize(index);
history_.back() = Entry(action, ba);
checkLimit();
scrollToItem(item(index - 1));
for (int i = 0; i < index; ++i)
item(i)->setSelected(true);
blockSignals(false);
emit changed();
emit redoAvailable(false);
emit undoAvailable((index > 1));
emit clearAvailable(history_.count() > 1);
}
void HistoryView::registerAction(int action, const QString & text, const QImage & icon) {
actions_[action] = HistoryView::Action(action, text, icon);
}
QString HistoryView::actionText(int action, int count_) {
return QString(actions_.value(action).text).replace("%count", QString::number(count_));
}
void HistoryView::checkLimit() {
if (count() < limit_ + 1) return;
int c = count() - limit_;
for (int i = 0; i < c; ++i) {
if (i >= index - 1) {
if (count() < 2) break;
delete takeItem(1);
history_.remove(1);
} else {
if (count() < 1) break;
delete takeItem(0);
history_.pop_front();
index--;
}
}
if (index < 1) index = 1;
if (index > count()) index = count();
}
void HistoryView::itemClicked(QListWidgetItem * item) {
if (!active_) return;
if (index == row(item) + 1) return;
index = row(item) + 1;
//qDebug() << actions[index - 1].command;
emit commandExecute(history_[index - 1].command);
emit changed();
itemSelectionChanged();
}
void HistoryView::itemSelectionChanged() {
if (!active_) return;
if (index < 1) index = 1;
//qDebug() << "changed" << count();
blockSignals(true);
setCurrentItem(item(index - 1));
for (int i = 0; i < index; ++i)
item(i)->setSelected(true);
for (int i = index; i < count(); ++i)
item(i)->setSelected(false);
blockSignals(false);
emit redoAvailable(index < count());
emit undoAvailable((index > 1));
}
void HistoryView::setLimit(int l) {
limit_ = l;
checkLimit();
emit redoAvailable(index < count());
emit undoAvailable((index > 1));
}
void HistoryView::setHistoryColor(const QColor & c) {
color_ = c;
QPalette pal(palette());
pal.setColor(QPalette::Highlight, color_);
pal.setColor(QPalette::HighlightedText, pal.color(QPalette::Text));
setPalette(pal);
}
void HistoryView::clear(bool silent) {
history_.clear();
QListWidget::clear();
if (!silent) addEntry(-1);
emit clearAvailable(false);
emit redoAvailable(index < count());
emit undoAvailable((index > 1));
}
void HistoryView::undo() {
if (index <= 1) return;
index--;
emit commandExecute(history_[index - 1].command);
emit changed();
itemSelectionChanged();
}
void HistoryView::redo() {
if (index >= count()) return;
index++;
emit commandExecute(history_[index - 1].command);
emit changed();
itemSelectionChanged();
}

View File

@@ -0,0 +1,79 @@
#ifndef HISTORYVIEW_H
#define HISTORYVIEW_H
#include <QListWidget>
#include <QDebug>
class HistoryView: public QListWidget
{
Q_OBJECT
Q_PROPERTY(bool active READ isActive WRITE setActive)
Q_PROPERTY(bool duplicatesEnabled READ isDuplicatesEnabled WRITE setDuplicatesEnabled)
Q_PROPERTY(int limit READ limit WRITE setLimit)
Q_PROPERTY(QColor historyColor READ historyColor WRITE setHistoryColor)
public:
explicit HistoryView(QWidget * parent = 0);
~HistoryView();
bool isActive() const {return active_;}
bool isDuplicatesEnabled() const {return duplicates_;}
int limit() const {return limit_;}
QColor historyColor() const {return color_;}
QByteArray current() const;
void addEntry(int action, int count = 0, const QString & suffix = QString());
void registerAction(int action, const QString & text, const QImage & icon = QImage());
private:
struct Action {
Action(int i = -1, const QString & t = QString(), const QImage & c = QImage()): id(i), text(t) {
QPixmap px = QPixmap::fromImage(c);
icon.addPixmap(px, QIcon::Active);
icon.addPixmap(px, QIcon::Disabled);
icon.addPixmap(px, QIcon::Normal);
icon.addPixmap(px, QIcon::Selected);
}
int id;
QString text;
QIcon icon;
};
struct Entry {
Entry(int a = -1, const QByteArray & c = QByteArray()): action(a), command(c) {}
int action;
QByteArray command;
};
void checkLimit();
QString actionText(int action, int count_);
QMap<int, Action> actions_;
QVector<Entry> history_;
QColor color_;
bool active_, duplicates_;
int index, limit_;
public slots:
void setActive(bool yes) {active_ = yes;}
void setDuplicatesEnabled(bool yes) {duplicates_ = yes;}
void setLimit(int l);
void setHistoryColor(const QColor & c);
void clear(bool silent = false);
void undo();
void redo();
private slots:
void itemClicked(QListWidgetItem * item);
void itemSelectionChanged();
signals:
void undoAvailable(bool);
void redoAvailable(bool);
void clearAvailable(bool);
void commandRequest(QByteArray & s);
void commandExecute(const QByteArray & s);
void changed();
};
#endif // HISTORYVIEW_H

View File

@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="ru_RU">
<context>
<name>EMainWindow</name>
<message>
<location filename="../emainwindow.cpp" line="28"/>
<location filename="../emainwindow.cpp" line="29"/>
<source>Show all</source>
<translation>Показать все</translation>
</message>
<message>
<location filename="../emainwindow.cpp" line="30"/>
<location filename="../emainwindow.cpp" line="31"/>
<source>Hide all</source>
<translation>Скрыть все</translation>
</message>
<message>
<location filename="../emainwindow.cpp" line="125"/>
<source>Toolbars</source>
<translation>Панели инструментов</translation>
</message>
<message>
<location filename="../emainwindow.cpp" line="150"/>
<source>Docks</source>
<translation>Окна</translation>
</message>
<message>
<location filename="../emainwindow.cpp" line="309"/>
<source>Select file to open</source>
<translation>Выбрать файл для открытия</translation>
</message>
<message>
<location filename="../emainwindow.cpp" line="317"/>
<source>Save changes%1?</source>
<translation>Сохранить изменения%1?</translation>
</message>
<message>
<location filename="../emainwindow.cpp" line="317"/>
<source> in</source>
<translation> в</translation>
</message>
<message>
<location filename="../emainwindow.cpp" line="329"/>
<source>Select file to save</source>
<translation>Выберите файл для сохранения</translation>
</message>
</context>
<context>
<name>HistoryView</name>
<message>
<location filename="../historyview.cpp" line="15"/>
<source>History cleared</source>
<translation>История очищена</translation>
</message>
</context>
</TS>

View File

@@ -0,0 +1 @@
qad_plugin(application "Gui;Widgets" "")

View File

@@ -0,0 +1,69 @@
#include "edockwidget.h"
#include "edockwidgetplugin.h"
#include <QtCore/QtPlugin>
EDockWidgetPlugin::EDockWidgetPlugin(QObject * parent): QObject(parent) {
m_initialized = false;
}
void EDockWidgetPlugin::initialize(QDesignerFormEditorInterface * /* core */) {
if (m_initialized)
return;
// Add extension registrations, etc. here
m_initialized = true;
}
bool EDockWidgetPlugin::isInitialized() const {
return m_initialized;
}
QWidget * EDockWidgetPlugin::createWidget(QWidget * parent) {
return new EDockWidget(parent);
}
QString EDockWidgetPlugin::name() const {
return QLatin1String("EDockWidget");
}
QString EDockWidgetPlugin::group() const {
return QLatin1String("Containers");
}
QIcon EDockWidgetPlugin::icon() const {
return QIcon(":/icons/edockwidget.png");
}
QString EDockWidgetPlugin::toolTip() const {
return QLatin1String("");
}
QString EDockWidgetPlugin::whatsThis() const {
return QLatin1String("");
}
bool EDockWidgetPlugin::isContainer() const {
return true;
}
QString EDockWidgetPlugin::domXml() const {
return QLatin1String("<widget class=\"EDockWidget\" name=\"dockWidget\">\n</widget>\n");
}
QString EDockWidgetPlugin::includeFile() const {
return QLatin1String("edockwidget.h");
}

View File

@@ -0,0 +1,36 @@
#ifndef EDOCKWIDGETPLUGIN_H
#define EDOCKWIDGETPLUGIN_H
#include <QObject>
#if QT_VERSION >= 0x050000
# include <QtUiPlugin/QDesignerCustomWidgetInterface>
#else
# include <QDesignerCustomWidgetInterface>
#endif
class EDockWidgetPlugin: public QObject, public QDesignerCustomWidgetInterface
{
Q_OBJECT
Q_INTERFACES(QDesignerCustomWidgetInterface)
public:
EDockWidgetPlugin(QObject * parent = 0);
bool isContainer() const;
bool isInitialized() const;
QIcon icon() const;
QString domXml() const;
QString group() const;
QString includeFile() const;
QString name() const;
QString toolTip() const;
QString whatsThis() const;
QWidget * createWidget(QWidget * parent);
void initialize(QDesignerFormEditorInterface * core);
private:
bool m_initialized;
};
#endif

View File

@@ -0,0 +1,69 @@
#include "emainwindow.h"
#include "emainwindowplugin.h"
#include <QtCore/QtPlugin>
EMainWindowPlugin::EMainWindowPlugin(QObject * parent): QObject(parent) {
m_initialized = false;
}
void EMainWindowPlugin::initialize(QDesignerFormEditorInterface * /* core */) {
if (m_initialized)
return;
// Add extension registrations, etc. here
m_initialized = true;
}
bool EMainWindowPlugin::isInitialized() const {
return m_initialized;
}
QWidget * EMainWindowPlugin::createWidget(QWidget * parent) {
return new EMainWindow(parent);
}
QString EMainWindowPlugin::name() const {
return QLatin1String("EMainWindow");
}
QString EMainWindowPlugin::group() const {
return QLatin1String("Containers");
}
QIcon EMainWindowPlugin::icon() const {
return QIcon();
}
QString EMainWindowPlugin::toolTip() const {
return QLatin1String("");
}
QString EMainWindowPlugin::whatsThis() const {
return QLatin1String("");
}
bool EMainWindowPlugin::isContainer() const {
return true;
}
QString EMainWindowPlugin::domXml() const {
return QLatin1String("<widget class=\"EMainWindow\" name=\"mainWindow\">\n</widget>\n");
}
QString EMainWindowPlugin::includeFile() const {
return QLatin1String("emainwindow.h");
}

View File

@@ -0,0 +1,36 @@
#ifndef EMAINWINDOWPLUGIN_H
#define EMAINWINDOWPLUGIN_H
#include <QObject>
#if QT_VERSION >= 0x050000
# include <QtUiPlugin/QDesignerCustomWidgetInterface>
#else
# include <QDesignerCustomWidgetInterface>
#endif
class EMainWindowPlugin: public QObject, public QDesignerCustomWidgetInterface
{
Q_OBJECT
Q_INTERFACES(QDesignerCustomWidgetInterface)
public:
EMainWindowPlugin(QObject * parent = 0);
bool isContainer() const;
bool isInitialized() const;
QIcon icon() const;
QString domXml() const;
QString group() const;
QString includeFile() const;
QString name() const;
QString toolTip() const;
QString whatsThis() const;
QWidget * createWidget(QWidget * parent);
void initialize(QDesignerFormEditorInterface * core);
private:
bool m_initialized;
};
#endif

View File

@@ -0,0 +1,69 @@
#include "historyview.h"
#include "historyviewplugin.h"
#include <QtCore/QtPlugin>
HistoryViewPlugin::HistoryViewPlugin(QObject * parent): QObject(parent) {
m_initialized = false;
}
void HistoryViewPlugin::initialize(QDesignerFormEditorInterface * /* core */) {
if (m_initialized)
return;
// Add extension registrations, etc. here
m_initialized = true;
}
bool HistoryViewPlugin::isInitialized() const {
return m_initialized;
}
QWidget * HistoryViewPlugin::createWidget(QWidget * parent) {
return new HistoryView(parent);
}
QString HistoryViewPlugin::name() const {
return QLatin1String("HistoryView");
}
QString HistoryViewPlugin::group() const {
return QLatin1String("Display Widgets");
}
QIcon HistoryViewPlugin::icon() const {
return QIcon(":/icons/historyview.png");
}
QString HistoryViewPlugin::toolTip() const {
return QLatin1String("");
}
QString HistoryViewPlugin::whatsThis() const {
return QLatin1String("");
}
bool HistoryViewPlugin::isContainer() const {
return true;
}
QString HistoryViewPlugin::domXml() const {
return QLatin1String("<widget class=\"HistoryView\" name=\"historyView\">\n</widget>\n");
}
QString HistoryViewPlugin::includeFile() const {
return QLatin1String("historyview.h");
}

View File

@@ -0,0 +1,36 @@
#ifndef HISTORYVIEWPLUGIN_H
#define HISTORYVIEWPLUGIN_H
#include <QObject>
#if QT_VERSION >= 0x050000
# include <QtUiPlugin/QDesignerCustomWidgetInterface>
#else
# include <QDesignerCustomWidgetInterface>
#endif
class HistoryViewPlugin: public QObject, public QDesignerCustomWidgetInterface
{
Q_OBJECT
Q_INTERFACES(QDesignerCustomWidgetInterface)
public:
HistoryViewPlugin(QObject * parent = 0);
bool isContainer() const;
bool isInitialized() const;
QIcon icon() const;
QString domXml() const;
QString group() const;
QString includeFile() const;
QString name() const;
QString toolTip() const;
QString whatsThis() const;
QWidget * createWidget(QWidget * parent);
void initialize(QDesignerFormEditorInterface * core);
private:
bool m_initialized;
};
#endif // HISTORYVIEWPLUGIN_H

View File

@@ -0,0 +1,21 @@
#include "qad_application.h"
#include "edockwidgetplugin.h"
#include "emainwindowplugin.h"
#include "historyviewplugin.h"
QADApplication::QADApplication(QObject * parent): QObject(parent) {
//m_widgets.append(new EDockWidgetPlugin(this));
m_widgets.append(new EMainWindowPlugin(this));
m_widgets.append(new HistoryViewPlugin(this));
}
QList<QDesignerCustomWidgetInterface * > QADApplication::customWidgets() const {
return m_widgets;
}
#if QT_VERSION < 0x050000
Q_EXPORT_PLUGIN2(qad_graphic_plugin, QADApplication)
#endif

View File

@@ -0,0 +1,23 @@
#ifndef QAD_APPLICATION_H
#define QAD_APPLICATION_H
#include <QtDesigner/QtDesigner>
#include <QtCore/qplugin.h>
class QADApplication: public QObject, public QDesignerCustomWidgetCollectionInterface
{
Q_OBJECT
Q_INTERFACES(QDesignerCustomWidgetCollectionInterface)
#if QT_VERSION >= 0x050000
Q_PLUGIN_METADATA(IID "qad.application")
#endif
public:
explicit QADApplication(QObject * parent = 0);
virtual QList<QDesignerCustomWidgetInterface * > customWidgets() const;
private:
QList<QDesignerCustomWidgetInterface * > m_widgets;
};
#endif // QAD_APPLICATION_H

View File

@@ -0,0 +1,31 @@
<RCC>
<qresource prefix="/">
<file>lang/qad_application_ru.ts</file>
<file>../icons/application-exit.png</file>
<file>../icons/dialog-close.png</file>
<file>../icons/configure.png</file>
<file>../icons/document-edit.png</file>
<file>../icons/document-new.png</file>
<file>../icons/document-save.png</file>
<file>../icons/document-save-all.png</file>
<file>../icons/document-save-as.png</file>
<file>../icons/document-open.png</file>
<file>../icons/document-open-recent.png</file>
<file>../icons/document-close.png</file>
<file>../icons/edit-clear.png</file>
<file>../icons/edit-clear-locationbar-rtl.png</file>
<file>../icons/edit-find.png</file>
<file>../icons/list-add.png</file>
<file>../icons/edit-delete.png</file>
<file>../icons/edit-copy.png</file>
<file>../icons/edit-paste.png</file>
<file>../icons/edit-undo.png</file>
<file>../icons/edit-redo.png</file>
<file>../icons/border-line.png</file>
<file>../icons/edockwidget.png</file>
<file>../icons/historyview.png</file>
<file>../icons/clear-history.png</file>
<file>../icons/layer-visible-off.png</file>
<file>../icons/layer-visible-on.png</file>
</qresource>
</RCC>

View File

@@ -0,0 +1,87 @@
#include <QDebug>
#include "qsingleapplication.h"
#define QSA_SHMSIZE 4096
#define QSA_MSGSIZE (QSA_SHMSIZE - sizeof(quint32) - sizeof(quint32))
QSingleApplication::QSingleApplication(const QString & app_name): QThread() {
shm.setKey(app_name);
exiting = false;
first = !shm.attach();
if (!first) {
shm.detach();
first = !shm.attach();
if (!first)
return;
}
shm.create(QSA_SHMSIZE);
shm.attach();
shm.lock();
void * d = shm.data();
if (d) memset(d, 0, sizeof(quint32));
shm.unlock();
start();
//qDebug() << "start listen";
}
QSingleApplication::~QSingleApplication() {
if (first) {
exiting = true;
quit();
if (!wait(100))
terminate();
}
if (shm.isAttached()) shm.detach();
}
void QSingleApplication::sendMessage(const QByteArray & m) {
//qDebug() << "send message" << first << shm.isAttached();
if (first || !shm.isAttached()) return;
if (m.size() > int(QSA_MSGSIZE)) {
qDebug() << "[QSingleApplication] Too large message:" << m.size() << ">" << QSA_MSGSIZE;
return;
}
shm.lock();
quint32 num(0), size = m.size();
void * d = shm.data();
if (d) {
memcpy(&num, d, sizeof(quint32));
num++;
memcpy(d, &num, sizeof(quint32));
memcpy((((char*)d) + sizeof(quint32)), &size, sizeof(quint32));
memcpy((((char*)d) + sizeof(quint32) + sizeof(quint32)), m.constData(), size);
}
shm.unlock();
}
void QSingleApplication::run() {
quint32 num(0), pnum(0), size(0);
while (!exiting) {
shm.lock();
const void * d = shm.constData();
if (d) {
memcpy(&num, d, sizeof(quint32));
if (pnum != num) {
pnum = num;
//qDebug() << "new message" << num;
memcpy(&size, (((const char*)d) + sizeof(quint32)), sizeof(quint32));
if (size <= int(QSA_MSGSIZE)) {
QByteArray msg;
msg.resize(size);
memcpy(msg.data(), (((const char*)d) + sizeof(quint32) + sizeof(quint32)), size);
emit messageReceived(msg);
} else {
qDebug() << "[QSingleApplication] Invalid message size:" << size;
}
}
}
shm.unlock();
if (exiting) break;
msleep(10);
}
}

View File

@@ -0,0 +1,30 @@
#ifndef QSINGLEAPPLICATION_H
#define QSINGLEAPPLICATION_H
#include <QThread>
#include <QSharedMemory>
class QSingleApplication: public QThread
{
Q_OBJECT
public:
QSingleApplication(const QString & app_name = QString("qapp"));
~QSingleApplication();
bool isFirst() const {return first;}
private:
void run();
QSharedMemory shm;
bool first, exiting;
public slots:
void sendMessage(const QByteArray & m);
signals:
void messageReceived(QByteArray);
};
#endif // QSINGLEAPPLICATION_H

View File

@@ -0,0 +1,230 @@
#include "ribbon.h"
#include "qad_types.h"
#include <QScrollBar>
Ribbon::Ribbon(QMainWindow * parent_): QToolBar() {
tab = 0;
scroll_area = 0;
delay_e = true;
delay = 1000;
hovered = -1;
setObjectName("ribbon");
setProperty("ribbon", true);
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
parent = parent_;
if (parent_)
parent_->installEventFilter(this);
init();
}
Ribbon::~Ribbon() {
}
bool Ribbon::eventFilter(QObject * o, QEvent * e) {
//qDebug() << e;
if (o == parent) {
if (e->type() == QEvent::Resize || e->type() == QEvent::WindowActivate)
_resize();
if (e->type() == QEvent::FontChange || e->type() == QEvent::Polish)
_setIconsSize();
return QToolBar::eventFilter(o, e);
}
if (e->type() == QEvent::ActionChanged) {
QToolButton * b = qobject_cast<QToolButton * >((QObject * )o->property("ribbonButton").toLongLong());
if (b != 0)
b->setEnabled(qobject_cast<QAction * >(o)->isEnabled());
}
return QToolBar::eventFilter(o, e);
}
void Ribbon::timerEvent(QTimerEvent * e) {
if (hovers.value(e->timerId(), -1) == hovered)
tab->setCurrentIndex(hovered);
hovers.remove(e->timerId());
killTimer(e->timerId());
}
void Ribbon::_resize() {
return; // WARNING
for (int i = 0; i < tab->count(); ++i) {
int h = ((QScrollArea*)(tab->widget(i)))->sizeHint().height();
if (((QScrollArea*)(tab->widget(i)))->horizontalScrollBar()->isVisible())
h += ((QScrollArea*)(tab->widget(i)))->horizontalScrollBar()->height();
((QScrollArea*)(tab->widget(i)))->setMinimumHeight(h);
}
}
void Ribbon::_setIconsSize() {
//qDebug() << "resize" << preferredIconSize() << QApplication::font();
setTabIconSize(preferredIconSize(2, this));
setIconSize(preferredIconSize(3, this));
}
void Ribbon::setVisible(bool yes) {
QToolBar::setVisible(yes);
if (parent == 0) return;
if (parent->menuBar() == 0) return;
parent->menuBar()->setVisible(!yes);
}
void Ribbon::init() {
if (parent == 0) return;
if (parent->menuBar() == 0) return;
QList<QAction * > lm = parent->menuBar()->actions(), la;
clear();
if (scroll_area) delete scroll_area;
buttons.clear();
tab = new ETabWidget();
tab->setObjectName("ribbon_tab_widget");
connect(tab, SIGNAL(tabHovered(int)), this, SLOT(tabHovered(int)));
connect(tab, SIGNAL(currentChanged(int)), this, SIGNAL(currentTabChanged(int)));
tab->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
QFrame * g;
QBoxLayout * l, * tl;
QToolButton * b;
//tab->setIconSize(QSize(32, 32));
foreach (QAction * i, lm) {
if (!i->menu()) continue;
//if (!i->menu()->isVisible()) continue;
la = i->menu()->actions();
QIcon tic = i->icon();
if (!tic.isNull())
i->setProperty("__icon", QVariant::fromValue<QIcon>(tic));
else
tic = i->property("__icon").value<QIcon>();
//#ifdef Q_OS_MACOS
// tic = QIcon();
//#endif
tab->addTab(new QWidget(), tic, i->text());
//qDebug() << this << i->icon() << i->text();
//continue;
/*QScrollArea * sa = new QScrollArea();
sa->setWidget(new QWidget());
sa->setWidgetResizable(true);
sa->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
sa->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
sa->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
sa->setFrameShape(QFrame::NoFrame);
tab->addTab(sa, i->icon(), i->text());*/
tab->widget(tab->count() - 1)->setProperty("ribbonAction", qlonglong((void * )i));
i->setIcon(QIcon());
tl = new QBoxLayout(QBoxLayout::LeftToRight);
tl->setSpacing(2);
#ifndef Q_OS_MACOS
tl->setContentsMargins(2, 2, 2, 2);
#else
tl->setContentsMargins(2, 0, 2, 2);
#endif
g = new QFrame(); g->setFrameShape(QFrame::StyledPanel);
l = new QBoxLayout(QBoxLayout::LeftToRight);
g->setLayout(l);
l->setSpacing(2);
l->setContentsMargins(2, 2, 2, 2);
foreach (QAction * j, la) {
if (j->isSeparator()) {
if (l->isEmpty()) continue;
tl->addWidget(g);
g = new QFrame(); g->setFrameShape(QFrame::StyledPanel);
l = new QBoxLayout(QBoxLayout::LeftToRight);
l->setSpacing(2);
l->setContentsMargins(2, 2, 2, 2);
g->setLayout(l);
continue;
}
if (qobject_cast<QWidgetAction*>(j)) {
QWidget * _w = qobject_cast<QWidgetAction*>(j)->defaultWidget();
l->addWidget(_w);
_w->show();
continue;
}
b = new QToolButton();
b->setEnabled(j->isEnabled());
b->setProperty("ribbonAction", qlonglong((void * )j));
j->setProperty("ribbonButton", qlonglong((void * )b));
j->installEventFilter(this);
if (j->menu() != 0) {
b->setPopupMode(QToolButton::InstantPopup);
b->setMenu(j->menu());
} else {
b->setCheckable(j->isCheckable());
if (b->isCheckable()) {
b->setChecked(j->isChecked());
connect(b, SIGNAL(toggled(bool)), j, SLOT(setChecked(bool)));
connect(b, SIGNAL(clicked(bool)), j, SIGNAL(triggered(bool)));
connect(j, SIGNAL(toggled(bool)), b, SLOT(setChecked(bool)));
} else
connect(b, SIGNAL(clicked()), j, SLOT(trigger()));
}
//b->setIconSize(QSize(16, 16));
b->setIcon(j->icon());
b->setText(j->text());
b->setToolTip(j->text());
//b->addAction(j);
//b->setShortcut(j->shortcut());
b->setAutoRaise(true);
b->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
b->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
buttons << b;
l->addWidget(b);
}
tl->addWidget(g);
tl->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Fixed));
//sa->widget()->setLayout(tl);
tab->widget(tab->count() - 1)->setLayout(tl);
}
setFloatable(false);
setMovable(false);
/*scroll_area = new QScrollArea();
scroll_area->setFrameShape(QFrame::NoFrame);
scroll_area->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
scroll_area->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
scroll_area->setWidget(tab);*/
_resize();
//addWidget(scroll_area);
addWidget(tab);
parent->addToolBar(Qt::TopToolBarArea, this);
parent->menuBar()->hide();
tab->setAutoFillBackground(false);
_setIconsSize();
}
void Ribbon::retranslate() {
QAction * a;
foreach (QToolButton * i, buttons) {
a = (QAction * )(i->property("ribbonAction").toLongLong());
if (a == 0) continue;
i->setText(a->text());
i->setToolTip(a->toolTip());
//i->setShortcut(a->shortcut());
}
for (int i = 0; i < tab->count(); ++i) {
a = (QAction * )(tab->widget(i)->property("ribbonAction").toLongLong());
if (a == 0) continue;
tab->setTabText(i, a->text());
}
_resize();
}
void Ribbon::setIconSize(const QSize & size) {
foreach (QToolButton * i, buttons)
i->setIconSize(size);
_resize();
}
void Ribbon::setTabIconSize(const QSize & size) {
#ifndef Q_OS_MACOS
tab->setIconSize(size);
#endif
_resize();
}

View File

@@ -0,0 +1,63 @@
#ifndef RIBBON_H
#define RIBBON_H
#include <QMainWindow>
#include <QActionGroup>
#include <QWidgetAction>
#include <QMenuBar>
#include <QTabWidget>
#include <QGroupBox>
#include <QDockWidget>
#include <QToolBar>
#include <QToolButton>
#include <QScrollArea>
#include "etabwidget.h"
class Ribbon: public QToolBar
{
Q_OBJECT
public:
explicit Ribbon(QMainWindow * parent = 0);
~Ribbon();
void init();
void retranslate();
void setIconSize(const QSize & size);
void setTabIconSize(const QSize & size);
void setButtonStyle(const Qt::ToolButtonStyle & style) {foreach (QToolButton * i, buttons) i->setToolButtonStyle(style);}
void setAutoSwitchEnabled(bool yes) {delay_e = yes;}
void setAutoSwitchDelay(float delay_s) {delay = delay_s * 1000;}
void setCurrentTab(int tab_) {if (tab_ < 0 || tab_ >= tab->count()) return; tab->setCurrentIndex(tab_);}
int currentTab() const {return tab->currentIndex();}
QTabWidget * tabWidget() const {return tab;}
private:
bool eventFilter(QObject * o, QEvent * e);
void timerEvent(QTimerEvent * e);
void _resize();
void _setIconsSize();
int hovered, delay;
bool delay_e;
QList<QToolButton * > buttons;
QMap<int, int> hovers;
ETabWidget * tab;
QScrollArea * scroll_area;
QMainWindow * parent;
private slots:
void tabHovered(int tab) {if (!delay_e) return; hovers.clear(); hovered = tab; hovers.insert(startTimer(delay), tab);}
public slots:
void setVisible(bool yes);
void setHidden(bool yes) {setVisible(!yes);}
void show() {setVisible(true);}
void hide() {setVisible(false);}
signals:
void currentTabChanged(int);
};
#endif // RIBBON_H

View File

@@ -0,0 +1,4 @@
qad_project(blockview "Gui;Widgets" "qad_utils;qad_widgets")
if (blockview_UTILS)
add_subdirectory(blockeditor)
endif()

View File

@@ -0,0 +1,62 @@
#include "alignedtextitem.h"
#include <QApplication>
#include <QPainter>
#include <QDebug>
AlignedTextItem::AlignedTextItem(QGraphicsItem * parent): QGraphicsItem(parent), text_(this) {
align_ = Qt::AlignTop | Qt::AlignHCenter;
text_.setData(1003, true);
setFont(font());
_move();
}
AlignedTextItem::AlignedTextItem(const QString & text, QGraphicsItem * parent): QGraphicsItem(parent), text_(this) {
align_ = Qt::AlignTop | Qt::AlignHCenter;
text_.setData(1003, true);
setFont(font());
setText(text);
}
void AlignedTextItem::setFont(const QFont & f) {
font_ = f;
text_.setFont(sceneFont(f));
_move();
}
QFont AlignedTextItem::sceneFont(const QFont & f) {
QFont ret = f;
double scl = 16. / QApplication::fontMetrics().size(0, "0").height();
ret.setPointSizeF(ret.pointSizeF() * scl);
return ret;
}
QPointF AlignedTextItem::_point(Qt::Alignment a) const {
QRectF br = text_.boundingRect();
QPointF ret;
switch (Qt::AlignmentFlag(int(align_ & Qt::AlignHorizontal_Mask))) {
case Qt::AlignRight: ret.rx() = br.left(); break;
case Qt::AlignHCenter: ret.rx() = br.center().x(); break;
case Qt::AlignLeft: ret.rx() = br.right(); break;
default: break;
}
switch (Qt::AlignmentFlag(int(align_ & Qt::AlignVertical_Mask))) {
case Qt::AlignBottom: ret.ry() = br.top(); break;
case Qt::AlignVCenter: ret.ry() = br.center().y(); break;
case Qt::AlignTop: ret.ry() = br.bottom(); break;
default: break;
}
return ret;
}
void AlignedTextItem::paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget) {
if (isSelected()) {
painter->setPen(QPen(Qt::DashLine));
painter->setBrush(Qt::NoBrush);
painter->drawRect(boundingRect());
}
}

View File

@@ -0,0 +1,48 @@
#ifndef ALIGNEDTEXTITEM_H
#define ALIGNEDTEXTITEM_H
#include <QGraphicsSimpleTextItem>
#include <QPen>
#include <QBrush>
#include <QFont>
class AlignedTextItem: public QGraphicsItem {
public:
AlignedTextItem(QGraphicsItem * parent = 0);
AlignedTextItem(const QString & text, QGraphicsItem * parent = 0);
void setText(const QString & t) {text_.setText(t); _move();}
void setFont(const QFont & f);
void setPen(const QPen & p) {text_.setPen(p); _move();}
void setBrush(const QBrush & b) {text_.setBrush(b); _move();}
void setAlignment(Qt::Alignment align) {align_ = align; _move();}
QString text() const {return text_.text();}
QFont font() const {return /*text_.font()*/font_;}
QPen pen() const {return text_.pen();}
QBrush brush() const {return text_.brush();}
Qt::Alignment alignment() const {return align_;}
void clear() {setText(QString());}
enum {Type = UserType + 0x100};
static QFont sceneFont(const QFont & f);
protected:
virtual QRectF boundingRect() const {return text_.boundingRect().translated(text_.pos());}
virtual void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0);
virtual int type() const {return Type;}
void _move() {text_.setPos(-_point(align_));}
QPointF _point(Qt::Alignment a) const;
QGraphicsSimpleTextItem text_;
Qt::Alignment align_;
QFont font_;
};
#endif // ALIGNEDTEXTITEM_H

View File

@@ -0,0 +1,109 @@
#include "blockbase.h"
#include "alignedtextitem.h"
#include "qvariantedit.h"
QDataStream & operator <<(QDataStream & s, const QGraphicsItem * item) {
if (!item) {
s << int(-1);
return s;
}
const QGraphicsRectItem * irect = qgraphicsitem_cast<const QGraphicsRectItem*>(item);
const QGraphicsEllipseItem * iell = qgraphicsitem_cast<const QGraphicsEllipseItem*>(item);
const QGraphicsSimpleTextItem * itext = qgraphicsitem_cast<const QGraphicsSimpleTextItem*>(item);
const AlignedTextItem * iatext = qgraphicsitem_cast<const AlignedTextItem*>(item);
const QGraphicsLineItem * iline = qgraphicsitem_cast<const QGraphicsLineItem*>(item);
const QGraphicsPathItem * ipath = qgraphicsitem_cast<const QGraphicsPathItem*>(item);
const QGraphicsPixmapItem * ipixmap = qgraphicsitem_cast<const QGraphicsPixmapItem*>(item);
if (irect) {
s << int(0) << (irect->pen()) << (irect->brush()) << (irect->rect());
} else if (iell) {
s << int(1) << (iell->pen()) << (iell->brush()) << (iell->rect());
} else if (itext) {
s << int(2) << (itext->pen()) << (itext->brush()) << (itext->font()) << (itext->text());
} else if (iatext) {
s << int(6) << (iatext->pen()) << (iatext->brush()) << (iatext->font()) << (iatext->text()) << int(iatext->alignment());
} else if (iline) {
s << int(3) << (iline->pen()) << (iline->line());
} else if (ipath) {
s << int(4) << (ipath->pen()) << (ipath->path());
} else if (ipixmap) {
s << int(7) << (ipixmap->pixmap()) << (ipixmap->transform());
} else {
s << int(-1);
return s;
}
s << (item->pos()) << (item->rotation()) << int(item->flags());
return s;
}
QDataStream & operator >>(QDataStream & s, QGraphicsItem *& item) {
int type_; s >> type_;
if (type_ < 0) {
item = 0;
return s;
}
QGraphicsRectItem * nrect = 0;
QGraphicsEllipseItem * nell = 0;
QGraphicsSimpleTextItem * ntext = 0;
AlignedTextItem * natext = 0;
QGraphicsLineItem * nline = 0;
QGraphicsPathItem * npath = 0;
QGraphicsPixmapItem * npixmap = 0;
item = 0;
switch (type_) {
case 0:
nrect = new QGraphicsRectItem(); item = nrect;
{QPen _v; s >> _v; nrect->setPen(_v);}
{QBrush _v; s >> _v; nrect->setBrush(_v);}
{QRectF _v; s >> _v; nrect->setRect(_v);}
break;
case 1:
nell = new QGraphicsEllipseItem(); item = nell;
{QPen _v; s >> _v; nell->setPen(_v);}
{QBrush _v; s >> _v; nell->setBrush(_v);}
{QRectF _v; s >> _v; nell->setRect(_v);}
break;
case 2:
ntext = new QGraphicsSimpleTextItem(); item = ntext;
{QPen _v; s >> _v; ntext->setPen(_v);}
{QBrush _v; s >> _v; ntext->setBrush(_v);}
{QFont _v; s >> _v; ntext->setFont(_v);}
{QString _v; s >> _v; ntext->setText(_v);}
break;
case 6:
natext = new AlignedTextItem(); item = natext;
{QPen _v; s >> _v; natext->setPen(_v);}
{QBrush _v; s >> _v; natext->setBrush(_v);}
{QFont _v; s >> _v; natext->setFont(_v);}
{QString _v; s >> _v; natext->setText(_v);}
{int _v; s >> _v; natext->setAlignment((Qt::AlignmentFlag)_v);}
break;
case 3:
nline = new QGraphicsLineItem(); item = nline;
{QPen _v; s >> _v; nline->setPen(_v);}
{QLineF _v; s >> _v; nline->setLine(_v);}
break;
case 4:
npath = new QGraphicsPathItem(); item = npath;
{QPen _v; s >> _v; npath->setPen(_v);}
{QPainterPath _v; s >> _v; npath->setPath(_v);}
break;
case 5:
npixmap = new QGraphicsPixmapItem(); item = npixmap;
{QPixmap _v; s >> _v; npixmap->setPixmap(_v);}
break;
case 7:
npixmap = new QGraphicsPixmapItem(); item = npixmap;
{QPixmap _v; s >> _v; npixmap->setPixmap(_v);}
{QTransform _t; s >> _t; npixmap->setTransform(_t);}
break;
}
if (item) {
{QPointF _v; s >> _v; item->setPos(_v);}
{qreal _v; s >> _v; item->setRotation(_v);}
{int _v; s >> _v; item->setFlags((QGraphicsItem::GraphicsItemFlags)_v);}
}
return s;
}

View File

@@ -0,0 +1,59 @@
#ifndef BLOCKBASE_H
#define BLOCKBASE_H
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsItem>
#include <QGraphicsObject>
#include <QGraphicsEllipseItem>
#include <QGraphicsSceneHoverEvent>
#include <QGraphicsSceneMouseEvent>
#include <QStack>
#include "qad_types.h"
/// data:
/// 1002 - flag for move parent (true)
/// 1003 - flag for visualize selection (true)
/// 1004 - BlockItemPin ("pin")
/// 1005 - BlockBusItem ("connection")
/// 1006 - BlockItem ("item")
/// 1007 - BlockItem selection ("item_selection")
/// 1008 - item is NOT decor, ignore for function decors() (true)
/// 1009 - item is scene decor ("decor")
/// 1010 - BlockItem decor (src text for QGraphicsSimpleTextItem)
/// 1011 - item is BlockItem decor ("decor")
/// 1100 - flag for correct move (true)
static const int _blockitem_current_version_ = 1;
QDataStream & operator <<(QDataStream & s, const QGraphicsItem * item);
QDataStream & operator >>(QDataStream & s, QGraphicsItem *& item);
class BlockItemBase: public QObject
{
Q_OBJECT
Q_ENUMS(Action)
public:
enum Action {
BlockAdd = 1,
BlockMove,
BlockRemove,
BlockCopy,
BusAdd,
BusRemove,
BusPointAdd,
BusPointMove,
BusPointRemove,
BusSegmentAdd,
BusSegmentMove,
BusSegmentRemove,
Paste
};
};
#endif // BLOCKBASE_H

View File

@@ -0,0 +1,814 @@
#include "blockview.h"
BlockBusItem::BlockBusItem(bool temp): QGraphicsObject(), PropertyStorage() {
temp_ = temp;
_init();
if (!temp) setData(1005, "connection");
else hide();
}
BlockBusItem::BlockBusItem(const BlockBusItem & other): QGraphicsObject(), PropertyStorage() {
temp_ = false;
_init();
setData(1005, "connection");
setPen(other.pen());
setBrush(other.brush());
setBusType(other.busType());
max_ep = other.max_ep;
pol = other.pol;
segments = other.segments;
im_bus = other.im_bus;
im_end = other.im_end;
im_bus_scale = other.im_bus_scale;
im_end_scale = other.im_end_scale;
updateGeometry();
}
void BlockBusItem::_init() {
setZValue(1.);
setBusType(-1);
setAcceptHoverEvents(true);
ph.setColor(Qt::blue); ph.setJoinStyle(Qt::MiterJoin);
bh.setColor(Qt::blue); bh.setStyle(Qt::SolidPattern);
pu = pa = pr = ph; bu = ba = br = bh;
grid_step = 10.;
pu.setWidth(1);
pu.setColor(Qt::black); bu.setColor(Qt::black);
pa.setColor(Qt::darkGreen); ba.setColor(Qt::darkGreen);
pr.setColor(Qt::darkRed); br.setColor(Qt::darkRed);
pn.setColor(Qt::gray); pn.setStyle(Qt::DashLine);
if (temp_) {
pu.setStyle(Qt::DashLine);
pu.setColor(Qt::darkGray);
bu.setColor(Qt::darkGray);
}
setPen(pu); setBrush(bu);
max_ep = 0;
selPoint = selSegment = state_ = -1;
pen_width = 2.;
point_size = 3.;
im_bus_scale = im_end_scale = 1.;
moved = deleted = mark_in = mark_out = new_segment = mm_cancel = lm_point = false;
anim_point_size.setTargetObject(this);
anim_point_size.setPropertyName("pointSize");
anim_point_size.setStartValue(0);
anim_point_size.setEasingCurve(QEasingCurve::OutQuad);
anim_point_size.setEndValue(point_size);
anim_point_size.setDuration(200);
}
void BlockBusItem::reconnect() {
if (temp_) return;
if (!scene()) return;
if (scene()->views().isEmpty()) return;
QMetaObject::invokeMethod(scene()->views().back(), "reconnectAll");
}
bool BlockBusItem::sceneEvent(QEvent * e) {
if (temp_) return QGraphicsObject::sceneEvent(e);
switch (e->type()) {
case QEvent::GraphicsSceneHoverEnter: hoverEnterEvent((QGraphicsSceneHoverEvent * )e); break;
case QEvent::GraphicsSceneHoverMove: hoverMoveEvent((QGraphicsSceneHoverEvent * )e); break;
case QEvent::GraphicsSceneHoverLeave: hoverLeaveEvent((QGraphicsSceneHoverEvent * )e); break;
case QEvent::GraphicsSceneMousePress: mousePressEvent((QGraphicsSceneMouseEvent * )e); break;
case QEvent::GraphicsSceneMouseMove: mouseMoveEvent((QGraphicsSceneMouseEvent * )e); break;
case QEvent::GraphicsSceneMouseRelease: mouseReleaseEvent((QGraphicsSceneMouseEvent * )e); break;
default: break;
}
return QGraphicsObject::sceneEvent(e);
}
int BlockBusItem::addPoint(const QPointF & point, bool update) {
int ei = pol.indexOf(point);
if (ei >= 0) return ei;
if (selSegment < 0 || selSegment >= pol.size() - 1) return -1;
pol << quantize(nearestPointOnLine(pol[segments[selSegment].first], pol[segments[selSegment].second], point), grid_step);
selPoint = pol.size() - 1;
segments << QPair<int, int>(selPoint, segments[selSegment].second);
segments[selSegment].second = selPoint;
selSegment = -1;
updateGeometry();
if (scene() != 0 && update) scene()->update();
return pol.size() - 1;
}
int BlockBusItem::segmentPointPair(int point, int * seg) const {
for (int i = 0; i < segments.size(); ++i) {
if (segments[i].first == point) {
if (seg) *seg = i;
return segments[i].second;
}
if (segments[i].second == point) {
if (seg) *seg = i;
return segments[i].first;
}
}
if (seg) *seg = -1;
return -1;
}
void BlockBusItem::removePoint(int index) {
if (index < 0 || index > pol.size() - 1) return;
int sc = 0, fs = -1, ss = -1;
for (int i = 0; i < segments.size(); ++i)
if (segments[i].first == index ||
segments[i].second == index) {
sc++;
if (fs < 0) fs = i;
else ss = i;
}
int ei(0);
switch (sc) {
case 1:
segments.removeAt(fs);
break;
case 2:
if (segments[ss].first == index) ei = segments[ss].second;
else ei = segments[ss].first;
if (segments[fs].first == index) segments[fs].first = ei;
else segments[fs].second = ei;
segments.removeAt(ss);
break;
default: return;
}
pol.remove(index);
for (int i = 0; i < segments.size(); ++i) {
if (segments[i].first >= index)
segments[i].first--;
if (segments[i].second >= index)
segments[i].second--;
}
selPoint = -1;
checkDelete();
updateGeometry();
if (scene() != 0) scene()->update();
}
void BlockBusItem::removeSegment(int index) {
if (index < 0 || index > segments.size() - 1) return;
int pif = segments[index].first, pis = segments[index].second;
if (pif > pis) qSwap<int>(pif, pis);
int scf = 0, scs = 0;
for (int i = 0; i < segments.size(); ++i) {
if (segments[i].first == pif ||
segments[i].second == pif)
scf++;
if (segments[i].first == pis ||
segments[i].second == pis)
scs++;
}
if (scs <= 2) removePoint(pis);
if (scf <= 2) removePoint(pif);
if (scs <= 2 || scf <= 2) selSegment = -1;
if (scene() != 0) scene()->update();
}
void BlockBusItem::appendPoint(const QPointF & p) {
pol << p;
if (pol.size() > 1)
segments << QPair<int, int>(pol.size() - 2, pol.size() - 1);
updateGeometry();
}
void BlockBusItem::appendPoint(qreal x, qreal y) {
appendPoint(QPointF(x, y));
}
void BlockBusItem::clear() {
pol.clear();
segments.clear();
updateGeometry();
}
void BlockBusItem::movePolyline(const QPointF & dp) {
pol.translate(dp);
prepareGeometryChange();
}
void BlockBusItem::movePoint(int index, const QPointF & dp) {
pol[index] += dp;
prepareGeometryChange();
}
void BlockBusItem::setWidth(const double & w) {
pen_width = w;
update();
}
void BlockBusItem::setColor(const QColor & c) {
pu.setColor(c);
bu.setColor(c);
update();
}
void BlockBusItem::markAsInput() {
mark_in = true;
mark_out = false;
}
void BlockBusItem::markAsOutput() {
mark_in = false;
mark_out = true;
}
void BlockBusItem::unmark() {
mark_in = mark_out = false;
}
void BlockBusItem::simplify(bool full) {
int pcnt = pol.size();
for (int s = 0; s < segments.size(); ++s) {
if (pol[segments[s].first] != pol[segments[s].second]) continue;
int ti = segments[s].first, fi = segments[s].second;
segments.removeAt(s);
pol.remove(fi);
for (int i = 0; i < segments.size(); ++i) {
if (segments[i].first == fi) segments[i].first = ti;
if (segments[i].second == fi) segments[i].second = ti;
if (segments[i].first > fi) segments[i].first--;
if (segments[i].second > fi) segments[i].second--;
}
}
if (full) {
QList<int> segs;
for (int p = 0; p < pol.size(); ++p) {
if (pointSegmentsCount(p, &segs) != 2) continue;
int s0 = segs[0], s1 = segs[1];
QPointF cp = pol[p], sp[2];
for (int i = 0; i < 2; ++i) {
if (segments[segs[i]].first == p) sp[i] = pol[segments[segs[i]].second];
else sp[i] = pol[segments[segs[i]].first];
}
QLineF l0(sp[0], cp), l1(cp, sp[1]);
if (qAbs(l0.angle() - l1.angle()) > 0.1) continue;
if (segments[s0].first == p) {
if (segments[s1].first == p) segments[s0].first = segments[s1].second;
else segments[s0].first = segments[s1].first;
} else {
if (segments[s1].first == p) segments[s0].second = segments[s1].second;
else segments[s0].second = segments[s1].first;
}
segments.removeAt(s1);
pol.remove(p);
for (int i = 0; i < segments.size(); ++i) {
if (segments[i].first >= p) segments[i].first--;
if (segments[i].second >= p) segments[i].second--;
}
p = -1;
}
}
if (pcnt == pol.size()) return;
updateGeometry();
//if (scene()) scene()->update();
}
void BlockBusItem::adjustLine() {
}
int BlockBusItem::endpointCount() const {
return endpoints().size();
}
QList<BlockItem * > BlockBusItem::connectedBlocks() const {
QList<BlockItemPin * > pins = connections_.values();
QSet<BlockItem * > ret;
foreach (BlockItemPin * p, pins)
ret << p->parent();
return ret.toList();
}
QList<BlockItemPin * > BlockBusItem::connectedPins() const {
return connections_.values();
}
void BlockBusItem::setBusState(bool state) {
int s = state ? 1 : 0;
if (state_ == s) return;
state_ = s;
update();
}
void BlockBusItem::clearBusState() {
if (state_ == -1) return;
state_ = -1;
update();
}
QByteArray BlockBusItem::save() const {
ChunkStream cs;
cs << cs.chunk(1, busType()) << cs.chunk(2, busName()) << cs.chunk(3, width()) << cs.chunk(4, pen())
<< cs.chunk(5, brush()) << cs.chunk(6, pol) << cs.chunk(7, segments) << cs.chunk(8, props)
<< cs.chunk(9, im_bus_scale) << cs.chunk(10, im_end_scale);
return cs.data();
}
void BlockBusItem::load(const QByteArray & data) {
clear();
if (data.isEmpty()) return;
ChunkStream cs(data);
while (!cs.atEnd()) {
switch (cs.read()) {
case 1: setBusType(cs.getData<int>()); break;
case 2: setBusName(cs.getData<QString>()); break;
case 3: setWidth(cs.getData<double>()); break;
case 4: setPen(cs.getData<QPen>()); break;
case 5: setBrush(cs.getData<QBrush>()); break;
case 6: pol = cs.getData<QPolygonF>(); break;
case 7: segments = cs.getData<QList<QPair<int, int> > >(); break;
case 8: props = cs.getData<QList<BlockItem::Property> >(); break;
case 9: im_bus_scale = cs.getData<double>(); break;
case 10: im_end_scale = cs.getData<double>(); break;
}
}
updateGeometry();
}
BlockBusItem * BlockBusItem::copy() const {
return new BlockBusItem(*this);
}
void BlockBusItem::saveState() {
segments_s = segments;
ends_ind_s = ends_ind;
ends_s = ends;
pol_s = pol;
}
void BlockBusItem::restoreState() {
segments = segments_s;
ends_ind = ends_ind_s;
ends = ends_s;
pol = pol_s;
}
void BlockBusItem::updateGeometry() {
ends = endpoints();
ends_ind.clear();
for (int e = 0; e < ends.size(); ++e) {
int ce = ends[e];
for (int s = 0; s < segments.size(); ++s) {
if (segments[s].first == ce) {
ends_ind << QPair<int, int>(segments[s].first, segments[s].second);
break;
}
if (segments[s].second == ce) {
ends_ind << QPair<int, int>(segments[s].second, segments[s].first);
break;
}
}
}
reconnect();
prepareGeometryChange();
}
bool BlockBusItem::checkDelete() {
if (pol.size() >= 2 && segments.size() >= 1) return false;
deleteLater();
return true;
}
void BlockBusItem::emitAction(BlockItemBase::Action a) {
QMetaObject::invokeMethod(scene()->views().back(), "schemeAction", Q_ARG(BlockItemBase::Action, a), Q_ARG(QList<QGraphicsItem*>, QList<QGraphicsItem*>() << this));
QMetaObject::invokeMethod(scene()->views().back(), "connectionsChanged");
}
QVector<int> BlockBusItem::endpoints() const {
QVector<int> counts(pol.size(), 0), ret;
for (int i = 0; i < segments.size(); ++i) {
counts[segments[i].first]++;
counts[segments[i].second]++;
}
for (int i = 0; i < counts.size(); ++i) {
if (counts[i] == 1)
ret << i;
}
return ret;
}
QVector<int> BlockBusItem::endpointLine(int ep, double angle) const {
QVector<int> ret;
int seg = -1;
int np = segmentPointPair(ep, &seg), pp = np;
if (ep < 0 || np < 0) return ret;
if (pol[np] == pol[ep]) return ret;
//QPointF sp = pol[np] - pol[ep];
QLineF l(pol[ep], pol[np]);
//qDebug() << "first" << l.angle() << angle << (l.angle() != angle);
if (qAbs(l.angle() - angle) > 0.1) return ret;
//qDebug() << "check next" << segments.size();
for (int i = 0; i < segments.size(); ++i) {
//qDebug() << i << np << pointSegmentsCount(np);
if (np < 0) break;
if (pointSegmentsCount(np) != 2) break;
if (i > 0) {
QLineF l(pol[pp], pol[np]);
//qDebug() << i << l.angle() << angle;
if (qAbs(l.angle() - angle) > 0.1) break;
}
ret << np;
pp = np;
np = neighborSegmentPoint(np, &seg);
}
return ret;
}
int BlockBusItem::pointSegmentsCount(int point, QList<int> * segs) const {
int ret = 0;
if (segs) segs->clear();
for (int i = 0; i < segments.size(); ++i)
if (segments[i].first == point || segments[i].second == point) {
ret++;
if (segs) segs->append(i);
}
return ret;
}
int BlockBusItem::neighborSegmentPoint(int point, int * seg) const {
if (point < 0 || !seg) return -1;
for (int i = 0; i < segments.size(); ++i) {
if (i == *seg) continue;
if (segments[i].first == point) {*seg = i; return segments[i].second;}
if (segments[i].second == point) {*seg = i; return segments[i].first ;}
}
return -1;
}
void BlockBusItem::testPoint(QPointF pos, int * sel_point, int * sel_segment) {
for (int i = 0; i < pol.size(); ++i) {
if ((pol[i] - pos).manhattanLength() <= 10.) { // Point
*sel_point = i;
*sel_segment = -1;
return;
}
}
for (int i = 0; i < segments.size(); ++i) {
if (distPointToLine(pol[segments[i].first], pol[segments[i].second], pos) <= 7.) { // Segment
*sel_point = -1;
*sel_segment = i;
return;
}
}
*sel_point = -1;
*sel_segment = -1;
}
void BlockBusItem::hoverEnterEvent(QGraphicsSceneHoverEvent * e) {
tt = bus_name + (bus_name.isEmpty() ? "" : "\n\n") + tr("Add point: Ctrl + LeftClick\nRemove point\\segment: Ctrl + RightClick\nNew branch: Shift + LeftClick\nRemove connection: Shift + RightClick");
}
void BlockBusItem::hoverMoveEvent(QGraphicsSceneHoverEvent * e) {
if (temp_) return;
QPointF sp = e->scenePos();
int pp = selPoint;
int ps = selSegment;
bool empt = !(selPoint >= 0 || selSegment >= 0);
testPoint(sp, &selPoint, &selSegment);
if ((selPoint >= 0 && pp != selPoint) || (selSegment >= 0 && ps != selSegment)) {
if (((BlockView *)scene()->views().back())->isBlockAnimationEnabled()) {
setPointSize(0);
anim_point_size.start();
} else setPointSize(anim_point_size.endValue().toDouble());
}
if (selPoint >= 0 || selSegment >= 0) {
if (empt) {
QList<BlockItemPin * > pins = connectedPins();
foreach (BlockItemPin * p, pins) {
p->animAccept();
}
}
setToolTip(tt);
update();
return;
}
setToolTip(QString());
QList<QGraphicsItem * > il = scene()->items(sp, Qt::ContainsItemBoundingRect, Qt::DescendingOrder), bil;
bil << this;
for (int i = 0; i < il.size(); ++i) {
QGraphicsItem * b = il[i];
if (b->data(1005) == "connection" && b != this) {
int tp = -1, ts = -1;
((BlockBusItem*)b)->testPoint(sp, &tp, &ts);
if (tp >= 0 || ts >= 0) {
foreach (QGraphicsItem * b2, bil)
b2->stackBefore(b);
break;
}
bil << b;
}
}
update();
}
void BlockBusItem::hoverLeaveEvent(QGraphicsSceneHoverEvent * e) {
if (temp_) return;
selPoint = selSegment = -1;
setPen(pu); setBrush(bu);
setToolTip(QString());
anim_point_size.stop();
update();
QGraphicsObject::hoverLeaveEvent(e);
}
void BlockBusItem::mousePressEvent(QGraphicsSceneMouseEvent * e) {
if (temp_) return;
lp = quantize(e->scenePos(), grid_step);
if (new_segment) {
QMetaObject::invokeMethod(scene()->views().back(), "newBranchCancel");
}
new_segment = false;
if ((selPoint < 0 || selPoint > pol.size() - 1) && (selSegment < 0)) {
QGraphicsObject::mousePressEvent(e);
return;
}
int btncnt = 0;
if (endpoints().contains(selPoint) && e->button() == Qt::LeftButton)
QMetaObject::invokeMethod(scene()->views().back(), "startBusPointMove", Q_ARG(int, busType()));
if (e->buttons().testFlag(Qt::LeftButton)) btncnt++;
if (e->buttons().testFlag(Qt::RightButton)) btncnt++;
if (e->buttons().testFlag(Qt::MidButton)) btncnt++;
if (btncnt > 0) mm_mods = e->modifiers();
//qDebug() << "press" << e;
if (btncnt >= 2 && e->button() == Qt::RightButton) {
mm_cancel = true;
moved = false;
QPointF lp = qp - press_pos;
//qDebug() << lp;
if (selPoint >= 0 && selPoint <= pol.size() - 1) {
pol[selPoint] += lp;
}
if (selSegment >= 0 && selSegment <= segments.size() - 1) {
pol[segments[selSegment].first] += lp;
pol[segments[selSegment].second] += lp;
}
moved = true;
prepareGeometryChange();
return;
}
if (e->modifiers().testFlag(Qt::ShiftModifier)) {
if (e->buttons().testFlag(Qt::LeftButton)) {
if (selSegment >= 0)
press_pos = quantize(nearestPointOnLine(pol[segments[selSegment].first], pol[segments[selSegment].second], e->scenePos()), grid_step);
else {
if (selPoint >= 0)
press_pos = pol[selPoint];
else
return;
}
if (max_ep >= 2) {
if (endpointCount() >= max_ep)
if (pointSegmentsCount(selPoint) >= 2 || selSegment >= 0)
return;
}
QMetaObject::invokeMethod(scene()->views().back(), "newBranch", Q_ARG(BlockBusItem * , this));
new_segment = true;
return;
}
if (e->buttons().testFlag(Qt::RightButton)) {
deleteLater();
}
}
if (e->modifiers().testFlag(Qt::ControlModifier)) {
if (e->buttons().testFlag(Qt::RightButton)) {
if (selPoint >= 0 && selPoint <= pol.size() - 1) {
removePoint(selPoint);
simplify();
if (!checkDelete()) emitAction(BlockItemBase::BusPointRemove);
return;
}
if (selSegment >= 0 && selSegment <= segments.size() - 1) {
removeSegment(selSegment);
simplify();
if (!checkDelete()) emitAction(BlockItemBase::BusSegmentRemove);
return;
}
}
if (e->buttons().testFlag(Qt::LeftButton) && selSegment >= 0) {
if (addPoint(e->scenePos()) >= 0)
emitAction(BlockItemBase::BusPointAdd);
return;
}
}
if (e->modifiers().testFlag(Qt::ShiftModifier)) {
if (e->buttons().testFlag(Qt::RightButton)) {
if (deleted) return;
deleted = true;
}
}
}
void BlockBusItem::mouseMoveEvent(QGraphicsSceneMouseEvent * e) {
if (temp_ || mm_cancel) return;
if (((selPoint < 0 || selPoint > pol.size() - 1) && (selSegment < 0)) && !new_segment) {
QGraphicsObject::mouseMoveEvent(e);
return;
}
qp = quantize(e->scenePos(), grid_step);
lp = qp - lp;
if (e->buttons().testFlag(Qt::LeftButton) && mm_mods.testFlag(Qt::ShiftModifier) && new_segment) {
QMetaObject::invokeMethod(scene()->views().back(), "newBranchTrace", Q_ARG(BlockBusItem * , this), Q_ARG(QPointF, e->scenePos()));
return;
}
if (new_segment) {
new_end = qp;
prepareGeometryChange();
} else {
if (e->buttons().testFlag(Qt::LeftButton)) {
lm_point = selPoint >= 0;
if (selPoint >= 0 && selPoint <= pol.size() - 1)
pol[selPoint] += lp;
if (selSegment >= 0 && selSegment <= segments.size() - 1) {
pol[segments[selSegment].first] += lp;
pol[segments[selSegment].second] += lp;
}
moved = true;
prepareGeometryChange();
}
}
lp = qp;
}
void BlockBusItem::mouseReleaseEvent(QGraphicsSceneMouseEvent * e) {
mm_mods = 0;
int btncnt = 0;
if (e->buttons().testFlag(Qt::LeftButton)) btncnt++;
if (e->buttons().testFlag(Qt::RightButton)) btncnt++;
if (e->buttons().testFlag(Qt::MidButton)) btncnt++;
if (btncnt == 0) mm_cancel = false;
if (new_segment) {
QMetaObject::invokeMethod(scene()->views().back(), "newBranchAccept", Q_ARG(BlockBusItem * , this));
updateGeometry();
selPoint = selSegment = -1;
}
if (moved) {
simplify(false);
if (lm_point) {
emitAction(BlockItemBase::BusPointMove);
} else {
reconnect();
emitAction( BlockItemBase::BusSegmentMove);
}
}
QMetaObject::invokeMethod(scene()->views().back(), "endBusPointMove");
moved = new_segment = false;
QGraphicsObject::mouseReleaseEvent(e);
}
void BlockBusItem::paint(QPainter * p, const QStyleOptionGraphicsItem * o, QWidget * w) {
ph.setWidthF(pen_width + point_size / 2.);
pu.setWidthF(pen_width);
pa.setWidthF(pen_width);
pr.setWidthF(pen_width);
pn.setWidthF(pen_width);
if (pol.size() < 2) return;
if (selPoint >= 0 || selSegment >= 0) {
p->setPen(pa);
p->setBrush(ba);
} else {
p->setPen(pu);
p->setBrush(bu);
}
//if (mark_in) {p->setPen(pa); p->setBrush(ba);}
//if (mark_out) {p->setPen(pr); p->setBrush(br);}
if (im_bus.isNull()) {
for (int i = 0; i < segments.size(); ++i) {
p->drawLine(pol[segments[i].first], pol[segments[i].second]);
}
} else {
QBrush br;
br.setTextureImage(im_bus);
for (int i = 0; i < segments.size(); ++i) {
QPointF sp(pol[segments[i].first]), ep(pol[segments[i].second]);
QTransform tf;
tf.translate(sp.x(), sp.y());
tf.rotate(-QLineF(sp, ep).angle());
tf.translate(0., -im_bus.height() / 2. * im_bus_scale);
tf.scale(im_bus_scale, im_bus_scale);
/*
br.setTransform(tf);
p->setPen(QPen(br, im_bus.height(), Qt::SolidLine, Qt::FlatCap, Qt::BevelJoin));
p->drawLine(sp, ep);
*/
p->save();
p->setTransform(tf, true);
p->setPen(Qt::NoPen);
p->setBrush(br);
//p->drawLine(QPointF(0., 0.), QPointF(QLineF(sp, ep).length(), 0.));
p->drawRect(QRectF(0., 0., QLineF(sp, ep).length() / qMax<double>(im_bus_scale, 1E-3), im_bus.height()));
p->restore();
}
}
if (!im_end.isNull()) {
for (int i = 0; i < ends_ind.size(); ++i) {
QPointF sp = pol[ends_ind[i].first], ep = pol[ends_ind[i].second];
QTransform tf;
tf.translate(sp.x(), sp.y());
tf.rotate(-QLineF(sp, ep).angle());
tf.translate(-pen_width, -im_end.height() / 2. * im_end_scale);
tf.scale(im_end_scale, im_end_scale);
p->save();
p->setTransform(tf, true);
p->drawImage(0, 0, im_end);
p->restore();
}
}
if (state_ >= 0) {
if (state_ == 0) {
pr.setWidthF(pen_width + 1.);
p->setPen(pr);
} else if (state_ == 1) {
pa.setWidthF(pen_width + 1.);
p->setPen(pa);
}
p->setOpacity(0.5);
for (int i = 0; i < segments.size(); ++i) {
p->drawLine(pol[segments[i].first], pol[segments[i].second]);
}
p->setOpacity(1.);
}
if (!im_bus.isNull() && (selPoint >= 0 || selSegment >= 0)) {
p->setPen(pa);
p->setBrush(ba);
for (int i = 0; i < segments.size(); ++i) {
p->drawLine(pol[segments[i].first], pol[segments[i].second]);
}
}
//if (mark_in) {p->setPen(pa); p->setBrush(ba);}
//if (mark_out) {p->setPen(pr); p->setBrush(br);}
if (selPoint >= 0) {
p->save();
p->setPen(ph);
p->setBrush(bh);
p->translate(pol[selPoint]);
p->drawEllipse(QPointF(0, 0), point_size, point_size);
p->restore();
}
if (selSegment >= 0) {
p->save();
p->setPen(ph);
p->drawLine(pol[segments[selSegment].first], pol[segments[selSegment].second]);
p->restore();
}
}
void BlockBusItem::setPointSize(double s) {
point_size = s;
update();
}
QRectF BlockBusItem::boundingRect() const {
QPolygonF p(pol);
if (new_segment) p << new_end;
return enlargedRect(p.boundingRect(), 0, 0, 10.f);
}

View File

@@ -0,0 +1,143 @@
#ifndef BLOCKBUSITEM_H
#define BLOCKBUSITEM_H
#include "blockitem.h"
/// data:
/// 1002 - flag for move parent (true)
/// 1003 - flag for visualize selection (true)
/// 1004 - BlockItemPin ("pin")
/// 1005 - BlockBusItem ("connection")
/// 1006 - BlockItem ("item")
/// 1007 - BlockItem selection ("item_selection")
/// 1008 - item is NOT decor, ignore for function decors() (true)
/// 1009 - item is scene decor ("decor")
/// 1010 - BlockItem decor (src text for QGraphicsSimpleTextItem)
/// 1011 - item is BlockItem decor ("decor")
/// 1100 - flag for correct move (true)
class BlockBusItem: public QGraphicsObject, public PropertyStorage {
Q_OBJECT
Q_INTERFACES(QGraphicsItem)
Q_PROPERTY(double pointSize READ pointSize WRITE setPointSize DESIGNABLE false SCRIPTABLE false)
friend class BlockView;
public:
BlockBusItem(bool temp = false);
BlockBusItem(const BlockBusItem & other);
~BlockBusItem() {;}
void setGridStep(double gs) {grid_step = gs;}
void setEndpointsNumber(int num) {max_ep = num;}
void setImages(const QImage & bus, const QImage & end = QImage()) {im_bus = bus; im_end = end; update();}
void setBusImageScale(double s) {im_bus_scale = s; update();}
void setEndpointImageScale(double s) {im_end_scale = s; update();}
void setBusType(int type_) {bus_type = type_;}
void setBusName(const QString & name) {bus_name = name;}
int busType() const {return bus_type;}
QString busName() const {return bus_name;}
double busImageScale() const {return im_bus_scale;}
double endpointImageScale() const {return im_end_scale;}
void appendPoint(const QPointF & p);
void appendPoint(qreal x, qreal y);
void testPoint(QPointF pos, int * sel_point, int * sel_segment);
void clear();
/*void setStart(const QPointF & p) {pol[0] = p; scene()->update();}
void setStart(qreal x, qreal y) {setStart(QPointF(x, y));}
void setFinish(const QPointF & p) {pol[pol.size() - 1] = p; scene()->update();}
void setFinish(qreal x, qreal y) {setFinish(QPointF(x, y));}
void setPoint(int index, const QPointF & p) {pol[index] = p; scene()->update();}
void setPoint(int index, qreal x, qreal y) {setPoint(index, QPointF(x, y));}*/
void setPen(const QPen & p) {p_ = p; update();}
QPen pen() const {return p_;}
void setBrush(const QBrush & b) {b_ = b; update();}
QBrush brush() const {return b_;}
//void disconnectBrick() {BrickBase::disconnect(brickFrom, portFrom, brickTo, portTo);}
void movePolyline(const QPointF & dp);
void movePoint(int index, const QPointF & dp);
double width() const {return pen_width;}
void setWidth(const double & w);
void setColor(const QColor & c);
int addPoint(const QPointF & point, bool update = true);
int segmentPointPair(int point, int * seg = 0) const;
void removePoint(int index);
void removeSegment(int index);
void markAsInput();
void markAsOutput();
void unmark();
void simplify(bool full = true);
void adjustLine();
int endpointCount() const;
bool isBusSelected() const {return selSegment >= 0 || selPoint >= 0;}
QList<BlockItem * > connectedBlocks() const;
QList<BlockItemPin * > connectedPins() const;
void setBusState(bool state);
bool busState() const {return state_ > 0;}
void clearBusState();
QByteArray save() const;
void load(const QByteArray & data);
BlockBusItem * copy() const;
void saveState();
void restoreState();
enum {Type = UserType + 2};
protected:
void _init();
void reconnect();
void updateGeometry();
bool checkDelete();
void emitAction(BlockItemBase::Action a);
QVector<int> endpoints() const;
QVector<int> endpointLine(int ep, double angle) const;
int pointSegmentsCount(int point, QList<int> * segs = 0) const;
int neighborSegmentPoint(int point, int * seg) const;
int type() const {return Type;}
QRectF boundingRect() const;
bool sceneEvent(QEvent * e);
void hoverEnterEvent(QGraphicsSceneHoverEvent * e);
void hoverMoveEvent(QGraphicsSceneHoverEvent * e);
void hoverLeaveEvent(QGraphicsSceneHoverEvent * e);
void mousePressEvent(QGraphicsSceneMouseEvent * e);
void mouseMoveEvent(QGraphicsSceneMouseEvent * e);
void mouseReleaseEvent(QGraphicsSceneMouseEvent * e);
void paint(QPainter * p, const QStyleOptionGraphicsItem * o, QWidget * w = 0);
QPointF lp, new_start, new_end, press_pos, qp;
QPen p_, ph, pu, pa, pr, pn;
QBrush b_, bh, bu, ba, br;
QString tt, bus_name;
QList<QPair<int, int> > segments, ends_ind, segments_s, ends_ind_s;
QMap<int, BlockItemPin * > connections_;
QVector<int> ends, ends_s;
QImage im_bus, im_end;
QPolygonF pol, bpol, pol_s;
Qt::KeyboardModifiers mm_mods;
bool temp_;
double pen_width, grid_step, im_bus_scale, im_end_scale;
int selPoint, selSegment, max_ep, bus_type, state_;
bool moved, deleted, mark_in, mark_out, new_segment, mm_cancel, lm_point;
private:
double pointSize() const {return point_size;}
void setPointSize(double s);
double point_size;
QPropertyAnimation anim_point_size;
};
inline QDataStream & operator <<(QDataStream & s, const BlockBusItem * b) {s << b->save(); return s;}
inline QDataStream & operator >>(QDataStream & s, BlockBusItem *& b) {
QByteArray ba; s >> ba;
b = new BlockBusItem();
b->load(ba);
return s;
}
#endif // BLOCKBUSITEM_H

View File

@@ -0,0 +1,389 @@
#include "blockeditor.h"
#include "ui_blockeditor.h"
#include "drawtools.h"
#include "blockview.h"
#include <QToolBar>
#include <QComboBox>
#include <QFileDialog>
#include <QFile>
#include <QTimer>
BlockEditor::BlockEditor(QWidget *parent) : QWidget(parent), ui(new Ui::BlockEditor) {
init = false;
m_editorMode = false;
m_pinsEditable = true;
ui->setupUi(this);
src_title = windowTitle();
connect(ui->blockView->scene(), SIGNAL(selectionChanged()), this, SLOT(selectionChanged()));
block.setFlags(0);
ui->blockView->addItem(&block);
ui->blockView->viewport()->installEventFilter(this);
DrawTools * drawtools = new DrawTools(ui->blockView);
connect(drawtools, SIGNAL(itemCreated(QGraphicsItem*)), this, SLOT(addItem(QGraphicsItem*)));
drawtools->textEditCombo()->addItems(QStringList() << "%name" << "%value" << "%id");
ui->layoutProperties->addWidget(drawtools->propertyWidget());
ui->actionRemove_items->setEnabled(false);
ui->button_color->setColor(Qt::lightGray);
ui->treePins->setItemDelegateForColumn(1, new PinBusDelegate());
connect(ui->treePins, SIGNAL(itemChanged(QTreeWidgetItem*,int)), this, SLOT(updateBlock()));
ui->treePins->viewport()->installEventFilter(this);
QToolBar * bar;
bar = new QToolBar(ui->widgetBar);
bar->setOrientation(Qt::Vertical);
bar->addActions(drawtools->actionsForAdd());
ui->widgetBar->setMinimumSize(bar->sizeHint());
bar = new QToolBar(ui->widgetBarZ);
bar->setOrientation(Qt::Vertical);
bar->addActions(drawtools->actionsForZ());
bar->addSeparator();
bar->addActions(QList<QAction*>() << ui->actionRemove_items);
ui->widgetBarZ->setMinimumSize(bar->sizeHint());
init = true;
on_buttonClear_clicked();
}
BlockEditor::~BlockEditor() {
init = false;
delete ui;
}
void BlockEditor::loadFile(QString path) {
if (path.isEmpty()) return;
QFile f(path);
if (f.open(QIODevice::ReadOnly)) {
cur_file = path;
loadModel(f.readAll());
QDir::setCurrent(QFileInfo(path).dir().path());
}
setWindowTitle(src_title + QString(" - %1").arg(QFileInfo(path).baseName()));
}
void BlockEditor::loadModel(const QByteArray &model) {
BlockItem b;
b.loadModel(model);
ui->spin_w->setValue(b.width());
ui->spin_h->setValue(b.height());
ui->spin_margin->setValue(b.pinsMargin());
ui->button_color->setColor(b.color());
block.loadModel(model);
treePinsClear();
ui->treePins->blockSignals(true);
QVector<BlockItemPin * > pins = block.pins();
foreach (BlockItemPin * p, pins) {
QTreeWidgetItem * ti = new QTreeWidgetItem(QStringList() << p->text() << QString::number(p->busType()));
ti->setData(0, Qt::UserRole, qulonglong(p));
ti->setData(0, Qt::UserRole + 1, (int)p->alignment());
ti->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsDragEnabled);
pin_tli[p->alignment()]->addChild(ti);
}
foreach (QGraphicsItem * i, block.decors()) {
i->setData(1002, false);
i->setData(1100, true);
}
ui->treePins->blockSignals(false);
}
QByteArray BlockEditor::saveModel() {
return block.saveModel();
}
void BlockEditor::setEditorMode(bool editorMode) {
m_editorMode = editorMode;
ui->buttonClear->setVisible(!editorMode);
ui->buttonSave->setVisible(!editorMode);
ui->buttonSaveAs->setVisible(!editorMode);
ui->buttonLoad->setVisible(!editorMode);
}
void BlockEditor::setPinsEditable(bool pinsEditable) {
m_pinsEditable = pinsEditable;
ui->treePins->setVisible(pinsEditable);
ui->buttonPinAdd->setVisible(pinsEditable);
ui->buttonPinClear->setVisible(pinsEditable);
ui->buttonPinDelete->setVisible(pinsEditable);
ui->buttonPinDup->setVisible(pinsEditable);
ui->groupPins->setVisible(pinsEditable);
}
void BlockEditor::selectionChanged() {
if (!init) return;
ui->actionRemove_items->setEnabled(!ui->blockView->scene()->selectedItems().isEmpty());
}
void BlockEditor::addItem(QGraphicsItem *item) {
block.addDecor(item);
item->setData(1002, false);
item->setData(1100, true);
}
void BlockEditor::updateBlock() {
block.setSize(ui->spin_w->value(), ui->spin_h->value());
block.setColor(ui->button_color->color());
block.setPinsMargin(ui->spin_margin->value());
}
void BlockEditor::treePinsClear() {
ui->treePins->blockSignals(true);
ui->treePins->clear();
QFont bf(font()); bf.setBold(true);
QList<int> al = QList<int>() << Qt::AlignLeft << Qt::AlignRight << Qt::AlignTop << Qt::AlignBottom;
QStringList an = QStringList() << "Left" << "Right" << "Top" << "Bottom";
pin_tli.clear();
for (int i = 0; i < al.size(); ++i) {
QTreeWidgetItem * ti = new QTreeWidgetItem();
ti->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDropEnabled);
ti->setData(0, Qt::UserRole, al[i]);
ti->setText(0, an[i]);
ti->setFont(0, bf);
ui->treePins->addTopLevelItem(ti);
ti->setFirstColumnSpanned(true);
ti->setExpanded(true);
pin_tli[al[i]] = ti;
}
ui->treePins->blockSignals(false);
}
bool BlockEditor::eventFilter(QObject *o, QEvent *e) {
if (!init) QWidget::eventFilter(o, e);
if (o == ui->treePins->viewport()) {
if (e->type() == QEvent::Drop) {
QTimer::singleShot(0, this, SLOT(arrangePins()));
}
}
if (o == ui->blockView->viewport()) {
if (e->type() == QEvent::Resize) {
ui->blockView->centerOn(&block);
}
}
return QWidget::eventFilter(o, e);
}
void BlockEditor::on_actionRemove_items_triggered() {
QList<QGraphicsItem*> si = ui->blockView->scene()->selectedItems();
foreach (QGraphicsItem * i, si)
block.removeDecor(i);
}
void BlockEditor::on_buttonSave_clicked() {
if (cur_file.isEmpty()) {
on_buttonSaveAs_clicked();
return;
}
QFile f(cur_file);
if (f.open(QIODevice::WriteOnly)) {
f.write(saveModel());
//setWindowTitle(src_title + QString(" - %1").arg(QFileInfo(c).baseName()));
}
}
void BlockEditor::on_buttonSaveAs_clicked() {
QString c = QFileDialog::getSaveFileName(this, "Save block model to file", cur_file, "*.blockmodel");
if (!c.isEmpty()) {
QFile f(c);
if (f.open(QIODevice::WriteOnly)) {
cur_file = c;
f.write(saveModel());
setWindowTitle(src_title + QString(" - %1").arg(QFileInfo(c).baseName()));
}
}
}
void BlockEditor::on_buttonLoad_clicked() {
QString c = QFileDialog::getOpenFileName(this, "Save block model to file", cur_file, "*.blockmodel");
loadFile(c);
}
void BlockEditor::on_buttonClear_clicked() {
BlockItem b;
ui->spin_w->setValue(b.width());
ui->spin_h->setValue(b.height());
ui->spin_margin->setValue(b.pinsMargin());
ui->button_color->setColor(b.color());
block.loadModel(QByteArray());
treePinsClear();
}
void BlockEditor::on_buttonPinAdd_clicked() {
ui->treePins->blockSignals(true);
QTreeWidgetItem * ti = new QTreeWidgetItem(QStringList() << "" << "0");
ti->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsDragEnabled);
ti->setData(0, Qt::UserRole, qulonglong(block.addPin(Qt::AlignLeft, ti->text(1).toInt(), ti->text(0))));
ti->setData(0, Qt::UserRole + 1, (int)Qt::AlignLeft);
pin_tli[Qt::AlignLeft]->addChild(ti);
ui->treePins->setCurrentItem(ti);
ui->treePins->blockSignals(false);
updateBlock();
}
void BlockEditor::on_buttonPinDup_clicked() {
QTreeWidgetItem * ci = ui->treePins->currentItem();
if (ci == 0) return;
ui->treePins->blockSignals(true);
QTreeWidgetItem * ti = ci->clone();
ti->setText(0, ti->text(0));
ti->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsDragEnabled);
Qt::Alignment al = (Qt::Alignment)ci->data(0, Qt::UserRole + 1).toInt();
ti->setData(0, Qt::UserRole, qulonglong(block.addPin(al, ci->text(1).toInt(), ci->text(0))));
ti->setData(0, Qt::UserRole + 1, (int)al);
pin_tli[al]->addChild(ti);
ui->treePins->setCurrentItem(ti);
ui->treePins->blockSignals(false);
}
void BlockEditor::on_buttonPinDelete_clicked() {
ui->treePins->blockSignals(true);
QList<QTreeWidgetItem*> si = ui->treePins->selectedItems();
foreach (QTreeWidgetItem * i, si) {
if (!i->parent()) continue;
block.removePin((BlockItemPin*)(i->data(0, Qt::UserRole).toLongLong()));
delete i;
}
ui->treePins->blockSignals(false);
}
void BlockEditor::on_buttonPinClear_clicked() {
treePinsClear();
block.clearPins();
}
void BlockEditor::on_treePins_itemChanged(QTreeWidgetItem * item, int column) {
if (!item) return;
BlockItemPin * pin = (BlockItemPin*)item->data(0, Qt::UserRole).toULongLong();
if (!pin) return;
switch (column) {
case 0:
ui->treePins->blockSignals(true);
item->setText(0, item->text(0));
pin->setText(item->text(0));
ui->treePins->blockSignals(false);
break;
case 1: pin->setBusType(item->text(1).toInt()); break;
};
}
void BlockEditor::arrangePins() {
QVector<BlockItemPin * > pins = block.pins();
// block.clearPins();
QList<QTreeWidgetItem*> tli = pin_tli.values();
foreach (QTreeWidgetItem * ti, tli) {
for (int i = 0; i < ti->childCount(); ++i) {
foreach (BlockItemPin * p, pins)
if (p == (BlockItemPin*)(ti->child(i)->data(0, Qt::UserRole).toULongLong())) {
p->setAlignment((Qt::Alignment)ti->data(0, Qt::UserRole).toInt());
BlockItemPin * np = block.addPin(p, false);
ti->child(i)->setData(0, Qt::UserRole, qulonglong(np));
ti->child(i)->setData(0, Qt::UserRole + 1, ti->data(0, Qt::UserRole).toInt());
break;
}
}
}
// for (int i = 0; i < ui->treePins->topLevelItemCount(); ++i) {
// QTreeWidgetItem * ti = ui->treePins->topLevelItem(i);
// if (tli.contains(ti)) continue;
// ti = ui->treePins->takeTopLevelItem(i);
// pin_tli[ti->data(0, Qt::UserRole + 1).toInt()]->addChild(ti);
// foreach (BlockItemPin * p, pins)
// if (p->text() == ti->text(0)) {
// p->setAlignment((Qt::Alignment)ti->data(0, Qt::UserRole + 1).toInt());
// block.addPin(p, false);
// break;
// }
// }
block.arrangePins();
}
/// ***********************************************************
/// ***********************************************************
/// ***********************************************************
/// ***********************************************************
QWidget * PinAlignDelegate::createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const {
QComboBox * combo = new QComboBox(parent);
int cv = index.data().toInt();
combo->addItem("Left", int(Qt::AlignLeft)); if (cv == Qt::AlignLeft) combo->setCurrentIndex(0);
combo->addItem("Right", int(Qt::AlignRight)); if (cv == Qt::AlignRight) combo->setCurrentIndex(1);
combo->addItem("Top", int(Qt::AlignTop)); if (cv == Qt::AlignTop) combo->setCurrentIndex(2);
combo->addItem("Bottom", int(Qt::AlignBottom)); if (cv == Qt::AlignBottom) combo->setCurrentIndex(3);
combo->setGeometry(option.rect);
return combo;
}
QString PinAlignDelegate::displayText(const QVariant & value, const QLocale & locale) const {
int cv = value.toInt();
switch (cv) {
case Qt::AlignLeft: return "Left"; break;
case Qt::AlignRight: return "Right"; break;
case Qt::AlignTop: return "Top"; break;
case Qt::AlignBottom: return "Bottom"; break;
}
return "unknown";
}
void PinAlignDelegate::setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const {
model->setData(index, ((QComboBox*)editor)->itemData(((QComboBox*)editor)->currentIndex()).toInt());
}
/// ***********************************************************
/// ***********************************************************
/// ***********************************************************
/// ***********************************************************
QWidget * PinBusDelegate::createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const {
QSpinBox * spin = new QSpinBox(parent);
spin->setMinimum(-2147483648);
spin->setMaximum(2147483647);
spin->setValue(index.data().toInt());
return spin;
}
QString PinBusDelegate::displayText(const QVariant & value, const QLocale & locale) const {
int cv = value.toInt();
return QString::number(cv);
}
void PinBusDelegate::setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const {
model->setData(index, ((QSpinBox*)editor)->value());
}
//void BlockEditor::on_treePins_itemSelectionChanged() {
// arrangePins();
// qDebug() << "111111111111111";
//}

View File

@@ -0,0 +1,91 @@
#ifndef BLOCKEDITOR_H
#define BLOCKEDITOR_H
#include <QWidget>
#include <QTreeWidgetItem>
#include <QStyledItemDelegate>
#include "blockitem.h"
namespace Ui {
class BlockEditor;
}
class BlockEditor : public QWidget
{
Q_OBJECT
Q_PROPERTY(bool editorMode READ editorMode WRITE setEditorMode)
Q_PROPERTY(bool pinsEditable READ pinsEditable WRITE setPinsEditable)
public:
explicit BlockEditor(QWidget *parent = 0);
~BlockEditor();
bool editorMode() const {return m_editorMode;}
bool pinsEditable() const {return m_pinsEditable;}
public slots:
void loadFile(QString path);
void loadModel(const QByteArray & model);
QByteArray saveModel();
void setEditorMode(bool editorMode);
void setPinsEditable(bool pinsEditable);
private slots:
void selectionChanged();
void addItem(QGraphicsItem * item);
void updateBlock();
void treePinsClear();
void arrangePins();
void on_actionRemove_items_triggered();
void on_buttonSave_clicked();
void on_buttonSaveAs_clicked();
void on_buttonLoad_clicked();
void on_buttonClear_clicked();
void on_buttonPinAdd_clicked();
void on_buttonPinDup_clicked();
void on_buttonPinDelete_clicked();
void on_buttonPinClear_clicked();
void on_treePins_itemChanged(QTreeWidgetItem *item, int column);
// void on_treePins_itemSelectionChanged();
private:
bool eventFilter(QObject * o, QEvent * e);
Ui::BlockEditor *ui;
QMap<int, QTreeWidgetItem*> pin_tli;
BlockItem block;
QString src_title, cur_file;
bool init;
bool m_editorMode;
bool m_pinsEditable;
};
class PinAlignDelegate: public QStyledItemDelegate {
Q_OBJECT
public:
PinAlignDelegate(QObject * parent = 0): QStyledItemDelegate(parent) {}
QWidget * createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const;
QString displayText(const QVariant & value, const QLocale & locale) const;
void setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const;
QSize sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const {return QSize(60, 26);}
};
class PinBusDelegate: public QStyledItemDelegate {
Q_OBJECT
public:
PinBusDelegate(QObject * parent = 0): QStyledItemDelegate(parent) {}
QWidget * createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const;
QString displayText(const QVariant & value, const QLocale & locale) const;
void setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const;
QSize sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const {return QSize(60, 26);}
private:
typedef QPair<int, QString> ISPair;
QVector<ISPair> buses;
};
#endif // BLOCKEDITOR_H

View File

@@ -0,0 +1,543 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>BlockEditor</class>
<widget class="QWidget" name="BlockEditor">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>847</width>
<height>810</height>
</rect>
</property>
<property name="windowTitle">
<string>Block editor</string>
</property>
<property name="windowIcon">
<iconset resource="qad_blockview.qrc">
<normaloff>:/icons/blockview.png</normaloff>:/icons/blockview.png</iconset>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QSplitter" name="splitter_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QGroupBox" name="groupParameters">
<property name="title">
<string>Block parameters</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<property name="labelAlignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="leftMargin">
<number>4</number>
</property>
<property name="topMargin">
<number>4</number>
</property>
<property name="rightMargin">
<number>4</number>
</property>
<property name="bottomMargin">
<number>4</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Width:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="spin_w">
<property name="maximum">
<number>1000</number>
</property>
<property name="singleStep">
<number>20</number>
</property>
<property name="value">
<number>100</number>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Heigth:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="spin_h">
<property name="maximum">
<number>1000</number>
</property>
<property name="singleStep">
<number>20</number>
</property>
<property name="value">
<number>60</number>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Pins margin:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="spin_margin">
<property name="maximum">
<number>100</number>
</property>
<property name="singleStep">
<number>10</number>
</property>
<property name="value">
<number>10</number>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Color:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="ColorButton" name="button_color"/>
</item>
</layout>
</widget>
<widget class="QGroupBox" name="groupPins">
<property name="title">
<string>Pins</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>2</number>
</property>
<item>
<widget class="QTreeWidget" name="treePins">
<property name="minimumSize">
<size>
<width>0</width>
<height>200</height>
</size>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::InternalMove</enum>
</property>
<property name="defaultDropAction">
<enum>Qt::MoveAction</enum>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="rootIsDecorated">
<bool>false</bool>
</property>
<property name="itemsExpandable">
<bool>false</bool>
</property>
<attribute name="headerDefaultSectionSize">
<number>200</number>
</attribute>
<column>
<property name="text">
<string>Name</string>
</property>
</column>
<column>
<property name="text">
<string>Bus</string>
</property>
</column>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QToolButton" name="buttonPinAdd">
<property name="toolTip">
<string>Add</string>
</property>
<property name="icon">
<iconset resource="../utils/qad_utils.qrc">
<normaloff>:/icons/list-add.png</normaloff>:/icons/list-add.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="buttonPinDup">
<property name="toolTip">
<string>Clone</string>
</property>
<property name="icon">
<iconset resource="../utils/qad_utils.qrc">
<normaloff>:/icons/edit-copy.png</normaloff>:/icons/edit-copy.png</iconset>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Vertical</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="buttonPinDelete">
<property name="toolTip">
<string>Remove selected</string>
</property>
<property name="icon">
<iconset resource="../utils/qad_utils.qrc">
<normaloff>:/icons/edit-delete.png</normaloff>:/icons/edit-delete.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="buttonPinClear">
<property name="toolTip">
<string>Remove all</string>
</property>
<property name="icon">
<iconset resource="../utils/qad_utils.qrc">
<normaloff>:/icons/edit-clear.png</normaloff>:/icons/edit-clear.png</iconset>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>1</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
<widget class="QWidget" name="layoutWidget">
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QFrame" name="frameProperties">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="layoutProperties">
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>2</number>
</property>
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QWidget" name="widgetBar" native="true"/>
</item>
<item>
<widget class="QWidget" name="widgetBarZ" native="true"/>
</item>
</layout>
</item>
<item>
<widget class="BlockView" name="blockView">
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="navigateAnimationEnabled">
<bool>true</bool>
</property>
<property name="miniMap" stdset="0">
<bool>false</bool>
</property>
<property name="zoomWheelOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QPushButton" name="buttonSave">
<property name="text">
<string>Save</string>
</property>
<property name="icon">
<iconset resource="../utils/qad_utils.qrc">
<normaloff>:/icons/document-save.png</normaloff>:/icons/document-save.png</iconset>
</property>
<property name="shortcut">
<string>Ctrl+S</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="buttonSaveAs">
<property name="text">
<string>Save as ...</string>
</property>
<property name="icon">
<iconset resource="../utils/qad_utils.qrc">
<normaloff>:/icons/document-save.png</normaloff>:/icons/document-save.png</iconset>
</property>
<property name="shortcut">
<string>Ctrl+S</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="buttonLoad">
<property name="text">
<string>Load ...</string>
</property>
<property name="icon">
<iconset resource="../application/qad_application.qrc">
<normaloff>:/icons/document-open.png</normaloff>:/icons/document-open.png</iconset>
</property>
<property name="shortcut">
<string>Ctrl+O</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="buttonClear">
<property name="text">
<string>Clear</string>
</property>
<property name="icon">
<iconset resource="../utils/qad_utils.qrc">
<normaloff>:/icons/edit-clear.png</normaloff>:/icons/edit-clear.png</iconset>
</property>
</widget>
</item>
</layout>
</item>
</layout>
<action name="actionRemove_items">
<property name="icon">
<iconset resource="../utils/qad_utils.qrc">
<normaloff>:/icons/edit-delete.png</normaloff>:/icons/edit-delete.png</iconset>
</property>
<property name="text">
<string>Remove items</string>
</property>
<property name="shortcut">
<string>Del</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>
<class>BlockView</class>
<extends>QGraphicsView</extends>
<header>blockview.h</header>
</customwidget>
<customwidget>
<class>ColorButton</class>
<extends>QPushButton</extends>
<header>colorbutton.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="../utils/qad_utils.qrc"/>
<include location="../application/qad_application.qrc"/>
<include location="qad_blockview.qrc"/>
</resources>
<connections>
<connection>
<sender>spin_w</sender>
<signal>valueChanged(int)</signal>
<receiver>BlockEditor</receiver>
<slot>updateBlock()</slot>
<hints>
<hint type="sourcelabel">
<x>170</x>
<y>21</y>
</hint>
<hint type="destinationlabel">
<x>254</x>
<y>1</y>
</hint>
</hints>
</connection>
<connection>
<sender>spin_h</sender>
<signal>valueChanged(int)</signal>
<receiver>BlockEditor</receiver>
<slot>updateBlock()</slot>
<hints>
<hint type="sourcelabel">
<x>250</x>
<y>49</y>
</hint>
<hint type="destinationlabel">
<x>373</x>
<y>5</y>
</hint>
</hints>
</connection>
<connection>
<sender>spin_margin</sender>
<signal>valueChanged(int)</signal>
<receiver>BlockEditor</receiver>
<slot>updateBlock()</slot>
<hints>
<hint type="sourcelabel">
<x>350</x>
<y>90</y>
</hint>
<hint type="destinationlabel">
<x>492</x>
<y>8</y>
</hint>
</hints>
</connection>
<connection>
<sender>button_color</sender>
<signal>colorChanged(QColor)</signal>
<receiver>BlockEditor</receiver>
<slot>updateBlock()</slot>
<hints>
<hint type="sourcelabel">
<x>561</x>
<y>115</y>
</hint>
<hint type="destinationlabel">
<x>613</x>
<y>6</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>updateBlock()</slot>
</slots>
</ui>

View File

@@ -0,0 +1,26 @@
project(blockeditor)
find_qt(${QtVersions} Core Gui Widgets)
qt_sources(SRC)
qt_wrap(${SRC} CPPS out_CPP QMS out_QM)
qt_add_executable(${PROJECT_NAME} WIN32 out_CPP)
qt_target_link_libraries(${PROJECT_NAME} qad_utils qad_widgets qad_blockview)
message(STATUS "Building ${PROJECT_NAME}")
if(LIB)
if(WIN32)
qt_install(TARGETS ${PROJECT_NAME} DESTINATION ${MINGW_BIN})
else()
if(APPLE)
qt_install(TARGETS ${PROJECT_NAME} DESTINATION /usr/local/bin)
else()
if (DEFINED ANDROID_PLATFORM)
qt_install(TARGETS ${PROJECT_NAME} DESTINATION ${ANDROID_SYSTEM_LIBRARY_PATH}/usr/bin)
else()
qt_install(TARGETS ${PROJECT_NAME} DESTINATION /usr/bin)
endif()
endif()
endif()
#message(STATUS "Install ${PROJECT_NAME} to system \"${CMAKE_INSTALL_PREFIX}\"")
else()
qt_install(TARGETS ${PROJECT_NAME} DESTINATION bin)
#message(STATUS "Install ${PROJECT_NAME} to local \"bin\"")
endif()

View File

@@ -0,0 +1,16 @@
#include <QApplication>
#include "blockeditor.h"
int main(int argc, char * argv[]) {
QApplication a(argc, argv);
#if QT_VERSION >= 0x050000
a.setAttribute(Qt::AA_UseHighDpiPixmaps, true);
#endif
a.setWindowIcon(QIcon(":/icons/blockview.png"));
BlockEditor w;
if (a.arguments().size() > 1)
w.loadFile(a.arguments().back());
w.show();
return a.exec();
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

View File

@@ -0,0 +1,43 @@
# if defined(UNDER_CE)
# include <winbase.h>
# else
# include <winver.h>
# endif
1 ICON icons/blockview.ico
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,0
PRODUCTVERSION 1,0,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x9L
#else
FILEFLAGS 0x8L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "Comments", "\0"
VALUE "CompanyName", "BMSTU SM5\0"
VALUE "FileDescription", "Block Editor\0"
VALUE "FileVersion", "1,0,0,0\0"
VALUE "InternalName", "Block Editor\0"
VALUE "LegalTrademarks", "\0"
VALUE "OriginalFilename", "blockeditor.exe\0"
VALUE "PrivateBuild", "1\0"
VALUE "ProductName", "Block Editor\0"
VALUE "ProductVersion", "1, 0, 0, 0\0"
VALUE "SpecialBuild", "\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END

View File

@@ -0,0 +1,548 @@
#include "blockview.h"
#include <QApplication>
#define BLOCKITEM_DEFAULT_PIN_MARGIN 20
BlockItem::BlockItem(QGraphicsItem * parent): QGraphicsObject(parent), PropertyStorage(),
g_main(this), g_selection(this) {
setData(1006, "item");
setZValue(2.);
setAcceptHoverEvents(true);
setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsMovable);
g_main.setData(1002, true);
g_selection.setData(1007, "item_selection");
g_selection.setAcceptedMouseButtons(0);
g_selection.setZValue(10.);
g_selection.hide();
g_selection.setData(1003, true);
col = Qt::lightGray;
_resize(QSizeF(100., 60.));
QPen p(QColor(128, 128, 255), lineThickness(), Qt::DotLine);
p.setCosmetic(true);
g_selection.setPen(p);
g_selection.setBrush(QColor(128, 128, 255, 32));
pins_margin = BLOCKITEM_DEFAULT_PIN_MARGIN;
anim_thick.setTargetObject(this);
anim_thick.setPropertyName("_thickness");
anim_thick.setEasingCurve(QEasingCurve::OutQuad);
anim_thick.setDuration(300);
anim_sel.setTargetObject(this);
anim_sel.setPropertyName("_selRect");
anim_sel.setEasingCurve(QEasingCurve::OutCubic);
anim_sel.setDuration(400);
t_sel.start();
//g_main.setBrush(QColor(128, 128, 128, 64));
/*
BlockItemPin * pin = new BlockItemPin(Qt::AlignRight, 0, this);
pin->setText("text");
pin->setBusType(0);
addPin(pin);
pin = new BlockItemPin(Qt::AlignTop, this);
pin->setBusType(0); addPin(pin);
pin = new BlockItemPin(Qt::AlignLeft, this);
pin->setBusType(1); addPin(pin);
pin = new BlockItemPin(Qt::AlignRight, this);
pin->setBusType(1); addPin(pin);*/
}
BlockItem::~BlockItem() {
clearDecors();
}
void BlockItem::_resize(QSizeF s) {
g_main.setRect(QRectF(QPointF(), s));
g_main.setPos(QPointF(-g_main.rect().center().x(), -10.));
g_selection.setRect(enlargedRect(g_main.rect(), 0, 0, 8));
g_selection.setPos(g_main.pos());
QRadialGradient g(g_main.rect().width() / 2., 0, qMax<qreal>(g_main.rect().width() / 2., g_main.rect().height()));
g.setSpread(QGradient::PadSpread);
g.setCoordinateMode(QGradient::LogicalMode);
g.setColorAt(0., col.darker(120.));
g.setColorAt(1., col.lighter(120.));
g_main.setBrush(QBrush(g));
prepareGeometryChange();
arrangePins();
}
void BlockItem::_moveToTop(bool only_decors) {
qreal dy = -g_main.rect().center().y() + 10;
if (!only_decors)
moveBy(0., dy);
foreach (QGraphicsItem * d, decors_)
d->moveBy(0., -dy);
}
BlockItemPin * BlockItem::addPin(BlockItemPin * pin, bool update_) {
pin->setParentItem(this);
if (!pins_[pin->alignment()].contains(pin)) pins_[pin->alignment()] << pin;
pin->parent_ = this;
if (update_)
arrangePins();
return pin;
}
BlockItemPin * BlockItem::addPin(Qt::Alignment align, int bus_type, const QString & text, bool update_) {
BlockItemPin * pin = new BlockItemPin(align, bus_type, text, this);
pin->parent_ = this;
pins_[pin->alignment()] << pin;
if (update_)
arrangePins();
return pin;
}
void BlockItem::removePin(BlockItemPin * pin) {
if (!pin) return;
QMutableMapIterator<Qt::Alignment, QVector<BlockItemPin * > > it(pins_);
while (it.hasNext()) {
it.next();
QVector<BlockItemPin * > & pv(it.value());
if (pv.contains(pin))
pv.remove(it.value().indexOf(pin));
}
delete pin;
arrangePins();
}
void BlockItem::addDecor(QGraphicsItem * item) {
if (decors_.contains(item)) return;
if (qgraphicsitem_cast<QGraphicsPixmapItem*>(item))
qgraphicsitem_cast<QGraphicsPixmapItem*>(item)->setTransformationMode(Qt::SmoothTransformation);
if (qgraphicsitem_cast<QGraphicsSimpleTextItem*>(item))
qgraphicsitem_cast<QGraphicsSimpleTextItem*>(item)->setData(1010, qgraphicsitem_cast<QGraphicsSimpleTextItem*>(item)->text());
if (qgraphicsitem_cast<AlignedTextItem*>(item))
qgraphicsitem_cast<AlignedTextItem*>(item)->setData(1010, qgraphicsitem_cast<AlignedTextItem*>(item)->text());
item->setData(1002, true);
item->setData(1011, "decor");
decors_ << item;
item->setParentItem(this);
}
void BlockItem::addDecor(QGraphicsItem & item) {
if (decors_.contains(&item)) return;
if (qgraphicsitem_cast<QGraphicsPixmapItem*>(&item))
qgraphicsitem_cast<QGraphicsPixmapItem*>(&item)->setTransformationMode(Qt::SmoothTransformation);
if (qgraphicsitem_cast<QGraphicsSimpleTextItem*>(&item))
qgraphicsitem_cast<QGraphicsSimpleTextItem*>(&item)->setData(1010, qgraphicsitem_cast<QGraphicsSimpleTextItem*>(&item)->text());
if (qgraphicsitem_cast<AlignedTextItem*>(&item))
qgraphicsitem_cast<AlignedTextItem*>(&item)->setData(1010, qgraphicsitem_cast<AlignedTextItem*>(&item)->text());
item.setData(1002, true);
item.setData(1011, "decor");
//decors_ << &item;
item.setParentItem(this);
}
void BlockItem::removeDecor(QGraphicsItem * item) {
if (scene() && item)
scene()->sendEvent(item, new QGraphicsSceneEvent(QEvent::Close));
decors_.removeAll(item);
delete item;
}
QVector<BlockItemPin * > BlockItem::takePins() {
QVector<BlockItemPin * > ret = pins();
pins_.clear();
return ret;
}
void BlockItem::clearPins() {
QList<QVector<BlockItemPin * > > mp = pins_.values();
for (int i = 0; i < mp.size(); ++i)
qDeleteAll(mp[i]);
pins_.clear();
}
void BlockItem::clearDecors() {
bool pbs = false;
if (scene()) pbs = scene()->blockSignals(true);
if (scene())
foreach (QGraphicsItem * i, decors_)
scene()->sendEvent(i, new QGraphicsSceneEvent(QEvent::Close));
qDeleteAll(decors_);
decors_.clear();
if (scene()) {
scene()->blockSignals(pbs);
QMetaObject::invokeMethod(scene(), "selectionChanged");
}
}
QVector<BlockItemPin * > BlockItem::pins() const {
QList<QVector<BlockItemPin * > > mp = pins_.values();
QVector<BlockItemPin * > ret;
for (int i = 0; i < mp.size(); ++i)
ret << mp[i];
return ret;
}
QByteArray BlockItem::saveModel() {
/*QDataStream s(&ret, QIODevice::ReadWrite);
QVector<BlockItemPin * > ps = pins();
s << pos() << rotation() << size() << color() << ps.size();
foreach (BlockItemPin * p, ps)
s << int(p->alignment()) << p->busType() << p->text() << p->devices();
s << decors_.size();
foreach (QGraphicsItem * i, decors_)
s << i;*/
ChunkStream cs;
cs << cs.chunk(1, pos()) << cs.chunk(2, rotation()) << cs.chunk(3, size()) << cs.chunk(4, color()) << cs.chunk(5, pins())
<< cs.chunk(6, decors_) << cs.chunk(7, pins_margin) << cs.chunk(0xFF, _blockitem_current_version_);
return cs.data();
}
void BlockItem::loadModel(const QByteArray & data) {
//qDebug() << "load from" << data.size() << "bytes";
clearPins();
clearDecors();
col = Qt::lightGray;
_resize(QSizeF(100., 60.));
if (data.isEmpty()) return;
/*QDataStream s(data);
{QPointF _v; s >> _v;}
{qreal _v; s >> _v;}
{QSizeF _v; s >> _v; setSize(_v);}
{QColor _v; s >> _v; setColor(_v);}
int _s; s >> _s;
for (int i = 0; i < _s; ++i) {
BlockItemPin * pin = new BlockItemPin();
{int _v; s >> _v; pin->setAlignment((Qt::Alignment)_v);}
{int _v; s >> _v; pin->setBusType(_v);}
{QString _v; s >> _v; pin->setText(_v);}
{QMap<QString, BlockItemPin::Device> _v; s >> _v; pin->setDevices(_v);}
addPin(pin);
}
s >> _s;
for (int i = 0; i < _s; ++i) {
if (s.atEnd()) break;
QGraphicsItem * ni = 0;
s >> ni;
if (ni) {
addDecor(ni);
}
}*/
ChunkStream cs(data);
QVector<BlockItemPin * > tp;
QList<QGraphicsItem * > dl;
int version = -1;
while (!cs.atEnd()) {
switch (cs.read()) {
case 1: /*setPos(cs.getData<QPointF>());*/ break;
case 2: /*setRotation(cs.getData<qreal>());*/ break;
case 3: setSize(cs.getData<QSizeF>()); break;
case 4: setColor(cs.getData<QColor>()); break;
case 5:
cs.get(tp);
foreach (BlockItemPin * p, tp) addPin(p);
break;
case 6:
cs.get(dl);
foreach (QGraphicsItem * d, dl) addDecor(d);
break;
case 7: setPinsMargin(cs.getData<int>()); break;
case 0xFF: cs.get(version); break;
}
}
if (version <= 0)
_moveToTop(true);
}
QByteArray BlockItem::save() const {
ChunkStream cs;
QMap<QString, QList<BlockItem::Property> > pp;
foreach (BlockItemPin * p, pins()) {
//qDebug() << "save pin" << p->text() << "->" << p->properties().size();
pp[p->text()] = p->properties();
}
cs << cs.chunk(1, pos()) << cs.chunk(2, rotation()) << cs.chunk(3, props) << cs.chunk(5, pp) << cs.chunk(6, size());
cs << cs.chunk(10, data(2000)) << cs.chunk(11, data(2001)) << cs.chunk(12, prop_bindings) << cs.chunk(0xFF, _blockitem_current_version_);
return cs.data();
}
void BlockItem::load(const QByteArray & data) {
if (data.isEmpty()) return;
ChunkStream cs(data);
QMap<QString, QList<BlockItem::Property> > _p;
int version = -1;
while (!cs.atEnd()) {
switch (cs.read()) {
case 1: setPos(cs.getData<QPointF>()); break;
case 2: setRotation(cs.getData<qreal>()); break;
case 3: cs.get(props); break;
case 5:
cs.get(_p);
//qDebug() << "load pins" << _p.size();
foreach (BlockItemPin * p, pins()) {
//qDebug() << "load pin" << p->text() << "->" << _p.contains(p->text());
if (_p.contains(p->text()))
p->properties() = _p[p->text()];
}
break;
case 6: setSize(cs.getData<QSizeF>()); break;
case 10: setData(2000, cs.getData<QVariant>()); break;
case 11: setData(2001, cs.getData<QVariant>()); break;
case 12: prop_bindings = cs.getData<QList<QPair<QString, QString> > >(); break;
case 0xFF: cs.get(version); break;
}
}
if (version <= 0) {
_moveToTop();
}
}
BlockItem * BlockItem::copy() const {
BlockItem * ret = new BlockItem();
ret->setPos(pos());
ret->setSize(size());
ret->setColor(color());
ret->setSelected(false);
ret->props = props;
ret->setPinsMargin(pinsMargin());
QVector<BlockItemPin * > mp = pins();
foreach (BlockItemPin * p, mp) {
BlockItemPin * np = new BlockItemPin();
np->setBusType(p->busType());
np->setAlignment(p->alignment());
np->setText(p->text());
np->setToolTip(p->toolTip());
np->properties() = p->properties();
ret->addPin(np);
}
QByteArray ba;
foreach (QGraphicsItem * i, decors_) {
ba.clear();
QGraphicsItem * ni = 0;
QDataStream s(&ba, QIODevice::ReadWrite); s << i;
QDataStream s2(ba); s2 >> ni;
if (ni)
ret->addDecor(ni);
}
return ret;
}
QList<BlockBusItem * > BlockItem::connectedBuses() const {
QList<BlockBusItem * > ret;
foreach (BlockItemPin * p, pins())
ret << p->connectedBuses();
return ret;
}
BlockItemPin * BlockItem::pinByText(const QString & t) const {
foreach (BlockItemPin * p, pins())
if (p->text() == t)
return p;
return 0;
}
BlockItemPin * BlockItem::pinAtBus(BlockBusItem * bus) const {
if (bus == 0) return 0;
foreach (BlockItemPin * p, pins())
if (p->connectedBuses().contains(bus))
return p;
return 0;
}
QRectF BlockItem::sceneRect() const {
return g_main.mapRectToScene(g_main.boundingRect());
}
QRectF BlockItem::boundingRect() const {
return g_main.mapRectToParent(g_main.boundingRect());
}
void BlockItem::mouseMoveEvent(QGraphicsSceneMouseEvent * event) {
//QGraphicsItem::mouseMoveEvent(event);
}
void BlockItem::hoverEnterEvent(QGraphicsSceneHoverEvent * e) {
bool anim = ((BlockView *)scene()->views().back())->isBlockAnimationEnabled();
if (anim) {
anim_thick.stop();
anim_thick.setStartValue(thickness());
anim_thick.setEndValue(2.5);
anim_thick.start();
} else setThickness(2.5);
emit blockHoverEnter(this);
}
void BlockItem::hoverLeaveEvent(QGraphicsSceneHoverEvent * e) {
bool anim = ((BlockView *)scene()->views().back())->isBlockAnimationEnabled();
if (anim) {
anim_thick.stop();
anim_thick.setStartValue(thickness());
anim_thick.setEndValue(1);
anim_thick.start();
} else setThickness(1);
emit blockHoverLeave(this);
}
#define _POS(m) (i - ((cp.size() - 1) / 2)) * m
void BlockItem::arrangePins() {
//double w = g_main.rect().width(), h = g_main.rect().height();
QVector<BlockItemPin * > pl = pins();
// pl = pl.fromList(pins().toList());
pins_.clear();
foreach (BlockItemPin * p, pl)
pins_[p->alignment()] << p;
QVector<BlockItemPin * > cp = pins_.value(Qt::AlignBottom);
for (int i = 0; i < cp.size(); ++i) cp[i]->setPos(_POS(pins_margin), bottom());
cp = pins_.value(Qt::AlignTop);
for (int i = 0; i < cp.size(); ++i) cp[i]->setPos(_POS(pins_margin), top());
cp = pins_.value(Qt::AlignLeft);
for (int i = 0; i < cp.size(); ++i) cp[i]->setPos(left(), i * pins_margin);
cp = pins_.value(Qt::AlignRight);
for (int i = 0; i < cp.size(); ++i) cp[i]->setPos(right(), i * pins_margin);
}
#undef _POS
void BlockItem::removeBindings(const QString & bind_name) {
for(int i=0; i<prop_bindings.size(); ++i) {
if (prop_bindings[i].second == bind_name) {
prop_bindings.removeAt(i);
i--;
}
}
}
void BlockItem::removeBindingByProperty(const QString & prop_name) {
for(int i=0; i<prop_bindings.size(); ++i) {
if (prop_bindings[i].first == prop_name) {
prop_bindings.removeAt(i);
i--;
}
}
}
void BlockItem::addBinding(const QString & prop_name, const QString & bind_name) {
QPair<QString, QString> pb(prop_name, bind_name);
prop_bindings.removeAll(pb);
prop_bindings << pb;
}
void BlockItem::applyBinding(const QString & bind_name, const QVariant & bind_value) {
for(int i=0; i<prop_bindings.size(); ++i) {
if (prop_bindings[i].second == bind_name) {
setPropertyValue(prop_bindings[i].first, bind_value);
}
}
}
void BlockItem::applyBindings(const PropertyStorage & bindings) {
for(int i=0; i<prop_bindings.size(); ++i) {
if (bindings.isPropertyExists(prop_bindings[i].second)) {
setPropertyValue(prop_bindings[i].first, bindings.propertyValueByName(prop_bindings[i].second));
}
}
}
void BlockItem::setBindings(const QList<QPair<QString, QString> > & bindings) {
prop_bindings = bindings;
}
QList<QPair<QString, QString> > BlockItem::getBindings() {
return prop_bindings;
}
QString BlockItem::getBindName(const QString & prop_name) const {
for(int i=0; i<prop_bindings.size(); ++i) {
if (prop_bindings[i].first == prop_name) {
return prop_bindings[i].second;
}
}
return QString();
}
QStringList BlockItem::getBindNames() const {
QStringList ret;
for(int i=0; i<prop_bindings.size(); ++i)
if (!ret.contains(prop_bindings[i].second)) ret << prop_bindings[i].second;
return ret;
}
QStringList BlockItem::getBindProps() const {
QStringList ret;
for(int i=0; i<prop_bindings.size(); ++i)
ret << prop_bindings[i].first;
return ret;
}
void BlockItem::paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget) {
//if ()
}
QVariant BlockItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant & value) {
if (change == QGraphicsItem::ItemSelectedChange) {
// qDebug() << "select" << value.toBool();
if (value.toBool() && !isSelected() && ((BlockView *)scene()->views().back())->isBlockAnimationEnabled() && t_sel.elapsed() > 50) {
g_selection.setRect(enlargedRect(g_main.rect(), 0, 0, 16));
anim_sel.setStartValue(selectionRect());
anim_sel.setEndValue(enlargedRect(g_main.rect(), 0, 0, 8));
anim_sel.start();
}
t_sel.restart();
g_selection.setVisible(value.toBool());
}
return QGraphicsItem::itemChange(change, value);
}
double BlockItem::thickness() const {
return g_main.pen().widthF();
}
void BlockItem::setThickness(double w) {
QPen p = g_main.pen();
p.setWidthF(w);
g_main.setPen(p);
}
QRectF BlockItem::selectionRect() const {
return g_selection.rect();
}
void BlockItem::setSelectionRect(const QRectF & r) {
g_selection.setRect(r);
}

View File

@@ -0,0 +1,144 @@
#ifndef BLOCKITEM_H
#define BLOCKITEM_H
#include "blockitempin.h"
#include <QTime>
/// data:
/// 1002 - flag for move parent (true)
/// 1003 - flag for visualize selection (true)
/// 1004 - BlockItemPin ("pin")
/// 1005 - BlockBusItem ("connection")
/// 1006 - BlockItem ("item")
/// 1007 - BlockItem selection ("item_selection")
/// 1008 - item is NOT decor, ignore for function decors() (true)
/// 1009 - item is scene decor ("decor")
/// 1010 - BlockItem decor (src text for QGraphicsSimpleTextItem)
/// 1011 - item is BlockItem decor ("decor")
/// 1100 - flag for correct move (true)
class BlockItem: public QGraphicsObject, public PropertyStorage
{
friend class BlockView;
friend class BlockItemPin;
friend class DrawTools;
Q_OBJECT
Q_PROPERTY(double _thickness READ thickness WRITE setThickness DESIGNABLE false SCRIPTABLE false)
Q_PROPERTY(QRectF _selRect READ selectionRect WRITE setSelectionRect DESIGNABLE false SCRIPTABLE false)
public:
BlockItem(QGraphicsItem * parent = 0);
~BlockItem();
BlockItem * copy() const;
BlockItemPin * addPin(BlockItemPin * pin, bool update_ = true);
BlockItemPin * addPin(Qt::Alignment align, int bus_type, const QString & text, bool update_ = true);
void removePin(BlockItemPin * pin);
void addDecor(QGraphicsItem * item);
void addDecor(QGraphicsItem & item);
void removeDecor(QGraphicsItem * item);
QVector<BlockItemPin * > takePins();
void clearPins();
void clearDecors();
QVector<BlockItemPin * > pins() const;
QList<QGraphicsItem * > decors() const {return decors_;}
QList<BlockBusItem * > connectedBuses() const;
BlockItemPin * pinByText(const QString & t) const;
BlockItemPin * pinAtBus(BlockBusItem * bus) const;
QColor color() const {return col;}
void setColor(QColor c) {col = c; _resize(size());}
QSizeF size() const {return g_main.rect().size();}
QRectF sceneRect() const;
qreal width() const {return size().width();}
qreal height() const {return size().height();}
int pinsMargin() const {return pins_margin;}
void setSize(QSizeF s) {_resize(s);}
void setSize(qreal w, qreal h) {setSize(QSizeF(w, h));}
void setWidth(qreal w) {setSize(QSizeF(w, size().height()));}
void setHeight(qreal h) {setSize(QSizeF(size().width(), h));}
void setPinsMargin(int marg) {if (marg > 1 && marg < 256) pins_margin = marg; arrangePins();}
QByteArray saveModel();
void loadModel(const QByteArray & data);
QByteArray save() const;
void load(const QByteArray & data);
void arrangePins();
void removeBindings(const QString & bind_name);
void removeBindingByProperty(const QString & prop_name);
void addBinding(const QString & prop_name, const QString & bind_name);
void applyBinding(const QString & bind_name, const QVariant & bind_value);
void applyBindings(const PropertyStorage & bindings);
void setBindings(const QList<QPair<QString, QString> > & bindings);
QList<QPair<QString, QString> > getBindings();
QString getBindName(const QString & prop_name) const;
QStringList getBindNames() const;
QStringList getBindProps() const;
enum {Type = UserType + 1};
protected:
void _resize(QSizeF s);
void _moveToTop(bool only_decors = false);
int type() const {return Type;}
QRectF boundingRect() const;
void mouseMoveEvent(QGraphicsSceneMouseEvent * event);
void hoverEnterEvent(QGraphicsSceneHoverEvent * event);
void hoverLeaveEvent(QGraphicsSceneHoverEvent * event);
double left() const {return boundingRect().left();}
double right() const {return boundingRect().right();}
double top() const {return boundingRect().top();}
double bottom() const {return boundingRect().bottom();}
void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0);
QVariant itemChange(GraphicsItemChange change, const QVariant & value);
QGraphicsRectItem g_main, g_selection;
int pins_margin;
QColor col;
QMap<Qt::Alignment, QVector<BlockItemPin * > > pins_;
QList<QGraphicsItem * > decors_;
QList<QPair<QString, QString> > prop_bindings; // <property_name, binding_name>
private:
double thickness() const;
void setThickness(double w);
QRectF selectionRect() const;
void setSelectionRect(const QRectF & r);
QPropertyAnimation anim_thick, anim_sel;
QTime t_sel;
signals:
void blockHoverEnter(BlockItem * b);
void blockHoverLeave(BlockItem * b);
};
inline QDataStream & operator <<(QDataStream & s, const BlockItemPin * p) {
ChunkStream cs;
cs << cs.chunk(1, int(p->alignment())) << cs.chunk(2, p->busType()) << cs.chunk(3, p->text()) << cs.chunk(4, p->toolTip());
s << cs.data(); return s;}
inline QDataStream & operator >>(QDataStream & s, BlockItemPin *& p) {
ChunkStream cs(s);
p = new BlockItemPin();
while (!cs.atEnd()) {
switch (cs.read()) {
case 1: p->setAlignment((Qt::Alignment)cs.getData<int>()); break;
case 2: p->setBusType(cs.getData<int>()); break;
case 3: p->setText(cs.getData<QString>()); break;
case 4: p->setToolTip(cs.getData<QString>()); break;
}
}
return s;
}
inline QDataStream & operator <<(QDataStream & s, const BlockItem * b) {s << b->save(); return s;}
inline QDataStream & operator >>(QDataStream & s, BlockItem *& b) {
QByteArray ba; s >> ba;
b = new BlockItem();
b->load(ba);
return s;
}
#endif // BLOCKITEM_H

View File

@@ -0,0 +1,163 @@
#include "blockview.h"
#include <QApplication>
BlockItemPin::BlockItemPin(Qt::Alignment a, int bus_type_, const QString & text_, QGraphicsObject * _parent): QGraphicsObject(_parent), ell_item(this), text_item(this) {
parent_ = 0;
setData(1004, "pin");
setAcceptHoverEvents(true);
text_item.setData(1002, true);
ell_item.setData(1003, true);
br[Disconnected] = QBrush(Qt::lightGray);
br[Connected] = QBrush(Qt::darkGreen);
br[Hover] = QBrush(Qt::blue);
br[Drop] = QBrush(Qt::green);
br[Accept] = QBrush(Qt::green);
br[Reject] = QBrush(Qt::red);
anim_pin_size.setTargetObject(this);
anim_pin_size.setPropertyName("pinSize");
anim_pin_size.setEasingCurve(QEasingCurve::OutElastic);
anim_pin_size.setDuration(700);
anim_accept.setTargetObject(this);
anim_accept.setPropertyName("pinSize");
anim_accept.setEasingCurve(QEasingCurve::InOutQuad);
anim_accept.setDuration(150);
connect(&anim_accept, SIGNAL(finished()), this, SLOT(animationAccept()));
setState(Disconnected);
setAlignment(a);
setBusType(bus_type_);
setText(text_);
setZValue(2.);
setDirection(BlockItemPin::InputOutput);
_reparent();
}
void BlockItemPin::animAccept() {
if (!((BlockView *)scene()->views().back())->isBlockAnimationEnabled() && anim_accept.state() != QAbstractAnimation::Running) return;
anim_accept.setStartValue(pinSize());
anim_accept.setEndValue(10.);
anim_accept.start();
}
void BlockItemPin::setState(State s) {
State os = state_;
state_ = s;
setBrush(br[int(state_)]);
if (s == Accept && os != Accept) {
animAccept();
}
update();
}
void BlockItemPin::enlargePin(bool enlarge) {
double sz = enlarge ? 12. : 7;
if (anim_accept.state() == QAbstractAnimation::Running && enlarge) {
anim_accept.stop();
resizePin(sz);
}
if (!((BlockView *)scene()->views().back())->isBlockAnimationEnabled()) {
resizePin(sz);
return;
}
if (sz == anim_pin_size.endValue())
return;
anim_pin_size.stop();
anim_pin_size.setStartValue(pinSize());
anim_pin_size.setEndValue(sz);
anim_pin_size.start();
}
void BlockItemPin::resizePin(double r) {
ell_item.setRect(-r, -r, r+r, r+r);
}
double BlockItemPin::pinSize() const {
return ell_item.rect().width() / 2.;
}
void BlockItemPin::animationAccept() {
if (anim_accept.endValue().toDouble() == 7.) return;
anim_accept.setStartValue(pinSize());
anim_accept.setEndValue(7.);
anim_accept.start();
}
void BlockItemPin::_init(bool affect_parent) {
text_item.setFont(AlignedTextItem::sceneFont(QApplication::font()));
QRectF tbr = text_item.boundingRect();
const double r = 7.;
ell_item.setRect(-r, -r, r+r, r+r);
ell_item.setSpanAngle(16*180);
text_item.resetTransform();
text_item.setPos(0, -tbr.height() / 2.);
text_item.setTransformOriginPoint(0, tbr.height() / 2.);
switch (align) {
case Qt::AlignBottom: ell_item.setStartAngle(16*0); text_item.setRotation(-90.); text_item.moveBy(0, -r * 1.5); break;
case Qt::AlignRight: ell_item.setStartAngle(16*90); text_item.setRotation(0.); text_item.moveBy(-tbr.width() - r * 1.5, 0); break;
case Qt::AlignTop: ell_item.setStartAngle(16*180); text_item.setRotation(-90.); text_item.moveBy(0, tbr.width() + r * 1.5); break;
case Qt::AlignLeft: ell_item.setStartAngle(16*270); text_item.setRotation(0.); text_item.moveBy(r * 1.5, 0); break;
default: break;
}
if (affect_parent && parent_)
parent_->arrangePins();
}
void BlockItemPin::_reparent() {
if (parentItem() == 0) return;
if (qgraphicsitem_cast<BlockItem*>(parentItem()) == 0) return;
QPen p = qgraphicsitem_cast<BlockItem*>(parentItem())->g_main.pen();
ell_item.setPen(p);
if (scene()) {
text_item.setFont(AlignedTextItem::sceneFont(scene()->font()));
QRectF tbr = text_item.boundingRect();
text_item.resetTransform();
text_item.setPos(0, -tbr.height() / 2.);
text_item.setTransformOriginPoint(0, tbr.height() / 2.);
}
}
QGraphicsView * BlockItemPin::_view() const {
if (!scene()) return 0;
if (scene()->views().isEmpty()) return 0;
return scene()->views().back();
}
QVariant BlockItemPin::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant & value) {
if (change == QGraphicsItem::ItemParentChange)
_reparent();
return QGraphicsItem::itemChange(change, value);
}
void BlockItemPin::hoverEnterEvent(QGraphicsSceneHoverEvent * e) {
QGraphicsView * v = _view();
bool m_pin_mc = false;
if (v) {
QMetaObject::invokeMethod(v, "getPinMC", Q_ARG(bool*, &m_pin_mc));
QMetaObject::invokeMethod(v, "pinHoverInOut", Qt::QueuedConnection, Q_ARG(BlockItemPin*, this));
}
if ((state() != Disconnected) && !m_pin_mc) return;
saveState();
setState(BlockItemPin::Hover);
enlargePin(true);
update();
}
void BlockItemPin::hoverLeaveEvent(QGraphicsSceneHoverEvent * e) {
QGraphicsView * v = _view();
restoreState();
enlargePin(false);
update();
if (v) QMetaObject::invokeMethod(v, "pinHoverInOut", Q_ARG(BlockItemPin*, 0));
}

View File

@@ -0,0 +1,112 @@
#ifndef BLOCKITEMPIN_H
#define BLOCKITEMPIN_H
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsObject>
#include <QGraphicsEllipseItem>
#include <QGraphicsSceneHoverEvent>
#include <QGraphicsSceneMouseEvent>
#include <QStack>
#include <QDebug>
#include <QPropertyAnimation>
#include <qmath.h>
#include "blockbase.h"
#include "alignedtextitem.h"
class BlockItem;
class BlockBusItem;
class BlockItemPin: public QGraphicsObject, public PropertyStorage
{
friend class BlockView;
friend class BlockItem;
Q_OBJECT
Q_PROPERTY(double pinSize READ pinSize WRITE resizePin DESIGNABLE false SCRIPTABLE false)
public:
BlockItemPin(Qt::Alignment a = Qt::AlignLeft, int bus_type = 0, const QString & text_ = QString(), QGraphicsObject * parent_ = 0);
enum State {
Disconnected,
Connected,
Hover,
Drop,
Accept,
Reject
};
enum Direction {
None = 0x0,
Input = 0x1,
Output = 0x2,
InputOutput = 0x3
};
void setPen(const QPen & p) {ell_item.setPen(p);}
QPen pen() const {return ell_item.pen();}
void setBrush(const QBrush & b) {ell_item.setBrush(b);}
QBrush brush() const {return ell_item.brush();}
int busType() const {return bus_type;}
Qt::Alignment alignment() const {return align;}
Direction direction() const {return dir;}
QString text() const {return text_item.text();}
State state() const {return state_;}
void setBusType(int type_) {bus_type = type_;}
void setAlignment(Qt::Alignment a) {align = a; _init(true);}
void setDirection(Direction d) {dir = d; _init(true);}
void setText(const QString & t) {text_item.setText(t); _init(true);}
void setState(State s);
void saveState() {sstate_.push(state_);}
bool restoreState() {if (sstate_.isEmpty()) return false; setState(sstate_.pop()); return true;}
void clearStateStack() {sstate_.clear();}
void enlargePin(bool enlarge);
BlockItem * parent() const {return parent_;}
QList<BlockBusItem * > connectedBuses() const {return buses_;}
enum {Type = UserType + 3};
public slots:
void animAccept();
protected:
void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0) {}
QRectF boundingRect() const {return ell_item.boundingRect().translated(ell_item.pos()) | text_item.boundingRect().translated(text_item.pos());}
int type() const {return Type;}
QVariant itemChange(GraphicsItemChange change, const QVariant & value);
void hoverEnterEvent(QGraphicsSceneHoverEvent * e);
void hoverLeaveEvent(QGraphicsSceneHoverEvent * e);
void _init(bool affect_parent = false);
void _reparent();
QGraphicsView * _view() const;
int bus_type;
State state_;
QGraphicsEllipseItem ell_item;
QGraphicsSimpleTextItem text_item;
QStack<State> sstate_;
QList<BlockBusItem * > buses_;
BlockItem * parent_;
Qt::Alignment align;
Direction dir;
QBrush br[6];
private slots:
void animationAccept();
private:
void resizePin(double r);
double pinSize() const;
QPropertyAnimation anim_pin_size;
QPropertyAnimation anim_accept;
};
#endif // BLOCKITEMPIN_H

View File

@@ -0,0 +1,2062 @@
#include "blockview.h"
#include <qmath.h>
#include <QScrollBar>
#include <QGraphicsSceneMouseEvent>
#include <QApplication>
#include <QAction>
#include <QShortcut>
#include <QVector2D>
#include <QClipboard>
#include <QMimeData>
const QString _BlockView_Mime_ = "_BlockView_copypaste_";
BlockView::BlockView(QWidget * parent): QGraphicsView(parent), tmp_bus(true) {
_init();
}
BlockView::BlockView(QGraphicsScene * scene, QWidget * parent): QGraphicsView(scene, parent), tmp_bus(true) {
_init();
}
BlockView::~BlockView() {
}
void BlockView::_init() {
qRegisterMetaType<BlockItem*>();
qRegisterMetaType<BlockItemPin*>();
qRegisterMetaType<BlockBusItem*>();
grid_visible = grid_snap = pm_connect = navigation = m_connect = m_trace_with_buses = prev_tcb = minimap = true;
mm_drag = moved = new_branch = new_bus = mm_cancel = iconnect = mm_copy = m_pin_mc = mm_thumb = move_bus_point = wheel_zoom = false;
match_bus = bus_from = 0;
mm_ci = 0;
hpin = 0;
ghost_ = 0;
grid_step = 10.;
grid_points = 1;
grid_pen = QPen(palette().color(QPalette::Disabled, QPalette::WindowText), 1, Qt::NoPen);
thick = 1;
thumb_hide_delay = 500;
timer_thumb = 0;
smode = BlockView::MultiSelection;
cur_scl = thumb_scl = prev_app_scale = 1.;
_talpha = 0.;
ae_enabled = is_block_anim = true;
is_nav_anim = true;
nav_prev_aa = nav_prev_imaa = nav_prev_grid = true;
thumb_size = QSizeF(200, 200);
if (scene() == 0) {
scene_ = new QGraphicsScene;
setScene(scene_);
}
scene_ = scene();
scene_->setSceneRect(-2500, -2500, 5000, 5000);
scene_->setItemIndexMethod(QGraphicsScene::NoIndex);
scene_->installEventFilter(this);
scene_->addItem(&tmp_bus);
widget_thumb.setParent(this);
//widget_thumb.setAutoFillBackground(true);
//widget_thumb.setStyleSheet("background-color: rgb(255, 0, 0);");
widget_thumb.installEventFilter(this);
widget_thumb.setMouseTracking(true);
widget_thumb.show();
widget_thumb.setWindowOpacity(0.);
thumb_anim.setTargetObject(this);
thumb_anim.setPropertyName("_thumb");
thumb_anim.setEasingCurve(QEasingCurve::InCubic);
nav_anim.setTargetObject(this);
nav_anim.setPropertyName("_nav");
nav_anim.setEasingCurve(QEasingCurve::Linear);
nav_anim.setDuration(150);
connect(QApplication::clipboard(), SIGNAL(dataChanged()), this, SLOT(checkPaste()));
connect(&nav_anim, SIGNAL(finished()), this, SLOT(_navFinished()));
connect(scene_, SIGNAL(sceneRectChanged(QRectF)), this, SLOT(adjustThumb()));
connect(scene_, SIGNAL(selectionChanged()), this, SLOT(sceneSelectionChanged()));
connect(horizontalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(scrolled()));
connect(verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(scrolled()));
centerOn(scene_->sceneRect().center());
setCacheMode(CacheBackground);
setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
setResizeAnchor(QGraphicsView::AnchorViewCenter);
setRenderHint(QPainter::Antialiasing);
setRenderHint(QPainter::SmoothPixmapTransform);
setMouseTracking(true);
sel_rect.setZValue(999.);
sel_rect.hide();
QColor sc = palette().color(QPalette::Highlight);
sc.setAlphaF(0.6);
QPen pen(sc.darker(200), lineThickness() + 1., Qt::DotLine);
pen.setCosmetic(true);
sel_rect.setPen(pen);
sc.setAlphaF(0.2);
sel_rect.setBrush(QBrush(sc));
checkPaste(true);
/*AlignedTextItem * ti = new AlignedTextItem("This is text!");
ti->setFlag(QGraphicsItem::ItemIsSelectable, true);
ti->setFlag(QGraphicsItem::ItemIsMovable, true);
addItem(ti);
ti->setAlignment(Qt::AlignBottom | Qt::AlignLeft);
ti->setText("text\nt");
QGraphicsSimpleTextItem * t__ = new QGraphicsSimpleTextItem("TEXT");
t__->setFlags(QGraphicsItem::ItemIsSelectable);
addItem(t__);
addItem(new QGraphicsLineItem(0, -50, 0, 50));
addItem(new QGraphicsLineItem(-50, 0, 50, 0));
for (int i = 0; i < 5; ++i) {
BlockItem * it = new BlockItem();
it->setPos(i*150, i*20);
it->addPin(new BlockItemPin());
if (i == 2)
it->setFlags(QGraphicsItem::ItemIsSelectable);
scene_->addItem(it);
}
QGraphicsItem * it = new QGraphicsRectItem(0, 0, 200, 100);
it->setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsMovable);
it->setData(1001, true);
scene_->addItem(it);
BlockBusItem * bus = new BlockBusItem();
bus->setImages(QImage("icons/bus_twin.png"), QImage("icons/bus_end_rj45.png"));
bus->setEndpointsNumber(3);
bus->setBusType(1);
bus->appendPoint(QPointF(20, 40));
bus->appendPoint(QPointF(150, -20));
bus->appendPoint(QPointF(40, -80));
//bus->setImages(QImage("icons/bus_twin.png"), QImage("icons/bus_end_rj45.png"));
addItem(bus);
bus = new BlockBusItem();
bus->appendPoint(QPointF(-20, 40));
bus->appendPoint(QPointF(100, -30));
bus->appendPoint(QPointF(20, -60));
addItem(bus);*/
}
void BlockView::_updateBack() {
setCacheMode(CacheNone);
invalidateScene();
setCacheMode(CacheBackground);
}
bool BlockView::event(QEvent * e) {
if (e->type() == QEvent::FontChange || e->type() == QEvent::Polish) {
double cscl = appScale(this);
QGraphicsView::scale(cscl / prev_app_scale, cscl / prev_app_scale);
prev_app_scale = cscl;
}
return QGraphicsView::event(e);
}
bool BlockView::eventFilter(QObject * o, QEvent * e) {
if (o == &widget_thumb) {
QMouseEvent * me = (QMouseEvent*)e;
switch (e->type()) {
case QEvent::Paint:
drawThumb();
return true;
case QEvent::Enter:
thumbShow();
break;
case QEvent::Leave:
restartTimer(timer_thumb, thumb_hide_delay);
break;
case QEvent::MouseButtonPress:
thumb_press = me->pos();
widget_thumb.setCursor(Qt::ClosedHandCursor);
if (!thumb_vr.contains(thumb_press)) {
thumb_vr.moveCenter(thumb_press);
scrollFromThumb();
}
break;
case QEvent::MouseButtonRelease:
widget_thumb.setCursor(Qt::OpenHandCursor);
break;
case QEvent::MouseMove:
if (me->buttons() == 0)
widget_thumb.setCursor(thumb_vr.contains(me->pos()) ? Qt::OpenHandCursor : Qt::CrossCursor);
if (me->buttons().testFlag(Qt::LeftButton)) {
thumb_vr.translate(me->pos() - thumb_press);
scrollFromThumb();
thumb_press = me->pos();
}
break;
default: break;
}
return QGraphicsView::eventFilter(o, e);
}
if (o == scene_) {
QGraphicsSceneMouseEvent * me = (QGraphicsSceneMouseEvent*)e;
QList<QGraphicsItem * > mil;
QPointF mdp;
bool fmm_drag = false;
int btncnt = 0;
switch (e->type()) {
case QEvent::GraphicsSceneMouseDoubleClick:
mil = scene_->items(scene_point);
foreach (QGraphicsItem * i, mil) {
if (i->data(1006) == "item") {
//emit blockDoubleClicked((BlockItem * )i);
QMetaObject::invokeMethod(this, "blockDoubleClicked", Qt::QueuedConnection, Q_ARG(BlockItem * , (BlockItem*)i));
return true;
}
if (i->data(1005) == "connection") {
if (qgraphicsitem_cast<BlockBusItem*>(i)->isBusSelected()) {
//emit busDoubleClicked(qgraphicsitem_cast<BlockBusItem*>(i));
QMetaObject::invokeMethod(this, "busDoubleClicked", Qt::QueuedConnection, Q_ARG(BlockBusItem * , (BlockBusItem*)i));
return true;
}
}
}
//return true;
break;
/*case QEvent::GraphicsSceneHoverMove:
mil = scene_->items(scene_point);
mm_ci = (mil.isEmpty() ? 0 : mil.front());
if (mm_ci != 0) {
while (mm_ci->data(1005).toString() == "connection") {
if (qgraphicsitem_cast<BlockBusItem*>(mm_ci))
if (qgraphicsitem_cast<BlockBusItem*>(mm_ci)->isBusSelected())
break;
if (mil.size() > 1) {
mm_ci = mil[1];
mil.pop_front();
} else {
mm_ci = 0;
break;
}
}
}
break;*/
case QEvent::GraphicsSceneMousePress:
if (mm_ci != 0)
if (mm_ci->data(1008).toBool())
break;
//qDebug() << "press";
if (me->buttons().testFlag(Qt::LeftButton)) btncnt++;
if (me->buttons().testFlag(Qt::RightButton)) btncnt++;
if (me->buttons().testFlag(Qt::MidButton)) btncnt++;
mm_cancel = btncnt >= 2;
match_bus = bus_from = 0;
hpin = 0;
copy_dp = QPointF();
//qDebug() << mm_cancel << mm_copy << mm_drag << new_branch << new_bus;
if (mm_copy && mm_cancel) {
deleteCopyTemp();
mm_copy = moved = false;
unsetCursor();
}
if (new_bus && mm_cancel) {
new_bus = false;
unmarkPins(true);
reconnectAll();
hideTmpBuses();
m_trace_with_buses = prev_tcb;
}
if (new_branch && mm_cancel) {
new_branch = false;
hideTmpBuses();
m_trace_with_buses = prev_tcb;
}
if (moved && mm_cancel) {
moved = false;
restoreSelState();
hideTmpBuses();
m_trace_with_buses = prev_tcb;
}
if (mm_cancel) return true;
mm_mods = me->modifiers();
mm_drag = moved = false;
screen_point = me->screenPos();
scene_point = me->scenePos();
if ((me->button() == Qt::MidButton)) {
thumbShow();
restartTimer(timer_thumb, thumb_hide_delay);
return true;
}
mil = scene_->items(scene_point);
mm_ci = (mil.isEmpty() ? 0 : mil.front());
if (mil.isEmpty()) return true;
if (mm_ci != 0) {
if (mm_ci->data(1008).toBool())
break;
while (mm_ci->data(1005).toString() == "connection") {
if (qgraphicsitem_cast<BlockBusItem*>(mm_ci))
if (qgraphicsitem_cast<BlockBusItem*>(mm_ci)->isBusSelected())
break;
if (mil.size() > 1) {
mm_ci = mil[1];
mil.pop_front();
} else {
mm_ci = 0;
break;
}
}
if (mm_ci->data(1003).toBool()) {
if (mil.size() > 1) {
mm_ci = mil[1];
mil.pop_front();
if (mm_ci->data(1003).toBool())
if (mil.size() > 1)
mm_ci = mil[1];
} else
mm_ci = 0;
}
if (mm_ci->data(1002).toBool()) {
QGraphicsItem * ti = mm_ci;
while (mm_ci->parentItem() != 0)
mm_ci = mm_ci->parentItem();
if (!ti->data(1010).toString().isEmpty()) { // text item, check for rect
BlockItem * bi = qgraphicsitem_cast<BlockItem*>(mm_ci);
if (bi) {
if (!bi->sceneRect().contains(scene_point)) {
//qDebug() << "return";
mm_ci = 0;
}
}
}
return true;
}
}
if (mm_ci) {
if (mm_ci->data(1004) == "pin" && m_connect) {
if (qgraphicsitem_cast<BlockItemPin*>(mm_ci)->state() == BlockItemPin::Hover) {
trace_from = mm_ci->scenePos();
qgraphicsitem_cast<BlockItemPin*>(mm_ci)->clearStateStack();
hideTmpBuses();
tmp_bus.setBusType(qgraphicsitem_cast<BlockItemPin*>(mm_ci)->busType());
tmp_bus.setEndpointsNumber(3);
tmp_bus.show();
new_bus = true;
qDeleteAll(tmp_buses);
tmp_buses.clear();
foreach (BlockItemPin * p, last_multiconnect_pl) {
tmp_buses << new BlockBusItem(true);
tmp_buses.back()->setBusType(p->busType());
addItem(tmp_buses.back());
}
//qDebug() << "new" << ;
prev_tcb = m_trace_with_buses;
newBusStarted(tmp_bus.busType());
markPins(tmp_bus.busType());
if (qgraphicsitem_cast<BlockItemPin*>(mm_ci)->alignment() == Qt::AlignLeft ||
qgraphicsitem_cast<BlockItemPin*>(mm_ci)->alignment() == Qt::AlignRight)
wavetrace.setPreferredDirection(BlockViewWavetrace::Horizontal);
else
wavetrace.setPreferredDirection(BlockViewWavetrace::Vertical);
return true;
}
}
}
cur_scl = qSqrt(transform().determinant());
//return true;
break;
case QEvent::GraphicsSceneMouseMove:
//qDebug() << "move" << (mm_ci != 0 ? mm_ci : 0);
/*if (ghost_) {
ghost_->setPos(quantize(me->scenePos(), grid_step));
}*/
if (mm_ci)
if (mm_ci->data(1008).toBool())
break;
if (mm_cancel) return true;
if (me->buttons().testFlag(Qt::LeftButton)) {
if (!mm_drag) {
if ((screen_point - me->screenPos()).manhattanLength() >= QApplication::startDragDistance()) {
mm_drag = fmm_drag = true;
saveBusesState();
}
} else {
if (tmp_bus.isVisible()) {
mil = scene_->items(me->scenePos());
hpin = 0;
foreach (QGraphicsItem * i, mil)
if (i->data(1004) == "pin") {
hpin = qgraphicsitem_cast<BlockItemPin*>(i);
break;
}
if (hpin) {
if (hpin->state() == BlockItemPin::Accept) {
unhoverPins(hpin);
hoverAcceptedPin(hpin, true);
} else hpin = 0;
} else unhoverPins();
if (new_branch) {
matchBus();
break;
}
trace(trace_from, me->scenePos(), &tmp_bus);
for (int i = 0; i < qMin(tmp_buses.size(), last_multiconnect_pl.size()); ++i) {
QPointF dp = last_multiconnect_pl[i]->scenePos() - trace_from;
//qDebug() << "trace" << i << dp;
trace(trace_from + dp, me->scenePos() + dp, tmp_buses[i], false);
tmp_buses[i]->show();
}
matchBus();
}
}
if (tmp_bus.isVisible()) return true;
if (mm_mods.testFlag(Qt::ShiftModifier)) {
if (fmm_drag) {
fmm_drag = false;
if (mm_ci) {
if ((mm_ci->data(1006) == "item")) {
if (!mm_ci->isSelected() && sel_items.isEmpty()) {
clearSelection();
mm_ci->setSelected(true);
}
} else {
mm_ci = 0;
break;
}
} else {
break;
}
sel_items = scene_->selectedItems();
deleteCopyTemp();
QList<BlockItem * > bi;
foreach (QGraphicsItem * i, sel_items) {
if (i->data(1006) == "item") {
//qDebug() << "copy";
bi << qgraphicsitem_cast<BlockItem*>(i);
BlockItem * ti = bi.back()->copy();
ti->g_main.setPen(QPen(ti->g_main.pen().color(), ti->g_main.pen().widthF(), Qt::DashLine));
QColor bc = ti->g_main.brush().color(); bc.setAlphaF(bc.alphaF() * 0.5);
ti->g_main.setBrush(bc);
copy_items << ti;
scene_->addItem(ti);
}
}
QList<BlockBusItem * > ibi = internalBuses(bi);
foreach (BlockBusItem * i, ibi) {
i = i->copy();
i->setOpacity(i->opacity() * 0.5);
copy_buses << i;
scene_->addItem(i);
}
mm_copy = true;
setCursor(Qt::DragCopyCursor);
}
} else {
if (smode == BlockView::SingleSelection) {
if (fmm_drag) {
clearSelection();
if (mm_ci != 0) {
mm_ci->setSelected(true);
}
saveSelState();
}
}
if (smode == BlockView::MultiSelection) {
sel_rect.setRect(QRectF(scene_point, me->scenePos()).normalized());
if (fmm_drag) {
if (mm_ci == 0) {
scene_->addItem(&sel_rect);
sel_rect.show();
if (!mm_mods.testFlag(Qt::ControlModifier))
clearSelection();
} else {
if (!mm_mods.testFlag(Qt::ControlModifier) && !mm_ci->isSelected()) {
clearSelection();
mm_ci->setSelected(true);
}
}
saveSelState();
if (mm_ci != 0)
if (!sel_items.contains(mm_ci))
mm_ci = 0;
}
}
}
if (sel_rect.isVisible())
applySelRect(me);
else {
if (mm_drag && mm_ci != 0) {
mdp = (me->scenePos() - scene_point);
if (grid_snap)
mdp = quantize(mdp, grid_step);
if (!mdp.isNull()) {
scene_point += mdp;
copy_dp += mdp;
}
if (mm_copy) {
if (!mdp.isNull())
moved = true;
foreach (QGraphicsItem * i, copy_items)
i->setPos(i->pos() + mdp);
foreach (BlockBusItem * i, copy_buses)
i->movePolyline(mdp);
}
if (!mm_mods.testFlag(Qt::ControlModifier) && !mm_mods.testFlag(Qt::ShiftModifier)) {
if (!mdp.isNull())
moved = true;
foreach (QGraphicsItem * i, sel_items)
if (i->flags().testFlag(QGraphicsItem::ItemIsMovable))
i->setPos(i->pos() + mdp);
if (!me->modifiers().testFlag(Qt::AltModifier))
moveBuses(sel_items, mdp);
setCursor(Qt::ClosedHandCursor);
}
return true;
}
}
if (mm_ci)
if (mm_ci->data(1100).toBool())
return true;
}
if (me->modifiers().testFlag(Qt::ControlModifier) && me->buttons() != 0 && mm_ci == 0)
return true;
//qDebug() << "scene mouse";
//return true;
break;
case QEvent::GraphicsSceneMouseRelease:
if (me->buttons().testFlag(Qt::LeftButton)) btncnt++;
if (me->buttons().testFlag(Qt::RightButton)) btncnt++;
if (me->buttons().testFlag(Qt::MidButton)) btncnt++;
mm_cancel = btncnt > 0;
if (mm_cancel || (me->button() == Qt::MidButton) || (me->button() == Qt::RightButton)) {
mm_ci = 0;
return true;
}
if (mm_ci)
if (mm_ci->data(1008).toBool()) {
mm_ci = 0;
break;
}
if (mm_copy) {
QList<QGraphicsItem*> ai;
blockSignals(true);
if (moved) {
QList<BlockItem*> ci;
QList<BlockBusItem*> bi;
foreach (QGraphicsItem * b, sel_items)
if (b->data(1006) == "item") {
ci << qgraphicsitem_cast<BlockItem*>(b);
ai << qgraphicsitem_cast<QGraphicsItem*>(b);
}
bi = internalBuses(ci);
if (!ci.isEmpty()) copyBlocks(ci, copy_dp);
if (!bi.isEmpty()) copyBuses(bi, copy_dp);
}
deleteCopyTemp();
blockSignals(false);
if (moved) {
moved = false;
reconnectAll();
emitActionEvent(BlockItemBase::BlockCopy, ai);
}
}
if (new_branch) {
hideTmpBuses(false);
}
if (moved && pm_connect) {
QList<QGraphicsItem*> ci;
foreach (QGraphicsItem * b, sel_items)
if (b->data(1006) == "item")
ci << b;
simplifyBuses();
emitActionEvent(BlockItemBase::BlockMove, ci);
reconnectAll();
}
moved = mm_copy = false;
if (tmp_bus.isVisible()) {
if (!tmp_bus.pol.isEmpty()) {
if (match_bus == 0) {
BlockBusItem * nb = new BlockBusItem(tmp_bus);
addItem(nb, tmp_buses.isEmpty());
foreach (BlockBusItem * b, tmp_buses) {
nb = new BlockBusItem(*b);
addItem(nb, b == tmp_buses.back());
}
} else {
if (connectTmpToBus(match_bus)) {
emitActionEvent(BlockItemBase::BusAdd, QList<QGraphicsItem*>() << match_bus);
emit connectionsChanged();
}
}
}
unmarkPins();
hideTmpBuses();
reconnectAll();
BlockItemPin * pin = getPin(scene_->items(me->scenePos()));
if (pin)
pin->hoverEnterEvent(0);
m_trace_with_buses = prev_tcb;
}
clearBusStates();
if (!mm_drag) {
switch (smode) {
case SingleSelection:
clearSelection();
if (mm_ci)
mm_ci->setSelected(true);
break;
case MultiSelection:
if (mm_ci == 0 || !me->modifiers().testFlag(Qt::ControlModifier)) {
clearSelection();
if (mm_ci)
mm_ci->setSelected(true);
} else {
if (mm_ci != 0) {
if (me->modifiers().testFlag(Qt::ControlModifier)) {
if (mm_ci->data(1006) == "item")
mm_ci->setSelected(!mm_ci->isSelected());
} else
mm_ci->setSelected(true);
}
}
break;
default:
clearSelection();
break;
}
}
sel_rect.hide();
if (sel_rect.scene())
scene_->removeItem(&sel_rect);
mm_drag = false;
mm_ci = 0;
unsetCursor();
break;
default: break;
}
}
return QGraphicsView::eventFilter(o, e);
}
void BlockView::stopTimer(int & tid) {
if (tid > 0) killTimer(tid);
tid = 0;
}
void BlockView::restartTimer(int & tid, int msecs) {
stopTimer(tid);
tid = startTimer(msecs);
}
void BlockView::timerEvent(QTimerEvent * e) {
if (e->timerId() == timer_thumb) {
thumbHide();
stopTimer(timer_thumb);
return;
}
QGraphicsView::timerEvent(e);
}
void BlockView::wheelEvent(QWheelEvent * e) {
if (!navigation) return;
if (wheel_zoom || e->modifiers().testFlag(Qt::ControlModifier)) {
double scl = 1. - e->delta() / 500.;
if (!is_nav_anim || (nav_anim.state() != QPropertyAnimation::Running))
nav_target = _nav();
QRectF r = nav_target;
double vw = viewport()->width(), vh = viewport()->height();
double cx = double(e->pos().x()) / vw, cy = double(e->pos().y()) / vh;
double pw = r.width(), ph = r.height();
r.setWidth(r.width() * scl);
r.setHeight(r.width() * vh / vw);
r.translate(cx * (pw - r.width()), cy * (ph - r.height()));
animateNav(r, scl);
return;
}
if (!wheel_zoom) QGraphicsView::wheelEvent(e);
}
void BlockView::mousePressEvent(QMouseEvent * event) {
press_point = event->pos();
if (event->buttons().testFlag(Qt::MidButton) || event->buttons().testFlag(Qt::RightButton)) {
setCursor(Qt::ClosedHandCursor);
sel_rect.hide();
if (sel_rect.scene())
scene_->removeItem(&sel_rect);
}
QGraphicsView::mousePressEvent(event);
}
void BlockView::mouseReleaseEvent(QMouseEvent * event) {
unsetCursor();
QGraphicsView::mouseReleaseEvent(event);
}
void BlockView::updateNavRect() {
QPointF t = mapToScene(viewport()->rect().topLeft());
QPointF b = mapToScene(viewport()->rect().bottomRight());
nav_rect = QRectF(t, b);
}
void BlockView::scrolled() {
updateNavRect();
}
void BlockView::mouseMoveEvent(QMouseEvent * event) {
if (navigation) {
if (event->buttons().testFlag(Qt::MidButton) || event->buttons().testFlag(Qt::RightButton)) {
QPoint dp = (press_point - event->pos());
horizontalScrollBar()->setValue(horizontalScrollBar()->value() + dp.x());
verticalScrollBar()->setValue(verticalScrollBar()->value() + dp.y());
press_point = event->pos();
updateNavRect();
QRectF nr = nav_anim.endValue().toRectF();
nr.moveCenter(_nav().center());
nav_anim.setEndValue(nr);
return;
}
}
QGraphicsView::mouseMoveEvent(event);
}
void BlockView::mouseDoubleClickEvent(QMouseEvent * event) {
if (event->buttons().testFlag(Qt::MidButton) || event->buttons().testFlag(Qt::RightButton)) {
fitInView();
return;
}
QGraphicsView::mouseDoubleClickEvent(event);
}
void BlockView::keyPressEvent(QKeyEvent * e) {
BlockItemPin * pin = getPin(items(mapFromGlobal(QCursor::pos())));
if (pin) {
//qDebug() << "pin" << pin->state();
if (pin->state() == BlockItemPin::Hover) {
highlightNearPins(pin, e->modifiers());
}
}
if (tmp_bus.isVisible()) {
bool retrace = false;
if (e->key() == Qt::Key_Shift) {
retrace = true;
switch (wavetrace.preferredDirection()) {
case BlockViewWavetrace::NoTrace: wavetrace.setPreferredDirection(BlockViewWavetrace::Horizontal); break;
case BlockViewWavetrace::Horizontal: wavetrace.setPreferredDirection(BlockViewWavetrace::Vertical); break;
case BlockViewWavetrace::Vertical: wavetrace.setPreferredDirection(BlockViewWavetrace::NoTrace); break;
}
}
if (e->key() == Qt::Key_Alt) {
retrace = true;
m_trace_with_buses = !m_trace_with_buses;
}
if (retrace) {
trace(last_trace_from, trace_to, &tmp_bus);
for (int i = 0; i < qMin(tmp_buses.size(), last_multiconnect_pl.size()); ++i) {
QPointF dp = last_multiconnect_pl[i]->scenePos() - last_trace_from;
//qDebug() << "trace" << i << dp;
trace(last_trace_from + dp, trace_to + dp, tmp_buses[i], false);
tmp_buses[i]->show();
}
return;
}
}
QGraphicsView::keyPressEvent(e);
}
void BlockView::keyReleaseEvent(QKeyEvent * e) {
BlockItemPin * pin = getPin(items(mapFromGlobal(QCursor::pos())));
if (pin) {
//qDebug() << "pin" << pin->state();
if (pin->state() == BlockItemPin::Hover) {
highlightNearPins(pin, e->modifiers());
}
}
QGraphicsView::keyReleaseEvent(e);
}
void BlockView::resizeEvent(QResizeEvent * event) {
QGraphicsView::resizeEvent(event);
thick = lineThickness();
adjustThumb();
updateNavRect();
nav_target = _nav();
}
void BlockView::scrollContentsBy(int dx, int dy) {
QGraphicsView::scrollContentsBy(dx, dy);
if (isHidden()) return;
thumbShow();
restartTimer(timer_thumb, thumb_hide_delay);
QMetaObject::invokeMethod(&widget_thumb, "update", Qt::QueuedConnection);
}
void BlockView::drawBackground(QPainter * painter, const QRectF & rect) {
// QGraphicsView::drawBackground(painter, rect);
if (mm_thumb) return;
float rx, ry, sx = grid_step, sy = grid_step;
double scl = qRound(1. / qSqrt(transform().determinant()));
painter->fillRect(rect, palette().brush(QPalette::Base));
painter->setRenderHint(QPainter::Antialiasing, false);
if (scl > 0.) {
sx *= scl;
sy *= scl;
}
if (!grid_visible) return;
rx = quantize(rect.left(), sx);
ry = quantize(rect.top(), sy);
bool gp = grid_points > 0.5;
if (gp) {
QPen pp(grid_pen.color(), qMax<int>(grid_points, thick), Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
pp.setCosmetic(true);
painter->setPen(pp);
for(int i = 0; i < qCeil(rect.width() / sx) + 1; ++i)
for(int j = 0; j < qCeil(rect.height() / sy) + 1; ++j)
painter->drawPoint(rx + i * sx, ry + j * sy);
}
if (grid_pen.style() == Qt::NoPen) return;
QPen pen = grid_pen;
pen.setWidth(qMax<int>(pen.width(), thick));
painter->setPen(grid_pen);
for(int i = 0; i < qCeil(rect.width() / sx) + 1; ++i) {
double cx = rx + i * sx;
painter->drawLine(cx, ry, cx, ry + rect.height());
}
for(int j = 0; j < qCeil(rect.height() / sy) + 1; ++j) {
double cy = ry + j * sy;
painter->drawLine(rx, cy, rx + rect.width(), cy);
}
}
void BlockView::scrollFromThumb() {
QRect r(thumb_vr);
double scl(thumb_scl);
horizontalScrollBar()->setValue(r.x() / scl + horizontalScrollBar()->minimum());
verticalScrollBar()->setValue(r.y() / scl + verticalScrollBar()->minimum());
}
void BlockView::deleteCopyTemp() {
qDeleteAll(copy_items);
copy_items.clear();
qDeleteAll(copy_buses);
copy_buses.clear();
}
void BlockView::emitActionEvent(BlockItemBase::Action action, QList<QGraphicsItem * > items) {
if (!ae_enabled) return;
emit schemeAction(action, items);
}
void BlockView::setGhost(BlockItem * item) {
clearGhost();
if (!item) return;
ghost_ = item;
ghost_->setOpacity(0.5);
addItem(item);
}
void BlockView::clearGhost() {
if (!ghost_) return;
delete ghost_;
ghost_ = 0;
}
void BlockView::drawThumb() {
if (!minimap) return;
QPainter p(&widget_thumb);
QRect wr = widget_thumb.rect().adjusted(0, 0, -1, -1);
QSizeF sr = sceneRect().size(), tr;
if (sr.width() >= sr.height())
thumb_scl = thumb_size.width() / sr.width();
else
thumb_scl = thumb_size.height() / sr.height();
tr = sr * thumb_scl;
cur_scl = qSqrt(transform().determinant());
thumb_scl /= cur_scl;
QSizeF vs(size().width() - verticalScrollBar()->width(), size().height() - horizontalScrollBar()->height());
QRectF vr(QPointF(horizontalScrollBar()->value() - horizontalScrollBar()->minimum(),
verticalScrollBar()->value() - verticalScrollBar()->minimum()) * thumb_scl, vs * thumb_scl);
vr.adjust(0, 0, -1, -1);
p.setBrush(Qt::lightGray);
p.setOpacity(0.5 * _talpha);
p.drawRect(wr);
p.drawImage(0, 0, im_scene);
p.setBrush(Qt::NoBrush);
p.drawRect(wr);
p.setBrush(Qt::white);
p.setRenderHint(QPainter::Antialiasing);
p.drawRect(vr);
thumb_sr = wr;
thumb_vr = vr.toRect();
}
void BlockView::drawSceneThumb() {
if (!minimap) return;
QRect wr = widget_thumb.rect().adjusted(0, 0, -1, -1);
im_scene = QImage(wr.size(), QImage::Format_ARGB32);
im_scene.fill(Qt::transparent);
QPainter p(&im_scene);
p.setRenderHint(QPainter::Antialiasing);
mm_thumb = true;
scene_->render(&p, im_scene.rect());
mm_thumb = false;
}
void BlockView::thumbHide() {
if (!minimap) {
widget_thumb.hide();
return;
}
if (QApplication::widgetAt(QCursor::pos()) == &widget_thumb) return;
thumb_anim.stop();
thumb_anim.setDuration(1000);
thumb_anim.setStartValue(_thumb());
thumb_anim.setEndValue(0.);
thumb_anim.start();
//qDebug() << "hide" << thumb_anim.startValue() << thumb_anim.endValue();
//widget_thumb.hide();
}
void BlockView::thumbShow() {
if (!minimap) return;
if (widget_thumb.isHidden() || (_talpha < 0.1)) drawSceneThumb();
thumb_anim.stop();
/*thumb_anim.setDuration(100);
thumb_anim.setStartValue(_thumb());
thumb_anim.setEndValue(1.);
thumb_anim.start();*/
_setThumb(1.);
//qDebug() << "show" << thumb_anim.startValue() << thumb_anim.endValue();
//widget_thumb.show();
}
void BlockView::clearSelection() {
sel_items.clear();
QList<QGraphicsItem*> gi = scene_->items();
foreach (QGraphicsItem * i, gi)
i->setSelected(false);
}
void BlockView::addItem(QGraphicsItem * item, bool emit_action) {
scene_->addItem(item);
applyGridStep();
if (item->data(1005) == "connection") {
loadBus(qgraphicsitem_cast<BlockBusItem*>(item));
connect((BlockBusItem*)item, SIGNAL(destroyed(QObject*)), this, SLOT(removedBus(QObject*)), Qt::UniqueConnection);
if (emit_action) emitActionEvent(BlockItemBase::BusAdd, QList<QGraphicsItem*>() << item);
emit connectionsChanged();
return;
}
if (item->data(1006) == "item") {
connect((BlockItem*)item, SIGNAL(destroyed(QObject*)), this, SLOT(removedBlock(QObject*)), Qt::UniqueConnection);
connect((BlockItem*)item, SIGNAL(blockHoverEnter(BlockItem*)), this, SIGNAL(blockHoverEnter(BlockItem*)), Qt::UniqueConnection);
connect((BlockItem*)item, SIGNAL(blockHoverLeave(BlockItem*)), this, SIGNAL(blockHoverLeave(BlockItem*)), Qt::UniqueConnection);
if (emit_action) emitActionEvent(BlockItemBase::BlockAdd, QList<QGraphicsItem*>() << item);
return;
}
item->setData(1009, "decor");
}
QList<BlockBusItem * > BlockView::buses() const {
QList<BlockBusItem * > ret;
QList<QGraphicsItem*> gi = scene_->items();
foreach (QGraphicsItem * i, gi)
if (i->data(1005) == "connection")
if (!copy_buses.contains((BlockBusItem*)i))
ret << qgraphicsitem_cast<BlockBusItem*>(i);
return ret;
}
QList<BlockBusItem * > BlockView::wrongConnectedBuses() const {
QList<BlockBusItem * > sl = buses(), ret;
QList<BlockItem * > bl = blocks();
foreach (BlockItem * b, bl) {
QVector<BlockItemPin * > pins = b->pins();
foreach (BlockItemPin * p, pins)
if (p->state() == BlockItemPin::Reject) {
QPointF pp = p->scenePos();
foreach (BlockBusItem * s, sl)
if (s->pol.contains(pp))
if (!ret.contains(s))
ret << s;
}
}
return ret;
}
QList<BlockItem * > BlockView::blocks() const {
QList<BlockItem * > ret;
QList<QGraphicsItem*> gi = scene_->items();
foreach (QGraphicsItem * i, gi)
if (i->data(1006) == "item")
ret << qgraphicsitem_cast<BlockItem*>(i);
return ret;
}
QList<QGraphicsItem * > BlockView::decors() const {
QList<QGraphicsItem*> ret, gi = scene_->items();
foreach (QGraphicsItem * i, gi)
if ((i->data(1009) == "decor") && !i->data(1008).toBool() && (i->parentItem() == 0)
&& (i != &sel_rect) && (i != &tmp_bus) && !tmp_buses.contains((BlockBusItem*)i))
ret << i;
return ret;
}
BlockBusItem * BlockView::connectionBus(BlockItem * b0, BlockItem * b1) const {
QList<BlockBusItem * > cbl = connectionBuses(b0, b1);
if (cbl.isEmpty()) return 0;
return cbl.front();
}
QList<BlockBusItem * > BlockView::connectionBuses(BlockItem * b0, BlockItem * b1) const {
if (!b0 || !b1) return QList<BlockBusItem * >();
QSet<BlockBusItem * > bs0 = b0->connectedBuses().toSet(), bs1 = b1->connectedBuses().toSet();
return (bs0 & bs1).values();
}
bool BlockView::connectPins(BlockItemPin * p0, BlockItemPin * p1) {
if (!p0 || !p1) return false;
if (p0 == p1) return false;
if (p0->busType() != p1->busType()) return false;
QList<BlockBusItem * > bl0 = p0->connectedBuses(), bl1 = p1->connectedBuses();
if (!(bl0.toSet() & bl1.toSet()).isEmpty()) return true;
BlockBusItem * nb = new BlockBusItem();
nb->setBusType(p0->busType());
//nb->setEndpointsNumber(3);
loadBus(nb);
if (!bl0.isEmpty() && !bl1.isEmpty()) { // connect two existing buses
} else {
if ((bl0.isEmpty() && !bl1.isEmpty()) || (bl1.isEmpty() && !bl0.isEmpty())) { // connect empty pin to existing bus
BlockItemPin * ep = 0;
BlockBusItem * eb = 0;
if (bl0.isEmpty()) {ep = p0; eb = bl1[0];}
else {ep = p1; eb = bl0[0];}
double md = -1; int mi = -1;
QPointF sp = ep->scenePos();
if (eb->pol.size() == 2) {
eb->selSegment = 0;
eb->addPoint((eb->pol[0] + eb->pol[1]) / 2.);
eb->selPoint = -1;
mi = 2;
} else {
for (int i = 0; i < eb->pol.size(); ++i) {
if (eb->ends.contains(i)) continue;
double cd = QVector2D(sp - eb->pol[i]).lengthSquared();
if (md < 0 || md > cd) {
md = cd;
mi = i;
}
}
}
if (mi < 0) {
return false;
}
trace(ep->scenePos(), eb->pol[mi], nb);
if (nb->pol.size() < 2) {
delete nb;
return false;
}
nb->pol.pop_back();
int lp = eb->pol.size();
eb->pol << nb->pol;
for (int i = 0; i < nb->pol.size() - 1; ++i)
eb->segments << QPair<int, int>(lp + i, lp + i + 1);
eb->segments << QPair<int, int>(mi, lp + nb->pol.size() - 1);
eb->updateGeometry();
delete nb;
} else { // connect two empty pins
trace(p0->scenePos(), p1->scenePos(), nb);
if (nb->pol.isEmpty()) {
delete nb;
return false;
}
addItem(nb);
}
}
reconnectAll();
emitActionEvent(BlockItemBase::BusAdd, QList<QGraphicsItem*>() << nb);
emit connectionsChanged();
return true;
}
void BlockView::setTransform(const QTransform & matrix, bool combine) {
QGraphicsView::setTransform(matrix, combine);
updateNavRect();
nav_target = _nav();
}
void BlockView::centerOn(const QPointF & pos) {
QGraphicsView::centerOn(pos);
updateNavRect();
nav_target = _nav();
}
void BlockView::centerOn(qreal x, qreal y) {
QGraphicsView::centerOn(x, y);
updateNavRect();
nav_target = _nav();
}
void BlockView::centerOn(const QGraphicsItem * item) {
QGraphicsView::centerOn(item);
updateNavRect();
nav_target = _nav();
}
void BlockView::fitInView(const QRectF & rect, Qt::AspectRatioMode aspectRatioMode) {
QGraphicsView::fitInView(rect, aspectRatioMode);
updateNavRect();
nav_target = _nav();
}
void BlockView::fitInView(qreal x, qreal y, qreal w, qreal h, Qt::AspectRatioMode aspectRatioMode) {
QGraphicsView::fitInView(x, y, w, h, aspectRatioMode);
updateNavRect();
nav_target = _nav();
}
void BlockView::fitInView(const QGraphicsItem * item, Qt::AspectRatioMode aspectRatioMode) {
QGraphicsView::fitInView(item, aspectRatioMode);
updateNavRect();
nav_target = _nav();
}
void BlockView::fitInView() {
QRectF r = _nav();
QGraphicsView::fitInView(itemsBoundingRect(), Qt::KeepAspectRatio);
updateNavRect();
QRectF t = _nav();
QGraphicsView::fitInView(r, Qt::KeepAspectRatio);
updateNavRect();
animateNav(t);
}
QRectF BlockView::itemsBoundingRect() const {
QList<QGraphicsItem*> gi = scene_->items();
if (gi.isEmpty()) return QRectF();
bool f = true;
QRectF ret;
foreach (QGraphicsItem * i, gi)
if (i->isVisible() && (i != &tmp_bus) && !tmp_buses.contains((BlockBusItem*)i)) {
if ((i->data(1007) != "item_selection") && !i->data(1008).toBool()) {
QRectF br = i->mapRectToScene(i->boundingRect());
if (br.width() <= 1 || br.height() <= 1) continue;
if (f) ret = br;
else ret |= br;
f = false;
}
}
return ret;
}
void BlockView::restoreSelState() {
foreach (QGraphicsItem * i, sel_items) {
i->setPos(i->data(1001).toPointF());
}
QList<QGraphicsItem*> gi = scene_->items();
foreach (QGraphicsItem * i, gi)
if (i->data(1005) == "connection") {
BlockBusItem * bi = qgraphicsitem_cast<BlockBusItem*>(i);
bi->pol = bi->bpol;
bi->prepareGeometryChange();
}
}
void BlockView::saveSelState() {
QList<QGraphicsItem*> gi = scene_->items();
sel_items = scene_->selectedItems();
foreach (QGraphicsItem * i, gi) {
i->setData(1000, i->isSelected());
i->setData(1001, i->pos());
if (i->data(1005) == "connection")
qgraphicsitem_cast<BlockBusItem*>(i)->bpol = qgraphicsitem_cast<BlockBusItem*>(i)->pol;
}
}
void BlockView::saveBusesState() {
QList<BlockBusItem*> bl = buses();
foreach (BlockBusItem * b, bl)
b->saveState();
}
void BlockView::restoreBusesState() {
QList<BlockBusItem*> bl = buses();
foreach (BlockBusItem * b, bl)
b->restoreState();
}
void BlockView::applySelRect(QGraphicsSceneMouseEvent * me) {
QList<QGraphicsItem*> ci = sel_rect.collidingItems(Qt::IntersectsItemBoundingRect);
QList<QGraphicsItem*> gi = scene_->items();
bool add = me->modifiers().testFlag(Qt::ControlModifier);
if (!add) clearSelection();
else {
foreach (QGraphicsItem * i, gi)
i->setSelected(i->data(1000).toBool());
}
foreach (QGraphicsItem * i, ci) {
i->setSelected(!i->isSelected());
}
}
void BlockView::applyGridStep() {
QList<QGraphicsItem*> gi = scene_->items();
foreach (QGraphicsItem * i, gi)
if (i->type() == QGraphicsItem::UserType + 2)
qgraphicsitem_cast<BlockBusItem*>(i)->setGridStep(grid_step);
}
void BlockView::trace(QPointF scene_pos_from, QPointF scene_pos_to, BlockBusItem * bus, bool primary) {
if (primary) {
if (hpin)
scene_pos_to = hpin->scenePos();
last_trace_from = scene_pos_from;
trace_to = scene_pos_to;
}
QRect sr = scene_->sceneRect().toRect();
int dx = sr.left() / grid_step, dy = sr.top() / grid_step;
//qDebug() << dp;
QPoint dp(-dx, -dy), qpt = quantize(scene_pos_to, grid_step).toPoint() / grid_step + dp;
QTime tm;
tm.restart();
wavetrace.resize(sr.size() / grid_step);
wavetrace.fill(BlockViewWavetrace::Empty);
QList<QGraphicsItem*> gi = scene_->items();
foreach (QGraphicsItem * i, gi)
if (i->data(1006) == "item") {
QRect ir = i->mapRectToScene(i->boundingRect()).toRect().normalized();
wavetrace.fill(QRect(ir.topLeft() / grid_step + dp, ir.bottomRight() / grid_step + dp), BlockViewWavetrace::Blocked);
QVector<BlockItemPin * > pins = qgraphicsitem_cast<BlockItem * >(i)->pins();
foreach (BlockItemPin * p, pins) {
if (p->busType() == bus->busType())
wavetrace.fill(quantize(p->scenePos(), grid_step).toPoint() / grid_step + dp, BlockViewWavetrace::Empty);
}
}
if (m_trace_with_buses) {
foreach (QGraphicsItem * i, gi)
if (i->data(1005) == "connection") {
BlockBusItem * b = qgraphicsitem_cast<BlockBusItem * >(i);
if (!b) continue;
for (int s = 0; s < b->segments.size(); ++s) {
QPointF p0 = b->pol[b->segments[s].first], p1 = b->pol[b->segments[s].second], cp = p0;
double sx(0.), sy(0.), dx = qAbs(p1.x() - p0.x()), dy = qAbs(p1.y() - p0.y());
double signx = (p1.x() >= p0.x() ? 1. : -1.), signy = (p1.y() >= p0.y() ? 1. : -1.);
int steps(0);
if ((dx + dy) < grid_step) continue;
if (dx >= dy) { // by x
sx = grid_step;
sy = sx * dy / dx;
steps = qRound(dx / grid_step);
} else {
sy = grid_step;
sx = sy * dx / dy;
steps = qRound(dy / grid_step);
}
sx *= signx;
sy *= signy;
//qDebug() << "fill" << p0 << "->" << p1 << "in" << steps << sx << sy;
for (int j = 0; j < steps; ++j) {
QPoint tp = quantize(cp, grid_step).toPoint() / grid_step + dp;
if (tp != qpt)
wavetrace.fill(tp, BlockViewWavetrace::Blocked);
//qDebug() << " set" << cp;
cp += QPointF(sx, sy);
}
}
}
}
bus->clear();
if (wavetrace.trace(quantize(scene_pos_from, grid_step).toPoint() / grid_step + dp, qpt)) {
wavetrace.gatherPath();
foreach (const QPoint & p, wavetrace.path()) {
bus->appendPoint((p - dp) * grid_step);
}
}
//qDebug() << quantize(scene_pos_from, grid_step).toPoint() / grid_step + dp << qpt;
scene_->update();
}
void BlockView::clearBusStates() {
QList<QGraphicsItem * > gi = scene_->items();
foreach (QGraphicsItem * i, gi)
if (i->data(1005) == "connection") {
BlockBusItem * b = qgraphicsitem_cast<BlockBusItem*>(i);
b->clearBusState();
// if (i != bus_from && i != match_bus)
//b->selPoint = b->selSegment = -1;
}
}
void BlockView::matchBus() {
match_bus = 0;
bool bv = tmp_bus.isVisible();
QList<QGraphicsItem * > gi = scene_->items();
QList<BlockBusItem * > buses;
QList<BlockItem * > blockl;
int sp = -1, ss = -1;
QPointF point;
iconnect = false;
if (!tmp_bus.pol.isEmpty())
point = tmp_bus.pol.back();
foreach (QGraphicsItem * i, gi) {
if (i != bus_from) {
if (i->data(1005) == "connection")
buses << qgraphicsitem_cast<BlockBusItem*>(i);
if (i->data(1006) == "item")
blockl << qgraphicsitem_cast<BlockItem*>(i);
}
}
foreach (BlockBusItem * b, buses) {
b->clearBusState();
b->selPoint = b->selSegment = -1;
}
if (!bv) return;
BlockBusItem * b(0);
if (m_pin_mc) {
foreach (BlockItem * b_, blockl)
foreach (BlockItemPin * p_, b_->pins())
if (p_->scenePos() == point) {
return;
}
}
//qDebug() << "1" << buses.size() << tmp_bus.pol;
for (int i = 0; i < buses.size(); ++i) {
b = buses[i];
b->testPoint(point, &sp, &ss);
//qDebug() << i << sp << ss;
if (sp >= 0 || ss >= 0) break;
}
if ((sp < 0 && ss < 0) || b == 0) return;
//qDebug("2");
match_bus = b;
if ((b->busType() != tmp_bus.busType()) || b->connections_.value(sp, 0) != 0) {
b->setBusState(false);
} else {
if (b->max_ep >= 2) {
if (bus_from == 0) {
if (ss >= 0) {
if (b->endpointCount() >= b->max_ep) {
b->setBusState(false);
return;
}
}
if (sp >= 0) {
if (b->endpointCount() + b->pointSegmentsCount(sp) - 2 >= b->max_ep) {
b->setBusState(false);
return;
}
}
} else {
int sep = b->endpointCount() + bus_from->endpointCount();
if (b->pointSegmentsCount(sp) == 1) sep--;
if (bus_from->selPoint >= 0)
if (bus_from->pointSegmentsCount(bus_from->selPoint) == 1) sep--;
if (sep > b->max_ep) {
b->setBusState(false);
return;
}
}
}
//b->press_point = point;
iconnect = true;
b->setBusState(true);
b->selPoint = sp;
b->selSegment = ss;
}
}
bool BlockView::connectTmpToBus(BlockBusItem * bus) {
if (bus == 0) return false;
if (!bus->busState()) return false;
if (tmp_bus.pol.size() < 2) return false;
int np = bus->selPoint;
if (np < 0)
np = bus->addPoint(tmp_bus.pol.back());
if (np < 0) return false;
tmp_bus.pol.pop_back();
int lp = bus->pol.size();
bus->pol << tmp_bus.pol;
for (int i = 0; i < tmp_bus.pol.size() - 1; ++i)
bus->segments << QPair<int, int>(lp + i, lp + i + 1);
bus->segments << QPair<int, int>(np, lp + tmp_bus.pol.size() - 1);
bus->updateGeometry();
tmp_bus.clear();
return true;
}
void BlockView::markPins(int bus_type) {
unhoverPins();
QList<QGraphicsItem * > gi = scene_->items();
foreach (QGraphicsItem * i, gi) {
if (i->data(1004) == "pin") {
BlockItemPin * p = qgraphicsitem_cast<BlockItemPin*>(i);
p->saveState();
if (m_pin_mc) {
if (p->busType() == bus_type)
p->setState(BlockItemPin::Accept);
} else {
if (p->busType() == bus_type) {
if (p->state() == BlockItemPin::Disconnected)
p->setState(BlockItemPin::Accept);
// else
// p->animAccept();
}
}
}
}
}
void BlockView::unmarkPins(bool to_normal) {
unhoverPins();
QList<QGraphicsItem * > gi = scene_->items();
foreach (QGraphicsItem * i, gi) {
if (i->data(1004) == "pin") {
qgraphicsitem_cast<BlockItemPin*>(i)->restoreState();
if (to_normal)
while (qgraphicsitem_cast<BlockItemPin*>(i)->restoreState());
}
}
}
void BlockView::hoverAcceptedPin(BlockItemPin * pin, bool hover) {
if (!pin) return;
pin->enlargePin(hover);
}
void BlockView::unhoverPins(BlockItemPin* excl_pin) {
QList<QGraphicsItem * > gi = scene_->items();
foreach (QGraphicsItem * i, gi) {
if (excl_pin == ((BlockItemPin*)i)) continue;
if (i->data(1004) == "pin") {
((BlockItemPin*)i)->enlargePin(false);
}
}
}
void BlockView::simplifyBuses() {
QList<BlockBusItem*> bl = buses();
foreach (BlockBusItem * b, bl)
b->simplify();
}
void BlockView::moveBuses(const QList<QGraphicsItem * > & items, QPointF dp) {
if (dp.isNull()) return;
QList<QGraphicsItem * > gi = scene_->items();
QVector<BlockItemPin * > pins;
QList<BlockBusItem * > buses;
//qDebug() << "move" << dp;
foreach (QGraphicsItem * i, items)
if (i->data(1006) == "item" && i->flags().testFlag(QGraphicsItem::ItemIsMovable))
pins << qgraphicsitem_cast<BlockItem*>(i)->pins();
foreach (QGraphicsItem * i, gi)
if (i->data(1005) == "connection")
buses << qgraphicsitem_cast<BlockBusItem*>(i);
foreach (BlockBusItem * b, buses) {
QList<BlockItemPin * > bpins = b->connections_.values();
if (!bpins.isEmpty()) {
foreach (BlockItemPin * p, pins)
bpins.removeAll(p);
if (bpins.isEmpty()) {
b->movePolyline(dp);
continue;
}
}
foreach (BlockItemPin * p, pins) {
QList<int> ends = b->connections_.keys(p);
for (int i = 0; i < ends.size(); ++i) {
/*int isp = b->segmentPointPair(ends[i]);
QPointF sdp;
if (isp >= 0 && b->pol.size() > 2) {
sdp = b->pol[isp] - b->pol[ends[i]];
if (!sdp.isNull()) {
if (sdp.x() == 0. && dp.x() != 0.)
b->movePoint(isp, QPointF(dp.x(), 0.));
if (sdp.y() == 0. && dp.y() != 0.)
b->movePoint(isp, QPointF(0., dp.y()));
} else {
if (p->alignment() == Qt::AlignTop || p->alignment() == Qt::AlignBottom)
b->movePoint(isp, QPointF(dp.x(), 0.));
if (p->alignment() == Qt::AlignLeft || p->alignment() == Qt::AlignRight)
b->movePoint(isp, QPointF(0., dp.y()));
}
}*/
QPointF pdp = dp;
double ang = 0.;
switch (p->alignment()) {
case Qt::AlignRight : pdp.setX(0.); ang = 0.; break;
case Qt::AlignTop : pdp.setY(0.); ang = 90.; break;
case Qt::AlignLeft : pdp.setX(0.); ang = 180.; break;
case Qt::AlignBottom: pdp.setY(0.); ang = 270.; break;
default: break;
}
QVector<int> epl = b->endpointLine(ends[i], ang);
foreach (int e, epl)
b->movePoint(e, pdp);
b->movePoint(ends[i], dp);
}
}
}
}
QList<BlockBusItem * > BlockView::internalBuses(const QList<BlockItem * > & items) {
QList<BlockBusItem * > ret;
if (items.isEmpty()) return ret;
QList<BlockBusItem * > sbl = buses();
QSet<BlockItem * > sis = QSet<BlockItem * >::fromList(items);
foreach (BlockBusItem * bi, sbl) {
if (bi->connectedBlocks().isEmpty()) continue;
QSet<BlockItem * > bis = QSet<BlockItem * >::fromList(bi->connectedBlocks());
if ((bis - sis).isEmpty())
ret << bi;
}
return ret;
}
QList<BlockItemPin * > BlockView::nearPins(BlockItemPin * pin, Qt::KeyboardModifiers km) {
QList<BlockItemPin * > ret;
bool up = km.testFlag(Qt::ShiftModifier);
bool down = km.testFlag(Qt::ControlModifier);
bool ab = km.testFlag(Qt::AltModifier);
//qDebug() << "nearPins" << km;
if (!pin || (!up && !down)) return ret;
const BlockItem * src = pin->parent();
if (!src) return ret;
bool dirs[2] = {up, down};
double dy[2] = {-1, 1};
for (int i = 0; i < 2; ++i) {
if (!dirs[i]) continue;
const BlockItem * cb = src;
BlockItemPin * cpin = pin;
//qDebug() << "dir" << dirs[i];
while (cpin) {
//qDebug() << "cur" << cpin;
QList<QGraphicsItem * > il = scene_->items(cpin->scenePos() + QPointF(0., dy[i] * cb->pinsMargin()));
BlockItemPin * np = getPin(il);
if (np == cpin) break;
cpin = np;
if (cpin) {
if (((cb != cpin->parent()) && !ab) ||
(cpin->state() != BlockItemPin::Disconnected)) {
break;
}
cb = cpin->parent();
ret << cpin;
}
}
}
return ret;
}
BlockItemPin * BlockView::getPin(const QList<QGraphicsItem *> & list) const {
foreach (QGraphicsItem * i, list) {
if (i->data(1004) == "pin")
return qgraphicsitem_cast<BlockItemPin*>(i);
}
return 0;
}
void BlockView::highlightNearPins(BlockItemPin * pin, Qt::KeyboardModifiers km) {
//qDebug() << "restore for" << last_multiconnect_pl.size();
foreach (BlockItemPin * p, last_multiconnect_pl)
p->restoreState();
QList<BlockItemPin * > pl = nearPins(pin, km);
foreach (BlockItemPin * p, pl) {
p->saveState();
p->setState(BlockItemPin::Hover);
}
last_multiconnect_pl = pl;
}
void BlockView::hideTmpBuses(bool clear) {
tmp_bus.hide();
if (clear) {
tmp_bus.clear();
qDeleteAll(tmp_buses);
tmp_buses.clear();
}
}
QList<BlockItem * > BlockView::selectedBlocks() const {
QList<BlockItem * > ret;
QList<QGraphicsItem * > sil = scene()->selectedItems();
foreach (QGraphicsItem * b, sil)
if (b->data(1006) == "item")
ret << qgraphicsitem_cast<BlockItem*>(b);
return ret;
}
QList<QGraphicsItem * > BlockView::selectedDecors() const {
QList<QGraphicsItem * > ret, sil = decors();
foreach (QGraphicsItem * b, sil)
if (b->isSelected())
ret << b;
return ret;
}
void BlockView::animateNav(QRectF d, double scl) {
nav_target = d;
if (is_nav_anim) {
if (qAbs<double>(scl - 1.) <= 0.1 && (nav_anim.state() != QAbstractAnimation::Running)) {
_setNav(d);
return;
}
if (nav_anim.state() != QAbstractAnimation::Running) {
nav_prev_aa = renderHints().testFlag(QPainter::Antialiasing);
nav_prev_imaa = renderHints().testFlag(QPainter::SmoothPixmapTransform);
nav_prev_grid = isGridVisible();
setRenderHint(QPainter::Antialiasing, false);
setRenderHint(QPainter::SmoothPixmapTransform, false);
setGridVisible(false);
}
nav_anim.stop();
nav_anim.setStartValue(_nav());
nav_anim.setEndValue(d);
nav_anim.start();
} else
_setNav(d);
}
void BlockView::adjustThumb() {
if (!scene()) return;
QSizeF sr = sceneRect().size(), tr;
double scl;
if (sr.width() >= sr.height())
scl = thumb_size.width() / sr.width();
else
scl = thumb_size.height() / sr.height();
tr = sr * scl;
int sx = 0, sy = 0;
if (verticalScrollBar()->isVisible() && (verticalScrollBarPolicy() != Qt::ScrollBarAlwaysOff))
sx = verticalScrollBar()->width();
if (horizontalScrollBar()->isVisible() && (horizontalScrollBarPolicy() != Qt::ScrollBarAlwaysOff))
sy = horizontalScrollBar()->height();
widget_thumb.setGeometry(QRect(QPoint(width() - tr.width() - 10 - sx,
height() - tr.height() - 10 - sy), tr.toSize()));
}
void BlockView::newBranch(BlockBusItem * item) {
bus_from = item;
prev_tcb = m_trace_with_buses;
newBusStarted(item->busType());
markPins(item->busType());
new_branch = true;
tmp_bus.setBusType(item->busType());
if (item->selSegment >= 0) {
QPointF ds(item->pol[item->segments[item->selSegment].first] - item->pol[item->segments[item->selSegment].second]);
if (ds.x() == 0.) wavetrace.setPreferredDirection(BlockViewWavetrace::Horizontal);
if (ds.y() == 0.) wavetrace.setPreferredDirection(BlockViewWavetrace::Vertical);
}
}
void BlockView::startBusPointMove(int bus_type) {
move_bus_point = true;
prev_tcb = m_trace_with_buses;
newBusStarted(bus_type);
markPins(bus_type);
}
void BlockView::endBusPointMove() {
move_bus_point = false;
unmarkPins();
reconnectAll();
}
void BlockView::pinHoverInOut(BlockItemPin * pin) {
//qDebug() << "pinHoverInOut" << pin << pin->state();
highlightNearPins(pin, QApplication::keyboardModifiers());
}
void BlockView::checkPaste(bool queued) {
const QMimeData * mime = QApplication::clipboard()->mimeData();
bool ret = false;
if (mime)
ret = mime->hasFormat(_BlockView_Mime_);
if (queued) QMetaObject::invokeMethod(this, "pasteEnabledChanged", Qt::QueuedConnection, Q_ARG(bool, ret));
else emit pasteEnabledChanged(ret);
}
void BlockView::newBranchTrace(BlockBusItem * item, QPointF to) {
trace(item->press_pos, to, &tmp_bus);
tmp_bus.show();
}
void BlockView::newBranchAccept(BlockBusItem * item) {
unmarkPins();
if (!new_branch) return;
new_branch = false;
tmp_bus.hide();
if (tmp_bus.pol.size() < 2) return;
tmp_bus.pol.pop_front();
int np = item->addPoint(item->press_pos);
if (np < 0) return;
if (match_bus) {
if (iconnect) tmp_bus.pol.pop_back();
else return;
}
if (item == match_bus) return;
int snp = np;
int lp = item->pol.size();
if (!tmp_bus.pol.isEmpty()) {
item->pol << tmp_bus.pol;
item->segments << QPair<int, int>(np, lp);
for (int i = 0; i < tmp_bus.pol.size() - 1; ++i)
item->segments << QPair<int, int>(lp + i, lp + i + 1);
}
if (match_bus != 0) {
if (!iconnect) return;
np = match_bus->selPoint;
if (np < 0)
np = match_bus->addPoint(trace_to);
if (np < 0) return;
lp = item->pol.size();
item->pol << match_bus->pol;
for (int i = 0; i < match_bus->segments.size(); ++i)
item->segments << QPair<int, int>(match_bus->segments[i].first + lp, match_bus->segments[i].second + lp);
if (tmp_bus.pol.isEmpty())
item->segments << QPair<int, int>(lp + np, snp);
else
item->segments << QPair<int, int>(lp + np, lp - 1);
match_bus->setProperty("_nodelete_", true);
match_bus->deleteLater();
match_bus = 0;
}
item->updateGeometry();
emitActionEvent(BlockItemBase::BusAdd, QList<QGraphicsItem*>() << item);
emit connectionsChanged();
tmp_bus.clear();
}
void BlockView::newBranchCancel() {
unmarkPins();
//qDebug() << "cancel";
new_branch = false;
hideTmpBuses();
}
void BlockView::removedBus(QObject * o) {
mm_ci = 0;
reconnectAll();
BlockBusItem * bus = (BlockBusItem*)o;
if (bus->property("_nodelete_").toBool()) return;
emitActionEvent(BlockItemBase::BusRemove, QList<QGraphicsItem*>() << bus);
emit connectionsChanged();
}
void BlockView::removedBlock(QObject * o) {
emit blockRemoved((BlockItem*)o);
emitActionEvent(BlockItemBase::BlockRemove, QList<QGraphicsItem*>() << qgraphicsitem_cast<QGraphicsItem*>((BlockItem*)o));
}
void BlockView::removeJunk() {
QList<QGraphicsItem * > gi = scene_->items();
foreach (QGraphicsItem * i, gi) {
if (i->data(1005) != "connection") continue;
BlockBusItem * b = qgraphicsitem_cast<BlockBusItem*>(i);
if (b->pol.size() <= 1) {
b->deleteLater();
}
}
}
void BlockView::sceneSelectionChanged() {
bool ie = scene()->selectedItems().isEmpty();
emit copyEnabledChanged(!ie);
}
void BlockView::_setThumb(double v) {
_talpha = v;
QMetaObject::invokeMethod(&widget_thumb, "update", Qt::QueuedConnection);
if (_talpha <= 0.01) widget_thumb.hide();
else widget_thumb.show();
}
void BlockView::_setNav(QRectF v) {
double vw = viewport()->width(), vh = viewport()->height();
if (vw < 1. || vh < 1. || v.isEmpty()) return;
QTransform matrix;
double scl = qMin(vw / v.width(), vh / v.height());
double ascl = appScale(this);
if (scl > 0.02 * ascl && scl < 50.0 * ascl) {
matrix.scale(scl, scl);
nav_rect = v;
QGraphicsView::setTransform(matrix);
QGraphicsView::centerOn(v.center());
}
}
QRectF BlockView::_nav() const {
return nav_rect;
}
void BlockView::_navFinished() {
setRenderHint(QPainter::Antialiasing, nav_prev_aa);
setRenderHint(QPainter::SmoothPixmapTransform, nav_prev_imaa);
setGridVisible(nav_prev_grid);
}
void BlockView::reconnectAll() {
//qDebug() << "reconnect";
removeJunk();
QList<QGraphicsItem * > gi = scene_->items();
QList<BlockItemPin * > pins;
QList<BlockBusItem * > buses;
foreach (QGraphicsItem * i, gi) {
if (i->data(1004) == "pin")
pins << qgraphicsitem_cast<BlockItemPin*>(i);
if (i->data(1005) == "connection")
buses << qgraphicsitem_cast<BlockBusItem*>(i);
}
foreach (BlockItemPin * p, pins) {
p->clearStateStack();
p->setState(BlockItemPin::Disconnected);
p->buses_.clear();
}
foreach (BlockBusItem * b, buses) {
b->connections_.clear();
QVector<int> conns(b->endpoints());
for (int c = 0; c < conns.size(); ++c) {
QPointF cp = b->pol[conns[c]];
for (int j = 0; j < pins.size(); ++j) {
if (!pins[j]->isVisible()) continue;
QPointF pp = pins[j]->scenePos();
if ((cp - pp).manhattanLength() <= (grid_step / 2.)) {
//qDebug() << "found";
if (b->busType() == pins[j]->busType()) {
b->connections_[conns[c]] = pins[j];
if (!pins[j]->buses_.contains(b))
pins[j]->buses_ << b;
pins[j]->setState(BlockItemPin::Connected);
} else
pins[j]->setState(BlockItemPin::Reject);
break;
}
}
}
}
//qDebug() << pins.size() << buses.size();
}
void BlockView::zoom(double factor) {
if (!is_nav_anim || (nav_anim.state() != QPropertyAnimation::Running))
nav_target = _nav();
QRectF r = nav_target;
QPoint mp;
if (underMouse()) mp = mapFromGlobal(QCursor::pos());
else mp = QPoint(viewport()->width() / 2, viewport()->height() / 2);
double cx = double(mp.x()) / viewport()->width(), cy = double(mp.y()) / viewport()->height();
double pw = r.width(), ph = r.height();
r.setWidth(r.width() / factor);
r.setHeight(r.height() / factor);
r.translate(cx * (pw - r.width()), cy * (ph - r.height()));
animateNav(r);
}
void BlockView::zoomReset() {
cur_scl = qSqrt(transform().determinant());
zoom(prev_app_scale / cur_scl);
}
void BlockView::copyToClipboard() {
QList<BlockItem*> bll = selectedBlocks();
QList<QGraphicsItem*> del = selectedDecors();
//qDebug() << "copy" << bll.size() << del.size();
if (bll.isEmpty() && del.isEmpty()) return;
QList<BlockBusItem*> bul = internalBuses(bll);
QByteArray ba;
QDataStream s(&ba, QIODevice::ReadWrite);
s << uint(0x89abcdef) << bll << bul << del;
QMimeData * mime = new QMimeData();
mime->setData(_BlockView_Mime_, ba);
QApplication::clipboard()->setMimeData(mime);
}
void BlockView::pasteFromClipboard() {
const QMimeData * mime = QApplication::clipboard()->mimeData();
if (!mime) return;
if (!mime->hasFormat(_BlockView_Mime_)) return;
QByteArray ba = mime->data(_BlockView_Mime_);
//qDebug() << "paste" << ba.size();
if (ba.size() < 4) return;
QList<BlockItem*> bll;
QList<BlockBusItem*> bul;
QList<QGraphicsItem*> del, gl;
uint hdr = 0;
QDataStream s(ba);
s >> hdr;
if (hdr != 0x89abcdef) return;
s >> bll >> bul >> del;
int all = bll.size() + bul.size() + del.size();
if (all == 0) return;
QRectF br;
foreach (BlockItem * b, bll) {
br |= b->boundingRect().translated(b->pos());
gl << b;
}
foreach (BlockBusItem * b, bul)
gl << b;
foreach (QGraphicsItem * b, del)
br |= b->boundingRect().translated(b->pos());
gl << del;
QPointF copy_dp;
if (underMouse()) copy_dp = mapToScene(mapFromGlobal(QCursor::pos()));
else copy_dp = mapToScene(rect().center());
copy_dp -= br.center();
copy_dp = quantize(copy_dp, grid_step);
ae_enabled = false;
if (!bll.isEmpty()) copyBlocks(bll, copy_dp);
if (!bul.isEmpty()) copyBuses(bul, copy_dp);
foreach (QGraphicsItem * i, del)
i->setPos(i->pos() + copy_dp);
addItems(del);
ae_enabled = true;
emitActionEvent(BlockItemBase::Paste, gl);
}
void BlockView::selectNone() {
QList<QGraphicsItem*> gi = scene_->items();
foreach (QGraphicsItem * i, gi)
i->setSelected(false);
}
void BlockView::selectAll() {
QList<QGraphicsItem*> gi = scene_->items();
foreach (QGraphicsItem * i, gi)
if (i->flags().testFlag(QGraphicsItem::ItemIsSelectable))
i->setSelected(true);
}
void BlockView::removeSelected() {
QList<QGraphicsItem*> gi = scene_->selectedItems(), ai;
blockSignals(true);
QList<BlockBusItem * > sbuses = buses(), dbuses, wbuses = wrongConnectedBuses();
//foreach (BlockBusItem * i, wbuses)
// sbuses.removeOne(i);
foreach (BlockBusItem * i, sbuses)
if (i->connectedBlocks().isEmpty())
dbuses << i;
foreach (QGraphicsItem * i, gi) {
if (i->data(1006) == "item")
ai << qgraphicsitem_cast<QGraphicsItem*>(i);
if ((i->data(1006) == "item") || (i->data(1005) == "connection") || (i->data(1009) == "decor")) {
scene_->sendEvent(i, new QGraphicsSceneEvent(QEvent::Close));
delete i;
}
}
reconnectAll();
foreach (BlockBusItem * i, sbuses)
if (i->connectedBlocks().isEmpty())
if (!dbuses.contains(i))
delete i;
blockSignals(false);
foreach (QGraphicsItem * i, ai)
emit blockRemoved((BlockItem*)i);
emitActionEvent(BlockItemBase::BlockRemove, ai);
}
void BlockView::removeAll() {
last_multiconnect_pl.clear();
QList<QGraphicsItem*> gi = scene_->items(), ai;
blockSignals(true);
foreach (QGraphicsItem * i, gi) {
if (i->data(1006) == "item")
ai << qgraphicsitem_cast<QGraphicsItem*>(i);
if ((i->data(1006) == "item") || (i->data(1005) == "connection") || (i->data(1009) == "decor")) {
if ((i != &sel_rect) && (i != &tmp_bus) && (i->parentItem() == 0) && !(i->data(1008).toBool())) {
//qDebug() << "delete" << i->data(1004);
scene_->sendEvent(i, new QGraphicsSceneEvent(QEvent::Close));
delete i;
}
}
}
blockSignals(false);
foreach (QGraphicsItem * i, ai)
emit blockRemoved((BlockItem*)i);
}

View File

@@ -0,0 +1,269 @@
#ifndef BLOCKVIEW_H
#define BLOCKVIEW_H
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QPainter>
#include <QPixmap>
#include <QMouseEvent>
#include <QDebug>
#include <QTime>
#include <QPropertyAnimation>
#include "blockviewwavetrace.h"
#include "blockbusitem.h"
/// data:
/// 1002 - flag for move parent (true)
/// 1003 - flag for visualize selection (true)
/// 1004 - BlockItemPin ("pin")
/// 1005 - BlockBusItem ("connection")
/// 1006 - BlockItem ("item")
/// 1007 - BlockItem selection ("item_selection")
/// 1008 - item is NOT decor, ignore for function decors() (true)
/// 1009 - item is scene decor ("decor")
/// 1010 - BlockItem decor (src text for QGraphicsSimpleTextItem)
/// 1011 - item is BlockItem decor ("decor")
/// 1100 - flag for correct move (true)
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
Q_DECLARE_METATYPE(BlockItem*)
Q_DECLARE_METATYPE(BlockItemPin*)
Q_DECLARE_METATYPE(BlockBusItem*)
class BlockView: public QGraphicsView
{
Q_OBJECT
Q_ENUMS(SelectionMode)
Q_PROPERTY(bool gridVisible READ isGridVisible WRITE setGridVisible)
Q_PROPERTY(bool snapToGrid READ isSnapToGrid WRITE setSnapToGrid)
Q_PROPERTY(QPen gridPen READ gridPen WRITE setGridPen)
Q_PROPERTY(double gridStep READ gridStep WRITE setGridStep)
Q_PROPERTY(double gridPointsWidth READ gridPointsWidth WRITE setGridPointsWidth)
Q_PROPERTY(SelectionMode selectionMode READ selectionMode WRITE setSelectionMode)
Q_PROPERTY(bool postMoveConnect READ isPostMoveConnectEnabled WRITE setPostMoveConnectEnabled)
Q_PROPERTY(bool connectByMouse READ isConnectByMouseEnabled WRITE setConnectByMouseEnabled)
Q_PROPERTY(bool navigationEnabled READ isNavigationEnabled WRITE setNavigationEnabled)
Q_PROPERTY(bool navigateAnimationEnabled READ isNavigateAnimationEnabled WRITE setNavigateAnimationEnabled)
Q_PROPERTY(bool blockAnimationEnabled READ isBlockAnimationEnabled WRITE setBlockAnimationEnabled)
Q_PROPERTY(bool traceConsiderBuses READ isTraceConsiderBuses WRITE setTraceConsiderBuses)
Q_PROPERTY(bool pinMulticonnect READ isPinMulticonnectEnabled WRITE setPinMulticonnectEnabled)
Q_PROPERTY(bool miniMap READ isMiniMapEnabled WRITE setMiniMapEnabled)
Q_PROPERTY(bool zoomWheelOnly READ isZoomWheelOnly WRITE setZoomWheelOnly)
Q_PROPERTY(double _thumb READ _thumb WRITE _setThumb DESIGNABLE false SCRIPTABLE false)
Q_PROPERTY(QRectF _nav READ _nav WRITE _setNav DESIGNABLE false SCRIPTABLE false)
public:
BlockView(QWidget * parent = 0);
BlockView(QGraphicsScene * scene, QWidget * parent = 0);
~BlockView();
enum SelectionMode {
NoSelection,
SingleSelection,
MultiSelection
};
QPen gridPen() const {return grid_pen;}
bool isGridVisible() const {return grid_visible;}
bool isSnapToGrid() const {return grid_snap;}
bool isPostMoveConnectEnabled() const {return pm_connect;}
bool isNavigationEnabled() const {return navigation;}
bool isNavigateAnimationEnabled() const {return is_nav_anim;}
bool isBlockAnimationEnabled() const {return is_block_anim;}
bool isConnectByMouseEnabled() const {return m_connect;}
bool isTraceConsiderBuses() const {return m_trace_with_buses;}
bool isPinMulticonnectEnabled() const {return m_pin_mc;}
bool isMiniMapEnabled() const {return minimap;}
bool isZoomWheelOnly() const {return wheel_zoom;}
double gridStep() const {return grid_step;}
double gridPointsWidth() const {return grid_points;}
SelectionMode selectionMode() const {return smode;}
void setSelectionMode(SelectionMode mode) {smode = mode;}
void addItems(QList<QGraphicsItem * > items) {foreach (QGraphicsItem * i, items) addItem(i);}
QList<BlockBusItem * > buses() const;
QList<BlockBusItem * > wrongConnectedBuses() const;
QList<BlockItem * > blocks() const;
QList<QGraphicsItem * > decors() const;
BlockBusItem * connectionBus(BlockItem * b0, BlockItem * b1) const;
QList<BlockBusItem * > connectionBuses(BlockItem * b0, BlockItem * b1) const;
bool connectPins(BlockItemPin * p0, BlockItemPin * p1);
QList<BlockItem * > selectedBlocks() const;
QList<QGraphicsItem * > selectedDecors() const;
void setTransform(const QTransform & matrix, bool combine = false);
void centerOn(const QPointF & pos);
void centerOn(qreal x, qreal y);
void centerOn(const QGraphicsItem * item);
void fitInView(const QRectF & rect, Qt::AspectRatioMode aspectRatioMode = Qt::IgnoreAspectRatio);
void fitInView(qreal x, qreal y, qreal w, qreal h, Qt::AspectRatioMode aspectRatioMode = Qt::IgnoreAspectRatio);
void fitInView(const QGraphicsItem * item, Qt::AspectRatioMode aspectRatioMode = Qt::IgnoreAspectRatio);
void fitInView();
QRectF itemsBoundingRect() const;
protected:
void _init();
void _updateBack();
bool event(QEvent * e);
bool eventFilter(QObject * o, QEvent * e);
void stopTimer(int & tid);
void restartTimer(int & tid, int msecs);
void timerEvent(QTimerEvent * e);
void wheelEvent(QWheelEvent * e);
void mousePressEvent(QMouseEvent * event);
void mouseReleaseEvent(QMouseEvent * event);
void mouseMoveEvent(QMouseEvent * event);
void mouseDoubleClickEvent(QMouseEvent * event);
void keyPressEvent(QKeyEvent * event);
void keyReleaseEvent(QKeyEvent * e);
void resizeEvent(QResizeEvent * event);
void scrollContentsBy(int dx, int dy);
void drawBackground(QPainter * painter, const QRectF & rect);
void drawThumb();
void drawSceneThumb();
void thumbHide();
void thumbShow();
void restoreSelState();
void saveSelState();
void saveBusesState();
void restoreBusesState();
void applySelRect(QGraphicsSceneMouseEvent * me);
void applyGridStep();
void trace(QPointF scene_pos_from, QPointF scene_pos_to, BlockBusItem * bus, bool primary = true);
void clearBusStates();
void matchBus();
bool connectTmpToBus(BlockBusItem* bus);
void markPins(int bus_type);
void unmarkPins(bool to_normal = false);
void hoverAcceptedPin(BlockItemPin * pin, bool hover);
void unhoverPins(BlockItemPin * excl_pin = 0);
void simplifyBuses();
void moveBuses(const QList<QGraphicsItem * > & items, QPointF dp);
QList<BlockBusItem * > internalBuses(const QList<BlockItem * > & items);
QList<BlockItemPin * > nearPins(BlockItemPin * pin, Qt::KeyboardModifiers km);
BlockItemPin * getPin(const QList<QGraphicsItem * > & list) const;
void highlightNearPins(BlockItemPin * pin, Qt::KeyboardModifiers km);
void hideTmpBuses(bool clear = true);
double _thumb() const {return _talpha;}
QRectF _nav() const;
void animateNav(QRectF d, double scl = 0.);
void scrollFromThumb();
void deleteCopyTemp();
void emitActionEvent(BlockItemBase::Action action, QList<QGraphicsItem * > items);
void setGhost(BlockItem * item);
void clearGhost();
BlockItem * ghost() const {return ghost_;}
virtual void loadBus(BlockBusItem * bus) {}
virtual void copyBlocks(QList<BlockItem * > items, QPointF offset) {}
virtual void copyBuses(QList<BlockBusItem * > items, QPointF offset) {}
virtual void newBusStarted(int bus_type) {}
QGraphicsScene * scene_;
QGraphicsRectItem sel_rect;
QGraphicsItem * mm_ci;
QList<QGraphicsItem * > sel_items;
QList<BlockItem * > copy_items;
QList<BlockItemPin * > last_multiconnect_pl;
QList<BlockBusItem * > copy_buses, tmp_buses;
BlockBusItem tmp_bus, * match_bus, * bus_from;
BlockItemPin * hpin;
BlockItem * ghost_;
BlockViewWavetrace wavetrace;
QPoint press_point, screen_point, thumb_press;
QPointF scene_point, trace_from, last_trace_from, trace_to, copy_dp;
QRect thumb_sr, thumb_vr;
QRectF nav_target, nav_rect;
QSizeF thumb_size;
QPen grid_pen;
SelectionMode smode;
QImage im_scene;
QWidget widget_thumb;
Qt::KeyboardModifiers mm_mods;
QPropertyAnimation thumb_anim, nav_anim;
int timer_thumb, thumb_hide_delay, thick;
bool mm_drag, new_bus, new_branch, moved, mm_cancel, iconnect, mm_copy, mm_thumb, ae_enabled, is_nav_anim, is_block_anim, move_bus_point;
bool grid_visible, grid_snap, pm_connect, navigation, m_connect, m_trace_with_buses, m_pin_mc, minimap, prev_tcb, wheel_zoom;
bool nav_prev_aa, nav_prev_imaa, nav_prev_grid;
double grid_step, grid_points, cur_scl, _talpha, thumb_scl;
double prev_app_scale;
protected slots:
void getPinMC(bool * v) {if (v) *v = m_pin_mc;}
void adjustThumb();
void newBranch(BlockBusItem * item);
void newBranchTrace(BlockBusItem * item, QPointF to);
void newBranchAccept(BlockBusItem * item);
void newBranchCancel();
void removedBus(QObject * o);
void removedBlock(QObject * o);
void removeJunk();
void sceneSelectionChanged();
void updateNavRect();
void scrolled();
void _setThumb(double v);
void _setNav(QRectF v);
void _navFinished();
void startBusPointMove(int bus_type);
void endBusPointMove();
void pinHoverInOut(BlockItemPin * pin);
void checkPaste(bool queued = false);
public slots:
void setGridPen(const QPen & pen) {grid_pen = pen; _updateBack();}
void setGridVisible(bool yes) {grid_visible = yes; _updateBack();}
void setSnapToGrid(bool yes) {grid_snap = yes;}
void setGridStep(double step) {grid_step = step; applyGridStep(); _updateBack();}
void setGridPointsWidth(double width_) {grid_points = width_; _updateBack();}
void setPostMoveConnectEnabled(bool on) {pm_connect = on;}
void setNavigationEnabled(bool on) {navigation = on;}
void setNavigateAnimationEnabled(bool on) {is_nav_anim = on;}
void setBlockAnimationEnabled(bool on) {is_block_anim = on;}
void setConnectByMouseEnabled(bool on) {m_connect = on;}
void setTraceConsiderBuses(bool on) {m_trace_with_buses = on;}
void setPinMulticonnectEnabled(bool on) {m_pin_mc = on;}
void setMiniMapEnabled(bool on) {minimap = on;}
void setZoomWheelOnly(bool on) {wheel_zoom = on;}
void zoom(double factor);
void zoomIn() {zoom(1.2);}
void zoomOut() {zoom(1. / 1.2);}
void zoomReset();
void copyToClipboard();
void pasteFromClipboard();
void reconnectAll();
void selectNone();
void selectAll();
void removeSelected();
void removeAll();
void clearSelection();
void addItem(QGraphicsItem * item, bool emit_action = true);
signals:
void blockDoubleClicked(BlockItem * );
void blockHoverEnter(BlockItem * );
void blockHoverLeave(BlockItem * );
void busDoubleClicked(BlockBusItem * );
void schemeAction(BlockItemBase::Action action, QList<QGraphicsItem * > items);
void blockRemoved(BlockItem * item);
void connectionsChanged();
void copyEnabledChanged(bool);
void pasteEnabledChanged(bool);
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // BLOCKVIEW_H

View File

@@ -0,0 +1,202 @@
#include "blockviewwavetrace.h"
#include <QTime>
BlockViewWavetrace::BlockViewWavetrace(int width, int height) {
max_steps = 512;
resize(width, height);
setPreferredDirection(BlockViewWavetrace::Horizontal);
}
void BlockViewWavetrace::resize(int width, int height) {
wid = width;
hei = height;
if (field.size() != wid)
field.resize(wid);
for (int i = 0; i < wid; ++i) {
if (field[i].size() != hei) {
field[i].resize(hei);
field[i].fill(-1);
}
}
}
void BlockViewWavetrace::fill(short val) {
QTime tm; tm.restart();
for (int i = 0; i < wid; ++i) {
if (i == 0)
field[i].fill(val);
else
memcpy(field[i].data(), field[0].constData(), hei * sizeof(field[0][0]));
}
}
void BlockViewWavetrace::fill(const QRect & rect, short val) {
for (int i = rect.left(); i <= rect.right(); ++i)
for (int j = rect.top(); j <= rect.bottom(); ++j)
field[i][j] = val;
}
bool BlockViewWavetrace::trace(const QPoint & start, const QPoint & finish) {
st = start;
fn = finish;
if (dir_ == NoTrace) return true;
//qDebug() << "trace" << start << finish;
//return true;
int cx, cy;
short cl = 0, empty = (short)BlockViewWavetrace::Empty;
QRect frect(0, 0, wid - 1, hei - 1);
QVector<QPoint> cpnts, npnts;
fill(st, cl);
cpnts.push_back(st);
if (field[fn.x()][fn.y()] == (short)BlockViewWavetrace::Blocked)
return false;
while (cpnts.size() > 0) {
npnts.clear();
cl++;
if (cl >= max_steps) return false;
for (int i = 0; i < cpnts.size(); ++i) {
if (cpnts[i] == fn) {
return true;
}
cx = cpnts[i].x() - 1;
cy = cpnts[i].y();
if (frect.contains(cx, cy)) {
if (field[cx][cy] == empty) {
npnts.push_back(QPoint(cx, cy));
fill(cx, cy, cl);
}
}
cx = cpnts[i].x() + 1;
if (frect.contains(cx, cy)) {
if (field[cx][cy] == empty) {
npnts.push_back(QPoint(cx, cy));
fill(cx, cy, cl);
}
}
cx = cpnts[i].x();
cy = cpnts[i].y() - 1;
if (frect.contains(cx, cy)) {
if (field[cx][cy] == empty) {
npnts.push_back(QPoint(cx, cy));
fill(cx, cy, cl);
}
}
cy = cpnts[i].y() + 1;
if (frect.contains(cx, cy)) {
if (field[cx][cy] == empty) {
npnts.push_back(QPoint(cx, cy));
fill(cx, cy, cl);
}
}
}
cpnts = npnts;
//qDebug() << cl << ": " << cpnts.size();
}
return false;
}
void BlockViewWavetrace::gatherPath() {
path_.clear();
path_.push_back(fn);
if (dir_ == NoTrace) {
path_.push_front(st);
return;
}
int cx, cy;
int pa = -1, ca = -1;
bool first = true;
short cl = field[fn.x()][fn.y()];
QRect frect(0, 0, wid, hei);
QPoint cpnt = fn;
//cout << "start from " << cl << endl;
while (cl > 0) {
cl--;
pa = ca;
int dir = 0;
cx = cpnt.x() + dps[dir].x();
cy = cpnt.y() + dps[dir].y();
dir++;
if (frect.contains(cx, cy)) {
if (field[cx][cy] == cl) {
ca = QLineF(QPointF(cx, cy), cpnt).angle();
if (ca != pa && !first)
path_.push_front(cpnt);
cpnt = QPoint(cx, cy);
first = false;
continue;
}
}
cx = cpnt.x() + dps[dir].x();
cy = cpnt.y() + dps[dir].y();
dir++;
if (frect.contains(cx, cy)) {
if (field[cx][cy] == cl) {
ca = QLineF(QPointF(cx, cy), cpnt).angle();
if (ca != pa && !first)
path_.push_front(cpnt);
cpnt = QPoint(cx, cy);
first = false;
continue;
}
}
cx = cpnt.x() + dps[dir].x();
cy = cpnt.y() + dps[dir].y();
dir++;
if (frect.contains(cx, cy)) {
if (field[cx][cy] == cl) {
ca = QLineF(QPointF(cx, cy), cpnt).angle();
if (ca != pa && !first)
path_.push_front(cpnt);
cpnt = QPoint(cx, cy);
first = false;
continue;
}
}
cx = cpnt.x() + dps[dir].x();
cy = cpnt.y() + dps[dir].y();
if (frect.contains(cx, cy)) {
if (field[cx][cy] == cl) {
ca = QLineF(QPointF(cx, cy), cpnt).angle();
if (ca != pa && !first)
path_.push_front(cpnt);
cpnt = QPoint(cx, cy);
first = false;
continue;
}
}
}
path_.push_front(st);
//cout << path_.size() << endl;
}
void BlockViewWavetrace::setPreferredDirection(BlockViewWavetrace::Direction dir) {
dir_ = dir;
if (dir == BlockViewWavetrace::Horizontal) {
dps[0] = QPoint(0, -1);
dps[1] = QPoint(0, 1);
dps[2] = QPoint(-1, 0);
dps[3] = QPoint(1, 0);
}
if (dir == BlockViewWavetrace::Vertical) {
dps[2] = QPoint(0, -1);
dps[3] = QPoint(0, 1);
dps[0] = QPoint(-1, 0);
dps[1] = QPoint(1, 0);
}
}
const QVector<QPoint> & BlockViewWavetrace::path() const {
/*path_.resize(3);
path_[0] = st;
path_[1] = (st + fn) / 2;
path_[2] = fn;*/
return path_;
}

View File

@@ -0,0 +1,43 @@
#ifndef BLOCKVIEWWAVETRACE_H
#define BLOCKVIEWWAVETRACE_H
#include "blockitem.h"
class BlockViewWavetrace {
public:
BlockViewWavetrace(int width = 1, int height = 1);
enum CellState {Empty = -1, Blocked = -2};
enum Direction {NoTrace, Horizontal, Vertical};
int width() const {return wid;}
int height() const {return hei;}
void resize(int width, int height);
void resize(const QSize & sz) {resize(sz.width(), sz.height());}
void fill(short val = -1);
void fill(const QRect & rect, short val = -1);
void fill(const QPoint & point, short val = -1) {field[point.x()][point.y()] = val;}
void fill(int px, int py, short val = -1) {field[px][py] = val;}
void fill(BlockViewWavetrace::CellState val = Empty) {fill((short)val);}
void fill(const QRect & rect, BlockViewWavetrace::CellState val = Empty) {fill(rect, (short)val);}
void fill(const QPoint & point, BlockViewWavetrace::CellState val = Empty) {fill(point, (short)val);}
void fill(int px, int py, BlockViewWavetrace::CellState val = Empty) {fill(px, py, (short)val);}
void clear() {fill(-1);}
bool trace(const QPoint & start, const QPoint & finish);
Direction preferredDirection() const {return dir_;}
void setPreferredDirection(Direction dir);
void setMaximumSteps(int steps) {max_steps = steps;}
int maximumSteps() const {return max_steps;}
void gatherPath();
const QVector<QPoint> & path() const;
private:
int wid, hei, max_steps;
Direction dir_;
QVector<QVector<short> > field;
QVector<QPoint> path_;
QPoint dps[4], st, fn;
};
#endif // BLOCKVIEWWAVETRACE_H

View File

@@ -0,0 +1,904 @@
#include "drawtools.h"
#include "ui_drawtools.h"
#include "alignedtextitem.h"
#include <QGraphicsLineItem>
#include <QLineEdit>
#include <QLabel>
#include <QMouseEvent>
#include <QFileDialog>
#include <QImageReader>
#include <QDialogButtonBox>
#include <QDebug>
_DTSizeItem::_DTSizeItem(): QGraphicsObject() {
cur_item = 0;
grid = 10.;
in_process = can_drag = false;
setData(1008, true);
for (int i = 0; i < 8; ++i) {
//qDebug() << &(rects[i]);
rects[i].setData(1008, true);
rects[i].setFlag(QGraphicsItem::ItemIgnoresTransformations);
rects[i].setZValue(10.);
rects[i].setAcceptHoverEvents(true);
rects[i].setRect(-5, -5, 10, 10);
rects[i].setPen(QPen(Qt::darkBlue));
rects[i].setBrush(QBrush(QColor(64, 64, 255, 128)));
//rects[i].setData(1100, true);
}
}
_DTSizeItem::~_DTSizeItem() {
assignObject(0);
//qDebug() << "!!!";
}
void _DTSizeItem::assignObject(QGraphicsItem * item) {
if (cur_item)
if (qgraphicsitem_cast<QGraphicsItem*>(cur_item))
cur_item->removeSceneEventFilter(this);
cur_item = item;
if (!cur_item) {
for (int i = 0; i < 8; ++i) {
rects[i].hide();
rects[i].setParentItem(0);
rects[i].removeSceneEventFilter(this);
}
return;
}
if (item)
if (item->scene())
if (!item->scene()->views().isEmpty())
grid = ((BlockView*)(item->scene()->views()[0]))->gridStep();
QGraphicsRectItem * irect = qgraphicsitem_cast<QGraphicsRectItem*>(cur_item);
QGraphicsEllipseItem * iell = qgraphicsitem_cast<QGraphicsEllipseItem*>(cur_item);
QGraphicsLineItem * iline = qgraphicsitem_cast<QGraphicsLineItem*>(cur_item);
if (irect || iell || iline) {
resizeHandles();
is_line = qgraphicsitem_cast<QGraphicsLineItem*>(item);
for (int i = 0; i < (is_line ? 2 : 8); ++i) {
rects[i].setParentItem(item);
rects[i].installSceneEventFilter(this);
rects[i].show();
}
}
item->installSceneEventFilter(this);
moveRects();
}
void _DTSizeItem::moveRects() {
if (!cur_item) return;
QRectF rect = itemRect(cur_item);
QPointF tl = rect.topLeft(), tr = rect.topRight(), bl = rect.bottomLeft(), br = rect.bottomRight();
if (is_line) {
rects[0].setPos(tl); rects[0].setData(2001, int(Qt::SizeAllCursor));
rects[1].setPos(br); rects[1].setData(2001, int(Qt::SizeAllCursor));
} else {
rects[0].setPos(tl); rects[0].setData(2001, int(Qt::SizeFDiagCursor));
rects[1].setPos((tl + tr) / 2.); rects[1].setData(2001, int(Qt::SizeVerCursor));
rects[2].setPos(tr); rects[2].setData(2001, int(Qt::SizeBDiagCursor));
rects[3].setPos((tr + br) / 2.); rects[3].setData(2001, int(Qt::SizeHorCursor));
rects[4].setPos(br); rects[4].setData(2001, int(Qt::SizeFDiagCursor));
rects[5].setPos((br + bl) / 2.); rects[5].setData(2001, int(Qt::SizeVerCursor));
rects[6].setPos(bl); rects[6].setData(2001, int(Qt::SizeBDiagCursor));
rects[7].setPos((bl + tl) / 2.); rects[7].setData(2001, int(Qt::SizeHorCursor));
}
}
void _DTSizeItem::applyRect() {
if (!cur_item) return;
QGraphicsRectItem * irect = qgraphicsitem_cast<QGraphicsRectItem*>(cur_item);
QGraphicsEllipseItem * iell = qgraphicsitem_cast<QGraphicsEllipseItem*>(cur_item);
QGraphicsLineItem * iline = qgraphicsitem_cast<QGraphicsLineItem*>(cur_item);
if (irect)
irect->setRect(nrect);
if (iell)
iell->setRect(nrect);
if (iline)
iline->setLine(QLineF(nrect.topLeft(), nrect.bottomRight()));
}
void _DTSizeItem::doubleClick() {
QGraphicsSimpleTextItem * itext = qgraphicsitem_cast<QGraphicsSimpleTextItem*>(cur_item);
AlignedTextItem * iatext = qgraphicsitem_cast<AlignedTextItem*>(cur_item);
QGraphicsPixmapItem * ipixmap = qgraphicsitem_cast<QGraphicsPixmapItem*>(cur_item);
if (itext || iatext) {
QMetaObject::invokeMethod(this, "textEditRequest", Qt::QueuedConnection);
}
if (ipixmap) {
QMetaObject::invokeMethod(this, "pixmapEditRequest", Qt::QueuedConnection);
}
}
void _DTSizeItem::resizeHandles() {
double sz = QApplication::fontMetrics().size(0, "0").height() / 3.;
QRectF r(-sz, -sz, sz*2, sz*2);
for (int i = 0; i < 8; ++i)
rects[i].setRect(r);
}
QRectF _DTSizeItem::itemRect(const QGraphicsItem * item) const {
if (!cur_item) return QRectF();
QGraphicsRectItem * irect = qgraphicsitem_cast<QGraphicsRectItem*>(cur_item);
QGraphicsEllipseItem * iell = qgraphicsitem_cast<QGraphicsEllipseItem*>(cur_item);
QGraphicsLineItem * iline = qgraphicsitem_cast<QGraphicsLineItem*>(cur_item);
if (irect)
return irect->rect();
if (iell)
return iell->rect();
if (iline)
return QRectF(iline->line().p1(), iline->line().p2());
return QRectF();
}
QRectF _DTSizeItem::boundingRect() const {
QRectF ret = rects[0].boundingRect().translated(rects[0].pos());
for (int i = 1; i < 8; ++i)
ret |= rects[i].boundingRect().translated(rects[i].pos());
return ret;
}
bool _DTSizeItem::sceneEventFilter(QGraphicsItem * watched, QEvent * event) {
QGraphicsSceneMouseEvent * me = (QGraphicsSceneMouseEvent * )event;
if (watched == cur_item) {
if (event->type() == QEvent::Close) {
assignObject(0);
return true;
}
if (event->type() == QEvent::GraphicsSceneMouseDoubleClick) {
doubleClick();
return true;
}
return QGraphicsItem::sceneEventFilter(watched, event);
}
if (!cur_item)
return QGraphicsItem::sceneEventFilter(watched, event);
view_ = 0;
switch (event->type()) {
case QEvent::GraphicsSceneHoverEnter:
if (watched->scene()) if (!watched->scene()->views().isEmpty()) view_ = watched->scene()->views()[0];
if (view_) view_->setCursor(Qt::CursorShape(watched->data(2001).toInt()));
break;
case QEvent::GraphicsSceneHoverLeave:
if (watched->scene()) if (!watched->scene()->views().isEmpty()) view_ = watched->scene()->views()[0];
if (view_) view_->unsetCursor();
break;
case QEvent::GraphicsSceneMousePress:
can_drag = (me->buttons() == Qt::LeftButton);
if (in_process) {
nrect = cur_item->data(2000).toRectF();
applyRect();
moveRects();
}
in_process = false;
pp = quantize(me->scenePos(), grid);
cur_item->setData(2000, itemRect(cur_item));
return true;
case QEvent::GraphicsSceneMouseMove:
if (me->buttons().testFlag(Qt::LeftButton)) {
sp = quantize(me->scenePos(), grid);
if (pp != sp && can_drag) {
in_process = true;
nrect = itemRect(cur_item);
if (is_line) {
if (watched == &(rects[0])) nrect.setTopLeft(rects[0].pos() + (sp - pp));
if (watched == &(rects[1])) nrect.setBottomRight(rects[1].pos() + (sp - pp));
} else {
if (watched == &(rects[0])) nrect.setTopLeft(rects[0].pos() + (sp - pp));
if (watched == &(rects[1])) nrect.setTop(rects[1].pos().y() + (sp - pp).y());
if (watched == &(rects[2])) nrect.setTopRight(rects[2].pos() + (sp - pp));
if (watched == &(rects[3])) nrect.setRight(rects[3].pos().x() + (sp - pp).x());
if (watched == &(rects[4])) nrect.setBottomRight(rects[4].pos() + (sp - pp));
if (watched == &(rects[5])) nrect.setBottom(rects[5].pos().y() + (sp - pp).y());
if (watched == &(rects[6])) nrect.setBottomLeft(rects[6].pos() + (sp - pp));
if (watched == &(rects[7])) nrect.setLeft(rects[7].pos().x() + (sp - pp).x());
nrect = nrect.normalized();
}
pp = sp;
applyRect();
moveRects();
}
}
return true;
case QEvent::GraphicsSceneMouseRelease:
if (in_process)
emit sizeChanged();
in_process = false;
can_drag = false;
return true;
default: break;
}
return QGraphicsItem::sceneEventFilter(watched, event);
}
DrawTools::DrawTools(BlockView * parent): QObject(parent),
actions_Z_up(this), actions_Z_top(this), actions_Z_down(this), actions_Z_bottom(this) {
widget_props = new QWidget();
ui = new Ui::DrawTools();
ui->setupUi(widget_props);
ui->labelPen->setMinimumSize(preferredIconSize(1.5, widget_props));
ui->labelPen->setMaximumSize(ui->labelPen->minimumSize());
ui->labelBrush->setMinimumSize(ui->labelPen->minimumSize());
ui->labelBrush->setMaximumSize(ui->labelBrush->minimumSize());
widget_props->setEnabled(false);
int fh = qMax<int>(QApplication::fontMetrics().size(0, "0").height(), 22);
int thick = lineThickness();
QSize sz(fh * 2.5, fh);
QStringList styles;
styles << tr("NoPen") << tr("Solid") << tr("Dash")
<< tr("Dot") << tr("Dash-Dot") << tr("Dash-Dot-Dot");
ui->comboLineStyle->setIconSize(sz);
for (int i = 0; i < 6; i++) {
QPixmap pix(sz);
pix.fill();
QPainter p(&pix);
p.setPen(QPen(Qt::black, thick, (Qt::PenStyle)i));
p.drawLine(0, pix.height() / 2, pix.width(), pix.height() / 2);
p.end();
ui->comboLineStyle->addItem(QIcon(pix), styles[i]);
}
#ifdef Q_OS_MACOS
setAlignCompact(true);
#else
setAlignCompact(false);
#endif
menu_hor.addActions(QList<QAction*>() << ui->actionLeft << ui->actionHCenter << ui->actionRight);
menu_ver.addActions(QList<QAction*>() << ui->actionTop << ui->actionVCenter << ui->actionBottom);
ui->buttonAlignHor->setMenu(&menu_hor);
ui->buttonAlignVer->setMenu(&menu_ver);
new_type = -1;
new_item = cur_item = 0;
view_ = 0;
resize_enabled = true;
text_dlg.setWindowTitle(trUtf8("Edit text"));
text_dlg.setLayout(new QBoxLayout(QBoxLayout::TopToBottom));
QDialogButtonBox * bbox = new QDialogButtonBox(QDialogButtonBox::Save | QDialogButtonBox::Cancel);
connect(bbox, SIGNAL(accepted()), &text_dlg, SLOT(accept()));
connect(bbox, SIGNAL(rejected()), &text_dlg, SLOT(reject()));
text_dlg.layout()->addWidget(&text_edit);
text_dlg.layout()->addWidget(bbox);
actions_Z_up.setText(trUtf8("Bring\nforward")); actions_Z_up.setIcon(QIcon(":/icons/z-up.png")); actions_Z_up.setEnabled(false);
actions_Z_top.setText(trUtf8("Bring\nto front")); actions_Z_top.setIcon(QIcon(":/icons/z-top.png")); actions_Z_top.setEnabled(false);
actions_Z_down.setText(trUtf8("Send\nbackward")); actions_Z_down.setIcon(QIcon(":/icons/z-down.png")); actions_Z_down.setEnabled(false);
actions_Z_bottom.setText(trUtf8("Send\nto back")); actions_Z_bottom.setIcon(QIcon(":/icons/z-bottom.png")); actions_Z_bottom.setEnabled(false);
actions_add << newAction(trUtf8("Draw\nRectangle"), QIcon(":/icons/draw-rectangle.png"), 1)
<< newAction(trUtf8("Draw\nEllipse"), QIcon(":/icons/draw-ellipse.png"), 2)
<< newAction(trUtf8("Draw\nLine"), QIcon(":/icons/draw-line.png"), 4)
<< newAction(trUtf8("Draw\nText"), QIcon(":/icons/draw-text.png"), 0)
<< newAction(trUtf8("Draw\nImage"), QIcon(":/icons/view-preview.png"), 3);
buttons_align << ui->buttonAlignTL << ui->buttonAlignTC << ui->buttonAlignTR
<< ui->buttonAlignCL << ui->buttonAlignCC << ui->buttonAlignCR
<< ui->buttonAlignBL << ui->buttonAlignBC << ui->buttonAlignBR;
foreach (QAction * a, actions_add)
connect(a, SIGNAL(toggled(bool)), this, SLOT(toggleNewItem(bool)));
foreach (QToolButton * b, buttons_align)
connect(b, SIGNAL(clicked(bool)), this, SLOT(alignClicked()));
connect(ui->buttonImage, SIGNAL(clicked(bool)), this, SLOT(buttonImage_clicked()));
connect(ui->buttonImagePaste, SIGNAL(clicked(bool)), this, SLOT(buttonImagePaste_clicked()));
connect(ui->buttonFont, SIGNAL(clicked(bool)), this, SLOT(buttonFont_clicked()));
connect(ui->buttonTextEdit, SIGNAL(clicked(bool)), this, SLOT(buttonTextEdit_clicked()));
connect(ui->spinWidth, SIGNAL(valueChanged(double)), this, SLOT(propertyChanged()));
connect(ui->spinWidth, SIGNAL(editingFinished()), this, SLOT(changeFinished()));
connect(ui->spinHeight, SIGNAL(valueChanged(double)), this, SLOT(propertyChanged()));
connect(ui->spinHeight, SIGNAL(editingFinished()), this, SLOT(changeFinished()));
connect(ui->spinThick, SIGNAL(valueChanged(double)), this, SLOT(propertyChanged()));
connect(ui->spinThick, SIGNAL(editingFinished()), this, SLOT(changeFinished()));
connect(ui->spinScale, SIGNAL(valueChanged(double)), this, SLOT(propertyChanged()));
connect(ui->spinScale, SIGNAL(editingFinished()), this, SLOT(changeFinished()));
connect(ui->comboText, SIGNAL(editTextChanged(QString)), this, SLOT(propertyChanged()));
connect(ui->comboText->lineEdit(), SIGNAL(editingFinished()), this, SLOT(changeFinished()));
connect(ui->comboLineStyle, SIGNAL(currentIndexChanged(int)), this, SLOT(comboLineStyleChanged()));
connect(ui->colorButtonPen, SIGNAL(colorChanged(QColor)), this, SLOT(propertyChanged()));
connect(ui->colorButtonPen, SIGNAL(colorChanged(QColor)), this, SLOT(changeFinished()));
connect(ui->colorButtonBrush, SIGNAL(colorChanged(QColor)), this, SLOT(propertyChanged()));
connect(ui->colorButtonBrush, SIGNAL(colorChanged(QColor)), this, SLOT(changeFinished()));
connect(ui->actionTop, SIGNAL(triggered(bool)), this, SLOT(actionTop_triggered(bool)));
connect(ui->actionVCenter, SIGNAL(triggered(bool)), this, SLOT(actionVCenter_triggered(bool)));
connect(ui->actionBottom, SIGNAL(triggered(bool)), this, SLOT(actionBottom_triggered(bool)));
connect(ui->actionLeft, SIGNAL(triggered(bool)), this, SLOT(actionLeft_triggered(bool)));
connect(ui->actionHCenter, SIGNAL(triggered(bool)), this, SLOT(actionHCenter_triggered(bool)));
connect(ui->actionRight, SIGNAL(triggered(bool)), this, SLOT(actionRight_triggered(bool)));
connect(&font_dlg, SIGNAL(currentFontChanged(QFont)), this, SLOT(propertyChanged()));
connect(&size_item, SIGNAL(sizeChanged()), this, SLOT(sizeChanged()));
connect(&size_item, SIGNAL(textEditRequest()), this, SLOT(buttonTextEdit_clicked()));
connect(&size_item, SIGNAL(pixmapEditRequest()), this, SLOT(buttonImage_clicked()));
connect(&actions_Z_up, SIGNAL(triggered(bool)), this, SLOT(actionZ_triggered()));
connect(&actions_Z_top, SIGNAL(triggered(bool)), this, SLOT(actionZ_triggered()));
connect(&actions_Z_down, SIGNAL(triggered(bool)), this, SLOT(actionZ_triggered()));
connect(&actions_Z_bottom, SIGNAL(triggered(bool)), this, SLOT(actionZ_triggered()));
setBlockView(parent);
}
DrawTools::~DrawTools() {
size_item.assignObject(0);
//delete ui;
//delete widget_props;
}
void DrawTools::setBlockView(BlockView * v) {
if (view_) view_->viewport()->removeEventFilter(this);
disconnect(this, SLOT(selectionChanged()));
view_ = v;
if (!view_) return;
view_->addItem(&size_item);
view_->viewport()->installEventFilter(this);
connect(view_->scene(), SIGNAL(selectionChanged()), this, SLOT(selectionChanged()));
}
void DrawTools::setAlignCompact(bool yes) {
ui->widgetAlign2->setVisible(yes);
ui->widgetAlign9->setVisible(!yes);
}
bool DrawTools::eventFilter(QObject * o, QEvent * e) {
QMouseEvent * me = (QMouseEvent*)e;
QPointF sp;
if (e->type() == QEvent::FontChange || e->type() == QEvent::Polish)
ui->labelPen->setMinimumSize(preferredIconSize(1.5, widget_props));
if (e->type() == QEvent::MouseButtonPress || e->type() == QEvent::MouseMove)
sp = quantize(view_->mapToScene(me->pos()), view_->gridStep());
QRectF mr;
switch (e->type()) {
case QEvent::MouseButtonPress:
if (new_type < 0) break;
if (new_item) {
delete new_item;
new_item = 0;
if (!me->modifiers().testFlag(Qt::ControlModifier)) {
foreach (QAction * a, actions_add)
a->setChecked(false);
new_type = -1;
//view_->setCursor(Qt::ArrowCursor);
return true;
}
}
new_item = 0;
pp = sp;
switch (new_type) {
case 0:
new_item = new AlignedTextItem();
((AlignedTextItem*)new_item)->setText("Text");
((AlignedTextItem*)new_item)->setPos(sp);
break;
case 1:
new_item = new QGraphicsRectItem();
break;
case 2:
new_item = new QGraphicsEllipseItem();
break;
case 3:
new_item = new QGraphicsPixmapItem(QPixmap(":/icons/view-preview.png"));
((QGraphicsPixmapItem*)new_item)->setPos(sp - QPointF(new_item->boundingRect().width() / 2, new_item->boundingRect().height() / 2));
break;
case 4:
new_item = new QGraphicsLineItem(QLineF(sp, sp));
break;
};
if (new_item) {
if (new_type == 1 || new_type == 2)
((QAbstractGraphicsShapeItem*)new_item)->setBrush(Qt::white);
new_item->setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsMovable);
new_item->setData(1100, true);
emit itemCreated(new_item);
return true;
}
break;
case QEvent::MouseMove:
if (me->buttons().testFlag(Qt::LeftButton)) {
if (new_item) {
mr = new_item->mapRectFromScene(QRectF(pp, sp).normalized());
//mr = QRectF(pp, sp).normalized();
switch (new_type) {
case 0:
((AlignedTextItem*)new_item)->setPos(sp);
break;
case 1:
((QGraphicsRectItem*)new_item)->setRect(mr);
break;
case 2:
((QGraphicsEllipseItem*)new_item)->setRect(mr);
break;
case 3:
((QGraphicsPixmapItem*)new_item)->setPos(sp - QPointF(new_item->boundingRect().width() / 2, new_item->boundingRect().height() / 2));
break;
case 4:
((QGraphicsLineItem*)new_item)->setLine(QLineF(pp, sp));
break;
};
return true;
}
}
break;
case QEvent::MouseButtonRelease:
if (new_item) {
if (new_item->boundingRect().isEmpty())
delete new_item;
else {
emit itemAddConfirm(new_item);
if (view_) {
view_->selectNone();
new_item->setSelected(true);
}
}
new_item = 0;
if (!me->modifiers().testFlag(Qt::ControlModifier)) {
foreach (QAction * a, actions_add)
a->setChecked(false);
new_type = -1;
//view_->setCursor(Qt::ArrowCursor);
}
return true;
}
break;
default: break;
}
return QObject::eventFilter(o, e);
}
QComboBox * DrawTools::textEditCombo() const {
return ui->comboText;
}
/*
void DrawTools::changeEvent(QEvent * e) {
if (e->type() == QEvent::LanguageChange) {
ui->retranslateUi(this);
return;
}
QObject::changeEvent(e);
}
*/
QAction * DrawTools::newAction(const QString & text, const QIcon & icon, int type) {
QAction * ret = new QAction(icon, text, this);
ret->setCheckable(true);
ret->setData(type);
return ret;
}
void DrawTools::toggleNewItem(bool on) {
QAction * sa = (QAction * )sender();
foreach (QAction * a, actions_add)
if (a != sa)
a->setChecked(false);
if (!on) {
new_type = -1;
view_->unsetCursor();
return;
}
new_type = sa->data().toInt();
view_->setCursor(Qt::CrossCursor);
}
void DrawTools::alignClicked() {
QToolButton * sb = (QToolButton * )sender();
foreach (QToolButton * b, buttons_align)
if (b != sb)
b->setChecked(false);
sb->setChecked(true);
align = 0;
QString als = sb->objectName().right(2).toLower();
if (als[0] == 't') align |= Qt::AlignTop;
if (als[0] == 'c') align |= Qt::AlignVCenter;
if (als[0] == 'b') align |= Qt::AlignBottom;
if (als[1] == 'l') align |= Qt::AlignLeft;
if (als[1] == 'c') align |= Qt::AlignHCenter;
if (als[1] == 'r') align |= Qt::AlignRight;
propertyChanged();
}
void DrawTools::setPenBrushEnabled(bool pen, bool brush) {
ui->labelPen->setEnabled(pen);
ui->colorButtonPen->setEnabled(pen);
ui->labelBrush->setEnabled(brush);
ui->colorButtonBrush->setEnabled(brush);
}
void DrawTools::blockPropSignals(bool block_) {
ui->spinWidth->blockSignals(block_);
ui->spinHeight->blockSignals(block_);
ui->spinThick->blockSignals(block_);
ui->comboText->blockSignals(block_);
ui->comboLineStyle->blockSignals(block_);
ui->colorButtonPen->blockSignals(block_);
ui->colorButtonBrush->blockSignals(block_);
ui->actionTop->blockSignals(block_);
ui->actionVCenter->blockSignals(block_);
ui->actionBottom->blockSignals(block_);
ui->actionHCenter->blockSignals(block_);
ui->actionLeft->blockSignals(block_);
ui->actionRight->blockSignals(block_);
foreach (QToolButton * b, buttons_align)
b->blockSignals(block_);
}
void DrawTools::actionAlignTrigger(bool vert, Qt::AlignmentFlag value) {
blockPropSignals(true);
if (vert) foreach (QAction * a, menu_ver.actions()) a->setChecked(false);
else foreach (QAction * a, menu_hor.actions()) a->setChecked(false);
align = align & (vert ? Qt::AlignHorizontal_Mask : Qt::AlignVertical_Mask);
align |= value;
((QAction*)sender())->setChecked(true);
blockPropSignals(false);
propertyChanged();
}
void DrawTools::emitZAvailabe(QGraphicsItem * item) {
BlockView * view = 0;
if (item) if (item->scene()) if (!item->scene()->views().isEmpty()) view = qobject_cast<BlockView * >(item->scene()->views()[0]);
if (view == 0) {
moveZUpAvailable(false);
moveZDownAvailable(false);
return;
}
QList<QGraphicsItem * > dl;
if (item->parentItem() == 0) dl = view->decors();
else if (item->parentItem()->data(1006) == "item") dl = ((BlockItem*)(item->parentItem()))->decors_;
if (dl.size() <= 1) {
moveZUpAvailable(false);
moveZDownAvailable(false);
return;
}
int ind = dl.indexOf(item);
if (ind < 0) {
moveZUpAvailable(false);
moveZDownAvailable(false);
} else {
moveZUpAvailable(ind < dl.size() - 1);
moveZDownAvailable(ind > 0);
}
}
void DrawTools::selectionChanged() {
cur_item = 0;
size_item.assignObject(0);
if (!view_) {
emitZAvailabe();
return;
}
QList<QGraphicsItem * > sil = view_->scene()->selectedItems();
if (sil.size() != 1) {
emitZAvailabe();
widget_props->setEnabled(false);
return;
}
widget_props->setEnabled(true);
cur_item = sil[0];
if (!cur_item) {
emitZAvailabe();
return;
}
QGraphicsSimpleTextItem * itext = qgraphicsitem_cast<QGraphicsSimpleTextItem*>(cur_item);
AlignedTextItem * iatext = qgraphicsitem_cast<AlignedTextItem*>(cur_item);
QGraphicsPixmapItem * ipixmap = qgraphicsitem_cast<QGraphicsPixmapItem*>(cur_item);
QGraphicsRectItem * irect = qgraphicsitem_cast<QGraphicsRectItem*>(cur_item);
QGraphicsEllipseItem * iell = qgraphicsitem_cast<QGraphicsEllipseItem*>(cur_item);
QGraphicsLineItem * iline = qgraphicsitem_cast<QGraphicsLineItem*>(cur_item);
blockPropSignals(true);
if (itext) {
ui->stackedProperties->setCurrentIndex(0);
ui->comboText->setEditText(itext->text());
ui->colorButtonPen->setColor(itext->brush().color());
font_dlg.blockSignals(true);
font_dlg.setCurrentFont(itext->font());
font_dlg.blockSignals(false);
setPenBrushEnabled(true, false);
ui->widgetAlign2->setEnabled(false);
ui->widgetAlign9->setEnabled(false);
size_item.assignObject(itext);
} else if (iatext) {
ui->stackedProperties->setCurrentIndex(0);
ui->comboText->setEditText(iatext->text());
ui->colorButtonPen->setColor(iatext->brush().color());
font_dlg.blockSignals(true);
font_dlg.setCurrentFont(iatext->font());
font_dlg.blockSignals(false);
setPenBrushEnabled(true, false);
foreach (QAction * a, menu_hor.actions()) a->setChecked(false);
foreach (QAction * a, menu_ver.actions()) a->setChecked(false);
align = iatext->alignment();
QString als;
if (align.testFlag(Qt::AlignTop)) {als += "T"; ui->actionTop->setChecked(true);}
if (align.testFlag(Qt::AlignVCenter)) {als += "C"; ui->actionVCenter->setChecked(true);}
if (align.testFlag(Qt::AlignBottom)) {als += "B"; ui->actionBottom->setChecked(true);}
if (align.testFlag(Qt::AlignLeft)) {als += "L"; ui->actionLeft->setChecked(true);}
if (align.testFlag(Qt::AlignHCenter)) {als += "C"; ui->actionHCenter->setChecked(true);}
if (align.testFlag(Qt::AlignRight)) {als += "R"; ui->actionRight->setChecked(true);}
foreach (QToolButton * b, buttons_align)
b->setChecked(false);
foreach (QToolButton * b, buttons_align)
if (b->objectName().endsWith(als)) {
b->setChecked(true);
break;
}
ui->widgetAlign2->setEnabled(true);
ui->widgetAlign9->setEnabled(true);
size_item.assignObject(iatext);
} else if (ipixmap) {
ui->stackedProperties->setCurrentIndex(2);
ui->spinScale->setValue(sqrt(ipixmap->transform().determinant()));
setPenBrushEnabled(false, false);
size_item.assignObject(ipixmap);
} else if (irect || iell) {
ui->stackedProperties->setCurrentIndex(1);
QAbstractGraphicsShapeItem * ishape(0);
if (irect) {
ishape = irect;
ui->spinWidth->setValue(irect->rect().width());
ui->spinHeight->setValue(irect->rect().height());
}
if (iell) {
ishape = iell;
ui->spinWidth->setValue(iell->rect().width());
ui->spinHeight->setValue(iell->rect().height());
}
if (ishape) {
ui->colorButtonPen->setColor(ishape->pen().color());
ui->colorButtonBrush->setColor(ishape->brush().color());
ui->spinThick->setValue(ishape->pen().widthF());
ui->comboLineStyle->setCurrentIndex(qMin<int>((int)ishape->pen().style(), ui->comboLineStyle->count() - 1));
setPenBrushEnabled(true, true);
if (resize_enabled)
size_item.assignObject(ishape);
}
} else if (iline) {
ui->stackedProperties->setCurrentIndex(1);
ui->colorButtonPen->setColor(iline->pen().color());
ui->spinThick->setValue(iline->pen().widthF());
ui->comboLineStyle->setCurrentIndex(qMin<int>((int)iline->pen().style(), ui->comboLineStyle->count() - 1));
setPenBrushEnabled(true, false);
if (resize_enabled)
size_item.assignObject(iline);
} else {
ui->stackedProperties->setCurrentIndex(3);
widget_props->setEnabled(false);
}
emitZAvailabe(cur_item);
blockPropSignals(false);
}
void DrawTools::sizeChanged() {
blockPropSignals(true);
QGraphicsRectItem * irect = qgraphicsitem_cast<QGraphicsRectItem*>(cur_item);
QGraphicsEllipseItem * iell = qgraphicsitem_cast<QGraphicsEllipseItem*>(cur_item);
if (irect || iell) {
if (irect) {
ui->spinWidth->setValue(irect->rect().width());
ui->spinHeight->setValue(irect->rect().height());
}
if (iell) {
ui->spinWidth->setValue(iell->rect().width());
ui->spinHeight->setValue(iell->rect().height());
}
}
blockPropSignals(false);
changeFinished();
}
void DrawTools::propertyChanged() {
if (!cur_item) return;
QGraphicsSimpleTextItem * itext = qgraphicsitem_cast<QGraphicsSimpleTextItem*>(cur_item);
AlignedTextItem * iatext = qgraphicsitem_cast<AlignedTextItem*>(cur_item);
QGraphicsPixmapItem * ipixmap = qgraphicsitem_cast<QGraphicsPixmapItem*>(cur_item);
QGraphicsRectItem * irect = qgraphicsitem_cast<QGraphicsRectItem*>(cur_item);
QGraphicsEllipseItem * iell = qgraphicsitem_cast<QGraphicsEllipseItem*>(cur_item);
QGraphicsLineItem * iline = qgraphicsitem_cast<QGraphicsLineItem*>(cur_item);
if (itext) {
QRectF obr = itext->boundingRect();
itext->setFont(font_dlg.currentFont());
itext->setText(ui->comboText->currentText());
QRectF nbr = itext->boundingRect();
QSizeF ds = (obr.size() - nbr.size()) / 2.;
itext->setPos(itext->pos() + QPointF(ds.width(), ds.height()));
itext->setBrush(ui->colorButtonPen->color());
} else if (iatext) {
iatext->setFont(font_dlg.currentFont());
iatext->setText(ui->comboText->currentText());
iatext->setBrush(ui->colorButtonPen->color());
iatext->setAlignment(align);
} else if (ipixmap) {
QTransform t = ipixmap->transform();
double det = sqrt(t.determinant());
QSizeF os = ipixmap->boundingRect().size() * det;
if (det != 0.) t.scale(1. / det, 1. / det);
det = ui->spinScale->value();
t.scale(det, det);
ipixmap->setTransform(t);
QSizeF ns = ipixmap->boundingRect().size() * det;
QSizeF ds = (os - ns) / 2.;
ipixmap->setPos(ipixmap->pos() + QPointF(ds.width(), ds.height()));
} else if (irect || iell) {
QAbstractGraphicsShapeItem * ishape(0);
if (irect) {
ishape = irect;
irect->setRect(QRectF(irect->rect().topLeft(), QSizeF(ui->spinWidth->value(), ui->spinHeight->value())));
}
if (iell) {
ishape = iell;
iell->setRect(QRectF(iell->rect().topLeft(), QSizeF(ui->spinWidth->value(), ui->spinHeight->value())));
}
if (ishape) {
ishape->setPen(QPen(ui->colorButtonPen->color(), ui->spinThick->value(), (Qt::PenStyle)ui->comboLineStyle->currentIndex()));
ishape->setBrush(ui->colorButtonBrush->color());
if (resize_enabled)
size_item.assignObject(ishape);
}
} else if (iline) {
iline->setPen(QPen(ui->colorButtonPen->color(), ui->spinThick->value(), (Qt::PenStyle)ui->comboLineStyle->currentIndex()));
if (resize_enabled)
size_item.assignObject(iline);
}
}
void DrawTools::comboLineStyleChanged() {
if (!cur_item) return;
QGraphicsRectItem * irect = qgraphicsitem_cast<QGraphicsRectItem*>(cur_item);
QGraphicsEllipseItem * iell = qgraphicsitem_cast<QGraphicsEllipseItem*>(cur_item);
QGraphicsLineItem * iline = qgraphicsitem_cast<QGraphicsLineItem*>(cur_item);
if (irect || iell) {
QAbstractGraphicsShapeItem * ishape(0);
if (irect)
ishape = irect;
if (iell)
ishape = iell;
if (ishape) {
QPen p(ishape->pen());
p.setStyle((Qt::PenStyle)ui->comboLineStyle->currentIndex());
ishape->setPen(p);
changeFinished();
}
} else if (iline) {
QPen p(iline->pen());
p.setStyle((Qt::PenStyle)ui->comboLineStyle->currentIndex());
iline->setPen(p);
changeFinished();
}
}
void DrawTools::buttonImage_clicked() {
QGraphicsPixmapItem * pi = qgraphicsitem_cast<QGraphicsPixmapItem * >(cur_item);
if (!pi) return;
QList<QByteArray> sif(QImageReader::supportedImageFormats());
QString f;
foreach (const QByteArray & i, sif) {
if (!f.isEmpty()) f += " ";
f += "*.";
f += i;
}
QString ret = QFileDialog::getOpenFileName(0, trUtf8("Select image"), pi->data(1101).toString(), QString("Images(%1)").arg(f));
if (ret.isEmpty()) return;
QImage im(ret);
if (im.isNull()) return;
pi->setData(1101, ret);
QRectF obr = pi->boundingRect();
pi->setPixmap(QPixmap::fromImage(im));
QRectF nbr = pi->boundingRect();
QSizeF ds = (obr.size() - nbr.size()) / 2.;
pi->setPos(pi->pos() + QPointF(ds.width(), ds.height()));
changeFinished();
}
void DrawTools::buttonImagePaste_clicked() {
QGraphicsPixmapItem * pi = qgraphicsitem_cast<QGraphicsPixmapItem * >(cur_item);
if (!pi) return;
QPixmap pm = QApplication::clipboard()->pixmap();
if (pm.isNull()) return;
QRectF obr = pi->boundingRect();
pi->setPixmap(pm);
QRectF nbr = pi->boundingRect();
QSizeF ds = (obr.size() - nbr.size()) / 2.;
pi->setPos(pi->pos() + QPointF(ds.width(), ds.height()));
changeFinished();
}
void DrawTools::buttonFont_clicked() {
if (!cur_item) return;
QGraphicsSimpleTextItem * ti = qgraphicsitem_cast<QGraphicsSimpleTextItem * >(cur_item);
AlignedTextItem * ati = qgraphicsitem_cast<AlignedTextItem * >(cur_item);
if (!ti && !ati) return;
QFont font_prev;
if (ti) font_prev = ti->font();
if (ati) font_prev = ati->font();
font_dlg.blockSignals(true);
font_dlg.setCurrentFont(font_prev);
font_dlg.blockSignals(false);
if (font_dlg.exec() == QDialog::Rejected)
font_dlg.setCurrentFont(font_prev);
else
changeFinished();
}
void DrawTools::buttonTextEdit_clicked() {
text_dlg.setWindowIcon(QApplication::activeWindow()->windowIcon());
text_edit.setPlainText(ui->comboText->lineEdit()->text());
text_edit.selectAll();
text_edit.setFocus();
if (text_dlg.exec() == QDialog::Rejected)
return;
ui->comboText->lineEdit()->setText(text_edit.toPlainText());
propertyChanged();
changeFinished();
}
void DrawTools::actionZ_triggered() {
if (!cur_item) return;
if (cur_item->data(1009) == "decor") {
BlockView * view = 0;
if (cur_item) if (cur_item->scene()) if (!cur_item->scene()->views().isEmpty())
view = qobject_cast<BlockView * >(cur_item->scene()->views()[0]);
if (!view) return;
QGraphicsScene * scene = view->scene();
QList<QGraphicsItem*> dl = view->decors();
scene->blockSignals(true);
foreach (QGraphicsItem * d, dl) scene->removeItem(d);
int ind = dl.indexOf(cur_item);
dl.removeAt(ind);
if (sender() == &actions_Z_up) dl.insert(ind + 1, cur_item);
if (sender() == &actions_Z_top) dl.append(cur_item);
if (sender() == &actions_Z_down) dl.insert(ind - 1, cur_item);
if (sender() == &actions_Z_bottom) dl.prepend(cur_item);
foreach (QGraphicsItem * d, dl) scene->addItem(d);
scene->blockSignals(false);
}
if (cur_item->data(1011) == "decor") {
BlockItem * bi = qgraphicsitem_cast<BlockItem*>(cur_item->parentItem());
if (!bi) return;
QList<QGraphicsItem*> dl = bi->decors_;
foreach (QGraphicsItem * d, dl) d->setParentItem(0);
int ind = dl.indexOf(cur_item);
dl.removeAt(ind);
if (sender() == &actions_Z_up) dl.insert(ind + 1, cur_item);
if (sender() == &actions_Z_top) dl.append(cur_item);
if (sender() == &actions_Z_down) dl.insert(ind - 1, cur_item);
if (sender() == &actions_Z_bottom) dl.prepend(cur_item);
bi->decors_ = dl;
foreach (QGraphicsItem * d, dl) d->setParentItem(bi);
}
size_item.assignObject(cur_item);
emitZAvailabe(cur_item);
emit itemZChanged(cur_item);
}
void DrawTools::setResizeHandlesEnabled(bool on) {
resize_enabled = on;
if (!on) {
size_item.assignObject(0);
return;
}
if (cur_item && on)
propertyChanged();
}

View File

@@ -0,0 +1,132 @@
#ifndef DRAWTOOLS_H
#define DRAWTOOLS_H
#include <QObject>
#include <QAction>
#include <QFontDialog>
#include <QToolButton>
#include <QPlainTextEdit>
#include <QMenu>
#include "blockview.h"
class QComboBox;
class _DTSizeItem: public QGraphicsObject
{
Q_OBJECT
public:
_DTSizeItem();
~_DTSizeItem();
void assignObject(QGraphicsItem * item);
protected:
void moveRects();
void applyRect();
void doubleClick();
void resizeHandles();
QRectF itemRect(const QGraphicsItem * item) const;
QRectF boundingRect() const;
void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0) {}
bool sceneEventFilter(QGraphicsItem * watched, QEvent * event);
QGraphicsItem * cur_item;
QGraphicsView * view_;
QGraphicsRectItem rects[8];
QPointF pp, sp;
QRectF nrect;
qreal grid;
bool in_process, can_drag, is_line;
signals:
void sizeChanged();
void textEditRequest();
void pixmapEditRequest();
};
namespace Ui {
class DrawTools;
}
class DrawTools: public QObject
{
Q_OBJECT
Q_PROPERTY(bool resizeHandlesEnabled READ isResizeHandlesEnabled WRITE setResizeHandlesEnabled)
public:
explicit DrawTools(BlockView * parent = 0);
~DrawTools();
void setBlockView(BlockView * v);
void resetSizeTool() {size_item.assignObject(0);}
bool isResizeHandlesEnabled() const {return resize_enabled;}
void setAlignCompact(bool yes);
QComboBox * textEditCombo() const;
QList<QAction * > actionsForAdd() const {return actions_add;}
QList<QAction * > actionsForZ() const {return QList<QAction * >() << &actions_Z_bottom << &actions_Z_down << &actions_Z_up << &actions_Z_top;}
QWidget * propertyWidget() const {return widget_props;}
protected:
bool eventFilter(QObject * o, QEvent * e);
QAction * newAction(const QString & text, const QIcon & icon, int type);
void setPenBrushEnabled(bool pen, bool brush);
void blockPropSignals(bool block_);
void actionAlignTrigger(bool vert, Qt::AlignmentFlag value);
void emitZAvailabe(QGraphicsItem * item = 0);
QWidget * widget_props;
Ui::DrawTools * ui;
BlockView * view_;
QList<QAction * > actions_add;
mutable QAction actions_Z_up, actions_Z_top, actions_Z_down, actions_Z_bottom;
QList<QToolButton * > buttons_align;
QGraphicsItem * new_item, * cur_item;
QFontDialog font_dlg;
QPointF pp;
QDialog text_dlg;
QPlainTextEdit text_edit;
QMenu menu_hor, menu_ver;
_DTSizeItem size_item;
Qt::Alignment align;
int new_type;
bool resize_enabled;
private slots:
void toggleNewItem(bool on);
void alignClicked();
void selectionChanged();
void sizeChanged();
void propertyChanged();
void comboLineStyleChanged();
void changeFinished() {if (cur_item) emit itemEdited(cur_item);}
void moveZUpAvailable(bool yes) {actions_Z_up.setEnabled(yes); actions_Z_top.setEnabled(yes);}
void moveZDownAvailable(bool yes) {actions_Z_down.setEnabled(yes); actions_Z_bottom.setEnabled(yes);}
void buttonImage_clicked();
void buttonImagePaste_clicked();
void buttonFont_clicked();
void buttonTextEdit_clicked();
void actionTop_triggered(bool on) {actionAlignTrigger(true, Qt::AlignTop);}
void actionVCenter_triggered(bool on) {actionAlignTrigger(true, Qt::AlignVCenter);}
void actionBottom_triggered(bool on) {actionAlignTrigger(true, Qt::AlignBottom);}
void actionLeft_triggered(bool on) {actionAlignTrigger(false, Qt::AlignLeft);}
void actionHCenter_triggered(bool on) {actionAlignTrigger(false, Qt::AlignHCenter);}
void actionRight_triggered(bool on) {actionAlignTrigger(false, Qt::AlignRight);}
void actionZ_triggered();
public slots:
void setResizeHandlesEnabled(bool on);
signals:
void itemCreated(QGraphicsItem * item);
void itemAddConfirm(QGraphicsItem * item);
void itemEdited(QGraphicsItem * item);
void itemZChanged(QGraphicsItem * item);
};
#endif // DRAWTOOLS_H

View File

@@ -0,0 +1,821 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DrawTools</class>
<widget class="QWidget" name="DrawTools">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1197</width>
<height>268</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QStackedWidget" name="stackedProperties">
<property name="currentIndex">
<number>2</number>
</property>
<widget class="QWidget" name="pageText">
<layout class="QHBoxLayout" name="horizontalLayout_6">
<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="QPushButton" name="buttonFont">
<property name="text">
<string>Font ...</string>
</property>
<property name="icon">
<iconset resource="qad_blockview.qrc">
<normaloff>:/icons/draw-text.png</normaloff>:/icons/draw-text.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Text:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboText">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="editable">
<bool>true</bool>
</property>
<property name="currentIndex">
<number>-1</number>
</property>
<property name="maxVisibleItems">
<number>32</number>
</property>
<property name="insertPolicy">
<enum>QComboBox::NoInsert</enum>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="buttonTextEdit">
<property name="toolTip">
<string>Edit text ...</string>
</property>
<property name="text">
<string>Edit text ...</string>
</property>
<property name="icon">
<iconset resource="../application/qad_application.qrc">
<normaloff>:/icons/document-edit.png</normaloff>:/icons/document-edit.png</iconset>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonIconOnly</enum>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="widgetAlign2" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_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="QToolButton" name="buttonAlignHor">
<property name="text">
<string>Align center left</string>
</property>
<property name="icon">
<iconset resource="qad_blockview.qrc">
<normaloff>:/icons/align-hor.png</normaloff>:/icons/align-hor.png</iconset>
</property>
<property name="popupMode">
<enum>QToolButton::InstantPopup</enum>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="buttonAlignVer">
<property name="text">
<string>Align center left</string>
</property>
<property name="icon">
<iconset resource="qad_blockview.qrc">
<normaloff>:/icons/align-ver.png</normaloff>:/icons/align-ver.png</iconset>
</property>
<property name="popupMode">
<enum>QToolButton::InstantPopup</enum>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="widgetAlign9" native="true">
<layout class="QGridLayout" name="gridLayout">
<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>
<property name="spacing">
<number>2</number>
</property>
<item row="1" column="1">
<widget class="QToolButton" name="buttonAlignCC">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Align center</string>
</property>
<property name="icon">
<iconset resource="qad_blockview.qrc">
<normaloff>:/icons/align-center-center.png</normaloff>:/icons/align-center-center.png</iconset>
</property>
<property name="iconSize">
<size>
<width>27</width>
<height>16</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QToolButton" name="buttonAlignCR">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Align center right</string>
</property>
<property name="icon">
<iconset resource="qad_blockview.qrc">
<normaloff>:/icons/align-center-right.png</normaloff>:/icons/align-center-right.png</iconset>
</property>
<property name="iconSize">
<size>
<width>27</width>
<height>16</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QToolButton" name="buttonAlignCL">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Align center left</string>
</property>
<property name="icon">
<iconset resource="qad_blockview.qrc">
<normaloff>:/icons/align-center-left.png</normaloff>:/icons/align-center-left.png</iconset>
</property>
<property name="iconSize">
<size>
<width>27</width>
<height>16</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QToolButton" name="buttonAlignTR">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Align top right</string>
</property>
<property name="icon">
<iconset resource="qad_blockview.qrc">
<normaloff>:/icons/align-top-right.png</normaloff>:/icons/align-top-right.png</iconset>
</property>
<property name="iconSize">
<size>
<width>27</width>
<height>16</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QToolButton" name="buttonAlignBR">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Align bottom right</string>
</property>
<property name="icon">
<iconset resource="qad_blockview.qrc">
<normaloff>:/icons/align-bottom-right.png</normaloff>:/icons/align-bottom-right.png</iconset>
</property>
<property name="iconSize">
<size>
<width>27</width>
<height>16</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QToolButton" name="buttonAlignBC">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Align bottom center</string>
</property>
<property name="icon">
<iconset resource="qad_blockview.qrc">
<normaloff>:/icons/align-bottom-center.png</normaloff>:/icons/align-bottom-center.png</iconset>
</property>
<property name="iconSize">
<size>
<width>27</width>
<height>16</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QToolButton" name="buttonAlignTL">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Align top left</string>
</property>
<property name="icon">
<iconset resource="qad_blockview.qrc">
<normaloff>:/icons/align-top-left.png</normaloff>:/icons/align-top-left.png</iconset>
</property>
<property name="iconSize">
<size>
<width>27</width>
<height>16</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QToolButton" name="buttonAlignTC">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Align top center</string>
</property>
<property name="icon">
<iconset resource="qad_blockview.qrc">
<normaloff>:/icons/align-top-center.png</normaloff>:/icons/align-top-center.png</iconset>
</property>
<property name="iconSize">
<size>
<width>27</width>
<height>16</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QToolButton" name="buttonAlignBL">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Align bottom left</string>
</property>
<property name="icon">
<iconset resource="qad_blockview.qrc">
<normaloff>:/icons/align-bottom-left.png</normaloff>:/icons/align-bottom-left.png</iconset>
</property>
<property name="iconSize">
<size>
<width>27</width>
<height>16</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="pageDim">
<layout class="QHBoxLayout" name="horizontalLayout_7">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="1">
<widget class="QDoubleSpinBox" name="spinWidth">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="decimals">
<number>0</number>
</property>
<property name="maximum">
<double>1000.000000000000000</double>
</property>
<property name="singleStep">
<double>10.000000000000000</double>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QDoubleSpinBox" name="spinHeight">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="decimals">
<number>0</number>
</property>
<property name="maximum">
<double>1000.000000000000000</double>
</property>
<property name="singleStep">
<double>10.000000000000000</double>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Width: </string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QDoubleSpinBox" name="spinThick">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="decimals">
<number>1</number>
</property>
<property name="maximum">
<double>999.000000000000000</double>
</property>
<property name="singleStep">
<double>0.500000000000000</double>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Thickness: </string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QLabel" name="label_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Height:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="2" rowspan="2">
<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 row="1" column="3">
<widget class="QLabel" name="label_6">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Style:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QComboBox" name="comboLineStyle"/>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="pageImage">
<layout class="QHBoxLayout" name="horizontalLayout_9">
<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="QPushButton" name="buttonImage">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Load image ...</string>
</property>
<property name="icon">
<iconset resource="../application/qad_application.qrc">
<normaloff>:/icons/document-open.png</normaloff>:/icons/document-open.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonImagePaste">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Paste image ...</string>
</property>
<property name="icon">
<iconset resource="qad_blockview.qrc">
<normaloff>:/icons/view-preview.png</normaloff>:/icons/view-preview.png</iconset>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>1</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_5">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Scale:</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="spinScale">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="maximum">
<double>999.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="pageEmpty"/>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>16</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="labelPen">
<property name="pixmap">
<pixmap resource="qad_blockview.qrc">:/icons/format-stroke-color.png</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="ColorButton" name="colorButtonPen">
<property name="useNativeDialog">
<bool>true</bool>
</property>
<property name="useAlphaChannel">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>16</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="labelBrush">
<property name="pixmap">
<pixmap resource="qad_blockview.qrc">:/icons/format-fill-color.png</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="ColorButton" name="colorButtonBrush">
<property name="useNativeDialog">
<bool>true</bool>
</property>
<property name="useAlphaChannel">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
<action name="actionTop">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Top</string>
</property>
</action>
<action name="actionVCenter">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Center</string>
</property>
<property name="toolTip">
<string>Center</string>
</property>
</action>
<action name="actionBottom">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Bottom</string>
</property>
<property name="toolTip">
<string>Bottom</string>
</property>
</action>
<action name="actionHCenter">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Center</string>
</property>
<property name="toolTip">
<string>Center</string>
</property>
</action>
<action name="actionLeft">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Left</string>
</property>
<property name="toolTip">
<string>Left</string>
</property>
</action>
<action name="actionRight">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Right</string>
</property>
<property name="toolTip">
<string>Right</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>
<class>ColorButton</class>
<extends>QPushButton</extends>
<header>colorbutton.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="../application/qad_application.qrc"/>
<include location="qad_blockview.qrc"/>
</resources>
<connections/>
</ui>

View File

@@ -0,0 +1,366 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="ru_RU">
<context>
<name>BlockBusItem</name>
<message>
<location filename="../blockbusitem.cpp" line="453"/>
<source>Add point: Ctrl + LeftClick
Remove point\segment: Ctrl + RightClick
New branch: Shift + LeftClick
Remove connection: Shift + RightClick</source>
<translation>Добавить точку: Ctrl + LeftClick
Удалить точку\сегмент: Ctrl + RightClick
Новая ветка: Shift + LeftClick
Удалить шину: Shift + RightClick</translation>
</message>
</context>
<context>
<name>BlockEditor</name>
<message>
<location filename="../blockeditor/blockeditor.ui" line="14"/>
<source>Block editor</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../blockeditor/blockeditor.ui" line="32"/>
<source>Block parameters</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../blockeditor/blockeditor.ui" line="59"/>
<source>Width:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../blockeditor/blockeditor.ui" line="79"/>
<source>Heigth:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../blockeditor/blockeditor.ui" line="99"/>
<source>Pins margin:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../blockeditor/blockeditor.ui" line="119"/>
<source>Color:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../blockeditor/blockeditor.ui" line="130"/>
<source>Pins</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../blockeditor/blockeditor.ui" line="179"/>
<source>Name</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../blockeditor/blockeditor.ui" line="184"/>
<source>Bus</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../blockeditor/blockeditor.ui" line="194"/>
<source>Add</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../blockeditor/blockeditor.ui" line="205"/>
<source>Clone</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../blockeditor/blockeditor.ui" line="232"/>
<source>Remove selected</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../blockeditor/blockeditor.ui" line="243"/>
<source>Remove all</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../blockeditor/blockeditor.ui" line="330"/>
<source>Save</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../blockeditor/blockeditor.ui" line="337"/>
<location filename="../blockeditor/blockeditor.ui" line="367"/>
<source>Ctrl+S</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../blockeditor/blockeditor.ui" line="360"/>
<source>Save as ...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../blockeditor/blockeditor.ui" line="390"/>
<source>Load ...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../blockeditor/blockeditor.ui" line="397"/>
<source>Ctrl+O</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../blockeditor/blockeditor.ui" line="417"/>
<source>Clear</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../blockeditor/blockeditor.ui" line="434"/>
<source>Remove items</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../blockeditor/blockeditor.ui" line="437"/>
<source>Del</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>DrawTools</name>
<message>
<location filename="../drawtools.ui" line="14"/>
<source>Form</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../drawtools.ui" line="51"/>
<source>Font ...</source>
<translation>Шрифт ...</translation>
</message>
<message>
<location filename="../drawtools.ui" line="62"/>
<source>Text:</source>
<translation>Текст:</translation>
</message>
<message>
<location filename="../drawtools.ui" line="91"/>
<location filename="../drawtools.ui" line="94"/>
<source>Edit text ...</source>
<translation>Изменить текст ...</translation>
</message>
<message>
<location filename="../drawtools.ui" line="123"/>
<location filename="../drawtools.ui" line="137"/>
<location filename="../drawtools.ui" line="230"/>
<source>Align center left</source>
<translation>Выравнивание слева по центру</translation>
</message>
<message>
<location filename="../drawtools.ui" line="178"/>
<source>Align center</source>
<translation>Выравнивание по центру</translation>
</message>
<message>
<location filename="../drawtools.ui" line="204"/>
<source>Align center right</source>
<translation>Выравнивание справа по центру</translation>
</message>
<message>
<location filename="../drawtools.ui" line="256"/>
<source>Align top right</source>
<translation>Выравнивание справа сверху</translation>
</message>
<message>
<location filename="../drawtools.ui" line="282"/>
<source>Align bottom right</source>
<translation>Выравнивание справа снизу</translation>
</message>
<message>
<location filename="../drawtools.ui" line="308"/>
<source>Align bottom center</source>
<translation>Выравнивание снизу по центру</translation>
</message>
<message>
<location filename="../drawtools.ui" line="334"/>
<source>Align top left</source>
<translation>Выравнивание слева сверху</translation>
</message>
<message>
<location filename="../drawtools.ui" line="360"/>
<source>Align top center</source>
<translation>Выравнивание сверху по центру</translation>
</message>
<message>
<location filename="../drawtools.ui" line="386"/>
<source>Align bottom left</source>
<translation>Выравнивание снизу слева</translation>
</message>
<message>
<source>Size: </source>
<translation type="vanished">Размер: </translation>
</message>
<message>
<location filename="../drawtools.ui" line="471"/>
<source>Width: </source>
<translation>Ширина: </translation>
</message>
<message>
<location filename="../drawtools.ui" line="506"/>
<source>Thickness: </source>
<translation>Толщина: </translation>
</message>
<message>
<location filename="../drawtools.ui" line="522"/>
<source>Height:</source>
<translation>Высота:</translation>
</message>
<message>
<location filename="../drawtools.ui" line="554"/>
<source>Style:</source>
<translation>Стиль:</translation>
</message>
<message>
<location filename="../drawtools.ui" line="591"/>
<source>Load image ...</source>
<translation>Загрузить картинку ...</translation>
</message>
<message>
<location filename="../drawtools.ui" line="624"/>
<source>Scale:</source>
<translation>Масштаб:</translation>
</message>
<message>
<location filename="../drawtools.ui" line="727"/>
<source>Top</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../drawtools.ui" line="735"/>
<location filename="../drawtools.ui" line="738"/>
<location filename="../drawtools.ui" line="757"/>
<location filename="../drawtools.ui" line="760"/>
<source>Center</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../drawtools.ui" line="746"/>
<location filename="../drawtools.ui" line="749"/>
<source>Bottom</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../drawtools.ui" line="768"/>
<location filename="../drawtools.ui" line="771"/>
<source>Left</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../drawtools.ui" line="779"/>
<location filename="../drawtools.ui" line="782"/>
<source>Right</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../drawtools.cpp" line="236"/>
<source>NoPen</source>
<translation>НетЛинии</translation>
</message>
<message>
<location filename="../drawtools.cpp" line="236"/>
<source>Solid</source>
<translation>Сплошная</translation>
</message>
<message>
<location filename="../drawtools.cpp" line="236"/>
<source>Dash</source>
<translation>Штриховая</translation>
</message>
<message>
<location filename="../drawtools.cpp" line="237"/>
<source>Dot</source>
<translation>Пунктирная</translation>
</message>
<message>
<location filename="../drawtools.cpp" line="237"/>
<source>Dash-Dot</source>
<translation>ШтрихПунктирная</translation>
</message>
<message>
<location filename="../drawtools.cpp" line="237"/>
<source>Dash-Dot-Dot</source>
<translation>ШтрихПунктирПунктирная</translation>
</message>
<message>
<location filename="../drawtools.cpp" line="257"/>
<source>Edit text</source>
<translation>Редактировать текст</translation>
</message>
<message>
<location filename="../drawtools.cpp" line="264"/>
<source>Bring
forward</source>
<translation>Переместить
выше</translation>
</message>
<message>
<location filename="../drawtools.cpp" line="265"/>
<source>Bring
to front</source>
<translation>На передний
фон</translation>
</message>
<message>
<location filename="../drawtools.cpp" line="266"/>
<source>Send
backward</source>
<translation>Переместить
ниже</translation>
</message>
<message>
<location filename="../drawtools.cpp" line="267"/>
<source>Send
to back</source>
<translation>На задний
фон</translation>
</message>
<message>
<location filename="../drawtools.cpp" line="268"/>
<source>Draw
Rectangle</source>
<translation>Нарисовать
прямоугольник</translation>
</message>
<message>
<location filename="../drawtools.cpp" line="269"/>
<source>Draw
Ellipse</source>
<translation>Нарисовать
эллипс</translation>
</message>
<message>
<location filename="../drawtools.cpp" line="270"/>
<source>Draw
Line</source>
<translation>Нарисовать
линию</translation>
</message>
<message>
<location filename="../drawtools.cpp" line="271"/>
<source>Draw
Text</source>
<translation>Нарисовать
текст</translation>
</message>
<message>
<location filename="../drawtools.cpp" line="272"/>
<source>Draw
Image</source>
<translation>Нарисовать
картинку</translation>
</message>
<message>
<location filename="../drawtools.cpp" line="778"/>
<source>Select image</source>
<translation>Выбрать картинку</translation>
</message>
</context>
</TS>

View File

@@ -0,0 +1 @@
qad_plugin(blockview "Gui;Widgets" "")

View File

@@ -0,0 +1,69 @@
#include "blockview.h"
#include "blockviewplugin.h"
#include <QtCore/QtPlugin>
BlockViewPlugin::BlockViewPlugin(QObject * parent): QObject(parent) {
m_initialized = false;
}
void BlockViewPlugin::initialize(QDesignerFormEditorInterface * /* core */) {
if (m_initialized)
return;
// Add extension registrations, etc. here
m_initialized = true;
}
bool BlockViewPlugin::isInitialized() const {
return m_initialized;
}
QWidget * BlockViewPlugin::createWidget(QWidget * parent) {
return new BlockView(parent);
}
QString BlockViewPlugin::name() const {
return QLatin1String("BlockView");
}
QString BlockViewPlugin::group() const {
return QLatin1String("Display Widgets");
}
QIcon BlockViewPlugin::icon() const {
return QIcon(":/icons/blockview.png");
}
QString BlockViewPlugin::toolTip() const {
return QLatin1String("");
}
QString BlockViewPlugin::whatsThis() const {
return QLatin1String("");
}
bool BlockViewPlugin::isContainer() const {
return false;
}
QString BlockViewPlugin::domXml() const {
return QLatin1String("<widget class=\"BlockView\" name=\"blockView\">\n</widget>\n");
}
QString BlockViewPlugin::includeFile() const {
return QLatin1String("blockview.h");
}

View File

@@ -0,0 +1,36 @@
#ifndef BLOCKVIEWPLUGIN_H
#define BLOCKVIEWPLUGIN_H
#include <QObject>
#if QT_VERSION >= 0x050000
# include <QtUiPlugin/QDesignerCustomWidgetInterface>
#else
# include <QDesignerCustomWidgetInterface>
#endif
class BlockViewPlugin: public QObject, public QDesignerCustomWidgetInterface
{
Q_OBJECT
Q_INTERFACES(QDesignerCustomWidgetInterface)
public:
BlockViewPlugin(QObject * parent = 0);
bool isContainer() const;
bool isInitialized() const;
QIcon icon() const;
QString domXml() const;
QString group() const;
QString includeFile() const;
QString name() const;
QString toolTip() const;
QString whatsThis() const;
QWidget * createWidget(QWidget * parent);
void initialize(QDesignerFormEditorInterface * core);
private:
bool m_initialized;
};
#endif // BLOCKVIEWPLUGIN_H

View File

@@ -0,0 +1,17 @@
#include "qad_blockview.h"
#include "blockviewplugin.h"
QADBlockView::QADBlockView(QObject * parent): QObject(parent)
{
m_widgets.append(new BlockViewPlugin(this));
}
QList<QDesignerCustomWidgetInterface * > QADBlockView::customWidgets() const {
return m_widgets;
}
#if QT_VERSION < 0x050000
Q_EXPORT_PLUGIN2(qad_graphic_plugin, QADBlockView)
#endif

View File

@@ -0,0 +1,23 @@
#ifndef QAD_BLOCKVIEW_H
#define QAD_BLOCKVIEW_H
#include <QtDesigner/QtDesigner>
#include <QtCore/qplugin.h>
class QADBlockView: public QObject, public QDesignerCustomWidgetCollectionInterface
{
Q_OBJECT
Q_INTERFACES(QDesignerCustomWidgetCollectionInterface)
#if QT_VERSION >= 0x050000
Q_PLUGIN_METADATA(IID "qad.blockview")
#endif
public:
explicit QADBlockView(QObject * parent = 0);
virtual QList<QDesignerCustomWidgetInterface * > customWidgets() const;
private:
QList<QDesignerCustomWidgetInterface * > m_widgets;
};
#endif // QAD_BLOCKVIEW_H

View File

@@ -0,0 +1,51 @@
<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-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/align-bottom-center.png</file>
<file>../icons/align-bottom-left.png</file>
<file>../icons/align-bottom-right.png</file>
<file>../icons/align-center-center.png</file>
<file>../icons/align-center-left.png</file>
<file>../icons/align-center-right.png</file>
<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>
</qresource>
</RCC>

View File

@@ -0,0 +1,4 @@
qad_project(graphic "Gui;Widgets;OpenGL" "qad_widgets;qad_utils;${OPENGL_LIBRARIES}")
if (graphic_UTILS)
add_subdirectory(qpicalculator)
endif()

1843
test/qad/graphic/graphic.cpp Normal file
View File

@@ -0,0 +1,1843 @@
#include "graphic.h"
#include "qad_types.h"
#include "uglwidget.h"
#include "ui_graphic.h"
#include "ui_graphic_conf.h"
#if QT_VERSION < 0x050000
# include <QTapAndHoldGesture>
# include <QPanGesture>
# include <QPinchGesture>
#endif
#ifndef Q_OS_ANDROID
# define HAS_GL
#endif
#ifdef HAS_GL
# ifndef GL_MULTISAMPLE
# define GL_MULTISAMPLE 0x809D
# endif
#endif
__GraphicRegistrator__ __graphic_registrator__;
Graphic::Graphic(QWidget * parent): QFrame(parent), canvas(0), line_x_min(this), line_x_max(this), line_y_min(this), line_y_max(this) {
QTranslator * trans = new QTranslator();
trans->load(":/lang/qad_graphic_" + QLocale::system().name().left(2));
if (trans->isEmpty())
trans->load("lang/qad_graphic_" + QLocale::system().name().left(2));
#if QT_VERSION >= 0x050000
if (!qApp->installTranslator(trans))
delete trans;
#else
qApp->installTranslator(trans);
#endif
gesture_angle = 45.;
leg_update = true;
visible_update = fullscr = need_mouse_pan = false;
gestures =
#ifdef Q_OS_ANDROID
true;
#else
false;
#endif
ui = new Ui::Graphic();
ui->setupUi(this);
/*line_x_min.resize(70, 22);
line_x_max.resize(70, 22);
line_y_min.resize(70, 22);
line_y_max.resize(70, 22);*/
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);
((QBoxLayout * )ui->widgetLY->layout())->addWidget(&line_y_max);
((QBoxLayout * )ui->widgetLX->layout())->insertWidget(0, &line_x_min);
((QBoxLayout * )ui->widgetLX->layout())->addWidget(&line_x_max);
tm.restart();
grid_numbers_x = grid_numbers_y = 1;
LN2 = qLn(2.);
LN5 = qLn(5.);
LN10 = qLn(10.);
line_x_min.setClearButtonVisible(true);
line_x_max.setClearButtonVisible(true);
line_y_min.setClearButtonVisible(true);
line_y_max.setClearButtonVisible(true);
connect(&line_x_min, SIGNAL(valueChanged(double)), this, SLOT(lineXMinChanged(double)));
connect(&line_x_max, SIGNAL(valueChanged(double)), this, SLOT(lineXMaxChanged(double)));
connect(&line_y_min, SIGNAL(valueChanged(double)), this, SLOT(lineYMinChanged(double)));
connect(&line_y_max, SIGNAL(valueChanged(double)), this, SLOT(lineYMaxChanged(double)));
connect(ui->canvas_raster, SIGNAL(paintEvent(QPaintEvent * )), this, SLOT(canvasPaintEvent()));
prepareCanvas(ui->canvas_raster);
#ifdef HAS_GL
canvas_gl = new UGLWidget();
ui->layoutCanvas->addWidget(canvas_gl);
connect(canvas_gl, SIGNAL(paintSignal()), this, SLOT(canvasPaintEvent()));
prepareCanvas(canvas_gl);
#endif
icon_exp_x = QIcon(":/icons/expand_x.png");
icon_exp_y = QIcon(":/icons/expand_y.png");
icon_exp_sx = QIcon(":/icons/expand_s_x.png");
icon_exp_sy = QIcon(":/icons/expand_s_y.png");
icon_pause_b = QImage(":/icons/pause-back.png");
icon_pause_f = QImage(":/icons/pause-front.png");
aupdate = grid = isFit = isEmpty = navigation = true;
aalias = mupdate = bufferActive = isOGL = cancel = isPrinting = guides = hasLblX = hasLblY = isHover = false;
pause_ = only_expand_x = only_expand_y = false;
//qDebug() << -DBL_MAX/2. << DBL_MAX/2. << DBL_MIN;
limit_.setCoords(-DBL_MAX, -DBL_MAX, DBL_MAX, DBL_MAX);
eminx = eminy = DBL_MAX;
emaxx = emaxy = DBL_MIN;
grad_x = grad_y = Auto;
axis_type_x = Numeric;
min_repaint_int = 25;
inc_x = 1.;
legy = 0;
buffer = 0;
gridx = gridy = 1.;
history = 5.;
min_int = 1;
max_int = 200;
mdm = 10.;
visible_time = -1.;
thick = lineThickness();
pause_phase = 0.;
def_rect.setRect(0., 0., 1., 1.);
selrect = def_rect;
margins_.setRect(4, 4, 4, 4);
curaction = gaMove;
selbrush.setStyle(Qt::SolidPattern);
selbrush.setColor(QColor(60, 175, 255, 100));
text_color = palette().color(QPalette::WindowText);
grid_pen = QPen(palette().color(QPalette::Disabled, QPalette::WindowText), 0., Qt::DotLine);
//graph_pen = QPen(Qt::red);
//graph_pen.setCosmetic(true);
graphics.append(GraphicType());
curGraphic = 0;
selpen = palette().color(QPalette::WindowText);
selpen.setStyle(Qt::DashLine);
back_color = palette().color(QPalette::Base);
buttons_ = AllButtons;
setOpenGL(false);
setButtonsPosition(Graphic::Left);
setAntialiasing(false);
setCaption("");
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
ui->layoutButtons->update();
updateLegend();
setRectToLines();
conf = new GraphicConf(graphics, this);
}
Graphic::~Graphic() {
delete conf;
if (buffer != 0) delete buffer;
}
void Graphic::changeEvent(QEvent * e) {
if (e->type() == QEvent::LanguageChange) {
ui->retranslateUi(this);
return;
}
QFrame::changeEvent(e);
}
void Graphic::resizeEvent(QResizeEvent *) {
if (leg_update) updateLegend(false);
}
void Graphic::timerEvent(QTimerEvent * ) {
pause_phase += 0.02;
if (pause_phase > 1.)
pause_phase -= 1.;
update();
}
bool Graphic::eventFilter(QObject * o, QEvent * e) {
//qDebug() << "event" << o << e;
if (o == canvas) {
switch (e->type()) {
case QEvent::Gesture:
if (!navigation || !gestures) break;
foreach (QGesture * g, ((QGestureEvent*)e)->gestures())
procGesture(g);
break;
case QEvent::KeyPress:
if (((QKeyEvent*)e)->key() == Qt::Key_Back)
leaveFullscreen();
break;
case QEvent::TouchBegin:
if (!navigation || !gestures) break;
need_mouse_pan = true;
break;
case QEvent::TouchUpdate: {
if (!navigation || !gestures) break;
QList<QTouchEvent::TouchPoint> tpl = ((QTouchEvent*)e)->touchPoints();
if (tpl.size() == 2) {
need_mouse_pan = false;
QPointF dp = tpl[0].scenePos() - tpl[1].scenePos();
gesture_angle = rad2deg_qpie * qAtan2(qAbs(dp.y()), qAbs(dp.x()));
}
} break;
default: break;
}
}
return QFrame::eventFilter(o, e);
}
void Graphic::prepareCanvas(QWidget * w) {
connect(w, SIGNAL(mouseMoveEvent(QMouseEvent * )), this, SLOT(canvasMouseMoveEvent(QMouseEvent * )));
connect(w, SIGNAL(mousePressEvent(QMouseEvent * )), this, SLOT(canvasMousePressEvent(QMouseEvent * )));
connect(w, SIGNAL(mouseReleaseEvent(QMouseEvent * )), this, SLOT(canvasMouseReleaseEvent(QMouseEvent * )));
connect(w, SIGNAL(mouseDoubleClickEvent(QMouseEvent*)), this, SLOT(canvasMouseDoubleClickEvent(QMouseEvent * )));
connect(w, SIGNAL(wheelEvent(QWheelEvent * )), this, SLOT(canvasWheelEvent(QWheelEvent * )));
connect(w, SIGNAL(leaveEvent(QEvent * )), this, SLOT(canvasLeaveEvent(QEvent * )));
connect(w, SIGNAL(keyPressEvent(QKeyEvent * )), this, SLOT(canvasKeyPressEvent(QKeyEvent * )));
//w->grabGesture(Qt::TapGesture);
w->grabGesture(Qt::TapAndHoldGesture);
w->grabGesture(Qt::PanGesture);
w->grabGesture(Qt::PinchGesture);
w->setMouseTracking(true);
w->installEventFilter(this);
}
void Graphic::procGesture(QGesture * g) {
if (!g) return;
switch (g->gestureType()) {
case Qt::PanGesture: {
if (need_mouse_pan) break;
QPanGesture * pg = (QPanGesture*)g;
QPointF dp = -pg->delta();
dp.rx() /= getScaleX();
dp.ry() /= getScaleY();
selrect.translate(dp);
totalUpdate();
} break;
case Qt::PinchGesture: {
QPinchGesture * pg = (QPinchGesture*)g;
//qDebug() << pg->totalRotationAngle();
Qt::KeyboardModifiers km = Qt::NoModifier;
if (gesture_angle <= 20.) km = Qt::ControlModifier;
if (gesture_angle >= 70.) km = Qt::ShiftModifier;
QPoint cp = pg->centerPoint().toPoint();
if (!fullscr) cp = mapFromGlobal(cp);
procZoom(cp, (pg->scaleFactor() - 1.) * 500., km);
totalUpdate();
} break;
case Qt::TapAndHoldGesture: {
QTapAndHoldGesture * pg = (QTapAndHoldGesture*)g;
if (pg->state() == Qt::GestureStarted)
fullscreen();
} break;
default:
qDebug() << g;
break;
}
//qDebug() << g;
}
void Graphic::procZoom(QPointF view_center, double dzoom, Qt::KeyboardModifiers km) {
double scl, wid = canvas->width() - gridborder.x() - margins_.width() - margins_.left(), hei = canvas->height() - gridborder.y() - margins_.height() - margins_.top();
double px = view_center.x() - gridborder.x() - margins_.left(), py = hei - view_center.y() + margins_.height();
px = px / wid * selrect.width() + selrect.x();
py = py / hei * selrect.height() + selrect.y();
scl = 1. - dzoom / 500.;
if (km == Qt::NoModifier)
selrect.setRect(px - (px - selrect.x()) * scl, py - (py - selrect.y()) * scl, selrect.width() * scl, selrect.height() * scl);
else {
if (km == Qt::ControlModifier)
selrect.setRect(px - (px - selrect.x()) * scl, selrect.y(), selrect.width() * scl, selrect.height());
if (km == Qt::ShiftModifier)
selrect.setRect(selrect.x(), py - (py - selrect.y()) * scl, selrect.width(), selrect.height() * scl);
}
}
void Graphic::totalUpdate() {
isFit = false;
emit visualRectChanged();
update(true);
setRectToLines();
}
void Graphic::canvasPaintEvent() {
if (is_lines_update) return;
//QMutexLocker ml(&mutex_);
//static int pwid = 0, phei = 0;
int wid = canvas->width(), hei = canvas->height();
lastw = wid;
lasth = hei;
font_sz = fontMetrics().size(0, "0");
font_sz.setHeight(font_sz.height() * 1.);
font_sz.setWidth(font_sz.width() * 8);
thick = lineThickness();
if (buffer != 0) if (buffer->width() != wid || buffer->height() != hei) {delete buffer; buffer = 0;}
if (buffer == 0) buffer = new QImage(wid, hei, QImage::Format_RGB32);
if (bufferActive) {
QPainter p(canvas);
p.drawImage(0, 0, *buffer);
painter = &p;
fp_size.clear();
if (curpos != startpos) drawAction();
drawGuides();
return;
}
//if (!aupdate && !mupdate && pwid == wid && phei == hei) return;
/*if (pwid != wid || phei != hei) {
line_x_min.move(0, hei - 35);
line_x_max.move(0, 0);
line_y_min.move(70, hei - line_x_min.height());
line_y_max.move(wid - line_y_max.width(), hei - line_x_min.height());
}
line_x_min.setVisible(grid);
line_x_max.setVisible(grid);
line_y_min.setVisible(grid);
line_y_max.setVisible(grid);*/
//pwid = wid;
//phei = hei;
QPainter p;
#ifdef HAS_GL
if (isOGL) {
p.fillRect(canvas->rect(), Qt::black);
glClearColor(0.f, 0.f, 0.f, 0.f);
p.begin(canvas);
} else
#endif
p.begin(buffer);
p.fillRect(canvas->rect(), back_color);
painter = &p;
p.setFont(font());
gridborder = QPoint(5, 5);
if (grid) {
gridborder += QPoint(font_sz.width(), font_sz.height());
if (hasLblY) gridborder += QPoint(font_sz.height(), 0);
if (hasLblX) gridborder += QPoint(0, font_sz.height());
}
painter->setClipping(true);
painter->setClipRect(QRect(gridborder.x(), 0, wid - gridborder.x(), hei - gridborder.y()));
emit beforeGraphicPaintEvent(painter);
painter->setClipping(false);
if (grid)
drawGrid();
p.setRenderHint(QPainter::Antialiasing, aalias);
#ifndef ANDROID
if (isOGL) {
if (aalias) glEnable(GL_MULTISAMPLE);
else glDisable(GL_MULTISAMPLE);
}
#endif
//p.setRenderHint(QPainter::HighQualityAntialiasing, aalias);
fp_size.clear();
if (!aalias) p.translate(-0.5, -0.5);
drawGraphics();
drawGuides();
if (pause_) drawPause();
emit graphicPaintEvent(painter);
p.end();
if (isOGL) return;
p.begin(canvas);
p.drawImage(0, 0, *buffer);
p.end();
}
void Graphic::canvasMouseMoveEvent(QMouseEvent * e) {
isHover = true;
curpos = e->pos();
curpos_r = canvas2real(curpos);
QPointF dp;
QString cursorstr = tr("Cursor: ") + pointCoords(curpos_r);
emit graphicMouseMoveEvent(curpos_r, e->buttons());
if (e->buttons() == Qt::NoButton) {
ui->status->setText(cursorstr);
if (guides) update();
return;
}
if (!navigation) return;
if (gestures) {
if (!need_mouse_pan) return;
curaction = gaMove;
} else
if (curaction != gaMove && (e->buttons() & Qt::RightButton) == Qt::RightButton) return;
switch (curaction) {
case gaZoomInRect:
ui->status->setText(tr("Selection") + ": " + pointCoords(startpos_r) + " -> " +
pointCoords(curpos_r) + ", " + tr("Size") + ": " + pointCoords(absPoint(curpos_r - startpos_r)));
repaintCanvas(true);
break;
case gaZoomRangeX:
ui->status->setText(tr("Range") + ": " + QString::number(startpos_r.x(), 'f', 3) +
" -> " + QString::number(curpos_r.x(), 'f', 3) + ", " + tr("Length") + ": " +
QString::number(qAbs(curpos_r.x() - startpos_r.x()), 'f', 3));
repaintCanvas(true);
break;
case gaZoomRangeY:
ui->status->setText(tr("Range") + ": " + QString::number(startpos_r.y(), 'f', 3) +
" -> " + QString::number(curpos_r.y(), 'f', 3) + ", " + tr("Length") + ": " +
QString::number(qAbs(curpos_r.y() - startpos_r.y()), 'f', 3));
repaintCanvas(true);
break;
case gaMove:
dp = e->pos() - prevpos;
dp.rx() *= selrect.width() / double(gridborder.x() + 5 - lastw);
dp.ry() *= selrect.height() / double(lasth - legy - gridborder.y() - 5);
if (e->modifiers() == Qt::ControlModifier)
dp.setY(0.);
if (e->modifiers() == Qt::ShiftModifier)
dp.setX(0.);
selrect.translate(dp);
totalUpdate();
break;
default: break;
}
prevpos = e->pos();
}
void Graphic::canvasMousePressEvent(QMouseEvent * e) {
emit graphicMousePressEvent(canvas2real(QPointF(e->pos())), e->buttons());
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);
prevpos = e->pos();
startpos = prevpos;
startpos_r = canvas2real(startpos);
if (cancel || gestures) return;
if (e->button() == Qt::MidButton) curaction = gaMove;
if (e->button() == Qt::RightButton) {
if (bufferActive) {
curpos = startpos;
curpos_r = canvas2real(curpos);
repaintCanvas(true);
swapToNormal();
cancel = true;
return;
} else {
prevaction = curaction;
curaction = gaMove;
return;
}
}
if (e->button() == Qt::LeftButton) {
if (e->modifiers() == Qt::ControlModifier) curaction = gaZoomRangeX;
else if (e->modifiers() == Qt::ShiftModifier) curaction = gaZoomRangeY;
else curaction = gaZoomInRect;
switch (curaction) {
case gaZoomInRect:
case gaZoomRangeX:
case gaZoomRangeY:
swapToBuffer();
break;
default: break;
}
}
setCurrentAction(curaction);
}
void Graphic::canvasMouseReleaseEvent(QMouseEvent * e) {
emit graphicMouseReleaseEvent(canvas2real(QPointF(e->pos())), e->buttons());
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);
QPointF tlp, brp;
QRect sr;
sr = QRect(startpos, curpos).normalized();
if (cancel) {
if (e->buttons() == Qt::NoButton) cancel = false;
return;
}
if (e->button() == Qt::RightButton && curaction == gaMove) {
curaction = prevaction;
return;
}
if (e->button() == Qt::LeftButton && (e->buttons() & Qt::RightButton) != Qt::RightButton) {
if (curpos != startpos) {
tlp = canvas2real(sr.topLeft());
brp = canvas2real(sr.bottomRight());
isFit = false;
switch (curaction) {
case gaZoomInRect:
if (sr.width() <= 1 || sr.height() <= 1) break;
selrect.setCoords(tlp.x(), brp.y(), brp.x(), tlp.y());
setRectToLines();
break;
case gaZoomRangeX:
if (sr.width() <= 1) break;
findGraphicsRect(tlp.x(), brp.x());
break;
case gaZoomRangeY:
if (sr.height() <= 1) break;
findGraphicsRect(0., 0., brp.y(), tlp.y());
break;
default: return;
}
}
swapToNormal();
update(true);
}
QPointF rp = canvas2real(QPointF(e->pos()));
ui->status->setText(tr("Cursor") + ": " + pointCoords(rp));
emit visualRectChanged();
}
void Graphic::canvasMouseDoubleClickEvent(QMouseEvent * ) {
autofit();
}
void Graphic::canvasWheelEvent(QWheelEvent * e) {
//if (curaction != gaMove) return;
emit graphicWheelEvent(canvas2real(QPointF(e->pos())), e->delta());
if (gestures) return;
if (!navigation) return;
procZoom(e->pos(), e->delta(), e->modifiers());
totalUpdate();
}
void Graphic::zoom(float factor) {
double wid = canvas->width() - gridborder.x() - margins_.width() - margins_.left(), hei = canvas->height() - gridborder.y() - margins_.height() - margins_.top();
double px = wid / 2, py = hei / 2;
px = px / wid * selrect.width() + selrect.x();
py = py / hei * selrect.height() + selrect.y();
selrect.setRect(px - (px - selrect.x()) * factor, py - (py - selrect.y()) * factor, selrect.width() * factor, selrect.height() * factor);
isFit = false;
update(true);
setRectToLines();
}
void Graphic::fullscreen() {
if (fullscr) leaveFullscreen();
else enterFullscreen();
}
void Graphic::canvasLeaveEvent(QEvent * ) {
isHover = false;
if (guides) update(true);
ui->status->setText(tr("Cursor") + ": ( ; )");
leaveFullscreen();
}
void Graphic::canvasKeyPressEvent(QKeyEvent * e) {
switch (e->key()) {
case Qt::Key_Escape: leaveFullscreen();
default: break;
};
}
void Graphic::clear() {
//cout << "clear" << endl;
for (int i = 0; i < graphics.size(); ++i) {
graphics[i].polyline.clear();
graphics[i].polyline_pause.clear();
graphics[i].max_x = 0.;
graphics[i].cvrect = QRectF();
}
if (isFit) on_buttonAutofit_clicked();
}
void Graphic::setAntialiasing(bool enabled) {
if (aalias == enabled) return;
aalias = enabled;
/*QGLFormat f = canvas_gl->format();
f.setSampleBuffers(enabled);
canvas_gl->setFormat(f);*/
update();
}
void Graphic::setPaused(bool yes) {
pause_ = yes;
ui->checkPause->blockSignals(true);
ui->checkPause->setChecked(yes);
ui->checkPause->blockSignals(false);
for (int i = 0; i < graphics.size(); ++i)
graphics[i].cvrect = QRectF();
if (!pause_) {
killTimer(timer_pause);
timer_pause = 0;
update(true);
return;
}
for (int i = 0; i < graphics.size(); ++i) {
graphics[i].polyline_pause = graphics[i].polyline;
graphics[i].polyline_pause.detach();
graphics[i].max_x_pause = graphics[i].max_x;
}
timer_pause = startTimer(40);
}
void Graphic::setHistorySize(double val) {
history = val;
double x;
for (int i = 0; i < graphics.size(); ++i) {
QPolygonF & pol(graphics[i].polyline);
if (pol.isEmpty() || history <= 0.) continue;
graphics[i].cvrect = QRectF();
x = pol.back().x() - history;
for (int j = pol.size() - 2; j >= 0 ; --j)
if (pol[j].x() < x) {
//qDebug() << pol.size() << j;
pol.erase(pol.begin(), pol.begin() + j);
break;
}
}
}
void Graphic::setOnlyExpandY(bool yes) {
only_expand_y = yes;
ui->checkExpandY->blockSignals(true);
ui->checkExpandY->setCheckable(yes);
ui->checkExpandY->blockSignals(false);
}
void Graphic::setOnlyExpandX(bool yes) {
only_expand_x = yes;
ui->checkExpandX->blockSignals(true);
ui->checkExpandX->setCheckable(yes);
ui->checkExpandX->blockSignals(false);
}
void Graphic::setGesturesNavigation(bool yes) {
gestures = yes;
}
Graphic::GraphicsData Graphic::graphicsData() const {
GraphicsData ret;
ret.resize(graphics.size());
for (int i = 0; i < graphics.size(); ++i)
ret[i] = graphics[i].polyline;
return ret;
}
QByteArray Graphic::graphicsDataRaw() const {
QByteArray ret;
QDataStream s(&ret, QIODevice::WriteOnly);
s << graphicsData();
return ret;
}
void Graphic::setGraphicsData(const Graphic::GraphicsData & gd) {
setGraphicsCount(gd.size());
for (int i = 0; i < gd.size(); ++i)
setGraphicData(gd[i], i, false);
updateGraphics();
}
void Graphic::setGraphicsDataRaw(const QByteArray & ba) {
if (ba.isEmpty()) {
clear();
return;
}
Graphic::GraphicsData gd;
QDataStream s(ba);
s >> gd;
setGraphicsData(gd);
}
void Graphic::setButtons(Graphic::Buttons b) {
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));
ui->buttonClear->setVisible(b.testFlag(Clear));
ui->buttonConfigure->setVisible(b.testFlag(Configure));
ui->buttonSave->setVisible(b.testFlag(Save));
ui->buttonClose->setVisible(b.testFlag(Close));
ui->checkPause->setVisible(b.testFlag(Pause));
if (ui->buttonAutofit->isVisible() || ui->checkGrid->isVisible() || ui->checkGuides->isVisible() ||
ui->buttonConfigure->isVisible() || ui->buttonSave->isVisible() || ui->checkPause->isVisible())
ui->verticalSpacer->changeSize(0, 30, QSizePolicy::Preferred, QSizePolicy::Preferred);
else
ui->verticalSpacer->changeSize(0, 0, QSizePolicy::Preferred, QSizePolicy::Preferred);
ui->layoutButtons->update();
}
void Graphic::setButtonsPosition(Graphic::Alignment a) {
align = a;
ui->widgetLeft->hide();
ui->widgetRight->hide();
switch (a) {
case Graphic::Left:
ui->widgetLeft->setLayout(ui->layoutButtons);
ui->widgetLeft->show();
break;
case Graphic::Right:
ui->widgetRight->setLayout(ui->layoutButtons);
ui->widgetRight->show();
break;
}
}
void Graphic::addPoint(const QPointF & p, int graphic, bool update_) {
if (graphic >= graphics.size() || graphic < 0) return;
GraphicType & t(graphics[graphic]);
if (!t.cvrect.isNull() && !pause_) {
// if (graphics[graphic].cvrect.contains(p))
// graphics[graphic].cvrect = QRectF();
if (t.cvrect.top() < p.y()) t.cvrect.setTop(p.y());
if (t.cvrect.bottom() > p.y()) t.cvrect.setBottom(p.y());
if (t.cvrect.right() < p.x()) t.cvrect.setRight(p.x());
if (t.cvrect.left() > p.x()) t.cvrect.setLeft(p.x());
}
if (t.polyline.size() == 0) t.max_x = p.x();
t.polyline << p;
if (t.max_x < p.x()) t.max_x = p.x();
tick(graphic, true, update_);
}
void Graphic::setGraphicData(const QVector<QPointF> & g, int graphic, bool update_) {
if (graphic >= graphics.size() || graphic < 0) return;
GraphicType & t(graphics[graphic]);
t.cvrect = QRectF();
t.polyline.clear();
t.polyline = g;
if (t.polyline.size() == 0) {
t.max_x = 0.;
tick(graphic, false, update_);
return;
}
t.max_x = t.polyline[0].x();
for (int i = 1; i < t.polyline.size(); ++i)
if (t.max_x < t.polyline[i].x())
t.max_x = t.polyline[i].x();
tick(graphic, false, update_);
}
void Graphic::setGraphicProperties(int graphic, const QString & name, const QColor& color, Qt::PenStyle style, double width, bool visible) {
if (graphic < 0 || graphic >= graphics.size()) return;
graphics[graphic].name = name;
graphics[graphic].pen.setColor(color);
graphics[graphic].pen.setStyle(style);
graphics[graphic].pen.setWidth(width);
graphics[graphic].visible = visible;
updateLegend();
}
void Graphic::addGraphic(const QString & name, const QColor & color, Qt::PenStyle style, double width, bool visible) {
graphics << GraphicType(name, color, style, width, visible);
updateLegend();
}
void Graphic::setVisualRect(const QRectF & rect) {
selrect = rect;
isFit = false;
update();
}
void Graphic::setDefaultRect(const QRectF & rect) {
def_rect = rect;
if (isFit) autofit();
}
void Graphic::saveImage() {
QString str = QFileDialog::getSaveFileName(this, tr("Save Image"), ppath, "PNG(*.png);;JPEG(*.jpg *.jpeg);;BMP(*.bmp);;TIFF(*.tiff *.tif);;PPM(*.ppm)");
if (str == "") return;
ppath = str;
QPixmap im(canvas->size());
mupdate = true;
canvas->render(&im);
mupdate = false;
im.save(ppath);
update(true);
}
void Graphic::setOpenGL(bool on) {
#ifdef HAS_GL
isOGL = on;
if (on) {
ui->canvas_raster->hide();
canvas_gl->show();
canvas = canvas_gl;
} else {
canvas_gl->hide();
ui->canvas_raster->show();
canvas = ui->canvas_raster;
}
#else
isOGL = false;
ui->canvas_raster->show();
canvas = ui->canvas_raster;
#endif
/*line_x_min.setParent(canvas);
line_x_max.setParent(canvas);
line_y_min.setParent(canvas);
line_y_max.setParent(canvas);
line_x_min.show();
line_x_max.show();
line_y_min.show();
line_y_max.show();*/
update();
}
void Graphic::update(bool force) {
mupdate = true;
repaintCanvas(force);
mupdate = false;
}
void Graphic::setGraphicsCount(int arg, bool update) {
if (arg < 0) return;
while (graphics.size() < arg)
graphics.append(GraphicType(tr("y(x)"), QColor::fromHsv((graphics.size() * 55) % 360, 255, 255 - qrand() % 115)));
while (graphics.size() > arg) {
delete graphics.back().pb;
graphics.pop_back();
}
if (update) updateLegend();
}
void Graphic::removeGraphic(int arg, bool update) {
if (arg < 0 || arg >= graphics.size()) return;
delete graphics[arg].pb;
graphics.remove(arg);
if (update) updateLegend();
}
/*void Graphic::setHistogramData(const QVector<float> & g, int graphic) {
graphics[graphic].polyline.clear();
if (g.isEmpty()) {
return;
}
QVector<float> data = g;
QVector<int> hist;
int ic = max_int, ci;
double md, cd, min, max, range, cx;
qSort(data);
md = DBL_MAX;
min = max = data[0];
for (int i = 1; i < data.size(); ++i) {
if (min > data[i]) min = data[i];
if (max < data[i]) max = data[i];
cd = qAbs<float>(data[i] - data[i - 1]);
if (md > cd && cd != 0.) md = cd;
}
range = max - min;
md = mdm;
//qDebug() << md << range << ic;
if (md != 0.)
ic = qRound(qMax<double>(qMin<double>(double(ic), range / md), double(min_int)));
md = range / ic;
hist.resize(ic);
foreach (const float & i, data) {
ci = qRound((i - min) / range * double(ic - 1));
//if (ci < 0) ci = 0;
//if (ci >= ic) ci = ic - 1;
hist[ci]++;
}
QPolygonF & cpol(graphics[graphic].polyline);
if (hist.size() == 1 || range == 0.) {
cpol << QPointF(min - 0.5, 0.) << QPointF(min - 0.25, 0.);
cpol << QPointF(min - 0.25, hist[0]) << QPointF(min + 0.25, hist[0]);
cpol << QPointF(min + 0.25, 0.) << QPointF(min + 0.5, 0.);
} else {
cpol << QPointF(min, 0.);
for (int i = 0; i < hist.size(); ++i) {
cx = i * range / ic + min;
cpol << QPointF(cx, hist[i]) << QPointF(cx + md, hist[i]);
}
cpol << QPointF(range + min, 0.);
}
updateGraphics();
}*/
void Graphic::findGraphicsRect(double start_x, double end_x, double start_y, double end_y) {
double cx, cy, maxX, minX, maxY, minY, vx;
bool isRangeX = (start_x != end_x), isRangeY = (start_y != end_y);
// bool isEmpty = true;
//bool fast = true;
bool can_fast = (start_x == 0 && end_x == 0 && start_y == 0 && end_y == 0);
bool anyVisible = false, isTimeLimit = (visible_time > 0.) && !(isRangeX || isRangeY);
bool force_find = (visible_time > 0.) && (history > 0.) && (visible_time < history);
if (force_find) can_fast = false;
// foreach (const GraphicType & t, graphics) {
// const QPolygonF & pol(pause_ ? t.polyline_pause : t.polyline);
// if (!pol.isEmpty()) {
// isEmpty = false;
// break;
// }
// }
// if (isEmpty) {
// grect = def_rect;
// setRectToLines();
// return;
// }
// can_fast = false;
vx = -DBL_MAX;
minY = minX = DBL_MAX;
maxY = maxX = -DBL_MAX;
foreach (const GraphicType & t, graphics) {
if (!t.visible) continue;
if (vx < (pause_ ? t.max_x_pause : t.max_x)) vx = (pause_ ? t.max_x_pause : t.max_x);
}
vx -= visible_time;
//qDebug() << "[Graphic]" << "can_fast" << can_fast;
for (int g = 0; g < graphics.size(); g++) {
GraphicType & t(graphics[g]);
if (!t.visible) continue;
const QPolygonF & pol(pause_ ? t.polyline_pause : t.polyline);
if (pol.isEmpty()) continue;
bool f = true;
//qDebug() << "[Graphic]" << "cvrect:" << t.cvrect << t.cvrect.isNull();
if (t.cvrect.isNull() || !can_fast) {
for (int i = 0; i < pol.size(); i++) {
cx = pol[i].x();
cy = pol[i].y();
if ((start_x > cx || end_x < cx) && isRangeX) continue;
if ((start_y > cy || end_y < cy) && isRangeY) continue;
if ((cx < vx) && isTimeLimit) continue;
if (f) {
t.cvrect.setRect(cx, cy, 0, 0);
f = false;
} else {
if (t.cvrect.top() < cy) t.cvrect.setTop(cy);
if (t.cvrect.bottom() > cy) t.cvrect.setBottom(cy);
if (t.cvrect.right() < cx) t.cvrect.setRight(cx);
if (t.cvrect.left() > cx) t.cvrect.setLeft(cx);
}
//fast = false;
}
if (f) continue;
//qDebug() << "[Graphic]" << "2 cvrect:" << t.cvrect;
}
anyVisible = true;
if (maxY < t.cvrect.top()) maxY = t.cvrect.top();
if (minY > t.cvrect.bottom()) minY = t.cvrect.bottom();
if (maxX < t.cvrect.right()) maxX = t.cvrect.right();
if (minX > t.cvrect.left()) minX = t.cvrect.left();
if (!can_fast) t.cvrect = QRectF();
}
if (!anyVisible) {
//qDebug() << "[Graphic]" << "empty autofit";
grect = def_rect;
setRectToLines();
return;
}
// if (fast) qDebug() << "[Graphic]" << "FAST autofit";
// else qDebug() << "[Graphic]" << "autofit";
if (maxX > limit_.right()) maxX = limit_.right();
if (minX > limit_.right()) minX = limit_.right();
if (minX < limit_.left()) minX = limit_.left();
if (maxX < limit_.left()) maxX = limit_.left();
if (maxY > limit_.bottom()) maxY = limit_.bottom();
if (minY > limit_.bottom()) minY = limit_.bottom();
if (minY < limit_.top()) minY = limit_.top();
if (maxY < limit_.top()) maxY = limit_.top();
if (minX > maxX) qSwap<double>(minX, maxX);
if (minY > maxY) qSwap<double>(minY, maxY);
if (qAbs<double>(minX - maxX) < 1E-60) {minX -= defaultRect().width()/2; maxX += defaultRect().width()/2;}
if (qAbs<double>(minY - maxY) < 1E-60) {minY -= defaultRect().height()/2; maxY += defaultRect().height()/2;}
if (only_expand_x) {
if (minX > eminx) minX = eminx;
if (maxX < emaxx) maxX = emaxx;
}
if (only_expand_y) {
if (minY > eminy) minY = eminy;
if (maxY < emaxy) maxY = emaxy;
}
eminx = minX; emaxx = maxX;
eminy = minY; emaxy = maxY;
if (isRangeX) selrect.setRect(start_x, minY, end_x - start_x, maxY - minY);
else if (isRangeY) selrect.setRect(minX, start_y, maxX - minX, end_y - start_y);
else grect.setRect(minX, minY, maxX - minX, maxY - minY);
grect = grect.normalized();
if (isFit)/* || isRangeX || isRangeY)*/ selrect = grect;
setRectToLines();
}
void Graphic::drawAction() {
//qDebug() << "draw action";
int wid = canvas->width(), hei = canvas->height() - gridborder.y(), sx = startpos.x(), sy = startpos.y(), cx = curpos.x(), cy = curpos.y();
painter->setPen(selpen);
painter->setBrush(selbrush);
switch (curaction) {
case gaZoomInRect: {
QSizeF rsz = QRectF(startpos_r, curpos_r).normalized().size();
painter->drawRect(QRect(startpos, curpos));
fp_size = " x " + pointCoords(QPointF(rsz.width(), rsz.height()));
} break;
case gaZoomRangeX:
painter->drawLine(sx, hei, sx, 0);
painter->drawLine(cx, hei, cx, 0);
painter->fillRect(sx, 0, cx - sx, hei, selbrush);
fp_size = " x " + pointCoords(QPointF(qAbs(startpos_r.x() - curpos_r.x()), 0.), true, false);
break;
case gaZoomRangeY:
painter->drawLine(gridborder.x(), sy, wid, sy);
painter->drawLine(gridborder.x(), cy, wid, cy);
painter->fillRect(gridborder.x(), sy, wid - gridborder.x(), cy - sy, selbrush);
fp_size = " x " + pointCoords(QPointF(0., qAbs(startpos_r.y() - curpos_r.y())), false, true);
break;
default: break;
}
}
void Graphic::drawGrid() {
int gbx = gridborder.x(), gby = gridborder.y(), cwid = canvas->width(), chei = canvas->height() - legy;
double px, py, range, step, start;
int wid = cwid - gbx - 5, hei = chei - gby - 5, cx, cy, cnt;
QRect rect;
QPair<QString, QString> str;
range = selrect.bottom() - selrect.top();
if (grad_y == Graphic::Auto) step = splitRange(range, hei / gridy / font_sz.height() / 1.4);
else step = gridy;//range / hei * gridy;
start = roundTo(canvas2realY(-hei), step) - step;
py = start + step;
cy = 0;
cx = gbx - 5;
grid_pen.setWidth(qMax<int>(qMax<int>(qRound(thick / 1.4), 1), grid_pen.width()));
QFont sf = font();
QFont nf = sf;
sf.setPointSizeF(qMax<qreal>(sf.pointSizeF() / 1.6, 7.));
QFontMetrics fm(nf), sfm(sf);
if (step > 0.) {
cnt = 1000;
while (cnt-- > 0) {
py -= step;
if (fabs(py) < step * .5) py = 0.;
cy = real2canvasY(py);
if (cy < 0) continue;
if (cy > hei + 5) break;
painter->setPen(grid_pen);
painter->drawLine(gbx, cy, cwid, cy);
str = gridMark(py * grid_numbers_y);
painter->setPen(text_color);
cy += font_sz.height() / 4.;
int dx = font_sz.height() / 8.;
if (!str.second.isEmpty()) {
rect = sfm.boundingRect(str.second);
painter->setFont(sf);
painter->drawText(cx - rect.width() - dx, cy - font_sz.height() / 2.5, str.second);
dx += rect.width() + font_sz.height() / 6.;
}
rect = fm.boundingRect(str.first);
painter->setFont(nf);
painter->drawText(cx - rect.width() - dx, cy, str.first);
}
}
cy = real2canvasY(0.);
if (cy >= 0 && cy <= (hei + 5)) {
QPen _p(grid_pen);
_p.setStyle(Qt::SolidLine);
painter->setPen(_p);
painter->drawLine(gbx, cy, cwid, cy);
}
if (hasLblY) {
painter->setPen(text_color);
painter->save();
painter->translate(5, hei);
painter->rotate(-90.);
painter->drawText(0, 0, hei, font_sz.height(), Qt::AlignCenter, label_y);
painter->restore();
}
cy = chei - font_sz.height() / 4;
if (hasLblX) cy -= font_sz.height();
range = selrect.right() - selrect.left();
QString df;
if (axis_type_x == Graphic::Numeric) {
if (grad_x == Graphic::Auto) step = splitRange(range, wid / gridx / font_sz.width() * 1.4);
else step = gridx;//range / wid * gridx;
start = roundTo(canvas2realX(wid), step) + step;
px = start + step;
if (step > 0.) {
cnt = 1000;
while (cnt-- > 0) {
px -= step;
if (fabs(px) < step * .5) px = 0.;
cx = real2canvasX(px);
if (cx > cwid) continue;
if (cx < gbx) break;
painter->setPen(grid_pen);
painter->drawLine(cx, hei + 5, cx, 0);
painter->setPen(text_color);
int dx = -font_sz.height() / 4.;
painter->setFont(nf);
str = gridMark(px * grid_numbers_x);
rect = fm.boundingRect(str.first);
painter->drawText(cx + dx, cy, str.first);
dx += rect.width() + font_sz.height() / 6.;
if (!str.second.isEmpty()) {
rect = sfm.boundingRect(str.second);
painter->setFont(sf);
painter->drawText(cx + dx, cy - font_sz.height() / 4., str.second);
}
}
}
cx = real2canvasX(0.);
if (cx <= cwid && cx >= gbx) {
QPen _p(grid_pen);
_p.setStyle(Qt::SolidLine);
painter->setPen(_p);
painter->drawLine(cx, hei + 5, cx, 0);
}
} else {
int cur_scl[7] = {0,0,0,0,0,0,0};
step = splitRangeDate(range, wid / gridx / font_sz.width() * 1.4, &df, cur_scl);
start = roundTo(canvas2realX(wid), step) + step;
px = start + step;
QDateTime cd = QDateTime::fromMSecsSinceEpoch(px * grid_numbers_x);
//qDebug() << "*** start" << cd << step;
roundDateTime(cd, cur_scl);
//qDebug() << "*** round" << cd;
addDateTime(cd, cur_scl);
//qDebug() << "*** add" << cd;
//qDebug() << "*** cur" << cur_scl[0] << cur_scl[1] << cur_scl[2] << cur_scl[3] << cur_scl[4] << cur_scl[5] << cur_scl[6];
if (step > 0.) {
cnt = 1000;
while (cnt-- > 0) {
addDateTime(cd, cur_scl, -1);
//roundDateTime(cd, cur_scl);
//qDebug() << "next" << cd;
cx = real2canvasX(cd.toMSecsSinceEpoch() / grid_numbers_x);
if (cx > cwid) continue;
if (cx < gbx) {/*qDebug() << cx << "<" << gbx;*/ break;}
painter->setPen(grid_pen);
painter->drawLine(cx, hei + 5, cx, 0);
painter->setPen(text_color);
int dx = -font_sz.height() / 4.;
painter->setFont(nf);
str.first = cd.toString(df);
painter->drawText(cx + dx, cy, str.first);
}
}
}
painter->setPen(text_color);
painter->setFont(nf);
if (hasLblX) {
painter->setPen(text_color);
painter->drawText(gbx, chei - font_sz.height(), wid, font_sz.height(), Qt::AlignCenter, label_x);
}
painter->setPen(QPen(grid_pen.color(), qMax<int>(thick, grid_pen.width())));
painter->drawRect(gbx, -1, wid + 6, hei + 6);
}
QPair<QString, QString> Graphic::gridMark(double v) const {
QPair<QString, QString> ret;
if ((qAbs(v) >= 1E+4 || qAbs(v) <= 1E-4) && v != 0.) {
int p = qFloor(qLn(qAbs(v)) / LN10);
v /= qPow(10., p);
if (v == 10.) {
v = 1.;
p += 1;
}
ret.first = QString::fromUtf8("%1·10").arg(v);
ret.second = QString::number(p);
} else
ret.first = QString::number(v);
return ret;
}
void Graphic::drawGraphics() {
if (isHover)
ui->status->setText(tr("Cursor: ") + pointCoords(canvas2real(QPointF(curpos))));
QPointF srp = -selrect.topLeft();
double sclx, scly, wid = canvas->width(), hei = canvas->height() - legy;
sclx = (wid - gridborder.x() - margins_.left() - margins_.width()) / selrect.width();
scly = (hei - gridborder.y() - margins_.top() - margins_.height()) / selrect.height();
painter->setClipping(true);
painter->setClipRect(QRect(gridborder.x(), 0, wid - gridborder.x(), hei - gridborder.y()));
painter->translate(gridborder.x() + margins_.left(), hei - gridborder.y() - margins_.top());
//if (isOGL && aalias) pen.setWidthF(1.5f);
painter->scale(sclx, -scly);
painter->translate(srp);
QTransform mat = painter->transform();
painter->resetTransform();
painter->setWorldMatrixEnabled(false);
QPolygonF cpol;
QPen pen;
for (int i = 0; i < graphics.size(); ++i) {
GraphicType & t(graphics[i]);
QPolygonF & rpol(pause_ ? t.polyline_pause : t.polyline);
if (t.visible && !rpol.isEmpty()) {
pen = t.pen;
if (qRound(pen.widthF()) == pen.widthF()) pen.setWidth(pen.width()*thick);
else pen.setWidthF(pen.widthF()*thick);
pen.setCosmetic(true);
if (t.lines) {
painter->setPen(pen);
if (t.fill) {
cpol = rpol;
painter->setBrush(t.fill_color);
//cpol.push_front(QPointF(cpol.front().x(), 0.));
//cpol.push_back(QPointF(cpol.back().x(), 0.));
painter->drawPolygon(mat.map(cpol));
} else
painter->drawPolyline(mat.map(rpol));
}
if (t.points) {
if (qRound(t.pointWidth) == t.pointWidth) pen.setWidth(qRound(t.pointWidth*thick));
else pen.setWidthF(t.pointWidth*thick);
painter->setPen(pen);
painter->drawPoints(mat.map(rpol));
}
}
}
painter->setWorldMatrixEnabled(true);
}
QString Graphic::pointCoords(QPointF point, bool x, bool y) {
QString ret = "(";
if (x) {
if (axis_type_x == Numeric)
ret += QString::number(point.x(), 'f', 3);
else
ret += QDateTime::fromMSecsSinceEpoch(point.x()).toString();
}
if (y) {
if (ret.size() > 1) ret += " ; ";
ret += QString::number(point.y(), 'f', 3);
}
ret += ")";
return ret;
}
void Graphic::drawGuides() {
if (!guides || !isHover) return;
int wid = canvas->width(), hei = canvas->height();
painter->setRenderHint(QPainter::Antialiasing, false);
painter->setPen(QPen(grid_pen.color(), qMax<int>(qRound(thick / 1.4), 1)));
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;
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.);
painter->setPen(text_color);
painter->drawText(p, str);
}
void Graphic::drawPause() {
painter->setClipping(false);
painter->save();
painter->resetMatrix();
painter->translate(canvas->width() - icon_pause_b.width() - 6, 6);
double o = (0.5 - pause_phase) * 2;
painter->setOpacity(o*o);
painter->drawImage(0, 0, icon_pause_b);
painter->setOpacity(1.);
painter->drawImage(0, 0, icon_pause_f);
painter->restore();
painter->setClipping(true);
}
double Graphic::splitRange(double range, int count) {
double digits, step, tln;
range = qAbs<double>(range);
tln = qFloor(qLn(range) / LN10);
for (int i = 0; i <= 5; ++i) {
digits = qPow(10., tln - i);
step = qRound(range / count / digits);
if (step > 0.) {
digits = qPow(10., tln - i - 1);
step = qRound(range / count / digits);
break;
}
}
double step5 = qRound(step / 5.) * 5., step10 = qRound(step / 10.) * 10.;
double err5 = qAbs<double>(step - step5), err10 = qAbs<double>(step - step10);
step = (err5 < err10 ? step5 : step10) * digits;
return step;
}
double Graphic::splitRangeDate(double range, int count, QString * format, int step[7]) {
double ret = splitRange(range, count);
//qDebug() << "ret =" << ret << getScaleX();
if (ret < 1000. * 1) {*format = "ss.zzz"; step[0] = ret;}
else if (ret < 1000. * 60) {*format = "h:m:ss"; step[1] = qRound(ret / 1000);}
else if (ret < 1000. * 60 * 60) {*format = "h:mm"; step[2] = qRound(ret / 1000 / 60);}
else if (ret < 1000. * 60 * 60 * 24) {*format = "dd(ddd) hh"; step[3] = qRound(ret / 1000 / 60 / 60);}
else if (ret < 1000. * 60 * 60 * 24 * 30) {*format = "MMM dd"; step[4] = qRound(ret / 1000 / 60 / 60 / 24);}
else if (ret < 1000. * 60 * 60 * 24 * 30 * 12) {*format = "yyyy MMM"; step[5] = qRound(ret / 1000 / 60 / 60 / 24 / 30);}
else {*format = "yyyy"; step[6] = qRound(ret / 1000 / 60 / 60 / 24 / 30 / 12);}
return ret;
}
double Graphic::roundTo(double value, double round_to) {
if (round_to == 0.) return value;
return qRound(value / round_to) * round_to;
}
void Graphic::roundDateTime(QDateTime & dt, int c[7]) {
QDate d(dt.date()); QTime t(dt.time());
//if (c[0] != 0) t.setHMS(t.hour(), t.minute(), t.second(), 0);
if (c[1] != 0) t.setHMS(t.hour(), t.minute(), t.second());
if (c[2] != 0) t.setHMS(t.hour(), t.minute(), 0);
if (c[3] != 0) t.setHMS(t.hour(), 0, 0);
if (c[4] != 0) {t.setHMS(0, 0, 0); d.setDate(d.year(), d.month(), d.day());}
if (c[5] != 0) {t.setHMS(0, 0, 0); d.setDate(d.year(), d.month(), 1);}
if (c[6] != 0) {t.setHMS(0, 0, 0); d.setDate(d.year(), 1, 1);}
dt = QDateTime(d, t);
}
void Graphic::addDateTime(QDateTime & dt, int c[7], int mul) {
if (c[0] != 0) dt = dt.addMSecs(mul * c[0]);
if (c[1] != 0) dt = dt.addSecs(mul * c[1]);
if (c[2] != 0) dt = dt.addSecs(mul * c[2] * 60);
if (c[3] != 0) dt = dt.addSecs(mul * c[3] * 60 * 60);
if (c[4] != 0) dt = dt.addDays(mul * c[4]);
if (c[5] != 0) dt = dt.addMonths(mul * c[5]);
if (c[6] != 0) dt = dt.addYears(mul * c[6]);
}
double Graphic::canvas2realX(double px) const {
int gbx = gridborder.x() + margins_.left(), cwid = lastw, wid = cwid - gbx - margins_.width();
double cx = px - gbx, sclx = selrect.width() / (double)wid;
return cx * sclx + selrect.x();
}
double Graphic::canvas2realY(double py) const {
int gby = gridborder.y() + margins_.top(), chei = lasth - legy, hei = chei - gby - margins_.height();
double cy = chei - py - gby, scly = selrect.height() / (double)hei;
return cy * scly + selrect.y();
}
double Graphic::real2canvasX(double px) const {
int gbx = gridborder.x() + margins_.left(), cwid = lastw, wid = cwid - gbx - margins_.width();
double sclx = selrect.width() / (double)wid;
return (px - selrect.x()) / sclx + gbx;
}
double Graphic::real2canvasY(double py) const {
int gby = gridborder.y() + margins_.top(), chei = lasth - legy, hei = chei - gby - margins_.height();
double scly = selrect.height() / (double)hei;
return chei - gby - (py - selrect.y()) / scly;
}
QPolygonF Graphic::real2canvas(const QPolygonF & real_polygon) const {
QPolygonF ret;
for (int i=0; i<real_polygon.size(); ++i)
ret << real2canvas(real_polygon[i]);
return ret;
}
QPolygonF Graphic::canvas2real(const QPolygonF & canvas_polygon) const {
QPolygonF ret;
for (int i=0; i<canvas_polygon.size(); ++i)
ret << canvas2real(canvas_polygon[i]);
return ret;
}
void Graphic::setCurrentAction(GraphicAction action) {
curaction = action;
switch (action) {
case gaNone:
if (guides) setCanvasCursor(Qt::BlankCursor);
else setCanvasCursor(Qt::ArrowCursor);
break;
case gaZoomInRect:
setCanvasCursor(Qt::CrossCursor);
break;
case gaZoomRangeX:
setCanvasCursor(Qt::SplitHCursor);
break;
case gaZoomRangeY:
setCanvasCursor(Qt::SplitVCursor);
break;
case gaMove:
setCanvasCursor(Qt::SizeAllCursor);
break;
}
}
void Graphic::setCanvasCursor(QCursor cursor) {
ui->canvas_raster->setCursor(cursor);
#ifdef HAS_GL
canvas_gl->setCursor(cursor);
#endif
}
void Graphic::swapToBuffer() {
QImage timg;
//qDebug() << "render start";
#ifdef HAS_GL
if (isOGL) {
timg = canvas_gl->grabFrameBuffer();
QPainter p(buffer);
p.drawImage(0, 0, timg);
p.end();
}
#endif
//qDebug() << "render finish";
bufferActive = true;
}
void Graphic::setRectToLines() {
is_lines_update = true;
//line_x_min.is_auto = line_x_max.is_auto = line_y_min.is_auto = line_y_max.is_auto = true;
//qDebug() << "set to lines" << selrect;
//line_x_min.is_reset = line_x_max.is_reset = line_y_min.is_reset = line_y_max.is_reset = isFit;
if (line_x_min.isVisible() && line_x_max.isVisible() && line_y_min.isVisible() && line_y_max.isVisible()) {
line_x_min.blockSignals(true); line_x_max.blockSignals(true); line_y_min.blockSignals(true); line_y_max.blockSignals(true);
if (!line_x_min.hasFocus()) {
if (isFit) line_x_min.setValue(grect.left());
else line_x_min.setValue(selrect.left());
}
if (!line_x_max.hasFocus()) {
if(isFit) line_x_max.setValue(grect.right());
else line_x_max.setValue(selrect.right());
}
if (!line_y_min.hasFocus()) {
if(isFit) line_y_min.setValue(grect.bottom());
else line_y_min.setValue(selrect.bottom());
}
if (!line_y_max.hasFocus()) {
if(isFit) line_y_max.setValue(grect.top());
else line_y_max.setValue(selrect.top());
}
line_x_min.setDefaultText(QString::number(grect.left()).toUpper());
line_x_max.setDefaultText(QString::number(grect.right()).toUpper());
line_y_min.setDefaultText(QString::number(grect.bottom()).toUpper());
line_y_max.setDefaultText(QString::number(grect.top()).toUpper());
line_x_min.blockSignals(false); line_x_max.blockSignals(false); line_y_min.blockSignals(false); line_y_max.blockSignals(false);
// if(isFit) {
// line_y_min.setValue(grect.left());
// line_y_max.setValue(grect.left());
// }
}
//line_x_min.is_auto = line_x_max.is_auto = line_y_min.is_auto = line_y_max.is_auto = false;
is_lines_update = false;
}
void Graphic::checkLines() {
isFit = (line_x_min.isCleared() && line_x_max.isCleared() && line_y_min.isCleared() && line_y_max.isCleared());
update(true);
}
void Graphic::tick(int index, bool slide, bool update_) {
if (slide) {
///mutex.lock();
GraphicType & t(graphics[index]);
if (history > 0.)
while (t.polyline.size() > 1) {
if (fabs(t.polyline.back().x() - t.polyline.front().x()) <= history) break;
/// TODO: [Graphic] fast autofit while addPoint(double y, ...)
if (!t.cvrect.isNull()) {
QPointF fp(t.polyline.first());
if (qFuzzyCompare(t.cvrect.left(), fp.x()) ||
qFuzzyCompare(t.cvrect.right(), fp.x()) ||
qFuzzyCompare(t.cvrect.top(), fp.y()) ||
qFuzzyCompare(t.cvrect.bottom(), fp.y())) {
t.cvrect = QRectF();
}
}
t.polyline.pop_front();
}
}
if (!update_) {
if (isFit) findGraphicsRect();
///mutex.unlock();
return;
}
//polyline.push_back(QPointF(brick->time_, brick->output(port)));
//cout << polyline.size() << endl;
if (isFit) findGraphicsRect();
if (!slide) {
if (aupdate) update();
return;
}
///mutex.unlock();
if (aupdate) update();
}
void Graphic::on_buttonAutofit_clicked() {
isFit = true;
bool isEmpty = true;
foreach (const GraphicType & t, graphics) {
const QPolygonF & pol(pause_ ? t.polyline_pause : t.polyline);
if (!pol.isEmpty()) {
isEmpty = false;
break;
}
}
if (isEmpty) grect = def_rect;
selrect = grect;
findGraphicsRect();
update();
}
void Graphic::on_buttonConfigure_clicked() {
conf->graphicItems.clear();
for (int i = 0; i < graphics.size(); i++) {
GraphicConf::GraphicItem item;
item.icon = graphics[i].icon;
item.name = graphics[i].name;
conf->graphicItems.append(item);
}
conf->ui->colorGrid->setColor(grid_pen.color());
conf->ui->comboStyleGrid->setCurrentIndex((int)grid_pen.style());
conf->ui->spinWidthGrid->setValue(grid_pen.widthF());
conf->ui->checkOGL->setChecked(isOGL);
conf->ui->checkAAlias->setChecked(aalias);
conf->ui->checkInputs->setChecked(borderInputsVisible());
conf->ui->checkStatus->setChecked(statusVisible());
conf->ui->checkLegend->setChecked(legendVisible());
conf->ui->checkGridAutoX->setChecked(grad_x == Auto);
conf->ui->checkGridAutoY->setChecked(grad_y == Auto);
conf->ui->colorBackground->setColor(back_color);
conf->ui->colorText->setColor(text_color);
conf->ui->spinGridStepX->setValue(gridx);
conf->ui->spinGridStepY->setValue(gridy);
conf->ui->spinMarginL->setValue(margins_.left());
conf->ui->spinMarginT->setValue(margins_.height());
conf->ui->spinMarginR->setValue(margins_.width());
conf->ui->spinMarginB->setValue(margins_.top());
conf->readParams();
if (conf->exec() == QDialog::Rejected) return;
grid_pen = QPen(conf->ui->colorGrid->color(), conf->ui->spinWidthGrid->value(), (Qt::PenStyle)conf->ui->comboStyleGrid->currentIndex());
back_color = conf->ui->colorBackground->color();
text_color = conf->ui->colorText->color();
grad_x = conf->ui->checkGridAutoX->isChecked() ? Auto : Fixed;
grad_y = conf->ui->checkGridAutoY->isChecked() ? Auto : Fixed;
gridx = conf->ui->spinGridStepX->value();
gridy = conf->ui->spinGridStepY->value();
setOpenGL(conf->ui->checkOGL->isChecked());
setAntialiasing(conf->ui->checkAAlias->isChecked());
setBorderInputsVisible(conf->ui->checkInputs->isChecked());
setStatusVisible(conf->ui->checkStatus->isChecked());
setLegendVisible(conf->ui->checkLegend->isChecked());
setMargins(conf->ui->spinMarginL->value(), conf->ui->spinMarginR->value(), conf->ui->spinMarginT->value(), conf->ui->spinMarginB->value());
updateLegend();
update();
}
void Graphic::on_checkGuides_toggled(bool checked) {
guides = checked;
if (guides) setCanvasCursor(Qt::BlankCursor);
else setCanvasCursor(Qt::ArrowCursor);
update();
}
void Graphic::updateLegend(bool es) {
QPixmap pix(60, 22);
for (int i = 0; i < graphics.size(); i++) {
pix.fill(back_color);
QPainter p(&pix);
QPen pen = graphics[i].pen;
if (qRound(pen.widthF()) == pen.widthF()) pen.setWidth(pen.width()*thick);
else pen.setWidthF(pen.widthF()*thick);
p.setPen(pen);
p.drawLine(0, pix.height() / 2, pix.width(), pix.height() / 2);
p.end();
graphics[i].icon = QIcon(pix);
}
if (!ui->widgetLegend->isVisibleTo(this)) {
if (es) emit graphicSettingsChanged();
// qDebug() << "skip updateLegend";
return;
}
// qDebug() << "updateLegend" << graphics.size();
leg_update = false;
int ps = 100;
for (int r = 0; r < ui->layoutLegend->rowCount(); ++r)
for (int c = 0; c < ui->layoutLegend->columnCount(); ++c) {
QLayoutItem * li = ui->layoutLegend->itemAtPosition(r, c);
if (!li) continue;
if (!li->widget()) continue;
while (li->widget()->actions().isEmpty())
li->widget()->removeAction(li->widget()->actions()[0]);
delete li->widget();
}
ui->layoutLegend->invalidate();
for (int i = 0; i < graphics.size(); i++) {
graphics[i].pb = new QCheckBox(graphics[i].name);
graphics[i].pb->setIconSize(pix.size());
//graphics[i].pb->setFlat(true);
graphics[i].pb->setIcon(graphics[i].icon);
graphics[i].pb->setChecked(graphics[i].visible);
graphics[i].pb->setProperty("graphic_num", i);
graphics[i].pb->setContextMenuPolicy(Qt::ActionsContextMenu);
//qDebug() << graphics[i].pb->actions();
QAction * act = new QAction(trUtf8("Check all"), 0);
act->setCheckable(true);
act->setChecked(true);
graphics[i].pb->addAction(act);
connect(act, SIGNAL(triggered(bool)), this, SLOT(graphicAllVisibleChange(bool)));
connect(graphics[i].pb, SIGNAL(toggled(bool)), this, SLOT(graphicVisibleChange(bool)));
int cps = graphics[i].pb->sizeHint().width() + 4;
if (cps > ps) ps = cps;
}
int maxcol = qMax<int>(ui->widgetLegend->width() / ps - 1, 1);
int row = 0, col = 0;
bool lv = ui->widgetLegend->isVisibleTo(this);
ui->widgetLegend->hide();
for (int i = 0; i < graphics.size(); i++) {
ui->layoutLegend->addWidget(graphics[i].pb,row,col);
graphics[i].pb->show();
col++;
if (col > maxcol) {col = 0; row++;}
}
ui->widgetLegend->setVisible(lv);
leg_update = true;
if (es) emit graphicSettingsChanged();
}
void Graphic::updateLegendChecks() {
for (int i = 0; i < graphics.size(); i++) {
if (!graphics[i].pb) continue;
bool pbs = graphics[i].pb->blockSignals(true);
graphics[i].pb->setChecked(graphics[i].visible);
graphics[i].pb->blockSignals(pbs);
}
emit graphicSettingsChanged();
}
void Graphic::graphicVisibleChange(bool checked) {
if (visible_update) return;
QCheckBox * cb = qobject_cast<QCheckBox*>(sender());
int i = cb->property("graphic_num").toInt();
graphics[i].visible = checked;
if (isFit) on_buttonAutofit_clicked();
else update();
emit graphicSettingsChanged();
// update();
}
void Graphic::graphicAllVisibleChange(bool checked) {
visible_update = true;
for (int i=0; i<graphics.size(); i++) {
graphics[i].visible = checked;
graphics[i].pb->setChecked(checked);
}
visible_update = false;
if (isFit) on_buttonAutofit_clicked();
else update();
emit graphicSettingsChanged();
}
void Graphic::enterFullscreen() {
if (fullscr) return;
ui->layoutCanvas->removeWidget(canvas);
canvas->setParent(0);
canvas->showFullScreen();
canvas->setFocus();
canvas->raise();
fullscr = true;
}
void Graphic::leaveFullscreen() {
if (!fullscr) return;
canvas->setWindowFlags(canvas->windowFlags() & ~Qt::WindowFullScreen);
ui->layoutCanvas->addWidget(canvas);
canvas->show();
fullscr = false;
}
QString Graphic::caption() const {
return ui->labelCaption->text();
}
bool Graphic::borderInputsVisible() const {
return ui->widgetLX->isVisible();
}
bool Graphic::statusVisible() const {
return ui->status->isVisible();
}
bool Graphic::legendVisible() const {
return ui->widgetLegend->isVisible();
}
QByteArray Graphic::save() {
// QByteArray ba;
// QDataStream s(&ba, QIODevice::ReadWrite);
// s << openGL() << antialiasing() << borderInputsVisible() << statusVisible() << legendVisible();
// s << graphics;
// return ba;
// version '2':
ChunkStream cs;
cs.add(1, antialiasing()).add(2, openGL()).add(3, borderInputsVisible()).add(4, statusVisible()).add(5, legendVisible());
cs.add(6, backgroundColor()).add(7, textColor()).add(8, margins());
cs.add(9, gridPen()).add(10, graduationX()).add(11, graduationY()).add(12, graduationStepX()).add(13, graduationStepY());
cs.add(14, graphics);
cs.add(15, isFit).add(16, visualRect());
return cs.data().prepend('2');
}
void Graphic::load(QByteArray ba) {
if (ba.isEmpty()) return;
char ver = ba[0];
//qDebug() << "load" << (int)ver;
switch(ver) {
case '2': {// version '2':
ba.remove(0, 1);
QRectF vrect;
ChunkStream cs(ba);
while (!cs.atEnd()) {
switch (cs.read()) {
case 1: setAntialiasing(cs.getData<bool>()); break;
case 2: setOpenGL(cs.getData<bool>()); break;
case 3: setBorderInputsVisible(cs.getData<bool>()); break;
case 4: setStatusVisible(cs.getData<bool>()); break;
case 5: setLegendVisible(cs.getData<bool>()); break;
case 6: setBackgroundColor(cs.getData<QColor>()); break;
case 7: setTextColor(cs.getData<QColor>()); break;
case 8: setMargins(cs.getData<QRect>()); break;
case 9: setGridPen(cs.getData<QPen>()); break;
case 10: setGraduationX(cs.getData<Graduation>()); break;
case 11: setGraduationY(cs.getData<Graduation>()); break;
case 12: setGraduationStepX(cs.getData<double>()); break;
case 13: setGraduationStepY(cs.getData<double>()); break;
case 14: graphics = cs.getData<QVector<GraphicType> >(); break;
case 15: isFit = cs.getData<bool>(); break;
case 16: vrect = cs.getData<QRectF>(); break;
default: break;
}
}
if (!isFit) setVisualRect(vrect);
} break;
default: {// old version 0:
QDataStream s(ba);
bool a;
s >> a; setOpenGL(a);
s >> a; setAntialiasing(a);
s >> a; setBorderInputsVisible(a);
s >> a; setStatusVisible(a);
s >> a;
s >> graphics;
setLegendVisible(a);
} break;
}
}
void Graphic::setCaption(const QString & str) {
ui->labelCaption->setText(str);
ui->labelCaption->setVisible(str.length() > 0);
if (aupdate) update();
}
void Graphic::setGridEnabled(bool enabled) {
ui->checkGrid->setChecked(enabled);
}
void Graphic::setBorderInputsVisible(bool visible) {
ui->widgetLX->setVisible(visible);
ui->widgetLY->setVisible(visible);
ui->checkBorderInputs->setChecked(visible);
if (visible) setRectToLines();
}
void Graphic::setStatusVisible(bool visible) {
ui->status->setVisible(visible);
}
void Graphic::setLegendVisible(bool visible) {
ui->widgetLegend->setVisible(visible);
ui->checkLegend->setChecked(visible);
updateLegend();
}
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) {
only_expand_x = checked;
ui->checkExpandX->setIcon(checked ? icon_exp_x : icon_exp_sx);
}

455
test/qad/graphic/graphic.h Normal file
View File

@@ -0,0 +1,455 @@
#ifndef GRAPHIC_H
#define GRAPHIC_H
#include <QWidget>
#include <QPainter>
#include <QPixmap>
#include <QMouseEvent>
#include <QComboBox>
///#include <QMutex>
#include <QDebug>
#include <QGridLayout>
#include <QFileDialog>
#include <QTime>
#include <QTranslator>
#include <QGestureEvent>
#include <qmath.h>
#include <float.h>
#include "graphic_conf.h"
#include "evalspinbox.h"
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
namespace Ui {
class Graphic;
}
class UGLWidget;
class Graphic: public QFrame
{
Q_OBJECT
Q_FLAGS(Buttons)
Q_ENUMS(Alignment Graduation AxisType)
Q_PROPERTY(QString caption READ caption WRITE setCaption)
Q_PROPERTY(QString labelX READ labelX WRITE setLabelX)
Q_PROPERTY(QString labelY READ labelY WRITE setLabelY)
Q_PROPERTY(QColor backgroundColor READ backgroundColor WRITE setBackgroundColor)
Q_PROPERTY(QColor textColor READ textColor WRITE setTextColor)
Q_PROPERTY(int currentGraphic READ currentGraphic WRITE setCurrentGraphic)
Q_PROPERTY(int graphicsCount READ graphicsCount WRITE setGraphicsCount)
Q_PROPERTY(QString graphicName READ graphicName WRITE setGraphicName)
Q_PROPERTY(QPen graphicPen READ graphicPen WRITE setGraphicPen)
Q_PROPERTY(QColor graphicColor READ graphicColor WRITE setGraphicColor)
Q_PROPERTY(Qt::PenStyle graphicStyle READ graphicStyle WRITE setGraphicStyle)
Q_PROPERTY(double graphicLineWidth READ graphicLineWidth WRITE setGraphicLineWidth)
Q_PROPERTY(double graphicPointWidth READ graphicPointWidth WRITE setGraphicPointWidth)
Q_PROPERTY(QColor graphicFillColor READ graphicFillColor WRITE setGraphicFillColor)
Q_PROPERTY(bool graphicLinesEnabled READ graphicLinesEnabled WRITE setGraphicLinesEnabled)
Q_PROPERTY(bool graphicPointsEnabled READ graphicPointsEnabled WRITE setGraphicPointsEnabled)
Q_PROPERTY(bool graphicFillEnabled READ graphicFillEnabled WRITE setGraphicFillEnabled)
Q_PROPERTY(bool gridEnabled READ gridEnabled WRITE setGridEnabled)
Q_PROPERTY(QPen gridPen READ gridPen WRITE setGridPen)
Q_PROPERTY(QColor gridColor READ gridColor WRITE setGridColor)
Q_PROPERTY(Qt::PenStyle gridStyle READ gridStyle WRITE setGridStyle)
Q_PROPERTY(QPen selectionPen READ selectionPen WRITE setSelectionPen)
Q_PROPERTY(QColor selectionColor READ selectionColor WRITE setSelectionColor)
Q_PROPERTY(Qt::PenStyle selectionStyle READ selectionStyle WRITE setSelectionStyle)
Q_PROPERTY(QBrush selectionBrush READ selectionBrush WRITE setSelectionBrush)
Q_PROPERTY(Alignment buttonsPosition READ buttonsPosition WRITE setButtonsPosition)
Q_PROPERTY(Buttons buttons READ buttons WRITE setButtons)
Q_PROPERTY(bool navigationEnabled READ navigationEnabled WRITE setNavigationEnabled)
Q_PROPERTY(bool openGL READ openGL WRITE setOpenGL)
Q_PROPERTY(bool antialiasing READ antialiasing WRITE setAntialiasing)
Q_PROPERTY(bool autoUpdate READ autoUpdate WRITE setAutoUpdate)
Q_PROPERTY(bool borderInputsVisible READ borderInputsVisible WRITE setBorderInputsVisible)
Q_PROPERTY(bool statusVisible READ statusVisible WRITE setStatusVisible)
Q_PROPERTY(bool legendVisible READ legendVisible WRITE setLegendVisible)
Q_PROPERTY(bool paused READ paused WRITE setPaused)
Q_PROPERTY(bool onlyExpandY READ onlyExpandY WRITE setOnlyExpandY)
Q_PROPERTY(bool onlyExpandX READ onlyExpandX WRITE setOnlyExpandX)
Q_PROPERTY(bool gesturesNavigation READ gesturesNavigation WRITE setGesturesNavigation)
Q_PROPERTY(double historySize READ historySize WRITE setHistorySize)
Q_PROPERTY(double maxVisibleTime READ maxVisibleTime WRITE setMaxVisibleTime)
Q_PROPERTY(double autoXIncrement READ autoXIncrement WRITE setAutoXIncrement)
Q_PROPERTY(QRectF limit READ limit WRITE setLimit)
Q_PROPERTY(QRect margins READ margins WRITE setMargins)
Q_PROPERTY(QRectF visualRect READ visualRect WRITE setVisualRect)
Q_PROPERTY(QRectF defaultRect READ defaultRect WRITE setDefaultRect)
Q_PROPERTY(int minimumRepaintInterval READ minimumRepaintInterval WRITE setMinimumRepaintInterval)
Q_PROPERTY(double gridNumbersMultiplierX READ gridNumbersMultiplierX WRITE setGridNumbersMultiplierX)
Q_PROPERTY(double gridNumbersMultiplierY READ gridNumbersMultiplierY WRITE setGridNumbersMultiplierY)
Q_PROPERTY(Graduation graduationX READ graduationX WRITE setGraduationX)
Q_PROPERTY(Graduation graduationY READ graduationY WRITE setGraduationY)
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(int histogramMinIntervals READ histogramMinIntervals WRITE setHistogramMinIntervals)
Q_PROPERTY(int histogramMaxIntervals READ histogramMaxIntervals WRITE setHistogramMaxIntervals)
Q_PROPERTY(double histogramMinDeltaMultiplier READ histogramMinDeltaMultiplier WRITE setHistogramMinDeltaMultiplier)
Q_PROPERTY(Graphic::GraphicsData graphicsData READ graphicsData WRITE setGraphicsData)
Q_PROPERTY(QByteArray graphicsDataRaw READ graphicsDataRaw WRITE setGraphicsDataRaw)
public:
Graphic(QWidget * parent = 0);
~Graphic();
typedef QVector<QVector<QPointF> > GraphicsData;
enum GraphicAction {gaNone, gaZoomInRect, gaZoomRangeX, gaZoomRangeY, gaMove};
enum Button {NoButtons = 0x0,
AllButtons = 0xFFFFFFFF,
Autofit = 0x01,
Grid = 0x02,
CursorAxis = 0x04,
OnlyExpandY = 0x08,
OnlyExpandX = 0x10,
Fullscreen = 0x20,
BorderInputs = 0x40,
Legend = 0x80,
Configure = 0x100,
Save = 0x200,
Clear = 0x800,
Close = 0x1000,
Pause = 0x2000,
StandartButtons = 0x2FFF
};
enum Alignment {Left, Right};
enum Graduation {Auto, Fixed};
enum AxisType {Numeric, DateTime};
Q_DECLARE_FLAGS(Buttons, Button)
QString caption() const;
QString labelX() const {return label_x;}
QString labelY() const {return label_y;}
QString graphicName() const {return graphics[curGraphic].name;}
QColor backgroundColor() const {return back_color;}
QColor textColor() const {return text_color;}
QColor graphicColor() const {return graphics[curGraphic].pen.color();}
QColor gridColor() const {return grid_pen.color();}
QColor selectionColor() const {return selpen.color();}
Qt::PenStyle graphicStyle() const {return graphics[curGraphic].pen.style();}
Qt::PenStyle gridStyle() const {return grid_pen.style();}
Qt::PenStyle selectionStyle() const {return selpen.style();}
double graphicLineWidth() const {return graphics[curGraphic].pen.widthF();}
double graphicPointWidth() const {return graphics[curGraphic].pointWidth;}
QColor graphicFillColor() const {return graphics[curGraphic].fill_color;}
bool graphicVisible() const {return graphics[curGraphic].visible;}
bool graphicLinesEnabled() const {return graphics[curGraphic].lines;}
bool graphicPointsEnabled() const {return graphics[curGraphic].points;}
bool graphicFillEnabled() const {return graphics[curGraphic].fill;}
QPen graphicPen() const {return graphics[curGraphic].pen;}
QPen gridPen() const {return grid_pen;}
QPen selectionPen() const {return selpen;}
QBrush selectionBrush() const {return selbrush;}
bool navigationEnabled() const {return navigation;}
bool openGL() const {return isOGL;}
bool antialiasing() const {return aalias;}
bool autoUpdate() const {return aupdate;}
bool gridEnabled() const {return grid;}
bool borderInputsVisible() const;
bool statusVisible() const;
bool legendVisible() const;
bool paused() const {return pause_;}
bool onlyExpandY() const {return only_expand_y;}
bool onlyExpandX() const {return only_expand_x;}
bool gesturesNavigation() const {return gestures;}
bool isAutofitted() const {return isFit;}
int currentGraphic() const {return curGraphic;}
int graphicsCount() const {return graphics.size();}
Graphic::Buttons buttons() const {return buttons_;}
Graphic::Alignment buttonsPosition() const {return align;}
double historySize() const {return history;}
double maxVisibleTime() const {return visible_time;}
double autoXIncrement() const {return inc_x;}
QRectF visualRect() const {return selrect;}
QRectF defaultRect() const {return def_rect;}
QRectF limit() const {return limit_;}
QRect margins() const {return margins_;}
int minimumRepaintInterval() const {return min_repaint_int;}
int histogramMinIntervals() const {return min_int;}
int histogramMaxIntervals() const {return max_int;}
double histogramMinDeltaMultiplier() const {return mdm;}
double gridNumbersMultiplierX() const {return grid_numbers_x;}
double gridNumbersMultiplierY() const {return grid_numbers_y;}
Graduation graduationX() const {return grad_x;}
Graduation graduationY() const {return grad_y;}
double graduationStepX() const {return gridx;}
double graduationStepY() const {return gridy;}
AxisType axisType() const {return axis_type_x;}
QVector<QPointF> graphicData(const int index = 0) const {return graphics[index].polyline;}
GraphicsData graphicsData() const;
QByteArray graphicsDataRaw() const;
QWidget * viewport() const {return canvas;}
QByteArray save();
void load(QByteArray ba);
///void lock() {mutex_.lock();}
///void unlock() {mutex_.unlock();}
///void reset() {mutex.lock(); clear(); mutex.unlock();}
void reset() {clear();}
GraphicType graphic(int arg) {if (arg < 0 || arg >= graphics.size()) return GraphicType(); return graphics[arg];}
const QVector<GraphicType> & allGraphics() const {return graphics;}
void setAllGraphics(const QVector<GraphicType> & g, bool update = true) {graphics = g; if (update) updateLegend();}
// void setHistogramData(const QVector<float> & g, int graphic);
// void setHistogramData(const QVector<float> & g) {setHistogramData(g, curGraphic);}
double canvas2realX(double px) const;
double canvas2realY(double py) const;
double real2canvasX(double px) const;
double real2canvasY(double py) const;
QPointF canvas2real(QPointF canvas_point) const {return QPointF(canvas2realX(canvas_point.x()), canvas2realY(canvas_point.y()));}
QPointF real2canvas(QPointF real_point) const {return QPointF(real2canvasX(real_point.x()), real2canvasY(real_point.y()));}
QPolygonF real2canvas(const QPolygonF & real_polygon) const;
QPolygonF canvas2real(const QPolygonF & canvas_polygon) const;
double getScaleX() const {return real2canvasX(1.) - real2canvasX(0.);}
double getScaleY() const {return real2canvasY(1.) - real2canvasY(0.);}
QPointF getScale() const {return QPointF(getScaleX(), getScaleY());}
public slots:
void setCaption(const QString & str);
void setLabelX(const QString & str) {label_x = str; hasLblX = (str.length() > 0); if (aupdate) update();}
void setLabelY(const QString & str) {label_y = str; hasLblY = (str.length() > 0); if (aupdate) update();}
void setGraphicName(const QString & str, int index) {graphics[index].name = str; updateLegend(); if (aupdate) update();}
void setGraphicName(const QString & str) {graphics[curGraphic].name = str; updateLegend(); if (aupdate) update();}
void setBackgroundColor(const QColor & color) {back_color = color; if (aupdate) update(); updateLegend();}
void setTextColor(const QColor & color) {text_color = color; if (aupdate) update();}
void setGraphicColor(const QColor & color, int index) {graphics[index].pen.setColor(color); updateLegend(); if (aupdate) update();}
void setGraphicColor(const QColor & color) {setGraphicColor(color, curGraphic);}
void setGridColor(const QColor & color) {grid_pen.setColor(color); if (aupdate) update();}
void setSelectionColor(const QColor & color) {selpen.setColor(color);}
void setGraphicStyle(const Qt::PenStyle & style) {graphics[curGraphic].pen.setStyle(style); updateLegend(); if (aupdate) update();}
void setGridStyle(const Qt::PenStyle & style) {grid_pen.setStyle(style); if (aupdate) update();}
void setSelectionStyle(const Qt::PenStyle & style) {selpen.setStyle(style);}
void setGraphicVisible(bool visible, int index) {graphics[index].visible = visible; updateLegendChecks(); if (aupdate) update();}
void setGraphicVisible(bool visible) {setGraphicVisible(visible, curGraphic);}
void setGraphicLineWidth(double w, int index) {if (qRound(w) == w) graphics[index].pen.setWidth(qRound(w)); else graphics[index].pen.setWidthF(w); updateLegend(); if (aupdate) update();}
void setGraphicLineWidth(double w) {setGraphicLineWidth(w, curGraphic);}
void setGraphicPointWidth(double w, int index) {graphics[index].pointWidth = w; updateLegend(); if (aupdate) update();}
void setGraphicPointWidth(double w) {setGraphicPointWidth(w, curGraphic);}
void setGraphicFillColor(const QColor & w, int index) {graphics[index].fill_color = w; updateLegend(); if (aupdate) update();}
void setGraphicFillColor(const QColor & w) {setGraphicFillColor(w, curGraphic);}
void setGraphicLinesEnabled(bool w, int index) {graphics[index].lines = w; updateLegend(); if (aupdate) update();}
void setGraphicLinesEnabled(bool w) {setGraphicLinesEnabled(w, curGraphic);}
void setGraphicPointsEnabled(bool w, int index) {graphics[index].points = w; updateLegend(); if (aupdate) update();}
void setGraphicPointsEnabled(bool w) {setGraphicPointsEnabled(w, curGraphic);}
void setGraphicFillEnabled(bool w, int index) {graphics[index].fill = w; updateLegend(); if (aupdate) update();}
void setGraphicFillEnabled(bool w) {setGraphicFillEnabled(w, curGraphic);}
void setGraphicPen(const QPen & pen, int index) {graphics[index].pen = pen; updateLegend(); if (aupdate) update();}
void setGraphicPen(const QPen & pen) {setGraphicPen(pen, curGraphic);}
void setGridPen(const QPen & pen) {grid_pen = pen; if (aupdate) update();}
void setSelectionPen(const QPen & pen) {selpen = pen;}
void setSelectionBrush(const QBrush & brush) {selbrush = brush;}
void setNavigationEnabled(bool on) {navigation = on;}
void setOpenGL(bool on);
void setAntialiasing(bool enabled);
void setAutoUpdate(bool enabled) {aupdate = enabled;}
void setGridEnabled(bool enabled);
void setBorderInputsVisible(bool visible);
void setStatusVisible(bool visible);
void setLegendVisible(bool visible);
void setPaused(bool yes);
void setButtons(Graphic::Buttons b);
void setButtonsPosition(Graphic::Alignment a);
void setHistorySize(double val);
void setMaxVisibleTime(double val) {visible_time = val;}
void setAutoXIncrement(double val) {inc_x = val;}
void setLimit(const QRectF & val) {limit_ = val;}
void setMargins(const QRect & val) {margins_ = val; update();}
void setMargins(int left_, int right_, int top_, int bottom_) {setMargins(QRect(left_, bottom_, right_, top_));}
void setLeftMargin(int value) {margins_.moveLeft(value); setMargins(margins_);}
void setRightMargin(int value) {margins_.setWidth(value); setMargins(margins_);}
void setTopMargin(int value) {margins_.setHeight(value); setMargins(margins_);}
void setBottomMargin(int value) {margins_.moveTop(value); setMargins(margins_);}
void setMinimumRepaintInterval(const int & val) {min_repaint_int = val;}
void setOnlyExpandY(bool yes);
void setOnlyExpandX(bool yes);
void setGesturesNavigation(bool yes);
void setHistogramMinIntervals(int value) {min_int = value; updateGraphics();}
void setHistogramMaxIntervals(int value) {max_int = value; updateGraphics();}
void setHistogramMinDeltaMultiplier(double value) {mdm = value; updateGraphics();}
void setGraphicsData(const GraphicsData & gd);
void setGraphicsDataRaw(const QByteArray & ba);
void setGridNumbersMultiplierX(double value) {grid_numbers_x = value; updateGraphics();}
void setGridNumbersMultiplierY(double value) {grid_numbers_y = value; updateGraphics();}
void setGraduationX(Graduation value) {grad_x = value; if (aupdate) update();;}
void setGraduationY(Graduation value) {grad_y = value; if (aupdate) update();;}
void setGraduationStepX(double sx) {gridx = sx; if (aupdate) update();}
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 addPoint(const QPointF & p, int graphic, bool update_ = true);
void addPoint(const QPointF & p, bool update = true) {addPoint(p, curGraphic, update);}
void addPoint(double x, double y, int graphic, bool update = true) {addPoint(QPointF(x, y), graphic, update);}
void addPoint(double x, double y, bool update = true) {addPoint(QPointF(x, y), update);}
void addPoint(double y, int graphic, bool update = true) {if (graphics[graphic].polyline.isEmpty()) addPoint(QPointF(0.0, y), graphic, update); else addPoint(QPointF(graphics[graphic].max_x + inc_x, y), graphic, update);}
void addPoint(double y, bool update = true) {if (graphics[curGraphic].polyline.isEmpty()) addPoint(QPointF(0.0, y), update); else addPoint(QPointF(graphics[curGraphic].max_x + inc_x, y), update);}
void setGraphicData(const QVector<QPointF> & g, int graphic, bool update_ = true);
void setGraphicData(const QVector<QPointF> & g) {setGraphicData(g, curGraphic);}
void setGraphicProperties(const QString & name, const QColor & color = Qt::darkRed, Qt::PenStyle style = Qt::SolidLine, double width = 0., bool visible = true) {setGraphicProperties(curGraphic, name, color, style, width, visible);}
void setGraphicProperties(int graphic, const QString & name, const QColor & color = Qt::darkRed, Qt::PenStyle style = Qt::SolidLine, double width = 0., bool visible = true);
void addGraphic(const QString & name, const QColor & color = Qt::darkRed, Qt::PenStyle style = Qt::SolidLine, double width = 0., bool visible = true);
void addGraphic(const GraphicType & gd, bool update = true) {graphics << gd; if (update) updateLegend();}
void setVisualRect(const QRectF & rect);
void setDefaultRect(const QRectF & rect);
void autofit() {on_buttonAutofit_clicked();}
void saveImage();
void clear();
void update(bool force = false);
void updateGraphics() {findGraphicsRect(); update();}
void setCurrentGraphic(int arg) {if (arg < 0 || arg >= graphics.size()) return; curGraphic = arg;}
void setGraphicsCount(int arg, bool update = true);
void removeGraphic(int arg, bool update = true);
void zoom(float factor);
void zoomIn() {zoom(1. / 1.2);}
void zoomOut() {zoom(1.2);}
void fullscreen();
protected:
virtual void changeEvent(QEvent * e);
virtual void resizeEvent(QResizeEvent * );
virtual QSize sizeHint() const {return QSize(400, 300);}
virtual void timerEvent(QTimerEvent * );
virtual bool eventFilter(QObject * o, QEvent * e);
void prepareCanvas(QWidget * w);
void procGesture(QGesture * g);
void procZoom(QPointF view_center, double dzoom, Qt::KeyboardModifiers km = Qt::NoModifier);
void totalUpdate();
void setCurrentAction(GraphicAction action);
void findGraphicsRect(double start_x = 0., double end_x = 0., double start_y = 0., double end_y = 0.);
void tick(int index, bool slide = true, bool update = true);
void repaintCanvas(bool force = false) {if (tm.elapsed() < min_repaint_int && !force) return; tm.restart(); canvas->update();}
void drawGraphics();
void drawGrid();
void drawGuides();
void drawPause();
void drawAction();
void updateLegend(bool es = true);
void updateLegendChecks();
void setCanvasCursor(QCursor cursor);
void swapToBuffer();
void swapToNormal() {bufferActive = false;}
void setRectToLines();
void checkLines();
double splitRange(double range, int count = 1);
double splitRangeDate(double range, int count = 1, QString * format = 0, int step[7] = 0);
double roundTo(double value, double round_to);
void roundDateTime(QDateTime & dt, int c[7]);
void addDateTime(QDateTime & dt, int c[7], int mul = 1);
QPointF absPoint(QPointF point) {return QPointF(qAbs(point.x()), qAbs(point.y()));}
QString pointCoords(QPointF point, bool x = true, bool y = true);
QPair<QString, QString> gridMark(double v) const;
Ui::Graphic * ui;
UGLWidget * canvas_gl;
///QMutex mutex, mutex_;
QWidget * canvas;
QImage * buffer;
QPainter * painter;
QBrush selbrush;
QPen grid_pen, selpen;
QColor back_color, text_color;
QVector<GraphicType> graphics;
int curGraphic;
GraphicAction curaction, prevaction;
QRectF grect, rrect, selrect, limit_, def_rect;
QRect margins_;
QSize font_sz;
QPoint startpos, curpos, prevpos, gridborder;
QPointF startpos_r, curpos_r;
QString label_x, label_y, ppath, fp_size;
Graphic::Buttons buttons_;
Graphic::Alignment align;
GraphicConf * conf;
EvalSpinBox line_x_min, line_x_max, line_y_min, line_y_max;
QTime tm;
QIcon icon_exp_x, icon_exp_y, icon_exp_sx, icon_exp_sy;
QImage icon_pause_b, icon_pause_f;
Graduation grad_x, grad_y;
AxisType axis_type_x;
double gridx, gridy, history, visible_time, inc_x, mdm, grid_numbers_x, grid_numbers_y, LN2, LN5, LN10;
double eminx, eminy, emaxx, emaxy, pause_phase, gesture_angle;
int legy, lastw, lasth, min_repaint_int, min_int, max_int, timer_pause, thick;
bool aalias, aupdate, mupdate, grid, guides, isFit, isEmpty, isOGL, isHover, bufferActive, cancel, pause_, isPrinting, gestures;
bool hasLblX, hasLblY, navigation, only_expand_y, only_expand_x, is_lines_update, leg_update, visible_update, fullscr, need_mouse_pan;
protected slots:
void canvasPaintEvent();
void canvasMouseMoveEvent(QMouseEvent * );
void canvasMousePressEvent(QMouseEvent * );
void canvasMouseReleaseEvent(QMouseEvent * );
void canvasMouseDoubleClickEvent(QMouseEvent * );
void canvasWheelEvent(QWheelEvent * );
void canvasLeaveEvent(QEvent * );
void canvasKeyPressEvent(QKeyEvent * );
void graphicVisibleChange(bool checked);
void graphicAllVisibleChange(bool checked);
void lineXMinChanged(double value) {selrect.setLeft(value); checkLines();}
void lineXMaxChanged(double value) {selrect.setRight(value); checkLines();}
void lineYMinChanged(double value) {selrect.setBottom(value); checkLines();}
void lineYMaxChanged(double value) {selrect.setTop(value); checkLines();}
void on_buttonClose_clicked() {emit closeRequest(this);}
void on_buttonClear_clicked() {reset(); emit cleared();}
void on_buttonAutofit_clicked();
void on_buttonConfigure_clicked();
void on_buttonFullscreen_clicked() {fullscreen();}
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_checkBorderInputs_toggled(bool checked) {setBorderInputsVisible(checked);}
void on_checkLegend_toggled(bool checked) {setLegendVisible(checked);}
void on_checkPause_toggled(bool checked) {setPaused(checked);}
void enterFullscreen();
void leaveFullscreen();
signals:
void beforeGraphicPaintEvent(QPainter * );
void graphicPaintEvent(QPainter * );
void graphicMouseMoveEvent(QPointF point, int buttons);
void graphicMousePressEvent(QPointF point, int buttons);
void graphicMouseReleaseEvent(QPointF point, int buttons);
void graphicWheelEvent(QPointF point, int delta);
void closeRequest(QWidget * );
void cleared();
void visualRectChanged();
void graphicSettingsChanged();
};
Q_DECLARE_METATYPE(Graphic::GraphicsData)
Q_DECLARE_OPERATORS_FOR_FLAGS(Graphic::Buttons)
inline QDataStream & operator <<(QDataStream & s, const Graphic::Graduation & v) {s << (int)v; return s;}
inline QDataStream & operator >>(QDataStream & s, Graphic::Graduation & v) {s >> *((int*)(&v)); return s;}
class __GraphicRegistrator__ {
public:
__GraphicRegistrator__() {
qRegisterMetaType<Graphic::GraphicsData>("Graphic::GraphicsData");
qRegisterMetaTypeStreamOperators<Graphic::GraphicsData>("Graphic::GraphicsData");
}
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // GRAPHIC_H

443
test/qad/graphic/graphic.ui Normal file
View File

@@ -0,0 +1,443 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Graphic</class>
<widget class="QFrame" name="Graphic">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>564</width>
<height>433</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>150</width>
<height>150</height>
</size>
</property>
<layout class="QGridLayout" name="gridLayout">
<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>
<property name="spacing">
<number>2</number>
</property>
<item row="0" column="0" rowspan="2">
<widget class="QWidget" name="widgetLeft" native="true">
<widget class="QWidget" name="layoutWidget">
<property name="geometry">
<rect>
<x>-10</x>
<y>0</y>
<width>33</width>
<height>420</height>
</rect>
</property>
<layout class="QVBoxLayout" name="layoutButtons">
<property name="spacing">
<number>2</number>
</property>
<item>
<widget class="QToolButton" name="buttonAutofit">
<property name="toolTip">
<string>Autofit</string>
</property>
<property name="icon">
<iconset resource="qad_graphic.qrc">
<normaloff>:/icons/view-autofit.png</normaloff>:/icons/view-autofit.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="checkGrid">
<property name="toolTip">
<string>Grid</string>
</property>
<property name="icon">
<iconset resource="../widgets/qad_widgets.qrc">
<normaloff>:/icons/view-grid.png</normaloff>:/icons/view-grid.png</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="checkGuides">
<property name="toolTip">
<string>Cursor axis</string>
</property>
<property name="icon">
<iconset resource="../widgets/qad_widgets.qrc">
<normaloff>:/icons/edit-guides.png</normaloff>:/icons/edit-guides.png</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</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">
<normaloff>:/icons/view-fullscreen.png</normaloff>:/icons/view-fullscreen.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="checkBorderInputs">
<property name="toolTip">
<string>Border inputs</string>
</property>
<property name="icon">
<iconset resource="../widgets/qad_widgets.qrc">
<normaloff>:/icons/border-line.png</normaloff>:/icons/border-line.png</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="checkLegend">
<property name="toolTip">
<string>Legend</string>
</property>
<property name="icon">
<iconset resource="../widgets/qad_widgets.qrc">
<normaloff>:/icons/legend.png</normaloff>:/icons/legend.png</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="checkPause">
<property name="toolTip">
<string>Pause</string>
</property>
<property name="icon">
<iconset resource="qad_graphic.qrc">
<normaloff>:/icons/media-playback-pause.png</normaloff>:/icons/media-playback-pause.png</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="buttonConfigure">
<property name="toolTip">
<string>Configure ...</string>
</property>
<property name="icon">
<iconset resource="../widgets/qad_widgets.qrc">
<normaloff>:/icons/configure.png</normaloff>:/icons/configure.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="buttonSave">
<property name="toolTip">
<string>Save image ...</string>
</property>
<property name="icon">
<iconset resource="../utils/qad_utils.qrc">
<normaloff>:/icons/document-save.png</normaloff>:/icons/document-save.png</iconset>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>30</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="buttonClear">
<property name="toolTip">
<string>Clear</string>
</property>
<property name="icon">
<iconset resource="../utils/qad_utils.qrc">
<normaloff>:/icons/edit-clear.png</normaloff>:/icons/edit-clear.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="buttonClose">
<property name="toolTip">
<string>Close</string>
</property>
<property name="icon">
<iconset resource="../widgets/qad_widgets.qrc">
<normaloff>:/icons/dialog-close.png</normaloff>:/icons/dialog-close.png</iconset>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>79</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="labelCaption">
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="0" column="2" rowspan="2">
<widget class="QWidget" name="widgetRight" native="true"/>
</item>
<item row="1" column="1">
<widget class="QFrame" name="frame">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<layout class="QGridLayout" name="gridLayout_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 row="2" column="1" colspan="2">
<widget class="QWidget" name="widgetLX" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>2</number>
</property>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item row="0" column="1" rowspan="2" colspan="2">
<layout class="QVBoxLayout" name="layoutCanvas">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="UWidget" name="canvas_raster" native="true">
<property name="mouseTracking">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="0" rowspan="2">
<widget class="QWidget" name="widgetLY" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>2</number>
</property>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="status">
<property name="text">
<string>Cursor: ( ; )</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QWidget" name="widgetLegend" native="true">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<layout class="QGridLayout" name="layoutLegend">
<property name="leftMargin">
<number>1</number>
</property>
<property name="topMargin">
<number>1</number>
</property>
<property name="rightMargin">
<number>1</number>
</property>
<property name="bottomMargin">
<number>1</number>
</property>
<property name="horizontalSpacing">
<number>4</number>
</property>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>UWidget</class>
<extends>QWidget</extends>
<header>uwidget.h</header>
</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/>
</ui>

View File

@@ -0,0 +1,107 @@
#include "graphic_conf.h"
#include "qad_types.h"
#include "ui_graphic_conf.h"
GraphicConf::GraphicConf(QVector<GraphicType> & graphics_, QWidget * parent): QDialog(parent), graphics(graphics_) {
ui = new Ui::GraphicConf();
ui->setupUi(this);
QStringList styles;
int fh = qMax<int>(fontMetrics().size(0, "0").height(), 22);
int thick = lineThickness();
QSize sz(fh * 2.5, fh);
styles << tr("NoPen") << tr("Solid") << tr("Dash")
<< tr("Dot") << tr("Dash-Dot") << tr("Dash-Dot-Dot");
ui->comboStyleGrid->setIconSize(sz);
ui->comboStyleGraphic->setIconSize(sz);
ui->cbGraphicNames->setIconSize(sz);
for (int i = 0; i < 6; i++) {
QPixmap pix(sz);
pix.fill();
QPainter p(&pix);
p.setPen(QPen(Qt::black, thick, (Qt::PenStyle)i));
p.drawLine(0, pix.height() / 2, pix.width(), pix.height() / 2);
p.end();
ui->comboStyleGraphic->addItem(QIcon(pix), styles[i]);
ui->comboStyleGrid->addItem(QIcon(pix), styles[i]);
}
}
void GraphicConf::changeEvent(QEvent * e) {
if (e->type() == QEvent::LanguageChange) {
ui->retranslateUi(this);
return;
}
QDialog::changeEvent(e);
}
void GraphicConf::readParams() {
ui->cbGraphicNames->clear();
for (int i = 0; i < graphicItems.size(); i++)
ui->cbGraphicNames->addItem(graphicItems[i].icon, graphicItems[i].name);
}
void GraphicConf::on_cbGraphicNames_currentIndexChanged(int i) {
if (i < 0) return;
if (graphicItems.isEmpty()) return;
ui->comboStyleGraphic->setCurrentIndex((int)graphics[i].pen.style());
ui->colorGraphic->setColor(graphics[i].pen.color());
ui->colorFill->setColor(graphics[i].fill_color);
ui->spinLineWidthGraphic->setValue(graphics[i].pen.widthF());
ui->spinPointWidthGraphic->setValue(graphics[i].pointWidth);
ui->checkLines->setChecked(graphics[i].lines);
ui->checkPoints->setChecked(graphics[i].points);
ui->checkFill->setChecked(graphics[i].fill);
}
void GraphicConf::on_colorGraphic_colorChanged(const QColor & c) {
if (graphicItems.isEmpty()) return;
graphics[ui->cbGraphicNames->currentIndex()].pen.setColor(c);
}
void GraphicConf::on_comboStyleGraphic_currentIndexChanged(int index) {
if (graphicItems.isEmpty()) return;
graphics[ui->cbGraphicNames->currentIndex()].pen.setStyle((Qt::PenStyle)index);
}
void GraphicConf::on_spinLineWidthGraphic_valueChanged(double value) {
if (graphicItems.isEmpty()) return;
if (qRound(value) == value) graphics[ui->cbGraphicNames->currentIndex()].pen.setWidth(qRound(value));
else graphics[ui->cbGraphicNames->currentIndex()].pen.setWidthF(value);
}
void GraphicConf::on_spinPointWidthGraphic_valueChanged(double value) {
if (graphicItems.isEmpty()) return;
graphics[ui->cbGraphicNames->currentIndex()].pointWidth = value;
}
void GraphicConf::on_checkLines_toggled(bool on) {
if (graphicItems.isEmpty()) return;
graphics[ui->cbGraphicNames->currentIndex()].lines = on;
}
void GraphicConf::on_checkPoints_toggled(bool on) {
if (graphicItems.isEmpty()) return;
graphics[ui->cbGraphicNames->currentIndex()].points = on;
}
void GraphicConf::on_checkFill_toggled(bool on) {
if (graphicItems.isEmpty()) return;
graphics[ui->cbGraphicNames->currentIndex()].fill = on;
}
void GraphicConf::on_colorFill_colorChanged(const QColor & color) {
if (graphicItems.isEmpty()) return;
graphics[ui->cbGraphicNames->currentIndex()].fill_color = color;
}

View File

@@ -0,0 +1,91 @@
#ifndef GRAPHIC_CONF_H
#define GRAPHIC_CONF_H
#include <QDialog>
#include <QCheckBox>
#include <QPen>
#include <QPainter>
namespace Ui {
class GraphicConf;
};
struct GraphicType {
GraphicType(QString name_ = "y(x)", QColor color = Qt::red, Qt::PenStyle style = Qt::SolidLine, double width = 0., bool visible_ = true) {
pen.setColor(color);
pen.setStyle(style);
lines = true;
points = false;
fill = false;
fill_color = Qt::yellow;
if (qRound(width) == width) pen.setWidth(qRound(width));
else pen.setWidthF(width);
pen.setWidth(1);
pen.setCosmetic(true);
max_x = 0.;
name = name_;
visible = visible_;
pointWidth = 2.;
pb = new QCheckBox(name);
}
//~GraphicType() {delete pb;}
QString name;
QPolygonF polyline;
QPolygonF polyline_pause;
QPen pen;
QColor fill_color;
bool lines;
bool points;
bool fill;
double pointWidth;
double max_x;
double max_x_pause;
QCheckBox * pb;
QIcon icon;
bool visible;
QRectF cvrect;
};
inline QDataStream & operator <<(QDataStream & s, const GraphicType & v) {s << v.name << v.pen << v.fill_color << v.lines << v.points << v.fill << v.pointWidth << v.visible; return s;}
inline QDataStream & operator >>(QDataStream & s, GraphicType & v) {s >> v.name >> v.pen >> v.fill_color >> v.lines >> v.points >> v.fill >> v.pointWidth >> v.visible; return s;}
class GraphicConf: public QDialog
{
Q_OBJECT
friend class Graphic;
public:
explicit GraphicConf(QVector<GraphicType> & graphics_, QWidget * parent = 0);
struct GraphicItem {
QString name;
QIcon icon;
};
void readParams();
QVector<GraphicType> & graphics;
QVector<GraphicItem> graphicItems;
protected:
void changeEvent(QEvent * e);
Ui::GraphicConf * ui;
private slots:
void on_cbGraphicNames_currentIndexChanged(int index);
void on_colorGraphic_colorChanged(const QColor &);
void on_colorFill_colorChanged(const QColor &);
void on_comboStyleGraphic_currentIndexChanged(int index);
void on_spinLineWidthGraphic_valueChanged(double value);
void on_spinPointWidthGraphic_valueChanged(double value);
void on_checkLines_toggled(bool on);
void on_checkPoints_toggled(bool on);
void on_checkFill_toggled(bool on);
};
#endif // GRAPHIC_CONF_H

View File

@@ -0,0 +1,644 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>GraphicConf</class>
<widget class="QDialog" name="GraphicConf">
<property name="windowModality">
<enum>Qt::WindowModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>500</width>
<height>583</height>
</rect>
</property>
<property name="windowTitle">
<string>Graphic parameters</string>
</property>
<property name="modal">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Appearance</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="gridLayout_2">
<item row="1" column="0">
<widget class="QCheckBox" name="checkInputs">
<property name="text">
<string>Border inputs</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="checkAAlias">
<property name="text">
<string>Antialiasing</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="checkStatus">
<property name="text">
<string>Status bar</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="checkOGL">
<property name="text">
<string>OpenGL</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QCheckBox" name="checkLegend">
<property name="text">
<string>Legend</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QFormLayout" name="formLayout_3">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Background color:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="ColorButton" name="colorBackground">
<property name="useAlphaChannel">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_7">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Text color:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="ColorButton" name="colorText">
<property name="useAlphaChannel">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item row="2" column="1">
<widget class="QGroupBox" name="groupBox_1">
<property name="title">
<string>Graphics</string>
</property>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<item row="0" column="0" colspan="2">
<widget class="QComboBox" name="cbGraphicNames">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Color:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="ColorButton" name="colorGraphic">
<property name="useAlphaChannel">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Style:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="comboStyleGraphic"/>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="checkLines">
<property name="text">
<string>Lines width:</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QDoubleSpinBox" name="spinLineWidthGraphic">
<property name="decimals">
<number>2</number>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="checkPoints">
<property name="text">
<string>Points width:</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QDoubleSpinBox" name="spinPointWidthGraphic">
<property name="decimals">
<number>2</number>
</property>
<property name="maximum">
<double>999.990000000000009</double>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QCheckBox" name="checkFill">
<property name="text">
<string>Fill:</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="ColorButton" name="colorFill">
<property name="useAlphaChannel">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="0">
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>Grid</string>
</property>
<layout class="QFormLayout" name="formLayout_2">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Color:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="ColorButton" name="colorGrid">
<property name="useAlphaChannel">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Style:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="comboStyleGrid"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Width:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QDoubleSpinBox" name="spinWidthGrid">
<property name="decimals">
<number>2</number>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Step X:</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Step Y:</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QCheckBox" name="checkGridAutoX">
<property name="text">
<string>Auto X</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="5" column="0" colspan="2">
<widget class="QCheckBox" name="checkGridAutoY">
<property name="text">
<string>Auto Y</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="EvalSpinBox" name="spinGridStepY">
<property name="expression">
<string>30</string>
</property>
<property name="defaultText">
<string>30</string>
</property>
<property name="clearButtonVisible">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="EvalSpinBox" name="spinGridStepX">
<property name="expression">
<string>50</string>
</property>
<property name="defaultText">
<string>50</string>
</property>
<property name="clearButtonVisible">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="4" column="0" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Margins</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="1" column="5">
<widget class="QSpinBox" name="spinMarginR">
<property name="suffix">
<string> px</string>
</property>
<property name="maximum">
<number>100</number>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QSpinBox" name="spinMarginB">
<property name="suffix">
<string> px</string>
</property>
<property name="maximum">
<number>100</number>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="labelAll">
<property name="text">
<string>All:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="spinMarginL">
<property name="suffix">
<string> px</string>
</property>
<property name="maximum">
<number>100</number>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QLabel" name="label_12">
<property name="text">
<string>Right:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_10">
<property name="text">
<string>Left:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLabel" name="label_13">
<property name="text">
<string>Bottom:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QSpinBox" name="spinMarginT">
<property name="suffix">
<string> px</string>
</property>
<property name="maximum">
<number>100</number>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_11">
<property name="text">
<string>Top:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QSpinBox" name="spinMarginT_2">
<property name="suffix">
<string> px</string>
</property>
<property name="maximum">
<number>100</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>ColorButton</class>
<extends>QPushButton</extends>
<header>colorbutton.h</header>
<slots>
<signal>colorChanged(QColor)</signal>
</slots>
</customwidget>
<customwidget>
<class>EvalSpinBox</class>
<extends>QWidget</extends>
<header>evalspinbox.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>checkAAlias</tabstop>
<tabstop>checkOGL</tabstop>
<tabstop>colorBackground</tabstop>
<tabstop>colorText</tabstop>
<tabstop>colorGrid</tabstop>
<tabstop>comboStyleGrid</tabstop>
<tabstop>spinWidthGrid</tabstop>
<tabstop>cbGraphicNames</tabstop>
<tabstop>colorGraphic</tabstop>
<tabstop>comboStyleGraphic</tabstop>
<tabstop>checkLines</tabstop>
<tabstop>spinLineWidthGraphic</tabstop>
<tabstop>checkPoints</tabstop>
<tabstop>spinPointWidthGraphic</tabstop>
<tabstop>buttonBox</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>GraphicConf</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>255</x>
<y>641</y>
</hint>
<hint type="destinationlabel">
<x>245</x>
<y>207</y>
</hint>
</hints>
</connection>
<connection>
<sender>checkLines</sender>
<signal>toggled(bool)</signal>
<receiver>spinLineWidthGraphic</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>322</x>
<y>410</y>
</hint>
<hint type="destinationlabel">
<x>415</x>
<y>411</y>
</hint>
</hints>
</connection>
<connection>
<sender>checkPoints</sender>
<signal>toggled(bool)</signal>
<receiver>spinPointWidthGraphic</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>322</x>
<y>434</y>
</hint>
<hint type="destinationlabel">
<x>415</x>
<y>435</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>GraphicConf</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>294</x>
<y>641</y>
</hint>
<hint type="destinationlabel">
<x>288</x>
<y>268</y>
</hint>
</hints>
</connection>
<connection>
<sender>checkFill</sender>
<signal>toggled(bool)</signal>
<receiver>colorFill</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>322</x>
<y>458</y>
</hint>
<hint type="destinationlabel">
<x>415</x>
<y>460</y>
</hint>
</hints>
</connection>
<connection>
<sender>spinMarginT_2</sender>
<signal>valueChanged(int)</signal>
<receiver>spinMarginT</receiver>
<slot>setValue(int)</slot>
<hints>
<hint type="sourcelabel">
<x>259</x>
<y>221</y>
</hint>
<hint type="destinationlabel">
<x>249</x>
<y>191</y>
</hint>
</hints>
</connection>
<connection>
<sender>spinMarginT_2</sender>
<signal>valueChanged(int)</signal>
<receiver>spinMarginR</receiver>
<slot>setValue(int)</slot>
<hints>
<hint type="sourcelabel">
<x>268</x>
<y>220</y>
</hint>
<hint type="destinationlabel">
<x>371</x>
<y>220</y>
</hint>
</hints>
</connection>
<connection>
<sender>spinMarginT_2</sender>
<signal>valueChanged(int)</signal>
<receiver>spinMarginB</receiver>
<slot>setValue(int)</slot>
<hints>
<hint type="sourcelabel">
<x>233</x>
<y>230</y>
</hint>
<hint type="destinationlabel">
<x>234</x>
<y>252</y>
</hint>
</hints>
</connection>
<connection>
<sender>spinMarginT_2</sender>
<signal>valueChanged(int)</signal>
<receiver>spinMarginL</receiver>
<slot>setValue(int)</slot>
<hints>
<hint type="sourcelabel">
<x>213</x>
<y>230</y>
</hint>
<hint type="destinationlabel">
<x>133</x>
<y>229</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -0,0 +1,351 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="ru_RU">
<context>
<name>Graphic</name>
<message>
<location filename="../graphic.ui" line="44"/>
<location filename="../ui_graphic.h" line="320"/>
<source>Autofit</source>
<translation>Автомасштаб</translation>
</message>
<message>
<location filename="../graphic.ui" line="61"/>
<location filename="../ui_graphic.h" line="323"/>
<source>Grid</source>
<translation>Сетка</translation>
</message>
<message>
<location filename="../graphic.ui" line="84"/>
<location filename="../ui_graphic.h" line="326"/>
<source>Cursor axis</source>
<translation>Плавающие оси</translation>
</message>
<message>
<location filename="../graphic.ui" line="104"/>
<location filename="../ui_graphic.h" line="329"/>
<source>Only expand Y</source>
<translation>Только расширять Y</translation>
</message>
<message>
<location filename="../graphic.ui" line="124"/>
<location filename="../ui_graphic.h" line="332"/>
<source>Only expand X</source>
<translation>Только расширять X</translation>
</message>
<message>
<location filename="../graphic.ui" line="144"/>
<location filename="../ui_graphic.h" line="335"/>
<source>Fullscreen</source>
<translation>Во весь экран</translation>
</message>
<message>
<location filename="../graphic.ui" line="161"/>
<location filename="../ui_graphic.h" line="338"/>
<source>Border inputs</source>
<translation>Граничные поля ввода</translation>
</message>
<message>
<location filename="../graphic.ui" line="184"/>
<location filename="../ui_graphic.h" line="341"/>
<source>Legend</source>
<translation>Легенда</translation>
</message>
<message>
<location filename="../graphic.ui" line="207"/>
<location filename="../ui_graphic.h" line="344"/>
<source>Configure ...</source>
<translation>Настроить ...</translation>
</message>
<message>
<location filename="../graphic.ui" line="224"/>
<location filename="../ui_graphic.h" line="347"/>
<source>Save image ...</source>
<translation>Сохранить изображение ...</translation>
</message>
<message>
<location filename="../graphic.ui" line="257"/>
<location filename="../ui_graphic.h" line="350"/>
<source>Clear</source>
<translation>Очистить</translation>
</message>
<message>
<location filename="../graphic.ui" line="274"/>
<location filename="../ui_graphic.h" line="353"/>
<source>Close</source>
<translation>Закрыть</translation>
</message>
<message>
<location filename="../graphic.ui" line="425"/>
<location filename="../ui_graphic.h" line="355"/>
<source>Cursor: ( ; )</source>
<translation>Курсор: ( ; )</translation>
</message>
<message>
<location filename="../graphic.cpp" line="205"/>
<location filename="../graphic.cpp" line="809"/>
<source>Cursor: </source>
<translation>Курсор: </translation>
</message>
<message>
<location filename="../graphic.cpp" line="216"/>
<source>Selection</source>
<translation>Выделение</translation>
</message>
<message>
<location filename="../graphic.cpp" line="217"/>
<source>Size</source>
<translation>Размер</translation>
</message>
<message>
<location filename="../graphic.cpp" line="221"/>
<location filename="../graphic.cpp" line="227"/>
<source>Range</source>
<translation>Диапазон</translation>
</message>
<message>
<location filename="../graphic.cpp" line="222"/>
<location filename="../graphic.cpp" line="228"/>
<source>Length</source>
<translation>Длина</translation>
</message>
<message>
<location filename="../graphic.cpp" line="329"/>
<location filename="../graphic.cpp" line="380"/>
<source>Cursor</source>
<translation>Курсор</translation>
</message>
<message>
<location filename="../graphic.cpp" line="531"/>
<source>Save Image</source>
<translation>Сохранить изображение</translation>
</message>
<message>
<location filename="../graphic.cpp" line="576"/>
<source>y(x)</source>
<translation></translation>
</message>
<message>
<location filename="../graphic.cpp" line="1124"/>
<source>Check all</source>
<translation>Выбрать все</translation>
</message>
</context>
<context>
<name>GraphicConf</name>
<message>
<location filename="../graphic_conf.ui" line="17"/>
<location filename="../ui_graphic_conf.h" line="450"/>
<source>Graphic parameters</source>
<translation>Параметры графика</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="32"/>
<location filename="../ui_graphic_conf.h" line="451"/>
<source>Appearance</source>
<translation>Внешний вид</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="46"/>
<location filename="../ui_graphic_conf.h" line="452"/>
<source>Border inputs</source>
<translation>Граничные поля ввода</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="53"/>
<location filename="../ui_graphic_conf.h" line="453"/>
<source>Antialiasing</source>
<translation>Сглаживание</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="60"/>
<location filename="../ui_graphic_conf.h" line="454"/>
<source>Status bar</source>
<translation>Панель статуса</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="67"/>
<location filename="../ui_graphic_conf.h" line="455"/>
<source>OpenGL</source>
<translation></translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="74"/>
<location filename="../ui_graphic_conf.h" line="456"/>
<source>Legend</source>
<translation>Легенда</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="94"/>
<location filename="../ui_graphic_conf.h" line="457"/>
<source>Background color:</source>
<translation>Цвет фона:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="114"/>
<location filename="../ui_graphic_conf.h" line="458"/>
<source>Text color:</source>
<translation>Цвет текста:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="133"/>
<location filename="../ui_graphic_conf.h" line="459"/>
<source>Graphics</source>
<translation>Графики</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="161"/>
<location filename="../graphic_conf.ui" line="263"/>
<location filename="../ui_graphic_conf.h" line="460"/>
<location filename="../ui_graphic_conf.h" line="466"/>
<source>Color:</source>
<translation>Цвет:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="175"/>
<location filename="../graphic_conf.ui" line="277"/>
<location filename="../ui_graphic_conf.h" line="461"/>
<location filename="../ui_graphic_conf.h" line="467"/>
<source>Style:</source>
<translation>Стиль:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="185"/>
<location filename="../ui_graphic_conf.h" line="462"/>
<source>Lines width:</source>
<translation>Толщина линий:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="205"/>
<location filename="../ui_graphic_conf.h" line="463"/>
<source>Points width:</source>
<translation>Толщина точек:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="225"/>
<location filename="../ui_graphic_conf.h" line="464"/>
<source>Fill:</source>
<translation>Заливка:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="245"/>
<location filename="../ui_graphic_conf.h" line="465"/>
<source>Grid</source>
<translation>Сетка</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="287"/>
<location filename="../ui_graphic_conf.h" line="468"/>
<source>Width:</source>
<translation>Толщина:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="317"/>
<location filename="../ui_graphic_conf.h" line="469"/>
<source>Step X:</source>
<translation>Шаг X:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="324"/>
<location filename="../ui_graphic_conf.h" line="470"/>
<source>Step Y:</source>
<translation>Шаг Y:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="347"/>
<location filename="../ui_graphic_conf.h" line="471"/>
<source>Auto X</source>
<translation>Авто X</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="357"/>
<location filename="../ui_graphic_conf.h" line="472"/>
<source>Auto Y</source>
<translation>Авто Y</translation>
</message>
<message>
<source>Auto step</source>
<translation type="obsolete">Автоматический шаг</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="390"/>
<location filename="../ui_graphic_conf.h" line="473"/>
<source>Margins</source>
<translation>Поля</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="402"/>
<location filename="../graphic_conf.ui" line="412"/>
<location filename="../graphic_conf.ui" line="432"/>
<location filename="../graphic_conf.ui" line="472"/>
<location filename="../graphic_conf.ui" line="492"/>
<location filename="../ui_graphic_conf.h" line="474"/>
<location filename="../ui_graphic_conf.h" line="475"/>
<location filename="../ui_graphic_conf.h" line="477"/>
<location filename="../ui_graphic_conf.h" line="481"/>
<location filename="../ui_graphic_conf.h" line="483"/>
<source> px</source>
<translation> пикс</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="422"/>
<location filename="../ui_graphic_conf.h" line="476"/>
<source>All:</source>
<translation>Все:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="442"/>
<location filename="../ui_graphic_conf.h" line="478"/>
<source>Right:</source>
<translation>Правое:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="452"/>
<location filename="../ui_graphic_conf.h" line="479"/>
<source>Left:</source>
<translation>Левое:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="462"/>
<location filename="../ui_graphic_conf.h" line="480"/>
<source>Bottom:</source>
<translation>Нижнее:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="482"/>
<location filename="../ui_graphic_conf.h" line="482"/>
<source>Top:</source>
<translation>Верхнее:</translation>
</message>
<message>
<location filename="../graphic_conf.cpp" line="7"/>
<source>NoPen</source>
<translation>НетЛинии</translation>
</message>
<message>
<location filename="../graphic_conf.cpp" line="7"/>
<source>Solid</source>
<translation>Сплошная</translation>
</message>
<message>
<location filename="../graphic_conf.cpp" line="7"/>
<source>Dash</source>
<translation>Штриховая</translation>
</message>
<message>
<location filename="../graphic_conf.cpp" line="8"/>
<source>Dot</source>
<translation>Пунктирная</translation>
</message>
<message>
<location filename="../graphic_conf.cpp" line="8"/>
<source>Dash-Dot</source>
<translation>ШтрихПунктирная</translation>
</message>
<message>
<location filename="../graphic_conf.cpp" line="8"/>
<source>Dash-Dot-Dot</source>
<translation>ШтрихПунктирПунктирная</translation>
</message>
</context>
</TS>

View File

@@ -0,0 +1 @@
qad_plugin(graphic "Gui;Widgets;OpenGL" "")

View File

@@ -0,0 +1,69 @@
#include "graphic.h"
#include "graphicplugin.h"
#include <QtCore/QtPlugin>
GraphicPlugin::GraphicPlugin(QObject * parent): QObject(parent) {
m_initialized = false;
}
void GraphicPlugin::initialize(QDesignerFormEditorInterface * /* core */) {
if (m_initialized)
return;
// Add extension registrations, etc. here
m_initialized = true;
}
bool GraphicPlugin::isInitialized() const {
return m_initialized;
}
QWidget * GraphicPlugin::createWidget(QWidget * parent) {
return new Graphic(parent);
}
QString GraphicPlugin::name() const {
return QLatin1String("Graphic");
}
QString GraphicPlugin::group() const {
return QLatin1String("Display Widgets");
}
QIcon GraphicPlugin::icon() const {
return QIcon(":/icons/graphic.png");
}
QString GraphicPlugin::toolTip() const {
return QLatin1String("");//QLatin1String("Widget for display any math graphics with grid and navigation");
}
QString GraphicPlugin::whatsThis() const {
return QLatin1String("");
}
bool GraphicPlugin::isContainer() const {
return false;
}
QString GraphicPlugin::domXml() const {
return QLatin1String("<widget class=\"Graphic\" name=\"graphic\">\n</widget>\n");
}
QString GraphicPlugin::includeFile() const {
return QLatin1String("graphic.h");
}

View File

@@ -0,0 +1,36 @@
#ifndef GRAPHICPLUGIN_H
#define GRAPHICPLUGIN_H
#include <QObject>
#if QT_VERSION >= 0x050000
# include <QtUiPlugin/QDesignerCustomWidgetInterface>
#else
# include <QDesignerCustomWidgetInterface>
#endif
class GraphicPlugin: public QObject, public QDesignerCustomWidgetInterface
{
Q_OBJECT
Q_INTERFACES(QDesignerCustomWidgetInterface)
public:
GraphicPlugin(QObject * parent = 0);
bool isContainer() const;
bool isInitialized() const;
QIcon icon() const;
QString domXml() const;
QString group() const;
QString includeFile() const;
QString name() const;
QString toolTip() const;
QString whatsThis() const;
QWidget * createWidget(QWidget * parent);
void initialize(QDesignerFormEditorInterface * core);
private:
bool m_initialized;
};
#endif

View File

@@ -0,0 +1,17 @@
#include "qad_graphic.h"
#include "graphicplugin.h"
QADGraphic::QADGraphic(QObject * parent): QObject(parent)
{
m_widgets.append(new GraphicPlugin(this));
}
QList<QDesignerCustomWidgetInterface * > QADGraphic::customWidgets() const {
return m_widgets;
}
#if QT_VERSION < 0x050000
Q_EXPORT_PLUGIN2(qad_graphic_plugin, QADGraphic)
#endif

View File

@@ -0,0 +1,23 @@
#ifndef QAD_GRAPHIC_H
#define QAD_GRAPHIC_H
#include <QtDesigner/QtDesigner>
#include <QtCore/qplugin.h>
class QADGraphic: public QObject, public QDesignerCustomWidgetCollectionInterface
{
Q_OBJECT
Q_INTERFACES(QDesignerCustomWidgetCollectionInterface)
#if QT_VERSION >= 0x050000
Q_PLUGIN_METADATA(IID "qad.graphic")
#endif
public:
explicit QADGraphic(QObject * parent = 0);
virtual QList<QDesignerCustomWidgetInterface * > customWidgets() const;
private:
QList<QDesignerCustomWidgetInterface * > m_widgets;
};
#endif // QAD_GRAPHIC_H

View File

@@ -0,0 +1,28 @@
<RCC>
<qresource prefix="/">
<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/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

@@ -0,0 +1,27 @@
project(qpicalc)
find_qt(${QtVersions} Core Gui Widgets)
qt_sources(SRC)
qt_wrap(${SRC} CPPS out_CPP QMS out_QM)
qt_add_executable(${PROJECT_NAME} WIN32 out_CPP)
qt_target_link_libraries(${PROJECT_NAME} qad_utils qad_widgets qad_graphic)
message(STATUS "Building ${PROJECT_NAME}")
if(LIB)
if(WIN32)
qt_install(TARGETS ${PROJECT_NAME} DESTINATION ${MINGW_BIN})
else()
if(APPLE)
qt_install(TARGETS ${PROJECT_NAME} DESTINATION /usr/local/bin)
else()
if (DEFINED ANDROID_PLATFORM)
qt_install(TARGETS ${PROJECT_NAME} DESTINATION ${ANDROID_SYSTEM_LIBRARY_PATH}/usr/bin)
else()
qt_install(TARGETS ${PROJECT_NAME} DESTINATION /usr/bin)
endif()
endif()
endif()
#message(STATUS "Install ${PROJECT_NAME} to system \"${CMAKE_INSTALL_PREFIX}\"")
else()
qt_install(TARGETS ${PROJECT_NAME} DESTINATION bin)
#message(STATUS "Install ${PROJECT_NAME} to local \"bin\"")
endif()

View File

@@ -0,0 +1,188 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 3.2.1, 2016-03-25T15:17:49. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>
<value type="QByteArray">{948faa78-0b50-402e-a285-1bca3b08de64}</value>
</data>
<data>
<variable>ProjectExplorer.Project.ActiveTarget</variable>
<value type="int">0</value>
</data>
<data>
<variable>ProjectExplorer.Project.EditorSettings</variable>
<valuemap type="QVariantMap">
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">false</value>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
<value type="QString" key="language">Cpp</value>
<valuemap type="QVariantMap" key="value">
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
</valuemap>
</valuemap>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
<value type="QString" key="language">QmlJS</value>
<valuemap type="QVariantMap" key="value">
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
</valuemap>
</valuemap>
<value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
<value type="int" key="EditorConfiguration.IndentSize">4</value>
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
<value type="int" key="EditorConfiguration.TabSize">8</value>
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.PluginSettings</variable>
<valuemap type="QVariantMap"/>
</data>
<data>
<variable>ProjectExplorer.Project.Target.0</variable>
<valuemap type="QVariantMap">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">DesktopBuild</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">DesktopBuild</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{3c749452-9483-442d-b011-933a1b5dac10}</value>
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
<value type="bool" key="CMakeProjectManager.CMakeBuildConfiguration.UseNinja">false</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">D:/work/qpicalculator-build</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="CMakeProjectManager.MakeStep.AdditionalArguments"></value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets"/>
<value type="bool" key="CMakeProjectManager.MakeStep.Clean">false</value>
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Сборка</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Сборка</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="CMakeProjectManager.MakeStep.AdditionalArguments">clean</value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets"/>
<value type="bool" key="CMakeProjectManager.MakeStep.Clean">true</value>
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Сборка</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Очистка</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">all</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Установка</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Локальная установка</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
<valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
<value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
<value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
<value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
<value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">3</value>
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
<value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
<value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
<value type="int">0</value>
<value type="int">1</value>
<value type="int">2</value>
<value type="int">3</value>
<value type="int">4</value>
<value type="int">5</value>
<value type="int">6</value>
<value type="int">7</value>
<value type="int">8</value>
<value type="int">9</value>
<value type="int">10</value>
<value type="int">11</value>
<value type="int">12</value>
<value type="int">13</value>
<value type="int">14</value>
</valuelist>
<value type="QString" key="CMakeProjectManager.CMakeRunConfiguation.Title">qpicalculator</value>
<value type="QString" key="CMakeProjectManager.CMakeRunConfiguration.Arguments"></value>
<value type="bool" key="CMakeProjectManager.CMakeRunConfiguration.UseTerminal">false</value>
<value type="QString" key="CMakeProjectManager.CMakeRunConfiguration.UserWorkingDirectory"></value>
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qpicalculator</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeRunConfiguration.qpicalculator</value>
<value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.TargetCount</variable>
<value type="int">1</value>
</data>
<data>
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
<value type="int">16</value>
</data>
<data>
<variable>Version</variable>
<value type="int">16</value>
</data>
</qtcreator>

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 842 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 839 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 798 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 468 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 538 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 494 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 717 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 813 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 678 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 726 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 639 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 794 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 839 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 563 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 644 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 802 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 485 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 368 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 640 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 634 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 544 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 529 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 813 B

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