File indexing completed on 2024-05-12 15:26:40

0001 /***************************************************************************
0002     File                 : Workbook.h
0003     Project              : LabPlot
0004     Description          : Aspect providing a container for storing data
0005                    in form of spreadsheets and matrices
0006     --------------------------------------------------------------------
0007     Copyright            : (C) 2015 Alexander Semke(alexander.semke@web.de)
0008 
0009  ***************************************************************************/
0010 
0011 /***************************************************************************
0012  *                                                                         *
0013  *  This program is free software; you can redistribute it and/or modify   *
0014  *  it under the terms of the GNU General Public License as published by   *
0015  *  the Free Software Foundation; either version 2 of the License, or      *
0016  *  (at your option) any later version.                                    *
0017  *                                                                         *
0018  *  This program is distributed in the hope that it will be useful,        *
0019  *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
0020  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
0021  *  GNU General Public License for more details.                           *
0022  *                                                                         *
0023  *   You should have received a copy of the GNU General Public License     *
0024  *   along with this program; if not, write to the Free Software           *
0025  *   Foundation, Inc., 51 Franklin Street, Fifth Floor,                    *
0026  *   Boston, MA  02110-1301  USA                                           *
0027  *                                                                         *
0028  ***************************************************************************/
0029 
0030 #include "Workbook.h"
0031 #include "backend/spreadsheet/Spreadsheet.h"
0032 #include "backend/matrix/Matrix.h"
0033 #include "backend/lib/XmlStreamReader.h"
0034 #include "commonfrontend/workbook/WorkbookView.h"
0035 #include "kdefrontend/spreadsheet/ExportSpreadsheetDialog.h"
0036 
0037 #include <QIcon>
0038 #include <KLocalizedString>
0039 
0040 /**
0041  * \class Workbook
0042  * \brief Top-level container for Spreadsheet and Matrix.
0043  * \ingroup backend
0044  */
0045 Workbook::Workbook(const QString& name) : AbstractPart(name, AspectType::Workbook) {
0046 }
0047 
0048 QIcon Workbook::icon() const {
0049     return QIcon::fromTheme("labplot-workbook");
0050 }
0051 
0052 /*!
0053  * Returns a new context menu. The caller takes ownership of the menu.
0054  */
0055 QMenu* Workbook::createContextMenu() {
0056     QMenu *menu = AbstractPart::createContextMenu();
0057     Q_ASSERT(menu);
0058     emit requestProjectContextMenu(menu);
0059     return menu;
0060 }
0061 
0062 QWidget* Workbook::view() const {
0063     if (!m_partView) {
0064         m_view = new WorkbookView(const_cast<Workbook*>(this));
0065         m_partView = m_view;
0066     }
0067     return m_partView;
0068 }
0069 
0070 bool Workbook::exportView() const {
0071     Spreadsheet* s = currentSpreadsheet();
0072     bool ret = false;
0073     if (s)
0074         ret = s->exportView();
0075     else {
0076         Matrix* m = currentMatrix();
0077         if (m)
0078             ret = m->exportView();
0079     }
0080     return ret;
0081 }
0082 
0083 bool Workbook::printView() {
0084     Spreadsheet* s = currentSpreadsheet();
0085     bool ret = false;
0086     if (s)
0087         ret = s->printView();
0088     else {
0089         Matrix* m = currentMatrix();
0090         if (m)
0091             ret = m->printView();
0092     }
0093     return ret;
0094 }
0095 
0096 bool Workbook::printPreview() const {
0097     Spreadsheet* s = currentSpreadsheet();
0098     bool ret = false;
0099     if (s)
0100         ret = s->printPreview();
0101     else {
0102         Matrix* m = currentMatrix();
0103         if (m)
0104             ret = m->printPreview();
0105     }
0106     return ret;
0107 }
0108 
0109 Spreadsheet* Workbook::currentSpreadsheet() const {
0110     if (!m_view)
0111         return nullptr;
0112 
0113     int index = m_view->currentIndex();
0114     if (index != -1) {
0115         auto* aspect = child<AbstractAspect>(index);
0116         return dynamic_cast<Spreadsheet*>(aspect);
0117     }
0118     return nullptr;
0119 }
0120 
0121 Matrix* Workbook::currentMatrix() const {
0122     if (!m_view)
0123         return nullptr;
0124 
0125     int index = reinterpret_cast<const WorkbookView*>(m_view)->currentIndex();
0126     if (index != -1) {
0127         auto* aspect = child<AbstractAspect>(index);
0128         return dynamic_cast<Matrix*>(aspect);
0129     }
0130     return nullptr;
0131 }
0132 
0133 /*!
0134     this slot is called when a workbook child is selected in the project explorer.
0135     emits \c workbookItemSelected() to forward this event to the \c WorkbookView
0136     in order to select the corresponding tab.
0137  */
0138 void Workbook::childSelected(const AbstractAspect* aspect) {
0139     int index = indexOfChild<AbstractAspect>(aspect);
0140     emit workbookItemSelected(index);
0141 }
0142 
0143 /*!
0144     this slot is called when a worksheet element is deselected in the project explorer.
0145  */
0146 void Workbook::childDeselected(const AbstractAspect* aspect) {
0147     Q_UNUSED(aspect);
0148 }
0149 
0150 /*!
0151  *  Emits the signal to select or to deselect the workbook item (spreadsheet or matrix) with the index \c index
0152  *  in the project explorer, if \c selected=true or \c selected=false, respectively.
0153  *  The signal is handled in \c AspectTreeModel and forwarded to the tree view in \c ProjectExplorer.
0154  *  This function is called in \c WorkbookView when the current tab was changed
0155  */
0156 void Workbook::setChildSelectedInView(int index, bool selected) {
0157     auto* aspect = child<AbstractAspect>(index);
0158     if (selected) {
0159         emit childAspectSelectedInView(aspect);
0160 
0161         //deselect the workbook in the project explorer, if a child (spreadsheet or matrix) was selected.
0162         //prevents unwanted multiple selection with workbook if it was selected before.
0163         emit childAspectDeselectedInView(this);
0164     } else {
0165         emit childAspectDeselectedInView(aspect);
0166 
0167         //deselect also all children that were potentially selected before (columns of a spreadsheet)
0168         for (auto* child : aspect->children<AbstractAspect>())
0169             emit childAspectDeselectedInView(child);
0170     }
0171 }
0172 
0173 //##############################################################################
0174 //##################  Serialization/Deserialization  ###########################
0175 //##############################################################################
0176 
0177 //! Save as XML
0178 void Workbook::save(QXmlStreamWriter* writer) const {
0179     writer->writeStartElement( "workbook" );
0180     writeBasicAttributes(writer);
0181     writeCommentElement(writer);
0182 
0183     //serialize all children
0184     for (auto* aspect : children<AbstractAspect>())
0185         aspect->save(writer);
0186 
0187     writer->writeEndElement(); // close "workbook" section
0188 }
0189 
0190 //! Load from XML
0191 bool Workbook::load(XmlStreamReader* reader, bool preview) {
0192     if (!readBasicAttributes(reader))
0193         return false;
0194 
0195     while (!reader->atEnd()) {
0196         reader->readNext();
0197         if (reader->isEndElement() && reader->name() == "workbook")
0198             break;
0199 
0200         if (!reader->isStartElement())
0201             continue;
0202 
0203         if (reader->name() == "comment") {
0204             if (!readCommentElement(reader))
0205                 return false;
0206         } else if (reader->name() == "spreadsheet") {
0207             Spreadsheet* spreadsheet = new Spreadsheet("spreadsheet", true);
0208             if (!spreadsheet->load(reader, preview)) {
0209                 delete spreadsheet;
0210                 return false;
0211             } else
0212                 addChild(spreadsheet);
0213         } else if (reader->name() == "matrix") {
0214             Matrix* matrix = new Matrix(i18n("matrix"), true);
0215             if (!matrix->load(reader, preview)) {
0216                 delete matrix;
0217                 return false;
0218             } else
0219                 addChild(matrix);
0220         } else { // unknown element
0221             reader->raiseWarning(i18n("unknown workbook element '%1'", reader->name().toString()));
0222             if (!reader->skipToEndElement()) return false;
0223         }
0224     }
0225 
0226     return true;
0227 }