AUI Framework  master
Cross-platform base for C++ UI apps
Loading...
Searching...
No Matches
AListModel.h
    1/*
    2 * AUI Framework - Declarative UI toolkit for modern C++20
    3 * Copyright (C) 2020-2025 Alex2772 and Contributors
    4 *
    5 * SPDX-License-Identifier: MPL-2.0
    6 *
    7 * This Source Code Form is subject to the terms of the Mozilla Public
    8 * License, v. 2.0. If a copy of the MPL was not distributed with this
    9 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
   10 */
   11
   12#pragma once
   13
   14#include <AUI/Common/AVector.h>
   15#include <AUI/Common/ASignal.h>
   16#include "AListModelIndex.h"
   17#include "IMutableListModel.h"
   18#include <AUI/Traits/strings.h>
   19
   20namespace aui::detail {
   21
   22}
   23
   24template <typename StoredType>
   25class AListModel: public IRemovableListModel<StoredType>,
   26                  public IValueMutableListModel<StoredType> {
   27private:
   28    AVector<StoredType> mVector;
   29
   30    using self = AListModel<StoredType>;
   31
   32public:
   33    using iterator = typename decltype(mVector)::iterator;
   34    using const_iterator = typename decltype(mVector)::const_iterator;
   35    using size_type = typename decltype(mVector)::size_type;
   36    using value_type = typename decltype(mVector)::value_type;
   37
   38    AListModel() = default;
   39    AListModel(const self& s): mVector(s.mVector) {}
   40    AListModel(self&& s) noexcept: mVector(std::move(s.mVector)) {}
   41    explicit AListModel(AVector<StoredType>&& vector) noexcept: mVector(std::move(vector)) {}
   42
   43    AListModel& operator=(AVector<StoredType>&& rhs) noexcept {
   44        clear();
   45        mVector = std::move(rhs);
   46        emit this->dataInserted(this->range(AListModelIndex(0),
   47                                            AListModelIndex(mVector.size())));
   48        return *this;
   49    }
   50
   51    void setItem(const AListModelIndex& item, const StoredType& value) override {
   52        mVector[item.getRow()] = value;
   53    }
   54
   55    [[nodiscard]]
   56    bool empty() const noexcept {
   57        return mVector.empty();
   58    }
   59    void reserve(size_t s) noexcept {
   60        mVector.reserve(s);
   61    }
   62    void resize(size_t s) noexcept {
   63        mVector.resize(s);
   64    }
   65
   66    iterator erase(iterator begin) noexcept  {
   67        return this->erase(begin, begin + 1);
   68    }
   69    iterator erase(iterator begin, iterator end) noexcept {
   70        if (!this->dataRemoved.hasOutgoingConnections()) {
   71            return mVector.erase(begin, end);
   72        }
   73
   74        auto range = this->range(AListModelIndex{size_t(begin - mVector.begin())},
   75                                 AListModelIndex{size_t(end   - mVector.begin())});
   76        auto it = mVector.erase(begin, end);
   77        emit this->dataRemoved(range);
   78        return it;
   79    }
   80
   81
   82    void push_back(const StoredType& data) {
   83        insert(end(), std::move(data));
   84    }
   85
   86    void push_back(StoredType&& data) {
   87        insert(end(), std::forward<StoredType>(data));
   88    }
   89
   90    auto insert(const_iterator at, StoredType data) -> decltype(mVector.insert(at, std::move(data))) {
   91        auto result = mVector.insert(at, std::move(data));
   92        if (!this->dataInserted.hasOutgoingConnections()) {
   93            return result;
   94        }
   95        emit this->dataInserted(this->range(AListModelIndex(result - begin()),
   96                                            AListModelIndex(result - begin() + 1)));
   97        return result;
   98    }
   99
  100    template<typename Iterator>
  101    auto insert(const_iterator at, Iterator begin, Iterator end) -> decltype(mVector.insert(at, begin, end)) {
  102        auto result = mVector.insert(at, begin, end);
  103        if (!this->dataInserted.hasOutgoingConnections()) {
  104            return result;
  105        }
  106        emit this->dataInserted(this->range(AListModelIndex(result - this->begin()),
  107                                            AListModelIndex(result - this->begin() + std::distance(begin, end))));
  108        return result;
  109    }
  110
  111    void pop_back() noexcept {
  112        mVector.pop_back();
  113        if (!this->dataRemoved.hasOutgoingConnections()) {
  114            return;
  115        }
  116        emit this->dataRemoved(this->range(AListModelIndex(mVector.size()    ),
  117                                           AListModelIndex(mVector.size() + 1)));
  118    }
  119
  120    AListModel& operator<<(const StoredType& data) {
  121        push_back(data);
  122        return *this;
  123    }
  124    AListModel& operator<<(StoredType&& data) {
  125        push_back(std::forward<StoredType>(data));
  126        return *this;
  127    }
  128
  129    size_t listSize() override {
  130        return mVector.size();
  131    }
  132
  133    StoredType listItemAt(const AListModelIndex& index) override {
  134        return mVector.at(index.getRow());
  135    }
  136
  137    void invalidate(size_t index) {
  138        if (!this->dataChanged.hasOutgoingConnections()) {
  139            return;
  140        }
  141        emit this->dataChanged(this->range(AListModelIndex(index), AListModelIndex(index + 1u)));
  142    }
  143
  144    void invalidate(iterator index) {
  145        invalidate(std::distance(begin(), index));
  146    }
  147
  148    void clear() noexcept {
  149        erase(mVector.begin(), mVector.end());
  150    }
  151
  152    void removeItems(const AListModelRange<StoredType>& items) override {
  153        erase(mVector.begin() + items.begin().getIndex().getRow(), mVector.end() + items.begin().getIndex().getRow());
  154    }
  155
  156    void removeItem(const AListModelIndex& item) override {
  157        erase(mVector.begin() + item.getRow());
  158    }
  159
  160    [[nodiscard]]
  161    size_t size() const noexcept {
  162        return mVector.size();
  163    }
  164
  176    const StoredType& at(size_t index) const {
  177        if (index >= size()) throw AException("index of bounds: {} (size {})"_format(index, size()));
  178        return *(mVector.begin() + index);
  179    }
  180
  199    StoredType& at(size_t index) {
  200        if (index >= size()) throw AException("index of bounds: {} (size {})"_format(index, size()));
  201        return *(mVector.begin() + index);
  202    }
  203
  211    const StoredType& operator[](size_t index) const {
  212        AUI_ASSERTX(size() > index, "index out of bounds");
  213        return *(mVector.begin() + index);
  214    }
  215
  224    void removeAt(size_t index) noexcept
  225    {
  226        aui::container::remove_at(*this, index);
  227    }
  228
  229    const_iterator begin() const {
  230        return mVector.begin();
  231    }
  232    const_iterator end() const {
  233        return mVector.end();
  234    }
  235
  236    iterator begin() {
  237        return mVector.begin();
  238    }
  239    iterator end() {
  240        return mVector.end();
  241    }
  242
  250    template<typename V = StoredType>
  251    static _<AListModel<StoredType>> make(const std::initializer_list<V>& t) {
  252        auto list = _new<AListModel<StoredType>>();
  253        list->reserve(t.size());
  254        for (auto& item : t) {
  255            list->push_back(item);
  256        }
  257        return list;
  258    }
  259
  267    template<typename V = StoredType>
  269        auto list = _new<AListModel<StoredType>>();
  270        list->mVector = std::move(t);
  271        return list;
  272    }
  273
  281    template<typename V>
  282    static _<AListModel<StoredType>> fromVector(std::vector<V> t) {
  283        auto list = _new<AListModel<StoredType>>();
  284        list->mVector = AVector<StoredType>(std::vector<StoredType>(std::move(t)));
  285        return list;
  286    }
  287
  288    template<typename UnaryOperation>
  289    auto map(UnaryOperation&& transformer) {
  290        return mVector.map(std::forward<UnaryOperation>(transformer));
  291    }
  292
  293    [[nodiscard]]
  294    const AVector<StoredType>& toVector() noexcept {
  295        return mVector;
  296    }
  297
  298    [[nodiscard]]
  299    bool operator==(const AListModel& rhs) const noexcept {
  300        return mVector == rhs.mVector;
  301    }
  302
  303    [[nodiscard]]
  304    bool operator!=(const AListModel& rhs) const noexcept {
  305        return mVector != rhs.mVector;
  306    }
  307};
Abstract AUI exception.
Definition AException.h:28
Definition AListModelIndex.h:20
Definition AListModelRange.h:23
static _< AListModel< StoredType > > fromVector(std::vector< V > t)
Definition AListModel.h:282
static _< AListModel< StoredType > > fromVector(AVector< V > t)
Definition AListModel.h:268
void removeAt(size_t index) noexcept
Definition AListModel.h:224
StoredType & at(size_t index)
Definition AListModel.h:199
const StoredType & operator[](size_t index) const
Definition AListModel.h:211
const StoredType & at(size_t index) const
Definition AListModel.h:176
static _< AListModel< StoredType > > make(const std::initializer_list< V > &t)
Definition AListModel.h:251
A std::vector with AUI extensions.
Definition AVector.h:39
emits< AListModelRange< StoredType > > dataInserted
Definition IListModel.h:88
emits< AListModelRange< StoredType > > dataChanged
Definition IListModel.h:83
emits< AListModelRange< StoredType > > dataRemoved
Definition IListModel.h:93
Definition IMutableListModel.h:20
Definition IMutableListModel.h:36
An std::weak_ptr with AUI extensions.
Definition SharedPtrTypes.h:179
void remove_at(Container &c, size_t index) noexcept
Removes element at the specified index.
Definition containers.h:98
#define emit
emits the specified signal in context of this object.
Definition AObject.h:343
#define AUI_ASSERTX(condition, what)
Asserts that the passed condition evaluates to true. Adds extra message string.
Definition Assert.h:74