diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8b502d9..51ef492 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -3,7 +3,7 @@ cmake_policy(SET CMP0017 NEW) # need include() with .cmake
cmake_policy(SET CMP0072 NEW) # FindOpenGL prefers GLVND by default
project(QAD)
set(QAD_MAJOR 2)
-set(QAD_MINOR 17)
+set(QAD_MINOR 18)
set(QAD_REVISION 0)
set(QAD_SUFFIX )
set(QAD_COMPANY SHS)
diff --git a/cmake/FindQAD.cmake b/cmake/FindQAD.cmake
index 512d34c..e9e3a1d 100644
--- a/cmake/FindQAD.cmake
+++ b/cmake/FindQAD.cmake
@@ -6,6 +6,7 @@ Create imported targets:
* QAD::Application
* QAD::Blockview
* QAD::Graphic
+ * QAD::GraphicAnalysis
* QAD::SQLTable
* QAD::TouchWidgets
* QAD::Doc
@@ -44,23 +45,24 @@ if(QAD_FIND_VERSION VERSION_GREATER QAD_VERSION)
message(FATAL_ERROR "QAD version ${QAD_VERSION} is available, but ${QAD_FIND_VERSION} requested!")
endif()
-set(__libs "utils;widgets;application;blockview;graphic;sql;sql_table;touch_widgets;doc;map")
+set(__libs "utils;widgets;application;blockview;graphic;graphic_analysis;sql;sql_table;touch_widgets;doc;map")
if (PIP_FOUND OR BUILDING_PIP)
list(APPEND __libs "piqt;piqt_utils")
endif()
-set(__module_utils Utils )
-set(__module_widgets Widgets )
-set(__module_application Application )
-set(__module_blockview Blockview )
-set(__module_graphic Graphic )
-set(__module_sql SQL )
-set(__module_sql_table SQLTable )
-set(__module_touch_widgets TouchWidgets )
-set(__module_doc Doc )
-set(__module_map Map )
-set(__module_piqt PIQt )
-set(__module_piqt_utils PIQtUtils )
+set(__module_utils Utils )
+set(__module_widgets Widgets )
+set(__module_application Application )
+set(__module_blockview Blockview )
+set(__module_graphic Graphic )
+set(__module_graphic_analysis GraphicAnalysis)
+set(__module_sql SQL )
+set(__module_sql_table SQLTable )
+set(__module_touch_widgets TouchWidgets )
+set(__module_doc Doc )
+set(__module_map Map )
+set(__module_piqt PIQt )
+set(__module_piqt_utils PIQtUtils )
foreach (_l ${__libs})
set( __inc_${_l} "")
@@ -68,15 +70,16 @@ foreach (_l ${__libs})
set(__libs_${_l} "")
endforeach()
-set(__deps_widgets "QAD::Utils")
-set(__deps_application "QAD::Widgets")
-set(__deps_blockview "QAD::Widgets")
-set(__deps_graphic "QAD::Widgets")
-set(__deps_sql "QAD::Utils")
-set(__deps_sql_table "QAD::Widgets")
-set(__deps_map "QAD::Utils;QAD::PIQt")
-set(__deps_piqt "QAD::Widgets;PIP")
-set(__deps_piqt_utils "QAD::Blockview;QAD::PIQt")
+set(__deps_widgets "QAD::Utils")
+set(__deps_application "QAD::Widgets")
+set(__deps_blockview "QAD::Widgets")
+set(__deps_graphic "QAD::Widgets")
+set(__deps_graphic_analysis "QAD::Graphic;PIP::FFTW")
+set(__deps_sql "QAD::Utils")
+set(__deps_sql_table "QAD::Widgets")
+set(__deps_map "QAD::Utils;QAD::PIQt")
+set(__deps_piqt "QAD::Widgets;PIP")
+set(__deps_piqt_utils "QAD::Blockview;QAD::PIQt")
#message("find QAD ${BUILDING_QAD}")
diff --git a/cmake/QtWraps.cmake b/cmake/QtWraps.cmake
index 89a68dc..9ecc10d 100644
--- a/cmake/QtWraps.cmake
+++ b/cmake/QtWraps.cmake
@@ -926,6 +926,15 @@ macro(qad_install_lang _NAME)
if ("${_libname}" STREQUAL "qad_piqtutils")
set(_libname "qad_piqt_utils")
endif()
+ if ("${_libname}" STREQUAL "qad_sqltable")
+ set(_libname "qad_sql_table")
+ endif()
+ if ("${_libname}" STREQUAL "qad_touchwidgets")
+ set(_libname "qad_touch_widgets")
+ endif()
+ if ("${_libname}" STREQUAL "qad_graphicanalysis")
+ set(_libname "qad_graphic_analysis")
+ endif()
#message("imp lib \"${_libname}\"")
list(APPEND _qt_libs ${_libname})
endif()
diff --git a/libs/graphic/graphic.cpp b/libs/graphic/graphic.cpp
index 8ee8b3d..b059f03 100644
--- a/libs/graphic/graphic.cpp
+++ b/libs/graphic/graphic.cpp
@@ -209,7 +209,7 @@ Graphic::~Graphic() {
delete buttons_menu;
#endif
delete conf;
- // if (buffer != 0) delete buffer;
+ delete ui;
}
diff --git a/libs/graphic/graphic.ui b/libs/graphic/graphic.ui
index 3c30c7e..43c7399 100644
--- a/libs/graphic/graphic.ui
+++ b/libs/graphic/graphic.ui
@@ -16,7 +16,10 @@
150
-
+
+
+ 0
+
0
@@ -29,384 +32,388 @@
0
-
- 2
-
- -
-
-
- Qt::RichText
+
-
+
+
+ 2
-
- Qt::AlignCenter
-
-
-
- -
-
-
-
-
- -10
- 0
- 35
- 420
-
-
-
-
- 2
-
-
-
-
-
- Autofit
-
-
-
- :/icons/view-autofit.png:/icons/view-autofit.png
-
-
-
- -
-
-
- Cursor axis
-
-
-
- :/icons/edit-guides.png:/icons/edit-guides.png
-
-
- true
-
-
-
- -
-
-
- Fullscreen
-
-
-
- :/icons/view-fullscreen.png:/icons/view-fullscreen.png
-
-
-
- -
-
-
- Border inputs
-
-
-
- :/icons/border-line.png:/icons/border-line.png
-
-
- true
-
-
-
- -
-
-
- Legend
-
-
-
- :/icons/legend.png:/icons/legend.png
-
-
- true
-
-
- false
-
-
-
- -
-
-
- Pause
-
-
-
- :/icons/media-playback-pause.png:/icons/media-playback-pause.png
-
-
- true
-
-
-
- -
-
-
- Configure ...
-
-
-
- :/icons/configure.png:/icons/configure.png
-
-
-
- -
-
-
- Save image ...
-
-
-
- :/icons/document-save.png:/icons/document-save.png
-
-
- QToolButton::InstantPopup
-
-
-
- -
-
-
- Record graphic
-
-
-
- :/icons/media-record.png:/icons/media-record.png
-
-
- true
-
-
-
- -
-
-
- Qt::Vertical
-
-
- QSizePolicy::Preferred
-
-
-
- 0
- 30
-
-
-
-
- -
-
-
- Clear
-
-
-
- :/icons/edit-clear.png:/icons/edit-clear.png
-
-
-
- -
-
-
- Close
-
-
-
- :/icons/dialog-close.png:/icons/dialog-close.png
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 0
- 0
-
-
-
-
-
-
-
-
- -
-
-
- -
-
-
- Cursor: ( ; )
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- QFrame::Box
-
-
- QFrame::Sunken
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
-
-
-
-
- 0
- 0
-
+
-
+
+
+
+
+ -10
+ 0
+ 35
+ 420
+
-
+
- 0
-
-
- 2
-
-
- 2
-
-
- 2
-
-
2
-
-
+
+
+ Autofit
+
+
+
+ :/icons/view-autofit.png:/icons/view-autofit.png
+
+
+
+ -
+
+
+ Cursor axis
+
+
+
+ :/icons/edit-guides.png:/icons/edit-guides.png
+
+
+ true
+
+
+
+ -
+
+
+ Fullscreen
+
+
+
+ :/icons/view-fullscreen.png:/icons/view-fullscreen.png
+
+
+
+ -
+
+
+ Border inputs
+
+
+
+ :/icons/border-line.png:/icons/border-line.png
+
+
+ true
+
+
+
+ -
+
+
+ Legend
+
+
+
+ :/icons/legend.png:/icons/legend.png
+
+
+ true
+
+
+ false
+
+
+
+ -
+
+
+ Pause
+
+
+
+ :/icons/media-playback-pause.png:/icons/media-playback-pause.png
+
+
+ true
+
+
+
+ -
+
+
+ Configure ...
+
+
+
+ :/icons/configure.png:/icons/configure.png
+
+
+
+ -
+
+
+ Save image ...
+
+
+
+ :/icons/document-save.png:/icons/document-save.png
+
+
+ QToolButton::InstantPopup
+
+
+
+ -
+
+
+ Record graphic
+
+
+
+ :/icons/media-record.png:/icons/media-record.png
+
+
+ true
+
+
+
+ -
+
- Qt::Horizontal
+ Qt::Vertical
+
+
+ QSizePolicy::Preferred
- 40
- 20
+ 0
+ 30
-
-
-
- -
-
-
- 0
-
-
-
-
-
- true
-
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 0
-
-
- 2
-
-
- 2
-
-
- 2
-
-
- 2
-
-
-
+
+
+ Clear
+
+
+
+ :/icons/edit-clear.png:/icons/edit-clear.png
+
+
+
+ -
+
+
+ Close
+
+
+
+ :/icons/dialog-close.png:/icons/dialog-close.png
+
+
+
+ -
+
Qt::Vertical
- 20
- 40
+ 0
+ 0
-
- -
-
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 1
-
-
- 4
-
-
- 2
-
-
-
-
-
-
-
- -
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
-
+
+
+ -
+
+
+ Qt::RichText
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ QFrame::Box
+
+
+ QFrame::Sunken
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+
+
+ 2
+
+
+ 2
+
+
+ 2
+
+
+ 2
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+ -
+
+
+ 0
+
+
-
+
+
+ true
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+
+
+ 2
+
+
+ 2
+
+
+ 2
+
+
+ 2
+
+
-
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+ -
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+ 4
+
+
+ 2
+
+
+
+
+
+
+
+ -
+
+
+ Cursor: ( ; )
+
+
+
+ -
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+
+
+
diff --git a/libs/graphic/graphic_ranges.cpp b/libs/graphic/graphic_ranges.cpp
new file mode 100644
index 0000000..01c1fd6
--- /dev/null
+++ b/libs/graphic/graphic_ranges.cpp
@@ -0,0 +1,184 @@
+#include
+#include "graphic_ranges.h"
+
+
+GraphicRanges::GraphicRanges(QWidget * parent): Graphic(parent) {
+ connect(this, SIGNAL(graphicPaintEvent(QPainter *)), this, SLOT(onPaintEvent(QPainter *)));
+ connect(this, SIGNAL(graphicMousePressEvent(QPointF, int)), this, SLOT(onMousePressEvent(QPointF, int)));
+ connect(this, SIGNAL(graphicMouseMoveEvent(QPointF, int)), this, SLOT(onMouseMoveEvent(QPointF, int)));
+ connect(this, SIGNAL(graphicMouseReleaseEvent(QPointF, int)), this, SLOT(onMouseReleaseEvent(QPointF, int)));
+ //setOpenGL(true);
+ range_start = range_end = 0.;
+ range_sel = request = false;
+ color_ = QColor(64, 192, 64, 128);
+ color_cur = QColor(64, 64, 192, 128);
+}
+
+
+GraphicRanges::~GraphicRanges() {
+}
+
+
+int GraphicRanges::addRange(double start, double end, QString name, QColor color) {
+ ranges_ << Range(start, end, name, color);
+ update();
+ return ranges_.size() - 1;
+}
+
+
+void GraphicRanges::replaceRange(int index, double start, double end) {
+ if (index < 0 || index >= ranges_.size()) return;
+ ranges_[index].start = start;
+ ranges_[index].end = end;
+ update();
+}
+
+
+GraphicRanges::Range GraphicRanges::removeRange(int index) {
+ if (index < 0 || index >= ranges_.size()) return Range();
+ Range ret = ranges_.takeAt(index);
+ update();
+ return ret;
+}
+
+
+void GraphicRanges::clearRanges() {
+ ranges_.clear();
+ update();
+}
+
+
+void GraphicRanges::clearRangesByColor(QColor c) {
+ for (int i = 0; i < ranges_.size(); ++i) {
+ if (ranges_[i].color == c) {
+ ranges_.removeAt(i);
+ --i;
+ }
+ }
+ update();
+}
+
+
+GraphicRanges::Range GraphicRanges::rangeAll() const {
+ Range ret;
+ for (int g = 0; g < graphicsCount(); ++g) {
+ const QPolygonF & gd(graphics[g].polyline);
+ if (!gd.isEmpty()) {
+ if (ret.isEmpty()) {
+ ret.start = gd.front().x();
+ ret.end = gd.back ().x();
+ } else {
+ ret.start = qMin(ret.start, gd.front().x());
+ ret.end = qMax(ret.end , gd.back ().x());
+ }
+ }
+ }
+ return ret;
+}
+
+
+GraphicRanges::Range GraphicRanges::rangeVisible() const {
+ Range ret;
+ ret.start = visualRect().left ();
+ ret.end = visualRect().right();
+ return ret;
+}
+
+
+void GraphicRanges::setCurrentRange(double start, double end) {
+ range_start = start;
+ range_end = end;
+ update();
+}
+
+
+void GraphicRanges::clearCurrentRange() {
+ range_start = range_end = 0.;
+ update();
+}
+
+
+GraphicRanges::Range GraphicRanges::currentRange() const {
+ return Range(range_start, range_end);
+}
+
+
+void GraphicRanges::clear() {
+ ranges_.clear();
+ Graphic::clear();
+}
+
+
+void GraphicRanges::drawRange(QPainter * p, const GraphicRanges::Range & r, QColor color) {
+ if (r.isEmpty()) return;
+ double cx[2] = {real2canvasX(r.start),
+ real2canvasX(r.end)};
+ p->fillRect(QRectF(cx[0], 0, cx[1] - cx[0], height()), color);
+ p->setPen(QPen(QColor(color.rgb()), 2, Qt::DotLine));
+ p->drawLine(cx[0], 0, cx[0], height());
+ p->drawLine(cx[1], 0, cx[1], height());
+ if (!r.name.isEmpty()) {
+ p->setPen(QPen(QColor(color.rgb()).darker(), 1, Qt::SolidLine));
+ p->drawText(QRectF(cx[0], 10, cx[1] - cx[0], height() - 10), Qt::AlignHCenter | Qt::AlignTop | Qt::TextDontClip, r.name);
+ }
+
+}
+
+
+void GraphicRanges::onPaintEvent(QPainter * p) {
+ p->save();
+ //QPen pen = p->pen();
+ for (const auto & r: ranges_) {
+ drawRange(p, r, r.hasColor() ? r.color : color_);
+ }
+ drawRange(p, Range(range_start, range_end), color_cur);
+ p->restore();
+}
+
+
+void GraphicRanges::onMousePressEvent(QPointF p, int b) {
+ if (b == Qt::RightButton) return;// request = false;
+ if (b != Qt::LeftButton || !request) return;
+ update();
+ range_sel = true;
+ range_start = range_end = p.x();
+ setNavigationEnabled(false);
+}
+
+
+void GraphicRanges::onMouseMoveEvent(QPointF p, int b) {
+ if (!range_sel) return;
+ range_end = p.x();
+ update();
+}
+
+
+void GraphicRanges::onMouseReleaseEvent(QPointF p, int b) {
+ if (b == Qt::RightButton && range_sel)
+ canvas->setCursor(Qt::SplitHCursor);
+ if (b != Qt::LeftButton) return;
+ if (range_sel) {
+ range_sel = request = false;
+ range_end = p.x();
+ if (range_start > range_end)
+ std::swap(range_start, range_end);
+ rangeSelected(range_start, range_end);
+ canvas->setCursor(Qt::ArrowCursor);
+ range_start = range_end = 0.;
+ }
+ QTimer::singleShot(10, [this](){setNavigationEnabled(true); update();});
+}
+
+
+void GraphicRanges::rangeRequest() {
+ request = true;
+ canvas->setCursor(Qt::SplitHCursor);
+}
+
+
+void GraphicRanges::cancelRangeRequest(bool with_nav) {
+ request = false;
+ canvas->setCursor(Qt::ArrowCursor);
+ if (with_nav)
+ QTimer::singleShot(10, [this](){setNavigationEnabled(true); update();});
+}
diff --git a/libs/graphic/graphic_ranges.h b/libs/graphic/graphic_ranges.h
new file mode 100644
index 0000000..9db55fa
--- /dev/null
+++ b/libs/graphic/graphic_ranges.h
@@ -0,0 +1,87 @@
+/*
+ QAD - Qt ADvanced
+
+ Ivan Pelipenko peri4ko@yandex.ru
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef GRAPHIC_RANGES_H
+#define GRAPHIC_RANGES_H
+
+#include "graphic.h"
+
+
+class QAD_GRAPHIC_EXPORT GraphicRanges: public Graphic {
+ Q_OBJECT
+
+public:
+ explicit GraphicRanges(QWidget * parent = 0);
+ ~GraphicRanges();
+
+ struct QAD_GRAPHIC_EXPORT Range {
+ Range(double s = 0., double e = 0., QString n = QString(), QColor c = Qt::black) {
+ start = s;
+ end = e;
+ name = n;
+ color = c;
+ }
+ bool isEmpty() const { return qFuzzyIsNull(start - end); }
+ bool hasColor() const { return color != Qt::black; }
+ QString name;
+ QColor color;
+ double start;
+ double end;
+ };
+
+ int addRange(double start, double end, QString name, QColor color = Qt::black);
+ void replaceRange(int index, double start, double end);
+ Range removeRange(int index);
+ void clearRanges();
+ void clearRangesByColor(QColor c);
+ QList ranges() const { return ranges_; }
+ Range rangeAll() const;
+ Range rangeVisible() const;
+ bool isRangeRequested() const { return request; }
+
+ void setCurrentRange(double start, double end);
+ void clearCurrentRange();
+ Range currentRange() const;
+
+ void clear();
+
+protected:
+ void drawRange(QPainter * p, const Range & r, QColor color);
+
+ QList ranges_;
+ QColor color_, color_cur;
+ double range_start, range_end;
+ bool range_sel, request;
+
+private slots:
+ void onPaintEvent(QPainter * p);
+ void onMousePressEvent(QPointF p, int b);
+ void onMouseMoveEvent(QPointF p, int b);
+ void onMouseReleaseEvent(QPointF p, int b);
+
+public slots:
+ void rangeRequest();
+ void cancelRangeRequest(bool with_nav = true);
+
+signals:
+ void rangeSelected(double start, double end);
+};
+
+
+#endif
diff --git a/libs/graphic/plugin/graphicplugin.cpp b/libs/graphic/plugin/graphicplugin.cpp
index 707f984..e6b1dee 100644
--- a/libs/graphic/plugin/graphicplugin.cpp
+++ b/libs/graphic/plugin/graphicplugin.cpp
@@ -2,7 +2,7 @@
#include "graphic.h"
-#include
+#include
GraphicPlugin::GraphicPlugin(QObject * parent): QObject(parent) {
@@ -10,12 +10,9 @@ GraphicPlugin::GraphicPlugin(QObject * parent): QObject(parent) {
}
-void GraphicPlugin::initialize(QDesignerFormEditorInterface * /* core */) {
+void GraphicPlugin::initialize(QDesignerFormEditorInterface *) {
m_designer = true;
if (m_initialized) return;
-
- // Add extension registrations, etc. here
-
m_initialized = true;
}
diff --git a/libs/graphic/plugin/qad_graphic.cpp b/libs/graphic/plugin/qad_graphic.cpp
index 344842c..f15896f 100644
--- a/libs/graphic/plugin/qad_graphic.cpp
+++ b/libs/graphic/plugin/qad_graphic.cpp
@@ -3,7 +3,7 @@
#include "graphicplugin.h"
QADGraphic::QADGraphic(QObject * parent): QObject(parent) {
- m_widgets.append(new GraphicPlugin(this));
+ m_widgets << new GraphicPlugin(this);
}
diff --git a/libs/graphic_analysis/CMakeLists.txt b/libs/graphic_analysis/CMakeLists.txt
new file mode 100644
index 0000000..f0f5865
--- /dev/null
+++ b/libs/graphic_analysis/CMakeLists.txt
@@ -0,0 +1,6 @@
+find_package(PIP)
+if (PIP_FOUND)
+
+ qad_library(graphic_analysis "Gui;Positioning" "PIP::FFTW;qad_graphic")
+
+endif()
diff --git a/libs/graphic_analysis/graphic_analysis.cpp b/libs/graphic_analysis/graphic_analysis.cpp
new file mode 100644
index 0000000..8bc4609
--- /dev/null
+++ b/libs/graphic_analysis/graphic_analysis.cpp
@@ -0,0 +1,321 @@
+#include "graphic_analysis.h"
+
+#include "qad_types.h"
+#include "ui_graphic_analysis.h"
+
+#include
+#include
+
+
+PIVector getAmplitude(const PIVector & result) {
+ PIVector ret;
+ ret.resize(result.size());
+ double tmp;
+ for (uint i = 0; i < result.size(); i++) {
+ tmp = sqrt(result[i].real() * result[i].real() + result[i].imag() * result[i].imag());
+ ret[i] = tmp;
+ }
+ return ret;
+}
+
+
+PIVector spectrumPIVector(PIFFTWd & fft, const PIVector & in, double frequency, QPointF * fft_mul = nullptr) {
+ PIVector ret;
+ if (in.size() <= 2 || frequency <= 0.) return ret;
+ ret = getAmplitude(fft.calcFFT(in));
+ ret.resize(ret.size_s() / 2);
+ ret[0] = 0.;
+ if (fft_mul) *fft_mul = QPointF(frequency / ret.size_s() / 2., 1. / ret.size_s());
+ return ret;
+}
+
+
+QPolygonF spectrumQPolygonF(PIFFTWd & fft, const PIVector & in, double frequency, QPointF * fft_mul = nullptr) {
+ QPolygonF ret;
+ QPointF mul;
+ PIVector spec = spectrumPIVector(fft, in, frequency, &mul);
+ if (spec.isEmpty()) return ret;
+ ret.resize(spec.size_s());
+ for (int i = 0; i < ret.size(); ++i)
+ ret[i] = QPointF(i * mul.x(), spec[i] * mul.y());
+ if (fft_mul) *fft_mul = mul;
+ return ret;
+}
+
+
+// GraphicAnalysis
+
+
+PRIVATE_DEFINITION_START(GraphicAnalysis)
+ PIFFTWd fft;
+PRIVATE_DEFINITION_END(GraphicAnalysis)
+
+
+GraphicAnalysis::GraphicAnalysis(QWidget * parent): GraphicRanges(parent) {
+ widget_toolbox = new QWidget();
+ ui = new Ui::GraphicAnalysis();
+ ui->setupUi(widget_toolbox);
+ ui->widgetSpectrum->hide();
+ connect(ui->checkSpectrum, SIGNAL(toggled(bool)), this, SLOT(checkSpectrum_toggled(bool)));
+ connect(ui->buttonSpectrumRange, SIGNAL(toggled(bool)), this, SLOT(buttonSpectrumRange_toggled(bool)));
+ connect(ui->checkSpectrumFixDuration, SIGNAL(toggled(bool)), this, SLOT(checkSpectrumFixDuration_toggled(bool)));
+ auto * lay = qobject_cast(layout());
+ lay->insertWidget(0, widget_toolbox);
+ connect(ui->spinSpectrumDuration, SIGNAL(valueChanged(double)), this, SIGNAL(configChanged()));
+ connect(this, SIGNAL(rangeSelected(double, double)), this, SLOT(gaRangeSelected(double, double)));
+ connect(this, SIGNAL(graphicMousePressEvent(QPointF, int)), this, SLOT(gaMousePressEvent(QPointF, int)));
+ connect(this, SIGNAL(graphicMouseMoveEvent(QPointF, int)), this, SLOT(gaMouseMoveEvent(QPointF, int)));
+ connect(this, SIGNAL(graphicMouseReleaseEvent(QPointF, int)), this, SLOT(gaMouseReleaseEvent(QPointF, int)));
+}
+
+
+GraphicAnalysis::~GraphicAnalysis() {
+ delete ui;
+ delete widget_toolbox;
+}
+
+
+void GraphicAnalysis::setGraphicData(const QPolygonF & g, int graphic, bool update_) {
+ if (graphic < 0 || graphic >= graphicsCount()) return;
+ src_data[graphic] = g;
+ updateGraphic(graphic);
+ if (update_) viewport()->update();
+}
+
+
+bool GraphicAnalysis::isSpectrumFixedDuration() const {
+ return ui->checkSpectrumFixDuration->isChecked();
+}
+
+
+void GraphicAnalysis::setIsSpectrumFixedDuration(bool on) {
+ ui->checkSpectrumFixDuration->setChecked(on);
+}
+
+
+double GraphicAnalysis::spectrumFixedDuration() const {
+ return ui->spinSpectrumDuration->value();
+}
+
+
+void GraphicAnalysis::setSpectrumFixedDuration(double val) {
+ ui->spinSpectrumDuration->setValue(val);
+}
+
+
+bool GraphicAnalysis::isToolboxVisible() const {
+ return widget_toolbox->isVisible();
+}
+
+
+void GraphicAnalysis::setToolboxVisible(bool yes) {
+ widget_toolbox->setVisible(yes);
+}
+
+
+void GraphicAnalysis::setLabelX(const QString & str) {
+ data_label_x = str;
+ if (!show_fft) Graphic::setLabelX(str);
+}
+
+
+QBoxLayout * GraphicAnalysis::toolboxLayout() {
+ return reinterpret_cast(widget_toolbox->layout());
+}
+
+
+QWidget * GraphicAnalysis::toolboxWidget() {
+ return widget_toolbox;
+}
+
+
+bool GraphicAnalysis::isShowSpectrum() const {
+ return show_fft;
+}
+
+
+void GraphicAnalysis::changeEvent(QEvent * e) {
+ Graphic::changeEvent(e);
+ if (e->type() == QEvent::LanguageChange) {
+ ui->retranslateUi(this);
+ return;
+ }
+}
+
+
+void GraphicAnalysis::updateGraphic(int index) {
+ if (!show_fft) {
+ if (tf_gr)
+ Graphic::setGraphicData(tf_gr(src_data.value(index)), index, false);
+ else
+ Graphic::setGraphicData(src_data.value(index), index, false);
+ } else {
+ const QPolygonF & src(src_data[index]);
+ int si = 0, ei = src.size() - 1;
+ for (int i = 0; i < src.size(); ++i) {
+ if (src[i].x() >= range_fft.start) {
+ si = i;
+ break;
+ }
+ }
+ for (int i = si; i < src.size(); ++i) {
+ if (src[i].x() > range_fft.end) {
+ ei = i;
+ break;
+ }
+ }
+ if (ei - si < 4) {
+ Graphic::setGraphicData({}, index, false);
+ return;
+ }
+ if (tf_fft)
+ Graphic::setGraphicData(tf_fft(calcToFFT(&(src[si]), ei - si)), index, false);
+ else
+ Graphic::setGraphicData(calcToFFT(&(src[si]), ei - si), index, false);
+ }
+}
+
+
+void GraphicAnalysis::updateAllGraphic() {
+ for (int i = 0; i < graphicsCount(); ++i)
+ updateGraphic(i);
+}
+
+
+void GraphicAnalysis::setFFT(bool on) {
+ if (show_fft) {
+ setFFTInternal(false);
+ }
+ if (on) {
+ range_fft = rangeVisible();
+ setFFTInternal(true);
+ }
+}
+
+
+void GraphicAnalysis::setFFTInternal(bool on) {
+ bool need_autofit = false;
+ if (!show_fft && on) {
+ saved_view = visualRect();
+ saved_autofit = isAutofitted();
+ need_autofit = true;
+ }
+ if (show_fft && !on) {
+ setVisualRect(saved_view);
+ if (saved_autofit) need_autofit = true;
+ }
+ show_fft = on;
+ Graphic::setLabelX(on ? tr("Hz") : data_label_x);
+ emit showSpectrumChanged(show_fft);
+ updateAllGraphic();
+ if (need_autofit) {
+ autofit();
+ }
+}
+
+
+QPolygonF GraphicAnalysis::calcToFFT(const QPointF * in, int count) {
+ PIVector fft_in, fft_out;
+ fft_in.reserve(count);
+ for (int i = 0; i < count; ++i)
+ fft_in << in[i].y();
+ double freq = double(count - 1) / (in[count - 1].x() - in[0].x());
+ return spectrumQPolygonF(PRIVATE->fft, fft_in, freq);
+}
+
+
+void GraphicAnalysis::checkRangeRequest() {
+ if (!ui->buttonSpectrumRange->isChecked()) return;
+ viewport()->unsetCursor();
+ if (!ui->checkSpectrumFixDuration->isChecked()) {
+ rangeRequest();
+ } else {
+ cancelRangeRequest(false);
+ viewport()->setCursor(Qt::CrossCursor);
+ }
+}
+
+
+void GraphicAnalysis::clear() {
+ src_data.clear();
+ Graphic::clear();
+}
+
+
+void GraphicAnalysis::setGraphicsCount(int cnt, bool update) {
+ for (int i = cnt; i < graphicsCount(); ++i)
+ src_data.remove(i);
+ Graphic::setGraphicsCount(cnt, update);
+}
+
+
+void GraphicAnalysis::addPoint(const QPointF & p, int graphic, bool update_) {
+ src_data[graphic] << p;
+ if (show_fft) return;
+ Graphic::addPoint(p, graphic, update_);
+}
+
+
+void GraphicAnalysis::setGraphicTransformFunction(std::function f) {
+ tf_gr = f;
+}
+
+
+void GraphicAnalysis::setSpectrumTransformFunction(std::function f) {
+ tf_fft = f;
+}
+
+
+void GraphicAnalysis::gaMousePressEvent(QPointF point, int buttons) {
+ if (!ui->buttonSpectrumRange->isChecked() || buttons != Qt::LeftButton || !ui->checkSpectrumFixDuration->isChecked()) return;
+ setNavigationEnabled(false);
+ graphicMouseMoveEvent(point, buttons);
+}
+
+
+void GraphicAnalysis::gaMouseMoveEvent(QPointF point, int buttons) {
+ if (!ui->buttonSpectrumRange->isChecked() || buttons != Qt::LeftButton || !ui->checkSpectrumFixDuration->isChecked()) return;
+ setCurrentRange(point.x(), point.x() + ui->spinSpectrumDuration->value());
+}
+
+
+void GraphicAnalysis::gaMouseReleaseEvent(QPointF point, int buttons) {
+ if (!ui->buttonSpectrumRange->isChecked() || buttons != Qt::LeftButton || !ui->checkSpectrumFixDuration->isChecked()) return;
+ auto r = currentRange();
+ clearCurrentRange();
+ gaRangeSelected(r.start, r.end);
+ viewport()->setCursor(Qt::ArrowCursor);
+ QTimer::singleShot(10, [this]() {
+ setNavigationEnabled(true);
+ update();
+ });
+}
+
+
+void GraphicAnalysis::gaRangeSelected(double start, double end) {
+ if (!ui->buttonSpectrumRange->isChecked()) return;
+ ui->buttonSpectrumRange->setChecked(false);
+ range_fft = GraphicRanges::Range(start, end);
+ updateAllGraphic();
+}
+
+
+void GraphicAnalysis::checkSpectrum_toggled(bool on) {
+ if (!on) ui->buttonSpectrumRange->setChecked(false);
+ setFFT(on);
+}
+
+
+void GraphicAnalysis::buttonSpectrumRange_toggled(bool on) {
+ setFFT(!on);
+ if (on)
+ checkRangeRequest();
+ else
+ viewport()->unsetCursor();
+}
+
+
+void GraphicAnalysis::checkSpectrumFixDuration_toggled(bool on) {
+ checkRangeRequest();
+ emit configChanged();
+}
diff --git a/libs/graphic_analysis/graphic_analysis.h b/libs/graphic_analysis/graphic_analysis.h
new file mode 100644
index 0000000..eda7344
--- /dev/null
+++ b/libs/graphic_analysis/graphic_analysis.h
@@ -0,0 +1,101 @@
+/*
+ QAD - Qt ADvanced
+
+ Ivan Pelipenko peri4ko@yandex.ru
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef graphic_analysis_h
+#define graphic_analysis_h
+
+#include "qad_graphic_analysis_export.h"
+
+#include
+#include
+
+namespace Ui {
+class GraphicAnalysis;
+}
+class GraphicAnalysisPlugin;
+
+class QAD_GRAPHIC_ANALYSIS_EXPORT GraphicAnalysis: public GraphicRanges {
+ Q_OBJECT
+ friend class GraphicAnalysisPlugin;
+ Q_PROPERTY(bool toolboxVisible READ isToolboxVisible WRITE setToolboxVisible)
+
+public:
+ GraphicAnalysis(QWidget * parent = 0);
+ virtual ~GraphicAnalysis();
+
+ void setGraphicData(const QPolygonF & g, int graphic, bool update_ = true);
+
+ bool isSpectrumFixedDuration() const;
+ void setIsSpectrumFixedDuration(bool on);
+ double spectrumFixedDuration() const;
+ void setSpectrumFixedDuration(double val);
+
+ bool isToolboxVisible() const;
+ void setToolboxVisible(bool yes);
+ void setLabelX(const QString & str);
+ QBoxLayout * toolboxLayout();
+ QWidget * toolboxWidget();
+ bool isShowSpectrum() const;
+
+ void setGraphicsCount(int cnt, bool update = true);
+ void addPoint(const QPointF & p, int graphic, bool update_ = true);
+
+ void setGraphicTransformFunction(std::function f);
+ void setSpectrumTransformFunction(std::function f);
+
+protected:
+ void changeEvent(QEvent * e);
+
+ void updateGraphic(int index);
+ void updateAllGraphic();
+ void setFFTInternal(bool on);
+ void setFFT(bool on);
+ QPolygonF calcToFFT(const QPointF * in, int count);
+ void checkRangeRequest();
+
+ Ui::GraphicAnalysis * ui = nullptr;
+ QWidget * widget_toolbox = nullptr;
+ QMap src_data;
+ GraphicRanges::Range range_fft;
+ std::function tf_gr, tf_fft;
+ QString data_label_x;
+ QRectF saved_view;
+ bool saved_autofit = true, show_fft = false;
+
+ PRIVATE_DECLARATION(QAD_GRAPHIC_ANALYSIS_EXPORT)
+
+public slots:
+ void clear();
+
+private slots:
+ void gaMousePressEvent(QPointF point, int buttons);
+ void gaMouseMoveEvent(QPointF point, int buttons);
+ void gaMouseReleaseEvent(QPointF point, int buttons);
+ void gaRangeSelected(double start, double end);
+ void checkSpectrum_toggled(bool on);
+ void buttonSpectrumRange_toggled(bool on);
+ void checkSpectrumFixDuration_toggled(bool on);
+
+signals:
+ void showSpectrumChanged(bool);
+ void configChanged();
+};
+
+
+#endif
diff --git a/libs/graphic_analysis/graphic_analysis.ui b/libs/graphic_analysis/graphic_analysis.ui
new file mode 100644
index 0000000..6687fd6
--- /dev/null
+++ b/libs/graphic_analysis/graphic_analysis.ui
@@ -0,0 +1,199 @@
+
+
+ GraphicAnalysis
+
+
+
+ 0
+ 0
+ 488
+ 57
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+ Spectrum
+
+
+
+ -
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ Select spectrum input data
+
+
+
+ :/icons/axis_x.png:/icons/axis_x.png
+
+
+ true
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QSizePolicy::Preferred
+
+
+
+ 10
+ 5
+
+
+
+
+ -
+
+
+ false
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ Fix dur.:
+
+
+
+ -
+
+
+ false
+
+
+ s
+
+
+ 3
+
+
+ 0.001000000000000
+
+
+ 99999.000000000000000
+
+
+ 10.000000000000000
+
+
+ 100.000000000000000
+
+
+
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 104
+ 0
+
+
+
+
+
+
+
+
+
+
+
+ checkSpectrum
+ toggled(bool)
+ widgetSpectrum
+ setVisible(bool)
+
+
+ 90
+ 19
+
+
+ 152
+ 5
+
+
+
+
+ checkSpectrumFixDuration
+ toggled(bool)
+ spinSpectrumDuration
+ setEnabled(bool)
+
+
+ 209
+ 24
+
+
+ 289
+ 20
+
+
+
+
+ buttonSpectrumRange
+ toggled(bool)
+ widgetFixedDuration
+ setEnabled(bool)
+
+
+ 126
+ 30
+
+
+ 181
+ 45
+
+
+
+
+
diff --git a/libs/graphic_analysis/lang/qad_graphic_analysis_en.ts b/libs/graphic_analysis/lang/qad_graphic_analysis_en.ts
new file mode 100644
index 0000000..1738ed1
--- /dev/null
+++ b/libs/graphic_analysis/lang/qad_graphic_analysis_en.ts
@@ -0,0 +1,32 @@
+
+
+
+
+ GraphicAnalysis
+
+
+ Spectrum
+
+
+
+
+ Select spectrum input data
+
+
+
+
+ Fix dur.:
+
+
+
+
+ s
+
+
+
+
+ Hz
+
+
+
+
diff --git a/libs/graphic_analysis/lang/qad_graphic_analysis_ru.ts b/libs/graphic_analysis/lang/qad_graphic_analysis_ru.ts
new file mode 100644
index 0000000..bcb3d51
--- /dev/null
+++ b/libs/graphic_analysis/lang/qad_graphic_analysis_ru.ts
@@ -0,0 +1,32 @@
+
+
+
+
+ GraphicAnalysis
+
+
+ Spectrum
+ Спектр
+
+
+
+ Select spectrum input data
+ Выбрать данные для построения спектра
+
+
+
+ Fix dur.:
+ Фикс. длит.:
+
+
+
+ s
+ с
+
+
+
+ Hz
+ Гц
+
+
+
diff --git a/libs/graphic_analysis/lang/update.bat b/libs/graphic_analysis/lang/update.bat
new file mode 100644
index 0000000..bebfc28
--- /dev/null
+++ b/libs/graphic_analysis/lang/update.bat
@@ -0,0 +1,2 @@
+lupdate ../ -ts qad_graphic_analysis_ru.ts
+lupdate ../ -ts qad_graphic_analysis_en.ts
diff --git a/libs/graphic_analysis/plugin/CMakeLists.txt b/libs/graphic_analysis/plugin/CMakeLists.txt
new file mode 100644
index 0000000..a5a4d99
--- /dev/null
+++ b/libs/graphic_analysis/plugin/CMakeLists.txt
@@ -0,0 +1 @@
+qad_plugin(graphic_analysis "Gui;Widgets" "")
diff --git a/libs/graphic_analysis/plugin/graphic_analysis_plugin.cpp b/libs/graphic_analysis/plugin/graphic_analysis_plugin.cpp
new file mode 100644
index 0000000..a1bc9e8
--- /dev/null
+++ b/libs/graphic_analysis/plugin/graphic_analysis_plugin.cpp
@@ -0,0 +1,71 @@
+#include "graphic_analysis_plugin.h"
+
+#include "graphic_analysis.h"
+
+#include
+#include
+#include
+
+
+GraphicAnalysisPlugin::GraphicAnalysisPlugin(QObject * parent): QObject(parent) {
+ m_initialized = m_designer = false;
+}
+
+
+void GraphicAnalysisPlugin::initialize(QDesignerFormEditorInterface * core) {
+ m_designer = true;
+ if (m_initialized) return;
+ m_initialized = true;
+}
+
+
+bool GraphicAnalysisPlugin::isInitialized() const {
+ return m_initialized;
+}
+
+
+QWidget * GraphicAnalysisPlugin::createWidget(QWidget * parent) {
+ auto ret = new GraphicAnalysis(parent);
+ if (m_designer) ret->m_fakeGL = true;
+ return ret;
+}
+
+
+QString GraphicAnalysisPlugin::name() const {
+ return QLatin1String("GraphicAnalysis");
+}
+
+
+QString GraphicAnalysisPlugin::group() const {
+ return QLatin1String("Display Widgets");
+}
+
+
+QIcon GraphicAnalysisPlugin::icon() const {
+ return QIcon(":/icons/graphic.png");
+}
+
+
+QString GraphicAnalysisPlugin::toolTip() const {
+ return QLatin1String(""); // QLatin1String("Widget for display any math graphics with grid and navigation");
+}
+
+
+QString GraphicAnalysisPlugin::whatsThis() const {
+ return QLatin1String("");
+}
+
+
+bool GraphicAnalysisPlugin::isContainer() const {
+ return false;
+}
+
+
+QString GraphicAnalysisPlugin::domXml() const {
+ return QLatin1String("\n\n");
+}
+
+
+QString GraphicAnalysisPlugin::includeFile() const {
+ return QLatin1String("graphic_analysis.h");
+}
diff --git a/libs/graphic_analysis/plugin/graphic_analysis_plugin.h b/libs/graphic_analysis/plugin/graphic_analysis_plugin.h
new file mode 100644
index 0000000..176cd59
--- /dev/null
+++ b/libs/graphic_analysis/plugin/graphic_analysis_plugin.h
@@ -0,0 +1,40 @@
+#ifndef GRAPHIC_analysis_PLUGIN_H
+#define GRAPHIC_analysis_PLUGIN_H
+
+#include
+#if QT_VERSION >= 0x050000
+# include
+#else
+# include
+#endif
+
+class GraphicAnalysis;
+
+
+class GraphicAnalysisPlugin
+ : public QObject
+ , public QDesignerCustomWidgetInterface {
+ Q_OBJECT
+ Q_INTERFACES(QDesignerCustomWidgetInterface)
+
+public:
+ GraphicAnalysisPlugin(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, m_designer;
+};
+
+
+#endif
diff --git a/libs/graphic_analysis/plugin/qad_graphic_analysis.cpp b/libs/graphic_analysis/plugin/qad_graphic_analysis.cpp
new file mode 100644
index 0000000..709138b
--- /dev/null
+++ b/libs/graphic_analysis/plugin/qad_graphic_analysis.cpp
@@ -0,0 +1,17 @@
+#include "qad_graphic_analysis.h"
+
+#include "graphic_analysis_plugin.h"
+
+QADGraphicAnalysis::QADGraphicAnalysis(QObject * parent): QObject(parent) {
+ m_widgets << new GraphicAnalysisPlugin(this);
+}
+
+
+QList QADGraphicAnalysis::customWidgets() const {
+ return m_widgets;
+}
+
+
+#if QT_VERSION < 0x050000
+Q_EXPORT_PLUGIN2(qad_graphic_analysis_plugin, QADGraphicAnalysis)
+#endif
diff --git a/libs/graphic_analysis/plugin/qad_graphic_analysis.h b/libs/graphic_analysis/plugin/qad_graphic_analysis.h
new file mode 100644
index 0000000..d0b2e4f
--- /dev/null
+++ b/libs/graphic_analysis/plugin/qad_graphic_analysis.h
@@ -0,0 +1,24 @@
+#ifndef QAD_GRAPHIC_H
+#define QAD_GRAPHIC_H
+
+#include
+#include
+
+class QADGraphicAnalysis
+ : public QObject
+ , public QDesignerCustomWidgetCollectionInterface {
+ Q_OBJECT
+ Q_INTERFACES(QDesignerCustomWidgetCollectionInterface)
+#if QT_VERSION >= 0x050000
+ Q_PLUGIN_METADATA(IID "qad.graphic_analysis")
+#endif
+
+public:
+ explicit QADGraphicAnalysis(QObject * parent = 0);
+ virtual QList customWidgets() const;
+
+private:
+ QList m_widgets;
+};
+
+#endif // QAD_GRAPHIC_H
diff --git a/libs/graphic_analysis/qad_graphic_analysis.qrc b/libs/graphic_analysis/qad_graphic_analysis.qrc
new file mode 100644
index 0000000..93e0881
--- /dev/null
+++ b/libs/graphic_analysis/qad_graphic_analysis.qrc
@@ -0,0 +1,6 @@
+
+
+ ../../icons/axis_x.png
+ ../../icons/graphic.png
+
+
diff --git a/libs/sql/sql_query.cpp b/libs/sql/sql_query.cpp
index f8164fc..a01d760 100644
--- a/libs/sql/sql_query.cpp
+++ b/libs/sql/sql_query.cpp
@@ -29,6 +29,7 @@ QAD::SQLQuery::Result QAD::SQLQuery::exec(QString query_, QVariantMap params, QS
ret.ok = true;
ret.rows = q.q.numRowsAffected();
ret.insertId = q.q.lastInsertId();
+ ret.query = q.q;
return ret;
}
if (Singleton::instance()->fail_handler) Singleton::instance()->fail_handler(q.q.lastQuery(), params, q.q.lastError());
diff --git a/libs/sql/sql_query.h b/libs/sql/sql_query.h
index 8b84cff..0a5d150 100644
--- a/libs/sql/sql_query.h
+++ b/libs/sql/sql_query.h
@@ -39,6 +39,7 @@ public:
bool ok = false;
int rows = 0;
QVariant insertId = -1;
+ QSqlQuery query;
operator bool() const { return ok; }
};