1 /* 2 * %injeqt copyright begin% 3 * Copyright 2014 Rafał Malinowski (rafal.przemyslaw.malinowski@gmail.com) 4 * %injeqt copyright end% 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20 21 #pragma once 22 23 #include <injeqt/exception/exception.h> 24 #include <injeqt/injeqt.h> 25 #include <injeqt/type.h> 26 27 #include "internal.h" 28 #include "types-by-name.h" 29 30 #include <QtCore/QMetaMethod> 31 32 /** 33 * @file 34 * @brief Contains classes and functions for representing setter methods. 35 */ 36 37 namespace injeqt { namespace internal { 38 39 /** 40 * @brief Abstraction of setter method. 41 * 42 * This class is used for defining setter based dependencies and for invoking these setter methods 43 * to resolve dependencies. Setter method is crated from Qt type QMetaMethod. As Qt only creates QMetaMethod 44 * objects for slots, signals and all methods marked with Q_INVOKABLE tag and Injeqt requires 45 * all its setter methods to be tagged with INJEQT_SET - setter method must be a slot. This method should return 46 * void is allowed to have only one parameter of pointer to type inherited from QObject. This type must 47 * be also configured in one of module to be able to be resolved. 48 * 49 * Example of valid setter method: 50 * 51 * class set_object : public QObject 52 * { 53 * Q_OBJECT 54 * }; 55 * 56 * class with_setter : public QObject 57 * { 58 * Q_OBJECT 59 * public slots: 60 * INJEQT_SET void setter(set_object *obj) { ... } 61 * }; 62 * 63 * Object with setter method must not take ownership of passed object. 64 */ 65 class INJEQT_INTERNAL_API setter_method final 66 { 67 68 public: 69 static bool is_setter_tag(const std::string &tag); 70 71 static bool validate_setter_method(type parameter_type, const QMetaMethod &meta_method); 72 73 /** 74 * @brief Create empty setter_method. 75 */ 76 setter_method(); 77 78 /** 79 * @brief Create object from QMetaMethod definition. 80 * @param parameter_type Type of parameter of setter @p meta_method 81 * @param meta_method Qt meta method that should be a setter method 82 * @note Qt QMetaType system limitations with plugins disallow use of QMetaType to retreive parameter type from QMetaMethod. 83 * @pre meta_method.methodType() == QMetaMethod::Slot 84 * @pre meta_method.parameterCount() == 1 85 * @pre meta_method.enclosingMetaObject() != nullptr 86 * @pre !parameter_type.is_empty() 87 * @pre parameter_type.name() + "*" == std::string{meta_method.parameterTypes()[0].data()} 88 */ 89 explicit setter_method(type parameter_type, QMetaMethod meta_method); 90 91 /** 92 * @return true if setter_method is empty and does not represent valie setter method 93 */ 94 bool is_empty() const; 95 96 /** 97 * @return Type of objects that owns this setter method. 98 * 99 * May return invalid type if QMetaMethod passed in constructor was invalid. 100 */ 101 const type & object_type() const; 102 103 /** 104 * @return Type of objects parameter accepted by setter method. 105 * 106 * May return invalid type if QMetaMethod passed in constructor was invalid. 107 */ 108 const type & parameter_type() const; 109 110 /** 111 * @return Qt representation of setter method. 112 * 113 * May return empty value if QMetaMethod passed in constructor was invalid. 114 */ 115 const QMetaMethod & meta_method() const; 116 117 /** 118 * @return String signature of setter method. 119 * 120 * May return empty value if QMetaMethod passed in constructor was invalid. 121 */ 122 std::string signature() const; 123 124 /** 125 * @param on object to call this method on 126 * @param parameter parmeter to be passed in invocation 127 * @return true if invoke was successfull 128 * @pre !is_empty() 129 * @pre on != nullptr 130 * @pre type{on->metaObject()} == object_type() 131 * @pre parameter != nullptr 132 * @pre !type{parameter->metaObject()}.is_empty() 133 * @pre implements(type{parameter->metaObject()}, _parameter_type) 134 * 135 * This method can be only called on valid objects with @p on parameter being 136 * the same type as object_type() returns and @p parameter of type that implements parameter_type(). 137 * 138 * Calling this on invalid object with result in undefined behavior. 139 */ 140 bool invoke(QObject *on, QObject *parameter) const; 141 142 private: 143 type _object_type; 144 type _parameter_type; 145 QMetaMethod _meta_method; 146 147 }; 148 149 INJEQT_INTERNAL_API bool operator == (const setter_method &x, const setter_method &y); 150 INJEQT_INTERNAL_API bool operator != (const setter_method &x, const setter_method &y); 151 INJEQT_INTERNAL_API bool operator < (const setter_method &x, const setter_method &y); 152 INJEQT_INTERNAL_API bool operator > (const setter_method &x, const setter_method &y); 153 INJEQT_INTERNAL_API bool operator <= (const setter_method &x, const setter_method &y); 154 INJEQT_INTERNAL_API bool operator >= (const setter_method &x, const setter_method &y); 155 156 INJEQT_INTERNAL_API setter_method make_setter_method(const types_by_name &known_types, const QMetaMethod &meta_method); 157 158 }} 159