Skip to main content

cxx_qt_lib/core/
qstringlist.rs

1// SPDX-FileCopyrightText: 2023 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
2// SPDX-FileContributor: Andrew Hayzen <andrew.hayzen@kdab.com>
3//
4// SPDX-License-Identifier: MIT OR Apache-2.0
5use crate::{QList, QString};
6use core::mem::MaybeUninit;
7use cxx::{type_id, ExternType};
8use cxx_qt::casting::Upcast;
9use std::fmt;
10use std::ops::{Deref, DerefMut};
11
12#[cxx::bridge]
13mod ffi {
14    #[namespace = "Qt"]
15    unsafe extern "C++" {
16        include!("cxx-qt-lib/qt.h");
17        type CaseSensitivity = crate::CaseSensitivity;
18    }
19
20    unsafe extern "C++" {
21        include!("cxx-qt-lib/qstring.h");
22        type QString = crate::QString;
23
24        include!("cxx-qt-lib/core/qlist/qlist_QString.h");
25        type QList_QString = crate::QList<QString>;
26
27        include!("cxx-qt-lib/qstringlist.h");
28        type QStringList = super::QStringList;
29
30        /// Returns `true` if the list contains the string `str`; otherwise returns `false`.
31        ///
32        /// If `cs` is [`CaseSensitivity::CaseSensitive`], the search is case-sensitive; otherwise the comparison is case-insensitive.
33        fn contains(self: &QStringList, str: &QString, cs: CaseSensitivity) -> bool;
34
35        /// Returns a list of all the strings containing the substring `str`.
36        ///
37        /// If `cs` is [`CaseSensitivity::CaseSensitive`], the search is case-sensitive; otherwise the comparison is case-insensitive.
38        fn filter(self: &QStringList, str: &QString, cs: CaseSensitivity) -> QStringList;
39
40        /// Joins all the string list's strings into a single string with each element
41        /// separated by the given `separator` (which can be an empty string).
42        fn join(self: &QStringList, separator: &QString) -> QString;
43
44        /// Sorts the list of strings in ascending order.
45        ///
46        /// If `cs` is [`CaseSensitivity::CaseSensitive`], the string comparison is case-sensitive; otherwise the comparison is case-insensitive.
47        fn sort(self: &mut QStringList, cs: CaseSensitivity);
48
49        /// Returns a string list where every string has had the `before` text replaced with the `after` text wherever the `before` text is found.
50        ///
51        /// **Note:** If you use an empty `before` argument, the `after` argument will be inserted *before and after* each character of the string.
52        ///
53        /// If `cs` is [`CaseSensitivity::CaseSensitive`], the string comparison is case-sensitive; otherwise the comparison is case-insensitive.
54        #[rust_name = "replace_in_strings"]
55        fn replaceInStrings(
56            self: &mut QStringList,
57            before: &QString,
58            after: &QString,
59            cs: CaseSensitivity,
60        ) -> &mut QStringList;
61    }
62
63    #[namespace = "rust::cxxqt1"]
64    unsafe extern "C++" {
65        include!("cxx-qt/casting.h");
66
67        #[doc(hidden)]
68        #[rust_name = "upcast_qstringlist"]
69        unsafe fn upcastPtr(thiz: *const QStringList) -> *const QList_QString;
70
71        #[doc(hidden)]
72        #[rust_name = "downcast_qlist_qstring"]
73        unsafe fn downcastPtrStatic(base: *const QList_QString) -> *const QStringList;
74    }
75
76    #[namespace = "rust::cxxqtlib1"]
77    unsafe extern "C++" {
78        include!("cxx-qt-lib/common.h");
79
80        #[doc(hidden)]
81        #[rust_name = "qstringlist_clone"]
82        fn construct(list: &QStringList) -> QStringList;
83
84        #[doc(hidden)]
85        #[rust_name = "qstringlist_drop"]
86        fn drop(url: &mut QStringList);
87
88        #[doc(hidden)]
89        #[rust_name = "qstringlist_default"]
90        fn construct() -> QStringList;
91
92        #[doc(hidden)]
93        #[rust_name = "qstringlist_from_qstring"]
94        fn construct(string: &QString) -> QStringList;
95
96        #[doc(hidden)]
97        #[rust_name = "qstringlist_eq"]
98        fn operatorEq(a: &QStringList, b: &QStringList) -> bool;
99
100        #[doc(hidden)]
101        #[rust_name = "qstringlist_to_debug_qstring"]
102        fn toDebugQString(value: &QStringList) -> QString;
103    }
104
105    #[namespace = "rust::cxxqtlib1"]
106    unsafe extern "C++" {
107        #[doc(hidden)]
108        #[rust_name = "qstringlist_from_qlist_qstring"]
109        fn qstringlistFromQListQString(list: &QList_QString) -> QStringList;
110        #[doc(hidden)]
111        #[rust_name = "qstringlist_as_qlist_qstring"]
112        fn qstringlistAsQListQString(list: &QStringList) -> QList_QString;
113        #[doc(hidden)]
114        #[rust_name = "qstringlist_remove_duplicates"]
115        fn qstringlistRemoveDuplicates(list: &mut QStringList) -> isize;
116    }
117}
118
119/// The `QStringList` class provides a list of strings.
120///
121/// Qt Documentation: [QStringList](https://doc.qt.io/qt/qstringlist.html#details)
122#[repr(C)]
123pub struct QStringList {
124    /// The layout has changed between Qt 5 and Qt 6
125    ///
126    /// Qt5 QStringList has one pointer as a member
127    /// Qt6 QStringList has one member, which contains two pointers and a ssize_t
128    _d: MaybeUninit<usize>,
129    #[cfg(cxxqt_qt_version_major = "6")]
130    _ptr: MaybeUninit<usize>,
131    #[cfg(cxxqt_qt_version_major = "6")]
132    _size: MaybeUninit<isize>,
133}
134
135impl QStringList {
136    /// This function removes duplicate entries from a list.
137    /// The entries do not have to be sorted. They will retain their original order.
138    ///
139    /// Returns the number of removed entries.
140    pub fn remove_duplicates(&mut self) -> isize {
141        ffi::qstringlist_remove_duplicates(self)
142    }
143}
144
145impl Clone for QStringList {
146    /// Constructs a copy of other.
147    fn clone(&self) -> Self {
148        ffi::qstringlist_clone(self)
149    }
150}
151
152impl Default for QStringList {
153    /// Constructs an empty list.
154    fn default() -> Self {
155        ffi::qstringlist_default()
156    }
157}
158
159impl std::cmp::PartialEq for QStringList {
160    fn eq(&self, other: &Self) -> bool {
161        ffi::qstringlist_eq(self, other)
162    }
163}
164
165impl std::cmp::Eq for QStringList {}
166
167impl fmt::Display for QStringList {
168    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
169        ffi::qstringlist_to_debug_qstring(self).fmt(f)
170    }
171}
172
173impl fmt::Debug for QStringList {
174    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
175        (**self).fmt(f)
176    }
177}
178
179impl Drop for QStringList {
180    /// Destroys the list.
181    fn drop(&mut self) {
182        ffi::qstringlist_drop(self);
183    }
184}
185
186impl From<&QString> for QStringList {
187    /// Constructs a string list that contains the given string.
188    fn from(string: &QString) -> Self {
189        ffi::qstringlist_from_qstring(string)
190    }
191}
192
193impl From<&QList<QString>> for QStringList {
194    /// Converts a `QList<QString>` into `QStringList`.
195    fn from(list: &QList<QString>) -> Self {
196        ffi::qstringlist_from_qlist_qstring(list)
197    }
198}
199
200impl From<&QStringList> for QList<QString> {
201    /// Converts a `QStringList` into a `QList<QString>`.
202    fn from(list: &QStringList) -> Self {
203        ffi::qstringlist_as_qlist_qstring(list)
204    }
205}
206
207impl<'a> FromIterator<&'a QString> for QStringList {
208    fn from_iter<I: IntoIterator<Item = &'a QString>>(iter: I) -> Self {
209        let mut qstringlist = Self::default();
210        qstringlist.extend(iter);
211        qstringlist
212    }
213}
214
215impl FromIterator<QString> for QStringList {
216    fn from_iter<I: IntoIterator<Item = QString>>(iter: I) -> Self {
217        let mut qstringlist = Self::default();
218        qstringlist.extend(iter);
219        qstringlist
220    }
221}
222
223impl Deref for QStringList {
224    type Target = QList<QString>;
225
226    fn deref(&self) -> &Self::Target {
227        self.upcast()
228    }
229}
230
231impl DerefMut for QStringList {
232    fn deref_mut(&mut self) -> &mut Self::Target {
233        self.upcast_mut()
234    }
235}
236
237unsafe impl Upcast<QList<QString>> for QStringList {
238    unsafe fn upcast_ptr(this: *const Self) -> *const QList<QString> {
239        ffi::upcast_qstringlist(this)
240    }
241
242    unsafe fn from_base_ptr(base: *const QList<QString>) -> *const Self {
243        ffi::downcast_qlist_qstring(base)
244    }
245}
246
247// Safety:
248//
249// Static checks on the C++ side to ensure the size is the same.
250unsafe impl ExternType for QStringList {
251    type Id = type_id!("QStringList");
252    type Kind = cxx::kind::Trivial;
253}
254
255#[cfg(test)]
256mod test {
257    use super::*;
258
259    #[test]
260    fn deref() {
261        let mut list = QStringList::default();
262        list.append(QString::from("element"));
263        assert_eq!(list.get(0).map(String::from).as_deref(), Some("element"));
264    }
265
266    #[cfg(feature = "serde")]
267    #[test]
268    fn qstringlist_serde() {
269        let mut qstringlist = QStringList::default();
270        qstringlist.append(QString::from("element 1"));
271        qstringlist.append(QString::from("element 2"));
272        assert_eq!(crate::serde_impl::roundtrip(&qstringlist), qstringlist)
273    }
274}