Loading files
c730ec352This file is pinned to the selected release. Download the original to open it in your design tool.
/*
* LibrePCB - Professional EDA for everyone!
* Copyright (C) 2013 LibrePCB Developers, see AUTHORS.md for contributors.
* https://librepcb.org/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LIBREPCB_EDITOR_UIOBJECTLIST_H
#define LIBREPCB_EDITOR_UIOBJECTLIST_H
/*******************************************************************************
* Includes
******************************************************************************/
#include <librepcb/core/utils/signalslot.h>
#include <QtCore>
#include <memory>
#include <slint.h>
/*******************************************************************************
* Namespace / Forward Declarations
******************************************************************************/
namespace librepcb {
namespace editor {
/*******************************************************************************
* Class UiObjectList
******************************************************************************/
/**
* @brief The UiObjectList class
*/
template <typename TObj, typename TUiData>
class UiObjectList : public slint::Model<TUiData> {
public:
typedef TObj Element;
typedef TUiData UiData;
// Signals
enum class Event {
ElementAdded,
ElementRemoved,
ElementUiDataChanged,
};
Signal<UiObjectList<TObj, TUiData>, int, const std::shared_ptr<TObj>&, Event>
onEdited;
typedef Slot<UiObjectList<TObj, TUiData>, int, const std::shared_ptr<TObj>&,
Event>
OnEditedSlot;
// Constructors / Destructor
UiObjectList() noexcept
: onEdited(*this),
mObjects(),
mOnUiDataChangedSlot(
*this, &UiObjectList<TObj, TUiData>::elementUiDataChangedHandler) {}
UiObjectList(const UiObjectList& other) = delete;
~UiObjectList() noexcept override {}
// General Methods
int count() const noexcept { return mObjects.count(); }
bool isEmpty() const noexcept { return mObjects.isEmpty(); }
const std::shared_ptr<TObj>& at(int index) noexcept {
return mObjects.at(index);
}
std::shared_ptr<TObj> value(int index) noexcept {
return mObjects.value(index);
}
void append(const std::shared_ptr<TObj>& obj) noexcept {
insert(mObjects.count(), obj);
}
void insert(int index, const std::shared_ptr<TObj>& obj) noexcept {
Q_ASSERT(obj);
index = qBound(0, index, mObjects.count());
mObjects.insert(index, obj);
slint::Model<TUiData>::notify_row_added(index, 1);
obj->onUiDataChanged.attach(mOnUiDataChangedSlot);
onEdited.notify(index, obj, Event::ElementAdded);
}
bool remove(int index) noexcept { return takeAt(index) != nullptr; }
std::shared_ptr<TObj> take(const TObj* obj) noexcept {
if (auto index = indexOf(obj)) {
return takeAt(*index);
} else {
return nullptr;
}
}
std::shared_ptr<TObj> takeAt(int index) noexcept {
if (auto obj = mObjects.takeAt(index)) {
slint::Model<TUiData>::notify_row_removed(index, 1);
obj->onUiDataChanged.detach(mOnUiDataChangedSlot);
onEdited.notify(index, obj, Event::ElementRemoved);
return obj;
} else {
return nullptr;
}
}
void clear() noexcept {
for (int i = mObjects.count() - 1; i >= 0; --i) {
takeAt(i);
}
}
std::optional<int> indexOf(const TObj* obj) const noexcept {
for (int i = 0; i < mObjects.count(); ++i) {
if (mObjects.at(i).get() == obj) {
return i;
}
}
return std::nullopt;
}
const QVector<std::shared_ptr<TObj>>& values() { return mObjects; }
auto begin() noexcept { return mObjects.begin(); }
auto end() noexcept { return mObjects.end(); }
// Implementations
std::size_t row_count() const noexcept override {
return static_cast<std::size_t>(mObjects.count());
}
std::optional<TUiData> row_data(std::size_t i) const override {
if (auto obj = mObjects.value(i)) {
return obj->getUiData();
}
return std::nullopt;
}
void set_row_data(size_t i, const TUiData& data) noexcept override {
if (auto obj = mObjects.value(i)) {
obj->setUiData(data);
}
}
// Operator Overloadings
UiObjectList& operator=(const UiObjectList& rhs) = delete;
private:
void elementUiDataChangedHandler(const TObj& obj) noexcept {
if (auto index = indexOf(&obj)) {
slint::Model<TUiData>::notify_row_changed(*index);
onEdited.notify(*index, at(*index), Event::ElementUiDataChanged);
}
}
QVector<std::shared_ptr<TObj>> mObjects;
Slot<TObj> mOnUiDataChangedSlot;
};
/*******************************************************************************
* End of File
******************************************************************************/
} // namespace editor
} // namespace librepcb
#endif