QRangeModel Class

QRangeModel implementiert QAbstractItemModel für jeden C++-Bereich. Mehr...

Kopfzeile: #include <QRangeModel>
CMake: find_package(Qt6 REQUIRED COMPONENTS Core)
target_link_libraries(mytarget PRIVATE Qt6::Core)
qmake: QT += core
Seit: Qt 6.10
Vererbt: QAbstractItemModel

Hinweis: Alle Funktionen in dieser Klasse sind reentrant.

Öffentliche Typen

(since 6.10) struct RowOptions
enum class RowCategory { Default, MultiRoleItem }

Eigenschaften

Öffentliche Funktionen

QRangeModel(Range &&range, QObject *parent = nullptr)
QRangeModel(Range &&range, Protocol &&protocol, QObject *parent = nullptr)
virtual ~QRangeModel() override
void resetRoleNames()
void setRoleNames(const QHash<int, QByteArray> &names)

Reimplementierte öffentliche Funktionen

virtual QModelIndex buddy(const QModelIndex &index) const override
virtual bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const override
virtual bool canFetchMore(const QModelIndex &parent) const override
virtual bool clearItemData(const QModelIndex &index) override
virtual int columnCount(const QModelIndex &parent = {}) const override
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override
virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override
virtual void fetchMore(const QModelIndex &parent) override
virtual Qt::ItemFlags flags(const QModelIndex &index) const override
virtual bool hasChildren(const QModelIndex &parent = QModelIndex()) const override
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override
virtual QModelIndex index(int row, int column, const QModelIndex &parent = {}) const override
virtual bool insertColumns(int column, int count, const QModelIndex &parent = {}) override
virtual bool insertRows(int row, int count, const QModelIndex &parent = {}) override
virtual QMap<int, QVariant> itemData(const QModelIndex &index) const override
virtual QModelIndexList match(const QModelIndex &start, int role, const QVariant &value, int hits, Qt::MatchFlags flags) const override
virtual QMimeData *mimeData(const QModelIndexList &indexes) const override
virtual QStringList mimeTypes() const override
virtual bool moveColumns(const QModelIndex &sourceParent, int sourceColumn, int count, const QModelIndex &destinationParent, int destinationColumn) override
virtual bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationRow) override
virtual void multiData(const QModelIndex &index, QModelRoleDataSpan roleDataSpan) const override
virtual QModelIndex parent(const QModelIndex &child) const override
virtual bool removeColumns(int column, int count, const QModelIndex &parent = {}) override
virtual bool removeRows(int row, int count, const QModelIndex &parent = {}) override
virtual QHash<int, QByteArray> roleNames() const override
virtual int rowCount(const QModelIndex &parent = {}) const override
virtual bool setData(const QModelIndex &index, const QVariant &data, int role = Qt::EditRole) override
virtual bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &data, int role = Qt::EditRole) override
virtual bool setItemData(const QModelIndex &index, const QMap<int, QVariant> &data) override
virtual QModelIndex sibling(int row, int column, const QModelIndex &index) const override
virtual void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) override
virtual QSize span(const QModelIndex &index) const override
virtual Qt::DropActions supportedDragActions() const override
virtual Qt::DropActions supportedDropActions() const override

Signale

Reimplementierte geschützte Funktionen

virtual bool event(QEvent *event) override
virtual bool eventFilter(QObject *object, QEvent *event) override

Geschützte Steckplätze

virtual void resetInternalData() override

Detaillierte Beschreibung

QRangeModel kann die Daten in jedem sequentiell iterierbaren C++-Typ für das Model/View-Framework von Qt verfügbar machen. Dies erleichtert die Anzeige vorhandener Datenstrukturen in den Elementansichten Qt Widgets und Qt Quick und ermöglicht es dem Benutzer der Anwendung, die Daten über eine grafische Benutzeroberfläche zu manipulieren.

Um QRangeModel zu verwenden, instanziieren Sie es mit einem C++-Bereich und legen es als Modell für eine oder mehrere Ansichten fest:

std::array<int, 5> numbers = {1, 2, 3, 4, 5};
QRangeModel model(numbers);
listView.setModel(&model);

Konstruieren des Modells

Der Bereich kann ein beliebiger C++-Typ sein, für den die Standardmethoden std::begin und std::end implementiert sind und für den der zurückgegebene Iteratortyp std::forward_iterator erfüllt. Bestimmte Modelloperationen funktionieren besser, wenn std::size verfügbar ist und wenn der Iterator std::random_access_iterator entspricht.

Der Bereich muss beim Erstellen des Modells angegeben werden; es gibt keine API, um den Bereich später festzulegen, und es gibt keine API, um den Bereich aus dem Modell abzurufen. Der Bereich kann als Wert, Referenz-Wrapper oder Zeiger angegeben werden. Wie das Modell konstruiert wurde, bestimmt, ob Änderungen durch die Modell-API die ursprünglichen Daten verändern.

Wenn es nach Wert konstruiert wurde, erstellt das Modell eine Kopie des Bereichs, und QAbstractItemModel APIs, die das Modell ändern, wie setData() oder insertRows(), haben keine Auswirkungen auf den ursprünglichen Bereich.

QRangeModel model(numbers);

Da es keine API gibt, um den Bereich erneut abzurufen, ist die Konstruktion des Modells aus einem Bereich nach Wert meist nur für die Anzeige schreibgeschützter Daten nützlich. Änderungen an den Daten können mit Hilfe der vom Modell ausgegebenen Signale überwacht werden, z. B. dataChanged().

Damit sich Änderungen am Modell auf den ursprünglichen Bereich auswirken, geben Sie den Bereich entweder durch einen Zeiger:

QRangeModel model(&numbers);

oder durch einen Referenz-Wrapper:

QRangeModel model(std::ref(numbers));

In diesem Fall ändern die APIs von QAbstractItemModel, die das Modell ändern, auch den Bereich. Methoden, die die Struktur des Bereichs ändern, wie insertRows() oder removeColumns(), verwenden die Standard-C++-Container-APIs resize(), insert(), erase(), zusätzlich zur Dereferenzierung eines mutierenden Iterators zum Setzen oder Löschen der Daten.

Hinweis: Sobald das Modell konstruiert und an eine Ansicht weitergegeben wurde, darf der Bereich, auf dem das Modell operiert, nicht mehr direkt geändert werden. Sichten auf das Modell würden nicht über die Änderungen informiert werden, und strukturelle Änderungen würden wahrscheinlich die Instanzen von QPersistentModelIndex beschädigen, die das Modell verwaltet.

Der Aufrufer muss sicherstellen, dass die Lebensdauer des Bereichs die Lebensdauer des Modells überschreitet.

Verwenden Sie intelligente Zeiger, um sicherzustellen, dass der Bereich nur gelöscht wird, wenn alle Clients damit fertig sind.

auto shared_numbers = std::make_shared<std::vector<int>>(numbers);
QRangeModel model(shared_numbers);

QRangeModel unterstützt sowohl gemeinsame als auch eindeutige Zeiger.

Schreibgeschützt oder veränderbar

Für Bereiche, bei denen es sich um konstante Objekte handelt, bei denen der Zugriff immer konstante Werte ergibt, oder bei denen die erforderlichen Container-APIs nicht verfügbar sind, implementiert QRangeModel Schreibzugriffs-APIs, die nichts tun und false zurückgeben. In dem Beispiel, das std::array verwendet, kann das Modell keine Zeilen hinzufügen oder entfernen, da die Anzahl der Einträge in einem C++-Array fest ist. Aber die Werte können mit setData() geändert werden, und der Benutzer kann die Bearbeitung der Werte in der Listenansicht auslösen. Dadurch, dass das Array const ist, werden die Werte auch schreibgeschützt.

const std::array<int, 5> numbers = {1, 2, 3, 4, 5};

Die Werte sind auch schreibgeschützt, wenn der Elementtyp const ist, wie in

std::array<const int, 5> numbers = {1, 2, 3, 4, 5};

In den obigen Beispielen mit std::vector kann das Modell Zeilen hinzufügen oder entfernen, und die Daten können geändert werden. Wird der Bereich als konstanter Verweis übergeben, wird das Modell schreibgeschützt.

QRangeModel model(std::cref(numbers));

Hinweis: Wenn die Werte im Bereich konstant sind, dann ist es auch nicht möglich, Spalten und Zeilen über die QAbstractItemModel API zu entfernen oder einzufügen. Für eine genauere Kontrolle implementieren Sie the C++ tuple protocol.

Zeilen und Spalten

Die Elemente im Bereich werden als Zeilen des Modells interpretiert. Je nach dem Typ dieser Zeilenelemente stellt QRangeModel den Bereich als Liste, Tabelle oder Baum dar.

Wenn die Zeilenelemente einfache Werte sind, wird der Bereich als Liste dargestellt.

QList<int> numbers = {1, 2, 3, 4, 5};
QRangeModel model(numbers); // columnCount() == 1
QListView listView;
listView.setModel(&model);

Wenn der Typ der Zeilenelemente ein iterierbarer Bereich ist, z. B. ein Vektor, eine Liste oder ein Array, dann wird der Bereich als Tabelle dargestellt.

std::vector<std::vector<int>> gridOfNumbers = {
    {1, 2, 3, 4, 5},
    {6, 7, 8, 9, 10},
    {11, 12, 13, 14, 15},
};
QRangeModel model(&gridOfNumbers); // columnCount() == 5
QTableView tableView;
tableView.setModel(&model);

Wenn der Zeilentyp die Standard-C++-Container-APIs resize(), insert(), erase() bereitstellt, können Spalten über insertColumns() und removeColumns() hinzugefügt und entfernt werden. Alle Zeilen müssen die gleiche Anzahl von Spalten haben.

Strukturen und Gadgets als Zeilen

Wenn der Zeilentyp the C++ tuple protocol implementiert, dann wird der Bereich als Tabelle mit einer festen Anzahl von Spalten dargestellt.

using TableRow = std::tuple<int, QString>;
QList<TableRow> numberNames = {
    {1, "one"},
    {2, "two"},
    {3, "three"}
};
QRangeModel model(&numberNames); // columnCount() == 2
QTableView tableView;
tableView.setModel(&model);

Eine einfachere und flexiblere Alternative zur Implementierung des Tupel-Protokolls für einen C++-Typ ist die Verwendung des Meta-Objektsystems von Qt, um einen Typ mit Eigenschaften zu deklarieren. Dies kann ein Wertetyp sein, der als gadget deklariert ist, oder eine QObject Unterklasse.

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;
};

Die Verwendung von QObject Unterklassen ermöglicht es, Eigenschaften zu binden oder Änderungsbenachrichtigungen zu senden. Die Verwendung von QObject Instanzen für Elemente hat jedoch einen erheblichen Speicher-Overhead.

Die Verwendung von Qt Gadgets oder Objekten ist bequemer und kann flexibler sein als die Implementierung des Tupel-Protokolls. Diese Typen sind auch direkt von QML aus zugänglich. Allerdings ist der Zugriff über das Eigenschaftssystem mit einem gewissen Laufzeit-Overhead verbunden. Für leistungskritische Modelle sollten Sie die Implementierung des Tupel-Protokolls in Betracht ziehen, um den Zugriffscode zur Kompilierzeit zu generieren.

Elemente mit mehreren Rollen

Der Typ der Elemente, auf die die Implementierungen von data(), setData(), clearItemData() usw. zugreifen, kann für das gesamte Modell gleich sein - wie im obigen Beispiel gridOfNumbers. Der Bereich kann aber auch unterschiedliche Elementtypen für verschiedene Spalten haben, wie im Fall numberNames.

Standardmäßig wird der Wert für die Rollen Qt::DisplayRole und Qt::EditRole verwendet. Die meisten Ansichten erwarten, dass der Wert convertible to and from a QString ist (aber ein benutzerdefinierter Delegat könnte mehr Flexibilität bieten).

Assoziative Container mit mehreren Rollen

Wenn das Element ein assoziativer Container ist, der int, Qt::ItemDataRole oder QString als Schlüsseltyp und QVariant als zugeordneten Typ verwendet, dann interpretiert QRangeModel diesen Container als die Speicherung der Daten für mehrere Rollen. Die Funktionen data() und setData() geben den zugeordneten Wert im Container zurück und ändern ihn, während setItemData() alle bereitgestellten Werte ändert, itemData() alle gespeicherten Werte zurückgibt und clearItemData() den gesamten Container löscht.

using ColorEntry = QMap<Qt::ItemDataRole, QVariant>;

const QStringList colorNames = QColor::colorNames();
QList<ColorEntry> 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()}};
}
QRangeModel colorModel(colors);
QListView list;
list.setModel(&colorModel);

Der effizienteste Datentyp, der als Schlüssel verwendet werden kann, ist Qt::ItemDataRole oder int. Bei Verwendung von int gibt itemData() den Container so zurück, wie er ist, und muss keine Kopie der Daten erstellen.

Gadgets und Objekte als Multi-Rollen-Elemente

Gadgets und QObject Typen können auch als Multi-Role-Elemente dargestellt werden. Die Eigenschaften dieser Elemente werden für die Rolle verwendet, zu der name of a role passt. Wenn alle Elemente denselben Typ von Gadget oder QObject enthalten, gibt die Implementierung roleNames() in QRangeModel die Liste der Eigenschaften dieses Typs zurück.

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;
};

Bei Verwendung in einer Tabelle ist dies die Standarddarstellung für Gadgets:

QList<QList<ColorEntry>> colorTable;

// ...

QRangeModel colorModel(colorTable);
QTableView table;
table.setModel(&colorModel);

Wenn sie in einer Liste verwendet werden, werden diese Typen jedoch standardmäßig als mehrspaltige Zeilen dargestellt, wobei jede Eigenschaft als separate Spalte dargestellt wird. Um zu erzwingen, dass ein Gadget als mehrspaltiges Element in einer Liste dargestellt wird, deklarieren Sie das Gadget als mehrspaltigen Typ, indem Sie QRoleModel::RowOptions spezialisieren, wobei eine static constexpr auto rowCategory Member-Variable auf MultiRoleItem gesetzt wird.

class ColorEntry
{
    Q_GADGET
    Q_PROPERTY(QString display MEMBER m_colorName)
    Q_PROPERTY(QColor decoration READ decoration)
    Q_PROPERTY(QString toolTip READ toolTip)
public:
    ...
};
template <>
struct QRangeModel::RowOptions<ColorEntry>
{
    static constexpr auto rowCategory = QRangeModel::RowCategory::MultiRoleItem;
};

Sie können solche Typen auch in ein Einzelelement-Tupel verpacken, wodurch die Liste zu einer Tabelle mit einer einzigen Spalte wird:

const QStringList colorNames = QColor::colorNames();
QList<std::tuple<ColorEntry>> colors;

// ...

QRangeModel colorModel(colors);
QListView list;
list.setModel(&colorModel);

In diesem Fall ist zu beachten, dass der direkte Zugriff auf die Elemente in den Listendaten über std::get erfolgen muss:

ColorEntry firstEntry = std::get<0>(colors.at(0));

oder alternativ eine strukturierte Bindung:

auto [firstEntry] = colors.at(0);

Zeilen als Werte oder Zeiger

In den bisherigen Beispielen haben wir QRangeModel immer mit Bereichen verwendet, die Werte enthalten. QRangeModel kann auch mit Bereichen arbeiten, die Zeiger enthalten, einschließlich intelligenter Zeiger. Dadurch kann QRangeModel mit Bereichen von polymorphen Typen arbeiten, z. B. mit QObject Unterklassen.

class Entry : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString display READ display WRITE setDisplay NOTIFY displayChanged)
    Q_PROPERTY(QIcon decoration READ decoration WRITE setDecoration NOTIFY decorationChanged)
    Q_PROPERTY(QString toolTip READ toolTip WRITE setToolTip NOTIFY toolTipChanged)

public:
    Entry() = default;

    QString display() const
    {
        return m_display;
    }

    void setDisplay(const QString &display)
    {
        if (m_display == display)
            return;
        m_display = display;
        emit displayChanged(m_display);
    }

signals:
    void displayChanged(const QString &);
    ...
};
std::vector<std::shared_ptr<Entry>> entries = {
    ...
};
QRangeModel model(std::ref(entries));
QListView listView;
listView.setModel(&model);

Wie bei Werten definiert der Typ der Zeile, ob der Bereich als Liste, Tabelle oder Baum dargestellt wird. Zeilen, die QObjects sind, stellen jede Eigenschaft als Spalte dar, es sei denn, die Vorlage QRangeModel::RowOptions ist so spezialisiert, dass der Typ als Multi-Role-Element deklariert ist.

template <>
struct QRangeModel::RowOptions<Entry>
{
    static constexpr auto rowCategory = QRangeModel::RowCategory::MultiRoleItem;
};
std::vector<std::shared_ptr<Entry>> entries = {
    std::make_shared<Entry>(),
    ...
};

QRangeModel model(std::ref(entries));

Hinweis: Wenn der Bereich rohe Zeiger enthält, dann müssen Sie QRangeModel aus einem Zeiger oder Referenz-Wrapper des Bereichs konstruieren. Andernfalls wird die Eigentümerschaft der Daten unklar, und eine Kopie des Bereichs würde immer noch mit denselben tatsächlichen Zeilendaten arbeiten, was zu unerwarteten Nebeneffekten führen würde.

Unterklassifizierung von QRangeModel

Die Unterklassifizierung von QRangeModel ermöglicht es, praktische APIs hinzuzufügen, die den Datentyp und die Struktur des Bereichs berücksichtigen.

class NumbersModel : public QRangeModel
{
    std::vector<int> m_numbers;

public:
    NumbersModel(const std::vector<int> &numbers)
        : QRangeModel(std::ref(m_numbers))
        , m_numbers(numbers)
    {
    }

Fügen Sie dabei den Bereich als privates Mitglied hinzu und rufen Sie den QRangeModel-Konstruktor mit einem Referenz-Wrapper oder Zeiger auf dieses Mitglied auf. Dadurch werden die Daten ordnungsgemäß gekapselt und ein direkter Zugriff vermieden.

    void setNumber(int idx, int number)
    {
        setData(index(idx, 0), QVariant::fromValue(number));
    }

    int number(int idx) const
    {
        return m_numbers.at(idx);
    }
};

Fügen Sie Memberfunktionen hinzu, um einen typsicheren Zugriff auf die Daten zu ermöglichen, und verwenden Sie die API QAbstractItemModel, um alle Operationen durchzuführen, die den Bereich verändern. Der Nur-Lese-Zugriff kann direkt auf die Datenstruktur wirken.

Datenbäume

QRangeModel kann eine Datenstruktur als Baummodell darstellen. Eine solche Baumdatenstruktur muss homomorph sein: Auf allen Ebenen des Baums muss die Liste der untergeordneten Zeilen genau dieselbe Darstellung verwenden wie der Baum selbst. Darüber hinaus muss der Zeilentyp eine statische Größe haben: entweder ein Gadget- oder QObject -Typ oder ein Typ, der das {C++ Tupel-Protokoll} implementiert.

Um solche Daten als Baum darzustellen, muss QRangeModel in der Lage sein, die Datenstruktur zu durchlaufen: für jede beliebige Zeile muss das Modell in der Lage sein, die übergeordnete Zeile und die optionale Spanne der Kinder abzurufen. Diese Traversalfunktionen können implizit über den Zeilentyp oder über einen expliziten Protokolltyp bereitgestellt werden.

Implizites Baum-Traversal-Protokoll

class TreeRow;

using Tree = std::vector<TreeRow>;

Der Baum selbst ist ein Vektor von TreeRow Werten. Siehe Tree Rows as pointers or values für die Überlegungen, ob Werte oder Zeiger für die Zeilen verwendet werden sollen.

class TreeRow
{
    Q_GADGET
    // properties

    TreeRow *m_parent;
    std::optional<Tree> m_children;

public:
    TreeRow() = default;

    // rule of 0: copy, move, and destructor implicitly defaulted

Die Zeilenklasse kann ein beliebiger, oben beschriebener Typ mit fester Größe sein: ein Typ, der das Tupelprotokoll implementiert, ein Gadget oder ein QObject. In diesem Beispiel wird ein Gadget verwendet.

Jedes Zeilenelement muss einen Zeiger auf die übergeordnete Zeile sowie einen optionalen Bereich von untergeordneten Zeilen enthalten. Dieser Bereich muss mit der für den Baum selbst verwendeten Bereichsstruktur identisch sein.

Den Zeilentyp standardmäßig konstruierbar zu machen, ist optional und ermöglicht es dem Modell, neue Zeilendatenelemente zu konstruieren, zum Beispiel in den Implementierungen insertRow() oder moveRows().

    // tree traversal protocol implementation
    const TreeRow *parentRow() const { return m_parent; }
    const std::optional<Tree> &childRows() const { return m_children; }

Das Protokoll zur Durchquerung des Baums kann dann als Mitgliedsfunktionen des Zeilendatentyps implementiert werden. Eine Funktion const parentRow() muss einen Zeiger auf ein const-Zeilenelement zurückgeben; und die Funktion childRows() muss einen Verweis auf eine const std::optional zurückgeben, die den optionalen Kindbereich enthalten kann.

Diese beiden Funktionen reichen aus, damit das Modell den Baum als schreibgeschützte Datenstruktur navigieren kann. Um dem Benutzer die Möglichkeit zu geben, Daten in einer Ansicht zu bearbeiten, und dem Modell zu ermöglichen, sich ändernde Modell-APIs wie insertRows(), removeRows() und moveRows() zu implementieren, müssen wir zusätzliche Funktionen für den Schreibzugriff implementieren:

    void setParentRow(TreeRow *parent) { m_parent = parent; }
    std::optional<Tree> &childRows() { return m_children; }

Das Modell ruft die Funktion setParentRow() und die veränderbare Überladung childRows() auf, um Zeilen in einen bestehenden Baumzweig zu verschieben oder einzufügen und um den übergeordneten Zeiger zu aktualisieren, wenn der alte Wert ungültig geworden ist. Die non-const Überladung von childRows() bietet zusätzlich Schreibzugriff auf die Zeilendaten.

Hinweis: Das Modell führt das Setzen des Elternteils einer Zeile, das Entfernen dieser Zeile aus dem alten Elternteil und das Hinzufügen zur Liste der Kinder des neuen Elternteils als separate Schritte aus. Dadurch wird die Protokollschnittstelle klein gehalten.

    ...
    // Helper to assembly a tree of rows, not used by QRangeModel
    template <typename ...Args>
    TreeRow &addChild(Args &&...args)
    {
        if (!m_children)
            m_children.emplace(Tree{});
        auto &child = m_children->emplace_back(std::forward<Args>(args)...);
        child.m_parent = this;
        return child;
    }
};

Der Rest der Klassenimplementierung ist für das Modell nicht relevant, aber eine addChild() -Hilfsfunktion bietet uns eine bequeme Möglichkeit, den Anfangszustand des Baums zu konstruieren.

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("...");

Ein QRangeModel, das mit einer Instanz eines solchen Bereichs instanziiert wird, stellt die Daten als Baum dar.

// instantiate the model with a pointer to the tree, not a copy!
QRangeModel model(&tree);
QTreeView view;
view.setModel(&model);

Protokoll für die Baumdurchquerung in einer separaten Klasse

Das Tree Traversal Protocol kann auch in einer separaten Klasse implementiert werden.

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<Tree> &childRows(const TreeRow &row) const { return row.m_children; }
    std::optional<Tree> &childRows(TreeRow &row) const { return row.m_children; }
};

Übergeben Sie eine Instanz dieser Protokollimplementierung an den QRangeModel-Konstruktor:

QRangeModel model(&tree, TreeTraversal{});

Tree Rows als Zeiger oder Werte

Der Zeilentyp des Datenbereichs kann entweder ein Wert oder ein Zeiger sein. Im obigen Code haben wir die Baumzeilen als Werte in einem Vektor verwendet, wodurch wir eine explizite Speicherverwaltung vermeiden. Ein Vektor als zusammenhängender Speicherblock macht jedoch alle Iteratoren und Verweise ungültig, wenn der Speicher neu zugewiesen werden muss oder wenn Elemente eingefügt oder entfernt werden. Dies wirkt sich auf den Zeiger auf das übergeordnete Element aus, d. h. auf die Position der übergeordneten Zeile innerhalb des Vektors. Die Sicherstellung, dass dieses übergeordnete Element (und die Instanzen von QPersistentModelIndex, die sich auf Elemente innerhalb dieses Elements beziehen) gültig bleibt, kann zu einem erheblichen Leistungs-Overhead führen. Die QRangeModel-Implementierung muss davon ausgehen, dass alle Verweise auf den Bereich ungültig werden, wenn der Bereich geändert wird.

Alternativ können wir auch einen Bereich von Zeilenzeigern als Baumtyp verwenden:

struct TreeRow;
using Tree = std::vector<TreeRow *>;

In diesem Fall müssen wir alle TreeRow-Instanzen explizit mit dem Operator new zuweisen und den Destruktor so implementieren, dass alle Elemente im Vektor der Kinder delete sind.

struct TreeRow { Q_GADGETpublic: TreeRow(const QString &value = {}) : m_value(value) {} ~TreeRow() { if (m_children)            qDeleteAll(*m_children);
    } // nur verschiebenTreeRow(TreeRow &&) = default; TreeRow &operator=(TreeRow &&) = default; // helper zum Auffüllen der Vorlage <typename ...Args>TreeRow *addChild(Args &&...args) { if (!m_children) m_children.emplace(Tree{}); auto *child =  m_children->emplace_back(new TreeRow(std::forward<Args>(args)...));  child->m_parent = this; return child; }private: friend struct TreeTraversal;    QString m_value; std::optional<Tree> m_children; TreeRow *m_parent = nullptr; }; 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");

Bevor wir ein Modell konstruieren können, das diese Daten als Baum darstellt, müssen wir auch das Protokoll für die Baumüberquerung implementieren.

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<Tree> &childRows(const TreeRow &row) const { return row.m_children; }
    std::optional<Tree> &childRows(TreeRow &row) { return row.m_children; }
};

Eine explizite Protokollimplementierung für veränderliche Zeigerbäume muss zwei zusätzliche Mitgliedsfunktionen bereitstellen: newRow() und deleteRow(RowType *).

int main(int argc, char **argv)
{
    QApplication app(argc, argv);

    Tree tree = make_tree_of_pointers();

    QRangeModel model(std::move(tree), TreeTraversal{});
    QTreeView treeView;
    treeView.setModel(&model);
    treeView.show();

    return app.exec();
}

Das Modell ruft diese Funktionen beim Anlegen neuer Zeilen in insertRows() und beim Entfernen von Zeilen in removeRows() auf. Wenn das Modell Eigentümer der Daten ist, löscht es außerdem alle Zeilen der obersten Ebene bei der Zerstörung. Beachten Sie, dass wir in diesem Beispiel den Baum in das Modell verschieben, so dass wir keine Operationen mehr an ihm durchführen müssen. QRangeModel, wenn es durch Verschieben von Baumdaten mit Zeilenzeigern konstruiert wird, übernimmt das Eigentum an den Daten und löscht die Zeilenzeiger in seinem Destruktor.

Die Verwendung von Zeigern als Zeilen bringt einen gewissen Overhead bei der Speicherzuweisung und -verwaltung mit sich. Die Verweise auf die Zeilenelemente bleiben jedoch stabil, auch wenn sie innerhalb des Bereichs verschoben werden oder der Bereich neu zugewiesen wird. Dies kann die Kosten für Änderungen an der Struktur des Modells bei Verwendung von insertRows(), removeRows() oder moveRows() erheblich reduzieren.

Jede Wahl hat unterschiedliche Kompromisse bei der Leistung und dem Speicher-Overhead. Die beste Option hängt vom genauen Anwendungsfall und der verwendeten Datenstruktur ab.

Das C++ Tupel-Protokoll

Wie im obigen Beispiel numberNames zu sehen ist, kann der Zeilentyp ein Tupel sein, und zwar jeder Typ, der das Tupelprotokoll implementiert. Dieses Protokoll wird durch die Spezialisierung von std::tuple_size und std::tuple_element und das Überladen der unqualifizierten Funktion get implementiert. Tun Sie dies für Ihren benutzerdefinierten Zeilentyp, um vorhandene strukturierte Daten für das Model/View-Framework in Qt verfügbar zu machen.

struct Book
{
    QString title;
    QString author;
    QString summary;
    int rating = 0;

    template <size_t I, typename T>
        requires ((I <= 3) && std::is_same_v<std::remove_cvref_t<T>, 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<T>(book.summary);
        else if constexpr (I == 3)
            return std::forward_like<T>(book.rating);
    }
};

namespace std {
    template <> struct tuple_size<Book> : std::integral_constant<size_t, 4> {};
    template <size_t I> struct tuple_element<I, Book>
    { using type = decltype(get<I>(std::declval<Book>())); };
}

In der obigen Implementierung werden die Werte title und author des Typs Book als const zurückgegeben, so dass das Modell Elemente in diesen beiden Spalten als schreibgeschützt kennzeichnet. Der Benutzer wird nicht in der Lage sein, die Bearbeitung auszulösen, und setData() tut nichts und gibt false zurück. Für summary und rating gibt die Implementierung dieselbe Wertkategorie wie das Buch zurück. Wenn also get mit einem veränderbaren Verweis auf Book aufgerufen wird, gibt es einen veränderbaren Verweis auf die entsprechende Variable zurück. Das Modell macht diese Spalten editierbar, sowohl für den Benutzer als auch für den programmatischen Zugriff.

Hinweis: Die obige Implementierung von get erfordert C++23.

Siehe auch Model/View Programming.

Dokumentation der Mitgliedstypen

enum class QRangeModel::RowCategory

Diese Aufzählung beschreibt, wie QRangeModel die Elemente des Bereichs, mit dem es erstellt wurde, darstellen soll.

KonstanteWertBeschreibung
QRangeModel::RowCategory::Default0QRangeModel entscheidet, wie die Zeilen dargestellt werden sollen.
QRangeModel::RowCategory::MultiRoleItem1QRangeModel stellt Elemente mit einem Meta-Objekt als Multi-Role-Elemente dar, auch bei Verwendung in einem eindimensionalen Bereich.

Spezialisieren Sie die Vorlage RowOptions für Ihren Typ, und fügen Sie eine öffentliche Member-Variable static constexpr auto rowCategory mit einem der Werte aus dieser Aufzählung hinzu.

Siehe auch RowOptions.

Dokumentation der Eigenschaft

roleNames : QHash<int, QByteArray>

Diese Eigenschaft enthält die Rollennamen für das Modell.

Wenn alle Spalten im Bereich vom gleichen Typ sind und wenn dieser Typ ein Meta-Objekt bereitstellt (d.h. es ist ein Gadget oder eine QObject Unterklasse), dann enthält diese Eigenschaft die Namen der Eigenschaften dieses Typs, die den Werten von Qt::ItemDataRole ab Qt::UserRole zugeordnet sind. Darüber hinaus bietet eine Rolle "modelData" Zugriff auf die Gadget- oder QObject -Instanz.

Setzen Sie dieses Standardverhalten außer Kraft, indem Sie diese Eigenschaft explizit auf eine nicht leere Zuordnung setzen. Das Setzen dieser Eigenschaft auf ein leeres Mapping oder die Verwendung von resetRoleNames() stellt das Standardverhalten wieder her.

Zugriffsfunktionen:

virtual QHash<int, QByteArray> roleNames() const override
void setRoleNames(const QHash<int, QByteArray> &names)
void resetRoleNames()

Benachrichtigungssignal:

void roleNamesChanged()

Siehe auch QAbstractItemModel::roleNames().

Dokumentation der Mitgliedsfunktionen

[explicit] template <typename Range, typename Protocol, int = true> QRangeModel::QRangeModel(Range &&range, Protocol &&protocol, QObject *parent = nullptr)

[explicit] template <typename Range, int = true> QRangeModel::QRangeModel(Range &&range, QObject *parent = nullptr)

[explicit] template <typename Range, int = true> QRangeModel::QRangeModel(Range &&range, QObject *parent = nullptr)

Konstruiert eine QRangeModel Instanz, die auf den Daten in range arbeitet. range muss ein sequentieller Bereich sein, für den std::begin und std::end verfügbar sind. Wenn protocol angegeben wird, dann stellt das Modell den Bereich als Baum dar, indem es die Protokollimplementierung verwendet. Die Modellinstanz wird ein Kind von parent.

range kann ein Zeiger oder ein Referenz-Wrapper sein. In diesem Fall werden die Daten in der referenzierten Bereichsinstanz durch ändernde Modell-APIs (wie setData() oder insertRow()) geändert. Wenn range ein Wert ist (oder in das Modell verschoben wurde), dann verbinden Sie sich mit den Signalen, die vom Modell ausgegeben werden, um auf Änderungen an den Daten zu reagieren.

QRangeModel greift nicht auf die range zu, während sie konstruiert wird. Dadurch ist es legal, einen Zeiger oder Verweis auf ein Bereichsobjekt, das noch nicht vollständig konstruiert ist, an diesen Konstruktor zu übergeben, zum Beispiel wenn subclassing QRangeModel.

Wenn die range in das Modell verschoben wurde, werden der Bereich und alle darin enthaltenen Daten bei der Zerstörung des Modells zerstört.

Hinweis: Obwohl das Modell ansonsten nicht den Besitz des Bereichsobjekts übernimmt, dürfen Sie range nicht direkt ändern, sobald das Modell konstruiert und an eine Ansicht weitergegeben wurde. Solche Änderungen werden keine Signale ausgeben, die notwendig sind, um die Modellbenutzer (andere Modelle oder Ansichten) mit dem Modell zu synchronisieren, was zu inkonsistenten Ergebnissen, undefiniertem Verhalten und Abstürzen führt.

[override virtual noexcept] QRangeModel::~QRangeModel()

Zerstört die QRangeModel.

Auf den Bereich, aus dem das Modell gebaut wurde, wird nicht zugegriffen, und er wird nur zerstört, wenn das Modell aus einem eingezogenen Bereich gebaut wurde.

[override virtual] QModelIndex QRangeModel::buddy(const QModelIndex &index) const

Reimplements: QAbstractItemModel::buddy(const QModelIndex &index) const.

[override virtual] bool QRangeModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const

Reimplements: QAbstractItemModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const.

[override virtual] bool QRangeModel::canFetchMore(const QModelIndex &parent) const

Reimplements: QAbstractItemModel::canFetchMore(const QModelIndex &parent) const.

[override virtual] bool QRangeModel::clearItemData(const QModelIndex &index)

Reimplements: QAbstractItemModel::clearItemData(const QModelIndex &index).

Ersetzt den im Bereich unter index gespeicherten Wert durch einen standardmäßig konstruierten Wert.

Bei Modellen, die mit einem schreibgeschützten Bereich oder mit einer schreibgeschützten Spalte in einem Zeilentyp arbeiten, der the C++ tuple protocol implementiert, gibt diese Implementierung sofort false zurück.

[override virtual] int QRangeModel::columnCount(const QModelIndex &parent = {}) const

Reimplements: QAbstractItemModel::columnCount(const QModelIndex &parent) const.

Gibt die Anzahl der Spalten des Modells zurück. Diese Funktion gibt den gleichen Wert für alle parent Indizes zurück.

Für Modelle, die mit einem statischen Zeilentyp arbeiten, ist der zurückgegebene Wert während der gesamten Lebensdauer des Modells immer derselbe. Bei Modellen, die mit dynamischen Zeilentypen arbeiten, gibt das Modell die Anzahl der Elemente in der ersten Zeile zurück, oder 0, wenn das Modell keine Zeilen hat.

Siehe auch rowCount und insertColumns().

[override virtual] QVariant QRangeModel::data(const QModelIndex &index, int role = Qt::DisplayRole) const

Reimplements: QAbstractItemModel::data(const QModelIndex &index, int role) const.

Gibt die unter dem angegebenen role gespeicherten Daten für den Wert in dem Bereich zurück, auf den index verweist.

Wenn der Elementtyp für diesen Index ein assoziativer Container ist, der entweder von int, Qt::ItemDataRole oder QString auf QVariant abbildet, werden die Rollendaten in diesem Container gesucht und zurückgegeben.

Wenn es sich bei dem Element um ein Gadget oder QObject handelt, gibt die Implementierung den Wert der Eigenschaft des Elements zurück, der dem Eintrag role in der Zuordnung roleNames() entspricht.

Andernfalls gibt die Implementierung ein QVariant zurück, das aus dem Element über QVariant::fromValue() für Qt::DisplayRole oder Qt::EditRole erstellt wurde. Für andere Rollen gibt die Implementierung ein ungültiges (standardmäßig konstruiertes) QVariant zurück.

Siehe auch Qt::ItemDataRole, setData(), und headerData().

[override virtual] bool QRangeModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)

Reimplements: QAbstractItemModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent).

[override virtual protected] bool QRangeModel::event(QEvent *event)

Reimplements: QObject::event(QEvent *e).

[override virtual protected] bool QRangeModel::eventFilter(QObject *object, QEvent *event)

Reimplements: QObject::eventFilter(QObject *watched, QEvent *event).

[override virtual] void QRangeModel::fetchMore(const QModelIndex &parent)

Reimplements: QAbstractItemModel::fetchMore(const QModelIndex &parent).

[override virtual] Qt::ItemFlags QRangeModel::flags(const QModelIndex &index) const

Reimplements: QAbstractItemModel::flags(const QModelIndex &index) const.

Gibt die Element-Flags für das angegebene index zurück.

Die Implementierung gibt eine Kombination von Flags zurück, die das Element aktiviert (ItemIsEnabled) und seine Auswahl erlaubt (ItemIsSelectable). Bei Modellen, die mit einem Bereich mit veränderlichen Daten arbeiten, wird auch das Flag gesetzt, das die Editierbarkeit des Elements ermöglicht (ItemIsEditable).

Siehe auch Qt::ItemFlags.

[override virtual] bool QRangeModel::hasChildren(const QModelIndex &parent = QModelIndex()) const

Reimplements: QAbstractItemModel::hasChildren(const QModelIndex &parent) const.

[override virtual] QVariant QRangeModel::headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const

Reimplements: QAbstractItemModel::headerData(int section, Qt::Orientation orientation, int role) const.

Gibt die Daten für die angegebenen role und section in der Kopfzeile mit der angegebenen orientation zurück.

Bei horizontalen Kopfzeilen entspricht die Nummer der Sektion der Nummer der Spalte. Bei vertikalen Kopfzeilen entspricht die Abschnittsnummer der Zeilennummer.

Für die horizontale Kopfzeile und die Qt::DisplayRole role geben Modelle, die mit einem Bereich arbeiten, der ein Array als Zeilentyp verwendet, section zurück. Handelt es sich bei dem Zeilentyp um ein Tupel, so gibt die Implementierung den Namen des Typs unter section zurück. Für Zeilen, die vom Typ Gadget oder QObject sind, gibt diese Funktion den Namen der Eigenschaft am Index von section zurück.

Für die vertikale Kopfzeile gibt diese Funktion immer das Ergebnis der Standardimplementierung in QAbstractItemModel zurück.

Siehe auch Qt::ItemDataRole, setHeaderData(), und QHeaderView.

[override virtual] QModelIndex QRangeModel::index(int row, int column, const QModelIndex &parent = {}) const

Reimplements: QAbstractItemModel::index(int row, int column, const QModelIndex &parent) const.

Gibt den Index des Modellelements unter row und column in parent zurück.

Die Übergabe eines gültigen Elternteils erzeugt einen ungültigen Index für Modelle, die mit Listen- und Tabellenbereichen arbeiten.

Siehe auch parent().

[override virtual] bool QRangeModel::insertColumns(int column, int count, const QModelIndex &parent = {})

Reimplements: QAbstractItemModel::insertColumns(int column, int count, const QModelIndex &parent).

Fügt count leere Spalten vor dem Element unter column in alle Zeilen des Bereichs unter parent ein. Gibt bei Erfolg true zurück, andernfalls false.

Hinweis: Ein dynamisch dimensionierter Zeilentyp muss eine insert(const_iterator, size_t, value_type) Memberfunktion bereitstellen.

Für Modelle, die mit einem schreibgeschützten Bereich oder einem Bereich mit einem Zeilentyp statischer Größe (z. B. einem Tupel, Array oder Struct) arbeiten, tut diese Implementierung nichts und gibt sofort false zurück. Dies ist bei Baummodellen immer der Fall.

[override virtual] bool QRangeModel::insertRows(int row, int count, const QModelIndex &parent = {})

Reimplements: QAbstractItemModel::insertRows(int row, int count, const QModelIndex &parent).

Fügt count leere Zeilen vor der angegebenen row in den Bereich bei parent ein. Gibt bei Erfolg true zurück, andernfalls false.

Hinweis: Der Bereich muss dynamisch dimensioniert sein und eine insert(const_iterator, size_t, value_type) Memberfunktion bereitstellen.

Für Modelle, die mit einem schreibgeschützten oder statisch dimensionierten Bereich arbeiten (z. B. ein Array), tut diese Implementierung nichts und gibt sofort false zurück.

Hinweis: Für Bereiche mit einem dynamisch dimensionierten Spaltentyp muss die Spalte eine resize(size_t) Memberfunktion bereitstellen.

[override virtual] QMap<int, QVariant> QRangeModel::itemData(const QModelIndex &index) const

Reimplements: QAbstractItemModel::itemData(const QModelIndex &index) const.

Gibt eine Map mit Werten für alle vordefinierten Rollen im Modell für das Element auf der angegebenen index zurück.

Wenn der Elementtyp für dieses index ein assoziativer Container ist, der entweder von int, Qt::ItemDataRole oder QString auf ein QVariant abbildet, dann werden die Daten aus diesem Container zurückgegeben.

Handelt es sich bei dem Elementtyp um ein Gadget oder eine QObject Unterklasse, werden die Werte der Eigenschaften zurückgegeben, die mit einer role name übereinstimmen.

Handelt es sich bei dem Element nicht um einen assoziativen Container, ein Gadget oder eine QObject Unterklasse, so wird die Implementierung der Basisklasse aufgerufen.

Siehe auch setItemData(), Qt::ItemDataRole, und data().

[override virtual] QModelIndexList QRangeModel::match(const QModelIndex &start, int role, const QVariant &value, int hits, Qt::MatchFlags flags) const

Reimplements: QAbstractItemModel::match(const QModelIndex &start, int role, const QVariant &value, int hits, Qt::MatchFlags flags) const.

[override virtual] QMimeData *QRangeModel::mimeData(const QModelIndexList &indexes) const

Reimplements: QAbstractItemModel::mimeData(const QModelIndexList &indexes) const.

[override virtual] QStringList QRangeModel::mimeTypes() const

Reimplements: QAbstractItemModel::mimeTypes() const.

[override virtual] bool QRangeModel::moveColumns(const QModelIndex &sourceParent, int sourceColumn, int count, const QModelIndex &destinationParent, int destinationColumn)

Reimplements: QAbstractItemModel::moveColumns(const QModelIndex &sourceParent, int sourceColumn, int count, const QModelIndex &destinationParent, int destinationChild).

Verschiebt die Spalten count beginnend mit der angegebenen sourceColumn unter dem übergeordneten sourceParent in die Spalte destinationColumn unter dem übergeordneten destinationParent.

Gibt true zurück, wenn die Spalten erfolgreich verschoben wurden; andernfalls false.

[override virtual] bool QRangeModel::moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationRow)

Reimplements: QAbstractItemModel::moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild).

Verschiebt die Zeilen count beginnend mit der angegebenen sourceRow unter dem übergeordneten sourceParent in die Zeile destinationRow unter dem übergeordneten destinationParent.

Gibt true zurück, wenn die Zeilen erfolgreich verschoben wurden; andernfalls wird false zurückgegeben.

[override virtual] void QRangeModel::multiData(const QModelIndex &index, QModelRoleDataSpan roleDataSpan) const

Reimplements: QAbstractItemModel::multiData(const QModelIndex &index, QModelRoleDataSpan roleDataSpan) const.

[override virtual] QModelIndex QRangeModel::parent(const QModelIndex &child) const

Reimplements: QAbstractItemModel::parent(const QModelIndex &index) const.

Gibt das übergeordnete Element des Elements mit dem Index child zurück.

Diese Funktion erzeugt immer einen ungültigen Index für Modelle, die mit Listen- und Tabellenbereichen arbeiten. Bei Modellen, die auf einem Baum operieren, gibt diese Funktion den Index für das Zeilenelement zurück, der von der parent()-Implementierung des Tree-Traversal-Protokolls zurückgegeben wird.

Siehe auch index() und hasChildren().

[override virtual] bool QRangeModel::removeColumns(int column, int count, const QModelIndex &parent = {})

Reimplements: QAbstractItemModel::removeColumns(int column, int count, const QModelIndex &parent).

Entfernt count Spalten aus dem Element unter column in allen Zeilen des Bereichs unter parent. Gibt bei Erfolg true zurück, andernfalls false.

Hinweis: Ein dynamisch dimensionierter Zeilentyp muss eine erase(const_iterator, size_t) Memberfunktion bereitstellen.

Bei Modellen, die mit einem schreibgeschützten Bereich oder einem Bereich mit einem Zeilentyp statischer Größe (wie einem Tupel, Array oder Struct) arbeiten, tut diese Implementierung nichts und gibt sofort false zurück. Dies ist bei Baummodellen immer der Fall.

[override virtual] bool QRangeModel::removeRows(int row, int count, const QModelIndex &parent = {})

Reimplements: QAbstractItemModel::removeRows(int row, int count, const QModelIndex &parent).

Entfernt count Zeilen aus dem Bereich parent, beginnend mit dem angegebenen row. Gibt bei Erfolg true zurück, andernfalls false.

Hinweis: Der Bereich muss dynamisch skaliert sein und eine erase(const_iterator, size_t) Memberfunktion bereitstellen.

Bei Modellen, die mit einem schreibgeschützten oder statisch dimensionierten Bereich (z. B. einem Array) arbeiten, tut diese Implementierung nichts und gibt sofort false zurück.

[override virtual protected slot] void QRangeModel::resetInternalData()

Reimplements: QAbstractItemModel::resetInternalData().

[override virtual] QHash<int, QByteArray> QRangeModel::roleNames() const

Reimplements: QAbstractItemModel::roleNames() const.

Hinweis: Das Überschreiben dieser Funktion in einer QRangeModel Unterklasse ist möglich, kann aber das Verhalten der Eigenschaft beeinträchtigen.

Hinweis: Getter-Funktion für die Eigenschaft roleNames.

Siehe auch setRoleNames().

[override virtual] int QRangeModel::rowCount(const QModelIndex &parent = {}) const

Reimplements: QAbstractItemModel::rowCount(const QModelIndex &parent) const.

Gibt die Anzahl der Zeilen unter dem angegebenen parent zurück. Dies ist die Anzahl der Elemente im Wurzelbereich für einen ungültigen parent Index.

Wenn der Index parent gültig ist, gibt diese Funktion bei Modellen, die mit Listen- und Tabellenbereichen arbeiten, immer 0 zurück. Bei Bäumen gibt diese Funktion die Größe des Bereichs zurück, der von der childRows()-Implementierung des Tree-Traversal-Protokolls zurückgegeben wird.

Siehe auch columnCount(), insertRows(), und hasChildren().

[override virtual] bool QRangeModel::setData(const QModelIndex &index, const QVariant &data, int role = Qt::EditRole)

Reimplements: QAbstractItemModel::setData(const QModelIndex &index, const QVariant &value, int role).

Setzt die Daten von role für das Element unter index auf data.

Wenn der Elementtyp für dieses index ein assoziativer Container ist, der entweder int, Qt::ItemDataRole oder QString auf QVariant abbildet, dann wird data in diesem Container für den durch role angegebenen Schlüssel gespeichert.

Wenn das Element ein Gadget oder QObject ist, wird data in die Eigenschaft des Elements geschrieben, die dem Eintrag role in der Zuordnung roleNames() entspricht. Die Funktion gibt true zurück, wenn eine Eigenschaft gefunden wurde und data einen Wert gespeichert hat, der in den erforderlichen Typ konvertiert werden konnte, andernfalls gibt sie false zurück.

Andernfalls ordnet diese Implementierung den Wert in data dem Element an der index im Bereich für Qt::DisplayRole und Qt::EditRole zu und gibt true zurück. Für andere Rollen gibt die Implementierung false zurück.

Für Modelle, die auf einem schreibgeschützten Bereich oder auf einer schreibgeschützten Spalte in einem Zeilentyp arbeiten, der the C++ tuple protocol implementiert, gibt diese Implementierung sofort false zurück.

Siehe auch data().

[override virtual] bool QRangeModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &data, int role = Qt::EditRole)

Reimplements: QAbstractItemModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role).

Siehe auch headerData().

[override virtual] bool QRangeModel::setItemData(const QModelIndex &index, const QMap<int, QVariant> &data)

Reimplements: QAbstractItemModel::setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles).

Wenn der Elementtyp für diesen index ein assoziativer Container ist, der entweder int oder Qt::ItemDataRole auf QVariant abbildet, dann werden die Einträge in data in diesem Container gespeichert. Wenn der assoziative Container von QString auf QVariant abbildet, werden nur die Werte in data gespeichert, für die es eine Abbildung in der Tabelle role names gibt.

Handelt es sich bei dem Elementtyp um ein Gadget oder eine QObject Unterklasse, werden die Eigenschaften, die einer role name entsprechen, auf den entsprechenden Wert in data gesetzt.

Rollen, für die es keinen Eintrag in data gibt, werden nicht geändert.

Für Elementtypen, die kopiert werden können, ist diese Implementierung transaktional und gibt true zurück, wenn alle Einträge von data gespeichert werden konnten. Konnte ein Eintrag nicht aktualisiert werden, wird der ursprüngliche Container überhaupt nicht geändert und die Funktion gibt false zurück.

Wenn es sich bei dem Element nicht um einen assoziativen Container, ein Gadget oder eine QObject Unterklasse handelt, wird die Implementierung der Basisklasse aufgerufen, die setData() für jeden Eintrag in data aufruft.

Siehe auch itemData(), setData(), und Qt::ItemDataRole.

[override virtual] QModelIndex QRangeModel::sibling(int row, int column, const QModelIndex &index) const

Reimplements: QAbstractItemModel::sibling(int row, int column, const QModelIndex &index) const.

Gibt die Geschwister unter row und column für das Element unter index zurück, oder ein ungültiges QModelIndex, wenn es keine Geschwister an dieser Stelle gibt.

Diese Implementierung ist wesentlich schneller als die parent() der index zu durchlaufen.

Siehe auch index(), QModelIndex::row(), und QModelIndex::column().

[override virtual] void QRangeModel::sort(int column, Qt::SortOrder order = Qt::AscendingOrder)

Reimplements: QAbstractItemModel::sort(int column, Qt::SortOrder order).

[override virtual] QSize QRangeModel::span(const QModelIndex &index) const

Reimplements: QAbstractItemModel::span(const QModelIndex &index) const.

[override virtual] Qt::DropActions QRangeModel::supportedDragActions() const

Reimplements: QAbstractItemModel::supportedDragActions() const.

[override virtual] Qt::DropActions QRangeModel::supportedDropActions() const

Reimplements: QAbstractItemModel::supportedDropActions() const.

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.