diff --git a/include/AutomatableModel.h b/include/AutomatableModel.h index 78f4882b4..f5215676e 100644 --- a/include/AutomatableModel.h +++ b/include/AutomatableModel.h @@ -33,6 +33,7 @@ #include "MidiTime.h" #include "ValueBuffer.h" #include "MemoryManager.h" +#include "ModelVisitor.h" // simple way to map a property of a view to a model #define mapPropertyFromModelPtr(type,getfunc,setfunc,modelname) \ @@ -68,6 +69,7 @@ class LMMS_EXPORT AutomatableModel : public Model, public JournallingObject Q_OBJECT MM_OPERATORS public: + typedef QVector AutoModelVector; enum ScaleType @@ -80,6 +82,32 @@ public: virtual ~AutomatableModel(); + // Implement those by using the MODEL_IS_VISITABLE macro + virtual void accept(ModelVisitor& v) = 0; + virtual void accept(ConstModelVisitor& v) const = 0; + // use this to make subclasses visitable +#define MODEL_IS_VISITABLE \ + void accept(ModelVisitor& v) override { v.visit(*this); } \ + void accept(ConstModelVisitor& v) const override { v.visit(*this); } + +public: + //! Return this class casted to Target, or nullptr if impossible + template + Target* dcast(bool doThrow = false) + { + DCastVisitor vis; accept(vis); + if(doThrow && !vis.result) Q_ASSERT(false); + return vis.result; + } + + //! Return this class casted to const Target, or nullptr if impossible + template + const Target* dcast(bool doThrow = false) const + { + ConstDCastVisitor vis; accept(vis); + if(doThrow && !vis.result) Q_ASSERT(false); + return vis.result; + } bool isAutomated() const; bool isAutomatedOrControlled() const @@ -283,6 +311,20 @@ protected: private: + template + struct DCastVisitor : public ModelVisitor + { + Target* result = nullptr; + void visit(Target& tar) { result = &tar; } + }; + + template + struct ConstDCastVisitor : public ConstModelVisitor + { + const Target* result = nullptr; + void visit(const Target& tar) { result = &tar; } + }; + static bool mustQuoteName(const QString &name); virtual void saveSettings( QDomDocument& doc, QDomElement& element ) @@ -382,6 +424,7 @@ public: class LMMS_EXPORT FloatModel : public TypedAutomatableModel { Q_OBJECT + MODEL_IS_VISITABLE public: FloatModel( float val = 0, float min = 0, float max = 0, float step = 0, Model * parent = NULL, @@ -399,6 +442,7 @@ public: class LMMS_EXPORT IntModel : public TypedAutomatableModel { Q_OBJECT + MODEL_IS_VISITABLE public: IntModel( int val = 0, int min = 0, int max = 0, Model* parent = NULL, @@ -414,6 +458,7 @@ public: class LMMS_EXPORT BoolModel : public TypedAutomatableModel { Q_OBJECT + MODEL_IS_VISITABLE public: BoolModel( const bool val = false, Model* parent = NULL, diff --git a/include/ComboBoxModel.h b/include/ComboBoxModel.h index ad3603759..82c01e69e 100644 --- a/include/ComboBoxModel.h +++ b/include/ComboBoxModel.h @@ -36,6 +36,7 @@ class LMMS_EXPORT ComboBoxModel : public IntModel { Q_OBJECT + MODEL_IS_VISITABLE public: ComboBoxModel( Model* parent = NULL, const QString& displayName = QString(), diff --git a/include/ModelVisitor.h b/include/ModelVisitor.h new file mode 100644 index 000000000..59d1df0c6 --- /dev/null +++ b/include/ModelVisitor.h @@ -0,0 +1,53 @@ +/* + * ModelVisitor.h - visitors for automatable models + * + * Copyright (c) 2019-2019 Johannes Lorenz + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef MODELVISITOR_H +#define MODELVISITOR_H + +class BoolModel; +class IntModel; +class FloatModel; +class ComboBoxModel; + +class ModelVisitor +{ +public: + virtual void visit(BoolModel& ) {} + virtual void visit(IntModel& ) {} + virtual void visit(FloatModel& ) {} + virtual void visit(ComboBoxModel& ) {} + virtual ~ModelVisitor(); +}; + +class ConstModelVisitor +{ +public: + virtual void visit(const BoolModel& ) {} + virtual void visit(const IntModel& ) {} + virtual void visit(const FloatModel& ) {} + virtual void visit(const ComboBoxModel& ) {} + virtual ~ConstModelVisitor(); +}; + +#endif // MODELVISITOR_H diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 85a00780b..b573b93b0 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -40,6 +40,7 @@ set(LMMS_SRCS core/MixerWorkerThread.cpp core/MixHelpers.cpp core/Model.cpp + core/ModelVisitor.cpp core/Note.cpp core/NotePlayHandle.cpp core/Oscillator.cpp diff --git a/src/core/ModelVisitor.cpp b/src/core/ModelVisitor.cpp new file mode 100644 index 000000000..11a8fc1b1 --- /dev/null +++ b/src/core/ModelVisitor.cpp @@ -0,0 +1,28 @@ +/* + * ModelVisitor.cpp - visitors for automatable models + * + * Copyright (c) 2019-2019 Johannes Lorenz + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include "ModelVisitor.h" + +ModelVisitor::~ModelVisitor() {} +ConstModelVisitor::~ConstModelVisitor() {}