// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only

/*!
    \example itemviews/simpletreemodel
    \title Simple Tree Model Example
    \examplecategory {User Interface Components}
    \ingroup examples-itemviews
    \ingroup examples-layout
    \brief The Simple Tree Model example shows how to use a hierarchical model
    with Qt's standard view classes.

    \brief The Simple Tree Model example shows how to create a basic, read-only
    hierarchical model to use with Qt's standard view classes. For a
    description of simple non-hierarchical list and table models, see the
    \l{Model/View Programming} overview.

    \image simpletreemodel-example.png

    Qt's model/view architecture provides a standard way for views to
    manipulate information in a data source, using an abstract model
    of the data to simplify and standardize the way it is accessed.
    Simple models represent data as a table of items, and allow views
    to access this data via an
    \l{Model/View Programming#Models}{index-based} system. More generally,
    models can be used to represent data in the form of a tree structure
    by allowing each item to act as a parent to a table of child items.

    Before attempting to implement a tree model, it is worth considering whether
    the data is supplied by an external source, or whether it is going to be
    maintained within the model itself. In this example, we will implement an
    internal structure to hold data rather than discuss how to package data from
    an external source.

    \section1 Design and Concepts

    The data structure that we use to represent the structure of the data takes
    the form of a tree built from \c TreeItem objects. Each \c TreeItem
    represents an item in a tree view, and contains several columns of data.

    \target SimpleTreeModelStructure
    \table
    \row \li \inlineimage treemodel-structure.png
    \li \b{Simple Tree Model Structure}

    The data is stored internally in the model using \c TreeItem objects that
    are linked together in a pointer-based tree structure. Generally, each
    \c TreeItem has a parent item, and can have a number of child items.
    However, the root item in the tree structure has no parent item and it
    is never referenced outside the model.

    Each \c TreeItem contains information about its place in the tree
    structure; it can return its parent item and its row number. Having
    this information readily available makes implementing the model easier.

    Since each item in a tree view usually contains several columns of data
    (a title and a summary in this example), it is natural to store this
    information in each item. For simplicity, we will use a list of QVariant
    objects to store the data for each column in the item.
    \endtable

    The use of a pointer-based tree structure means that, when passing a
    model index to a view, we can record the address of the corresponding
    item in the index (see QAbstractItemModel::createIndex()) and retrieve
    it later with QModelIndex::internalPointer(). This makes writing the
    model easier and ensures that all model indexes that refer to the same
    item have the same internal data pointer.

    With the appropriate data structure in place, we can create a tree model
    with a minimal amount of extra code to supply model indexes and data to
    other components.

    \section1 TreeItem Class Definition

    The \c TreeItem class is defined as follows:

    \snippet itemviews/simpletreemodel/treeitem.h 0

    The class is a basic C++ class. It does not inherit from QObject or
    provide signals and slots. It is used to hold a list of QVariants,
    containing column data, and information about its position in the tree
    structure. The functions provide the following features:

    \list
    \li The \c appendChildItem() is used to add data when the model is first
       constructed and is not used during normal use.
    \li The \c child() and \c childCount() functions allow the model to obtain
       information about any child items.
    \li Information about the number of columns associated with the item is
       provided by \c columnCount(), and the data in each column can be
       obtained with the data() function.
    \li The \c row() and \c parent() functions are used to obtain the item's
       row number and parent item.
    \endlist

    The parent item and column data are stored in the \c parentItem and
    \c itemData private member variables. The \c childItems variable contains
    a list of pointers to the item's own child items.

    \section1 TreeItem Class Implementation

    The constructor is only used to record the item's parent and the data
    associated with each column.

    \snippet itemviews/simpletreemodel/treeitem.cpp 0

    A pointer to each of the child items belonging to this item will be
    stored in the \c childItems private member variable as an std::unique_ptr.
    When the class's destructor is called, the child items will be automatically
    deleted to ensure that their memory is reused:

    Since each of the child items are constructed when the model is initially
    populated with data, the function to add child items is straightforward:

    \snippet itemviews/simpletreemodel/treeitem.cpp 1

    Each item is able to return any of its child items when given a suitable
    row number. For example, in the \l{#SimpleTreeModelStructure}{above diagram},
    the item marked with the letter "A" corresponds to the child of the root item
    with \c{row = 0}, the "B" item is a child of the "A" item with \c{row = 1},
    and the "C" item is a child of the root item with \c{row = 1}.

    The \c child() function returns the child that corresponds to
    the specified row number in the item's list of child items:

    \snippet itemviews/simpletreemodel/treeitem.cpp 2

    The number of child items held can be found with \c childCount():

    \snippet itemviews/simpletreemodel/treeitem.cpp 3

    The \c TreeModel uses this function to determine the number of rows that
    exist for a given parent item.

    The \c row() function reports the item's location within its parent's
    list of items:

    \snippet itemviews/simpletreemodel/treeitem.cpp 7

    Note that, although the root item (with no parent item) is automatically
    assigned a row number of 0, this information is never used by the model.

    The number of columns of data in the item is trivially returned by the
    \c columnCount() function.

    \snippet itemviews/simpletreemodel/treeitem.cpp 4

    Column data is returned by the \c data() function. We use
    the QList::value() convenience function which checks the bounds
    and returns a default-constructed QVariant in case they are violated:

    \snippet itemviews/simpletreemodel/treeitem.cpp 5

    The item's parent is found with \c parent():

    \snippet itemviews/simpletreemodel/treeitem.cpp 6

    Note that, since the root item in the model will not have a parent, this
    function will return zero in that case. We need to ensure that the model
    handles this case correctly when we implement the \c TreeModel::parent()
    function.

    \section1 TreeModel Class Definition

    The \c TreeModel class is defined as follows:

    \snippet itemviews/simpletreemodel/treemodel.h 0

    This class is similar to most other subclasses of QAbstractItemModel that
    provide read-only models. Only the form of the constructor and the
    \c setupModelData() function are specific to this model. In addition, we
    provide a destructor to clean up when the model is destroyed.

    \section1 TreeModel Class Implementation

    For simplicity, the model does not allow its data to be edited. As a
    result, the constructor takes an argument containing the data that the
    model will share with views and delegates:

    \snippet itemviews/simpletreemodel/treemodel.cpp 0

    It is up to the constructor to create a root item for the model. This
    item only contains vertical header data for convenience. We also use it
    to reference the internal data structure that contains the model data,
    and it is used to represent an imaginary parent of top-level items in
    the model. The root item is managed with a std::unique_ptr to ensure the
    entire tree of item is deleted when the model is deleted.

    The model's internal data structure is populated with items by the
    \c setupModelData() function. We will examine this function separately
    at the end of this document.

    The destructor ensures that the root item and all of its descendants
    are deleted when the model is destroyed. This is done automatically
    since the root item is stored in a unique_ptr.

    \snippet itemviews/simpletreemodel/treemodel.cpp 1

    Since we cannot add data to the model after it is constructed and set
    up, this simplifies the way that the internal tree of items is managed.

    Models must implement an \c index() function to provide indexes for
    views and delegates to use when accessing data. Indexes are created
    for other components when they are referenced by their row and column
    numbers, and their parent model index. If an invalid model
    index is specified as the parent, it is up to the model to return an
    index that corresponds to a top-level item in the model.

    When supplied with a model index, we first check whether it is valid.
    If it is not, we assume that a top-level item is being referred to;
    otherwise, we obtain the data pointer from the model index with its
    \l{QModelIndex::internalPointer()}{internalPointer()} function and use
    it to reference a \c TreeItem object. Note that all the model indexes
    that we construct will contain a pointer to an existing \c TreeItem,
    so we can guarantee that any valid model indexes that we receive will
    contain a valid data pointer.

    \snippet itemviews/simpletreemodel/treemodel.cpp 6

    Since the row and column arguments to this function refer to a
    child item of the corresponding parent item, we obtain the item using
    the \c TreeItem::child() function. The
    \l{QAbstractItemModel::createIndex()}{createIndex()} function is used
    to create a model index to be returned. We specify the row and column
    numbers, and a pointer to the item itself. The model index can be used
    later to obtain the item's data.

    The way that the \c TreeItem objects are defined makes writing the
    \c parent() function easy:

    \snippet itemviews/simpletreemodel/treemodel.cpp 7

    We only need to ensure that we never return a model index corresponding
    to the root item. To be consistent with the way that the \c index()
    function is implemented, we return an invalid model index for the
    parent of any top-level items in the model.

    When creating a model index to return, we must specify the row and
    column numbers of the parent item within its own parent. We can
    easily discover the row number with the \c TreeItem::row() function,
    but we follow a convention of specifying 0 as the column number of
    the parent. The model index is created with
    \l{QAbstractItemModel::createIndex()}{createIndex()} in the same way
    as in the \c index() function.

    The \c rowCount() function simply returns the number of child items
    for the \c TreeItem that corresponds to a given model index, or the
    number of top-level items if an invalid index is specified:

    \snippet itemviews/simpletreemodel/treemodel.cpp 8

    Since each item manages its own column data, the \c columnCount()
    function has to call the item's own \c columnCount() function to
    determine how many columns are present for a given model index.
    As with the \c rowCount() function, if an invalid model index is
    specified, the number of columns returned is determined from the
    root item:

    \snippet itemviews/simpletreemodel/treemodel.cpp 2

    Data is obtained from the model via \c data(). Since the item manages
    its own columns, we need to use the column number to retrieve the data
    with the \c TreeItem::data() function:

    \snippet itemviews/simpletreemodel/treemodel.cpp 3

    Note that we only support the \l{Qt::ItemDataRole}{DisplayRole}
    in this implementation, and we also return invalid QVariant objects for
    invalid model indexes.

    We use the \c flags() function to ensure that views know that the
    model is read-only:

    \snippet itemviews/simpletreemodel/treemodel.cpp 4

    The \c headerData() function returns data that we conveniently stored
    in the root item:

    \snippet itemviews/simpletreemodel/treemodel.cpp 5

    This information could have been supplied in a different way: either
    specified in the constructor, or hard coded into the \c headerData()
    function.

    \section1 Setting Up the Data in the Model

    We use the \c setupModelData() function to set up the initial data in
    the model. This function parses a text file, extracting strings of
    text to use in the model, and creates item objects that record both
    the data and the overall model structure.
    Naturally, this function works in a way that is very specific to
    this model. We provide the following description of its behavior,
    and refer the reader to the example code itself for more information.

    We begin with a text file in the following format:

    \code
    Getting Started                         How to familiarize yourself with Qt Designer
        Launching Designer                  Running the Qt Designer application
        The User Interface                  How to interact with Qt Designer
    \endcode
    \dots
    \code
    Connection Editing Mode                 Connecting widgets together with signals and slots
        Connecting Objects                  Making connections in Qt Designer
        Editing Connections                 Changing existing connections
    \endcode

    We process the text file with the following two rules:

    \list
    \li For each pair of strings on each line, create an item (or node)
       in a tree structure, and place each string in a column of data
       in the item.
    \li When the first string on a line is indented with respect to the
       first string on the previous line, make the item a child of the
       previous item created.
    \endlist

    To ensure that the model works correctly, it is only necessary to
    create instances of \c TreeItem with the correct data and parent item.

    \section1 Testing the model

    Correctly implementing an item model can be challenging. The class
    \l [QtTest] QAbstractItemModelTester from the \l [QtTest] {Qt Test} module
    checks for model consistency, like the model index creation and
    parent-child relationships.

    You can test your model by just passing a model instance to the class
    constructor, for instance as part of a Qt unit test:

    \snippet itemviews/simpletreemodel/test.cpp 1

    To create a test which can be run using the \c ctest executable,
    \c add_test() is used:

    \snippet itemviews/simpletreemodel/CMakeLists.txt 1
*/
