- Qt 6.7
- Qt Graphs
- Graph Gallery
- Qt Graphs | Commercial or GPLv3

# Graph Gallery

     // Copyright (C) 2023 The Qt Company Ltd.
     // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause

     #include "surfacegraph.h"

     #include <QtGui/qpainter.h>
     #include <QtWidgets/qboxlayout.h>
     #include <QtWidgets/qcheckbox.h>
     #include <QtWidgets/qcombobox.h>
     #include <QtWidgets/qcommandlinkbutton.h>
     #include <QtWidgets/qgroupbox.h>
     #include <QtWidgets/qlabel.h>
     #include <QtWidgets/qradiobutton.h>

     using namespace Qt::StringLiterals;

     static QPixmap gradientBtoYPB_Pixmap()
     {
         QLinearGradient grBtoY(0, 0, 1, 100);
         grBtoY.setColorAt(1.f, Qt::black);
         grBtoY.setColorAt(0.67f, Qt::blue);
         grBtoY.setColorAt(0.33f, Qt::red);
         grBtoY.setColorAt(0.f, Qt::yellow);
         QPixmap pm(24, 100);
         QPainter pmp(&pm);
         pmp.setBrush(QBrush(grBtoY));
         pmp.setPen(Qt::NoPen);
         pmp.drawRect(0, 0, 24, 100);
         return pm;
     }

     static QPixmap gradientGtoRPB_Pixmap()
     {
         QLinearGradient grGtoR(0, 0, 1, 100);
         grGtoR.setColorAt(1.f, Qt::darkGreen);
         grGtoR.setColorAt(0.5f, Qt::yellow);
         grGtoR.setColorAt(0.2f, Qt::red);
         grGtoR.setColorAt(0.f, Qt::darkRed);
         QPixmap pm(24, 100);
         QPainter pmp(&pm);
         pmp.setBrush(QBrush(grGtoR));
         pmp.drawRect(0, 0, 24, 100);
         return pm;
     }

     static QPixmap highlightPixmap()
     {
         constexpr int height = 400;
         constexpr int width = 110;
         constexpr int border = 10;
         QLinearGradient gr(0, 0, 1, height - 2 * border);
         gr.setColorAt(1.f, Qt::black);
         gr.setColorAt(0.8f, Qt::darkGreen);
         gr.setColorAt(0.6f, Qt::green);
         gr.setColorAt(0.4f, Qt::yellow);
         gr.setColorAt(0.2f, Qt::red);
         gr.setColorAt(0.f, Qt::darkRed);

         QPixmap pmHighlight(width, height);
         pmHighlight.fill(Qt::transparent);
         QPainter pmpHighlight(&pmHighlight);
         pmpHighlight.setBrush(QBrush(gr));
         pmpHighlight.setPen(Qt::NoPen);
         pmpHighlight.drawRect(border, border, 35, height - 2 * border);
         pmpHighlight.setPen(Qt::black);
         int step = (height - 2 * border) / 5;
         for (int i = 0; i < 6; ++i) {
             int yPos = i * step + border;
             pmpHighlight.drawLine(border, yPos, 55, yPos);
             const int height = 550 - (i * 110);
             pmpHighlight.drawText(60, yPos + 2, QString::number(height) + u" m"_s);
         }
         return pmHighlight;
     }

     SurfaceGraph::SurfaceGraph()
     {
         m_surfaceGraph = new Q3DSurface();
         initialize();
     }

     void SurfaceGraph::initialize()
     {
         m_surfaceWidget = new QWidget;
         auto *hLayout = new QHBoxLayout(m_surfaceWidget);
         QSize screenSize = m_surfaceGraph->screen()->size();
         m_surfaceGraph->setMinimumSize(QSize(screenSize.width() / 2, screenSize.height() / 1.75));
         m_surfaceGraph->setMaximumSize(screenSize);
         m_surfaceGraph->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
         m_surfaceGraph->setFocusPolicy(Qt::StrongFocus);
         hLayout->addWidget(m_surfaceGraph, 1);

         auto *vLayout = new QVBoxLayout();
         hLayout->addLayout(vLayout);
         vLayout->setAlignment(Qt::AlignTop);

         // Create control widgets
         auto *modelGroupBox = new QGroupBox(u"Model"_s);

         auto *sqrtSinModelRB = new QRadioButton(m_surfaceWidget);
         sqrtSinModelRB->setText(u"Sqrt && Sin"_s);
         sqrtSinModelRB->setChecked(false);

         auto *heightMapModelRB = new QRadioButton(m_surfaceWidget);
         heightMapModelRB->setText(u"Multiseries\nHeight Map"_s);
         heightMapModelRB->setChecked(false);

         auto *texturedModelRB = new QRadioButton(m_surfaceWidget);
         texturedModelRB->setText(u"Textured\nTopography"_s);
         texturedModelRB->setChecked(false);

         auto *modelVBox = new QVBoxLayout;
         modelVBox->addWidget(sqrtSinModelRB);
         modelVBox->addWidget(heightMapModelRB);
         modelVBox->addWidget(texturedModelRB);
         modelGroupBox->setLayout(modelVBox);

         auto *selectionGroupBox = new QGroupBox(u"Graph Selection Mode"_s);

         auto *modeNoneRB = new QRadioButton(m_surfaceWidget);
         modeNoneRB->setText(u"No selection"_s);
         modeNoneRB->setChecked(false);

         auto *modeItemRB = new QRadioButton(m_surfaceWidget);
         modeItemRB->setText(u"Item"_s);
         modeItemRB->setChecked(false);

         auto *modeSliceRowRB = new QRadioButton(m_surfaceWidget);
         modeSliceRowRB->setText(u"Row Slice"_s);
         modeSliceRowRB->setChecked(false);

         auto *modeSliceColumnRB = new QRadioButton(m_surfaceWidget);
         modeSliceColumnRB->setText(u"Column Slice"_s);
         modeSliceColumnRB->setChecked(false);

         auto *selectionVBox = new QVBoxLayout;
         selectionVBox->addWidget(modeNoneRB);
         selectionVBox->addWidget(modeItemRB);
         selectionVBox->addWidget(modeSliceRowRB);
         selectionVBox->addWidget(modeSliceColumnRB);
         selectionGroupBox->setLayout(selectionVBox);

         auto *axisGroupBox = new QGroupBox(u"Axis ranges"_s);

         auto *axisMinSliderX = new QSlider(Qt::Horizontal);
         axisMinSliderX->setMinimum(0);
         axisMinSliderX->setTickInterval(1);
         axisMinSliderX->setEnabled(true);
         auto *axisMaxSliderX = new QSlider(Qt::Horizontal);
         axisMaxSliderX->setMinimum(1);
         axisMaxSliderX->setTickInterval(1);
         axisMaxSliderX->setEnabled(true);
         auto *axisMinSliderZ = new QSlider(Qt::Horizontal);
         axisMinSliderZ->setMinimum(0);
         axisMinSliderZ->setTickInterval(1);
         axisMinSliderZ->setEnabled(true);
         auto *axisMaxSliderZ = new QSlider(Qt::Horizontal);
         axisMaxSliderZ->setMinimum(1);
         axisMaxSliderZ->setTickInterval(1);
         axisMaxSliderZ->setEnabled(true);

         auto *axisVBox = new QVBoxLayout;
         axisVBox->addWidget(new QLabel(u"Column range"_s));
         axisVBox->addWidget(axisMinSliderX);
         axisVBox->addWidget(axisMaxSliderX);
         axisVBox->addWidget(new QLabel(u"Row range"_s));
         axisVBox->addWidget(axisMinSliderZ);
         axisVBox->addWidget(axisMaxSliderZ);
         axisGroupBox->setLayout(axisVBox);

         // Mode-dependent controls
         // sqrt-sin
         auto *colorGroupBox = new QGroupBox(u"Custom gradient"_s);

         QPixmap pixmap = gradientBtoYPB_Pixmap();
         auto *gradientBtoYPB = new QPushButton(m_surfaceWidget);
         gradientBtoYPB->setIcon(QIcon(pixmap));
         gradientBtoYPB->setIconSize(pixmap.size());

         pixmap = gradientGtoRPB_Pixmap();
         auto *gradientGtoRPB = new QPushButton(m_surfaceWidget);
         gradientGtoRPB->setIcon(QIcon(pixmap));
         gradientGtoRPB->setIconSize(pixmap.size());

         auto *colorHBox = new QHBoxLayout;
         colorHBox->addWidget(gradientBtoYPB);
         colorHBox->addWidget(gradientGtoRPB);
         colorGroupBox->setLayout(colorHBox);

         // Multiseries heightmap
         auto *showGroupBox = new QGroupBox(u"_show Object"_s);
         showGroupBox->setVisible(false);

         auto *checkboxShowOilRigOne = new QCheckBox(u"Oil Rig 1"_s);
         checkboxShowOilRigOne->setChecked(true);

         auto *checkboxShowOilRigTwo = new QCheckBox(u"Oil Rig 2"_s);
         checkboxShowOilRigTwo->setChecked(true);

         auto *checkboxShowRefinery = new QCheckBox(u"Refinery"_s);

         auto *showVBox = new QVBoxLayout;
         showVBox->addWidget(checkboxShowOilRigOne);
         showVBox->addWidget(checkboxShowOilRigTwo);
         showVBox->addWidget(checkboxShowRefinery);
         showGroupBox->setLayout(showVBox);

         auto *visualsGroupBox = new QGroupBox(u"Visuals"_s);
         visualsGroupBox->setVisible(false);

         auto *checkboxVisualsSeeThrough = new QCheckBox(u"See-Through"_s);

         auto *checkboxHighlightOil = new QCheckBox(u"Highlight Oil"_s);

         auto *checkboxShowShadows = new QCheckBox(u"Shadows"_s);
         checkboxShowShadows->setChecked(true);

         auto *visualVBox = new QVBoxLayout;
         visualVBox->addWidget(checkboxVisualsSeeThrough);
         visualVBox->addWidget(checkboxHighlightOil);
         visualVBox->addWidget(checkboxShowShadows);
         visualsGroupBox->setLayout(visualVBox);

         auto *labelSelection = new QLabel(u"Selection:"_s);
         labelSelection->setVisible(false);

         auto *labelSelectedItem = new QLabel(u"Nothing"_s);
         labelSelectedItem->setVisible(false);

         // Textured topography heightmap
         auto *enableTexture = new QCheckBox(u"Surface texture"_s);
         enableTexture->setVisible(false);

         auto *label = new QLabel(m_surfaceWidget);
         label->setPixmap(highlightPixmap());

         auto *heightMapGroupBox = new QGroupBox(u"Highlight color map"_s);
         auto *colorMapVBox = new QVBoxLayout;
         colorMapVBox->addWidget(label);
         heightMapGroupBox->setLayout(colorMapVBox);
         heightMapGroupBox->setVisible(false);

         // Populate vertical layout
         // Common
         vLayout->addWidget(modelGroupBox);
         vLayout->addWidget(selectionGroupBox);
         vLayout->addWidget(axisGroupBox);

         // Sqrt Sin
         vLayout->addWidget(colorGroupBox);

         // Multiseries heightmap
         vLayout->addWidget(showGroupBox);
         vLayout->addWidget(visualsGroupBox);
         vLayout->addWidget(labelSelection);
         vLayout->addWidget(labelSelectedItem);

         // Textured topography
         vLayout->addWidget(heightMapGroupBox);
         vLayout->addWidget(enableTexture);

         // Raise the graph to the top of the widget stack, to hide UI if resized smaller
         m_surfaceGraph->raise();

         // Create the controller
         m_modifier = new SurfaceGraphModifier(m_surfaceGraph, labelSelectedItem, this);

         // Connect widget controls to controller
         QObject::connect(heightMapModelRB,
                          &QRadioButton::toggled,
                          m_modifier,
                          &SurfaceGraphModifier::enableHeightMapModel);
         QObject::connect(sqrtSinModelRB,
                          &QRadioButton::toggled,
                          m_modifier,
                          &SurfaceGraphModifier::enableSqrtSinModel);
         QObject::connect(texturedModelRB,
                          &QRadioButton::toggled,
                          m_modifier,
                          &SurfaceGraphModifier::enableTopographyModel);

         QObject::connect(modeNoneRB,
                          &QRadioButton::toggled,
                          m_modifier,
                          &SurfaceGraphModifier::toggleModeNone);
         QObject::connect(modeItemRB,
                          &QRadioButton::toggled,
                          m_modifier,
                          &SurfaceGraphModifier::toggleModeItem);
         QObject::connect(modeSliceRowRB,
                          &QRadioButton::toggled,
                          m_modifier,
                          &SurfaceGraphModifier::toggleModeSliceRow);
         QObject::connect(modeSliceColumnRB,
                          &QRadioButton::toggled,
                          m_modifier,
                          &SurfaceGraphModifier::toggleModeSliceColumn);

         QObject::connect(axisMinSliderX,
                          &QSlider::valueChanged,
                          m_modifier,
                          &SurfaceGraphModifier::adjustXMin);
         QObject::connect(axisMaxSliderX,
                          &QSlider::valueChanged,
                          m_modifier,
                          &SurfaceGraphModifier::adjustXMax);
         QObject::connect(axisMinSliderZ,
                          &QSlider::valueChanged,
                          m_modifier,
                          &SurfaceGraphModifier::adjustZMin);
         QObject::connect(axisMaxSliderZ,
                          &QSlider::valueChanged,
                          m_modifier,
                          &SurfaceGraphModifier::adjustZMax);

         // Mode dependent connections
         QObject::connect(gradientBtoYPB,
                          &QPushButton::pressed,
                          m_modifier,
                          &SurfaceGraphModifier::setBlackToYellowGradient);
         QObject::connect(gradientGtoRPB,
                          &QPushButton::pressed,
                          m_modifier,
                          &SurfaceGraphModifier::setGreenToRedGradient);

         QObject::connect(checkboxShowOilRigOne,
                          &QCheckBox::stateChanged,
                          m_modifier,
                          &SurfaceGraphModifier::toggleItemOne);
         QObject::connect(checkboxShowOilRigTwo,
                          &QCheckBox::stateChanged,
                          m_modifier,
                          &SurfaceGraphModifier::toggleItemTwo);
         QObject::connect(checkboxShowRefinery,
                          &QCheckBox::stateChanged,
                          m_modifier,
                          &SurfaceGraphModifier::toggleItemThree);

         QObject::connect(checkboxVisualsSeeThrough,
                          &QCheckBox::stateChanged,
                          m_modifier,
                          &SurfaceGraphModifier::toggleSeeThrough);
         QObject::connect(checkboxHighlightOil,
                          &QCheckBox::stateChanged,
                          m_modifier,
                          &SurfaceGraphModifier::toggleOilHighlight);
         QObject::connect(checkboxShowShadows,
                          &QCheckBox::stateChanged,
                          m_modifier,
                          &SurfaceGraphModifier::toggleShadows);

         QObject::connect(enableTexture,
                          &QCheckBox::stateChanged,
                          m_modifier,
                          &SurfaceGraphModifier::toggleSurfaceTexture);

         // Connections to disable features depending on mode
         QObject::connect(sqrtSinModelRB, &QRadioButton::toggled, colorGroupBox, &QGroupBox::setVisible);

         QObject::connect(heightMapModelRB, &QRadioButton::toggled, showGroupBox, &QGroupBox::setVisible);
         QObject::connect(heightMapModelRB,
                          &QRadioButton::toggled,
                          visualsGroupBox,
                          &QGroupBox::setVisible);
         QObject::connect(heightMapModelRB, &QRadioButton::toggled, labelSelection, &QLabel::setVisible);
         QObject::connect(heightMapModelRB,
                          &QRadioButton::toggled,
                          labelSelectedItem,
                          &QLabel::setVisible);

         QObject::connect(texturedModelRB, &QRadioButton::toggled, enableTexture, &QLabel::setVisible);
         QObject::connect(texturedModelRB,
                          &QRadioButton::toggled,
                          heightMapGroupBox,
                          &QGroupBox::setVisible);

         m_modifier->setAxisMinSliderX(axisMinSliderX);
         m_modifier->setAxisMaxSliderX(axisMaxSliderX);
         m_modifier->setAxisMinSliderZ(axisMinSliderZ);
         m_modifier->setAxisMaxSliderZ(axisMaxSliderZ);

         sqrtSinModelRB->setChecked(true);
         modeItemRB->setChecked(true);
         enableTexture->setChecked(true);
     }