1#[cfg(feature = "qt_gui")]
7use crate::QColor;
8#[cfg(not(target_os = "emscripten"))]
9use crate::QDateTime;
10use crate::{
11 QByteArray, QDate, QLine, QLineF, QMargins, QMarginsF, QPersistentModelIndex, QPoint, QPointF,
12 QRect, QRectF, QSize, QSizeF, QString, QTime, QUrl, QVariant,
13};
14use core::{marker::PhantomData, mem::MaybeUninit};
15use cxx::{type_id, ExternType};
16
17#[repr(C)]
21pub struct QList<T>
22where
23 T: QListElement,
24{
25 #[cfg(cxxqt_qt_version_major = "5")]
30 _space: MaybeUninit<usize>,
31 #[cfg(cxxqt_qt_version_major = "6")]
32 _space: MaybeUninit<[usize; 3]>,
33 _value: PhantomData<T>,
34}
35
36impl<T> Clone for QList<T>
37where
38 T: QListElement,
39{
40 fn clone(&self) -> Self {
42 T::clone(self)
43 }
44}
45
46impl<T> Default for QList<T>
47where
48 T: QListElement,
49{
50 fn default() -> Self {
52 T::default()
53 }
54}
55
56impl<T> Drop for QList<T>
57where
58 T: QListElement,
59{
60 fn drop(&mut self) {
62 T::drop(self);
63 }
64}
65
66impl<T> PartialEq for QList<T>
67where
68 T: QListElement + PartialEq,
69{
70 fn eq(&self, other: &Self) -> bool {
72 self.len() == other.len() && self.iter().zip(other.iter()).all(|(a, b)| a == b)
73 }
74}
75
76impl<T> Eq for QList<T> where T: QListElement + Eq {}
77
78impl<T> QList<T>
79where
80 T: QListElement,
81{
82 pub fn append_clone(&mut self, value: &T) {
87 T::append_clone(self, value);
88 }
89
90 pub fn clear(&mut self) {
92 T::clear(self);
93 }
94
95 pub fn contains(&self, value: &T) -> bool {
97 T::contains(self, value)
98 }
99
100 pub fn get(&self, index: isize) -> Option<&T> {
104 if index >= 0 && index < self.len() {
105 Some(unsafe { T::get_unchecked(self, index) })
106 } else {
107 None
108 }
109 }
110
111 pub fn index_of(&self, value: &T) -> isize {
114 T::index_of(self, value)
115 }
116
117 pub fn insert_clone(&mut self, pos: isize, value: &T) {
122 T::insert_clone(self, pos, value);
123 }
124
125 pub fn is_empty(&self) -> bool {
127 T::len(self) == 0
128 }
129
130 pub fn iter(&self) -> Iter<'_, T> {
133 Iter {
134 list: self,
135 index: 0,
136 }
137 }
138
139 pub fn len(&self) -> isize {
141 T::len(self)
142 }
143
144 pub fn remove(&mut self, pos: isize) {
146 T::remove(self, pos);
147 }
148
149 pub fn reserve(&mut self, size: isize) {
152 T::reserve(self, size);
153 }
154}
155
156impl<T> From<&QList<T>> for Vec<T>
157where
158 T: QListElement + Clone,
159{
160 fn from(qlist: &QList<T>) -> Self {
163 let mut vec = Vec::with_capacity(qlist.len().try_into().unwrap());
164 for element in qlist.iter() {
165 vec.push(element.clone());
166 }
167 vec
168 }
169}
170
171impl<T, S> From<S> for QList<T>
172where
173 T: QListElement + Clone,
174 S: AsRef<[T]>,
175{
176 fn from(vec: S) -> Self {
180 let mut qlist = Self::default();
181 qlist.reserve(vec.as_ref().len().try_into().unwrap());
182 for element in vec.as_ref() {
183 qlist.append_clone(element);
184 }
185 qlist
186 }
187}
188
189impl<T> QList<T>
190where
191 T: QListElement + ExternType<Kind = cxx::kind::Trivial>,
192{
193 pub fn append(&mut self, value: T) {
195 T::append(self, value);
196 }
197
198 pub fn insert(&mut self, pos: isize, value: T) {
200 T::insert(self, pos, value);
201 }
202}
203
204unsafe impl<T> ExternType for QList<T>
205where
206 T: ExternType + QListElement,
207{
208 type Id = T::TypeId;
209 type Kind = cxx::kind::Trivial;
210}
211
212pub struct Iter<'a, T>
213where
214 T: QListElement,
215{
216 list: &'a QList<T>,
217 index: isize,
218}
219
220impl<'a, T> Iterator for Iter<'a, T>
221where
222 T: QListElement,
223{
224 type Item = &'a T;
225
226 fn next(&mut self) -> Option<Self::Item> {
227 if self.index < self.list.len() {
228 let next = unsafe { T::get_unchecked(self.list, self.index) };
229 self.index += 1;
230 Some(next)
231 } else {
232 None
233 }
234 }
235
236 fn size_hint(&self) -> (usize, Option<usize>) {
237 let len = self.len();
238 (len, Some(len))
239 }
240}
241
242impl<T> ExactSizeIterator for Iter<'_, T>
243where
244 T: QListElement,
245{
246 fn len(&self) -> usize {
247 (self.list.len() - self.index) as usize
248 }
249}
250
251pub trait QListElement: Sized {
253 type TypeId;
254
255 fn append(list: &mut QList<Self>, value: Self)
256 where
257 Self: ExternType<Kind = cxx::kind::Trivial>;
258 fn append_clone(list: &mut QList<Self>, value: &Self);
259 fn clear(list: &mut QList<Self>);
260 fn clone(list: &QList<Self>) -> QList<Self>;
261 fn contains(list: &QList<Self>, value: &Self) -> bool;
262 fn default() -> QList<Self>;
263 fn drop(list: &mut QList<Self>);
264 unsafe fn get_unchecked(list: &QList<Self>, pos: isize) -> &Self;
269 fn index_of(list: &QList<Self>, value: &Self) -> isize;
270 fn insert(list: &mut QList<Self>, pos: isize, value: Self)
271 where
272 Self: ExternType<Kind = cxx::kind::Trivial>;
273 fn insert_clone(list: &mut QList<Self>, pos: isize, value: &Self);
274 fn len(list: &QList<Self>) -> isize;
275 fn remove(list: &mut QList<Self>, pos: isize);
276 fn reserve(vector: &mut QList<Self>, size: isize);
277}
278
279macro_rules! impl_qlist_element {
280 ( $typeName:ty, $module:ident, $typeId:literal ) => {
281 mod $module;
282
283 impl QListElement for $typeName {
284 type TypeId = type_id!($typeId);
285
286 fn append(list: &mut QList<Self>, value: Self) {
287 $module::append(list, &value);
288 }
289
290 fn append_clone(list: &mut QList<Self>, value: &Self) {
291 $module::append(list, value);
292 }
293
294 fn clear(list: &mut QList<Self>) {
295 list.cxx_clear()
296 }
297
298 fn clone(list: &QList<Self>) -> QList<Self> {
299 $module::clone(list)
300 }
301
302 fn contains(list: &QList<Self>, value: &Self) -> bool {
303 list.cxx_contains(value)
304 }
305
306 fn default() -> QList<Self> {
307 $module::default()
308 }
309
310 fn drop(list: &mut QList<Self>) {
311 $module::drop(list);
312 }
313
314 unsafe fn get_unchecked(list: &QList<Self>, pos: isize) -> &Self {
315 $module::get_unchecked(list, pos)
316 }
317
318 fn index_of(list: &QList<Self>, value: &Self) -> isize {
319 $module::index_of(list, value)
320 }
321
322 fn insert(list: &mut QList<Self>, pos: isize, value: Self) {
323 $module::insert(list, pos, &value);
324 }
325
326 fn insert_clone(list: &mut QList<Self>, pos: isize, value: &Self) {
327 $module::insert(list, pos, value);
328 }
329
330 fn len(list: &QList<Self>) -> isize {
331 $module::len(list)
332 }
333
334 fn remove(list: &mut QList<Self>, pos: isize) {
335 $module::remove(list, pos);
336 }
337
338 fn reserve(list: &mut QList<Self>, size: isize) {
339 $module::reserve(list, size);
340 }
341 }
342 };
343}
344
345impl_qlist_element!(bool, qlist_bool, "QList_bool");
346impl_qlist_element!(f32, qlist_f32, "QList_f32");
347impl_qlist_element!(f64, qlist_f64, "QList_f64");
348impl_qlist_element!(i8, qlist_i8, "QList_i8");
349impl_qlist_element!(i16, qlist_i16, "QList_i16");
350impl_qlist_element!(i32, qlist_i32, "QList_i32");
351impl_qlist_element!(i64, qlist_i64, "QList_i64");
352impl_qlist_element!(QByteArray, qlist_qbytearray, "QList_QByteArray");
353#[cfg(feature = "qt_gui")]
354impl_qlist_element!(QColor, qlist_qcolor, "QList_QColor");
355impl_qlist_element!(QDate, qlist_qdate, "QList_QDate");
356#[cfg(not(target_os = "emscripten"))]
357impl_qlist_element!(QDateTime, qlist_qdatetime, "QList_QDateTime");
358impl_qlist_element!(QLine, qlist_qline, "QList_QLine");
359impl_qlist_element!(QLineF, qlist_qlinef, "QList_QLineF");
360impl_qlist_element!(QMargins, qlist_qmargins, "QList_QMargins");
361impl_qlist_element!(QMarginsF, qlist_qmarginsf, "QList_QMarginsF");
362impl_qlist_element!(
363 QPersistentModelIndex,
364 qlist_qpersistentmodelindex,
365 "QList_QPersistentModelIndex"
366);
367impl_qlist_element!(QPoint, qlist_qpoint, "QList_QPoint");
368impl_qlist_element!(QPointF, qlist_qpointf, "QList_QPointF");
369impl_qlist_element!(QRect, qlist_qrect, "QList_QRect");
370impl_qlist_element!(QRectF, qlist_qrectf, "QList_QRectF");
371impl_qlist_element!(QSize, qlist_qsize, "QList_QSize");
372impl_qlist_element!(QSizeF, qlist_qsizef, "QList_QSizeF");
373impl_qlist_element!(QString, qlist_qstring, "QList_QString");
374impl_qlist_element!(QTime, qlist_qtime, "QList_QTime");
375impl_qlist_element!(QUrl, qlist_qurl, "QList_QUrl");
376impl_qlist_element!(QVariant, qlist_qvariant, "QList_QVariant");
377impl_qlist_element!(u8, qlist_u8, "QList_u8");
378impl_qlist_element!(u16, qlist_u16, "QList_u16");
379impl_qlist_element!(u32, qlist_u32, "QList_u32");
380impl_qlist_element!(u64, qlist_u64, "QList_u64");
381
382#[cfg(test)]
383mod test {
384 use super::*;
385
386 #[test]
387 fn qlist_from_array_to_vec() {
388 let array = [0, 1, 2];
389 let qlist = QList::<u8>::from(array);
390 assert_eq!(Vec::from(&qlist), array);
391 }
392}