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

This commit is contained in:
2017-05-12 12:10:48 +00:00
parent d5218d7c4a
commit e6112cdb96
337 changed files with 26799 additions and 251 deletions

View File

@@ -5,14 +5,31 @@ if(MINGW)
find_package(MinGW REQUIRED)
endif()
set(LIB 1)
set(LIBPROJECT 1)
set(PULT 1)
set(USB 1)
set(ICU 1)
set(CRYPT 1)
set(FFTW 1)
set(LIBPROJECT 1)
set(PIP_LIBRARY pip)
set(PIP_FOLDERS "." "core" "containers" "thread" "system" "io" "console" "math" "code" "geo")
set(PIP_INCLUDES)
if (LIB)
if (WIN32)
set(CMAKE_INSTALL_PREFIX ${MINGW_DIR})
else ()
if(APPLE)
set(CMAKE_INSTALL_PREFIX /usr/local)
else()
set(CMAKE_INSTALL_PREFIX /usr)
endif()
endif ()
message(STATUS "Install to system \"${CMAKE_INSTALL_PREFIX}\"")
else ()
message(STATUS "Install to local \"bin\"")
endif ()
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native")
#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native")
foreach(F ${PIP_FOLDERS})
@@ -24,17 +41,21 @@ if(WIN32)
set(PIP_DLL_DIR "${CMAKE_CURRENT_BINARY_DIR}/pip")
endif()
set(LIST_LIBS pip qad_utils qad_widgets qad_application qad_blockview qad_graphic qad_sql_table piqt cd_utils qcd_utils kx_utils piqt_utils touch_widgets qglview)
#set(LIST_LIBS pip)
foreach(L ${LIST_LIBS})
add_subdirectory(${L})
include_directories(${L})
endforeach(L)
set(QAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/qad)
add_subdirectory(pip)
add_subdirectory(qad)
set(_DIRS piqt piqt_utils cd_utils qcd_utils)
foreach(_D ${_DIRS})
include_directories(${_D})
add_subdirectory(${_D})
endforeach(_D)
if(WIN32)
get_filename_component(QTDIR ${QT_QMAKE_EXECUTABLE} PATH)
foreach(PIP_LT ${PIP_LIBS_TARGETS})
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/pip/lib${PIP_LT}.dll" DESTINATION ${QTDIR})
endforeach()
install(FILES "FindMinGW.cmake" DESTINATION ${CMAKE_ROOT}/Modules)
set(CMAKES "FindMinGW.cmake" "QtProject.cmake")
install(FILES ${CMAKES} DESTINATION ${CMAKE_ROOT}/Modules)
endif()

View File

@@ -5,7 +5,7 @@ if(${MINGW})
find_path(MINGW_INCLUDE
windows.h
PATHS
EVN INCLUDE
ENV INCLUDE
${MINGW_DIR}
${MINGW_DIR}/i686-w64-mingw32
${MINGW_DIR}/x86_64-w64-mingw32
@@ -15,8 +15,8 @@ if(${MINGW})
#if(NOT ${MINGW_INCLUDE}) MINGW_INCLUDE = ${MINGW_DIR}/include
find_library(MINGW_LIB m HINTS ${MINGW_BIN}/../lib ${MINGW_INCLUDE}/../lib)
get_filename_component(MINGW_LIB ${MINGW_LIB} PATH)
message(STATUS "Find MinGW binary path = ${MINGW_BIN}")
message(STATUS "Find MinGW include path = ${MINGW_INCLUDE}")
message(STATUS "Find MinGW library path = ${MINGW_LIB}")
message(STATUS "Found MinGW binary path = ${MINGW_BIN}")
message(STATUS "Found MinGW include path = ${MINGW_INCLUDE}")
message(STATUS "Found MinGW library path = ${MINGW_LIB}")
endif()
endif(${MINGW})

30
QtProject.cmake Normal file
View File

@@ -0,0 +1,30 @@
set(QTVERSION 4)
find_package(Qt${QTVERSION} REQUIRED)
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${QT_INCLUDES})
macro(qt_project NAME _TYPE _LIBS _H_OUT _CPP_OUT)
project(${NAME})
find_package(Qt4 REQUIRED)
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${QT_INCLUDES})
file(GLOB ${_H_OUT} "./*.h")
file(GLOB CPPS "./*.cpp")
file(GLOB UIS "./*.ui")
file(GLOB RES "./*.qrc")
qt4_wrap_ui(CUIS ${UIS})
qt4_wrap_cpp(CMOCS ${${_H_OUT}} OPTIONS -nw)
qt4_add_resources(CRES ${RES})
set(${_CPP_OUT} ${CPPS})
list(APPEND ${_CPP_OUT} ${CUIS})
list(APPEND ${_CPP_OUT} ${CMOCS})
list(APPEND ${_CPP_OUT} ${CRES})
if ("_${_TYPE}" STREQUAL "_EXE")
add_executable(${PROJECT_NAME} ${${_H_OUT}} ${${_CPP_OUT}})
else()
if ("_${_TYPE}" STREQUAL "_LIB")
add_library(${PROJECT_NAME} SHARED ${${_H_OUT}} ${${_CPP_OUT}})
else()
message(FATAL_ERROR "You must specify \"EXE\" ot \"LIB\" by second argument of \"qt_project()\"!")
endif()
endif()
target_link_libraries(${PROJECT_NAME} ${_LIBS})
endmacro()

22
SDKMacros.cmake Normal file
View File

@@ -0,0 +1,22 @@
macro(sdk_install _DIR _TARGET _H_FILES)
if (LIB)
if (WIN32)
if (NOT _H_FILES STREQUAL "")
#message("HFILES ${_H_FILES}")
install(FILES ${_H_FILES} DESTINATION ${MINGW_INCLUDE}/${_DIR})
endif()
install(TARGETS ${_TARGET} DESTINATION ${MINGW_LIB})
install(TARGETS ${_TARGET} DESTINATION ${MINGW_BIN})
get_filename_component(QTDIR ${QT_QMAKE_EXECUTABLE} PATH)
install(TARGETS ${_TARGET} DESTINATION ${QTDIR})
else ()
if (NOT _H_FILES STREQUAL "")
install(FILES ${_H_FILES} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/${_DIR})
endif()
install(TARGETS ${_TARGET} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib)
endif ()
else ()
install(TARGETS ${_TARGET} DESTINATION bin)
endif ()
endmacro()

View File

@@ -7,7 +7,6 @@ if (MINGW)
find_package(MinGW REQUIRED)
endif()
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${PIP_INCLUDES})
set(PULT_NAME "cd_pult")
option(LIB "System install" 1)
option(DEBUG "Build with -g3" 0)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -Wall")
@@ -28,23 +27,7 @@ target_link_libraries(${PROJECT_NAME} ${PIP_LIBRARY})
add_executable(cdutilstest "cdutilstest.cpp" "cdtest.h")
target_link_libraries(cdutilstest ${PIP_LIBRARY} ${PROJECT_NAME})
if (LIB)
if (WIN32)
set(CMAKE_INSTALL_PREFIX ${MINGW_DIR})
install(FILES ${HDRS_UTILS} DESTINATION ${MINGW_INCLUDE})
install(TARGETS ${PROJECT_NAME} DESTINATION ${MINGW_LIB})
install(TARGETS ${PROJECT_NAME} DESTINATION ${MINGW_BIN})
else ()
if(APPLE)
set(CMAKE_INSTALL_PREFIX /usr/local)
else()
set(CMAKE_INSTALL_PREFIX /usr)
endif()
install(FILES ${HDRS_UTILS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include)
install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib)
endif ()
message(STATUS "Install to system \"${CMAKE_INSTALL_PREFIX}\"")
else ()
install(TARGETS ${PROJECT_NAME} DESTINATION bin)
message(STATUS "Install to local \"bin\"")
if (LIB)
include(SDKMacros)
sdk_install("" "${PROJECT_NAME}" "${HDRS_UTILS}")
endif ()

View File

@@ -1,3 +1,3 @@
@echo off
mkdir ../libs_build_win
cd ../libs_build_win && cmake_mgw ../libs && cmake_mgw ../libs && make install -j8 && cd ../libs && pause
cd ../libs_build_win && cmake_mgw ../libs && make install -j8 && cd ../libs && pause

View File

@@ -1,41 +1,13 @@
project(piqt)
cmake_minimum_required(VERSION 2.6)
option(LIB "System install" 0)
find_package(Qt4 REQUIRED)
if(LIBPROJECT)
include(PIPMacros)
else()
if(NOT LIBPROJECT)
find_package(PIP REQUIRED)
endif()
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${PIP_INCLUDES} ${QT_INCLUDES})
file(GLOB HDRS "*.h")
file(GLOB CPPS "*.cpp")
if(DEFINED ENV{QNX_HOST})
add_library(${PROJECT_NAME} STATIC ${CPPS})
else()
add_library(${PROJECT_NAME} SHARED ${CPPS})
endif()
set(LIBS ${QT_QTCORE_LIBRARY} ${PIP_LIBRARY} qad_utils)
target_link_libraries(${PROJECT_NAME} ${LIBS})
if(LIB)
if(WIN32)
set(CMAKE_INSTALL_PREFIX ${MINGW_DIR})
install(FILES ${HDRS} DESTINATION ${MINGW_INCLUDE})
install(TARGETS ${PROJECT_NAME} DESTINATION ${MINGW_LIB})
install(TARGETS ${PROJECT_NAME} DESTINATION ${MINGW_BIN})
get_filename_component(QTDIR ${QT_QMAKE_EXECUTABLE} PATH)
install(TARGETS ${PROJECT_NAME} DESTINATION ${QTDIR})
else()
if(APPLE)
set(CMAKE_INSTALL_PREFIX /usr/local)
else()
set(CMAKE_INSTALL_PREFIX /usr)
endif()
install(FILES ${HDRS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include)
install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib)
endif()
message(STATUS "Install to system \"${CMAKE_INSTALL_PREFIX}\"")
else()
install(TARGETS ${PROJECT_NAME} DESTINATION bin)
message(STATUS "Install to local \"bin\"")
find_package(QAD REQUIRED)
include_directories(${PIP_INCLUDES} ${QAD_INCLUDES})
set(LIBS ${PIP_LIBRARY} ${QAD_UTILS_LIBRARY})
qt_project(${PROJECT_NAME} "LIB" "${LIBS}" H CPP)
if(LIBPROJECT)
include(SDKMacros)
sdk_install("" "${PROJECT_NAME}" "${H}")
endif()

View File

@@ -3,21 +3,22 @@ cmake_minimum_required(VERSION 2.6)
if(MINGW)
find_package(MinGW REQUIRED)
endif()
find_package(Qt4 REQUIRED)
if(LIBPROJECT)
include(PIPMacros)
else()
find_package(PIP REQUIRED)
endif()
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${PIP_INCLUDES} ${QT_INCLUDES})
option(LIB "System install" 0)
option(DEBUG "Build with -g3" 0)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -Wall")
if(DEBUG)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3")
endif()
set(LIBS ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${PIP_LIBRARY} qad_widgets qad_utils qad_blockview)
if(LIBPROJECT)
include(PIPMacros)
include(SDKMacros)
else()
find_package(PIP REQUIRED)
endif()
find_package(QAD REQUIRED)
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${QT_INCLUDES} ${PIP_INCLUDES} ${QAD_INCLUDES})
pip_code_model(CCM "../pip/src_main/io/piiodevice.h" "../pip/src_main/io/pipacketextractor.h" OPTIONS "-DPIP_EXPORT" "-Es")
set(LIBS ${QAD_WIDGETS_LIBRARY} ${QAD_UTILS_LIBRARY} ${QAD_BLOCKVIEW_LIBRARY} ${PIP_LIBRARY})
#message(STATUS "pip_code_model for iodevice = ${CCM}")
#message(STATUS "pip_INCLUDES = ${PIP_INCLUDES}")
file(GLOB CPPS_UTILS "piqt_*.cpp")
@@ -58,29 +59,31 @@ if (NOT DEFINED ENV{QNX_HOST})
add_executable(piconnectionedit "piconnedit_main.cpp" ${RESS})
target_link_libraries(piconnectionedit ${LIBS} ${PROJECT_NAME})
endif()
if(LIB)
if(WIN32)
set(CMAKE_INSTALL_PREFIX ${MINGW_DIR})
install(FILES ${HDRS_UTILS} DESTINATION ${MINGW_INCLUDE})
install(TARGETS ${PROJECT_NAME} DESTINATION ${MINGW_LIB})
install(TARGETS ${PROJECT_NAME} DESTINATION ${MINGW_BIN})
get_filename_component(QTDIR ${QT_QMAKE_EXECUTABLE} PATH)
install(TARGETS ${PROJECT_NAME} DESTINATION ${QTDIR})
else()
if(APPLE)
set(CMAKE_INSTALL_PREFIX /usr/local)
else()
set(CMAKE_INSTALL_PREFIX /usr)
endif()
install(FILES ${HDRS_UTILS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include)
install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib)
endif()
message(STATUS "Install to system \"${CMAKE_INSTALL_PREFIX}\"")
else()
install(TARGETS ${PROJECT_NAME} DESTINATION bin)
message(STATUS "Install to local \"bin\"")
endif()
if(NOT DEFINED ENV{QNX_HOST})
install(TARGETS pidumper DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
install(TARGETS piconnectionedit DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
endif()
set(_TARGETS ${PROJECT_NAME} pidumper piconnectionedit)
sdk_install("" "${TARGETS}" "${HDRS_UTILS}")
#if(LIB)
# if(WIN32)
# set(CMAKE_INSTALL_PREFIX ${MINGW_DIR})
# install(FILES ${HDRS_UTILS} DESTINATION ${MINGW_INCLUDE})
# install(TARGETS ${PROJECT_NAME} DESTINATION ${MINGW_LIB})
# install(TARGETS ${PROJECT_NAME} DESTINATION ${MINGW_BIN})
# get_filename_component(QTDIR ${QT_QMAKE_EXECUTABLE} PATH)
# install(TARGETS ${PROJECT_NAME} DESTINATION ${QTDIR})
# else()
# if(APPLE)
# set(CMAKE_INSTALL_PREFIX /usr/local)
# else()
# set(CMAKE_INSTALL_PREFIX /usr)
# endif()
# install(FILES ${HDRS_UTILS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include)
# install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib)
# endif()
# message(STATUS "Install to system \"${CMAKE_INSTALL_PREFIX}\"")
#else()
# install(TARGETS ${PROJECT_NAME} DESTINATION bin)
# message(STATUS "Install to local \"bin\"")
#endif()
#if(NOT DEFINED ENV{QNX_HOST})
# install(TARGETS pidumper DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
# install(TARGETS piconnectionedit DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
#endif()

72
qad/CMakeLists.txt Normal file
View File

@@ -0,0 +1,72 @@
project(qad)
cmake_minimum_required(VERSION 2.6)
include(../SDKMacros.cmake)
include(../QtProject.cmake)
find_package(OpenGL REQUIRED)
if (MINGW)
find_package(MinGW REQUIRED)
endif()
#include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${QT_INCLUDES})
option(LIB "System install" 0)
option(DEBUG "Build with -g3" 0)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -Wall")
if (DEBUG)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3")
endif ()
#set(LIBS ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${QT_QTOPENGL_LIBRARY} ${OPENGL_LIBRARIES} qad_widgets qad_utils)
if (NOT LIBPROJECT)
if (LIB)
if (WIN32)
set(CMAKE_INSTALL_PREFIX ${MINGW_DIR})
else ()
if(APPLE)
set(CMAKE_INSTALL_PREFIX /usr/local)
else()
set(CMAKE_INSTALL_PREFIX /usr)
endif()
endif ()
message(STATUS "Install to system \"${CMAKE_INSTALL_PREFIX}\"")
else ()
message(STATUS "Install to local \"bin\"")
endif ()
endif()
set(CMAKES "FindQAD.cmake")
install(FILES ${CMAKES} DESTINATION ${CMAKE_ROOT}/Modules)
macro(qad_install _TARGET _H_FILES)
sdk_install(qad "${_TARGET}" "${_H_FILES}")
endmacro()
macro(qad_plugin NAME _LIBS)
project(qad_${NAME}_plugin)
include_directories("..")
set(LIBS ${_${NAME}_LIBS} qad_${NAME} "${_LIBS}")
#message(${_${NAME}_PLUGIN_LIBS})
add_definitions(-DQT_PLUGIN)
add_definitions(-DQT_NO_DEBUG)
add_definitions(-DQT_SHARED)
add_definitions(-DQDESIGNER_EXPORT_WIDGETS)
file(GLOB PMOCS "./*.h")
file(GLOB PCPPS "./*.cpp")
qt4_wrap_cpp(PCMOCS ${PMOCS} OPTIONS -nw)
add_library(${PROJECT_NAME} SHARED ${PCMOCS} ${PCPPS} ${PMOCS})
target_link_libraries(${PROJECT_NAME} ${LIBS} ${QT_QTDESIGNER_LIBRARY})
install(TARGETS ${PROJECT_NAME} DESTINATION ${QT_PLUGINS_DIR}/designer)
endmacro()
macro(qad_project NAME _LIBS)
qt_project(qad_${NAME} "LIB" "${_LIBS}" _H _CPP)
message(STATUS "Building ${PROJECT_NAME}")
qad_install(${PROJECT_NAME} "${_H}")
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/plugin")
set(_${NAME}_PLUGIN_LIBS "${_LIBS}")
add_subdirectory(plugin)
endif()
endmacro()
set(DIRS utils widgets application blockview graphic sql_table touch_widgets)
foreach(D ${DIRS})
include_directories(${D})
add_subdirectory(${D})
endforeach(D)

31
qad/FindQAD.cmake Normal file
View File

@@ -0,0 +1,31 @@
include(QtProject)
set(_SEARCH_DIR)
if(WIN32)
find_package(MinGW REQUIRED)
set(_SEARCH_DIR ${MINGW_LIB})
set(QAD_INCLUDES ${MINGW_INCLUDE}/qad)
else()
set(_DIR_ "/usr")
if(APPLE)
set(_DIR_ "/usr/local")
endif()
set(_SEARCH_DIR ${_DIR_}/lib/)
set(QAD_INCLUDES ${_DIR_}/include/qad)
endif()
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()
find_library(QAD_${_QU}_LIBRARY qad_${_Q} ${_SEARCH_DIR})
endif()
#message(STATUS "Library ${_Q} (${_QU}) -> ${QAD_${_QU}_LIBRARY} found in ${_SEARCH_DIR}")
endforeach()
if(NOT LIBPROJECT)
message(STATUS "Found QAD")
endif()

1
qad/QADConfig.cmake Normal file
View File

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

View File

@@ -0,0 +1,2 @@
set(LIBS ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} qad_widgets)
qad_project(application "${LIBS}")

View File

@@ -0,0 +1,51 @@
#include "edockwidget.h"
#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::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();
lbl_icon->setPixmap(windowIcon().pixmap(QSize(24, 24)));
lbl_icon->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
lbl_title = new QLabel(windowTitle());
lbl_title->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
btn_dock = new QToolButton();
//btn_dock->setIconSize(QSize(16, 16));
int btn_wh = style()->pixelMetric(QStyle::PM_SmallIconSize);
QSize icon_size(btn_wh, btn_wh);
btn_wh += 2 * style()->pixelMetric(QStyle::PM_DockWidgetTitleBarButtonMargin, 0, this);
QSize btn_size(btn_wh, btn_wh);
btn_dock->setIcon(style()->standardIcon(QStyle::SP_TitleBarNormalButton));
btn_dock->setIconSize(icon_size);
btn_dock->setFixedSize(btn_size);
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->setIcon(style()->standardIcon(QStyle::SP_DockWidgetCloseButton));
btn_hide->setIconSize(icon_size);
btn_hide->setFixedSize(btn_size);
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);
setTitleBarWidget(header);
}

View File

@@ -0,0 +1,37 @@
#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) {lbl_title->setText(title); QDockWidget::setWindowTitle(title);}
void setWindowIcon(const QIcon & icon) {lbl_icon->setPixmap(icon.pixmap(QSize(24, 24))); QDockWidget::setWindowIcon(icon);}
private:
void init();
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,333 @@
/*
Peri4 Paint
Copyright (C) 2017 Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "emainwindow.h"
#include <QFileDialog>
#include <QMessageBox>
#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) {
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"));
setChanged(false);
initMenus();
tid = startTimer(200);
}
EMainWindow::~EMainWindow() {
saveSession();
}
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::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 & )));
session.addEntry("EMainWindow", this);
}
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);
t->setIconSize(dockTabsIconSIze());
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 (dock == 0) continue;
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::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;
load(ret);
}
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();
save(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;
save(ret);
return true;
}

View File

@@ -0,0 +1,109 @@
#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
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() {}
protected:
// Qt`s overloaded
void showEvent(QShowEvent * );
void closeEvent(QCloseEvent * );
bool eventFilter(QObject * o, QEvent * e);
void timerEvent(QTimerEvent * e);
QMenu * createPopupMenu();
void init(const QString & config) {session.setFile(config); initMenus(); initSession(); loadSession();}
void initMenus();
void initSession();
virtual void saveSession();
virtual void loadSession();
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);}
QAction action_show_all_tools, action_hide_all_tools, action_show_all_docks, action_hide_all_docks;
QString file_name, title_src;
QList<QTabBar * > tbars;
QList<QDockWidget * > tdocks;
SessionManager session;
bool isChanged, first_show;
int tid;
private slots:
void changedDock();
// void changedDockClose(QObject * dock);
void closeDock(int index);
virtual void sessionLoading(QPIConfig & conf) {}
virtual void sessionSaving(QPIConfig & conf) {}
public slots:
void changed() {setChanged(true);}
void newFile();
void openFile();
bool saveFile(bool ask = false);
bool saveAsFile();
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,140 @@
#include "historyview.h"
HistoryView::HistoryView(QWidget* parent): QListWidget(parent) {
setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
setSelectionMode(QAbstractItemView::MultiSelection);
setEditTriggers(NoEditTriggers);
active_ = true;
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() {
}
void HistoryView::addEntry(int action, int count_, const QString & suffix) {
if (!active_) return;
int cnt = count();
for (int i = index; i < cnt; ++i)
if (i >= 0) delete takeItem(index);
addItem(new QListWidgetItem(actions_.value(action).icon, actionText(action, count_) + suffix));
index = count();
history_.resize(index);
history_.back() = Entry(action);
checkLimit();
emit commandRequest(history_.back().command);
scrollToItem(item(index - 1));
blockSignals(true);
for (int i = 0; i < index; ++i)
item(i)->setSelected(true);
blockSignals(false);
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);
itemSelectionChanged();
}
void HistoryView::itemSelectionChanged() {
if (!active_) return;
if (index < 1) index = 1;
//qDebug() << "changed" << count();
blockSignals(true);
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);
itemSelectionChanged();
}
void HistoryView::redo() {
if (index >= count()) return;
index++;
emit commandExecute(history_[index - 1].command);
itemSelectionChanged();
}

View File

@@ -0,0 +1,74 @@
#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(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_;}
int limit() const {return limit_;}
QColor historyColor() const {return color_;}
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_;
int index, limit_;
public slots:
void setActive(bool yes) {active_ = 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);
};
#endif // HISTORYVIEW_H

View File

@@ -0,0 +1,290 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.0" language="ru_RU">
<context>
<name>Graphic</name>
<message>
<location filename="../graphic.ui" line="44"/>
<source>Autofit</source>
<translation>Автомасштаб</translation>
</message>
<message>
<location filename="../graphic.ui" line="61"/>
<source>Grid</source>
<translation>Сетка</translation>
</message>
<message>
<location filename="../graphic.ui" line="84"/>
<source>Cursor axis</source>
<translation>Плавающие оси</translation>
</message>
<message>
<location filename="../graphic.ui" line="104"/>
<source>Only expand Y</source>
<translation>Только расширять Y</translation>
</message>
<message>
<location filename="../graphic.ui" line="124"/>
<source>Only expand X</source>
<translation>Только расширять X</translation>
</message>
<message>
<location filename="../graphic.ui" line="144"/>
<source>Border inputs</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../graphic.ui" line="167"/>
<source>Legend</source>
<translation>Легенда</translation>
</message>
<message>
<location filename="../graphic.ui" line="190"/>
<source>Configure ...</source>
<translation>Настроить ...</translation>
</message>
<message>
<location filename="../graphic.ui" line="207"/>
<source>Save image ...</source>
<translation>Сохранить изображение ...</translation>
</message>
<message>
<location filename="../graphic.ui" line="240"/>
<source>Clear</source>
<translation>Очистить</translation>
</message>
<message>
<location filename="../graphic.ui" line="257"/>
<source>Close</source>
<translation>Закрыть</translation>
</message>
<message>
<location filename="../graphic.ui" line="408"/>
<source>Cursor: ( ; )</source>
<translation>Курсор: ( ; )</translation>
</message>
<message>
<location filename="../graphic.cpp" line="198"/>
<location filename="../graphic.cpp" line="784"/>
<source>Cursor: </source>
<translation>Курсор: </translation>
</message>
<message>
<location filename="../graphic.cpp" line="209"/>
<source>Selection</source>
<translation>Выделение</translation>
</message>
<message>
<location filename="../graphic.cpp" line="210"/>
<source>Size</source>
<translation>Размер</translation>
</message>
<message>
<location filename="../graphic.cpp" line="214"/>
<location filename="../graphic.cpp" line="220"/>
<source>Range</source>
<translation>Диапазон</translation>
</message>
<message>
<location filename="../graphic.cpp" line="215"/>
<location filename="../graphic.cpp" line="221"/>
<source>Length</source>
<translation>Длина</translation>
</message>
<message>
<location filename="../graphic.cpp" line="322"/>
<location filename="../graphic.cpp" line="367"/>
<source>Cursor</source>
<translation>Курсор</translation>
</message>
<message>
<location filename="../graphic.cpp" line="508"/>
<source>Save Image</source>
<translation>Сохранить изображение</translation>
</message>
<message>
<location filename="../graphic.cpp" line="553"/>
<source>y(x)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../graphic.cpp" line="1096"/>
<source>Check all</source>
<translation>Выбрать все</translation>
</message>
</context>
<context>
<name>GraphicConf</name>
<message>
<location filename="../graphic_conf.ui" line="17"/>
<source>Graphic parameters</source>
<translation>Параметры графика</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="32"/>
<source>Appearance</source>
<translation>Внешний вид</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="46"/>
<source>Border inputs</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="53"/>
<source>Antialiasing</source>
<translation>Сглаживание</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="60"/>
<source>Status bar</source>
<translation>Панель статуса</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="67"/>
<source>OpenGL</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="74"/>
<source>Legend</source>
<translation>Легенда</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="94"/>
<source>Background color:</source>
<translation>Цвет фона:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="114"/>
<source>Text color:</source>
<translation>Цвет текста:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="133"/>
<source>Graphics</source>
<translation>Графики</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="161"/>
<location filename="../graphic_conf.ui" line="263"/>
<source>Color:</source>
<translation>Цвет:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="175"/>
<location filename="../graphic_conf.ui" line="277"/>
<source>Style:</source>
<translation>Стиль:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="185"/>
<source>Lines width:</source>
<translation>Толщина линий:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="205"/>
<source>Points width:</source>
<translation>Толщина точек:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="225"/>
<source>Fill:</source>
<translation>Заливка:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="245"/>
<source>Grid</source>
<translation>Сетка</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="287"/>
<source>Width:</source>
<translation>Толщина:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="317"/>
<source>Step X:</source>
<translation>Шаг X:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="324"/>
<source>Step Y:</source>
<translation>Шаг Y:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="347"/>
<source>Auto step</source>
<translation>Автоматический шаг</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="380"/>
<source>Margins</source>
<translation>Поля</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="392"/>
<location filename="../graphic_conf.ui" line="402"/>
<location filename="../graphic_conf.ui" line="422"/>
<location filename="../graphic_conf.ui" line="462"/>
<location filename="../graphic_conf.ui" line="482"/>
<source> px</source>
<translation> пикс</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="412"/>
<source>All:</source>
<translation>Все:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="432"/>
<source>Right:</source>
<translation>Правое:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="442"/>
<source>Left:</source>
<translation>Левое:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="452"/>
<source>Bottom:</source>
<translation>Нижнее:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="472"/>
<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(application "")

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,31 @@
#ifndef EDOCKWIDGETPLUGIN_H
#define EDOCKWIDGETPLUGIN_H
#include <QDesignerCustomWidgetInterface>
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,31 @@
#ifndef EMAINWINDOWPLUGIN_H
#define EMAINWINDOWPLUGIN_H
#include <QDesignerCustomWidgetInterface>
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,31 @@
#ifndef HISTORYVIEWPLUGIN_H
#define HISTORYVIEWPLUGIN_H
#include <QDesignerCustomWidgetInterface>
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,19 @@
#include "edockwidgetplugin.h"
#include "emainwindowplugin.h"
#include "historyviewplugin.h"
#include "qad_application.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;
}
Q_EXPORT_PLUGIN2(qad_graphic_plugin, QADApplication)

View File

@@ -0,0 +1,21 @@
#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)
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,33 @@
<RCC>
<qresource prefix="/">
<file>lang/qad_application_ru.ts</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/graphic.png</file>
<file>../icons/edockwidget.png</file>
<file>../icons/layer-visible-off.png</file>
<file>../icons/layer-visible-on.png</file>
<file>../icons/historyview.png</file>
<file>../icons/clear-history.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

196
qad/application/ribbon.cpp Normal file
View File

@@ -0,0 +1,196 @@
#include "ribbon.h"
#include <QScrollBar>
Ribbon::Ribbon(QMainWindow * parent_): QToolBar() {
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) {
if (o == parent) {
if (e->type() == QEvent::Resize || e->type() == QEvent::WindowActivate)
_resize();
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::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;
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);
QGroupBox * g;
QBoxLayout * l, * tl;
QToolButton * b;
//tab->setIconSize(QSize(32, 32));
foreach (QAction * i, lm) {
if (i->menu() == 0) continue;
la = i->menu()->actions();
tab->addTab(new QWidget(), i->icon(), i->text());
/*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);
tl->setContentsMargins(2, 2, 2, 2);
g = new QGroupBox();
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 QGroupBox();
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->toolTip());
//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);
}
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) {
tab->setIconSize(size);
_resize();
}

62
qad/application/ribbon.h Normal file
View File

@@ -0,0 +1,62 @@
#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();
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,2 @@
set(LIBS ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} qad_widgets qad_utils)
qad_project(blockview "${LIBS}")

View File

@@ -0,0 +1,45 @@
#include "alignedtextitem.h"
#include <QPainter>
#include <QDebug>
AlignedTextItem::AlignedTextItem(QGraphicsItem * parent): QGraphicsItem(parent), text_(this) {
align_ = Qt::AlignTop | Qt::AlignHCenter;
text_.setData(1003, true);
_move();
}
AlignedTextItem::AlignedTextItem(const QString & text, QGraphicsItem * parent): QGraphicsItem(parent), text_(this) {
align_ = Qt::AlignTop | Qt::AlignHCenter;
text_.setData(1003, true);
setText(text);
}
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,45 @@
#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) {text_.setFont(f); _move();}
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();}
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};
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_;
};
#endif // ALIGNEDTEXTITEM_H

104
qad/blockview/blockbase.cpp Normal file
View File

@@ -0,0 +1,104 @@
#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(5) << (ipixmap->pixmap());
} 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;
}
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;
}

57
qad/blockview/blockbase.h Normal file
View File

@@ -0,0 +1,57 @@
#ifndef BLOCKBASE_H
#define BLOCKBASE_H
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsItem>
#include <QGraphicsObject>
#include <QGraphicsEllipseItem>
#include <QGraphicsSceneHoverEvent>
#include <QGraphicsSceneMouseEvent>
#include <QStack>
#include "propertystorage.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)
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,733 @@
#include "blockbusitem.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;
updateGeometry();
}
void BlockBusItem::_init() {
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.;
moved = deleted = mark_in = mark_out = new_segment = mm_cancel = lm_point = false;
}
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::clear() {
pol.clear();
segments.clear();
updateGeometry();
}
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);
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;
}
}
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();
}
void BlockBusItem::checkDelete() {
if (pol.size() < 2 || segments.size() < 1) deleteLater();
}
void BlockBusItem::emitAction(BlockItemBase::Action a) {
QMetaObject::invokeMethod(scene()->views().back(), "actionEvent", 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();
testPoint(sp, &selPoint, &selSegment);
if (selPoint >= 0 || selSegment >= 0) {
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());
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 (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();
emitAction(BlockItemBase::BusPointRemove);
return;
}
if (selSegment >= 0 && selSegment <= segments.size() - 1) {
removeSegment(selSegment);
simplify();
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);
reconnect();
emitAction(lm_point ? BlockItemBase::BusPointMove : BlockItemBase::BusSegmentMove);
}
moved = new_segment = false;
QGraphicsObject::mouseReleaseEvent(e);
}
void BlockBusItem::paint(QPainter * p, const QStyleOptionGraphicsItem * o, QWidget * w) {
ph.setWidthF(pen_width + 1.);
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.);
/*
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(), 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.);
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), 3, 3);
p->restore();
}
if (selSegment >= 0) {
p->save();
p->setPen(ph);
p->drawLine(pol[segments[selSegment].first], pol[segments[selSegment].second]);
p->restore();
}
}
QRectF BlockBusItem::boundingRect() const {
QPolygonF p(pol);
p << new_end;
return enlargedRect(p.boundingRect(), 0, 0, 10.f);
}

View File

@@ -0,0 +1,119 @@
#ifndef BLOCKBUSITEM_H
#define BLOCKBUSITEM_H
#include "blockitem.h"
class BlockBusItem: public QGraphicsObject, public PropertyStorage {
//Q_OBJECT
Q_INTERFACES(QGraphicsItem)
//Q_PROPERTY(double width READ width WRITE setWidth)
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;}
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;}
void appendPoint(const QPointF & p);
void appendPoint(qreal x, qreal y) {appendPoint(QPointF(x, 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) {pol.translate(dp); prepareGeometryChange();}
void movePoint(int index, const QPointF & dp) {pol[index] += dp; prepareGeometryChange();}
double width() const {return pen_width;}
void setWidth(const double & w) {pen_width = w; update();}
void setColor(const QColor & c) {pu.setColor(c); bu.setColor(c); update();}
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();
void 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;
int selPoint, selSegment, max_ep, bus_type, state_;
bool moved, deleted, mark_in, mark_out, new_segment, mm_cancel, lm_point;
};
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,347 @@
#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;
ui->setupUi(this);
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);
drawtools->setAlignCompact(true);
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::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::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() {
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());
}
}
}
void BlockEditor::on_buttonLoad_clicked() {
QString c = QFileDialog::getOpenFileName(this, "Save block model to file", cur_file, "*.blockmodel");
if (!c.isEmpty()) {
QFile f(c);
if (f.open(QIODevice::ReadOnly)) {
cur_file = c;
loadModel(f.readAll());
}
}
}
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,81 @@
#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
public:
explicit BlockEditor(QWidget *parent = 0);
~BlockEditor();
public slots:
void loadModel(const QByteArray & model);
QByteArray saveModel();
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_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 cur_file;
bool init;
};
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,458 @@
<?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>901</width>
<height>861</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</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="groupBox_2">
<property name="title">
<string>Block parameters</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<layout class="QFormLayout" name="formLayout">
<property name="margin">
<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="groupBox">
<property name="title">
<string>Pins</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="margin">
<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="qad_blockview.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="qad_blockview.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="qad_blockview.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="qad_blockview.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="margin">
<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"/>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QPushButton" name="buttonSave">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Save</string>
</property>
<property name="icon">
<iconset resource="qad_blockview.qrc">
<normaloff>:/icons/document-save.png</normaloff>:/icons/document-save.png</iconset>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="buttonLoad">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Load</string>
</property>
<property name="icon">
<iconset resource="qad_blockview.qrc">
<normaloff>:/icons/document-open.png</normaloff>:/icons/document-open.png</iconset>
</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="qad_blockview.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="qad_blockview.qrc">
<normaloff>:/icons/edit-delete.png</normaloff>:/icons/edit-delete.png</iconset>
</property>
<property name="text">
<string>Remove items</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="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,10 @@
#include <QApplication>
#include "blockeditor.h"
int main(int argc, char * argv[]) {
QApplication a(argc, argv);
BlockEditor w;
w.show();
return a.exec();
}

448
qad/blockview/blockitem.cpp Normal file
View File

@@ -0,0 +1,448 @@
#include "blockitem.h"
BlockItemPin::BlockItemPin(Qt::Alignment a, int bus_type_, const QString & text_, QGraphicsItem * _parent): QGraphicsItem(_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);
setState(Disconnected);
setAlignment(a);
setBusType(bus_type_);
setText(text_);
setZValue(2.);
setDirection(BlockItemPin::InputOutput);
_reparent();
}
void BlockItemPin::resizePin(double r) {
ell_item.setRect(-r, -r, r+r, r+r);
}
void BlockItemPin::_init(bool affect_parent) {
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);
}
QVariant BlockItemPin::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant & value) {
if (change == QGraphicsItem::ItemParentChange)
_reparent();
return QGraphicsItem::itemChange(change, value);
}
void BlockItemPin::hoverEnterEvent(QGraphicsSceneHoverEvent * e) {
bool m_pin_mc(false);
if (scene()) if (!scene()->views().isEmpty())
QMetaObject::invokeMethod(scene()->views()[0], "getPinMC", Q_ARG(bool*, &m_pin_mc));
if ((state() != Disconnected) && !m_pin_mc) return;
saveState();
setState(BlockItemPin::Hover);
update();
}
void BlockItemPin::hoverLeaveEvent(QGraphicsSceneHoverEvent * e) {
restoreState();
update();
}
#define BLOCKITEM_DEFAULT_PIN_MARGIN 20
BlockItem::BlockItem(QGraphicsItem * parent): QGraphicsObject(parent), PropertyStorage(),
g_main(this), g_selection(this) {
setData(1006, "item");
setZValue(1.);
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), 1., Qt::DotLine);
p.setCosmetic(true);
g_selection.setPen(p);
g_selection.setBrush(QColor(128, 128, 255, 32));
pins_margin = BLOCKITEM_DEFAULT_PIN_MARGIN;
//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(-g_main.rect().center());
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();
}
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();
it.value().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);
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;
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:
tp = cs.getData<QVector<BlockItemPin * > >();
foreach (BlockItemPin * p, tp) addPin(p);
break;
case 6:
dl = cs.getData<QList<QGraphicsItem * > >();
foreach (QGraphicsItem * d, dl) addDecor(d);
break;
case 7: setPinsMargin(cs.getData<int>()); break;
}
}
}
QByteArray BlockItem::save() const {
ChunkStream cs;
QMap<QString, QList<BlockItem::Property> > pp;
foreach (BlockItemPin * p, pins()) {
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));
return cs.data();
}
void BlockItem::load(const QByteArray & data) {
if (data.isEmpty()) return;
ChunkStream cs(data);
QMap<QString, QList<BlockItem::Property> > _p;
while (!cs.atEnd()) {
switch (cs.read()) {
case 1: setPos(cs.getData<QPointF>()); break;
case 2: setRotation(cs.getData<qreal>()); break;
case 3: props = cs.getData<QList<BlockItem::Property> >(); break;
case 5:
_p = cs.getData<QMap<QString, QList<BlockItem::Property> > >();
foreach (BlockItemPin * p, pins())
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;
}
}
}
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::boundingRect() const {
return g_main.mapRectToParent(g_main.boundingRect());
}
void BlockItem::mouseMoveEvent(QGraphicsSceneMouseEvent * event) {
//QGraphicsItem::mouseMoveEvent(event);
}
#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(), _POS(pins_margin));
cp = pins_.value(Qt::AlignRight);
for (int i = 0; i < cp.size(); ++i) cp[i]->setPos(right(), _POS(pins_margin));
}
#undef _POS
void BlockItem::paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget) {
//if ()
}
QVariant BlockItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant & value) {
if (change == QGraphicsItem::ItemSelectedChange)
g_selection.setVisible(value.toBool());
return QGraphicsItem::itemChange(change, value);
}

207
qad/blockview/blockitem.h Normal file
View File

@@ -0,0 +1,207 @@
#ifndef BLOCKITEM_H
#define BLOCKITEM_H
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsItem>
#include <QGraphicsObject>
#include <QGraphicsEllipseItem>
#include <QGraphicsSceneHoverEvent>
#include <QGraphicsSceneMouseEvent>
#include <QStack>
#include <QDebug>
#include <qmath.h>
#include "blockbase.h"
#include "alignedtextitem.h"
#include "chunkstream.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 BlockItem;
class BlockBusItem;
class BlockItemPin: public QGraphicsItem, public PropertyStorage
{
friend class BlockView;
friend class BlockItem;
public:
BlockItemPin(Qt::Alignment a = Qt::AlignLeft, int bus_type = 0, const QString & text_ = QString(), QGraphicsItem * 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) {state_ = s; setBrush(br[int(state_)]); update();}
void saveState() {sstate_.push(state_);}
bool restoreState() {if (sstate_.isEmpty()) return false; setState(sstate_.pop()); return true;}
void clearStateStack() {sstate_.clear();}
void resizePin(double r = 7.);
BlockItem * parent() const {return parent_;}
QList<BlockBusItem * > connectedBuses() const {return buses_;}
enum {Type = UserType + 3};
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();
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];
};
class BlockItem: public QGraphicsObject, public PropertyStorage
{
friend class BlockView;
friend class BlockItemPin;
friend class DrawTools;
Q_OBJECT
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();}
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();
enum {Type = UserType + 1};
protected:
void _resize(QSizeF s);
int type() const {return Type;}
QRectF boundingRect() const;
void mouseMoveEvent(QGraphicsSceneMouseEvent * 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_;
};
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

1630
qad/blockview/blockview.cpp Normal file
View File

@@ -0,0 +1,1630 @@
#include "blockview.h"
#include <qmath.h>
#include <QScrollBar>
#include <QGraphicsSceneMouseEvent>
#include <QApplication>
#include <QAction>
#include <QShortcut>
#include <QVector2D>
#include <QClipboard>
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() {
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);
connect(scene_, SIGNAL(sceneRectChanged(QRectF)), this, SLOT(adjustThumb()));
connect(scene_, SIGNAL(selectionChanged()), this, SLOT(sceneSelectionChanged()));
centerOn(scene_->sceneRect().center());
setCacheMode(CacheBackground);
setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
setResizeAnchor(QGraphicsView::AnchorUnderMouse);
setRenderHint(QPainter::Antialiasing);
setRenderHint(QPainter::SmoothPixmapTransform);
setMouseTracking(true);
grid_visible = grid_snap = pm_connect = navigation = m_connect = m_trace_with_buses = minimap = true;
mm_drag = moved = new_branch = new_bus = mm_cancel = iconnect = mm_copy = m_pin_mc = mm_thumb = false;
match_bus = bus_from = 0;
mm_ci = 0;
hpin = 0;
grid_step = 10.;
grid_points = 1;
grid_pen = QPen(Qt::lightGray, 1, Qt::NoPen);
thumb_hide_delay = 500;
smode = BlockView::MultiSelection;
cur_scl = thumb_scl = 1.;
_talpha = 0.;
ae_enabled = true;
thumb_size = QSizeF(200, 200);
sel_rect.setZValue(999.);
sel_rect.hide();
QColor sc = palette().color(QPalette::Highlight);
sc.setAlphaF(0.6);
QPen pen(sc.darker(200), 2., Qt::DotLine);
pen.setCosmetic(true);
sel_rect.setPen(pen);
sc.setAlphaF(0.2);
sel_rect.setBrush(QBrush(sc));
/*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::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);
break;
}
if (i->data(1005) == "connection") {
if (qgraphicsitem_cast<BlockBusItem*>(i)->isBusSelected()) {
emit busDoubleClicked(qgraphicsitem_cast<BlockBusItem*>(i));
break;
}
}
}
//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();
tmp_bus.hide();
tmp_bus.clear();
}
if (new_branch && mm_cancel) {
new_branch = false;
tmp_bus.hide();
tmp_bus.clear();
}
if (moved && mm_cancel) {
moved = false;
restoreSelState();
tmp_bus.hide();
tmp_bus.clear();
}
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()) {
while (mm_ci->parentItem() != 0)
mm_ci = mm_ci->parentItem();
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();
tmp_bus.setBusType(qgraphicsitem_cast<BlockItemPin*>(mm_ci)->busType());
tmp_bus.setEndpointsNumber(3);
tmp_bus.clear();
tmp_bus.show();
new_bus = true;
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);
}
}
}
cur_scl = qSqrt(transform().determinant());
//return true;
break;
case QEvent::GraphicsSceneMouseMove:
//qDebug() << "move" << (mm_ci != 0 ? mm_ci : 0);
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)
hoverAcceptedPin(hpin);
else
hpin = 0;
} else
unhoverPins();
if (new_branch) {
matchBus();
break;
}
trace(trace_from, me->scenePos(), &tmp_bus);
matchBus();
}
}
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);
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) {
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) {
tmp_bus.hide();
}
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()) {
//qDebug() << "!!!";
if (match_bus == 0) {
BlockBusItem * nb = new BlockBusItem(tmp_bus);
loadBus(nb);
addItem(nb);
} else {
if (connectTmpToBus(match_bus)) {
emitActionEvent(BlockItemBase::BusAdd, QList<QGraphicsItem*>() << match_bus);
emit connectionsChanged();
}
}
unmarkPins();
tmp_bus.hide();
tmp_bus.clear();
reconnectAll();
}
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 * event) {
if (!navigation) return;
if (event->modifiers().testFlag(Qt::ControlModifier)) {
double scl = 1. + event->delta() / 500.;
scale(scl, scl);
return;
}
QGraphicsView::wheelEvent(event);
}
void BlockView::mousePressEvent(QMouseEvent * event) {
press_point = event->pos();
QGraphicsView::mousePressEvent(event);
}
void BlockView::mouseMoveEvent(QMouseEvent * event) {
if (navigation) {
if (event->buttons().testFlag(Qt::MidButton)) {
QPoint dp = (press_point - event->pos());
horizontalScrollBar()->setValue(horizontalScrollBar()->value() + dp.x());
verticalScrollBar()->setValue(verticalScrollBar()->value() + dp.y());
press_point = event->pos();
return;
}
}
QGraphicsView::mouseMoveEvent(event);
}
void BlockView::keyPressEvent(QKeyEvent * e) {
if (e->key() == Qt::Key_Shift) {
if (tmp_bus.isVisible()) {
wavetrace.setPreferredDirection((BlockViewWavetrace::Direction)(1 - wavetrace.preferredDirection()));
trace(last_trace_from, trace_to, &tmp_bus);
}
return;
}
QGraphicsView::keyPressEvent(e);
}
void BlockView::resizeEvent(QResizeEvent * event) {
QGraphicsView::resizeEvent(event);
adjustThumb();
}
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, "repaint", 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->eraseRect(rect);
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(), grid_points, 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;
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 actionEvent(action, items);
}
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) {
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);
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);
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))
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::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) {
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() == tmp_bus.busType())
p->setState(BlockItemPin::Accept);
} else {
if (p->busType() == tmp_bus.busType() && p->state() == BlockItemPin::Disconnected)
p->setState(BlockItemPin::Accept);
}
}
}
}
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) {
if (!pin) return;
pin->resizePin(12.);
}
void BlockView::unhoverPins() {
QList<QGraphicsItem * > gi = scene_->items();
foreach (QGraphicsItem * i, gi)
if (i->data(1004) == "pin")
((BlockItemPin*)i)->resizePin();
}
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) {
QSet<BlockItem * > bis = QSet<BlockItem * >::fromList(bi->connectedBlocks());
if ((bis - sis).isEmpty())
ret << bi;
}
return ret;
}
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::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;
widget_thumb.setGeometry(QRect(QPoint(width() - tr.width() - 10 - verticalScrollBar()->width(),
height() - tr.height() - 10 - horizontalScrollBar()->height()), tr.toSize()));
}
void BlockView::newBranch(BlockBusItem * item) {
bus_from = item;
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::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;
tmp_bus.hide();
tmp_bus.clear();
}
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, "repaint", Qt::QueuedConnection);
if (_talpha <= 0.01) widget_thumb.hide();
else widget_thumb.show();
}
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->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) {
//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) {
scale(factor, factor);
}
void BlockView::zoomReset() {
cur_scl = qSqrt(transform().determinant());
zoom(1. / 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.isEmpty()) 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() {
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);
}

200
qad/blockview/blockview.h Normal file
View File

@@ -0,0 +1,200 @@
#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"
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
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 traceConsiderBuses READ isTraceConsiderBuses WRITE setTraceConsiderBuses)
Q_PROPERTY(bool pinMulticonnect READ isPinMulticonnectEnabled WRITE setPinMulticonnectEnabled)
Q_PROPERTY(bool miniMap READ isMiniMapEnabled WRITE setMiniMapEnabled)
Q_PROPERTY(double _thumb READ _thumb WRITE _setThumb 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 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;}
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);
protected:
void _init();
void _updateBack();
bool eventFilter(QObject * o, QEvent * e);
void stopTimer(int & tid);
void restartTimer(int & tid, int msecs);
void timerEvent(QTimerEvent * e);
void wheelEvent(QWheelEvent * event);
void mousePressEvent(QMouseEvent * event);
void mouseMoveEvent(QMouseEvent * event);
void keyPressEvent(QKeyEvent * event);
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);
void clearBusStates();
void matchBus();
bool connectTmpToBus(BlockBusItem* bus);
void markPins(int bus_type);
void unmarkPins(bool to_normal = false);
void hoverAcceptedPin(BlockItemPin * pin);
void unhoverPins();
void simplifyBuses();
void moveBuses(const QList<QGraphicsItem * > & items, QPointF dp);
QList<BlockBusItem * > internalBuses(const QList<BlockItem * > & items);
QList<BlockItem * > selectedBlocks() const;
QList<QGraphicsItem * > selectedDecors() const;
double _thumb() const {return _talpha;}
void scrollFromThumb();
void deleteCopyTemp();
void emitActionEvent(BlockItemBase::Action action, QList<QGraphicsItem * > items);
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<BlockBusItem * > copy_buses;
BlockBusItem tmp_bus, * match_bus, * bus_from;
BlockItemPin * hpin;
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;
QSizeF thumb_size;
QPen grid_pen;
SelectionMode smode;
QImage im_scene;
QWidget widget_thumb;
Qt::KeyboardModifiers mm_mods;
QPropertyAnimation thumb_anim;
int timer_thumb, thumb_hide_delay;
bool mm_drag, new_bus, new_branch, moved, mm_cancel, iconnect, mm_copy, mm_thumb, ae_enabled;
bool grid_visible, grid_snap, pm_connect, navigation, m_connect, m_trace_with_buses, m_pin_mc, minimap;
double grid_step, grid_points, cur_scl, _talpha, thumb_scl;
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 _setThumb(double v);
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 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 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);
signals:
void blockDoubleClicked(BlockItem * );
void busDoubleClicked(BlockBusItem * );
void actionEvent(BlockItemBase::Action action, QList<QGraphicsItem * > items);
void blockRemoved(BlockItem * item);
void connectionsChanged();
void copyEnabledChanged(bool);
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // BLOCKVIEW_H

View File

@@ -0,0 +1,197 @@
#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;
//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);
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 {Horizontal = 0, Vertical = 1};
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

791
qad/blockview/drawtools.cpp Normal file
View File

@@ -0,0 +1,791 @@
#include "drawtools.h"
#include "ui_drawtools.h"
#include "alignedtextitem.h"
#include <QGraphicsLineItem>
#include <QLineEdit>
#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) {
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) {
emit textEditRequest();
}
if (ipixmap) {
emit pixmapEditRequest();
}
}
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);
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);
widget_props->setEnabled(false);
setAlignCompact(false);
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->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->comboText, SIGNAL(editTextChanged(QString)), this, SLOT(propertyChanged()));
connect(ui->comboText->lineEdit(), SIGNAL(editingFinished()), this, SLOT(changeFinished()));
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::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);
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;
}
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->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);
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());
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());
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) {
} 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()));
ishape->setBrush(ui->colorButtonBrush->color());
if (resize_enabled)
size_item.assignObject(ishape);
}
} else if (iline) {
iline->setPen(QPen(ui->colorButtonPen->color(), ui->spinThick->value()));
if (resize_enabled)
size_item.assignObject(iline);
}
}
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::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_edit.setPlainText(ui->comboText->lineEdit()->text());
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();
}

129
qad/blockview/drawtools.h Normal file
View File

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

666
qad/blockview/drawtools.ui Normal file
View File

@@ -0,0 +1,666 @@
<?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>656</width>
<height>111</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QStackedWidget" name="stackedProperties">
<property name="currentIndex">
<number>3</number>
</property>
<widget class="QWidget" name="pageText">
<layout class="QHBoxLayout" name="horizontalLayout_6">
<property name="margin">
<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="qad_blockview.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="margin">
<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="iconSize">
<size>
<width>27</width>
<height>22</height>
</size>
</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="iconSize">
<size>
<width>27</width>
<height>22</height>
</size>
</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="margin">
<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="margin">
<number>0</number>
</property>
<item>
<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>Size: </string>
</property>
</widget>
</item>
<item>
<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>
<widget class="QLabel" name="label_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>X</string>
</property>
</widget>
</item>
<item>
<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>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Width: </string>
</property>
</widget>
</item>
<item>
<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>
</layout>
</widget>
<widget class="QWidget" name="pageImage">
<layout class="QHBoxLayout" name="horizontalLayout_9">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QPushButton" name="buttonImage">
<property name="text">
<string>Load image ...</string>
</property>
<property name="icon">
<iconset resource="qad_blockview.qrc">
<normaloff>:/icons/document-open.png</normaloff>:/icons/document-open.png</iconset>
</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>
</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>
</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="qad_blockview.qrc"/>
</resources>
<connections/>
</ui>

Binary file not shown.

View File

@@ -0,0 +1,290 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.0" language="ru_RU">
<context>
<name>Graphic</name>
<message>
<location filename="../graphic.ui" line="44"/>
<source>Autofit</source>
<translation>Автомасштаб</translation>
</message>
<message>
<location filename="../graphic.ui" line="61"/>
<source>Grid</source>
<translation>Сетка</translation>
</message>
<message>
<location filename="../graphic.ui" line="84"/>
<source>Cursor axis</source>
<translation>Плавающие оси</translation>
</message>
<message>
<location filename="../graphic.ui" line="104"/>
<source>Only expand Y</source>
<translation>Только расширять Y</translation>
</message>
<message>
<location filename="../graphic.ui" line="124"/>
<source>Only expand X</source>
<translation>Только расширять X</translation>
</message>
<message>
<location filename="../graphic.ui" line="144"/>
<source>Border inputs</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../graphic.ui" line="167"/>
<source>Legend</source>
<translation>Легенда</translation>
</message>
<message>
<location filename="../graphic.ui" line="190"/>
<source>Configure ...</source>
<translation>Настроить ...</translation>
</message>
<message>
<location filename="../graphic.ui" line="207"/>
<source>Save image ...</source>
<translation>Сохранить изображение ...</translation>
</message>
<message>
<location filename="../graphic.ui" line="240"/>
<source>Clear</source>
<translation>Очистить</translation>
</message>
<message>
<location filename="../graphic.ui" line="257"/>
<source>Close</source>
<translation>Закрыть</translation>
</message>
<message>
<location filename="../graphic.ui" line="408"/>
<source>Cursor: ( ; )</source>
<translation>Курсор: ( ; )</translation>
</message>
<message>
<location filename="../graphic.cpp" line="198"/>
<location filename="../graphic.cpp" line="784"/>
<source>Cursor: </source>
<translation>Курсор: </translation>
</message>
<message>
<location filename="../graphic.cpp" line="209"/>
<source>Selection</source>
<translation>Выделение</translation>
</message>
<message>
<location filename="../graphic.cpp" line="210"/>
<source>Size</source>
<translation>Размер</translation>
</message>
<message>
<location filename="../graphic.cpp" line="214"/>
<location filename="../graphic.cpp" line="220"/>
<source>Range</source>
<translation>Диапазон</translation>
</message>
<message>
<location filename="../graphic.cpp" line="215"/>
<location filename="../graphic.cpp" line="221"/>
<source>Length</source>
<translation>Длина</translation>
</message>
<message>
<location filename="../graphic.cpp" line="322"/>
<location filename="../graphic.cpp" line="367"/>
<source>Cursor</source>
<translation>Курсор</translation>
</message>
<message>
<location filename="../graphic.cpp" line="508"/>
<source>Save Image</source>
<translation>Сохранить изображение</translation>
</message>
<message>
<location filename="../graphic.cpp" line="553"/>
<source>y(x)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../graphic.cpp" line="1096"/>
<source>Check all</source>
<translation>Выбрать все</translation>
</message>
</context>
<context>
<name>GraphicConf</name>
<message>
<location filename="../graphic_conf.ui" line="17"/>
<source>Graphic parameters</source>
<translation>Параметры графика</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="32"/>
<source>Appearance</source>
<translation>Внешний вид</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="46"/>
<source>Border inputs</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="53"/>
<source>Antialiasing</source>
<translation>Сглаживание</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="60"/>
<source>Status bar</source>
<translation>Панель статуса</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="67"/>
<source>OpenGL</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="74"/>
<source>Legend</source>
<translation>Легенда</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="94"/>
<source>Background color:</source>
<translation>Цвет фона:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="114"/>
<source>Text color:</source>
<translation>Цвет текста:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="133"/>
<source>Graphics</source>
<translation>Графики</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="161"/>
<location filename="../graphic_conf.ui" line="263"/>
<source>Color:</source>
<translation>Цвет:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="175"/>
<location filename="../graphic_conf.ui" line="277"/>
<source>Style:</source>
<translation>Стиль:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="185"/>
<source>Lines width:</source>
<translation>Толщина линий:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="205"/>
<source>Points width:</source>
<translation>Толщина точек:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="225"/>
<source>Fill:</source>
<translation>Заливка:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="245"/>
<source>Grid</source>
<translation>Сетка</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="287"/>
<source>Width:</source>
<translation>Толщина:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="317"/>
<source>Step X:</source>
<translation>Шаг X:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="324"/>
<source>Step Y:</source>
<translation>Шаг Y:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="347"/>
<source>Auto step</source>
<translation>Автоматический шаг</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="380"/>
<source>Margins</source>
<translation>Поля</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="392"/>
<location filename="../graphic_conf.ui" line="402"/>
<location filename="../graphic_conf.ui" line="422"/>
<location filename="../graphic_conf.ui" line="462"/>
<location filename="../graphic_conf.ui" line="482"/>
<source> px</source>
<translation> пикс</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="412"/>
<source>All:</source>
<translation>Все:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="432"/>
<source>Right:</source>
<translation>Правое:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="442"/>
<source>Left:</source>
<translation>Левое:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="452"/>
<source>Bottom:</source>
<translation>Нижнее:</translation>
</message>
<message>
<location filename="../graphic_conf.ui" line="472"/>
<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(blockview "")

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,31 @@
#ifndef BLOCKVIEWPLUGIN_H
#define BLOCKVIEWPLUGIN_H
#include <QDesignerCustomWidgetInterface>
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,14 @@
#include "blockviewplugin.h"
#include "qad_blockview.h"
QADBlockView::QADBlockView(QObject * parent): QObject(parent)
{
m_widgets.append(new BlockViewPlugin(this));
}
QList<QDesignerCustomWidgetInterface * > QADBlockView::customWidgets() const {
return m_widgets;
}
Q_EXPORT_PLUGIN2(qad_graphic_plugin, QADBlockView)

View File

@@ -0,0 +1,21 @@
#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)
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,53 @@
<RCC>
<qresource prefix="/">
<file>lang/qad_blockview_ru.qm</file>
<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/document-edit-.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,2 @@
set(LIBS ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${QT_QTOPENGL_LIBRARY} ${OPENGL_LIBRARIES} qad_widgets qad_utils)
qad_project(graphic "${LIBS}")

1522
qad/graphic/graphic.cpp Normal file
View File

@@ -0,0 +1,1522 @@
#include "graphic.h"
#include "ui_graphic.h"
#include "ui_graphic_conf.h"
__GraphicRegistrator__ __graphic_registrator__;
ELineEdit::ELineEdit(QWidget * parent): CLineEdit(parent) {
last_ret = complexd_0;
is_auto = false;
is_reset = true;
connect(this, SIGNAL(editingFinished()), this, SLOT(calculate()));
connect(this, SIGNAL(cleared()), this, SLOT(toDefaultClicked()));
}
void ELineEdit::wheelEvent(QWheelEvent * e) {
double mul = 1.1;
if (e->delta() < 0) mul = 0.9;
CLineEdit::setText(QString::number(last_ret.real() * mul).toUpper());
calculate();
}
void ELineEdit::calculate() {
evaluator.check(text().replace(",", "."));
if (!evaluator.isCorrect()) return;
is_reset = false;
last_ret = evaluator.evaluate();
CLineEdit::setText(QString::number(last_ret.real()).toUpper());
emit valueChanged(last_ret.real());
}
Graphic::Graphic(QWidget * parent): QFrame(parent), 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));
qApp->installTranslator(trans);
leg_update = true;
visible_update = fullscr = false;
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.);
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(QPaintEvent * )));
connect(ui->canvas_raster, SIGNAL(mouseMoveEvent(QMouseEvent * )), this, SLOT(canvasMouseMoveEvent(QMouseEvent * )));
connect(ui->canvas_raster, SIGNAL(mousePressEvent(QMouseEvent * )), this, SLOT(canvasMousePressEvent(QMouseEvent * )));
connect(ui->canvas_raster, SIGNAL(mouseReleaseEvent(QMouseEvent * )), this, SLOT(canvasMouseReleaseEvent(QMouseEvent * )));
connect(ui->canvas_raster, SIGNAL(mouseDoubleClickEvent(QMouseEvent*)), this, SLOT(canvasMouseDoubleClickEvent(QMouseEvent * )));
connect(ui->canvas_raster, SIGNAL(wheelEvent(QWheelEvent * )), this, SLOT(canvasWheelEvent(QWheelEvent * )));
connect(ui->canvas_raster, SIGNAL(leaveEvent(QEvent * )), this, SLOT(canvasLeaveEvent(QEvent * )));
connect(ui->canvas_raster, SIGNAL(keyPressEvent(QKeyEvent * )), this, SLOT(canvasKeyPressEvent(QKeyEvent * )));
connect(ui->canvas_gl, SIGNAL(paintEvent(QPaintEvent * )), this, SLOT(canvasPaintEvent(QPaintEvent * )));
connect(ui->canvas_gl, SIGNAL(mouseMoveEvent(QMouseEvent * )), this, SLOT(canvasMouseMoveEvent(QMouseEvent * )));
connect(ui->canvas_gl, SIGNAL(mousePressEvent(QMouseEvent * )), this, SLOT(canvasMousePressEvent(QMouseEvent * )));
connect(ui->canvas_gl, SIGNAL(mouseReleaseEvent(QMouseEvent * )), this, SLOT(canvasMouseReleaseEvent(QMouseEvent * )));
connect(ui->canvas_gl, SIGNAL(mouseDoubleClickEvent(QMouseEvent*)), this, SLOT(canvasMouseDoubleClickEvent(QMouseEvent * )));
connect(ui->canvas_gl, SIGNAL(wheelEvent(QWheelEvent * )), this, SLOT(canvasWheelEvent(QWheelEvent * )));
connect(ui->canvas_gl, SIGNAL(leaveEvent(QEvent * )), this, SLOT(canvasLeaveEvent(QEvent * )));
connect(ui->canvas_gl, SIGNAL(keyPressEvent(QKeyEvent * )), this, SLOT(canvasKeyPressEvent(QKeyEvent * )));
ui->canvas_raster->grabGesture(Qt::PinchGesture);
ui->canvas_raster->grabGesture(Qt::PanGesture);
ui->canvas_raster->installEventFilter(this);
ui->canvas_gl->grabGesture(Qt::PinchGesture);
ui->canvas_gl->grabGesture(Qt::PanGesture);
ui->canvas_gl->installEventFilter(this);
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.;
pause_phase = 0.;
selrect.setRect(0., 0., 1., 1.);
def_rect = selrect;
margins_.setRect(4, 4, 4, 4);
curaction = gaMove;
selbrush.setStyle(Qt::SolidPattern);
selbrush.setColor(QColor(60, 175, 255, 100));
text_color = Qt::black;
grid_pen = QPen(Qt::gray, 0., Qt::DotLine);
//graph_pen = QPen(Qt::red);
//graph_pen.setCosmetic(true);
graphics.append(GraphicType());
curGraphic = 0;
selpen = QPen(Qt::black);
selpen.setStyle(Qt::DashLine);
back_color = Qt::white;
buttons_ = AllButtons;
setButtonsPosition(Graphic::Left);
setOpenGL(false);
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::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:
foreach (QGesture * g, ((QGestureEvent*)e)->gestures())
procGesture(g);
break;
default: break;
}
}
return QFrame::eventFilter(o, e);
}
void Graphic::procGesture(QGesture * g) {
if (!g) return;
qDebug() << g;
}
void Graphic::canvasPaintEvent(QPaintEvent * ) {
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 = qMax<int>(qRound(font_sz.height() / 15.), 1);
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;
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;
if (isOGL) {
glClearColor(0.f, 0.f, 0.f, 0.f);
p.begin(canvas);
} else 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());
drawGrid();
}
p.setRenderHint(QPainter::Antialiasing, aalias);
if (isOGL) {
if (aalias) glEnable(GL_MULTISAMPLE);
else glDisable(GL_MULTISAMPLE);
}
//p.setRenderHint(QPainter::HighQualityAntialiasing, aalias);
if (!aalias) p.translate(-0.5, -0.5);
drawGraphics();
drawGuides();
if (pause_) drawPause();
emit graphicPaintEvent(&p);
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();
QPointF rp = canvas2real(QPointF(e->pos())), srp = canvas2real(startpos), crp = canvas2real(curpos), dp;
QString cursorstr = tr("Cursor: ") + pointCoords(rp);
emit graphicMouseMoveEvent(rp, e->buttons());
if (e->buttons() == Qt::NoButton) {
ui->status->setText(cursorstr);
if (guides) update();
return;
}
if (!navigation) return;
if (curaction != gaMove && (e->buttons() & Qt::RightButton) == Qt::RightButton) return;
switch (curaction) {
case gaZoomInRect:
ui->status->setText(tr("Selection") + ": " + pointCoords(srp) + " -> " +
pointCoords(crp) + ", " + tr("Size") + ": " + pointCoords(absPoint(crp - srp)));
repaintCanvas(true);
break;
case gaZoomRangeX:
ui->status->setText(tr("Range") + ": " + QString::number(srp.x(), 'f', 3) +
" -> " + QString::number(crp.x(), 'f', 3) + ", " + tr("Length") + ": " +
QString::number(qAbs(crp.x() - srp.x()), 'f', 3));
repaintCanvas(true);
break;
case gaZoomRangeY:
ui->status->setText(tr("Range") + ": " + QString::number(srp.y(), 'f', 3) +
" -> " + QString::number(crp.y(), 'f', 3) + ", " + tr("Length") + ": " +
QString::number(qAbs(crp.y() - srp.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);
selrect.translate(dp);
isFit = false;
emit visualRectChanged();
update(true);
setRectToLines();
break;
default: break;
}
prevpos = e->pos();
}
void Graphic::canvasMousePressEvent(QMouseEvent * e) {
emit graphicMousePressEvent(canvas2real(QPointF(e->pos())), e->buttons());
if (!navigation) return;
ui->canvas_gl->setCursor(guides ? Qt::BlankCursor : Qt::ArrowCursor);
ui->canvas_raster->setCursor(guides ? Qt::BlankCursor : Qt::ArrowCursor);
prevpos = e->pos();
startpos = prevpos;
if (cancel) return;
if (e->button() == Qt::MidButton) curaction = gaMove;
if (e->button() == Qt::RightButton) {
if (bufferActive) {
curpos = startpos;
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 (!navigation) return;
ui->canvas_gl->setCursor(guides ? Qt::BlankCursor : Qt::ArrowCursor);
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 (!navigation) return;
double scl, wid = canvas->width() - gridborder.x() - margins_.width() - margins_.left(), hei = canvas->height() - gridborder.y() - margins_.height() - margins_.top();
double px = e->pos().x() - gridborder.x() - margins_.left(), py = hei - e->pos().y() + margins_.height();
px = px / wid * selrect.width() + selrect.x();
py = py / hei * selrect.height() + selrect.y();
if (e->delta() > 0) scl = 1. / 1.2;
else scl = 1.2;
if (e->modifiers() == Qt::NoModifier)
selrect.setRect(px - (px - selrect.x()) * scl, py - (py - selrect.y()) * scl, selrect.width() * scl, selrect.height() * scl);
else {
if (e->modifiers() == Qt::ControlModifier)
selrect.setRect(px - (px - selrect.x()) * scl, selrect.y(), selrect.width() * scl, selrect.height());
if (e->modifiers() == Qt::ShiftModifier)
selrect.setRect(selrect.x(), py - (py - selrect.y()) * scl, selrect.width(), selrect.height() * scl);
}
isFit = false;
update(true);
setRectToLines();
emit visualRectChanged();
}
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.;
}
on_buttonAutofit_clicked();
}
void Graphic::setAntialiasing(bool enabled) {
if (aalias == enabled) return;
aalias = enabled;
/*QGLFormat f = ui->canvas_gl->format();
f.setSampleBuffers(enabled);
ui->canvas_gl->setFormat(f);*/
update();
}
void Graphic::setPaused(bool yes) {
pause_ = yes;
ui->checkPause->blockSignals(true);
ui->checkPause->setChecked(yes);
ui->checkPause->blockSignals(false);
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;
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);
}
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;
}
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::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;
if (graphics.at(graphic).polyline.size() == 0) graphics[graphic].max_x = p.x();
graphics[graphic].polyline << p;
if (graphics.at(graphic).max_x < p.x()) graphics[graphic].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;
graphics[graphic].polyline.clear();
graphics[graphic].polyline = g;
if (graphics.at(graphic).polyline.size() == 0) {
graphics[graphic].max_x = 0.;
tick(graphic, false, update_);
return;
}
graphics[graphic].max_x = graphics.at(graphic).polyline[0].x();
for (int i = 1; i < graphics.at(graphic).polyline.size(); ++i)
if (graphics.at(graphic).max_x < graphics.at(graphic).polyline[i].x())
graphics[graphic].max_x = graphics.at(graphic).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) {
isOGL = on;
if (on) {
ui->canvas_raster->hide();
ui->canvas_gl->show();
canvas = ui->canvas_gl;
} else {
ui->canvas_gl->hide();
ui->canvas_raster->show();
canvas = ui->canvas_raster;
}
/*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::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 = DBL_MIN;
bool isRangeX = (start_x != end_x), isRangeY = (start_y != end_y);
bool isEmpty = true, anyVisible = false, isTimeLimit = (visible_time > 0.) && !(isRangeX || isRangeY);
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;
}
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;
foreach (const GraphicType & t, graphics) {
if (!t.visible) continue;
const QPolygonF & pol(pause_ ? t.polyline_pause : t.polyline);
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 (maxY < cy) maxY = cy;
if (minY > cy) minY = cy;
if (maxX < cx) maxX = cx;
if (minX > cx) minX = cx;
}
if (!pol.isEmpty()) anyVisible = true;
}
if (!anyVisible) {
grect.setRect(0., 0., 1., 1.);
setRectToLines();
return;
}
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 -= 1E-20; maxX += 1E-20;}
if (qAbs<double>(minY - maxY) < 1E-60) {minY -= 1E-20; maxY += 1E-20;}
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:
painter->drawRect(QRect(startpos, curpos));
break;
case gaZoomRangeX:
painter->drawLine(sx, hei, sx, 0);
painter->drawLine(cx, hei, cx, 0);
painter->fillRect(sx, 0, cx - sx, hei, selbrush);
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);
break;
default: break;
}
}
void Graphic::drawGrid() {
int gbx = gridborder.x(), gby = gridborder.y(), cwid = painter->viewport().width(), chei = painter->viewport().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>(qRound(thick / 1.4), 1));
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() / 2.5, 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(), thick));
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(), cp;
double sclx, scly, wid = painter->viewport().width(), hei = painter->viewport().height() - legy, pw;
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;
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()) {
pw = t.pen.widthF();
if (t.lines) {
t.pen.setCosmetic(true);
painter->setPen(t.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) t.pen.setWidth(qRound(t.pointWidth));
else t.pen.setWidthF(t.pointWidth);
t.pen.setCosmetic(true);
painter->setPen(t.pen);
painter->drawPoints(mat.map(rpol));
if (qRound(pw) == pw) t.pen.setWidth(qRound(pw));
else t.pen.setWidthF(pw);
}
}
}
painter->setWorldMatrixEnabled(true);
}
QString Graphic::pointCoords(QPointF point) {
if (axis_type_x == Numeric)
return "(" + QString::number(point.x(), 'f', 3) + " ; " + QString::number(point.y(), 'f', 3) + ")";
return "(" + QDateTime::fromMSecsSinceEpoch(point.x()).toString() + " ; " + QString::number(point.y(), 'f', 3) + ")";
}
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));
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;
}
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);
ui->canvas_gl->setCursor(cursor);
}
void Graphic::swapToBuffer() {
QImage timg;
//qDebug() << "render start";
if (isOGL) {
timg = ui->canvas_gl->grabFrameBuffer();
QPainter p(buffer);
p.drawImage(0, 0, timg);
p.end();
}
//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.hasFocus()) line_x_min.setValue(selrect.left());
if (!line_x_max.hasFocus()) line_x_max.setValue(selrect.right());
if (!line_y_min.hasFocus()) line_y_min.setValue(selrect.bottom());
if (!line_y_max.hasFocus()) line_y_max.setValue(selrect.top());
if (!isFit) {
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.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.isDefault() && line_x_max.isDefault() && line_y_min.isDefault() && line_y_max.isDefault());
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;
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() {
if (!ui->widgetLegend->isVisible()) return;
leg_update = false;
int ps = 100;
for (int i = 0; i < graphics.size(); i++) {
while (!graphics[i].pb->actions().isEmpty()) graphics[i].pb->removeAction(graphics[i].pb->actions()[0]);
delete graphics[i].pb;
QPixmap pix(60, 22);
pix.fill(back_color);
QPainter p(&pix);
p.setPen(graphics[i].pen);
p.drawLine(0, pix.height() / 2, pix.width(), pix.height() / 2);
p.end();
graphics[i].icon = QIcon(pix);
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->isVisible();
ui->widgetLegend->hide();
for (int i = 0; i < graphics.size(); i++) {
ui->layoutLegend->addWidget(graphics[i].pb,row,col);
col++;
if (col > maxcol) {col = 0; row++;}
}
ui->widgetLegend->setVisible(lv);
leg_update = true;
}
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();
// 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();
}
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;
}
void Graphic::load(QByteArray ba) {
if (ba.isEmpty()) return;
QDataStream s(ba);
bool a;
s >> a; setOpenGL(a);
s >> a; setAntialiasing(a);
s >> a; setBorderInputsVisible(a);
s >> a; setStatusVisible(a);
s >> a; setLegendVisible(a);
s >> graphics;
}
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);
}
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);
}

459
qad/graphic/graphic.h Normal file
View File

@@ -0,0 +1,459 @@
#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 "clineedit.h"
#include "qpievaluator.h"
#if QT_VERSION >= 0x050100
# include <QSensorGestureManager>
#endif
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class ELineEdit: public CLineEdit {
Q_OBJECT
public:
explicit ELineEdit(QWidget * parent = 0);
//void setText(const QString & v) {if (!is_auto) is_reset = false; CLineEdit::setText(v); setDefaultText(v, is_reset); last_ret = complexd(v.toDouble(), 0.); emit valueChanged(last_ret.real());}
void setValue(const int & v) {if (is_reset) setDefaultText(QString::number(v).toUpper(), is_reset); else setText(QString::number(v).toUpper()); last_ret = complexd(v, 0.); if (!is_auto) emit valueChanged(last_ret.real());}
void setValue(const double & v) {if (is_reset) setDefaultText(QString::number(v).toUpper(), is_reset); else setText(QString::number(v).toUpper()); last_ret = complexd(v, 0.); if (!is_auto) emit valueChanged(last_ret.real());}
double value() const {return last_ret.real();}
bool isDefault() const {return !cw->isVisible();}
bool is_reset, is_auto;
protected:
void wheelEvent(QWheelEvent * e);
QPIEvaluator evaluator;
complexd last_ret;
private slots:
void toDefaultClicked() {is_reset = true; calculate();}
void calculate();
signals:
void valueChanged(double value);
};
namespace Ui {
class Graphic;
};
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(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)
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
};
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;}
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;
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();}
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()));}
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; updateLegend(); 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 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 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) {addPoint(QPointF(graphics.at(graphic).max_x + inc_x, y), graphic, update);}
void addPoint(double y, bool update = true) {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 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 * ) {if (leg_update) updateLegend();}
virtual QSize sizeHint() const {return QSize(400, 300);}
virtual void timerEvent(QTimerEvent * );
virtual bool eventFilter(QObject * o, QEvent * e);
void procGesture(QGesture * g);
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();
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);
QPair<QString, QString> gridMark(double v) const;
Ui::Graphic * ui;
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;
QString label_x, label_y, ppath;
Graphic::Buttons buttons_;
Graphic::Alignment align;
GraphicConf * conf;
ELineEdit 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;
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;
bool hasLblX, hasLblY, navigation, only_expand_y, only_expand_x, is_lines_update, leg_update, visible_update, fullscr;
protected slots:
void canvasPaintEvent(QPaintEvent * );
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 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();
};
Q_DECLARE_METATYPE(Graphic::GraphicsData)
Q_DECLARE_OPERATORS_FOR_FLAGS(Graphic::Buttons)
//inline QDataStream & operator <<(QDataStream & s, const Graphic::GraphicsData & v) {s << v; return s;}
//inline QDataStream & operator >>(QDataStream & s, Graphic::GraphicsData & v) {s >> 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

485
qad/graphic/graphic.ui Normal file
View File

@@ -0,0 +1,485 @@
<?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="margin">
<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>28</width>
<height>361</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/zoom-fit-best.png</normaloff>:/icons/zoom-fit-best.png</iconset>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="checkGrid">
<property name="toolTip">
<string>Grid</string>
</property>
<property name="icon">
<iconset resource="qad_graphic.qrc">
<normaloff>:/icons/view-grid.png</normaloff>:/icons/view-grid.png</iconset>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</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="qad_graphic.qrc">
<normaloff>:/icons/edit-guides.png</normaloff>:/icons/edit-guides.png</iconset>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</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="qad_graphic.qrc">
<normaloff>:/icons/expand_s_y.png</normaloff>:/icons/expand_s_y.png</iconset>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</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="qad_graphic.qrc">
<normaloff>:/icons/expand_s_x.png</normaloff>:/icons/expand_s_x.png</iconset>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</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="qad_graphic.qrc">
<normaloff>:/icons/view-fullscreen.png</normaloff>:/icons/view-fullscreen.png</iconset>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="checkBorderInputs">
<property name="toolTip">
<string>Border inputs</string>
</property>
<property name="icon">
<iconset resource="qad_graphic.qrc">
<normaloff>:/icons/border-line.png</normaloff>:/icons/border-line.png</iconset>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</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="qad_graphic.qrc">
<normaloff>:/icons/legend.png</normaloff>:/icons/legend.png</iconset>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</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="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</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="qad_graphic.qrc">
<normaloff>:/icons/configure.png</normaloff>:/icons/configure.png</iconset>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="buttonSave">
<property name="toolTip">
<string>Save image ...</string>
</property>
<property name="icon">
<iconset resource="qad_graphic.qrc">
<normaloff>:/icons/document-save.png</normaloff>:/icons/document-save.png</iconset>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</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="qad_graphic.qrc">
<normaloff>:/icons/edit-clear.png</normaloff>:/icons/edit-clear.png</iconset>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="buttonClose">
<property name="toolTip">
<string>Close</string>
</property>
<property name="icon">
<iconset resource="qad_graphic.qrc">
<normaloff>:/icons/dialog-close.png</normaloff>:/icons/dialog-close.png</iconset>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</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="margin">
<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="margin">
<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="UGLWidget" name="canvas_gl" native="true">
<property name="mouseTracking">
<bool>true</bool>
</property>
</widget>
</item>
<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="margin">
<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="horizontalSpacing">
<number>4</number>
</property>
<property name="margin">
<number>1</number>
</property>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>UWidget</class>
<extends>QWidget</extends>
<header>uwidget.h</header>
</customwidget>
<customwidget>
<class>UGLWidget</class>
<extends>QWidget</extends>
<header>uglwidget.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="qad_graphic.qrc"/>
</resources>
<connections/>
</ui>

View File

@@ -0,0 +1,103 @@
#include "graphic_conf.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;
styles << tr("NoPen") << tr("Solid") << tr("Dash")
<< tr("Dot") << tr("Dash-Dot") << tr("Dash-Dot-Dot");
ui->comboStyleGrid->setIconSize(QSize(60, 22));
ui->comboStyleGraphic->setIconSize(QSize(60, 22));
ui->cbGraphicNames->setIconSize(QSize(60, 22));
for (int i = 0; i < 6; i++) {
QPixmap pix(60, 22);
pix.fill();
QPainter p(&pix);
p.setPen(QPen(Qt::black, 1, (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,90 @@
#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;
};
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

678
qad/graphic/graphic_conf.ui Normal file
View File

@@ -0,0 +1,678 @@
<?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>448</width>
<height>513</height>
</rect>
</property>
<property name="windowTitle">
<string>Graphic parameters</string>
</property>
<property name="modal">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="margin">
<number>2</number>
</property>
<property name="spacing">
<number>2</number>
</property>
<item row="0" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Appearance</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>2</number>
</property>
<property name="margin">
<number>2</number>
</property>
<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>
<property name="horizontalSpacing">
<number>2</number>
</property>
<property name="verticalSpacing">
<number>2</number>
</property>
<property name="margin">
<number>2</number>
</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="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>
<property name="horizontalSpacing">
<number>2</number>
</property>
<property name="verticalSpacing">
<number>2</number>
</property>
<property name="margin">
<number>2</number>
</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="1">
<widget class="QDoubleSpinBox" name="spinGridStepX">
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>0.001000000000000</double>
</property>
<property name="maximum">
<double>9999999.000000000000000</double>
</property>
<property name="value">
<double>50.000000000000000</double>
</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="6" column="1">
<widget class="QDoubleSpinBox" name="spinGridStepY">
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>0.001000000000000</double>
</property>
<property name="maximum">
<double>9999999.000000000000000</double>
</property>
<property name="value">
<double>30.000000000000000</double>
</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>
</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">
<property name="margin">
<number>2</number>
</property>
<property name="spacing">
<number>2</number>
</property>
<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>
</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>

Binary file not shown.

View File

@@ -0,0 +1,351 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.0" 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 type="unfinished"></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 type="unfinished"></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 "")

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,31 @@
#ifndef GRAPHICPLUGIN_H
#define GRAPHICPLUGIN_H
#include <QDesignerCustomWidgetInterface>
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,14 @@
#include "graphicplugin.h"
#include "qad_graphic.h"
QADGraphic::QADGraphic(QObject * parent): QObject(parent)
{
m_widgets.append(new GraphicPlugin(this));
}
QList<QDesignerCustomWidgetInterface * > QADGraphic::customWidgets() const {
return m_widgets;
}
Q_EXPORT_PLUGIN2(qad_graphic_plugin, QADGraphic)

View File

@@ -0,0 +1,21 @@
#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)
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,32 @@
<RCC>
<qresource prefix="/">
<file>lang/qad_graphic_ru.qm</file>
<file>../icons/media-playback-pause.png</file>
<file>../icons/dialog-close.png</file>
<file>../icons/edit-clear.png</file>
<file>../icons/edit-guides.png</file>
<file>../icons/view-grid.png</file>
<file>../icons/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/graphic.png</file>
<file>../icons/view-fullscreen.png</file>
<file>../icons/pause-back.png</file>
<file>../icons/pause-front.png</file>
</qresource>
</RCC>

48
qad/graphic/uglwidget.h Normal file
View File

@@ -0,0 +1,48 @@
#ifndef UGLWIDGET_H
#define UGLWIDGET_H
#include <QGLWidget>
#ifndef GL_MULTISAMPLE
#define GL_MULTISAMPLE 0x809D
#endif
class UGLWidget: public QGLWidget
{
Q_OBJECT
public:
UGLWidget(QWidget * parent = 0): QGLWidget(QGLFormat(QGL::DoubleBuffer | QGL::AlphaChannel | QGL::DirectRendering | QGL::SampleBuffers), parent) {};
UGLWidget(QGLContext * context, QWidget * parent = 0): QGLWidget(context, parent) {};
signals:
void closeEvent(QCloseEvent * e);
void dragEnterEvent(QDragEnterEvent * e);
void dragLeaveEvent(QDragLeaveEvent * e);
void dragMoveEvent(QDragMoveEvent * e);
void dropEvent(QDropEvent * e);
void enterEvent(QEvent * e);
void hideEvent(QHideEvent * e);
void keyPressEvent(QKeyEvent * e);
void keyReleaseEvent(QKeyEvent * e);
void leaveEvent(QEvent * e);
void mouseDoubleClickEvent(QMouseEvent * e);
void mouseMoveEvent(QMouseEvent * e);
void mousePressEvent(QMouseEvent * e);
void mouseReleaseEvent(QMouseEvent * e);
void moveEvent(QMoveEvent * e);
void resizeEvent(QResizeEvent * e);
void showEvent(QShowEvent * e);
void wheelEvent(QWheelEvent * e);
void paintEvent(QPaintEvent * e);
void glDraw();
void glInit();
void initializeGL();
void initializeOverlayGL();
void paintGL();
void paintOverlayGL();
void resizeGL(int width, int height);
void resizeOverlayGL(int width, int height);
};
#endif

52
qad/graphic/uwidget.h Normal file
View File

@@ -0,0 +1,52 @@
#ifndef UWIDGET_H
#define UWIDGET_H
#include <QWidget>
#include <QPainter>
#include <QStyle>
#include <QStyleOption>
#include <QEvent>
class UWidget: public QWidget
{
Q_OBJECT
public:
UWidget(QWidget * parent = 0): QWidget(parent) {};
private:
virtual bool event(QEvent * e) {
if (e->type() != QEvent::Paint) return QWidget::event(e);
e->accept();
QStyleOption opt;
opt.init(this);
QPainter p(this);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
emit paintEvent((QPaintEvent * )e);
return true;
}
signals:
void closeEvent(QCloseEvent * e);
void dragEnterEvent(QDragEnterEvent * e);
void dragLeaveEvent(QDragLeaveEvent * e);
void dragMoveEvent(QDragMoveEvent * e);
void dropEvent(QDropEvent * e);
void enterEvent(QEvent * e);
void hideEvent(QHideEvent * e);
void keyPressEvent(QKeyEvent * e);
void keyReleaseEvent(QKeyEvent * e);
void leaveEvent(QEvent * e);
void mouseDoubleClickEvent(QMouseEvent * e);
void mouseMoveEvent(QMouseEvent * e);
void mousePressEvent(QMouseEvent * e);
void mouseReleaseEvent(QMouseEvent * e);
void moveEvent(QMoveEvent * e);
void resizeEvent(QResizeEvent * e);
void showEvent(QShowEvent * e);
void wheelEvent(QWheelEvent * e);
void paintEvent(QPaintEvent * e);
};
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 342 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 384 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 382 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 303 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 348 B

BIN
qad/icons/align-hor.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 992 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 403 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 387 B

BIN
qad/icons/align-ver.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
qad/icons/alpha.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 626 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 588 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 433 B

BIN
qad/icons/arrow-down.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 525 B

BIN
qad/icons/arrow-up.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 484 B

BIN
qad/icons/axis_x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 235 B

BIN
qad/icons/axis_y.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 B

BIN
qad/icons/blockview.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 943 B

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