1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the QtQml module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or (at your option) the GNU General |
28 | ** Public license version 3 or any later version approved by the KDE Free |
29 | ** Qt Foundation. The licenses are as published by the Free Software |
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | ** included in the packaging of this file. Please review the following |
32 | ** information to ensure the GNU General Public License requirements will |
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | ** |
36 | ** $QT_END_LICENSE$ |
37 | ** |
38 | ****************************************************************************/ |
39 | |
40 | #include "qquickpackage_p.h" |
41 | |
42 | #include <private/qobject_p.h> |
43 | #include <private/qqmlguard_p.h> |
44 | |
45 | QT_BEGIN_NAMESPACE |
46 | |
47 | /*! |
48 | \qmltype Package |
49 | \instantiates QQuickPackage |
50 | \inqmlmodule QtQml.Models |
51 | \ingroup qtquick-models |
52 | \brief Specifies a collection of named items. |
53 | |
54 | The Package type is used in conjunction with |
55 | DelegateModel to enable delegates with a shared context |
56 | to be provided to multiple views. |
57 | |
58 | Any item within a Package may be assigned a name via the |
59 | \l{Package::name}{Package.name} attached property. |
60 | |
61 | The example below creates a Package containing two named items; |
62 | \e list and \e grid. The third item in the package (the \l Rectangle) is parented to whichever |
63 | delegate it should appear in. This allows an item to move |
64 | between views. |
65 | |
66 | \snippet package/Delegate.qml 0 |
67 | |
68 | These named items are used as the delegates by the two views who |
69 | reference the special \l{DelegateModel::parts} property to select |
70 | a model which provides the chosen delegate. |
71 | |
72 | \snippet package/view.qml 0 |
73 | |
74 | \note Package is part of QtQml.Models since version 2.14 and part of QtQuick since version 2.0. |
75 | Importing Package via QtQuick is deprecated since Qt 5.14. |
76 | |
77 | \sa {Qt Quick Examples - Views}, {Qt Quick Demo - Photo Viewer}, {Qt QML} |
78 | */ |
79 | |
80 | /*! |
81 | \qmlattachedproperty string QtQuick::Package::name |
82 | This attached property holds the name of an item within a Package. |
83 | */ |
84 | |
85 | |
86 | class QQuickPackagePrivate : public QObjectPrivate |
87 | { |
88 | public: |
89 | QQuickPackagePrivate() {} |
90 | |
91 | struct DataGuard : public QQmlGuard<QObject> |
92 | { |
93 | DataGuard(QObject *obj, QList<DataGuard> *l) : list(l) { (QQmlGuard<QObject>&)*this = obj; } |
94 | QList<DataGuard> *list; |
95 | void objectDestroyed(QObject *) override { |
96 | // we assume priv will always be destroyed after objectDestroyed calls |
97 | list->removeOne(t: *this); |
98 | } |
99 | }; |
100 | |
101 | QList<DataGuard> dataList; |
102 | static void data_append(QQmlListProperty<QObject> *prop, QObject *o) { |
103 | QList<DataGuard> *list = static_cast<QList<DataGuard> *>(prop->data); |
104 | list->append(t: DataGuard(o, list)); |
105 | } |
106 | static void data_clear(QQmlListProperty<QObject> *prop) { |
107 | QList<DataGuard> *list = static_cast<QList<DataGuard> *>(prop->data); |
108 | list->clear(); |
109 | } |
110 | static QObject *data_at(QQmlListProperty<QObject> *prop, int index) { |
111 | QList<DataGuard> *list = static_cast<QList<DataGuard> *>(prop->data); |
112 | return list->at(i: index); |
113 | } |
114 | static int data_count(QQmlListProperty<QObject> *prop) { |
115 | QList<DataGuard> *list = static_cast<QList<DataGuard> *>(prop->data); |
116 | return list->count(); |
117 | } |
118 | static void data_replace(QQmlListProperty<QObject> *prop, int index, QObject *o) { |
119 | QList<DataGuard> *list = static_cast<QList<DataGuard> *>(prop->data); |
120 | list->replace(i: index, t: DataGuard(o, list)); |
121 | } |
122 | static void data_removeLast(QQmlListProperty<QObject> *prop) { |
123 | QList<DataGuard> *list = static_cast<QList<DataGuard> *>(prop->data); |
124 | list->removeLast(); |
125 | } |
126 | }; |
127 | |
128 | QHash<QObject *, QQuickPackageAttached *> QQuickPackageAttached::attached; |
129 | |
130 | QQuickPackageAttached::QQuickPackageAttached(QObject *parent) |
131 | : QObject(parent) |
132 | { |
133 | attached.insert(key: parent, value: this); |
134 | } |
135 | |
136 | QQuickPackageAttached::~QQuickPackageAttached() |
137 | { |
138 | attached.remove(key: parent()); |
139 | } |
140 | |
141 | QString QQuickPackageAttached::name() const |
142 | { |
143 | return _name; |
144 | } |
145 | |
146 | void QQuickPackageAttached::setName(const QString &n) |
147 | { |
148 | _name = n; |
149 | } |
150 | |
151 | QQuickPackage::QQuickPackage(QObject *parent) |
152 | : QObject(*(new QQuickPackagePrivate), parent) |
153 | { |
154 | } |
155 | |
156 | QQuickPackage::~QQuickPackage() |
157 | { |
158 | } |
159 | |
160 | QQmlListProperty<QObject> QQuickPackage::data() |
161 | { |
162 | Q_D(QQuickPackage); |
163 | return QQmlListProperty<QObject>(this, &d->dataList, |
164 | QQuickPackagePrivate::data_append, |
165 | QQuickPackagePrivate::data_count, |
166 | QQuickPackagePrivate::data_at, |
167 | QQuickPackagePrivate::data_clear, |
168 | QQuickPackagePrivate::data_replace, |
169 | QQuickPackagePrivate::data_removeLast); |
170 | } |
171 | |
172 | bool QQuickPackage::hasPart(const QString &name) |
173 | { |
174 | Q_D(QQuickPackage); |
175 | for (int ii = 0; ii < d->dataList.count(); ++ii) { |
176 | QObject *obj = d->dataList.at(i: ii); |
177 | QQuickPackageAttached *a = QQuickPackageAttached::attached.value(key: obj); |
178 | if (a && a->name() == name) |
179 | return true; |
180 | } |
181 | return false; |
182 | } |
183 | |
184 | QObject *QQuickPackage::part(const QString &name) |
185 | { |
186 | Q_D(QQuickPackage); |
187 | if (name.isEmpty() && !d->dataList.isEmpty()) |
188 | return d->dataList.at(i: 0); |
189 | |
190 | for (int ii = 0; ii < d->dataList.count(); ++ii) { |
191 | QObject *obj = d->dataList.at(i: ii); |
192 | QQuickPackageAttached *a = QQuickPackageAttached::attached.value(key: obj); |
193 | if (a && a->name() == name) |
194 | return obj; |
195 | } |
196 | |
197 | if (name == QLatin1String("default" ) && !d->dataList.isEmpty()) |
198 | return d->dataList.at(i: 0); |
199 | |
200 | return nullptr; |
201 | } |
202 | |
203 | QQuickPackageAttached *QQuickPackage::qmlAttachedProperties(QObject *o) |
204 | { |
205 | return new QQuickPackageAttached(o); |
206 | } |
207 | |
208 | |
209 | |
210 | QT_END_NAMESPACE |
211 | |
212 | #include "moc_qquickpackage_p.cpp" |
213 | |