File indexing completed on 2024-05-12 03:47:25
0001 /* 0002 File : AbstractAspect.h 0003 Project : LabPlot 0004 Description : Base class for all objects in a Project. 0005 -------------------------------------------------------------------- 0006 SPDX-FileCopyrightText: 2007-2009 Tilman Benkert <thzs@gmx.net> 0007 SPDX-FileCopyrightText: 2007-2010 Knut Franke <knut.franke@gmx.de> 0008 SPDX-FileCopyrightText: 2011-2023 Alexander Semke <alexander.semke@web.de> 0009 SPDX-License-Identifier: GPL-2.0-or-later 0010 */ 0011 0012 #ifndef ABSTRACT_ASPECT_H 0013 #define ABSTRACT_ASPECT_H 0014 0015 #include <QObject> 0016 #include <QVector> 0017 0018 class AbstractAspectPrivate; 0019 class Folder; 0020 class Project; 0021 class XmlStreamReader; 0022 0023 class QDateTime; 0024 class QIcon; 0025 class QMenu; 0026 class QUndoCommand; 0027 class QUndoStack; 0028 class QXmlStreamWriter; 0029 0030 /// Information about class inheritance 0031 /// enum values are chosen such that @verbatim inherits(base)@endverbatim 0032 /// returns true if the class inherits from @verbatim base@endverbatim. 0033 /// 0034 /// AspectType is used in GuiObserver to select the correct dock widget. 0035 enum class AspectType : quint64 { 0036 AbstractAspect = 0, 0037 0038 // classes without inheriters 0039 AbstractFilter = 0x0100001, 0040 DatapickerCurve = 0x0100002, 0041 DatapickerPoint = 0x0100004, 0042 0043 WorksheetElement = 0x0200000, 0044 Axis = 0x0210001, 0045 CartesianPlotLegend = 0x0210002, 0046 CustomPoint = 0x0210004, 0047 PlotArea = 0x0210010, 0048 TextLabel = 0x0210020, 0049 Image = 0x0210030, 0050 ReferenceLine = 0x0210040, 0051 ReferenceRange = 0x0210060, 0052 InfoElement = 0x0210080, 0053 0054 // bar plots 0055 BarPlot = 0x0210200, 0056 LollipopPlot = 0x0210400, 0057 0058 // statistical plots 0059 Histogram = 0x0210008, 0060 BoxPlot = 0x0210100, 0061 QQPlot = 0x0210800, 0062 KDEPlot = 0x0210802, 0063 0064 WorksheetElementContainer = 0x0220000, 0065 AbstractPlot = 0x0221000, 0066 CartesianPlot = 0x0221001, 0067 WorksheetElementGroup = 0x0222000, 0068 XYCurve = 0x0240000, 0069 XYEquationCurve = 0x0240001, 0070 0071 // analysis curves 0072 XYAnalysisCurve = 0x0280000, 0073 XYConvolutionCurve = 0x0280001, 0074 XYCorrelationCurve = 0x0280002, 0075 XYDataReductionCurve = 0x0280004, 0076 XYDifferentiationCurve = 0x0280008, 0077 XYFitCurve = 0x0280010, 0078 XYFourierFilterCurve = 0x0280020, 0079 XYFourierTransformCurve = 0x0280040, 0080 XYInterpolationCurve = 0x0280080, 0081 XYIntegrationCurve = 0x0280100, 0082 XYSmoothCurve = 0x0280200, 0083 XYHilbertTransformCurve = 0x0280400, 0084 0085 AbstractPart = 0x0400000, 0086 AbstractDataSource = 0x0410000, 0087 Matrix = 0x0411000, 0088 Spreadsheet = 0x0412000, 0089 LiveDataSource = 0x0412001, 0090 MQTTTopic = 0x0412002, 0091 StatisticsSpreadsheet = 0x0412004, 0092 CantorWorksheet = 0x0420001, 0093 Datapicker = 0x0420002, 0094 DatapickerImage = 0x0420004, 0095 Note = 0x0420008, 0096 Workbook = 0x0420010, 0097 Worksheet = 0x0420020, 0098 0099 AbstractColumn = 0x1000000, 0100 Column = 0x1000001, 0101 SimpleFilterColumn = 0x1000002, 0102 ColumnStringIO = 0x1000004, 0103 0104 Folder = 0x2000000, 0105 Project = 0x2000001, 0106 MQTTClient = 0x2000002, 0107 MQTTSubscription = 0x2000004, 0108 }; 0109 0110 #ifdef SDK 0111 #include "labplot_export.h" 0112 class LABPLOT_EXPORT AbstractAspect : public QObject { 0113 #else 0114 class AbstractAspect : public QObject { 0115 #endif 0116 Q_OBJECT 0117 0118 public: 0119 enum class ChildIndexFlag { IncludeHidden = 0x01, Recursive = 0x02, Compress = 0x04 }; 0120 0121 Q_DECLARE_FLAGS(ChildIndexFlags, ChildIndexFlag) 0122 0123 friend class AspectChildAddCmd; 0124 friend class AspectChildRemoveCmd; 0125 friend class AbstractAspectPrivate; 0126 0127 AbstractAspect(const QString& name, AspectType type); 0128 ~AbstractAspect() override; 0129 0130 enum class NameHandling { 0131 AutoUnique, // Set the name and make it unique (enforce the uniqueness) 0132 UniqueNotRequired, // Set the name without making it unique 0133 UniqueRequired, // Set the name only if it's already unique 0134 }; 0135 0136 // type name for internal use (no translation) 0137 static QString typeName(AspectType type) { 0138 switch (type) { 0139 case AspectType::AbstractAspect: 0140 return QStringLiteral("AbstractAspect"); 0141 case AspectType::AbstractFilter: 0142 return QStringLiteral("AbstractFilter"); 0143 case AspectType::DatapickerCurve: 0144 return QStringLiteral("DatapickerCurve"); 0145 case AspectType::DatapickerPoint: 0146 return QStringLiteral("DatapickerPoint"); 0147 case AspectType::WorksheetElement: 0148 return QStringLiteral("WorksheetElement"); 0149 case AspectType::Axis: 0150 return QStringLiteral("Axis"); 0151 case AspectType::CartesianPlotLegend: 0152 return QStringLiteral("CartesianPlotLegend"); 0153 case AspectType::CustomPoint: 0154 return QStringLiteral("CustomPoint"); 0155 case AspectType::Histogram: 0156 return QStringLiteral("Histogram"); 0157 case AspectType::PlotArea: 0158 return QStringLiteral("PlotArea"); 0159 case AspectType::TextLabel: 0160 return QStringLiteral("TextLabel"); 0161 case AspectType::Image: 0162 return QStringLiteral("Image"); 0163 case AspectType::ReferenceLine: 0164 return QStringLiteral("ReferenceLine"); 0165 case AspectType::ReferenceRange: 0166 return QStringLiteral("ReferenceRange"); 0167 case AspectType::InfoElement: 0168 return QStringLiteral("InfoElement"); 0169 case AspectType::WorksheetElementContainer: 0170 return QStringLiteral("WorksheetElementContainer"); 0171 case AspectType::AbstractPlot: 0172 return QStringLiteral("AbstractPlot"); 0173 case AspectType::CartesianPlot: 0174 return QStringLiteral("CartesianPlot"); 0175 case AspectType::WorksheetElementGroup: 0176 return QStringLiteral("WorksheetElementGroup"); 0177 case AspectType::XYCurve: 0178 return QStringLiteral("XYCurve"); 0179 case AspectType::XYEquationCurve: 0180 return QStringLiteral("XYEquationCurve"); 0181 case AspectType::XYAnalysisCurve: 0182 return QStringLiteral("XYAnalysisCurve"); 0183 case AspectType::XYConvolutionCurve: 0184 return QStringLiteral("XYConvolutionCurve"); 0185 case AspectType::XYCorrelationCurve: 0186 return QStringLiteral("XYCorrelationCurve"); 0187 case AspectType::XYDataReductionCurve: 0188 return QStringLiteral("XYDataReductionCurve"); 0189 case AspectType::XYDifferentiationCurve: 0190 return QStringLiteral("XYDifferentiationCurve"); 0191 case AspectType::XYFitCurve: 0192 return QStringLiteral("XYFitCurve"); 0193 case AspectType::XYFourierFilterCurve: 0194 return QStringLiteral("XYFourierFilterCurve"); 0195 case AspectType::XYFourierTransformCurve: 0196 return QStringLiteral("XYFourierTransformCurve"); 0197 case AspectType::XYInterpolationCurve: 0198 return QStringLiteral("XYInterpolationCurve"); 0199 case AspectType::XYIntegrationCurve: 0200 return QStringLiteral("XYIntegrationCurve"); 0201 case AspectType::XYSmoothCurve: 0202 return QStringLiteral("XYSmoothCurve"); 0203 case AspectType::XYHilbertTransformCurve: 0204 return QStringLiteral("XYHilbertTransformCurve"); 0205 case AspectType::BarPlot: 0206 return QStringLiteral("BarPlot"); 0207 case AspectType::BoxPlot: 0208 return QStringLiteral("BoxPlot"); 0209 case AspectType::QQPlot: 0210 return QStringLiteral("QQPlot"); 0211 case AspectType::KDEPlot: 0212 return QStringLiteral("KDEPlot"); 0213 case AspectType::LollipopPlot: 0214 return QStringLiteral("LollipopPlot"); 0215 case AspectType::AbstractPart: 0216 return QStringLiteral("AbstractPart"); 0217 case AspectType::AbstractDataSource: 0218 return QStringLiteral("AbstractDataSource"); 0219 case AspectType::Matrix: 0220 return QStringLiteral("Matrix"); 0221 case AspectType::Spreadsheet: 0222 return QStringLiteral("Spreadsheet"); 0223 case AspectType::StatisticsSpreadsheet: 0224 return QStringLiteral("StatisticsSpreadsheet"); 0225 case AspectType::LiveDataSource: 0226 return QStringLiteral("LiveDataSource"); 0227 case AspectType::MQTTTopic: 0228 return QStringLiteral("MQTTTopic"); 0229 case AspectType::CantorWorksheet: 0230 return QStringLiteral("CantorWorksheet"); 0231 case AspectType::Datapicker: 0232 return QStringLiteral("Datapicker"); 0233 case AspectType::DatapickerImage: 0234 return QStringLiteral("DatapickerImage"); 0235 case AspectType::Note: 0236 return QStringLiteral("Note"); 0237 case AspectType::Workbook: 0238 return QStringLiteral("Workbook"); 0239 case AspectType::Worksheet: 0240 return QStringLiteral("Worksheet"); 0241 case AspectType::AbstractColumn: 0242 return QStringLiteral("AbstractColumn"); 0243 case AspectType::Column: 0244 return QStringLiteral("Column"); 0245 case AspectType::SimpleFilterColumn: 0246 return QStringLiteral("SimpleFilterColumn"); 0247 case AspectType::ColumnStringIO: 0248 return QStringLiteral("ColumnStringIO"); 0249 case AspectType::Folder: 0250 return QStringLiteral("Folder"); 0251 case AspectType::Project: 0252 return QStringLiteral("Project"); 0253 case AspectType::MQTTClient: 0254 return QStringLiteral("MQTTClient"); 0255 case AspectType::MQTTSubscription: 0256 return QStringLiteral("MQTTSubscription"); 0257 } 0258 0259 return {}; 0260 } 0261 0262 QString name() const; 0263 QUuid uuid() const; 0264 void setSuppressWriteUuid(bool); 0265 QString comment() const; 0266 void setCreationTime(const QDateTime&); 0267 QDateTime creationTime() const; 0268 virtual Project* project(); 0269 virtual QString path() const; 0270 void setHidden(bool); 0271 bool hidden() const; 0272 void setFixed(bool); 0273 bool isFixed() const; 0274 void setSelected(bool); 0275 void setMoved(bool); 0276 bool isMoved() const; 0277 void setIsLoading(bool); 0278 bool isLoading() const; 0279 virtual QIcon icon() const; 0280 virtual QMenu* createContextMenu(); 0281 0282 AspectType type() const; 0283 bool inherits(AspectType type) const; 0284 0285 // functions related to the handling of the tree-like project structure 0286 AbstractAspect* parentAspect() const; 0287 AbstractAspect* parent(AspectType type) const; 0288 void setParentAspect(AbstractAspect*); 0289 Folder* folder(); 0290 bool isDescendantOf(AbstractAspect* other); 0291 void addChild(AbstractAspect*, QUndoCommand* parent = nullptr); 0292 void addChildFast(AbstractAspect*); 0293 virtual void finalizeAdd(){}; 0294 QVector<AbstractAspect*> children(AspectType type, ChildIndexFlags flags = {}) const; 0295 void insertChild(AbstractAspect* child, int index, QUndoCommand* parent = nullptr); 0296 void insertChildBefore(AbstractAspect* child, AbstractAspect* before, QUndoCommand* parent = nullptr); 0297 void insertChildBeforeFast(AbstractAspect* child, AbstractAspect* before); 0298 void reparent(AbstractAspect* newParent, int newIndex = -1); 0299 /*! 0300 * \brief removeChild 0301 * Removing child aspect using an undo command 0302 * \param parent If parent is not nullptr the command will not be executed, but the parent must be executed 0303 * to indirectly execute the created undocommand 0304 */ 0305 void removeChild(AbstractAspect*, QUndoCommand* parent = nullptr); 0306 void removeAllChildren(); 0307 virtual QVector<AbstractAspect*> dependsOn() const; 0308 0309 virtual QVector<AspectType> pasteTypes() const; 0310 virtual bool isDraggable() const; 0311 virtual QVector<AspectType> dropableOn() const; 0312 virtual void processDropEvent(const QVector<quintptr>&){}; 0313 0314 template<class T> 0315 T* ancestor() const { 0316 AbstractAspect* parent = parentAspect(); 0317 while (parent) { 0318 T* ancestorAspect = dynamic_cast<T*>(parent); 0319 if (ancestorAspect) 0320 return ancestorAspect; 0321 parent = parent->parentAspect(); 0322 } 0323 return nullptr; 0324 } 0325 0326 template<class T> 0327 QVector<T*> children(ChildIndexFlags flags = {}) const { 0328 QVector<T*> result; 0329 for (auto* child : children()) { 0330 if (flags & ChildIndexFlag::IncludeHidden || !child->hidden()) { 0331 T* i = dynamic_cast<T*>(child); 0332 if (i) 0333 result << i; 0334 0335 if (child && flags & ChildIndexFlag::Recursive) 0336 result << child->template children<T>(flags); 0337 } 0338 } 0339 return result; 0340 } 0341 0342 template<class T> 0343 T* child(int index, ChildIndexFlags flags = {}) const { 0344 int i = 0; 0345 for (auto* child : children()) { 0346 T* c = dynamic_cast<T*>(child); 0347 if (c && (flags & ChildIndexFlag::IncludeHidden || !child->hidden()) && index == i++) 0348 return c; 0349 } 0350 return nullptr; 0351 } 0352 0353 template<class T> 0354 T* child(const QString& name) const { 0355 for (auto* child : children()) { 0356 T* c = dynamic_cast<T*>(child); 0357 if (c && child->name() == name) 0358 return c; 0359 } 0360 return nullptr; 0361 } 0362 0363 template<class T> 0364 int childCount(ChildIndexFlags flags = {}) const { 0365 int result = 0; 0366 for (auto* child : children()) { 0367 T* i = dynamic_cast<T*>(child); 0368 if (i && (flags & ChildIndexFlag::IncludeHidden || !child->hidden())) 0369 result++; 0370 } 0371 return result; 0372 } 0373 0374 template<class T> 0375 int indexOfChild(const AbstractAspect* child, ChildIndexFlags flags = {}) const { 0376 int index = 0; 0377 for (auto* c : children()) { 0378 if (child == c) 0379 return index; 0380 T* i = dynamic_cast<T*>(c); 0381 if (i && (flags & ChildIndexFlag::IncludeHidden || !c->hidden())) 0382 index++; 0383 } 0384 return -1; 0385 } 0386 0387 // undo/redo related functions 0388 void setUndoAware(bool); 0389 virtual QUndoStack* undoStack() const; 0390 void exec(QUndoCommand*); 0391 void exec(QUndoCommand* command, 0392 const char* preChangeSignal, 0393 const char* postChangeSignal, 0394 QGenericArgument val0 = QGenericArgument(), 0395 QGenericArgument val1 = QGenericArgument(), 0396 QGenericArgument val2 = QGenericArgument(), 0397 QGenericArgument val3 = QGenericArgument()); 0398 void beginMacro(const QString& text); 0399 void endMacro(); 0400 0401 // save/load 0402 virtual void save(QXmlStreamWriter*) const = 0; 0403 virtual bool load(XmlStreamReader*, bool preview) = 0; 0404 void setPasted(bool); 0405 bool pasted() const; 0406 0407 static AspectType clipboardAspectType(QString&); 0408 static QString uniqueNameFor(const QString& name, const QStringList& names); 0409 0410 protected: 0411 void info(const QString& text) { 0412 Q_EMIT statusInfo(text); 0413 } 0414 0415 // serialization/deserialization 0416 bool readBasicAttributes(XmlStreamReader*); 0417 void writeBasicAttributes(QXmlStreamWriter*) const; 0418 void writeCommentElement(QXmlStreamWriter*) const; 0419 bool readCommentElement(XmlStreamReader*); 0420 0421 const AspectType m_type; 0422 0423 private: 0424 AbstractAspectPrivate* d; 0425 0426 QString uniqueNameFor(const QString&) const; 0427 const QVector<AbstractAspect*>& children() const; 0428 void connectChild(AbstractAspect*); 0429 0430 public Q_SLOTS: 0431 bool setName(const QString&, NameHandling handling = NameHandling::AutoUnique, QUndoCommand* parent = nullptr); 0432 void setComment(const QString&); 0433 void remove(); 0434 void remove(QUndoCommand* parent); 0435 void copy(); 0436 void duplicate(); 0437 void paste(bool duplicate = false); 0438 0439 private Q_SLOTS: 0440 void moveUp(); 0441 void moveDown(); 0442 0443 protected Q_SLOTS: 0444 virtual void childSelected(const AbstractAspect*); 0445 virtual void childDeselected(const AbstractAspect*); 0446 0447 Q_SIGNALS: 0448 void aspectDescriptionAboutToChange(const AbstractAspect*); 0449 void aspectDescriptionChanged(const AbstractAspect*); 0450 /*! 0451 * \brief aspectAboutToBeAdded 0452 * Signal indicating a new child was added at position \p index. Do not connect to both variants of aspectAboutToBeAdded! 0453 * \param parent 0454 * \param index Position of the new aspect 0455 * \param child 0456 */ 0457 void childAspectAboutToBeAdded(const AbstractAspect* parent, int index, const AbstractAspect* child); 0458 /*! 0459 * \brief aspectAboutToBeAdded 0460 * \param parent 0461 * \param before aspect one position before the child 0462 * \param child 0463 */ 0464 void childAspectAboutToBeAdded(const AbstractAspect* parent, const AbstractAspect* before, const AbstractAspect* child); 0465 void childAspectAdded(const AbstractAspect*); 0466 /*! 0467 * \brief aspectAboutToBeRemoved 0468 * Called from the parent if a child is being removed 0469 */ 0470 void childAspectAboutToBeRemoved(const AbstractAspect* child); 0471 void childAspectRemoved(const AbstractAspect* parent, const AbstractAspect* before, const AbstractAspect* child); 0472 /*! 0473 * \brief aspectAboutToBeRemoved 0474 * Called by the aspect itself when it's being removed 0475 */ 0476 void aspectAboutToBeRemoved(const AbstractAspect*); 0477 void aspectHiddenAboutToChange(const AbstractAspect*); 0478 void aspectHiddenChanged(const AbstractAspect*); 0479 void statusInfo(const QString&); 0480 void renameRequested(); 0481 void contextMenuRequested(AspectType, QMenu*); 0482 0483 // selection/deselection in model (project explorer) 0484 void selected(const AbstractAspect*); 0485 void deselected(const AbstractAspect*); 0486 0487 // selection/deselection in view 0488 void childAspectSelectedInView(const AbstractAspect*); 0489 void childAspectDeselectedInView(const AbstractAspect*); 0490 0491 // Used by the retransformTests 0492 Q_SIGNALS: 0493 void retransformCalledSignal(const AbstractAspect* sender, bool suppressed); 0494 0495 public: 0496 void resetRetransformCalled() { 0497 mRetransformCalled = 0; 0498 } 0499 int retransformCalled() const { 0500 return mRetransformCalled; 0501 } 0502 int mRetransformCalled{0}; 0503 0504 #define trackRetransformCalled(suppressed) \ 0505 Q_EMIT q->retransformCalledSignal(q, suppressed); \ 0506 if (!suppressed) \ 0507 q->mRetransformCalled += 1; 0508 0509 friend class AbstractAspectTest; 0510 }; 0511 0512 Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractAspect::ChildIndexFlags) 0513 0514 #endif // ifndef ABSTRACT_ASPECT_H