mirror of
https://github.com/zhuzichu520/FluentUI.git
synced 2025-07-05 09:35:28 +08:00
add qcustomplot
This commit is contained in:
@ -30,8 +30,8 @@ endif ()
|
||||
option(FLUENTUI_BUILD_STATIC_LIB "Build static library." OFF)
|
||||
|
||||
#导入Qt相关依赖包
|
||||
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core Quick Qml)
|
||||
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Quick)
|
||||
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core Quick Qml Widgets PrintSupport)
|
||||
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Quick Widgets PrintSupport)
|
||||
|
||||
set(QT_SDK_DIR "${Qt${QT_VERSION_MAJOR}_DIR}/../../..")
|
||||
cmake_path(SET QT_SDK_DIR NORMALIZE ${QT_SDK_DIR})
|
||||
@ -196,6 +196,8 @@ target_link_libraries(${PROJECT_NAME} PUBLIC
|
||||
Qt${QT_VERSION_MAJOR}::Core
|
||||
Qt${QT_VERSION_MAJOR}::Quick
|
||||
Qt${QT_VERSION_MAJOR}::Qml
|
||||
Qt${QT_VERSION_MAJOR}::Widgets
|
||||
Qt${QT_VERSION_MAJOR}::PrintSupport
|
||||
)
|
||||
if(APPLE)
|
||||
find_library(CARBON_LIBRARY Carbon)
|
||||
@ -216,6 +218,10 @@ elseif(UNIX)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE X11)
|
||||
endif()
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/qmlcustomplot
|
||||
)
|
||||
|
||||
if ((${QT_VERSION_MAJOR} LESS_EQUAL 6) AND (CMAKE_BUILD_TYPE MATCHES "Release"))
|
||||
find_program(QML_PLUGIN_DUMP NAMES qmlplugindump)
|
||||
add_custom_target(Script-Generate-QmlTypes
|
||||
|
@ -17,6 +17,11 @@
|
||||
#include "FluFrameless.h"
|
||||
#include "FluTableModel.h"
|
||||
#include "FluHotkey.h"
|
||||
#include "qmlcustomplot/TimePlot.h"
|
||||
#include "qmlcustomplot/baseplot.h"
|
||||
#include "qmlcustomplot/axis.h"
|
||||
#include "qmlcustomplot/ticker.h"
|
||||
#include "qmlcustomplot/grid.h"
|
||||
|
||||
void FluentUI::registerTypes(QQmlEngine *engine) {
|
||||
initializeEngine(engine, _uri);
|
||||
@ -40,6 +45,13 @@ void FluentUI::registerTypes(const char *uri) const {
|
||||
qmlRegisterType<FluHotkey>(uri, major, minor, "FluHotkey");
|
||||
qmlRegisterType<FluTableSortProxyModel>(uri, major, minor, "FluTableSortProxyModel");
|
||||
|
||||
qmlRegisterType<QmlQCustomPlot::TimePlot>(uri, major, minor, "TimePlot");
|
||||
qmlRegisterType<QmlQCustomPlot::BasePlot>(uri, major, minor, "BasePlot");
|
||||
|
||||
qmlRegisterUncreatableType<QmlQCustomPlot::Axis>(uri, major, minor, "Axis", "");
|
||||
qmlRegisterUncreatableType<QmlQCustomPlot::Ticker>(uri, major, minor, "Ticker", "");
|
||||
qmlRegisterUncreatableType<QmlQCustomPlot::Grid>(uri, major, minor, "Grid", "");
|
||||
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluAcrylic.qml"), uri, major, minor, "FluAcrylic");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluAppBar.qml"), uri, major, minor, "FluAppBar");
|
||||
qmlRegisterType(QUrl("qrc:/qt/qml/FluentUI/Controls/FluFrame.qml"), uri, major, minor, "FluFrame");
|
||||
|
88
src/qmlcustomplot/TimePlot.cpp
Normal file
88
src/qmlcustomplot/TimePlot.cpp
Normal file
@ -0,0 +1,88 @@
|
||||
#include "TimePlot.h"
|
||||
#include "graph.h"
|
||||
#include "axis.h"
|
||||
#include "qcustomplot.h"
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
namespace QmlQCustomPlot
|
||||
{
|
||||
|
||||
TimePlot::TimePlot(QQuickItem *parent)
|
||||
: BasePlot(parent)
|
||||
, m_timer(new QTimer(this))
|
||||
{
|
||||
xAxis()->setTickerType(Axis::Time);
|
||||
connect(m_timer, &QTimer::timeout, this, &TimePlot::onTimeOut);
|
||||
m_timer->start(5);
|
||||
startTimer(25);
|
||||
m_plotTimeRangeInMilliseconds = 60;
|
||||
}
|
||||
|
||||
TimePlot::~TimePlot()
|
||||
{
|
||||
}
|
||||
|
||||
void TimePlot::set_plotTimeRangeInMilliseconds(int value) noexcept
|
||||
{
|
||||
if(m_plotTimeRangeInMilliseconds != value) {
|
||||
m_plotTimeRangeInMilliseconds = value;
|
||||
emit plotTimeRangeInMillisecondsChanged(value);
|
||||
}
|
||||
}
|
||||
|
||||
Q_INVOKABLE void TimePlot::setTimeFormat(const QString &format) noexcept
|
||||
{
|
||||
if(xAxis()) {
|
||||
QSharedPointer<QCPAxisTickerTime> timeTicker(new QCPAxisTickerTime);
|
||||
timeTicker->setTimeFormat(format);
|
||||
xAxis()->setTicker(timeTicker);
|
||||
}
|
||||
}
|
||||
|
||||
Q_INVOKABLE void TimePlot::addCurrentTimeValue(const QString &name, double value) noexcept
|
||||
{
|
||||
auto graph = getGraph(name);
|
||||
if(graph) {
|
||||
graph->addData(m_currentTimeKey, value);
|
||||
}
|
||||
}
|
||||
|
||||
Q_INVOKABLE void TimePlot::addCurrentTimeValues(QVariantMap values) noexcept
|
||||
{
|
||||
for(auto it = values.begin(); it != values.end(); ++it) {
|
||||
addCurrentTimeValue(it.key(), it.value().toDouble());
|
||||
}
|
||||
}
|
||||
|
||||
void TimePlot::onTimeOut() noexcept
|
||||
{
|
||||
auto todayString = QDateTime::currentDateTime().toString("yyyy-MM-dd") + " 00:00:00";
|
||||
auto todayTime = QDateTime::fromString(todayString, "yyyy-MM-dd hh:mm:ss");
|
||||
m_currentTimeKey = todayTime.msecsTo(QDateTime::currentDateTime()) / 1000.0;
|
||||
if(m_currentTimeKey - m_lastClearTime > m_plotTimeRangeInMilliseconds || m_currentTimeKey < m_lastClearTime) {
|
||||
auto map = graphsMap();
|
||||
std::for_each(map.begin(), map.end(), [this](auto graph) {
|
||||
if(graph) graph->removeDataBefore(m_currentTimeKey - m_plotTimeRangeInMilliseconds);
|
||||
});
|
||||
m_lastClearTime = m_currentTimeKey;
|
||||
}
|
||||
// if(m_currentTimeKey - m_lastAddedTime > 0.002 || m_currentTimeKey < m_lastAddedTime) {
|
||||
// auto map = graphsMap();
|
||||
// std::for_each(map.begin(), map.end(), [this](auto graph) {
|
||||
// if(graph) graph->addData(m_currentTimeKey, 4.0);
|
||||
// });
|
||||
// m_lastAddedTime = m_currentTimeKey;
|
||||
// }
|
||||
if(xAxis())
|
||||
xAxis()->setRange(m_currentTimeKey - m_plotTimeRangeInMilliseconds, m_currentTimeKey);
|
||||
// QCP::MarginSide s = &static_cast<QCP::MarginSide*>((customPlot()->axisRect()->autoMargins()));
|
||||
// qDebug() << s;
|
||||
}
|
||||
|
||||
void TimePlot::timerEvent(QTimerEvent *event)
|
||||
{
|
||||
customPlot()->replot();
|
||||
}
|
||||
|
||||
} // namespace QmlQCustomPlot
|
113
src/qmlcustomplot/TimePlot.h
Normal file
113
src/qmlcustomplot/TimePlot.h
Normal file
@ -0,0 +1,113 @@
|
||||
#pragma once
|
||||
|
||||
#include "baseplot.h"
|
||||
|
||||
#include <QElapsedTimer>
|
||||
|
||||
class QTimer;
|
||||
|
||||
namespace QmlQCustomPlot
|
||||
{
|
||||
|
||||
/*
|
||||
* @class TimePlot
|
||||
* @brief A class for dynamically updating the x-axis and curves with the current time in milliseconds.
|
||||
*
|
||||
* This class extends the BasePlot and provides functionalities to dynamically update
|
||||
* a plot with time values. It allows adding time values either individually or in bulk.
|
||||
* The x-axis is based on the current time of the day, displaying values within a specified time range.
|
||||
*/
|
||||
class TimePlot : public BasePlot
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
QML_READ_WRITE_NOTIFY_PROPERTY(int, plotTimeRangeInMilliseconds) // Property to hold the time range for the plot display in milliseconds.
|
||||
public:
|
||||
/*
|
||||
* @brief Constructor for the TimePlot class.
|
||||
*
|
||||
* This constructor initializes the TimePlot object, setting the parent QQuickItem and
|
||||
* initializing the internal timer and elapsed time tracker.
|
||||
*
|
||||
* @param parent The parent QQuickItem, default is nullptr.
|
||||
*/
|
||||
TimePlot(QQuickItem *parent = nullptr);
|
||||
|
||||
~TimePlot();
|
||||
|
||||
/*
|
||||
* @brief Sets the time range for the plot display in milliseconds.
|
||||
*
|
||||
* This function allows the user to specify the range of time (in milliseconds) that the
|
||||
* plot should display on the x-axis. For example, setting this to 60000 will display the
|
||||
* last 60 seconds of data on the plot.
|
||||
* Default is 60 seconds
|
||||
*
|
||||
* @param value The time range in milliseconds.
|
||||
*/
|
||||
void set_plotTimeRangeInMilliseconds(int value) noexcept;
|
||||
|
||||
/*
|
||||
* @brief Sets the time format for the x-axis labels.
|
||||
*
|
||||
* This function allows the user to specify the format of the time labels on the x-axis.
|
||||
* The format should be a valid QDateTime format string, such as "hh:mm:ss" or "hh:mm:ss.zzz".
|
||||
* Default is "hh:mm:ss".
|
||||
*
|
||||
* @param format The format string for the time labels.
|
||||
*/
|
||||
Q_INVOKABLE void setTimeFormat(const QString &format) noexcept;
|
||||
|
||||
/*
|
||||
* @brief Adds a current time value to the plot.
|
||||
*
|
||||
* This function adds a single data point to the plot. The x-axis value is the current
|
||||
* elapsed time in milliseconds since the timer started, and the y-axis value is provided
|
||||
* by the user. The data point is associated with a specific series name (curve name).
|
||||
*
|
||||
* @param name The name of the data series (curve name).
|
||||
* @param value The value to be added to the plot.
|
||||
*/
|
||||
Q_INVOKABLE void addCurrentTimeValue(const QString& name, double value) noexcept;
|
||||
|
||||
/*
|
||||
* @brief Adds multiple current time values to the plot.
|
||||
*
|
||||
* This function allows adding multiple data points to the plot at once. The values are
|
||||
* provided as a QVariantMap, where each key is the name of a data series (curve name)
|
||||
* and the corresponding value is the data point to be added. The x-axis value for all
|
||||
* data points is the current elapsed time in milliseconds.
|
||||
*
|
||||
* @param values A map of series names (curve names) and their corresponding values to be added to the plot.
|
||||
*/
|
||||
Q_INVOKABLE void addCurrentTimeValues(QVariantMap values) noexcept;
|
||||
|
||||
protected:
|
||||
/*
|
||||
* @brief Function called when the timer times out.
|
||||
*
|
||||
* This function is intended to be overridden by subclasses to define custom behavior
|
||||
* when the timer expires. By default, it does nothing, but it can be used to update
|
||||
* the plot or perform other actions at regular intervals.
|
||||
*/
|
||||
virtual void onTimeOut() noexcept;
|
||||
|
||||
/*
|
||||
* @brief Handles timer events.
|
||||
*
|
||||
* This function is called automatically by the Qt framework when a timer event occurs.
|
||||
* It updates the plot by adding a new time value if necessary and handles any other
|
||||
* timer-related functionality.
|
||||
*
|
||||
* @param event The timer event containing information about the timer that triggered the event.
|
||||
*/
|
||||
void timerEvent(QTimerEvent *event) override;
|
||||
|
||||
private:
|
||||
QTimer *m_timer = nullptr; ///< Pointer to the QTimer object used to trigger regular updates.
|
||||
double m_currentTimeKey = 0; ///< Current time key (x-axis value) in seconds.
|
||||
// double m_lastAddedTime = 0; ///< Time (in milliseconds) of the last added data point.
|
||||
double m_lastClearTime = 0; ///< Time (in milliseconds) of the last clear operation.
|
||||
};
|
||||
|
||||
} // namespace QmlQCustomPlot
|
132
src/qmlcustomplot/axis.cpp
Normal file
132
src/qmlcustomplot/axis.cpp
Normal file
@ -0,0 +1,132 @@
|
||||
#include "axis.h"
|
||||
#include "grid.h"
|
||||
#include "ticker.h"
|
||||
#include "qcustomplot.h"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
namespace QmlQCustomPlot
|
||||
{
|
||||
|
||||
Axis::Axis(QObject *parent) : QObject(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
Axis::Axis(QCPAxis* axis, QCustomPlot *parentPlot, QObject *parent)
|
||||
: m_parentPlot(parentPlot), m_axis(axis), QObject(parent)
|
||||
{
|
||||
if(parentPlot == nullptr || axis == nullptr)
|
||||
throw std::invalid_argument(nullptr);
|
||||
connect(parentPlot, &QCustomPlot::beforeReplot, this, &Axis::updateProperty);
|
||||
connect(axis, &QCPAxis::destroyed, this, &Axis::deleteLater);
|
||||
m_ticker = new Ticker(axis, m_parentPlot, this);
|
||||
m_grid = new Grid(axis->grid(), m_parentPlot, this);
|
||||
updateProperty();
|
||||
}
|
||||
|
||||
Axis::~Axis()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Axis::setTickerType(TickerType type)
|
||||
{
|
||||
QSharedPointer<QCPAxisTicker> ticker;
|
||||
switch (type)
|
||||
{
|
||||
default:
|
||||
case Fixed:
|
||||
ticker = QSharedPointer<QCPAxisTicker>(new QCPAxisTickerFixed);
|
||||
break;
|
||||
case Log:
|
||||
ticker = QSharedPointer<QCPAxisTicker>(new QCPAxisTickerLog);
|
||||
break;
|
||||
case Pi:
|
||||
ticker = QSharedPointer<QCPAxisTicker>(new QCPAxisTickerPi);
|
||||
break;
|
||||
case Text:
|
||||
ticker = QSharedPointer<QCPAxisTicker>(new QCPAxisTickerText);
|
||||
break;
|
||||
case DateTime:
|
||||
ticker = QSharedPointer<QCPAxisTicker>(new QCPAxisTickerDateTime);
|
||||
break;
|
||||
case Time:
|
||||
ticker = QSharedPointer<QCPAxisTicker>(new QCPAxisTickerTime);
|
||||
break;
|
||||
}
|
||||
m_axis->setTicker(ticker);
|
||||
m_parentPlot->replot();
|
||||
}
|
||||
|
||||
void Axis::setRange(float position, float size, Qt::AlignmentFlag align) noexcept
|
||||
{
|
||||
m_axis->setRange(position, size, align);
|
||||
m_parentPlot->replot();
|
||||
}
|
||||
|
||||
Q_INVOKABLE void Axis::setRange(float lower, float upper) noexcept
|
||||
{
|
||||
m_axis->setRange(lower, upper);
|
||||
}
|
||||
|
||||
void Axis::setTicker(QSharedPointer<QCPAxisTicker> ticker) noexcept
|
||||
{
|
||||
m_axis->setTicker(ticker);
|
||||
m_parentPlot->replot();
|
||||
}
|
||||
|
||||
void Axis::set_visible(bool value) noexcept
|
||||
{
|
||||
m_visible = m_axis->visible();
|
||||
if(m_visible == value) return;
|
||||
m_visible = value;
|
||||
m_axis->setVisible(value);
|
||||
Q_EMIT visibleChanged(m_visible);
|
||||
m_parentPlot->replot();
|
||||
}
|
||||
|
||||
void Axis::set_label(const QString &value) noexcept
|
||||
{
|
||||
m_label = m_axis->label();
|
||||
if(m_label == value) return;
|
||||
m_label = value;
|
||||
m_axis->setLabel(value);
|
||||
Q_EMIT labelChanged(m_label);
|
||||
m_parentPlot->replot();
|
||||
}
|
||||
|
||||
void Axis::set_upper(float value) noexcept
|
||||
{
|
||||
m_upper = m_axis->range().upper;
|
||||
if(m_upper == value) return;
|
||||
m_upper = value;
|
||||
m_axis->setRangeLower(value);
|
||||
Q_EMIT upperChanged(m_upper);
|
||||
m_parentPlot->replot();
|
||||
}
|
||||
|
||||
void Axis::set_lower(float value) noexcept
|
||||
{
|
||||
m_lower = m_axis->range().lower;
|
||||
if(m_lower == value) return;
|
||||
m_lower = value;
|
||||
m_axis->setRangeUpper(value);
|
||||
Q_EMIT lowerChanged(m_lower);
|
||||
m_parentPlot->replot();
|
||||
}
|
||||
|
||||
void Axis::updateProperty() noexcept
|
||||
{
|
||||
m_visible = m_axis->visible();
|
||||
m_label = m_axis->label();
|
||||
m_upper = m_axis->range().upper;
|
||||
m_lower = m_axis->range().lower;
|
||||
Q_EMIT visibleChanged(m_visible);
|
||||
Q_EMIT labelChanged(m_label);
|
||||
Q_EMIT upperChanged(m_upper);
|
||||
Q_EMIT lowerChanged(m_lower);
|
||||
}
|
||||
|
||||
} // namespace QmlQCustomPlot
|
56
src/qmlcustomplot/axis.h
Normal file
56
src/qmlcustomplot/axis.h
Normal file
@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
|
||||
#include "macros.h"
|
||||
#include <QtCore/QObject>
|
||||
#include <QtQml/qqml.h>
|
||||
#include "grid.h"
|
||||
#include "ticker.h"
|
||||
|
||||
class QCPAxis;
|
||||
class QCPAxisTicker;
|
||||
class QCustomPlot;
|
||||
|
||||
|
||||
namespace QmlQCustomPlot
|
||||
{
|
||||
|
||||
class Grid;
|
||||
class Ticker;
|
||||
class Axis : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_READ_WRITE_NOTIFY_PROPERTY(bool , visible)
|
||||
QML_READ_WRITE_NOTIFY_PROPERTY(QString , label)
|
||||
QML_READ_WRITE_NOTIFY_PROPERTY(float , upper)
|
||||
QML_READ_WRITE_NOTIFY_PROPERTY(float , lower)
|
||||
QML_READ_CONSTANT(QmlQCustomPlot::Grid*, grid)
|
||||
QML_READ_CONSTANT(QmlQCustomPlot::Ticker*, ticker)
|
||||
QML_ELEMENT
|
||||
QML_UNCREATABLE("")
|
||||
public:
|
||||
explicit Axis(QObject *parent = nullptr);
|
||||
Axis(QCPAxis* axis, QCustomPlot *parentPlot, QObject *parent = nullptr);
|
||||
~Axis();
|
||||
|
||||
Q_ENUMS(TickerType)
|
||||
enum TickerType { Fixed, Log, Pi, Text, DateTime, Time };
|
||||
Q_INVOKABLE void setTickerType(TickerType type);
|
||||
Q_INVOKABLE void setRange(float position, float size, Qt::AlignmentFlag align) noexcept;
|
||||
Q_INVOKABLE void setRange(float lower, float upper) noexcept;
|
||||
|
||||
void setTicker(QSharedPointer<QCPAxisTicker> ticker) noexcept;
|
||||
|
||||
void set_visible(bool value) noexcept;
|
||||
void set_label(const QString &value) noexcept;
|
||||
void set_upper(float value) noexcept;
|
||||
void set_lower(float value) noexcept;
|
||||
|
||||
private:
|
||||
void updateProperty() noexcept;
|
||||
|
||||
private:
|
||||
QCustomPlot *m_parentPlot = nullptr;
|
||||
QCPAxis* m_axis = nullptr;
|
||||
};
|
||||
|
||||
} // namespace QmlQCustomPlot
|
138
src/qmlcustomplot/baseplot.cpp
Normal file
138
src/qmlcustomplot/baseplot.cpp
Normal file
@ -0,0 +1,138 @@
|
||||
#include "baseplot.h"
|
||||
#include "axis.h"
|
||||
#include "graph.h"
|
||||
#include "qcustomplot.h"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
namespace QmlQCustomPlot
|
||||
{
|
||||
|
||||
|
||||
BasePlot::BasePlot(QQuickItem *parent)
|
||||
: QQuickPaintedItem(parent)
|
||||
, m_customPlot(new QCustomPlot())
|
||||
{
|
||||
setFlag(QQuickItem::ItemHasContents, true);
|
||||
setAcceptedMouseButtons(Qt::AllButtons);
|
||||
setAcceptHoverEvents(true);
|
||||
connect(this, &QQuickPaintedItem::widthChanged, this, &BasePlot::onChartViewSizeChanged);
|
||||
connect(this, &QQuickPaintedItem::heightChanged, this, &BasePlot::onChartViewSizeChanged);
|
||||
connect(m_customPlot, &QCustomPlot::afterReplot, this, &BasePlot::onChartViewReplot, Qt::UniqueConnection);
|
||||
try {
|
||||
m_xAxis = new Axis(m_customPlot->xAxis, m_customPlot, this);
|
||||
m_x1Axis = new Axis(m_customPlot->xAxis2, m_customPlot, this);
|
||||
m_yAxis = new Axis(m_customPlot->yAxis, m_customPlot, this);
|
||||
m_y1Axis = new Axis(m_customPlot->yAxis2, m_customPlot, this);
|
||||
connect(m_xAxis, &Axis::destroyed, this, [this]{ m_xAxis = nullptr; Q_EMIT xAxisChanged(nullptr); });
|
||||
connect(m_x1Axis, &Axis::destroyed, this, [this]{ m_x1Axis = nullptr; Q_EMIT x1AxisChanged(nullptr);});
|
||||
connect(m_yAxis, &Axis::destroyed, this, [this]{ m_yAxis = nullptr; Q_EMIT yAxisChanged(nullptr); });
|
||||
connect(m_y1Axis, &Axis::destroyed, this, [this]{ m_y1Axis = nullptr; Q_EMIT y1AxisChanged(nullptr);});
|
||||
connect(m_customPlot->xAxis, SIGNAL(rangeChanged(QCPRange)), m_customPlot->xAxis2, SLOT(setRange(QCPRange)));
|
||||
connect(m_customPlot->yAxis, SIGNAL(rangeChanged(QCPRange)), m_customPlot->yAxis2, SLOT(setRange(QCPRange)));
|
||||
|
||||
}
|
||||
catch(const std::exception &e) {
|
||||
qCritical() << e.what();
|
||||
m_xAxis = nullptr;
|
||||
m_x1Axis = nullptr;
|
||||
m_yAxis = nullptr;
|
||||
m_y1Axis = nullptr;
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
BasePlot::~BasePlot()
|
||||
{
|
||||
delete m_customPlot;
|
||||
}
|
||||
|
||||
void BasePlot::set_backgroundColor(const QColor &value)
|
||||
{
|
||||
// m_backgroundColor = m_customPlot->background().toImage().pixelColor(0, 0);
|
||||
if(m_backgroundColor == value) return;
|
||||
m_backgroundColor = value;
|
||||
m_customPlot->setBackground(QBrush(m_backgroundColor));
|
||||
// m_customPlot->axisRect()->setBackground(QBrush(m_backgroundColor));
|
||||
emit backgroundColorChanged(m_backgroundColor);
|
||||
m_customPlot->replot();
|
||||
}
|
||||
|
||||
QVariantMap BasePlot::graphs() const
|
||||
{
|
||||
QVariantMap map;
|
||||
for(auto it = m_graphs.begin(); it != m_graphs.end(); ++it) {
|
||||
map.insert(it.key(), QVariant::fromValue(it.value()));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
Q_INVOKABLE void BasePlot::addGraph(const QString &key)
|
||||
{
|
||||
if(m_graphs.contains(key)) return;
|
||||
|
||||
auto g = m_customPlot->addGraph();
|
||||
if(g == nullptr) return;
|
||||
g->setName(key);
|
||||
auto graph = new Graph(g, m_customPlot, this);
|
||||
m_graphs.insert(key, graph);
|
||||
emit graphsChanged();
|
||||
}
|
||||
|
||||
Q_INVOKABLE void BasePlot::removeGraph(const QString &key)
|
||||
{
|
||||
if(m_graphs.contains(key)) {
|
||||
auto graph = m_graphs.take(key);
|
||||
delete graph;
|
||||
emit graphsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
Q_INVOKABLE void BasePlot::rescaleAxes(bool onlyVisiblePlottables)
|
||||
{
|
||||
m_customPlot->rescaleAxes(onlyVisiblePlottables);
|
||||
}
|
||||
|
||||
Graph *BasePlot::getGraph(const QString &key) const
|
||||
{
|
||||
if(m_graphs.contains(key)) {
|
||||
return m_graphs.value(key);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void BasePlot::paint(QPainter *painter)
|
||||
{
|
||||
if (!painter->isActive())
|
||||
return;
|
||||
QPixmap picture( boundingRect().size().toSize() );
|
||||
QCPPainter qcpPainter( &picture );
|
||||
m_customPlot->toPainter(&qcpPainter);
|
||||
painter->drawPixmap(QPoint(), picture);
|
||||
}
|
||||
|
||||
void BasePlot::onChartViewSizeChanged()
|
||||
{
|
||||
m_customPlot->setGeometry(0, 0, (int)width(), (int)height());
|
||||
m_customPlot->setViewport(QRect(0, 0, (int)width(), (int)height()));
|
||||
m_customPlot->axisRect()->setOuterRect(QRect(0, 0, (int)width(), (int)height()));
|
||||
m_customPlot->axisRect()->setMinimumMargins (QMargins(0, 0, 0, 0));
|
||||
m_customPlot->axisRect()->setMargins(QMargins(0, 0, 0, 0));
|
||||
}
|
||||
|
||||
void BasePlot::routeMouseEvents(QMouseEvent *event)
|
||||
{
|
||||
QMouseEvent* newEvent = new QMouseEvent(event->type(), event->localPos(), event->button(), event->buttons(), event->modifiers());
|
||||
QCoreApplication::postEvent(m_customPlot, newEvent);
|
||||
}
|
||||
|
||||
void BasePlot::routeWheelEvents(QWheelEvent *event)
|
||||
{
|
||||
QWheelEvent* newEvent = new QWheelEvent(event->position(), event->globalPosition(),
|
||||
event->pixelDelta(), event->angleDelta(),
|
||||
event->buttons(), event->modifiers(),
|
||||
event->phase(), event->inverted());
|
||||
QCoreApplication::postEvent(m_customPlot, newEvent);
|
||||
}
|
||||
|
||||
} // namespace QmlQCustomPlot
|
60
src/qmlcustomplot/baseplot.h
Normal file
60
src/qmlcustomplot/baseplot.h
Normal file
@ -0,0 +1,60 @@
|
||||
#pragma once
|
||||
|
||||
#include "macros.h"
|
||||
#include <QtGui/QColor>
|
||||
#include <QtCore/QVariantMap>
|
||||
#include <QtCore/QString>
|
||||
#include <QtQuick/QQuickPaintedItem>
|
||||
|
||||
class QCustomPlot;
|
||||
|
||||
namespace QmlQCustomPlot
|
||||
{
|
||||
|
||||
class Axis;
|
||||
class Graph;
|
||||
class BasePlot : public QQuickPaintedItem
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_READ_WRITE_NOTIFY_PROPERTY(QColor, backgroundColor)
|
||||
QML_READ_NOTIFY_PROPERTY(QmlQCustomPlot::Axis *, xAxis)
|
||||
QML_READ_NOTIFY_PROPERTY(QmlQCustomPlot::Axis *, x1Axis)
|
||||
QML_READ_NOTIFY_PROPERTY(QmlQCustomPlot::Axis *, yAxis)
|
||||
QML_READ_NOTIFY_PROPERTY(QmlQCustomPlot::Axis *, y1Axis)
|
||||
QML_ELEMENT
|
||||
Q_PROPERTY(QVariantMap graphs READ graphs NOTIFY graphsChanged)
|
||||
public:
|
||||
BasePlot(QQuickItem *parent = nullptr);
|
||||
~BasePlot();
|
||||
|
||||
void set_backgroundColor(const QColor &value);
|
||||
QVariantMap graphs() const;
|
||||
Q_SIGNAL void graphsChanged();
|
||||
Q_INVOKABLE void addGraph(const QString &key);
|
||||
Q_INVOKABLE void removeGraph(const QString &key);
|
||||
Q_INVOKABLE void rescaleAxes(bool onlyVisiblePlottables=false);
|
||||
|
||||
void paint(QPainter *painter);
|
||||
QCustomPlot *customPlot() const { return m_customPlot; }
|
||||
const QMap<QString, Graph *> &graphsMap() const { return m_graphs; }
|
||||
Graph* getGraph(const QString &key) const;
|
||||
|
||||
protected:
|
||||
virtual void onChartViewReplot() { update(); }
|
||||
virtual void onChartViewSizeChanged();
|
||||
|
||||
virtual void hoverMoveEvent(QHoverEvent *event) override { Q_UNUSED(event) }
|
||||
virtual void mousePressEvent(QMouseEvent *event) override { routeMouseEvents(event); }
|
||||
virtual void mouseReleaseEvent(QMouseEvent *event) override { routeMouseEvents(event); }
|
||||
virtual void mouseMoveEvent(QMouseEvent *event) override { routeMouseEvents(event); }
|
||||
virtual void mouseDoubleClickEvent(QMouseEvent *event) override { routeMouseEvents(event); }
|
||||
virtual void wheelEvent(QWheelEvent *event) override { routeWheelEvents(event); }
|
||||
void routeMouseEvents(QMouseEvent *event);
|
||||
void routeWheelEvents(QWheelEvent *event);
|
||||
|
||||
private:
|
||||
QCustomPlot *m_customPlot = nullptr;
|
||||
QMap<QString, Graph *> m_graphs;
|
||||
};
|
||||
|
||||
} // namespace QmlQCustomPlot
|
128
src/qmlcustomplot/graph.cpp
Normal file
128
src/qmlcustomplot/graph.cpp
Normal file
@ -0,0 +1,128 @@
|
||||
#include "graph.h"
|
||||
#include "qcustomplot.h"
|
||||
|
||||
#include <QPen>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace QmlQCustomPlot
|
||||
{
|
||||
|
||||
Graph::Graph(QCPGraph* graph, QCustomPlot *parentPlot, QObject *parent)
|
||||
: m_graph(graph), m_parentPlot(parentPlot), QObject(parent)
|
||||
{
|
||||
if(parentPlot == nullptr || graph == nullptr)
|
||||
throw std::invalid_argument(nullptr);
|
||||
|
||||
connect(parentPlot, &QCustomPlot::beforeReplot, this, &Graph::updateProperty);
|
||||
updateProperty();
|
||||
}
|
||||
|
||||
Graph::~Graph()
|
||||
{
|
||||
}
|
||||
|
||||
void Graph::setData(const QVector<double> &keys, const QVector<double> &values) noexcept
|
||||
{
|
||||
m_graph->setData(keys, values);
|
||||
m_parentPlot->replot();
|
||||
}
|
||||
|
||||
void Graph::addData(double key, double value) noexcept
|
||||
{
|
||||
m_graph->addData(key, value);
|
||||
m_parentPlot->replot();
|
||||
}
|
||||
|
||||
void Graph::removeDataBefore(double key) noexcept
|
||||
{
|
||||
m_graph->data()->removeBefore(key);
|
||||
m_parentPlot->replot();
|
||||
}
|
||||
|
||||
void Graph::clearData() noexcept
|
||||
{
|
||||
m_graph->data()->clear();
|
||||
m_parentPlot->replot();
|
||||
}
|
||||
|
||||
void Graph::set_visible(bool value) noexcept
|
||||
{
|
||||
m_visible = m_graph->visible();
|
||||
if(m_visible == value) return;
|
||||
m_visible = value;
|
||||
m_graph->setVisible(value);
|
||||
Q_EMIT visibleChanged(m_visible);
|
||||
m_parentPlot->replot();
|
||||
}
|
||||
|
||||
void Graph::set_antialiased(bool value) noexcept
|
||||
{
|
||||
m_antialiased = m_graph->antialiased();
|
||||
if(m_antialiased == value) return;
|
||||
m_antialiased = value;
|
||||
m_graph->setAntialiased(value);
|
||||
Q_EMIT antialiasedChanged(m_antialiased);
|
||||
m_parentPlot->replot();
|
||||
}
|
||||
|
||||
void Graph::set_name(const QString &value) noexcept
|
||||
{
|
||||
m_name = m_graph->name();
|
||||
if(m_name == value) return;
|
||||
m_name = value;
|
||||
m_graph->setName(value);
|
||||
Q_EMIT nameChanged(m_name);
|
||||
m_parentPlot->replot();
|
||||
}
|
||||
|
||||
void Graph::set_lineStyle(LineStyle value) noexcept
|
||||
{
|
||||
m_lineStyle = static_cast<Graph::LineStyle>(m_graph->lineStyle());
|
||||
if(m_lineStyle == value) return;
|
||||
m_lineStyle = value;
|
||||
m_graph->setLineStyle(static_cast<QCPGraph::LineStyle>(value));
|
||||
Q_EMIT lineStyleChanged(m_lineStyle);
|
||||
m_parentPlot->replot();
|
||||
}
|
||||
|
||||
void Graph::set_graphWidth(int value) noexcept
|
||||
{
|
||||
m_graphWidth = m_graph->pen().width();
|
||||
if(m_graphWidth == value) return;
|
||||
m_graphWidth = value;
|
||||
QPen pen = m_graph->pen();
|
||||
pen.setWidth(value);
|
||||
m_graph->setPen(pen);
|
||||
Q_EMIT graphWidthChanged(m_graphWidth);
|
||||
m_parentPlot->replot();
|
||||
}
|
||||
|
||||
void Graph::set_graphColor(const QColor &value) noexcept
|
||||
{
|
||||
m_graphColor = m_graph->pen().color();
|
||||
if(m_graphColor == value) return;
|
||||
m_graphColor = value;
|
||||
QPen pen = m_graph->pen();
|
||||
pen.setColor(value);
|
||||
m_graph->setPen(pen);
|
||||
Q_EMIT graphColorChanged(m_graphColor);
|
||||
m_parentPlot->replot();
|
||||
}
|
||||
|
||||
void Graph::updateProperty() noexcept
|
||||
{
|
||||
m_visible = m_graph->visible();
|
||||
m_antialiased = m_graph->antialiased();
|
||||
m_name = m_graph->name();
|
||||
m_lineStyle = static_cast<Graph::LineStyle>(m_graph->lineStyle());
|
||||
m_graphWidth = m_graph->pen().width();
|
||||
m_graphColor = m_graph->pen().color();
|
||||
Q_EMIT visibleChanged(m_visible);
|
||||
Q_EMIT antialiasedChanged(m_antialiased);
|
||||
Q_EMIT nameChanged(m_name);
|
||||
Q_EMIT lineStyleChanged(m_lineStyle);
|
||||
Q_EMIT graphWidthChanged(m_graphWidth);
|
||||
Q_EMIT graphColorChanged(m_graphColor);
|
||||
}
|
||||
|
||||
}
|
58
src/qmlcustomplot/graph.h
Normal file
58
src/qmlcustomplot/graph.h
Normal file
@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
#include "macros.h"
|
||||
#include <QtCore/QObject>
|
||||
#include <QtGui/QColor>
|
||||
|
||||
class QCPGraph;
|
||||
class QCustomPlot;
|
||||
|
||||
namespace QmlQCustomPlot
|
||||
{
|
||||
|
||||
class Graph : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_ENUMS(LineType)
|
||||
public:
|
||||
enum LineStyle
|
||||
{
|
||||
lsNone,
|
||||
lsLine,
|
||||
lsStepLeft,
|
||||
lsStepRight,
|
||||
lsStepCenter,
|
||||
lsImpulse
|
||||
};
|
||||
|
||||
private:
|
||||
QML_READ_WRITE_NOTIFY_PROPERTY(bool, visible)
|
||||
QML_READ_WRITE_NOTIFY_PROPERTY(bool, antialiased)
|
||||
QML_READ_WRITE_NOTIFY_PROPERTY(QString, name)
|
||||
QML_READ_WRITE_NOTIFY_PROPERTY(LineStyle, lineStyle)
|
||||
QML_READ_WRITE_NOTIFY_PROPERTY(int, graphWidth)
|
||||
QML_READ_WRITE_NOTIFY_PROPERTY(QColor, graphColor)
|
||||
public:
|
||||
Graph(QCPGraph *graph, QCustomPlot *parentPlot, QObject *parent = nullptr);
|
||||
~Graph();
|
||||
|
||||
Q_INVOKABLE void setData(const QVector<double> &keys, const QVector<double> &values) noexcept;
|
||||
Q_INVOKABLE void addData(double key, double value) noexcept;
|
||||
Q_INVOKABLE void removeDataBefore(double key) noexcept;
|
||||
Q_INVOKABLE void clearData() noexcept;
|
||||
void set_visible(bool value) noexcept;
|
||||
void set_antialiased(bool value) noexcept;
|
||||
void set_name(const QString &value) noexcept;
|
||||
void set_lineStyle(LineStyle value) noexcept;
|
||||
void set_graphWidth(int value) noexcept;
|
||||
void set_graphColor(const QColor &value) noexcept;
|
||||
|
||||
private:
|
||||
void updateProperty() noexcept;
|
||||
|
||||
private:
|
||||
QCustomPlot *m_parentPlot = nullptr;
|
||||
QCPGraph *m_graph = nullptr;
|
||||
};
|
||||
|
||||
} // namespace QmlQCustomPlot
|
136
src/qmlcustomplot/grid.cpp
Normal file
136
src/qmlcustomplot/grid.cpp
Normal file
@ -0,0 +1,136 @@
|
||||
#include "grid.h"
|
||||
#include "qcustomplot.h"
|
||||
|
||||
#include <QPen>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace QmlQCustomPlot
|
||||
{
|
||||
|
||||
Grid::Grid(QCPGrid* grid, QCustomPlot *parentPlot, QObject *parent)
|
||||
: m_qcpgrid(grid), m_parentPlot(parentPlot), QObject(parent)
|
||||
{
|
||||
if(parentPlot == nullptr || grid == nullptr)
|
||||
throw std::invalid_argument(nullptr);
|
||||
|
||||
connect(parentPlot, &QCustomPlot::beforeReplot, this, &Grid::updateProperty);
|
||||
updateProperty();
|
||||
}
|
||||
|
||||
Grid::~Grid()
|
||||
{
|
||||
}
|
||||
|
||||
void Grid::set_visible(bool value) noexcept
|
||||
{
|
||||
m_visible = m_qcpgrid->visible();
|
||||
if(m_visible == value) return;
|
||||
m_visible = value;
|
||||
m_qcpgrid->setVisible(value);
|
||||
Q_EMIT visibleChanged(m_visible);
|
||||
m_parentPlot->replot();
|
||||
}
|
||||
|
||||
void Grid::set_subVisible(bool value) noexcept
|
||||
{
|
||||
m_subVisible = m_qcpgrid->subGridVisible();
|
||||
if(m_subVisible == value) return;
|
||||
m_subVisible = value;
|
||||
m_qcpgrid->setSubGridVisible(value);
|
||||
Q_EMIT subVisibleChanged(m_subVisible);
|
||||
m_parentPlot->replot();
|
||||
}
|
||||
|
||||
void Grid::set_lineWidth(int value) noexcept
|
||||
{
|
||||
m_lineWidth = m_qcpgrid->pen().width();
|
||||
if(m_lineWidth == value) return;
|
||||
m_lineWidth = value;
|
||||
QPen pen = m_qcpgrid->pen();
|
||||
pen.setWidth(value);
|
||||
m_qcpgrid->setPen(pen);
|
||||
Q_EMIT lineWidthChanged(m_lineWidth);
|
||||
m_parentPlot->replot();
|
||||
}
|
||||
|
||||
void Grid::set_lineColor(const QColor &value) noexcept
|
||||
{
|
||||
m_lineColor = m_qcpgrid->pen().color();
|
||||
if(m_lineColor == value) return;
|
||||
m_lineColor = value;
|
||||
QPen pen = m_qcpgrid->pen();
|
||||
pen.setColor(value);
|
||||
m_qcpgrid->setPen(pen);
|
||||
Q_EMIT lineColorChanged(m_lineColor);
|
||||
m_parentPlot->replot();
|
||||
}
|
||||
|
||||
void Grid::set_lineType(LineType value) noexcept
|
||||
{
|
||||
m_lineType = static_cast<LineType>(m_qcpgrid->pen().style());
|
||||
if(m_lineType == value) return;
|
||||
m_lineType = value;
|
||||
QPen pen = m_qcpgrid->pen();
|
||||
pen.setStyle(static_cast<Qt::PenStyle>(value));
|
||||
m_qcpgrid->setPen(pen);
|
||||
Q_EMIT lineTypeChanged(m_lineType);
|
||||
m_parentPlot->replot();
|
||||
}
|
||||
|
||||
void Grid::set_subLineWidth(int value) noexcept
|
||||
{
|
||||
m_subLineWidth = m_qcpgrid->subGridPen().width();
|
||||
if(m_subLineWidth == value) return;
|
||||
m_subLineWidth = value;
|
||||
QPen pen = m_qcpgrid->subGridPen();
|
||||
pen.setWidth(value);
|
||||
m_qcpgrid->setSubGridPen(pen);
|
||||
Q_EMIT subLineWidthChanged(m_subLineWidth);
|
||||
m_parentPlot->replot();
|
||||
}
|
||||
|
||||
void Grid::set_subLineColor(const QColor &value) noexcept
|
||||
{
|
||||
m_subLineColor = m_qcpgrid->subGridPen().color();
|
||||
if(m_subLineColor == value) return;
|
||||
m_subLineColor = value;
|
||||
QPen pen = m_qcpgrid->subGridPen();
|
||||
pen.setColor(value);
|
||||
m_qcpgrid->setSubGridPen(pen);
|
||||
Q_EMIT subLineColorChanged(m_subLineColor);
|
||||
m_parentPlot->replot();
|
||||
}
|
||||
|
||||
void Grid::set_subLineType(LineType value) noexcept
|
||||
{
|
||||
m_subLineType = static_cast<LineType>(m_qcpgrid->subGridPen().style());
|
||||
if(m_subLineType == value) return;
|
||||
m_subLineType = value;
|
||||
QPen pen = m_qcpgrid->subGridPen();
|
||||
pen.setStyle(static_cast<Qt::PenStyle>(value));
|
||||
m_qcpgrid->setSubGridPen(pen);
|
||||
Q_EMIT subLineTypeChanged(m_subLineType);
|
||||
m_parentPlot->replot();
|
||||
}
|
||||
|
||||
void Grid::updateProperty() noexcept
|
||||
{
|
||||
m_visible = m_qcpgrid->visible();
|
||||
m_subVisible = m_qcpgrid->subGridVisible();
|
||||
m_lineWidth = m_qcpgrid->pen().width();
|
||||
m_lineColor = m_qcpgrid->pen().color();
|
||||
m_lineType = static_cast<LineType>(m_qcpgrid->pen().style());
|
||||
m_subLineWidth = m_qcpgrid->subGridPen().width();
|
||||
m_subLineColor = m_qcpgrid->subGridPen().color();
|
||||
m_subLineType = static_cast<LineType>(m_qcpgrid->subGridPen().style());
|
||||
Q_EMIT visibleChanged(m_visible);
|
||||
Q_EMIT subVisibleChanged(m_subVisible);
|
||||
Q_EMIT lineWidthChanged(m_lineWidth);
|
||||
Q_EMIT lineColorChanged(m_lineColor);
|
||||
Q_EMIT lineTypeChanged(m_lineType);
|
||||
Q_EMIT subLineWidthChanged(m_subLineWidth);
|
||||
Q_EMIT subLineColorChanged(m_subLineColor);
|
||||
Q_EMIT subLineTypeChanged(m_subLineType);
|
||||
}
|
||||
|
||||
}
|
61
src/qmlcustomplot/grid.h
Normal file
61
src/qmlcustomplot/grid.h
Normal file
@ -0,0 +1,61 @@
|
||||
#pragma once
|
||||
|
||||
#include "macros.h"
|
||||
#include <QtCore/QObject>
|
||||
#include <QtGui/QColor>
|
||||
#include <QtQml/qqml.h>
|
||||
|
||||
class QCPGrid;
|
||||
class QCustomPlot;
|
||||
|
||||
namespace QmlQCustomPlot
|
||||
{
|
||||
|
||||
class Grid : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_ENUMS(LineType)
|
||||
QML_ELEMENT
|
||||
QML_UNCREATABLE("")
|
||||
public:
|
||||
enum LineType
|
||||
{
|
||||
NoPen,
|
||||
SolidLine,
|
||||
DashLine,
|
||||
DotLine,
|
||||
DashDotLine,
|
||||
DashDotDotLine
|
||||
};
|
||||
private:
|
||||
QML_READ_WRITE_NOTIFY_PROPERTY(bool, visible)
|
||||
QML_READ_WRITE_NOTIFY_PROPERTY(bool, subVisible)
|
||||
QML_READ_WRITE_NOTIFY_PROPERTY(int, lineWidth)
|
||||
QML_READ_WRITE_NOTIFY_PROPERTY(QColor, lineColor)
|
||||
QML_READ_WRITE_NOTIFY_PROPERTY(LineType, lineType)
|
||||
QML_READ_WRITE_NOTIFY_PROPERTY(int, subLineWidth)
|
||||
QML_READ_WRITE_NOTIFY_PROPERTY(QColor, subLineColor)
|
||||
QML_READ_WRITE_NOTIFY_PROPERTY(LineType, subLineType)
|
||||
public:
|
||||
|
||||
Grid(QCPGrid* grid, QCustomPlot *parentPlot, QObject *parent = nullptr);
|
||||
~Grid();
|
||||
|
||||
void set_visible(bool value) noexcept;
|
||||
void set_subVisible(bool value) noexcept;
|
||||
void set_lineWidth(int value) noexcept;
|
||||
void set_lineColor(const QColor &value) noexcept;
|
||||
void set_lineType(LineType value) noexcept;
|
||||
void set_subLineWidth(int value) noexcept;
|
||||
void set_subLineColor(const QColor &value) noexcept;
|
||||
void set_subLineType(LineType value) noexcept;
|
||||
|
||||
private:
|
||||
void updateProperty() noexcept;
|
||||
|
||||
private:
|
||||
QCustomPlot *m_parentPlot = nullptr;
|
||||
QCPGrid *m_qcpgrid = nullptr;
|
||||
};
|
||||
|
||||
} // namespace QmlQCustomPlot
|
33
src/qmlcustomplot/macros.h
Normal file
33
src/qmlcustomplot/macros.h
Normal file
@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
namespace QmlQCustomPlot
|
||||
{
|
||||
|
||||
|
||||
|
||||
#define QML_READ_WRITE_NOTIFY_PROPERTY(TYPE, NAME) \
|
||||
Q_PROPERTY(TYPE NAME READ NAME WRITE set_##NAME NOTIFY NAME##Changed) \
|
||||
public: \
|
||||
TYPE NAME() const { return m_##NAME; } \
|
||||
Q_SIGNAL void NAME##Changed(TYPE); \
|
||||
private: \
|
||||
TYPE m_##NAME {};
|
||||
|
||||
#define QML_READ_NOTIFY_PROPERTY(TYPE, NAME) \
|
||||
Q_PROPERTY(TYPE NAME READ NAME NOTIFY NAME##Changed) \
|
||||
public: \
|
||||
TYPE NAME() const { return m_##NAME; } \
|
||||
Q_SIGNAL void NAME##Changed(TYPE); \
|
||||
private: \
|
||||
TYPE m_##NAME {};
|
||||
|
||||
#define QML_READ_CONSTANT(TYPE, NAME) \
|
||||
Q_PROPERTY(TYPE NAME READ NAME CONSTANT) \
|
||||
public: \
|
||||
TYPE NAME() const { return m_##NAME; } \
|
||||
Q_SIGNAL void NAME##Changed(TYPE); \
|
||||
private: \
|
||||
TYPE m_##NAME {};
|
||||
|
||||
|
||||
} // namespace QmlQCustomPlot
|
35529
src/qmlcustomplot/qcustomplot.cpp
Normal file
35529
src/qmlcustomplot/qcustomplot.cpp
Normal file
File diff suppressed because it is too large
Load Diff
7774
src/qmlcustomplot/qcustomplot.h
Normal file
7774
src/qmlcustomplot/qcustomplot.h
Normal file
File diff suppressed because it is too large
Load Diff
120
src/qmlcustomplot/ticker.cpp
Normal file
120
src/qmlcustomplot/ticker.cpp
Normal file
@ -0,0 +1,120 @@
|
||||
#include "ticker.h"
|
||||
#include "qcustomplot.h"
|
||||
|
||||
#include <QPen>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace QmlQCustomPlot
|
||||
{
|
||||
|
||||
Ticker::Ticker(QCPAxis* parentAxis, QCustomPlot *parentPlot, QObject *parent)
|
||||
: m_parentAxis(parentAxis), m_parentPlot(parentPlot), QObject(parent)
|
||||
{
|
||||
if(parentPlot == nullptr || parentAxis == nullptr)
|
||||
throw std::invalid_argument(nullptr);
|
||||
|
||||
connect(parentPlot, &QCustomPlot::beforeReplot, this, &Ticker::updateProperty);
|
||||
updateProperty();
|
||||
}
|
||||
|
||||
Ticker::~Ticker()
|
||||
{
|
||||
}
|
||||
|
||||
void Ticker::set_ticks(bool value) noexcept
|
||||
{
|
||||
m_ticks = m_parentAxis->ticks();
|
||||
if(m_ticks == value) return;
|
||||
m_ticks = value;
|
||||
m_parentAxis->setTicks(value);
|
||||
Q_EMIT ticksChanged(m_ticks);
|
||||
m_parentPlot->replot();
|
||||
}
|
||||
|
||||
void Ticker::set_subTicks(bool value) noexcept
|
||||
{
|
||||
m_subTicks = m_parentAxis->subTicks();
|
||||
if(m_subTicks == value) return;
|
||||
m_subTicks = value;
|
||||
m_parentAxis->setSubTicks(value);
|
||||
Q_EMIT subTicksChanged(m_subTicks);
|
||||
m_parentPlot->replot();
|
||||
}
|
||||
|
||||
void Ticker::set_tickCount(int value) noexcept
|
||||
{
|
||||
m_tickCount = m_parentAxis->ticker()->tickCount();
|
||||
if(m_tickCount == value) return;
|
||||
m_tickCount = value;
|
||||
m_parentAxis->ticker()->setTickCount(value);
|
||||
Q_EMIT tickCountChanged(m_tickCount);
|
||||
m_parentPlot->replot();
|
||||
}
|
||||
|
||||
void Ticker::set_baseWidth(int value) noexcept
|
||||
{
|
||||
m_baseWidth = m_parentAxis->basePen().width();
|
||||
if(m_baseWidth == value) return;
|
||||
m_baseWidth = value;
|
||||
QPen pen = m_parentAxis->basePen();
|
||||
pen.setWidth(value);
|
||||
m_parentAxis->setBasePen(pen);
|
||||
Q_EMIT baseWidthChanged(m_baseWidth);
|
||||
m_parentPlot->replot();
|
||||
}
|
||||
|
||||
void Ticker::set_baseColor(const QColor &value) noexcept
|
||||
{
|
||||
m_baseColor = m_parentAxis->basePen().color();
|
||||
if(m_baseColor == value) return;
|
||||
m_baseColor = value;
|
||||
QPen pen = m_parentAxis->basePen();
|
||||
pen.setColor(value);
|
||||
m_parentAxis->setBasePen(pen);
|
||||
Q_EMIT baseColorChanged(m_baseColor);
|
||||
m_parentPlot->replot();
|
||||
}
|
||||
|
||||
void Ticker::set_tickColor(const QColor &value) noexcept
|
||||
{
|
||||
m_tickColor = m_parentAxis->tickPen().color();
|
||||
if(m_tickColor == value) return;
|
||||
m_tickColor = value;
|
||||
QPen pen = m_parentAxis->tickPen();
|
||||
pen.setColor(value);
|
||||
m_parentAxis->setTickPen(pen);
|
||||
Q_EMIT tickColorChanged(m_tickColor);
|
||||
m_parentPlot->replot();
|
||||
}
|
||||
|
||||
void Ticker::set_subTickColor(const QColor &value) noexcept
|
||||
{
|
||||
m_subTickColor = m_parentAxis->subTickPen().color();
|
||||
if(m_subTickColor == value) return;
|
||||
m_subTickColor = value;
|
||||
QPen pen = m_parentAxis->subTickPen();
|
||||
pen.setColor(value);
|
||||
m_parentAxis->setSubTickPen(pen);
|
||||
Q_EMIT subTickColorChanged(m_subTickColor);
|
||||
m_parentPlot->replot();
|
||||
}
|
||||
|
||||
void Ticker::updateProperty() noexcept
|
||||
{
|
||||
m_ticks = m_parentAxis->ticks();
|
||||
m_subTicks = m_parentAxis->subTicks();
|
||||
m_tickCount = m_parentAxis->ticker()->tickCount();
|
||||
m_baseWidth = m_parentAxis->basePen().width();
|
||||
m_baseColor = m_parentAxis->basePen().color();
|
||||
m_tickColor = m_parentAxis->tickPen().color();
|
||||
m_subTickColor = m_parentAxis->subTickPen().color();
|
||||
Q_EMIT ticksChanged(m_ticks);
|
||||
Q_EMIT subTicksChanged(m_subTicks);
|
||||
Q_EMIT tickCountChanged(m_tickCount);
|
||||
Q_EMIT baseWidthChanged(m_baseWidth);
|
||||
Q_EMIT baseColorChanged(m_baseColor);
|
||||
Q_EMIT tickColorChanged(m_tickColor);
|
||||
Q_EMIT subTickColorChanged(m_subTickColor);
|
||||
}
|
||||
|
||||
}
|
47
src/qmlcustomplot/ticker.h
Normal file
47
src/qmlcustomplot/ticker.h
Normal file
@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
#include "macros.h"
|
||||
#include <QtCore/QObject>
|
||||
#include <QtGui/QColor>
|
||||
#include <QtQml/qqml.h>
|
||||
|
||||
class QCPAxis;
|
||||
class QCustomPlot;
|
||||
|
||||
namespace QmlQCustomPlot
|
||||
{
|
||||
|
||||
class Ticker : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_READ_WRITE_NOTIFY_PROPERTY(bool, ticks)
|
||||
QML_READ_WRITE_NOTIFY_PROPERTY(bool, subTicks)
|
||||
QML_READ_WRITE_NOTIFY_PROPERTY(int, tickCount)
|
||||
QML_READ_WRITE_NOTIFY_PROPERTY(int, baseWidth)
|
||||
QML_READ_WRITE_NOTIFY_PROPERTY(QColor, baseColor)
|
||||
QML_READ_WRITE_NOTIFY_PROPERTY(QColor, tickColor)
|
||||
QML_READ_WRITE_NOTIFY_PROPERTY(QColor, subTickColor)
|
||||
QML_ELEMENT
|
||||
QML_UNCREATABLE("")
|
||||
public:
|
||||
|
||||
Ticker(QCPAxis* parentAxis, QCustomPlot *parentPlot, QObject *parent = nullptr);
|
||||
~Ticker();
|
||||
|
||||
void set_ticks(bool value) noexcept;
|
||||
void set_subTicks(bool value) noexcept;
|
||||
void set_tickCount(int value) noexcept;
|
||||
void set_baseWidth(int value) noexcept;
|
||||
void set_baseColor(const QColor &value) noexcept;
|
||||
void set_tickColor(const QColor &value) noexcept;
|
||||
void set_subTickColor(const QColor &value) noexcept;
|
||||
|
||||
private:
|
||||
void updateProperty() noexcept;
|
||||
|
||||
private:
|
||||
QCustomPlot *m_parentPlot = nullptr;
|
||||
QCPAxis* m_parentAxis = nullptr;
|
||||
};
|
||||
|
||||
} // namespace QmlQCustomPlot
|
Reference in New Issue
Block a user