File indexing completed on 2024-04-14 03:39:24

0001 /*************************************************************************************
0002  *  Copyright (C) 2015 by Aleix Pol <aleixpol@kde.org>                               *
0003  *                                                                                   *
0004  *  This program is free software; you can redistribute it and/or                    *
0005  *  modify it under the terms of the GNU General Public License                      *
0006  *  as published by the Free Software Foundation; either version 2                   *
0007  *  of the License, or (at your option) any later version.                           *
0008  *                                                                                   *
0009  *  This program is distributed in the hope that it will be useful,                  *
0010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of                   *
0011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                    *
0012  *  GNU General Public License for more details.                                     *
0013  *                                                                                   *
0014  *  You should have received a copy of the GNU General Public License                *
0015  *  along with this program; if not, write to the Free Software                      *
0016  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA   *
0017  *************************************************************************************/
0018 
0019 #include "graph3ditem.h"
0020 #include <QQuickWindow>
0021 #include <QOpenGLFramebufferObject>
0022 #include <analitzaplot/plotsmodel.h>
0023 #include <QTimer>
0024 #include <QQuickItemGrabResult>
0025 #include <QGuiApplication>
0026 #include <QElapsedTimer>
0027 
0028 using namespace Analitza;
0029 
0030 Plotter3DRenderer::Plotter3DRenderer(Graph3DItem* item)
0031     : QObject(item)
0032     , m_item(item)
0033 {}
0034 
0035 void Plotter3DRenderer::renderGL()
0036 {
0037     QTimer::singleShot(0, m_item, &Graph3DItem::update);
0038 }
0039 
0040 QQuickWindow* Plotter3DRenderer::window() const
0041 {
0042     return m_item->window();
0043 }
0044 
0045 Graph3DItem::Graph3DItem(QQuickItem* parent)
0046     : QQuickFramebufferObject(parent)
0047     , m_plotter(new Plotter3DRenderer(this))
0048 {
0049     //FIXME
0050     m_plotter->setUseSimpleRotation(true);
0051     setModel(new PlotsModel(this));
0052 
0053     setMirrorVertically(true);
0054 }
0055 
0056 Graph3DItem::~Graph3DItem()
0057 {}
0058 
0059 QStringList Graph3DItem::addFunction(const QString& expression, const QSharedPointer<Analitza::Variables>& vars)
0060 {
0061     PlotsModel* plotsmodel = qobject_cast<PlotsModel*>(m_plotter->model());
0062     if(!plotsmodel)
0063         qWarning() << "only can add plots to a PlotsModel instance";
0064     else
0065         return plotsmodel->addFunction(expression, Dim3D, vars);
0066     return {};
0067 }
0068 
0069 QAbstractItemModel* Graph3DItem::model() const
0070 {
0071     return m_plotter->model();
0072 }
0073 
0074 void Graph3DItem::setModel(QAbstractItemModel* model)
0075 {
0076     if (m_plotter->model())
0077         disconnect(m_plotter->model(), nullptr, this, nullptr);
0078 
0079     m_plotter->setModel(model);
0080 
0081     connect(model, &QAbstractItemModel::dataChanged, m_plotter, [this](const QModelIndex& start, const QModelIndex& end)
0082         { m_plotter->updatePlots(QModelIndex(), start.row(), end.row()); }
0083     );
0084 
0085     auto updateCount = [this](const QModelIndex &parent, int start, int end) { m_plotter->updatePlots(parent, start, end); };
0086     connect(model, &QAbstractItemModel::rowsInserted, this, updateCount);
0087     connect(model, &QAbstractItemModel::rowsAboutToBeRemoved, this, updateCount);
0088 
0089     Q_EMIT modelChanged(model);
0090 }
0091 
0092 void Graph3DItem::rotate(qreal x, qreal y)
0093 {
0094     m_plotter->rotate(x, y);
0095 }
0096 
0097 void Graph3DItem::scale(qreal s)
0098 {
0099     m_plotter->scale(s);
0100 }
0101 
0102 void Graph3DItem::resetViewport()
0103 {
0104     m_plotter->resetViewport();
0105 }
0106 
0107 bool Graph3DItem::save(const QUrl& url)
0108 {
0109     return m_plotter->save(url);
0110 }
0111 
0112 QStringList Graph3DItem::filters() const
0113 {
0114     return m_plotter->filters();
0115 }
0116 
0117 class Plotter3DFboRenderer : public QQuickFramebufferObject::Renderer
0118 {
0119 public:
0120     Plotter3DFboRenderer(Plotter3DRenderer* plotter)
0121         : m_plotter(plotter)
0122     {
0123         m_plotter->initGL();
0124     }
0125 
0126     void render() override {
0127         m_plotter->drawPlots();
0128     }
0129 
0130     QOpenGLFramebufferObject *createFramebufferObject(const QSize &size) override
0131     {
0132         QOpenGLFramebufferObjectFormat format;
0133         format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
0134         return new QOpenGLFramebufferObject(size, format);
0135     }
0136 
0137 private:
0138     Plotter3DRenderer* m_plotter;
0139 };
0140 
0141 QQuickFramebufferObject::Renderer* Graph3DItem::createRenderer() const
0142 {
0143     m_plotter->setViewport(QRectF({0,0}, QSizeF(width(), height())));
0144     return new Plotter3DFboRenderer(m_plotter);
0145 }
0146 
0147 QImage Plotter3DRenderer::grabImage()
0148 {
0149     QSharedPointer<QQuickItemGrabResult> imgGrab = m_item->grabToImage();
0150     QImage ret;
0151     connect(imgGrab.data(), &QQuickItemGrabResult::ready, this, [imgGrab, &ret]() {
0152         ret = imgGrab->image();
0153     });
0154     QElapsedTimer timer;
0155     timer.start();
0156     while(ret.size().isEmpty() && timer.elapsed()<2000) {
0157         qGuiApp->processEvents();
0158     }
0159     return ret;
0160 }
0161 
0162 #include "moc_graph3ditem.cpp"