File indexing completed on 2024-05-12 03:47:28
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 SPDX-FileCopyrightText: 2015 Alexander Semke <alexander.semke@web.de> 0008 SPDX-License-Identifier: GPL-2.0-or-later 0009 */ 0010 0011 #include "Workbook.h" 0012 #include "backend/lib/XmlStreamReader.h" 0013 #include "backend/matrix/Matrix.h" 0014 #include "backend/spreadsheet/Spreadsheet.h" 0015 #include "commonfrontend/workbook/WorkbookView.h" 0016 #include "kdefrontend/spreadsheet/ExportSpreadsheetDialog.h" 0017 0018 #include <KLocalizedString> 0019 #include <QIcon> 0020 0021 /** 0022 * \class Workbook 0023 * \brief Top-level container for Spreadsheet and Matrix. 0024 * \ingroup backend 0025 */ 0026 Workbook::Workbook(const QString& name) 0027 : AbstractPart(name, AspectType::Workbook) { 0028 } 0029 0030 QIcon Workbook::icon() const { 0031 return QIcon::fromTheme(QLatin1String("labplot-workbook")); 0032 } 0033 0034 /*! 0035 * Returns a new context menu. The caller takes ownership of the menu. 0036 */ 0037 QMenu* Workbook::createContextMenu() { 0038 QMenu* menu = AbstractPart::createContextMenu(); 0039 Q_ASSERT(menu); 0040 Q_EMIT requestProjectContextMenu(menu); 0041 return menu; 0042 } 0043 0044 QWidget* Workbook::view() const { 0045 if (!m_partView) { 0046 m_view = new WorkbookView(const_cast<Workbook*>(this)); 0047 m_partView = m_view; 0048 connect(this, &Workbook::viewAboutToBeDeleted, [this]() { 0049 m_view = nullptr; 0050 }); 0051 } 0052 return m_partView; 0053 } 0054 0055 bool Workbook::exportView() const { 0056 Spreadsheet* s = currentSpreadsheet(); 0057 bool ret = false; 0058 if (s) 0059 ret = s->exportView(); 0060 else { 0061 Matrix* m = currentMatrix(); 0062 if (m) 0063 ret = m->exportView(); 0064 } 0065 return ret; 0066 } 0067 0068 bool Workbook::printView() { 0069 Spreadsheet* s = currentSpreadsheet(); 0070 bool ret = false; 0071 if (s) 0072 ret = s->printView(); 0073 else { 0074 Matrix* m = currentMatrix(); 0075 if (m) 0076 ret = m->printView(); 0077 } 0078 return ret; 0079 } 0080 0081 bool Workbook::printPreview() const { 0082 Spreadsheet* s = currentSpreadsheet(); 0083 bool ret = false; 0084 if (s) 0085 ret = s->printPreview(); 0086 else { 0087 Matrix* m = currentMatrix(); 0088 if (m) 0089 ret = m->printPreview(); 0090 } 0091 return ret; 0092 } 0093 0094 Spreadsheet* Workbook::currentSpreadsheet() const { 0095 if (!m_view) 0096 return nullptr; 0097 0098 int index = m_view->currentIndex(); 0099 if (index != -1) { 0100 auto* aspect = child<AbstractAspect>(index); 0101 return dynamic_cast<Spreadsheet*>(aspect); 0102 } 0103 return nullptr; 0104 } 0105 0106 Matrix* Workbook::currentMatrix() const { 0107 if (!m_view) 0108 return nullptr; 0109 0110 int index = reinterpret_cast<const WorkbookView*>(m_view)->currentIndex(); 0111 if (index != -1) { 0112 auto* aspect = child<AbstractAspect>(index); 0113 return dynamic_cast<Matrix*>(aspect); 0114 } 0115 return nullptr; 0116 } 0117 0118 /*! 0119 this slot is called when a workbook child is selected in the project explorer. 0120 emits \c workbookItemSelected() to forward this event to the \c WorkbookView 0121 in order to select the corresponding tab. 0122 */ 0123 void Workbook::childSelected(const AbstractAspect* aspect) { 0124 int index = indexOfChild<AbstractAspect>(aspect); 0125 Q_EMIT workbookItemSelected(index); 0126 } 0127 0128 /*! 0129 this slot is called when a worksheet element is deselected in the project explorer. 0130 */ 0131 void Workbook::childDeselected(const AbstractAspect*) { 0132 } 0133 0134 /*! 0135 * Emits the signal to select or to deselect the workbook item (spreadsheet or matrix) with the index \c index 0136 * in the project explorer, if \c selected=true or \c selected=false, respectively. 0137 * The signal is handled in \c AspectTreeModel and forwarded to the tree view in \c ProjectExplorer. 0138 * This function is called in \c WorkbookView when the current tab was changed 0139 */ 0140 void Workbook::setChildSelectedInView(int index, bool selected) { 0141 auto* aspect = child<AbstractAspect>(index); 0142 if (selected) { 0143 Q_EMIT childAspectSelectedInView(aspect); 0144 0145 // deselect the workbook in the project explorer, if a child (spreadsheet or matrix) was selected. 0146 // prevents unwanted multiple selection with workbook if it was selected before. 0147 Q_EMIT childAspectDeselectedInView(this); 0148 } else { 0149 Q_EMIT childAspectDeselectedInView(aspect); 0150 0151 // deselect also all children that were potentially selected before (columns of a spreadsheet) 0152 for (auto* child : aspect->children<AbstractAspect>()) 0153 Q_EMIT childAspectDeselectedInView(child); 0154 } 0155 } 0156 0157 QVector<AspectType> Workbook::pasteTypes() const { 0158 return QVector<AspectType>{AspectType::Spreadsheet, AspectType::Matrix}; 0159 } 0160 0161 void Workbook::processDropEvent(const QVector<quintptr>& vec) { 0162 for (auto a : vec) { 0163 auto* aspect = reinterpret_cast<AbstractAspect*>(a); 0164 aspect->reparent(this); 0165 } 0166 } 0167 // ############################################################################## 0168 // ################## Serialization/Deserialization ########################### 0169 // ############################################################################## 0170 0171 //! Save as XML 0172 void Workbook::save(QXmlStreamWriter* writer) const { 0173 writer->writeStartElement(QLatin1String("workbook")); 0174 writeBasicAttributes(writer); 0175 writeCommentElement(writer); 0176 0177 // serialize all children 0178 for (auto* aspect : children<AbstractAspect>()) 0179 aspect->save(writer); 0180 0181 writer->writeEndElement(); // close "workbook" section 0182 } 0183 0184 //! Load from XML 0185 bool Workbook::load(XmlStreamReader* reader, bool preview) { 0186 if (!readBasicAttributes(reader)) 0187 return false; 0188 0189 while (!reader->atEnd()) { 0190 reader->readNext(); 0191 if (reader->isEndElement() && reader->name() == QLatin1String("workbook")) 0192 break; 0193 0194 if (!reader->isStartElement()) 0195 continue; 0196 0197 if (reader->name() == QLatin1String("comment")) { 0198 if (!readCommentElement(reader)) 0199 return false; 0200 } else if (reader->name() == QLatin1String("spreadsheet")) { 0201 auto* spreadsheet = new Spreadsheet(QStringLiteral("spreadsheet"), true); 0202 if (!spreadsheet->load(reader, preview)) { 0203 delete spreadsheet; 0204 return false; 0205 } else 0206 addChild(spreadsheet); 0207 } else if (reader->name() == QLatin1String("matrix")) { 0208 auto* matrix = new Matrix(i18n("matrix"), true); 0209 if (!matrix->load(reader, preview)) { 0210 delete matrix; 0211 return false; 0212 } else 0213 addChild(matrix); 0214 } else { // unknown element 0215 reader->raiseWarning(i18n("unknown workbook element '%1'", reader->name().toString())); 0216 if (!reader->skipToEndElement()) 0217 return false; 0218 } 0219 } 0220 0221 return true; 0222 }