1 /*
2 Scan Tailor - Interactive post-processing tool for scanned pages.
3 Copyright (C) 2007-2009 Joseph Artsimovich <joseph_a@mail.ru>
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #ifndef PROPERTY_SET_H_
20 #define PROPERTY_SET_H_
21
22 #include <vector>
23 #include "Property.h"
24 #include "intrusive_ptr.h"
25 #include "ref_countable.h"
26
27 class PropertyFactory;
28 class QDomDocument;
29 class QDomElement;
30 class QString;
31
32 class PropertySet : public ref_countable {
33 public:
34 PropertySet() = default;
35
36 /**
37 * \brief Makes a deep copy of another property set.
38 */
39 PropertySet(const PropertySet& other);
40
41 PropertySet(const QDomElement& el, const PropertyFactory& factory);
42
43 /**
44 * \brief Makes a deep copy of another property set.
45 */
46 PropertySet& operator=(const PropertySet& other);
47
48 void swap(PropertySet& other);
49
50 QDomElement toXml(QDomDocument& doc, const QString& name) const;
51
52 /**
53 * Returns a property stored in this set, if one having a suitable
54 * type is found, or returns a null smart pointer otherwise.
55 */
56 template <typename T>
57 intrusive_ptr<T> locate();
58
59 template <typename T>
60 intrusive_ptr<const T> locate() const;
61
62 /**
63 * Returns a property stored in this set, if one having a suitable
64 * type is found, or returns a default constructed object otherwise.
65 */
66 template <typename T>
67 intrusive_ptr<T> locateOrDefault();
68
69 template <typename T>
70 intrusive_ptr<const T> locateOrDefault() const;
71
72 /**
73 * Returns a property stored in this set, if one having a suitable
74 * type is found. Otherwise, a default constructed object is put
75 * to the set and then returned.
76 */
77 template <typename T>
78 intrusive_ptr<T> locateOrCreate();
79
80 private:
81 typedef std::vector<intrusive_ptr<Property>> PropList;
82 PropList m_props;
83 };
84
85
86 template <typename T>
locate()87 intrusive_ptr<T> PropertySet::locate() {
88 auto it(m_props.begin());
89 const auto end(m_props.end());
90 for (; it != end; ++it) {
91 if (T* obj = dynamic_cast<T*>(it->get())) {
92 return intrusive_ptr<T>(obj);
93 }
94 }
95
96 return nullptr;
97 }
98
99 template <typename T>
locate()100 intrusive_ptr<const T> PropertySet::locate() const {
101 auto it(m_props.begin());
102 const auto end(m_props.end());
103 for (; it != end; ++it) {
104 if (const T* obj = dynamic_cast<const T*>(it->get())) {
105 return intrusive_ptr<const T>(obj);
106 }
107 }
108
109 return nullptr;
110 }
111
112 template <typename T>
locateOrDefault()113 intrusive_ptr<T> PropertySet::locateOrDefault() {
114 intrusive_ptr<T> obj(locate<T>());
115 if (!obj) {
116 obj.reset(new T);
117 }
118
119 return obj;
120 }
121
122 template <typename T>
locateOrDefault()123 intrusive_ptr<const T> PropertySet::locateOrDefault() const {
124 intrusive_ptr<const T> obj(locate<T>());
125 if (!obj) {
126 obj.reset(new T);
127 }
128
129 return obj;
130 }
131
132 template <typename T>
locateOrCreate()133 intrusive_ptr<T> PropertySet::locateOrCreate() {
134 intrusive_ptr<T> obj(locate<T>());
135 if (!obj) {
136 obj.reset(new T);
137 m_props.push_back(obj);
138 }
139
140 return obj;
141 }
142
swap(PropertySet & o1,PropertySet & o2)143 inline void swap(PropertySet& o1, PropertySet& o2) {
144 o1.swap(o2);
145 }
146
147 #endif // ifndef PROPERTY_SET_H_
148