File indexing completed on 2024-04-28 15:14:00

0001 /***************************************************************************
0002 File                 : GuiObserver.cpp
0003 Project              : LabPlot
0004 Description          : GUI observer
0005 --------------------------------------------------------------------
0006 Copyright            : (C) 2010-2015 Alexander Semke (alexander.semke@web.de)
0007 Copyright            : (C) 2015-2018 Stefan Gerlach (stefan.gerlach@uni.kn)
0008 Copyright            : (C) 2016 Garvit Khatri (garvitdelhi@gmail.com)
0009 
0010 ***************************************************************************/
0011 
0012 /***************************************************************************
0013 *                                                                         *
0014 *  This program is free software; you can redistribute it and/or modify   *
0015 *  it under the terms of the GNU General Public License as published by   *
0016 *  the Free Software Foundation; either version 2 of the License, or      *
0017 *  (at your option) any later version.                                    *
0018 *                                                                         *
0019 *  This program is distributed in the hope that it will be useful,        *
0020 *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
0021 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
0022 *  GNU General Public License for more details.                           *
0023 *                                                                         *
0024 *   You should have received a copy of the GNU General Public License     *
0025 *   along with this program; if not, write to the Free Software           *
0026 *   Foundation, Inc., 51 Franklin Street, Fifth Floor,                    *
0027 *   Boston, MA  02110-1301  USA                                           *
0028 *                                                                         *
0029 ***************************************************************************/
0030 
0031 #include "kdefrontend/GuiObserver.h"
0032 #include "backend/core/AspectTreeModel.h"
0033 #include "backend/core/AbstractAspect.h"
0034 #include "backend/datasources/LiveDataSource.h"
0035 #include "backend/matrix/Matrix.h"
0036 #include "backend/spreadsheet/Spreadsheet.h"
0037 #include "backend/worksheet/Worksheet.h"
0038 #include "backend/worksheet/plots/cartesian/CartesianPlot.h"
0039 #include "backend/worksheet/plots/cartesian/CartesianPlotLegend.h"
0040 #include "backend/worksheet/plots/cartesian/XYCurve.h"
0041 #include "backend/worksheet/plots/cartesian/Axis.h"
0042 #include "backend/worksheet/plots/cartesian/CustomPoint.h"
0043 #include "backend/worksheet/plots/cartesian/ReferenceLine.h"
0044 #include "backend/worksheet/plots/cartesian/Histogram.h"
0045 #include "backend/worksheet/Image.h"
0046 #include "backend/worksheet/TextLabel.h"
0047 #ifdef HAVE_CANTOR_LIBS
0048 #include "backend/cantorWorksheet/CantorWorksheet.h"
0049 #endif
0050 #ifdef HAVE_MQTT
0051 #include "backend/datasources/MQTTClient.h"
0052 #include "backend/datasources/MQTTSubscription.h"
0053 #include "backend/datasources/MQTTTopic.h"
0054 #endif
0055 #include "backend/core/Project.h"
0056 #include "backend/datapicker/Datapicker.h"
0057 #include "backend/datapicker/DatapickerImage.h"
0058 #include "backend/datapicker/DatapickerCurve.h"
0059 #include "commonfrontend/ProjectExplorer.h"
0060 #include "kdefrontend/MainWin.h"
0061 #include "kdefrontend/dockwidgets/AxisDock.h"
0062 #include "kdefrontend/dockwidgets/NoteDock.h"
0063 #include "kdefrontend/dockwidgets/CursorDock.h"
0064 #include "kdefrontend/dockwidgets/CartesianPlotDock.h"
0065 #include "kdefrontend/dockwidgets/CartesianPlotLegendDock.h"
0066 #include "kdefrontend/dockwidgets/ColumnDock.h"
0067 #include "kdefrontend/dockwidgets/ImageDock.h"
0068 #include "kdefrontend/dockwidgets/LiveDataDock.h"
0069 #include "kdefrontend/dockwidgets/MatrixDock.h"
0070 #include "kdefrontend/dockwidgets/ProjectDock.h"
0071 #include "kdefrontend/dockwidgets/SpreadsheetDock.h"
0072 #include "kdefrontend/dockwidgets/XYCurveDock.h"
0073 #include "kdefrontend/dockwidgets/HistogramDock.h"
0074 #include "kdefrontend/dockwidgets/XYEquationCurveDock.h"
0075 #include "kdefrontend/dockwidgets/XYDataReductionCurveDock.h"
0076 #include "kdefrontend/dockwidgets/XYDifferentiationCurveDock.h"
0077 #include "kdefrontend/dockwidgets/XYIntegrationCurveDock.h"
0078 #include "kdefrontend/dockwidgets/XYInterpolationCurveDock.h"
0079 #include "kdefrontend/dockwidgets/XYSmoothCurveDock.h"
0080 #include "kdefrontend/dockwidgets/XYFitCurveDock.h"
0081 #include "kdefrontend/dockwidgets/XYFourierFilterCurveDock.h"
0082 #include "kdefrontend/dockwidgets/XYFourierTransformCurveDock.h"
0083 #include "kdefrontend/dockwidgets/XYConvolutionCurveDock.h"
0084 #include "kdefrontend/dockwidgets/XYCorrelationCurveDock.h"
0085 #include "kdefrontend/dockwidgets/CustomPointDock.h"
0086 #include "kdefrontend/dockwidgets/ReferenceLineDock.h"
0087 #include "kdefrontend/dockwidgets/WorksheetDock.h"
0088 #ifdef HAVE_CANTOR_LIBS
0089 #include "kdefrontend/dockwidgets/CantorWorksheetDock.h"
0090 #endif
0091 #include "kdefrontend/widgets/LabelWidget.h"
0092 #include "kdefrontend/widgets/DatapickerImageWidget.h"
0093 #include "kdefrontend/widgets/DatapickerCurveWidget.h"
0094 
0095 #include <QDockWidget>
0096 #include <QStackedWidget>
0097 #include <QStatusBar>
0098 #include <QToolBar>
0099 #include <KI18n/KLocalizedString>
0100 
0101 /*!
0102   \class GuiObserver
0103   \brief The GUI observer looks for the selection changes in the main window
0104   and shows/hides the correspondings dock widgets, toolbars etc.
0105   This class is intended to simplify (or not to overload) the code in MainWin.
0106 
0107   \ingroup kdefrontend
0108 */
0109 
0110 namespace GuiObserverHelper {
0111 
0112 template<class T>
0113 bool raiseDock(T*& dock, QStackedWidget* parent) {
0114     Q_ASSERT(parent);
0115     DEBUG(Q_FUNC_INFO << ", number of stacked widgets = " << parent->count())
0116 
0117     const bool generated = !dock;
0118     if (generated) {
0119         dock = new T(parent);
0120         parent->addWidget(dock);
0121     }
0122 
0123     // see https://wiki.qt.io/Technical_FAQ#How_can_I_get_a_QStackedWidget_to_automatically_switch_size_depending_on_the_content_of_the_page
0124     if (parent->currentWidget())
0125         parent->currentWidget()->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
0126     parent->setCurrentWidget(dock);
0127     parent->currentWidget()->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
0128 
0129     // scroll the scroll area up to the top
0130     if (parent->parent() && parent->parent()->parent()) {
0131         auto* scrollArea = dynamic_cast<QScrollArea*>(parent->parent()->parent());
0132         if (scrollArea)
0133             scrollArea->ensureVisible(0, 0);
0134     }
0135     return generated;
0136 }
0137 
0138 template<class T>
0139 void raiseDockConnect(T*& dock, QStatusBar* statusBar, QStackedWidget* parent) {
0140     if (raiseDock(dock, parent))
0141         QObject::connect(dock, &T::info, [=](const QString& text){ statusBar->showMessage(text); });
0142 }
0143 
0144 template<class T>
0145 void raiseDockSetupConnect(T*& dock, QStatusBar* statusBar, QStackedWidget* parent) {
0146     if (raiseDock(dock, parent)) {
0147         dock->setupGeneral();
0148         QObject::connect(dock, &T::info, [=](const QString& text){ statusBar->showMessage(text); });
0149     }
0150 }
0151 
0152 template<class T>
0153 QList<T*> castList(QList<AbstractAspect*>& selectedAspects) {
0154     QList<T*> list;
0155     for (auto* aspect : selectedAspects)
0156         list << static_cast<T*>(aspect);
0157     return list;
0158 }
0159 
0160 } // namespace GuiObserverHelper
0161 
0162 using namespace GuiObserverHelper;
0163 
0164 GuiObserver::GuiObserver(MainWin* mainWin) {
0165     connect(mainWin->m_projectExplorer, &ProjectExplorer::selectedAspectsChanged, this, &GuiObserver::selectedAspectsChanged);
0166     connect(mainWin->m_projectExplorer, &ProjectExplorer::hiddenAspectSelected, this, &GuiObserver::hiddenAspectSelected);
0167     m_mainWindow = mainWin;
0168 }
0169 
0170 /*!
0171   called on selection changes in the project explorer.
0172   Determines the type of the currently selected objects (aspects)
0173   and activates the corresponding dockwidgets, toolbars etc.
0174 */
0175 void GuiObserver::selectedAspectsChanged(QList<AbstractAspect*>& selectedAspects) const {
0176     auto clearDock = [&]() {
0177         if (m_mainWindow->stackedWidget->currentWidget())
0178             m_mainWindow->stackedWidget->currentWidget()->hide();
0179 
0180         m_mainWindow->m_propertiesDock->setWindowTitle(i18nc("@title:window", "Properties"));
0181     };
0182 
0183     if (selectedAspects.isEmpty()) {
0184         clearDock();
0185         return;
0186     }
0187 
0188     const AspectType type{ selectedAspects.front()->type() };
0189     DEBUG(Q_FUNC_INFO << ", type: " << std::hex << static_cast<quint64>(type))
0190 
0191     // update cursor dock
0192     if (m_mainWindow->cursorWidget) {
0193         if (type == AspectType::Worksheet) {
0194             Worksheet* worksheet = static_cast<Worksheet*>(selectedAspects.front());
0195             m_mainWindow->cursorWidget->setWorksheet(worksheet);
0196         } else {
0197             AbstractAspect* parent = selectedAspects.front()->parent(AspectType::Worksheet);
0198             if (parent) {
0199                 Worksheet* worksheet = static_cast<Worksheet*>(parent);
0200                 m_mainWindow->cursorWidget->setWorksheet(worksheet);
0201             }
0202         }
0203     }
0204 
0205     // Check, whether objects of different types were selected.
0206     // Don't show any dock widgets in this case.
0207     for (const auto* aspect : selectedAspects) {
0208         if (aspect->type() != type) {
0209             clearDock();
0210             return;
0211         }
0212     }
0213 
0214     switch (type) {
0215     case AspectType::Spreadsheet:
0216         m_mainWindow->m_propertiesDock->setWindowTitle(i18nc("@title:window", "Spreadsheet"));
0217         raiseDockConnect(m_mainWindow->spreadsheetDock, m_mainWindow->statusBar(), m_mainWindow->stackedWidget);
0218         m_mainWindow->spreadsheetDock->setSpreadsheets(castList<Spreadsheet>(selectedAspects));
0219         break;
0220     case AspectType::Column:
0221         m_mainWindow->m_propertiesDock->setWindowTitle(i18nc("@title:window", "Column"));
0222         raiseDockConnect(m_mainWindow->columnDock, m_mainWindow->statusBar(), m_mainWindow->stackedWidget);
0223         m_mainWindow->columnDock->setColumns(castList<Column>(selectedAspects));
0224         break;
0225     case AspectType::Matrix:
0226         m_mainWindow->m_propertiesDock->setWindowTitle(i18nc("@title:window", "Matrix"));
0227         raiseDockConnect(m_mainWindow->matrixDock, m_mainWindow->statusBar(), m_mainWindow->stackedWidget);
0228         m_mainWindow->matrixDock->setMatrices(castList<Matrix>(selectedAspects));
0229         break;
0230     case AspectType::Worksheet: {
0231         m_mainWindow->m_propertiesDock->setWindowTitle(i18nc("@title:window", "Worksheet"));
0232         if (!m_mainWindow->worksheetDock) {
0233             m_mainWindow->worksheetDock = new WorksheetDock(m_mainWindow->stackedWidget);
0234             connect(m_mainWindow->worksheetDock, SIGNAL(info(QString)), m_mainWindow->statusBar(), SLOT(showMessage(QString)));
0235             m_mainWindow->stackedWidget->addWidget(m_mainWindow->worksheetDock);
0236         }
0237         raiseDockConnect(m_mainWindow->worksheetDock, m_mainWindow->statusBar(), m_mainWindow->stackedWidget);
0238         m_mainWindow->worksheetDock->setWorksheets(castList<Worksheet>(selectedAspects));
0239         break;
0240     } case AspectType::CartesianPlot: {
0241         m_mainWindow->m_propertiesDock->setWindowTitle(i18nc("@title:window", "Cartesian Plot"));
0242         raiseDockConnect(m_mainWindow->cartesianPlotDock, m_mainWindow->statusBar(), m_mainWindow->stackedWidget);
0243         m_mainWindow->cartesianPlotDock->setPlots(castList<CartesianPlot>(selectedAspects));
0244         break;
0245     } case AspectType::CartesianPlotLegend:
0246         m_mainWindow->m_propertiesDock->setWindowTitle(i18nc("@title:window", "Legend"));
0247         raiseDockConnect(m_mainWindow->cartesianPlotLegendDock, m_mainWindow->statusBar(), m_mainWindow->stackedWidget);
0248         m_mainWindow->cartesianPlotLegendDock->setLegends(castList<CartesianPlotLegend>(selectedAspects));
0249         break;
0250     case AspectType::Axis:
0251         m_mainWindow->m_propertiesDock->setWindowTitle(i18nc("@title:window", "Axis"));
0252         raiseDockConnect(m_mainWindow->axisDock, m_mainWindow->statusBar(), m_mainWindow->stackedWidget);
0253         m_mainWindow->axisDock->setAxes(castList<Axis>(selectedAspects));
0254         break;
0255     case AspectType::XYCurve:
0256         m_mainWindow->m_propertiesDock->setWindowTitle(i18nc("@title:window", "xy-Curve"));
0257         raiseDockSetupConnect(m_mainWindow->xyCurveDock, m_mainWindow->statusBar(), m_mainWindow->stackedWidget);
0258         m_mainWindow->xyCurveDock->setCurves(castList<XYCurve>(selectedAspects));
0259         break;
0260     case AspectType::XYEquationCurve:
0261         m_mainWindow->m_propertiesDock->setWindowTitle(i18nc("@title:window", "xy-Equation"));
0262         raiseDockSetupConnect(m_mainWindow->xyEquationCurveDock, m_mainWindow->statusBar(), m_mainWindow->stackedWidget);
0263         m_mainWindow->xyEquationCurveDock->setCurves(castList<XYCurve>(selectedAspects));
0264         break;
0265     case AspectType::XYDataReductionCurve:
0266         m_mainWindow->m_propertiesDock->setWindowTitle(i18nc("@title:window", "Data Reduction"));
0267 
0268         if (!m_mainWindow->xyDataReductionCurveDock) {
0269             m_mainWindow->xyDataReductionCurveDock = new XYDataReductionCurveDock(m_mainWindow->stackedWidget, m_mainWindow->statusBar());
0270             m_mainWindow->xyDataReductionCurveDock->setupGeneral();
0271             connect(m_mainWindow->xyDataReductionCurveDock, &XYDataReductionCurveDock::info,
0272                     [&](const QString& text){ m_mainWindow->statusBar()->showMessage(text); });
0273             m_mainWindow->stackedWidget->addWidget(m_mainWindow->xyDataReductionCurveDock);
0274         }
0275 
0276         m_mainWindow->xyDataReductionCurveDock->setCurves(castList<XYCurve>(selectedAspects));
0277 
0278         m_mainWindow->stackedWidget->setCurrentWidget(m_mainWindow->xyDataReductionCurveDock);
0279         break;
0280     case AspectType::XYDifferentiationCurve:
0281         m_mainWindow->m_propertiesDock->setWindowTitle(i18nc("@title:window", "Differentiation"));
0282         raiseDockSetupConnect(m_mainWindow->xyDifferentiationCurveDock, m_mainWindow->statusBar(), m_mainWindow->stackedWidget);
0283         m_mainWindow->xyDifferentiationCurveDock->setCurves(castList<XYCurve>(selectedAspects));
0284         break;
0285     case AspectType::XYIntegrationCurve:
0286         m_mainWindow->m_propertiesDock->setWindowTitle(i18nc("@title:window", "Integration"));
0287         raiseDockSetupConnect(m_mainWindow->xyIntegrationCurveDock, m_mainWindow->statusBar(), m_mainWindow->stackedWidget);
0288         m_mainWindow->xyIntegrationCurveDock->setCurves(castList<XYCurve>(selectedAspects));
0289         break;
0290     case AspectType::XYInterpolationCurve:
0291         m_mainWindow->m_propertiesDock->setWindowTitle(i18nc("@title:window", "Interpolation"));
0292         raiseDockSetupConnect(m_mainWindow->xyInterpolationCurveDock, m_mainWindow->statusBar(), m_mainWindow->stackedWidget);
0293         m_mainWindow->xyInterpolationCurveDock->setCurves(castList<XYCurve>(selectedAspects));
0294         break;
0295     case AspectType::XYSmoothCurve:
0296         m_mainWindow->m_propertiesDock->setWindowTitle(i18nc("@title:window", "Smoothing"));
0297         raiseDockSetupConnect(m_mainWindow->xySmoothCurveDock, m_mainWindow->statusBar(), m_mainWindow->stackedWidget);
0298         m_mainWindow->xySmoothCurveDock->setCurves(castList<XYCurve>(selectedAspects));
0299         break;
0300     case AspectType::XYFitCurve:
0301         m_mainWindow->m_propertiesDock->setWindowTitle(i18nc("@title:window", "Fit"));
0302         raiseDockSetupConnect(m_mainWindow->xyFitCurveDock, m_mainWindow->statusBar(), m_mainWindow->stackedWidget);
0303         m_mainWindow->xyFitCurveDock->setCurves(castList<XYCurve>(selectedAspects));
0304         break;
0305     case AspectType::XYFourierTransformCurve:
0306         m_mainWindow->m_propertiesDock->setWindowTitle(i18nc("@title:window", "Fourier Transform"));
0307         raiseDockSetupConnect(m_mainWindow->xyFourierTransformCurveDock, m_mainWindow->statusBar(), m_mainWindow->stackedWidget);
0308         m_mainWindow->xyFourierTransformCurveDock->setCurves(castList<XYCurve>(selectedAspects));
0309         break;
0310     case AspectType::XYFourierFilterCurve:
0311         m_mainWindow->m_propertiesDock->setWindowTitle(i18nc("@title:window", "Fourier Filter"));
0312         raiseDockSetupConnect(m_mainWindow->xyFourierFilterCurveDock, m_mainWindow->statusBar(), m_mainWindow->stackedWidget);
0313         m_mainWindow->xyFourierFilterCurveDock->setCurves(castList<XYCurve>(selectedAspects));
0314         break;
0315     case AspectType::XYConvolution:
0316         m_mainWindow->m_propertiesDock->setWindowTitle(i18nc("@title:window", "Convolution/Deconvolution"));
0317         raiseDockSetupConnect(m_mainWindow->xyConvolutionCurveDock, m_mainWindow->statusBar(), m_mainWindow->stackedWidget);
0318         m_mainWindow->xyConvolutionCurveDock->setCurves(castList<XYCurve>(selectedAspects));
0319         break;
0320     case AspectType::XYCorrelationCurve:
0321         m_mainWindow->m_propertiesDock->setWindowTitle(i18nc("@title:window", "Auto-/Cross-Correlation"));
0322         raiseDockSetupConnect(m_mainWindow->xyCorrelationCurveDock, m_mainWindow->statusBar(), m_mainWindow->stackedWidget);
0323         m_mainWindow->xyCorrelationCurveDock->setCurves(castList<XYCurve>(selectedAspects));
0324         break;
0325     case AspectType::Histogram:
0326         m_mainWindow->m_propertiesDock->setWindowTitle(i18nc("@title:window", "Histogram Properties"));
0327         raiseDockConnect(m_mainWindow->histogramDock, m_mainWindow->statusBar(), m_mainWindow->stackedWidget);
0328         m_mainWindow->histogramDock->setCurves(castList<Histogram>(selectedAspects));
0329         break;
0330     case AspectType::TextLabel:
0331         m_mainWindow->m_propertiesDock->setWindowTitle(i18nc("@title:window", "Text Label"));
0332         raiseDock(m_mainWindow->textLabelDock, m_mainWindow->stackedWidget);
0333         m_mainWindow->textLabelDock->setLabels(castList<TextLabel>(selectedAspects));
0334         break;
0335     case AspectType::Image:
0336         m_mainWindow->m_propertiesDock->setWindowTitle(i18nc("@title:window", "Image"));
0337         raiseDock(m_mainWindow->imageDock, m_mainWindow->stackedWidget);
0338         m_mainWindow->imageDock->setImages(castList<Image>(selectedAspects));
0339         break;
0340     case AspectType::CustomPoint:
0341         m_mainWindow->m_propertiesDock->setWindowTitle(i18nc("@title:window", "Custom Point"));
0342         raiseDock(m_mainWindow->customPointDock, m_mainWindow->stackedWidget);
0343         m_mainWindow->customPointDock->setPoints(castList<CustomPoint>(selectedAspects));
0344         break;
0345     case AspectType::ReferenceLine:
0346         m_mainWindow->m_propertiesDock->setWindowTitle(i18nc("@title:window", "Reference Line"));
0347         raiseDock(m_mainWindow->referenceLineDock, m_mainWindow->stackedWidget);
0348         m_mainWindow->referenceLineDock->setReferenceLines(castList<ReferenceLine>(selectedAspects));
0349         break;
0350     case AspectType::DatapickerCurve:
0351         m_mainWindow->m_propertiesDock->setWindowTitle(i18nc("@title:window", "Datapicker Curve"));
0352         raiseDock(m_mainWindow->datapickerCurveDock, m_mainWindow->stackedWidget);
0353         m_mainWindow->datapickerCurveDock->setCurves(castList<DatapickerCurve>(selectedAspects));
0354         break;
0355     case AspectType::Datapicker:
0356         m_mainWindow->m_propertiesDock->setWindowTitle(i18nc("@title:window", "Datapicker"));
0357         raiseDock(m_mainWindow->datapickerImageDock, m_mainWindow->stackedWidget);
0358 
0359         {
0360             QList<DatapickerImage*> list;
0361             for (auto* aspect : selectedAspects)
0362                 list << static_cast<Datapicker*>(aspect)->image();
0363             m_mainWindow->datapickerImageDock->setImages(list);
0364         }
0365         break;
0366     case AspectType::Project:
0367         m_mainWindow->m_propertiesDock->setWindowTitle(i18nc("@title:window", "Project"));
0368         raiseDock(m_mainWindow->projectDock, m_mainWindow->stackedWidget);
0369         m_mainWindow->projectDock->setProject(m_mainWindow->m_project);
0370         break;
0371     case AspectType::CantorWorksheet:
0372 #ifdef HAVE_CANTOR_LIBS
0373         raiseDockConnect(m_mainWindow->cantorWorksheetDock, m_mainWindow->statusBar(), m_mainWindow->stackedWidget);
0374 
0375         {
0376             QList<CantorWorksheet*> list = castList<CantorWorksheet>(selectedAspects);
0377             if (list.size() == 1)
0378                 m_mainWindow->m_propertiesDock->setWindowTitle(i18nc("@title:window %1 is a Cantor backend", "%1 Properties", list.first()->backendName()));
0379             else
0380                 m_mainWindow->m_propertiesDock->setWindowTitle(i18nc("@title:window", "CAS Properties"));
0381             m_mainWindow->cantorWorksheetDock->setCantorWorksheets(list);
0382         }
0383 #endif
0384         break;
0385     case AspectType::Note:
0386         m_mainWindow->m_propertiesDock->setWindowTitle(i18nc("@title:window", "Notes"));
0387         raiseDock(m_mainWindow->notesDock, m_mainWindow->stackedWidget);
0388         m_mainWindow->notesDock->setNotesList(castList<Note>(selectedAspects));
0389         break;
0390     case AspectType::MQTTClient:
0391 #ifdef HAVE_MQTT
0392         m_mainWindow->m_propertiesDock->setWindowTitle(i18nc("@title:window", "MQTT Data Source"));
0393         raiseDock(m_mainWindow->m_liveDataDock, m_mainWindow->stackedWidget);
0394         m_mainWindow->m_liveDataDock->setMQTTClient(static_cast<MQTTClient*>(selectedAspects.first()));
0395 #endif
0396         break;
0397     case AspectType::MQTTSubscription:
0398 #ifdef HAVE_MQTT
0399         m_mainWindow->m_propertiesDock->setWindowTitle(i18nc("@title:window", "MQTT Data Source"));
0400         raiseDock(m_mainWindow->m_liveDataDock, m_mainWindow->stackedWidget);
0401         m_mainWindow->m_liveDataDock->setMQTTClient(static_cast<MQTTSubscription*>(selectedAspects.first())->mqttClient());
0402 #endif
0403         break;
0404     case AspectType::MQTTTopic:
0405 #ifdef HAVE_MQTT
0406         m_mainWindow->m_propertiesDock->setWindowTitle(i18nc("@title:window", "MQTT Data Source"));
0407         raiseDock(m_mainWindow->m_liveDataDock, m_mainWindow->stackedWidget);
0408         m_mainWindow->m_liveDataDock->setMQTTClient(static_cast<MQTTTopic*>(selectedAspects.first())->mqttClient());
0409 #endif
0410         break;
0411     case AspectType::LiveDataSource:
0412         m_mainWindow->m_propertiesDock->setWindowTitle(i18nc("@title:window", "Live Data Source"));
0413         raiseDock(m_mainWindow->m_liveDataDock, m_mainWindow->stackedWidget);
0414         m_mainWindow->m_liveDataDock->setLiveDataSource(static_cast<LiveDataSource*>(selectedAspects.first()));
0415         break;
0416     case AspectType::AbstractAspect:
0417     case AspectType::AbstractColumn:
0418     case AspectType::AbstractDataSource:
0419     case AspectType::AbstractFilter:
0420     case AspectType::AbstractPart:
0421     case AspectType::AbstractPlot:
0422     case AspectType::ColumnStringIO:
0423     case AspectType::DatapickerImage:
0424     case AspectType::DatapickerPoint:
0425     case AspectType::Folder:
0426     case AspectType::PlotArea:
0427     case AspectType::SimpleFilterColumn:
0428     case AspectType::Workbook:
0429     case AspectType::WorksheetElement:
0430     case AspectType::WorksheetElementContainer:
0431     case AspectType::WorksheetElementGroup:
0432     case AspectType::XYAnalysisCurve:
0433         clearDock();
0434         return;
0435     }
0436 
0437     m_mainWindow->stackedWidget->currentWidget()->show();
0438 }
0439 
0440 /*!
0441     handles the selection of a hidden aspect \c aspect in the view (relevant for WorksheetView only at the moment).
0442     Currently, a hidden aspect can only be a plot title lable or an axis label.
0443     -> Activate the corresponding DockWidget and make the title tab current.
0444  */
0445 void GuiObserver::hiddenAspectSelected(const AbstractAspect* aspect) const {
0446     const AbstractAspect* parent = aspect->parentAspect();
0447     if (!parent)
0448         return;
0449 
0450     switch (static_cast<quint64>(parent->type())) {  // cast the enum to turn off warnings about unhandled cases
0451     case static_cast<quint64>(AspectType::Axis):
0452         if (!m_mainWindow->axisDock) {
0453             m_mainWindow->axisDock = new AxisDock(m_mainWindow->stackedWidget);
0454             m_mainWindow->stackedWidget->addWidget(m_mainWindow->axisDock);
0455         }
0456         m_mainWindow->axisDock->activateTitleTab();
0457         break;
0458     case static_cast<quint64>(AspectType::CartesianPlot):
0459         if (!m_mainWindow->cartesianPlotDock) {
0460             m_mainWindow->cartesianPlotDock = new CartesianPlotDock(m_mainWindow->stackedWidget);
0461             m_mainWindow->stackedWidget->addWidget(m_mainWindow->cartesianPlotDock);
0462         }
0463         m_mainWindow->cartesianPlotDock->activateTitleTab();
0464         break;
0465     case static_cast<quint64>(AspectType::CartesianPlotLegend):
0466         if (!m_mainWindow->cartesianPlotLegendDock) {
0467             m_mainWindow->cartesianPlotLegendDock = new CartesianPlotLegendDock(m_mainWindow->stackedWidget);
0468             m_mainWindow->stackedWidget->addWidget(m_mainWindow->cartesianPlotLegendDock);
0469         }
0470         m_mainWindow->cartesianPlotLegendDock->activateTitleTab();
0471         break;
0472     default:
0473         break;
0474     }
0475 }
0476