// Copyright (C) 2025 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause #include #ifndef QT_NO_WIDGETS #include #include #include #include #include #include void array() { QListView listView; //! [array] std::array numbers = {1, 2, 3, 4, 5}; QGenericItemModel model(numbers); listView.setModel(&model); //! [array] } void construct_by() { std::vector numbers = {1, 2, 3, 4, 5}; { //! [value] QGenericItemModel model(numbers); //! [value] } { //! [pointer] QGenericItemModel model(&numbers); //! [pointer] } { //! [reference_wrapper] QGenericItemModel model(std::ref(numbers)); //! [reference_wrapper] } { //! [smart_pointer] auto shared_numbers = std::make_shared>(numbers); QGenericItemModel model(shared_numbers); //! [smart_pointer] } } void const_array() { //! [const_array] const std::array numbers = {1, 2, 3, 4, 5}; //! [const_array] QGenericItemModel model(numbers); } void const_values() { //! [const_values] std::array numbers = {1, 2, 3, 4, 5}; //! [const_values] QGenericItemModel model(numbers); } void const_ref() { std::vector numbers = {1, 2, 3, 4, 5}; //! [const_ref] QGenericItemModel model(std::cref(numbers)); //! [const_ref] } void list_of_int() { //! [list_of_int] QList numbers = {1, 2, 3, 4, 5}; QGenericItemModel model(numbers); // columnCount() == 1 QListView listView; listView.setModel(&model); //! [list_of_int] } void grid_of_numbers() { //! [grid_of_numbers] std::vector> gridOfNumbers = { {1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}, {11, 12, 13, 14, 15}, }; QGenericItemModel model(&gridOfNumbers); // columnCount() == 5 QTableView tableView; tableView.setModel(&model); //! [grid_of_numbers] } void pair_int_QString() { //! [pair_int_QString] using TableRow = std::tuple; QList numberNames = { {1, "one"}, {2, "two"}, {3, "three"} }; QGenericItemModel model(&numberNames); // columnCount() == 2 QTableView tableView; tableView.setModel(&model); //! [pair_int_QString] } #if defined(__cpp_concepts) && defined(__cpp_lib_forward_like) //! [tuple_protocol] struct Book { QString title; QString author; QString summary; int rating = 0; template requires ((I <= 3) && std::is_same_v, Book>) friend inline decltype(auto) get(T &&book) { if constexpr (I == 0) return std::as_const(book.title); else if constexpr (I == 1) return std::as_const(book.author); else if constexpr (I == 2) return std::forward_like(book.summary); else if constexpr (I == 3) return std::forward_like(book.rating); } }; namespace std { template <> struct tuple_size : std::integral_constant {}; template struct tuple_element { using type = decltype(get(std::declval())); }; } //! [tuple_protocol] #endif // __cpp_concepts && forward_like namespace gadget { //! [gadget] class Book { Q_GADGET Q_PROPERTY(QString title READ title) Q_PROPERTY(QString author READ author) Q_PROPERTY(QString summary MEMBER m_summary) Q_PROPERTY(int rating READ rating WRITE setRating) public: Book(const QString &title, const QString &author); // C++ rule of 0: destructor, as well as copy/move operations // provided by the compiler. // read-only properties QString title() const { return m_title; } QString author() const { return m_author; } // read/writable property with input validation int rating() const { return m_rating; } void setRating(int rating) { m_rating = qBound(0, rating, 5); } private: QString m_title; QString m_author; QString m_summary; int m_rating = 0; }; //! [gadget] } // namespace gadget namespace tree_protocol { //! [tree_protocol_0] class TreeRow; using Tree = std::vector; //! [tree_protocol_0] //! [tree_protocol_1] class TreeRow { Q_GADGET // properties TreeRow *m_parent; std::optional m_children; public: TreeRow() = default; // rule of 0: copy, move, and destructor implicitly defaulted //! [tree_protocol_1] friend struct TreeTraversal; TreeRow(const QString &) {} //! [tree_protocol_2] // tree traversal protocol implementation const TreeRow *parentRow() const { return m_parent; } const std::optional &childRows() const { return m_children; } //! [tree_protocol_2] //! [tree_protocol_3] void setParentRow(TreeRow *parent) { m_parent = parent; } std::optional &childRows() { return m_children; } //! [tree_protocol_3] //! [tree_protocol_4] // Helper to assembly a tree of rows, not used by QGenericItemModel template TreeRow &addChild(Args &&...args) { if (!m_children) m_children.emplace(Tree{}); auto &child = m_children->emplace_back(std::forward(args)...); child.m_parent = this; return child; } }; //! [tree_protocol_4] void tree_protocol() { //! [tree_protocol_5] Tree tree = { {"..."}, {"..."}, {"..."}, }; // each toplevel row has three children tree[0].addChild("..."); tree[0].addChild("..."); tree[0].addChild("..."); tree[1].addChild("..."); tree[1].addChild("..."); tree[1].addChild("..."); tree[2].addChild("..."); tree[2].addChild("..."); tree[2].addChild("..."); //! [tree_protocol_5] { //! [tree_protocol_6] // instantiate the model with a pointer to the tree, not a copy! QGenericItemModel model(&tree); QTreeView view; view.setModel(&model); //! [tree_protocol_6] } } //! [explicit_tree_protocol_0] struct TreeTraversal { TreeRow newRow() const { return TreeRow{}; } const TreeRow *parentRow(const TreeRow &row) const { return row.m_parent; } void setParentRow(TreeRow &row, TreeRow *parent) const { row.m_parent = parent; } const std::optional &childRows(const TreeRow &row) const { return row.m_children; } std::optional &childRows(TreeRow &row) const { return row.m_children; } }; //! [explicit_tree_protocol_0] void explicit_tree_protocol() { Tree tree; //! [explicit_tree_protocol_1] QGenericItemModel model(&tree, TreeTraversal{}); //! [explicit_tree_protocol_1] } } // namespace tree_protocol namespace tree_of_pointers { //! [tree_of_pointers_0] struct TreeRow; using Tree = std::vector; //! [tree_of_pointers_0] //! [tree_of_pointers_1] struct TreeRow { Q_GADGET public: TreeRow(const QString &value = {}) : m_value(value) {} ~TreeRow() { if (m_children) qDeleteAll(*m_children); } // move-only TreeRow(TreeRow &&) = default; TreeRow &operator=(TreeRow &&) = default; // helper to populate template TreeRow *addChild(Args &&...args) { if (!m_children) m_children.emplace(Tree{}); auto *child = m_children->emplace_back(new TreeRow(std::forward(args)...)); child->m_parent = this; return child; } private: friend struct TreeTraversal; QString m_value; std::optional m_children; TreeRow *m_parent = nullptr; }; //! [tree_of_pointers_1] Tree make_tree_of_pointers() { //! [tree_of_pointers_2] Tree tree = { new TreeRow("1"), new TreeRow("2"), new TreeRow("3"), new TreeRow("4"), }; tree[0]->addChild("1.1"); tree[1]->addChild("2.1"); tree[2]->addChild("3.1")->addChild("3.1.1"); tree[3]->addChild("4.1"); //! [tree_of_pointers_2] return tree; } //! [tree_of_pointers_3] struct TreeTraversal { TreeRow *newRow() const { return new TreeRow; } void deleteRow(TreeRow *row) { delete row; } const TreeRow *parentRow(const TreeRow &row) const { return row.m_parent; } void setParentRow(TreeRow &row, TreeRow *parent) { row.m_parent = parent; } const std::optional &childRows(const TreeRow &row) const { return row.m_children; } std::optional &childRows(TreeRow &row) { return row.m_children; } }; //! [tree_of_pointers_3] //! [tree_of_pointers_4] int main(int argc, char **argv) { QApplication app(argc, argv); Tree tree = make_tree_of_pointers(); QGenericItemModel model(std::move(tree), TreeTraversal{}); QTreeView treeView; treeView.setModel(&model); treeView.show(); return app.exec(); } //! [tree_of_pointers_4] } // namespace tree_of_pointers void color_map() { //! [color_map] using ColorEntry = QMap; const QStringList colorNames = QColor::colorNames(); QList colors; colors.reserve(colorNames.size()); for (const QString &name : colorNames) { const QColor color = QColor::fromString(name); colors << ColorEntry{{Qt::DisplayRole, name}, {Qt::DecorationRole, color}, {Qt::ToolTipRole, color.name()}}; } QGenericItemModel colorModel(colors); QListView list; list.setModel(&colorModel); //! [color_map] } namespace multirole_gadget { //! [color_gadget_0] class ColorEntry { Q_GADGET Q_PROPERTY(QString display MEMBER m_colorName) Q_PROPERTY(QColor decoration READ decoration) Q_PROPERTY(QString toolTip READ toolTip) public: ColorEntry(const QString &color = {}) : m_colorName(color) {} QColor decoration() const { return QColor::fromString(m_colorName); } QString toolTip() const { return QColor::fromString(m_colorName).name(); } private: QString m_colorName; }; //! [color_gadget_0] void color_list() { //! [color_gadget_1] const QStringList colorNames = QColor::colorNames(); QList> colors; colors.reserve(colorNames.size()); for (const QString &name : colorNames) colors << ColorEntry{name}; QGenericItemModel colorModel(colors); QListView list; list.setModel(&colorModel); //! [color_gadget_1] } } // namespace multirole_gadget #endif // QT_NO_WIDGETS