support using QWT instead of KChart (in progress)
authorAlexey Chernobaev <achernobaev@dev.rtsoft.ru>
Tue, 6 Mar 2018 16:11:31 +0000 (19:11 +0300)
committerAlexey Chernobaev <achernobaev@dev.rtsoft.ru>
Tue, 6 Mar 2018 16:11:31 +0000 (19:11 +0300)
src/analyze/gui/chartmodel.cpp
src/analyze/gui/chartmodel.h
src/analyze/gui/chartmodel2qwtseriesdata.cpp [new file with mode: 0644]
src/analyze/gui/chartmodel2qwtseriesdata.h [new file with mode: 0644]
src/analyze/gui/chartwidget.cpp
src/analyze/gui/chartwidget.h
src/analyze/gui/gui_config.h
src/heaptrack_gui.pro

index 61456f9c015fe1e4fac10d1815e6715f16e1fba6..78ea20b7d6600bb45692a67bb980929fbc6fd7a3 100644 (file)
@@ -60,7 +60,12 @@ ChartModel::Type ChartModel::type() const
 
 QVariant ChartModel::headerData(int section, Qt::Orientation orientation, int role) const
 {
-    Q_ASSERT(orientation == Qt::Horizontal || section < columnCount());
+//!!    Q_ASSERT(orientation == Qt::Horizontal || section < columnCount());
+    if (!((orientation == Qt::Horizontal || section < columnCount())))
+    {
+        return {};
+    }
+
     if (orientation == Qt::Horizontal) {
 #ifdef KChart_FOUND
         if (role == KChart::DatasetPenRole) {
@@ -228,3 +233,13 @@ void ChartModel::clearData()
     m_columnDataSetPens = {};
     endResetModel();
 }
+
+const QPen& ChartModel::getColumnDataSetPen(int column) const
+{
+    return m_columnDataSetPens[column];
+}
+
+const QBrush& ChartModel::getColumnDataSetBrush(int column) const
+{
+    return m_columnDataSetBrushes[column];
+}
index eee5f35f2ab5b46596bdc6b4a59386552300fd9a..cb162c1a761c334a8a571ce65109e628fef8750f 100644 (file)
@@ -71,6 +71,9 @@ public:
     int rowCount(const QModelIndex& parent = QModelIndex()) const override;
     int columnCount(const QModelIndex& parent = QModelIndex()) const override;
 
+    const QPen& getColumnDataSetPen(int column) const;
+    const QBrush& getColumnDataSetBrush(int column) const;
+
 public slots:
     void resetData(const ChartData& data);
     void clearData();
diff --git a/src/analyze/gui/chartmodel2qwtseriesdata.cpp b/src/analyze/gui/chartmodel2qwtseriesdata.cpp
new file mode 100644 (file)
index 0000000..cf96d6c
--- /dev/null
@@ -0,0 +1,41 @@
+#include "chartmodel2qwtseriesdata.h"
+
+ChartModel2QwtSeriesData::ChartModel2QwtSeriesData(ChartModel *model, int column)
+    : m_model(model), m_column(column)
+{
+    updateBoundingRect();
+}
+
+void ChartModel2QwtSeriesData::updateBoundingRect()
+{
+    int rows = m_model->rowCount();
+    if (rows > 0)
+    {
+        m_boundingRect.setLeft(m_model->data(m_model->index(0, 0)).toDouble());
+        m_boundingRect.setTop(m_model->data(m_model->index(0, m_column)).toDouble());
+        m_boundingRect.setRight(m_model->data(m_model->index(rows - 1, 0)).toDouble());
+        qreal maxCost = -1E9;
+        for (int row = 0; row < rows; ++row)
+        {
+            qreal cost = m_model->data(m_model->index(row, m_column)).toDouble();
+            if (cost > maxCost)
+            {
+                maxCost = cost;
+            }
+        }
+        m_boundingRect.setBottom(maxCost);
+    }
+}
+
+QPointF ChartModel2QwtSeriesData::sample(size_t i) const
+{
+    int row = (int)i;
+    qreal timeStamp = m_model->data(m_model->index(row, 0)).toDouble();
+    qreal cost = m_model->data(m_model->index(row, m_column)).toDouble();
+    return QPointF(timeStamp, cost);
+}
+
+QRectF ChartModel2QwtSeriesData::boundingRect() const
+{
+    return m_boundingRect;
+}
diff --git a/src/analyze/gui/chartmodel2qwtseriesdata.h b/src/analyze/gui/chartmodel2qwtseriesdata.h
new file mode 100644 (file)
index 0000000..968843c
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef CHARTMODEL2QWTSERIESDATA_H
+#define CHARTMODEL2QWTSERIESDATA_H
+
+#include "chartmodel.h"
+#include "qwt_series_data.h"
+
+class ChartModel2QwtSeriesData : public QwtSeriesData<QPointF>
+{
+public:
+    ChartModel2QwtSeriesData(ChartModel *model, int column);
+
+    size_t size() const override
+    {
+        return m_model->rowCount();
+    }
+
+    QPointF sample(size_t i) const override;
+
+    virtual QRectF boundingRect() const override;
+
+private:
+    void updateBoundingRect();
+
+    ChartModel *m_model;
+    int m_column;
+    QRectF m_boundingRect;
+};
+
+#endif // CHARTMODEL2QWTSERIESDATA_H
index f61b8ab501aa28af7164a1ac7dcf4a032486c1ba..89aee21d42ac7963352240c4157596d87d3f1c58 100644 (file)
@@ -20,7 +20,7 @@
 
 #include <QVBoxLayout>
 
-#ifdef KChart_FOUND
+#if defined(KChart_FOUND)
 #include <KChartChart>
 #include <KChartPlotter>
 
 #include <KChartGridAttributes>
 #include <KChartHeaderFooter>
 #include <KChartLegend>
+#elif defined(QWT_FOUND)
+#include <qwt_plot.h>
+#include <qwt_plot_curve.h>
+#include <qwt_plot_grid.h>
+#include <qwt_symbol.h>
+#include <qwt_legend.h>
 #endif
 
 #ifdef NO_K_LIB
@@ -84,13 +90,30 @@ public:
 
 ChartWidget::ChartWidget(QWidget* parent)
     : QWidget(parent)
-#ifdef KChart_FOUND
+#if defined(KChart_FOUND)
     , m_chart(new Chart(this))
+#elif defined(QWT_FOUND)
+    , m_model(nullptr)
+    , m_plot(new QwtPlot(this))
+#endif
+#ifdef SHOW_TABLES
+    , m_tableViewTotal(new QTableView(this))
+    , m_tableViewNoTotal(new QTableView(this))
 #endif
 {
     auto layout = new QVBoxLayout(this);
-#ifdef KChart_FOUND
+#if defined(KChart_FOUND)
     layout->addWidget(m_chart);
+#elif defined(QWT_FOUND)
+    layout->addWidget(m_plot);
+#endif
+#ifdef SHOW_TABLES
+    auto hLayout = new QHBoxLayout();
+    hLayout->addWidget(m_tableViewTotal);
+    hLayout->addWidget(m_tableViewNoTotal);
+    layout->addLayout(hLayout);
+    layout->setStretch(0, 100);
+    layout->setStretch(1, 100);
 #endif
     setLayout(layout);
 
@@ -144,11 +167,14 @@ void ChartWidget::setModel(ChartModel* model, bool minimalMode)
         break;
     }
 
-#ifdef KChart_FOUND
+#if defined(KChart_FOUND) || defined(SHOW_TABLES)
+    ChartProxy *totalProxy, *proxy;
+#endif
+#if defined(KChart_FOUND)
     {
         auto totalPlotter = new Plotter(this);
         totalPlotter->setAntiAliasing(true);
-        auto totalProxy = new ChartProxy(true, this);
+        totalProxy = new ChartProxy(true, this);
         totalProxy->setSourceModel(model);
         totalPlotter->setModel(totalProxy);
         totalPlotter->setType(Plotter::Stacked);
@@ -198,11 +224,36 @@ void ChartWidget::setModel(ChartModel* model, bool minimalMode)
         plotter->setAntiAliasing(true);
         plotter->setType(Plotter::Stacked);
 
-        auto proxy = new ChartProxy(false, this);
+        proxy = new ChartProxy(false, this);
         proxy->setSourceModel(model);
         plotter->setModel(proxy);
         coordinatePlane->addDiagram(plotter);
     }
+#elif defined(QWT_FOUND)
+    connect(model, SIGNAL(modelReset()), this, SLOT(modelReset()));
+    m_model = model;
+
+//!!    m_plot->setTitle( "Plot Demo" );
+    m_plot->setCanvasBackground(Qt::white);
+    m_plot->enableAxis(QwtPlot::yRight);
+    m_plot->enableAxis(QwtPlot::yLeft, false);
+//    m_plot->setAxisScale( QwtPlot::yLeft, 0.0, 10.0 );
+//    m_plot->insertLegend( new QwtLegend() );
+
+    QwtPlotGrid *grid = new QwtPlotGrid();
+    grid->attach(m_plot);
+
+#ifdef SHOW_TABLES
+    totalProxy = new ChartProxy(true, this);
+    totalProxy->setSourceModel(model);
+
+    proxy = new ChartProxy(false, this);
+    proxy->setSourceModel(model);
+#endif // SHOW_TABLES
+#endif // QWT_FOUND
+#ifdef SHOW_TABLES
+    m_tableViewTotal->setModel(totalProxy);
+    m_tableViewNoTotal->setModel(proxy);
 #endif
 }
 
@@ -211,4 +262,62 @@ QSize ChartWidget::sizeHint() const
     return {400, 50};
 }
 
+#ifdef QWT_FOUND
+void ChartWidget::modelReset()
+{
+    updateQwtChart();
+}
+
+void ChartWidget::updateQwtChart()
+{
+    int columns = m_model->columnCount();
+//    int rows = m_model->rowCount();
+//    qDebug() << "rows: " << rows << "; columns: " << columns;
+/*
+    QwtPlotCurve *curve = new QwtPlotCurve();
+    curve->setTitle( "Some Points" );
+    QwtSymbol *symbol = new QwtSymbol( QwtSymbol::Ellipse,
+        QBrush( Qt::yellow ), QPen( Qt::red, 2 ), QSize( 8, 8 ) );
+    curve->setSymbol( symbol );
+    QPolygonF points;
+    points << QPointF( 0.0, 4.4 ) << QPointF( 1.0, 3.0 )
+        << QPointF( 2.0, 4.5 ) << QPointF( 3.0, 6.8 )
+        << QPointF( 4.0, 7.9 ) << QPointF( 5.0, 7.1 );
+    curve->setSamples( points );
+    curve->attach( m_plot );
+*/
+    m_plot->detachItems();
+
+    m_plot->setAxisTitle(QwtPlot::xBottom, m_model->headerData(0).toString());
+    m_plot->setAxisTitle(QwtPlot::yRight, m_model->headerData(1).toString());
+
+    for (int column = 1; column < columns ; column += 2)
+    {
+        auto curve = new QwtPlotCurve();
+        curve->setRenderHint(QwtPlotItem::RenderAntialiased, true);
+        curve->setYAxis(QwtPlot::yRight);
+
+        curve->setPen(m_model->getColumnDataSetPen(column));
+        curve->setBrush(m_model->getColumnDataSetBrush(column));
+
+        auto adapter = new ChartModel2QwtSeriesData(m_model, column);
+        curve->setSamples(adapter);
+/*
+        QPolygonF points;
+        for (int row = 0; row < rows; ++row)
+        {
+            QModelIndex index = m_model->index(row, 0); // time
+            qreal timeStamp = m_model->data(index).toDouble();
+            qreal cost = m_model->data(m_model->index(row, column)).toDouble();
+            points << QPointF(timeStamp, cost);
+        }
+        curve->setSamples(points);
+*/
+        curve->attach(m_plot);
+    }
+
+    m_plot->replot();
+}
+#endif
+
 #include "chartwidget.moc"
index bb8e6d2c8d6ac352116bed7318aa250d77b7f142..2c2d320b0d7a6ad1aca65a0bf3c3cbdbcd2310d3 100644 (file)
 
 #include <QWidget>
 
+//!! for debugging
+//#define SHOW_TABLES
+
+#ifdef SHOW_TABLES
+#include <QTableView>
+#endif
+
 class ChartModel;
 
-#ifdef KChart_FOUND
+#if defined(KChart_FOUND)
 namespace KChart {
 class Chart;
 }
+#elif defined(QWT_FOUND)
+#include "chartmodel2qwtseriesdata.h"
+class QwtPlot;
 #endif
 
 class QAbstractItemModel;
@@ -44,9 +54,23 @@ public:
 
     QSize sizeHint() const override;
 
+#if defined(QWT_FOUND)
+public slots:
+    void modelReset();
+#endif
+
 private:
-#ifdef KChart_FOUND
+#if defined(KChart_FOUND)
     KChart::Chart* m_chart;
+#elif defined(QWT_FOUND)
+    void updateQwtChart();
+
+    ChartModel* m_model;
+    QwtPlot* m_plot;
+#endif
+#ifdef SHOW_TABLES
+    QTableView* m_tableViewTotal;
+    QTableView* m_tableViewNoTotal;
 #endif
 };
 
index 88dddca89ee9d872e6c4c516711928c32636cc11..0e43f80781fe7af393d117e4126cbbbc61906eb1 100644 (file)
 #ifndef HEAPTRACK_GUI_CONFIG_H
 #define HEAPTRACK_GUI_CONFIG_H
 
-#ifndef NO_K_CHART
+#if !defined(NO_K_CHART)
 #define KChart_FOUND 1
+#elif defined(QWT)
+#define QWT_FOUND 1
 #endif
 
 #endif // HEAPTRACK_CONFIG_H
index 700957e67e4dd20bf118514c7731bcbb8f263c88..31535cc3bbcf1119caa5a4d13644e597cf77ef1e 100644 (file)
@@ -28,13 +28,6 @@ unix {
 #CONFIG *= NO_K_LIB
 #DEFINES *= NO_K_LIB
 
-QWT_CHART {
-    # QMAKEFEATURES and QWT_ROOT environment variables must be set (e.g. to d:\Qwt\Qwt-6.2).
-    # This is the directory where qwt.prf and qwt*.pri files reside.
-    CONFIG *= USE_CHART QWT
-    DEFINES *= USE_CHART
-}
-
 SOURCES += \
     analyze/accumulatedtracedata.cpp \
     analyze/gui/gui.cpp \
@@ -70,52 +63,57 @@ HEADERS += \
     analyze/gui/util.h \
     util/config.h
 
-!NO_K_LIB {
-    QT += KCoreAddons # for KFormat
-    QT += KI18n
-
-    QT += KIOCore
-    QT += KIOFileWidgets
-
-    QT += KConfigWidgets
-    QT += KIOWidgets
+QWT_CHART {
+    # QMAKEFEATURES and QWT_ROOT environment variables must be set (e.g. to d:\Qwt\Qwt-6.2).
+    # This is the directory where qwt.prf and qwt*.pri files reside.
+    CONFIG *= USE_CHART QWT
+    DEFINES *= USE_CHART QWT
 
-    QT += KItemModels
+    SOURCES += \
+        analyze/gui/chartmodel2qwtseriesdata.cpp
 
-    QT += ThreadWeaver
+    HEADERS += \
+        analyze/gui/chartmodel2qwtseriesdata.h
 }
 
 USE_CHART {
     SOURCES += \
         analyze/gui/chartmodel.cpp \
-#        analyze/gui/chartproxy.cpp \
+        analyze/gui/chartproxy.cpp \
         analyze/gui/chartwidget.cpp \
         analyze/gui/histogrammodel.cpp \
 #        analyze/gui/histogramwidget.cpp
 
     HEADERS += \
         analyze/gui/chartmodel.h \
-#        analyze/gui/chartproxy.h \
+        analyze/gui/chartproxy.h \
         analyze/gui/chartwidget.h \
         analyze/gui/histogrammodel.h \
 #        analyze/gui/histogramwidget.h
 }
 
+!NO_K_LIB {
+    QT += KCoreAddons # for KFormat
+    QT += KI18n
+
+    QT += KIOCore
+    QT += KIOFileWidgets
+
+    QT += KConfigWidgets
+    QT += KIOWidgets
+
+    QT += KItemModels
+
+    QT += ThreadWeaver
+}
+
 !NO_K_CHART {
     QT += KChart
 
     SOURCES += \
-#        analyze/gui/chartmodel.cpp \
-        analyze/gui/chartproxy.cpp \
-#        analyze/gui/chartwidget.cpp \
-#        analyze/gui/histogrammodel.cpp \
         analyze/gui/histogramwidget.cpp
 
     HEADERS += \
-#        analyze/gui/chartmodel.h \
-        analyze/gui/chartproxy.h \
-#        analyze/gui/chartwidget.h \
-#        analyze/gui/histogrammodel.h \
         analyze/gui/histogramwidget.h
 
     FORMS += \