File indexing completed on 2024-05-12 03:48:25

0001 /*
0002     File                 : DatapickerView.cpp
0003     Project              : LabPlot
0004     Description          : View class for Datapicker
0005     --------------------------------------------------------------------
0006     SPDX-FileCopyrightText: 2015 Ankit Wagadre <wagadre.ankit@gmail.com>
0007     SPDX-FileCopyrightText: 2015-2021 Alexander Semke <alexander.semke@web.de>
0008 
0009     SPDX-License-Identifier: GPL-2.0-or-later
0010 */
0011 
0012 #include "DatapickerView.h"
0013 #include "backend/datapicker/Datapicker.h"
0014 #include "backend/datapicker/DatapickerCurve.h"
0015 #include "backend/datapicker/DatapickerImage.h"
0016 #include "backend/lib/macros.h"
0017 #include "backend/spreadsheet/Spreadsheet.h"
0018 #include "commonfrontend/datapicker/DatapickerImageView.h"
0019 #include "commonfrontend/workbook/WorkbookView.h"
0020 
0021 #include <QHBoxLayout>
0022 #include <QMenu>
0023 #include <QTabBar>
0024 #include <QTabWidget>
0025 
0026 #include <KLocalizedString>
0027 
0028 /*!
0029     \class DatapickerView
0030     \brief View class for Datapicker
0031 
0032     \ingroup commonfrontend
0033  */
0034 DatapickerView::DatapickerView(Datapicker* datapicker)
0035     : QWidget()
0036     , m_tabWidget(new QTabWidget(this))
0037     , m_datapicker(datapicker) {
0038     m_tabWidget->setTabPosition(QTabWidget::South);
0039     m_tabWidget->setTabShape(QTabWidget::Rounded);
0040     // m_tabWidget->setMovable(true);
0041     m_tabWidget->setContextMenuPolicy(Qt::CustomContextMenu);
0042 
0043     auto* layout = new QHBoxLayout(this);
0044     layout->setContentsMargins(0, 0, 0, 0);
0045     layout->addWidget(m_tabWidget);
0046 
0047     // add tab for each children view
0048     m_initializing = true;
0049     for (const auto* aspect : m_datapicker->children<AbstractAspect>(AbstractAspect::ChildIndexFlag::IncludeHidden)) {
0050         handleAspectAdded(aspect);
0051         for (const auto* child : aspect->children<AbstractAspect>())
0052             handleAspectAdded(child);
0053     }
0054     m_initializing = false;
0055 
0056     if (!m_datapicker->isLoading()) {
0057         const auto& size = m_datapicker->image()->view()->size();
0058         resize(size.width() * 1.1, size.height() * 1.1);
0059     }
0060 
0061     // SIGNALs/SLOTs
0062     connect(m_datapicker, &Datapicker::aspectDescriptionChanged, this, &DatapickerView::handleDescriptionChanged);
0063     connect(m_datapicker, &Datapicker::childAspectAdded, this, &DatapickerView::handleAspectAdded);
0064     connect(m_datapicker, &Datapicker::childAspectAboutToBeRemoved, this, &DatapickerView::handleAspectAboutToBeRemoved);
0065     connect(m_datapicker, &Datapicker::datapickerItemSelected, this, &DatapickerView::itemSelected);
0066 
0067     connect(m_tabWidget, &QTabWidget::currentChanged, this, &DatapickerView::tabChanged);
0068     connect(m_tabWidget, &QTabWidget::customContextMenuRequested, this, &DatapickerView::showTabContextMenu);
0069     connect(m_tabWidget->tabBar(), &QTabBar::tabMoved, this, &DatapickerView::tabMoved);
0070 }
0071 
0072 DatapickerView::~DatapickerView() {
0073     // delete all children views here, its own view will be deleted in ~AbstractPart()
0074     for (const auto* aspect : m_datapicker->children<AbstractAspect>(AbstractAspect::ChildIndexFlag::IncludeHidden)) {
0075         for (const auto* child : aspect->children<AbstractAspect>()) {
0076             const auto* part = dynamic_cast<const AbstractPart*>(child);
0077             if (part)
0078                 part->deleteView();
0079         }
0080         const auto* part = dynamic_cast<const AbstractPart*>(aspect);
0081         if (part)
0082             part->deleteView();
0083     }
0084 }
0085 
0086 void DatapickerView::fillToolBar(QToolBar* toolBar) {
0087     auto* view = static_cast<DatapickerImageView*>(m_datapicker->image()->view());
0088     view->fillToolBar(toolBar);
0089 }
0090 
0091 void DatapickerView::createContextMenu(QMenu* menu) const {
0092     Q_ASSERT(menu);
0093     m_datapicker->image()->createContextMenu(menu);
0094 }
0095 
0096 int DatapickerView::currentIndex() const {
0097     return m_tabWidget->currentIndex();
0098 }
0099 
0100 // ##############################################################################
0101 // #########################  Private slots  ####################################
0102 // ##############################################################################
0103 /*!
0104   called when the current tab was changed. Propagates the selection of \c Spreadsheet
0105   or of a \c DatapickerImage object to \c Datapicker.
0106 */
0107 void DatapickerView::tabChanged(int index) {
0108     if (m_initializing || index == -1)
0109         return;
0110 
0111     m_datapicker->setChildSelectedInView(lastSelectedIndex, false);
0112     m_datapicker->setChildSelectedInView(index, true);
0113     lastSelectedIndex = index;
0114 }
0115 
0116 void DatapickerView::tabMoved(int /*from*/, int /*to*/) {
0117     // TODO:
0118     //  AbstractAspect* aspect = m_datapicker->child<AbstractAspect>(to);
0119     //  if (aspect) {
0120     //      m_tabMoving = true;
0121     //      AbstractAspect* sibling = m_datapicker->child<AbstractAspect>(from);
0122     //      qDebug()<<"insert: " << to << "  " <<  aspect->name() << ",  " << from << "  " << sibling->name();
0123     //      aspect->remove();
0124     //      m_datapicker->insertChildBefore(aspect, sibling);
0125     //      qDebug()<<"inserted";
0126     //      m_tabMoving = false;
0127     //  }
0128 }
0129 
0130 void DatapickerView::itemSelected(int index) {
0131     m_initializing = true;
0132     m_tabWidget->setCurrentIndex(index);
0133     m_initializing = false;
0134 }
0135 
0136 void DatapickerView::showTabContextMenu(QPoint point) {
0137     QMenu* menu = nullptr;
0138     auto* aspect = m_datapicker->child<AbstractAspect>(m_tabWidget->currentIndex(), AbstractAspect::ChildIndexFlag::IncludeHidden);
0139     auto* spreadsheet = dynamic_cast<Spreadsheet*>(aspect);
0140     if (spreadsheet) {
0141         menu = spreadsheet->createContextMenu();
0142     } else {
0143         auto* image = dynamic_cast<DatapickerImage*>(aspect);
0144         if (image)
0145             menu = image->createContextMenu();
0146     }
0147 
0148     if (menu)
0149         menu->exec(m_tabWidget->mapToGlobal(point));
0150 }
0151 
0152 /*!
0153  * handle the renames of child aspects to adjust the names of the tabs accordingly.
0154  */
0155 void DatapickerView::handleDescriptionChanged(const AbstractAspect* aspect) {
0156     // nothing to do if the parent itself was renamed, we only need to handle curves and data spreadsheets.
0157     if (aspect == m_datapicker || aspect == m_datapicker->image())
0158         return;
0159 
0160     // determine the child that was changed and adjust the name of the corresponding tab widget
0161     int index = -1;
0162     QString name;
0163     if (aspect->parentAspect() == m_datapicker) {
0164         // datapicker curve was renamed
0165         index = m_datapicker->indexOfChild<AbstractAspect>(aspect, AbstractAspect::ChildIndexFlag::IncludeHidden);
0166         if (index != -1)
0167             name = aspect->name() + QStringLiteral(": ") + aspect->children<Spreadsheet>().constFirst()->name();
0168     } else {
0169         // data spreadsheet was renamed or one of its columns, which is not relevant here
0170         index = m_datapicker->indexOfChild<AbstractAspect>(aspect->parentAspect(), AbstractAspect::ChildIndexFlag::IncludeHidden);
0171         if (index != -1)
0172             name = aspect->parentAspect()->name() + QStringLiteral(": ") + aspect->name();
0173     }
0174 
0175     if (index != -1)
0176         m_tabWidget->setTabText(index, name);
0177 }
0178 
0179 void DatapickerView::handleAspectAdded(const AbstractAspect* aspect) {
0180     int index = 0;
0181     QString name;
0182     const AbstractPart* part = dynamic_cast<const DatapickerImage*>(aspect);
0183     if (part) {
0184         name = aspect->name();
0185     } else if (dynamic_cast<const DatapickerCurve*>(aspect)) {
0186         index = m_datapicker->indexOfChild<AbstractAspect>(aspect, AbstractAspect::ChildIndexFlag::IncludeHidden);
0187         const auto* spreadsheet = static_cast<const Spreadsheet*>(aspect->child<AbstractAspect>(0));
0188         part = spreadsheet;
0189         name = aspect->name() + QStringLiteral(": ") + spreadsheet->name();
0190     } else
0191         return;
0192 
0193     m_tabWidget->insertTab(index, part->view(), name);
0194     m_tabWidget->setTabIcon(m_tabWidget->count(), aspect->icon());
0195 }
0196 
0197 void DatapickerView::handleAspectAboutToBeRemoved(const AbstractAspect* aspect) {
0198     const auto* curve = dynamic_cast<const DatapickerCurve*>(aspect);
0199     if (curve) {
0200         int index = m_datapicker->indexOfChild<AbstractAspect>(aspect, AbstractAspect::ChildIndexFlag::IncludeHidden);
0201         m_tabWidget->removeTab(index);
0202     }
0203 }