File indexing completed on 2024-05-12 15:27:36

0001 /***************************************************************************
0002     File                 : DatapickerView.cpp
0003     Project              : LabPlot
0004     Description          : View class for Datapicker
0005     --------------------------------------------------------------------
0006     Copyright            : (C) 2015 by Ankit Wagadre (wagadre.ankit@gmail.com)
0007     Copyright            : (C) 2015-2020 by Alexander Semke (alexander.semke@web.de)
0008 
0009  ***************************************************************************/
0010 /***************************************************************************
0011  *                                                                         *
0012  *  This program is free software; you can redistribute it and/or modify   *
0013  *  it under the terms of the GNU General Public License as published by   *
0014  *  the Free Software Foundation; either version 2 of the License, or      *
0015  *  (at your option) any later version.                                    *
0016  *                                                                         *
0017  *  This program is distributed in the hope that it will be useful,        *
0018  *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
0019  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
0020  *  GNU General Public License for more details.                           *
0021  *                                                                         *
0022  *   You should have received a copy of the GNU General Public License     *
0023  *   along with this program; if not, write to the Free Software           *
0024  *   Foundation, Inc., 51 Franklin Street, Fifth Floor,                    *
0025  *   Boston, MA  02110-1301  USA                                           *
0026  *                                                                         *
0027  ***************************************************************************/
0028 
0029 #include "DatapickerView.h"
0030 #include "backend/datapicker/Datapicker.h"
0031 #include "backend/lib/macros.h"
0032 #include "backend/spreadsheet/Spreadsheet.h"
0033 #include "backend/datapicker/DatapickerImage.h"
0034 #include "commonfrontend/workbook/WorkbookView.h"
0035 #include "backend/datapicker/DatapickerCurve.h"
0036 #include "commonfrontend/datapicker/DatapickerImageView.h"
0037 
0038 #include <QHBoxLayout>
0039 #include <QMenu>
0040 #include <QTabBar>
0041 #include <QTabWidget>
0042 
0043 #include <KLocalizedString>
0044 
0045 /*!
0046     \class DatapickerView
0047     \brief View class for Datapicker
0048 
0049     \ingroup commonfrontend
0050  */
0051 DatapickerView::DatapickerView(Datapicker* datapicker) : QWidget(),
0052     m_tabWidget(new QTabWidget(this)),
0053     m_datapicker(datapicker) {
0054 
0055     m_tabWidget->setTabPosition(QTabWidget::South);
0056     m_tabWidget->setTabShape(QTabWidget::Rounded);
0057 //     m_tabWidget->setMovable(true);
0058     m_tabWidget->setContextMenuPolicy(Qt::CustomContextMenu);
0059     m_tabWidget->setMinimumSize(600, 600);
0060 
0061     auto* layout = new QHBoxLayout(this);
0062     layout->setContentsMargins(0, 0, 0, 0);
0063     layout->addWidget(m_tabWidget);
0064 
0065     //add tab for each children view
0066     m_initializing = true;
0067     for (const auto* aspect : m_datapicker->children<AbstractAspect>(AbstractAspect::ChildIndexFlag::IncludeHidden)) {
0068         handleAspectAdded(aspect);
0069         for (const auto* child : aspect->children<AbstractAspect>()) {
0070             handleAspectAdded(child);
0071         }
0072     }
0073     m_initializing = false;
0074 
0075     //SIGNALs/SLOTs
0076     connect(m_datapicker, &Datapicker::aspectDescriptionChanged, this, &DatapickerView::handleDescriptionChanged);
0077     connect(m_datapicker, &Datapicker::aspectAdded, this, &DatapickerView::handleAspectAdded);
0078     connect(m_datapicker, &Datapicker::aspectAboutToBeRemoved, this, &DatapickerView::handleAspectAboutToBeRemoved);
0079     connect(m_datapicker, &Datapicker::datapickerItemSelected, this, &DatapickerView::itemSelected);
0080 
0081     connect(m_tabWidget, &QTabWidget::currentChanged, this, &DatapickerView::tabChanged);
0082     connect(m_tabWidget, &QTabWidget::customContextMenuRequested, this, &DatapickerView::showTabContextMenu);
0083     connect(m_tabWidget->tabBar(), &QTabBar::tabMoved, this, &DatapickerView::tabMoved);
0084 }
0085 
0086 DatapickerView::~DatapickerView() {
0087     //delete all children views here, its own view will be deleted in ~AbstractPart()
0088     for (const auto* aspect : m_datapicker->children<AbstractAspect>(AbstractAspect::ChildIndexFlag::IncludeHidden)) {
0089         for (const auto* child : aspect->children<AbstractAspect>()) {
0090             const auto* part = dynamic_cast<const AbstractPart*>(child);
0091             if (part)
0092                 part->deleteView();
0093         }
0094         const auto* part = dynamic_cast<const AbstractPart*>(aspect);
0095         if (part)
0096             part->deleteView();
0097     }
0098 }
0099 
0100 void DatapickerView::fillToolBar(QToolBar* toolBar) {
0101     auto* view = static_cast<DatapickerImageView*>(m_datapicker->image()->view());
0102     view->fillToolBar(toolBar);
0103 }
0104 
0105 void DatapickerView::createContextMenu(QMenu* menu) const {
0106     Q_ASSERT(menu);
0107     m_datapicker->image()->createContextMenu(menu);
0108 }
0109 
0110 int DatapickerView::currentIndex() const {
0111     return m_tabWidget->currentIndex();
0112 }
0113 
0114 //##############################################################################
0115 //#########################  Private slots  ####################################
0116 //##############################################################################
0117 /*!
0118   called when the current tab was changed. Propagates the selection of \c Spreadsheet
0119   or of a \c DatapickerImage object to \c Datapicker.
0120 */
0121 void DatapickerView::tabChanged(int index) {
0122     if (m_initializing)
0123         return;
0124 
0125     if (index == -1)
0126         return;
0127 
0128     m_datapicker->setChildSelectedInView(lastSelectedIndex, false);
0129     m_datapicker->setChildSelectedInView(index, true);
0130     lastSelectedIndex = index;
0131 }
0132 
0133 void DatapickerView::tabMoved(int from, int to) {
0134     Q_UNUSED(from);
0135     Q_UNUSED(to);
0136     //TODO:
0137 //  AbstractAspect* aspect = m_datapicker->child<AbstractAspect>(to);
0138 //  if (aspect) {
0139 //      m_tabMoving = true;
0140 //      AbstractAspect* sibling = m_datapicker->child<AbstractAspect>(from);
0141 //      qDebug()<<"insert: " << to << "  " <<  aspect->name() << ",  " << from << "  " << sibling->name();
0142 //      aspect->remove();
0143 //      m_datapicker->insertChildBefore(aspect, sibling);
0144 //      qDebug()<<"inserted";
0145 //      m_tabMoving = false;
0146 //  }
0147 }
0148 
0149 void DatapickerView::itemSelected(int index) {
0150     m_initializing = true;
0151     m_tabWidget->setCurrentIndex(index);
0152     m_initializing = false;
0153 }
0154 
0155 void DatapickerView::showTabContextMenu(QPoint point) {
0156     QMenu* menu = nullptr;
0157     auto* aspect = m_datapicker->child<AbstractAspect>(m_tabWidget->currentIndex(), AbstractAspect::ChildIndexFlag::IncludeHidden);
0158     auto* spreadsheet = dynamic_cast<Spreadsheet*>(aspect);
0159     if (spreadsheet) {
0160         menu = spreadsheet->createContextMenu();
0161     } else {
0162         auto* image = dynamic_cast<DatapickerImage*>(aspect);
0163         if (image)
0164             menu = image->createContextMenu();
0165     }
0166 
0167     if (menu)
0168         menu->exec(m_tabWidget->mapToGlobal(point));
0169 }
0170 
0171 void DatapickerView::handleDescriptionChanged(const AbstractAspect* aspect) {
0172     if (aspect == m_datapicker)
0173         return;
0174 
0175     //determine the child that was changed and adjust the name of the corresponding tab widget
0176     int index = -1;
0177     QString name;
0178     if (aspect->parentAspect() == m_datapicker) {
0179         //datapicker curve was renamed
0180         index = m_datapicker->indexOfChild<AbstractAspect>(aspect, AbstractAspect::ChildIndexFlag::IncludeHidden);
0181         if (index != -1)
0182             name = aspect->name() + ": " + aspect->children<Spreadsheet>().constFirst()->name();
0183     } else {
0184         //data spreadsheet was renamed or one of its columns, which is not relevant here
0185         index = m_datapicker->indexOfChild<AbstractAspect>(aspect->parentAspect(), AbstractAspect::ChildIndexFlag::IncludeHidden);
0186         if (index != -1)
0187             name = aspect->parentAspect()->name() + ": " + aspect->name();
0188     }
0189 
0190     if (index != -1)
0191         m_tabWidget->setTabText(index, name);
0192 }
0193 
0194 void DatapickerView::handleAspectAdded(const AbstractAspect* aspect) {
0195     int index;
0196     QString name;
0197     const AbstractPart* part = dynamic_cast<const DatapickerImage*>(aspect);
0198     if (part) {
0199         index = 0;
0200         name = aspect->name();
0201     } else if (dynamic_cast<const DatapickerCurve*>(aspect)) {
0202         index = m_datapicker->indexOfChild<AbstractAspect>(aspect, AbstractAspect::ChildIndexFlag::IncludeHidden);
0203         const Spreadsheet* spreadsheet = static_cast<const Spreadsheet*>(aspect->child<AbstractAspect>(0));
0204         part = spreadsheet;
0205         name = aspect->name() + ": " + spreadsheet->name();
0206     } else
0207         return;
0208 
0209     m_tabWidget->insertTab(index, part->view(), name);
0210     m_tabWidget->setTabIcon(m_tabWidget->count(), aspect->icon());
0211 }
0212 
0213 void DatapickerView::handleAspectAboutToBeRemoved(const AbstractAspect* aspect) {
0214     const auto* curve = dynamic_cast<const DatapickerCurve*>(aspect);
0215     if (curve) {
0216         int index = m_datapicker->indexOfChild<AbstractAspect>(aspect, AbstractAspect::ChildIndexFlag::IncludeHidden);
0217         m_tabWidget->removeTab(index);
0218     }
0219 }