DataSourceItem.cpp
221 lines
| 5.7 KiB
| text/x-c
|
CppLexer
r0 | #include <DataSource/DataSourceItem.h> | |||
#include <DataSource/DataSourceItemAction.h> | ||||
#include <DataSource/DataSourceItemMergeHelper.h> | ||||
#include <QVector> | ||||
r73 | const QString DataSourceItem::NAME_DATA_KEY = QStringLiteral("name"); | |||
r0 | const QString DataSourceItem::PLUGIN_DATA_KEY = QStringLiteral("plugin"); | |||
r73 | const QString DataSourceItem::ID_DATA_KEY = QStringLiteral("uuid"); | |||
r0 | ||||
r73 | struct DataSourceItem::DataSourceItemPrivate | |||
{ | ||||
explicit DataSourceItemPrivate(DataSourceItemType type, QVariantHash data) | ||||
: m_Parent{nullptr}, | ||||
m_Children{}, m_Type{type}, m_Data{std::move(data)}, m_Actions{} | ||||
{} | ||||
r0 | ||||
r73 | DataSourceItem* m_Parent; | |||
std::vector<std::unique_ptr<DataSourceItem>> m_Children; | ||||
DataSourceItemType m_Type; | ||||
QVariantHash m_Data; | ||||
std::vector<std::unique_ptr<DataSourceItemAction>> m_Actions; | ||||
r0 | }; | |||
r73 | DataSourceItem::DataSourceItem(DataSourceItemType type, const QString& name) | |||
: DataSourceItem{type, QVariantHash{{NAME_DATA_KEY, name}}} | ||||
{} | ||||
r0 | ||||
DataSourceItem::DataSourceItem(DataSourceItemType type, QVariantHash data) | ||||
r73 | : impl{spimpl::make_unique_impl<DataSourceItemPrivate>(type, | |||
std::move(data))} | ||||
{} | ||||
r0 | ||||
std::unique_ptr<DataSourceItem> DataSourceItem::clone() const | ||||
{ | ||||
r73 | auto result = std::make_unique<DataSourceItem>(impl->m_Type, impl->m_Data); | |||
r0 | ||||
r73 | // Clones children | |||
for(const auto& child : impl->m_Children) | ||||
{ | ||||
result->appendChild(std::move(child->clone())); | ||||
} | ||||
r0 | ||||
r73 | // Clones actions | |||
for(const auto& action : impl->m_Actions) | ||||
{ | ||||
result->addAction(std::move(action->clone())); | ||||
} | ||||
r0 | ||||
r73 | return result; | |||
r0 | } | |||
r73 | QVector<DataSourceItemAction*> DataSourceItem::actions() const noexcept | |||
r0 | { | |||
r73 | auto result = QVector<DataSourceItemAction*>{}; | |||
r0 | ||||
r73 | std::transform(std::cbegin(impl->m_Actions), std::cend(impl->m_Actions), | |||
std::back_inserter(result), | ||||
[](const auto& action) { return action.get(); }); | ||||
r0 | ||||
r73 | return result; | |||
r0 | } | |||
r73 | void DataSourceItem::addAction( | |||
std::unique_ptr<DataSourceItemAction> action) noexcept | ||||
r0 | { | |||
r73 | action->setDataSourceItem(this); | |||
impl->m_Actions.push_back(std::move(action)); | ||||
r0 | } | |||
void DataSourceItem::appendChild(std::unique_ptr<DataSourceItem> child) noexcept | ||||
{ | ||||
r73 | child->impl->m_Parent = this; | |||
impl->m_Children.push_back(std::move(child)); | ||||
r0 | } | |||
r73 | DataSourceItem* DataSourceItem::child(int childIndex) const noexcept | |||
r0 | { | |||
r73 | if(childIndex < 0 || childIndex >= childCount()) { return nullptr; } | |||
else | ||||
{ | ||||
return impl->m_Children.at(childIndex).get(); | ||||
} | ||||
r0 | } | |||
int DataSourceItem::childCount() const noexcept | ||||
{ | ||||
r73 | return impl->m_Children.size(); | |||
r0 | } | |||
r73 | QVariant DataSourceItem::data(const QString& key) const noexcept | |||
r0 | { | |||
r73 | return impl->m_Data.value(key); | |||
r0 | } | |||
r73 | QVariantHash DataSourceItem::data() const noexcept { return impl->m_Data; } | |||
r0 | ||||
r73 | void DataSourceItem::merge(const DataSourceItem& item) | |||
r0 | { | |||
r73 | DataSourceItemMergeHelper::merge(item, *this); | |||
r0 | } | |||
bool DataSourceItem::isRoot() const noexcept | ||||
{ | ||||
r73 | return impl->m_Parent == nullptr; | |||
r0 | } | |||
QString DataSourceItem::name() const noexcept | ||||
{ | ||||
r73 | return data(NAME_DATA_KEY).toString(); | |||
r0 | } | |||
r73 | DataSourceItem* DataSourceItem::parentItem() const noexcept | |||
r0 | { | |||
r73 | return impl->m_Parent; | |||
r0 | } | |||
r73 | const DataSourceItem& DataSourceItem::rootItem() const noexcept | |||
r0 | { | |||
r73 | return isRoot() ? *this : parentItem()->rootItem(); | |||
r0 | } | |||
r73 | void DataSourceItem::setData(const QString& key, const QVariant& value, | |||
bool append) noexcept | ||||
r0 | { | |||
r73 | auto it = impl->m_Data.constFind(key); | |||
if(append && it != impl->m_Data.constEnd()) | ||||
{ | ||||
// Case of an existing value to which we want to add to the new value | ||||
if(it->canConvert<QVariantList>()) | ||||
{ | ||||
auto variantList = it->value<QVariantList>(); | ||||
variantList.append(value); | ||||
r0 | ||||
r73 | impl->m_Data.insert(key, variantList); | |||
r0 | } | |||
r73 | else | |||
{ | ||||
impl->m_Data.insert(key, QVariantList{*it, value}); | ||||
r0 | } | |||
r73 | } | |||
else | ||||
{ | ||||
// Other cases : | ||||
// - new value in map OR | ||||
// - replacement of an existing value (not appending) | ||||
impl->m_Data.insert(key, value); | ||||
} | ||||
r0 | } | |||
DataSourceItemType DataSourceItem::type() const noexcept | ||||
{ | ||||
r73 | return impl->m_Type; | |||
r0 | } | |||
r73 | DataSourceItem* DataSourceItem::findItem(const QVariantHash& data, | |||
bool recursive) | ||||
r0 | { | |||
r73 | for(const auto& child : impl->m_Children) | |||
{ | ||||
if(child->impl->m_Data == data) { return child.get(); } | ||||
r0 | ||||
r73 | if(recursive) | |||
{ | ||||
if(auto foundItem = child->findItem(data, true)) { return foundItem; } | ||||
r0 | } | |||
r73 | } | |||
r0 | ||||
r73 | return nullptr; | |||
r0 | } | |||
r73 | DataSourceItem* DataSourceItem::findItem(const QString& name) | |||
r0 | { | |||
r73 | auto item = | |||
std::find_if(std::cbegin(impl->m_Children), std::cend(impl->m_Children), | ||||
[name](const auto& item) { return item->name() == name; }); | ||||
if(item != std::cend(impl->m_Children)) return item->get(); | ||||
return nullptr; | ||||
} | ||||
r0 | ||||
r73 | DataSourceItem* DataSourceItem::findItem(const QString& datasourceIdKey, | |||
bool recursive) | ||||
{ | ||||
for(const auto& child : impl->m_Children) | ||||
{ | ||||
auto childId = child->impl->m_Data.value(ID_DATA_KEY); | ||||
if(childId == datasourceIdKey) { return child.get(); } | ||||
if(recursive) | ||||
{ | ||||
if(auto foundItem = child->findItem(datasourceIdKey, true)) | ||||
{ return foundItem; } | ||||
r0 | } | |||
r73 | } | |||
r0 | ||||
r73 | return nullptr; | |||
r0 | } | |||
r73 | bool DataSourceItem::operator==(const DataSourceItem& other) | |||
r0 | { | |||
r73 | // Compares items' attributes | |||
if(std::tie(impl->m_Type, impl->m_Data) == | ||||
std::tie(other.impl->m_Type, other.impl->m_Data)) | ||||
{ | ||||
// Compares contents of items' children | ||||
return std::equal( | ||||
std::cbegin(impl->m_Children), std::cend(impl->m_Children), | ||||
std::cbegin(other.impl->m_Children), std::cend(other.impl->m_Children), | ||||
[](const auto& itemChild, const auto& otherChild) { | ||||
return *itemChild == *otherChild; | ||||
}); | ||||
} | ||||
else | ||||
{ | ||||
return false; | ||||
} | ||||
r0 | } | |||
r73 | bool DataSourceItem::operator!=(const DataSourceItem& other) | |||
r0 | { | |||
r73 | return !(*this == other); | |||
r0 | } | |||