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

0001 /***************************************************************************
0002     File                 : WorkbookView.cpp
0003     Project              : LabPlot
0004     Description          : View class for Workbook
0005     --------------------------------------------------------------------
0006     Copyright            : (C) 2015-2020 by Alexander Semke (alexander.semke@web.de)
0007 
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 "WorkbookView.h"
0030 #include "backend/core/AbstractAspect.h"
0031 #include "backend/core/AbstractPart.h"
0032 #include "backend/core/Workbook.h"
0033 #include "backend/lib/macros.h"
0034 #include "backend/spreadsheet/Spreadsheet.h"
0035 #include "backend/matrix/Matrix.h"
0036 
0037 #include <QHBoxLayout>
0038 #include <QMenu>
0039 #include <QTabBar>
0040 #include <QTabWidget>
0041 
0042 #include <KLocalizedString>
0043 
0044 /*!
0045     \class WorkbookView
0046     \brief View class for Workbook
0047 
0048     \ingroup commonfrontend
0049  */
0050 WorkbookView::WorkbookView(Workbook* workbook) : QWidget(),
0051     m_tabWidget(new QTabWidget(this)),
0052     m_workbook(workbook) {
0053 
0054     m_tabWidget->setTabPosition(QTabWidget::South);
0055     m_tabWidget->setTabShape(QTabWidget::Rounded);
0056 //  m_tabWidget->setMovable(true);
0057     m_tabWidget->setContextMenuPolicy(Qt::CustomContextMenu);
0058     m_tabWidget->setMinimumSize(200, 200);
0059 
0060     auto* layout = new QHBoxLayout(this);
0061     layout->setContentsMargins(0,0,0,0);
0062     layout->addWidget(m_tabWidget);
0063 
0064     //add tab for each children view
0065     m_initializing = true;
0066     for (const auto* aspect : m_workbook->children<AbstractAspect>())
0067         handleAspectAdded(aspect);
0068     m_initializing = false;
0069 
0070     //Actions
0071     action_add_spreadsheet = new QAction(QIcon::fromTheme("labplot-spreadsheet"), i18n("Add new Spreadsheet"), this);
0072     action_add_matrix = new QAction(QIcon::fromTheme("labplot-matrix"), i18n("Add new Matrix"), this);
0073     connect(action_add_spreadsheet, &QAction::triggered, this, &WorkbookView::addSpreadsheet);
0074     connect(action_add_matrix, &QAction::triggered, this, &WorkbookView::addMatrix);
0075 
0076     //SIGNALs/SLOTs
0077     connect(m_workbook, &Workbook::aspectDescriptionChanged, this, &WorkbookView::handleDescriptionChanged);
0078     connect(m_workbook, &Workbook::aspectAdded, this, &WorkbookView::handleAspectAdded);
0079     connect(m_workbook, &Workbook::aspectAboutToBeRemoved, this, &WorkbookView::handleAspectAboutToBeRemoved);
0080     connect(m_workbook, &Workbook::requestProjectContextMenu, this, &WorkbookView::createContextMenu);
0081     connect(m_workbook, &Workbook::workbookItemSelected, this, &WorkbookView::itemSelected);
0082 
0083     connect(m_tabWidget, &QTabWidget::currentChanged, this, &WorkbookView::tabChanged);
0084     connect(m_tabWidget, &QTabWidget::customContextMenuRequested, this, &WorkbookView::showTabContextMenu);
0085 //  connect(m_tabWidget->tabBar(), &QTabBar::tabMoved, this, &WorkbookView::tabMoved);
0086 }
0087 
0088 WorkbookView::~WorkbookView() {
0089     //no need to react on currentChanged() in TabWidget when views are deleted
0090     disconnect(m_tabWidget, nullptr, nullptr, nullptr);
0091 
0092     //delete all children views here, its own view will be deleted in ~AbstractPart()
0093     for (const auto* part : m_workbook->children<AbstractPart>())
0094         part->deleteView();
0095 }
0096 
0097 int WorkbookView::currentIndex() const {
0098     return m_tabWidget->currentIndex();
0099 }
0100 
0101 //##############################################################################
0102 //#########################  Private slots  ####################################
0103 //##############################################################################
0104 /*!
0105   called when the current tab was changed. Propagates the selection of \c Spreadsheet
0106   or of a \c Matrix object to \c Workbook.
0107 */
0108 void WorkbookView::tabChanged(int index) {
0109     if (m_initializing)
0110         return;
0111 
0112     if (index == -1)
0113         return;
0114 
0115     m_workbook->setChildSelectedInView(lastSelectedIndex, false);
0116     m_workbook->setChildSelectedInView(index, true);
0117     lastSelectedIndex = index;
0118 }
0119 
0120 void WorkbookView::tabMoved(int from, int to) {
0121     Q_UNUSED(from);
0122     Q_UNUSED(to);
0123     //TODO:
0124 //  AbstractAspect* aspect = m_workbook->child<AbstractAspect>(to);
0125 //  if (aspect) {
0126 //      m_tabMoving = true;
0127 //      AbstractAspect* sibling = m_workbook->child<AbstractAspect>(from);
0128 //      qDebug()<<"insert: " << to << "  " <<  aspect->name() << ",  " << from << "  " << sibling->name();
0129 //      aspect->remove();
0130 //      m_workbook->insertChildBefore(aspect, sibling);
0131 //      qDebug()<<"inserted";
0132 //      m_tabMoving = false;
0133 //  }
0134 }
0135 
0136 void WorkbookView::itemSelected(int index) {
0137     m_tabWidget->setCurrentIndex(index);
0138 }
0139 
0140 /*!
0141  * Populates the menu \c menu with the spreadsheet and spreadsheet view relevant actions.
0142  * The menu is used
0143  *   - as the context menu in WorkbookView
0144  *   - as the "spreadsheet menu" in the main menu-bar (called form MainWin)
0145  *   - as a part of the spreadsheet context menu in project explorer
0146  */
0147 void WorkbookView::createContextMenu(QMenu* menu) const {
0148     Q_ASSERT(menu);
0149 
0150     QAction* firstAction = nullptr;
0151     // if we're populating the context menu for the project explorer, then
0152     //there're already actions available there. Skip the first title-action
0153     //and insert the action at the beginning of the menu.
0154     if (menu->actions().size()>1)
0155         firstAction = menu->actions().at(1);
0156 
0157     menu->insertAction(firstAction, action_add_spreadsheet);
0158     menu->insertAction(firstAction, action_add_matrix);
0159     menu->insertSeparator(firstAction);
0160 }
0161 
0162 void WorkbookView::showTabContextMenu(QPoint point) {
0163     QMenu* menu = nullptr;
0164     auto* aspect = m_workbook->child<AbstractAspect>(m_tabWidget->currentIndex());
0165     auto* spreadsheet = dynamic_cast<Spreadsheet*>(aspect);
0166     if (spreadsheet) {
0167         menu = spreadsheet->createContextMenu();
0168     } else {
0169         Matrix* matrix = dynamic_cast<Matrix*>(aspect);
0170         if (matrix)
0171             menu = matrix->createContextMenu();
0172     }
0173 
0174     if (menu)
0175         menu->exec(m_tabWidget->mapToGlobal(point));
0176 }
0177 
0178 void WorkbookView::addMatrix() {
0179     Matrix* matrix = new Matrix(i18n("Matrix"));
0180     m_workbook->addChild(matrix);
0181 }
0182 
0183 void WorkbookView::addSpreadsheet() {
0184     Spreadsheet* spreadsheet = new Spreadsheet(i18n("Spreadsheet"));
0185     m_workbook->addChild(spreadsheet);
0186 }
0187 
0188 void WorkbookView::handleDescriptionChanged(const AbstractAspect* aspect) {
0189     int index = m_workbook->indexOfChild<AbstractAspect>(aspect);
0190     if (index != -1 && index<m_tabWidget->count())
0191         m_tabWidget->setTabText(index, aspect->name());
0192 }
0193 
0194 void WorkbookView::handleAspectAdded(const AbstractAspect* aspect) {
0195     const auto* part = dynamic_cast<const AbstractPart*>(aspect);
0196     if (!part)
0197         return;
0198 
0199     int index = m_workbook->indexOfChild<AbstractAspect>(aspect);
0200     m_tabWidget->insertTab(index, part->view(), aspect->name());
0201     m_tabWidget->setCurrentIndex(index);
0202     m_tabWidget->setTabIcon(m_tabWidget->count(), aspect->icon());
0203     this->tabChanged(index);
0204 }
0205 
0206 void WorkbookView::handleAspectAboutToBeRemoved(const AbstractAspect* aspect) {
0207     int index = m_workbook->indexOfChild<AbstractAspect>(aspect);
0208     m_tabWidget->removeTab(index);
0209 }