PropertyCommand.hpp
1 #pragma once
2 #include <score/command/Command.hpp>
3 #include <score/model/path/Path.hpp>
4 #include <score/model/path/PathSerialization.hpp>
5 
6 #include <QString>
7 #include <QVariant>
8 
9 namespace score
10 {
20 class SCORE_LIB_BASE_EXPORT PropertyCommand : public Command
21 {
22 public:
23  using Command::Command;
24  PropertyCommand() = default;
25 
26  template <typename T, typename... Args>
27  PropertyCommand(const T& obj, QString property, QVariant newval)
28  : m_path{Path<T>(obj).unsafePath()}
29  , m_property{std::move(property)}
30  , m_old{obj.property(m_property.toUtf8().constData())}
31  , m_new{std::move(newval)}
32  {
33  }
34 
35  ~PropertyCommand() override;
36 
37  void undo(const score::DocumentContext& ctx) const final override;
38  void redo(const score::DocumentContext& ctx) const final override;
39 
40  template <typename Path_T>
41  void update(const Path_T&, QVariant newval)
42  {
43  m_new = std::move(newval);
44  }
45 
46 protected:
47  void serializeImpl(DataStreamInput&) const final override;
48  void deserializeImpl(DataStreamOutput&) final override;
49 
50 private:
51  ObjectPath m_path;
52  QString m_property;
53  QVariant m_old, m_new;
54 };
55 
56 template <typename T>
58 {
59 public:
60  using model_t = typename T::model_type;
61  using param_t = typename T::param_type;
62 
63  template <typename U>
64  struct command;
65 
66  using score::Command::Command;
67  PropertyCommand_T() = default;
68 
69  template <typename U>
70  PropertyCommand_T(const model_t& obj, U&& newval)
71  : m_path{obj}
72  , m_old{(obj.*T::get)()}
73  , m_new{std::forward<U>(newval)}
74  {
75  }
76 
77  ~PropertyCommand_T() override { }
78 
79  template <typename Path_T, typename U>
80  void update(const Path_T&, U&& newval)
81  {
82  m_new = std::forward<U>(newval);
83  }
84 
85  void undo(const score::DocumentContext& ctx) const final override
86  {
87  (m_path.find(ctx).*T::set)(m_old);
88  }
89 
90  void redo(const score::DocumentContext& ctx) const final override
91  {
92  (m_path.find(ctx).*T::set)(m_new);
93  }
94 
95 private:
96  void serializeImpl(DataStreamInput& s) const final override
97  {
98  s << m_path << m_old << m_new;
99  }
100 
101  void deserializeImpl(DataStreamOutput& s) final override
102  {
103  s >> m_path >> m_old >> m_new;
104  }
105 
106  Path<model_t> m_path;
107  param_t m_old, m_new;
108 };
109 
110 template <typename T>
111 struct StaticPropertyCommand : score::PropertyCommand_T<T>::template command<void>::type
112 {
113  using score::PropertyCommand_T<T>::template command<void>::type::type;
114 };
115 }
116 
117 #define PROPERTY_COMMAND_T(NS, Name, Property, Description) \
118  namespace NS \
119  { \
120  class Name : public score::PropertyCommand_T<Property> \
121  { \
122  SCORE_COMMAND_DECL(NS::CommandFactoryName(), Name, Description) \
123  public: \
124  using PropertyCommand_T::PropertyCommand_T; \
125  }; \
126  } \
127  \
128  namespace score \
129  { \
130  template <> \
131  template <> \
132  struct score::PropertyCommand_T<NS::Property>::command<void> \
133  { \
134  using type = NS::Name; \
135  }; \
136  }
The ObjectPath class.
Definition: ObjectPath.hpp:37
The Command class.
Definition: Command.hpp:34
Definition: PropertyCommand.hpp:58
The PropertyCommand class.
Definition: PropertyCommand.hpp:21
Base toolkit upon which the software is built.
Definition: Application.cpp:90
Definition: DataStreamHelpers.hpp:99
Definition: DataStreamHelpers.hpp:103
Definition: DocumentContext.hpp:18
Definition: PropertyCommand.hpp:64
Definition: PropertyCommand.hpp:112