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

0001 /***************************************************************************
0002     File                 : AbstractAspect.h
0003     Project              : LabPlot
0004     --------------------------------------------------------------------
0005     Copyright            : (C) 2007-2009 by Tilman Benkert (thzs@gmx.net)
0006     Copyright            : (C) 2007-2010 by Knut Franke (knut.franke@gmx.de)
0007     Copyright            : (C) 2011-2015 by Alexander Semke (alexander.semke@web.de)
0008     Description          : Base class for all objects in a Project.
0009 
0010  ***************************************************************************/
0011 
0012 /***************************************************************************
0013  *                                                                         *
0014  *  This program is free software; you can redistribute it and/or modify   *
0015  *  it under the terms of the GNU General Public License as published by   *
0016  *  the Free Software Foundation; either version 2 of the License, or      *
0017  *  (at your option) any later version.                                    *
0018  *                                                                         *
0019  *  This program is distributed in the hope that it will be useful,        *
0020  *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
0021  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
0022  *  GNU General Public License for more details.                           *
0023  *                                                                         *
0024  *   You should have received a copy of the GNU General Public License     *
0025  *   along with this program; if not, write to the Free Software           *
0026  *   Foundation, Inc., 51 Franklin Street, Fifth Floor,                    *
0027  *   Boston, MA  02110-1301  USA                                           *
0028  *                                                                         *
0029  ***************************************************************************/
0030 #ifndef ABSTRACT_ASPECT_H
0031 #define ABSTRACT_ASPECT_H
0032 
0033 #include <QObject>
0034 #include <QVector>
0035 
0036 class AbstractAspectPrivate;
0037 class Folder;
0038 class Project;
0039 class XmlStreamReader;
0040 
0041 class QDateTime;
0042 class QIcon;
0043 class QMenu;
0044 class QUndoCommand;
0045 class QUndoStack;
0046 class QXmlStreamWriter;
0047 
0048 /// Information about class inheritance
0049 /// enum values are chosen such that @verbatim inherits(base)@endverbatim
0050 /// returns true iff the class inherits from @verbatim base@endverbatim.
0051 ///
0052 /// AspectType is used in GuiObserver to select the correct dock widget.
0053 enum class AspectType : quint64 {
0054     AbstractAspect = 0,
0055 
0056     // classes without inheriters
0057     AbstractFilter = 0x0100001,
0058     DatapickerCurve = 0x0100002,
0059     DatapickerPoint = 0x0100004,
0060 
0061     WorksheetElement = 0x0200000,
0062         Axis = 0x0210001,
0063         CartesianPlotLegend = 0x0210002,
0064         CustomPoint = 0x0210004,
0065         Histogram = 0x0210008,
0066         PlotArea = 0x0210010,
0067         TextLabel = 0x0210020,
0068         Image = 0x0210030,
0069         ReferenceLine = 0x0210040,
0070         WorksheetElementContainer = 0x0220000,
0071             AbstractPlot = 0x0221000,
0072                 CartesianPlot = 0x0221001,
0073             WorksheetElementGroup = 0x0222000,
0074         XYCurve = 0x0240000,
0075             XYEquationCurve = 0x0240001,
0076         XYAnalysisCurve = 0x0280000,
0077             XYConvolution = 0x0280001,
0078             XYCorrelationCurve = 0x0280002,
0079             XYDataReductionCurve = 0x0280004,
0080             XYDifferentiationCurve = 0x0280008,
0081             XYFitCurve = 0x0280010,
0082             XYFourierFilterCurve = 0x0280020,
0083             XYFourierTransformCurve = 0x0280040,
0084             XYInterpolationCurve = 0x0280080,
0085             XYIntegrationCurve = 0x0280100,
0086             XYSmoothCurve = 0x0280200,
0087 
0088     AbstractPart = 0x0400000,
0089         AbstractDataSource = 0x0410000,
0090             Matrix = 0x0411000,
0091             Spreadsheet = 0x0412000,
0092                 LiveDataSource = 0x0412001,
0093                 MQTTTopic = 0x0412002,
0094         CantorWorksheet = 0x0420001,
0095         Datapicker = 0x0420002,
0096         DatapickerImage = 0x0420004,
0097         Note = 0x0420008,
0098         Workbook = 0x0420010,
0099         Worksheet = 0x0420020,
0100 
0101     AbstractColumn = 0x1000000,
0102         Column = 0x1000001,
0103         SimpleFilterColumn = 0x1000002,
0104         ColumnStringIO = 0x1000004,
0105 
0106     Folder = 0x2000000,
0107         Project = 0x2000001,
0108         MQTTClient = 0x2000002,
0109         MQTTSubscription = 0x2000004,
0110 };
0111 
0112 class AbstractAspect : public QObject {
0113     Q_OBJECT
0114 
0115 public:
0116     enum class ChildIndexFlag {
0117         IncludeHidden = 0x01,
0118         Recursive = 0x02,
0119         Compress = 0x04
0120     };
0121 
0122     Q_DECLARE_FLAGS(ChildIndexFlags, ChildIndexFlag)
0123 
0124     friend class AspectChildAddCmd;
0125     friend class AspectChildRemoveCmd;
0126     friend class AbstractAspectPrivate;
0127 
0128     AbstractAspect(const QString& name, AspectType type);
0129     ~AbstractAspect() override;
0130 
0131     QString name() const;
0132     QString comment() const;
0133     void setCreationTime(const QDateTime&);
0134     QDateTime creationTime() const;
0135     virtual Project* project();
0136     virtual QString path() const;
0137     void setHidden(bool);
0138     bool hidden() const;
0139     void setSelected(bool);
0140     void setIsLoading(bool);
0141     bool isLoading() const;
0142     virtual QIcon icon() const;
0143     virtual QMenu* createContextMenu();
0144 
0145     AspectType type() const;
0146     bool inherits(AspectType type) const;
0147 
0148     //functions related to the handling of the tree-like project structure
0149     AbstractAspect* parentAspect() const;
0150     AbstractAspect* parent(AspectType type) const;
0151     void setParentAspect(AbstractAspect*);
0152     Folder* folder();
0153     bool isDescendantOf(AbstractAspect* other);
0154     void addChild(AbstractAspect*);
0155     void addChildFast(AbstractAspect*);
0156     virtual void finalizeAdd() {};
0157     QVector<AbstractAspect*> children(AspectType type, ChildIndexFlags flags = {}) const;
0158     void insertChildBefore(AbstractAspect* child, AbstractAspect* before);
0159     void insertChildBeforeFast(AbstractAspect* child, AbstractAspect* before);
0160     void reparent(AbstractAspect* newParent, int newIndex = -1);
0161     void removeChild(AbstractAspect*);
0162     void removeAllChildren();
0163     virtual QVector<AbstractAspect*> dependsOn() const;
0164 
0165     virtual bool isDraggable() const;
0166     virtual QVector<AspectType> dropableOn() const;
0167     virtual void processDropEvent(const QVector<quintptr>&) {};
0168 
0169     template <class T> T* ancestor() const {
0170         AbstractAspect* parent = parentAspect();
0171         while (parent) {
0172             T* ancestorAspect = dynamic_cast<T*>(parent);
0173             if (ancestorAspect)
0174                 return ancestorAspect;
0175             parent = parent->parentAspect();
0176         }
0177         return nullptr;
0178     }
0179 
0180     template <class T> QVector<T*> children(ChildIndexFlags flags = {}) const {
0181         QVector<T*> result;
0182         for (auto* child: children()) {
0183             if (flags & ChildIndexFlag::IncludeHidden || !child->hidden()) {
0184                 T* i = dynamic_cast<T*>(child);
0185                 if (i)
0186                     result << i;
0187 
0188                 if (child && flags & ChildIndexFlag::Recursive)
0189                     result << child->template children<T>(flags);
0190             }
0191         }
0192         return result;
0193     }
0194 
0195     template <class T> T* child(int index, ChildIndexFlags flags = {}) const {
0196         int i = 0;
0197         for (auto* child: children()) {
0198             T* c = dynamic_cast<T*>(child);
0199             if (c && (flags & ChildIndexFlag::IncludeHidden || !child->hidden()) && index == i++)
0200                 return c;
0201         }
0202         return nullptr;
0203     }
0204 
0205     template <class T> T* child(const QString& name) const {
0206         for (auto* child: children()) {
0207             T* c = dynamic_cast<T*>(child);
0208             if (c && child->name() == name)
0209                 return c;
0210         }
0211         return nullptr;
0212     }
0213 
0214     template <class T> int childCount(ChildIndexFlags flags = {}) const {
0215         int result = 0;
0216         for (auto* child: children()) {
0217             T* i = dynamic_cast<T*>(child);
0218             if (i && (flags & ChildIndexFlag::IncludeHidden || !child->hidden()))
0219                 result++;
0220         }
0221         return result;
0222     }
0223 
0224     template <class T> int indexOfChild(const AbstractAspect* child, ChildIndexFlags flags = {}) const {
0225         int index = 0;
0226         for (auto* c:    children()) {
0227             if (child == c) return index;
0228             T* i = dynamic_cast<T*>(c);
0229             if (i && (flags & ChildIndexFlag::IncludeHidden || !c->hidden()))
0230                 index++;
0231         }
0232         return -1;
0233     }
0234 
0235     //undo/redo related functions
0236     void setUndoAware(bool);
0237     virtual QUndoStack* undoStack() const;
0238     void exec(QUndoCommand*);
0239     void exec(QUndoCommand* command, const char* preChangeSignal, const char* postChangeSignal,
0240         QGenericArgument val0 = QGenericArgument(), QGenericArgument val1 = QGenericArgument(),
0241         QGenericArgument val2 = QGenericArgument(), QGenericArgument val3 = QGenericArgument());
0242     void beginMacro(const QString& text);
0243     void endMacro();
0244 
0245     //save/load
0246     virtual void save(QXmlStreamWriter*) const = 0;
0247     virtual bool load(XmlStreamReader*, bool preview) = 0;
0248 
0249 protected:
0250     void info(const QString& text) { emit statusInfo(text); }
0251 
0252     //serialization/deserialization
0253     bool readBasicAttributes(XmlStreamReader*);
0254     void writeBasicAttributes(QXmlStreamWriter*) const;
0255     void writeCommentElement(QXmlStreamWriter*) const;
0256     bool readCommentElement(XmlStreamReader*);
0257 
0258     const AspectType m_type;
0259 
0260 private:
0261     AbstractAspectPrivate* d;
0262 
0263     QString uniqueNameFor(const QString&) const;
0264     const QVector<AbstractAspect*>& children() const;
0265     void connectChild(AbstractAspect*);
0266 
0267 public slots:
0268     bool setName(const QString&, bool autoUnique = true);
0269     void setComment(const QString&);
0270     void remove();
0271 
0272 protected slots:
0273     virtual void childSelected(const AbstractAspect*);
0274     virtual void childDeselected(const AbstractAspect*);
0275 
0276 signals:
0277     void aspectDescriptionAboutToChange(const AbstractAspect*);
0278     void aspectDescriptionChanged(const AbstractAspect*);
0279     void aspectAboutToBeAdded(const AbstractAspect* parent, const AbstractAspect* before, const AbstractAspect* child);
0280     void aspectAdded(const AbstractAspect*);
0281     void aspectAboutToBeRemoved(const AbstractAspect*);
0282     void aspectRemoved(const AbstractAspect* parent, const AbstractAspect* before, const AbstractAspect* child);
0283     void aspectHiddenAboutToChange(const AbstractAspect*);
0284     void aspectHiddenChanged(const AbstractAspect*);
0285     void statusInfo(const QString&);
0286     void renameRequested();
0287 
0288     //selection/deselection in model (project explorer)
0289     void selected(const AbstractAspect*);
0290     void deselected(const AbstractAspect*);
0291 
0292     //selection/deselection in view
0293     void childAspectSelectedInView(const AbstractAspect*);
0294     void childAspectDeselectedInView(const AbstractAspect*);
0295 };
0296 
0297 Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractAspect::ChildIndexFlags)
0298 
0299 #endif // ifndef ABSTRACT_ASPECT_H