diff --git a/include/Data/IDataProvider.h b/include/Data/IDataProvider.h index d72009c..4f856c5 100644 --- a/include/Data/IDataProvider.h +++ b/include/Data/IDataProvider.h @@ -43,6 +43,8 @@ public: { return QString("%1-%2").arg(this->metaObject()->className()).arg(id().toString()); } + + operator QUuid(){return _id;} signals: diff --git a/include/DataSource/DataSourceItem.h b/include/DataSource/DataSourceItem.h index 1ee86ab..51ac5f4 100644 --- a/include/DataSource/DataSourceItem.h +++ b/include/DataSource/DataSourceItem.h @@ -4,10 +4,12 @@ #include "CoreGlobal.h" #include +#include #include #include #include #include +#include #include class DataSourceItemAction; @@ -43,8 +45,9 @@ public: /// Key associated with a unique id of the plugin static const QString ID_DATA_KEY; - explicit DataSourceItem(DataSourceItemType type, const QString& name); - explicit DataSourceItem(DataSourceItemType type, QVariantHash data = {}); + //explicit DataSourceItem(DataSourceItemType type, const QString& name); + explicit DataSourceItem(DataSourceItemType type, const QString& name, QVariantHash data = {}, + std::optional sourceUUID = std::nullopt); std::unique_ptr clone() const; @@ -128,7 +131,15 @@ public: bool isRoot() const noexcept; + inline bool isProductOrComponent() const noexcept + { + return (this->type() == DataSourceItemType::PRODUCT) || + (this->type() == DataSourceItemType::COMPONENT); + } + QString name() const noexcept; + QString icon() const noexcept; + void setIcon(const QString& iconName); /** * Get the item's parent @@ -183,8 +194,10 @@ public: const_iterator_type cbegin() const noexcept; const_iterator_type cend() const noexcept; + std::optional source_uuid() const noexcept; + private: - class DataSourceItemPrivate; + struct DataSourceItemPrivate; spimpl::unique_impl_ptr impl; }; diff --git a/include/DataSource/DataSourcesFilter.h b/include/DataSource/DataSourcesFilter.h new file mode 100644 index 0000000..a4493e4 --- /dev/null +++ b/include/DataSource/DataSourcesFilter.h @@ -0,0 +1,55 @@ +/*------------------------------------------------------------------------------ + * -- This file is a part of SciQLop + * -- Copyright (C) 2019, Plasma Physics Laboratory - CNRS + * -- + * -- 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, write to the Free Software + * -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * -------------------------------------------------------------------------------*/ +/* -- Author : Alexis Jeandet + * -- Mail : alexis.jeandet@lpp.polytechnique.fr + * -- alexis.jeandet@member.fsf.org + * ----------------------------------------------------------------------------*/ +#ifndef DATASOURCESFILTER_H_INCLUDED +#define DATASOURCESFILTER_H_INCLUDED + +#include "DataSourceItem.h" + +#include +#include + +class DataSourceFilter : public QSortFilterProxyModel +{ + Q_OBJECT +public: + explicit DataSourceFilter(QObject* parent = nullptr); + + bool filterAcceptsRow(int sourceRow, + const QModelIndex& sourceParent) const override + { + if(filterRegExp().isEmpty()) { return true; } + DataSourceItem* childItem = static_cast( + sourceModel()->index(sourceRow, 0, sourceParent).internalPointer()); + if(childItem) + { + auto data = childItem->data(); + return (std::find_if(std::cbegin(data), std::cend(data), + [regex = filterRegExp()](const auto& item) { + return item.toString().contains(regex); + }) != std::cend(data)); + } + return false; + } +}; + +#endif // DATASOURCESFILTER_H_INCLUDED diff --git a/include/DataSource/datasources.h b/include/DataSource/datasources.h index d6f54af..9b287f0 100644 --- a/include/DataSource/datasources.h +++ b/include/DataSource/datasources.h @@ -1,4 +1,3 @@ - /*------------------------------------------------------------------------------ * -- This file is a part of SciQLop * -- Copyright (C) 2019, Plasma Physics Laboratory - CNRS @@ -29,6 +28,8 @@ #include "DataSourceItem.h" #include +#include +#include class DataSources : public QAbstractItemModel { @@ -41,28 +42,49 @@ public: }; public: - DataSources() : _root{} {} + DataSources() : _root(new DataSourceItem(DataSourceItemType::NODE, "root")) {} ~DataSources() { delete _root; } - virtual QVariant data(const QModelIndex& index, int role) const override; + virtual QVariant data(const QModelIndex& index, int role) const final; + virtual QMimeData* mimeData(const QModelIndexList& indexes) const final; - int columnCount(const QModelIndex& parent) const override; + virtual int columnCount(const QModelIndex& parent) const final; - virtual int rowCount(const QModelIndex& parent) const override; + virtual int rowCount(const QModelIndex& parent) const final; - QModelIndex parent(const QModelIndex& index) const override; + QModelIndex parent(const QModelIndex& index) const final; virtual QModelIndex index(int row, int column, - const QModelIndex& parent) const override; + const QModelIndex& parent) const final; + + Qt::ItemFlags flags(const QModelIndex& index) const final; void addDataSourceItem(const QUuid& providerUid, const QString& path, const QMap& metaData) noexcept; void addProvider(IDataProvider* provider) noexcept; + void updateNodeMetaData(const QString& path, + const QMap& metaData) noexcept; + + void createVariable(const DataSourceItem& item); + + void addIcon(const QString& name, QVariant icon) + { + _icons[name] = std::move(icon); + } + + void setIcon(const QString& path, const QString& iconName); + +Q_SIGNALS: + void createVariable(const QString& variableName, + const QVariantHash& variableMetadata, + std::shared_ptr variableProvider); + private: DataSourceItem* _root; std::map> _DataProviders; + QHash _icons; }; #endif // DATASOURCES_H diff --git a/meson.build b/meson.build index 7879638..74ea9db 100644 --- a/meson.build +++ b/meson.build @@ -31,6 +31,7 @@ core_moc_headers = [ './include/Settings/ISqpSettingsBindable.h', './include/DataSource/DataSourceController.h', './include/DataSource/datasources.h', + './include/DataSource/DataSourcesFilter.h', './include/DataSource/DataSourceItem.h', './include/DataSource/DataSourceItemAction.h', './include/DataSource/DataSourceItemMergeHelper.h', @@ -63,6 +64,7 @@ core_sources = ['./src/Common/MimeTypesDef.cpp', './src/DataSource/DataSourceItem.cpp', './src/DataSource/DataSourceController.cpp', './src/DataSource/datasources.cpp', + './src/DataSource/DataSourcesFilter.cpp', './src/Time/TimeController.cpp', './src/PluginManager/PluginManager.cpp', './src/Version.cpp', diff --git a/src/DataSource/DataSourceController.cpp b/src/DataSource/DataSourceController.cpp index 8f41043..7ececa0 100644 --- a/src/DataSource/DataSourceController.cpp +++ b/src/DataSource/DataSourceController.cpp @@ -40,15 +40,16 @@ std::unique_ptr make_product_item(const QVariantHash& metaData, const QUuid& dataSourceUid, const QString& DATA_SOURCE_NAME, DataSourceController* dc) { + auto productName = metaData.value(DataSourceItem::NAME_DATA_KEY).toString(); auto result = - std::make_unique(DataSourceItemType::PRODUCT, metaData); + std::make_unique(DataSourceItemType::PRODUCT,productName, metaData); // Adds plugin name to product metadata result->setData(DataSourceItem::PLUGIN_DATA_KEY, DATA_SOURCE_NAME); result->setData(DataSourceItem::ID_DATA_KEY, metaData.value(DataSourceItem::NAME_DATA_KEY)); - auto productName = metaData.value(DataSourceItem::NAME_DATA_KEY).toString(); + // Add action to load product from DataSourceController result->addAction(std::make_unique( diff --git a/src/DataSource/DataSourceItem.cpp b/src/DataSource/DataSourceItem.cpp index ca39380..2adf2fc 100644 --- a/src/DataSource/DataSourceItem.cpp +++ b/src/DataSource/DataSourceItem.cpp @@ -1,8 +1,10 @@ #include #include #include +#include #include #include +#include const QString DataSourceItem::NAME_DATA_KEY = QStringLiteral("name"); const QString DataSourceItem::PLUGIN_DATA_KEY = QStringLiteral("plugin"); @@ -10,42 +12,63 @@ const QString DataSourceItem::ID_DATA_KEY = QStringLiteral("uuid"); struct DataSourceItem::DataSourceItemPrivate { - explicit DataSourceItemPrivate(DataSourceItemType type, QVariantHash data) - : m_Parent{nullptr}, - m_Children{}, m_Type{type}, m_Data{std::move(data)}, m_Actions{} - {} + explicit DataSourceItemPrivate(DataSourceItemType type, const QString& name, + QVariantHash data, + std::optional sourceUUID = std::nullopt) + : m_Parent{nullptr}, m_dataSourceUid{sourceUUID}, m_Children{}, + m_name{name}, m_Type{type}, m_Data{std::move(data)}, m_Actions{} + { + m_Data[DataSourceItem::NAME_DATA_KEY] = name; + } DataSourceItem* m_Parent; + std::optional m_dataSourceUid = std::nullopt; std::vector> m_Children; + QString m_icon; + QString m_name; DataSourceItemType m_Type; - //TODO check if QVariant is really wise here, looks quite overkill + // TODO check if QVariant is really wise here, looks quite overkill // maybe a simple map could be enough QVariantHash m_Data; std::vector> m_Actions; - auto begin()noexcept{return m_Children.begin();} - auto end()noexcept{return m_Children.end();} - auto cbegin()const noexcept{return m_Children.cbegin();} - auto cend()const noexcept{return m_Children.cend();} - + auto begin() noexcept { return m_Children.begin(); } + auto end() noexcept { return m_Children.end(); } + auto cbegin() const noexcept { return m_Children.cbegin(); } + auto cend() const noexcept { return m_Children.cend(); } + inline std::optional source_uuid() const noexcept + { + return m_dataSourceUid; + } int index_of(const DataSourceItem* item) { - return std::distance( - std::cbegin(m_Children), std::find_if(std::cbegin(m_Children), std::cend(m_Children), [item](const auto& other){return other.get()==item;})); + return std::distance(std::cbegin(m_Children), + std::find_if(std::cbegin(m_Children), + std::cend(m_Children), + [item](const auto& other) { + return other.get() == item; + })); } + inline QString name() const noexcept { return m_name; } + inline QString icon() const noexcept { return m_icon; } + inline void setIcon(const QString& iconName) { m_icon = iconName; } }; -DataSourceItem::DataSourceItem(DataSourceItemType type, const QString& name) - : DataSourceItem{type, QVariantHash{{NAME_DATA_KEY, name}}} -{} +// DataSourceItem::DataSourceItem(DataSourceItemType type, const QString& name) +// : DataSourceItem{type,name, QVariantHash{{NAME_DATA_KEY, name}}} +//{} -DataSourceItem::DataSourceItem(DataSourceItemType type, QVariantHash data) - : impl{spimpl::make_unique_impl(type, - std::move(data))} +DataSourceItem::DataSourceItem(DataSourceItemType type, const QString& name, + QVariantHash data, + std::optional sourceUUID) + : impl{spimpl::make_unique_impl( + type, name, std::move(data), sourceUUID)} {} +// TODO remove this method ASAP std::unique_ptr DataSourceItem::clone() const { - auto result = std::make_unique(impl->m_Type, impl->m_Data); + auto result = std::make_unique(impl->m_Type, impl->m_name, + impl->m_Data); // Clones children for(const auto& child : impl->m_Children) @@ -117,9 +140,13 @@ bool DataSourceItem::isRoot() const noexcept return impl->m_Parent == nullptr; } -QString DataSourceItem::name() const noexcept +QString DataSourceItem::name() const noexcept { return impl->name(); } + +QString DataSourceItem::icon() const noexcept { return impl->icon(); } + +void DataSourceItem::setIcon(const QString& iconName) { - return data(NAME_DATA_KEY).toString(); + impl->setIcon(iconName); } DataSourceItem* DataSourceItem::parentItem() const noexcept @@ -129,11 +156,9 @@ DataSourceItem* DataSourceItem::parentItem() const noexcept int DataSourceItem::index() const noexcept { - if(auto parent = parentItem(); parent) - { - return parent->impl->index_of(this); - } - return 0; + if(auto parent = parentItem(); parent) + { return parent->impl->index_of(this); } + return 0; } const DataSourceItem& DataSourceItem::rootItem() const noexcept @@ -271,3 +296,8 @@ DataSourceItem::const_iterator_type DataSourceItem::end() const noexcept { return impl->cend(); } + +std::optional DataSourceItem::source_uuid() const noexcept +{ + return impl->source_uuid(); +} diff --git a/src/DataSource/DataSourcesFilter.cpp b/src/DataSource/DataSourcesFilter.cpp new file mode 100644 index 0000000..2f791a8 --- /dev/null +++ b/src/DataSource/DataSourcesFilter.cpp @@ -0,0 +1,28 @@ +/*------------------------------------------------------------------------------ + * -- This file is a part of SciQLop + * -- Copyright (C) 2019, Plasma Physics Laboratory - CNRS + * -- + * -- 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, write to the Free Software + * -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * -------------------------------------------------------------------------------*/ +/* -- Author : Alexis Jeandet + * -- Mail : alexis.jeandet@lpp.polytechnique.fr + * -- alexis.jeandet@member.fsf.org + * ----------------------------------------------------------------------------*/ + +#include "DataSource/DataSourcesFilter.h" + +DataSourceFilter::DataSourceFilter(QObject* parent) + : QSortFilterProxyModel(parent) +{} diff --git a/src/DataSource/datasources.cpp b/src/DataSource/datasources.cpp index 9b242ae..a7f3d20 100644 --- a/src/DataSource/datasources.cpp +++ b/src/DataSource/datasources.cpp @@ -24,49 +24,109 @@ #include "DataSource/datasources.h" +#include "Common/MimeTypesDef.h" +#include "DataSource/DataSourceItemAction.h" +#include "containers/algorithms.hpp" + +#include + +QString QVariant2QString(const QVariant& variant) noexcept +{ + if(variant.canConvert()) + { + auto valueString = QStringLiteral("{"); + auto variantList = variant.value(); + QStringList items; + std::transform(std::cbegin(variantList), std::cend(variantList), + std::back_inserter(items), + [](const auto& item) { return QVariant2QString(item); }); + valueString.append(cpp_utils::containers::join(items, ", ")); + valueString.append("}"); + return valueString; + } + else + { + return variant.toString(); + } +} + inline std::unique_ptr make_folder_item(const QString& name) { return std::make_unique(DataSourceItemType::NODE, name); } template -DataSourceItem* make_path_items(const T& path_list_begin, - const T& path_list_end, DataSourceItem* root) +DataSourceItem* walk_tree( + const T& path_list_begin, const T& path_list_end, DataSourceItem* root, + const std::function())&)>& + f = [](DataSourceItem* parent, DataSourceItem* node, + const auto& name) -> DataSourceItem* { + (void)parent; + (void)name; + return node; + }) { std::for_each(path_list_begin, path_list_end, - [&root](const auto& folder_name) mutable { + [&root, &f](const auto& folder_name) mutable { auto folder_ptr = root->findItem(folder_name); - if(folder_ptr == nullptr) - { - auto folder = make_folder_item(folder_name); - folder_ptr = folder.get(); - root->appendChild(std::move(folder)); - } - root = folder_ptr; + root = f(root, folder_ptr, folder_name); }); return root; } +DataSourceItem* walk_tree( + const QString& path, DataSourceItem* root, + const std::function& f = + [](DataSourceItem* parent, DataSourceItem* node, + const auto& name) -> DataSourceItem* { + (void)parent; + (void)name; + return node; + }) +{ + auto path_list = path.split('/', QString::SkipEmptyParts); + return walk_tree(std::cbegin(path_list), std::cend(path_list), root, f); +} + +template +DataSourceItem* make_path_items(const T& path_list_begin, + const T& path_list_end, DataSourceItem* root) +{ + auto node_ctor = [](DataSourceItem* parent, DataSourceItem* node, + const auto& name) -> DataSourceItem* { + if(node == nullptr) + { + auto folder = make_folder_item(name); + node = folder.get(); + parent->appendChild(std::move(folder)); + } + return node; + }; + return walk_tree(path_list_begin, path_list_end, root, node_ctor); +} + inline std::unique_ptr -make_product_item(const QVariantHash& metaData, const QUuid& dataSourceUid, - const QString& DATA_SOURCE_NAME, DataSources* dc) +make_product_item(const QString& name, QVariantHash& metaData, + const QUuid& dataSourceUid, const QString& DATA_SOURCE_NAME, + DataSources* dataSources) { - auto result = - std::make_unique(DataSourceItemType::PRODUCT, metaData); + auto result = std::make_unique(DataSourceItemType::PRODUCT, + name, metaData, dataSourceUid); // Adds plugin name to product metadata + // TODO re-consider adding a name attribute to DataSourceItem class result->setData(DataSourceItem::PLUGIN_DATA_KEY, DATA_SOURCE_NAME); - result->setData(DataSourceItem::ID_DATA_KEY, - metaData.value(DataSourceItem::NAME_DATA_KEY)); - - auto productName = metaData.value(DataSourceItem::NAME_DATA_KEY).toString(); + // result->setData(DataSourceItem::ID_DATA_KEY, + // metaData.value(DataSourceItem::NAME_DATA_KEY)); - // Add action to load product from DataSourceController - // result->addAction(std::make_unique( - // QObject::tr("Load %1 product").arg(productName), - // [productName, dataSourceUid, dc](DataSourceItem& item) { - // if(dc) { dc->loadProductItem(dataSourceUid, item); } - // })); + // Add action to load product from DataSources + result->addAction(std::make_unique( + QObject::tr("Load %1 product").arg(name), + [dataSources](DataSourceItem& item) { + if(dataSources) { dataSources->createVariable(item); } + })); return result; } @@ -74,15 +134,51 @@ make_product_item(const QVariantHash& metaData, const QUuid& dataSourceUid, QVariant DataSources::data(const QModelIndex& index, int role) const { if(!index.isValid()) return QVariant(); - if(role != Qt::DisplayRole) return QVariant(); DataSourceItem* item = static_cast(index.internalPointer()); - return item->name(); + if(role == Qt::DisplayRole) { return item->name(); } + if(role == Qt::DecorationRole) + { return _icons.value(item->icon(), QVariant{}); } + if(role == Qt::ToolTipRole) + { + auto result = QString{}; + const auto& data = item->data(); + std::for_each(data.constKeyValueBegin(), data.constKeyValueEnd(), + [&result](const auto& item) { + result.append(QString{"%1: %2
"}.arg( + item.first, QVariant2QString(item.second))); + }); + return result; + } + return QVariant(); +} + +QMimeData* DataSources::mimeData(const QModelIndexList& indexes) const +{ + QVariantList productData; + std::for_each(std::cbegin(indexes), std::cend(indexes), + [&productData](const auto& index) { + if(index.isValid()) + { + DataSourceItem* item = + static_cast(index.internalPointer()); + if(item->isProductOrComponent()) + { productData.append(item->data()); } + } + }); + // TODO refactor this later + // maybe just an encode function + QByteArray encodedData; + QDataStream stream{&encodedData, QIODevice::WriteOnly}; + stream << productData; + auto mimeData = new QMimeData; + mimeData->setData(MIME_TYPE_PRODUCT_LIST, encodedData); + return mimeData; } int DataSources::columnCount(const QModelIndex& parent) const { (void)parent; - return 0; + return 1; } int DataSources::rowCount(const QModelIndex& parent) const @@ -120,10 +216,28 @@ QModelIndex DataSources::index(int row, int column, return QModelIndex(); } +Qt::ItemFlags DataSources::flags(const QModelIndex& index) const +{ + Qt::ItemFlags flags = Qt::NoItemFlags; + if(index.isValid()) + { + flags |= Qt::ItemIsSelectable | Qt::ItemIsEnabled; + DataSourceItem* item = + static_cast(index.internalPointer()); + if(item && item->isProductOrComponent()) + { flags |= Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; } + } + return flags; +} + +// TODO This can be optimized to only use insert row and column +// this should be much faster than doing a ResetModel all the time +// but this is more difficult to implement void DataSources::addDataSourceItem( const QUuid& providerUid, const QString& path, const QMap& metaData) noexcept { + beginResetModel(); auto path_list = path.split('/', QString::SkipEmptyParts); auto name = *(std::cend(path_list) - 1); auto path_item = @@ -134,7 +248,8 @@ void DataSources::addDataSourceItem( meta_data[key] = metaData[key]; } path_item->appendChild( - make_product_item(meta_data, providerUid, "test", this)); + make_product_item(name, meta_data, providerUid, "test", this)); + endResetModel(); } void DataSources::addProvider(IDataProvider* provider) noexcept @@ -142,3 +257,32 @@ void DataSources::addProvider(IDataProvider* provider) noexcept _DataProviders.insert( {provider->id(), std::unique_ptr{provider}}); } + +void DataSources::updateNodeMetaData( + const QString& path, const QMap& metaData) noexcept +{ + auto node = walk_tree(path, _root); + if(node != nullptr) + { + std::for_each( + metaData.constKeyValueBegin(), metaData.constKeyValueEnd(), + [node](const auto& it) { node->setData(it.first, it.second, true); }); + } +} + +void DataSources::createVariable(const DataSourceItem& item) +{ + if(auto ds_uuid = item.source_uuid(); + ds_uuid.has_value() && item.isProductOrComponent()) + { + if(auto data_source_it = _DataProviders.find(ds_uuid.value()); + data_source_it != std::cend(_DataProviders)) + emit createVariable(item.name(), item.data(), data_source_it->second); + } +} + +void DataSources::setIcon(const QString& path, const QString& iconName) +{ + auto node = walk_tree(path, _root); + if(node != nullptr) { node->setIcon(iconName); } +} diff --git a/tests/Data/TestDateTimeRange.cpp b/tests/Data/TestDateTimeRange.cpp index 10a4d3e..19c7109 100644 --- a/tests/Data/TestDateTimeRange.cpp +++ b/tests/Data/TestDateTimeRange.cpp @@ -30,7 +30,7 @@ private slots: QTest::addColumn("tend"); QTest::addColumn("expected"); auto now = QDateTime::currentDateTime(); - auto yesterday = QDateTime::currentDateTime().addDays(-1); + auto yesterday = now.addDays(-1); QTest::newRow("No delta") << now << now << 0.; QTest::newRow("One day delta") << yesterday << now << 60. * 60. * 24.; QTest::newRow("Minus one day delta") @@ -103,6 +103,7 @@ private slots: QTest::newRow("Zoom OUT 0.001") << range << 0.999 << computeZoom(yestd, now, 0.999); } + void testRangeZoom() { QFETCH(DateTimeRange, initial); @@ -196,6 +197,7 @@ private slots: << range << range * 0.9 + Seconds{-10.} << DateTimeRangeTransformation{0.9, Seconds{-10.}}; } + void testRangeTransformations() { QFETCH(DateTimeRange, range1); diff --git a/tests/DataSource/DataSourceItemBuilder.cpp b/tests/DataSource/DataSourceItemBuilder.cpp index c3ff319..1878319 100644 --- a/tests/DataSource/DataSourceItemBuilder.cpp +++ b/tests/DataSource/DataSourceItemBuilder.cpp @@ -9,7 +9,7 @@ DataSourceItemBuilder &DataSourceItemBuilder::root(const QString &name) DataSourceItemBuilder &DataSourceItemBuilder::root(QVariantHash data) { - m_Root = std::make_shared(DataSourceItemType::NODE, data); + m_Root = std::make_shared(DataSourceItemType::NODE,data[DataSourceItem::NAME_DATA_KEY].toString(), data); m_Items.push(m_Root.get()); return *this; } @@ -21,7 +21,7 @@ DataSourceItemBuilder &DataSourceItemBuilder::node(const QString &name) DataSourceItemBuilder &DataSourceItemBuilder::node(QVariantHash data) { - return append(DataSourceItemType::NODE, std::move(data)); + return append(DataSourceItemType::NODE,data[DataSourceItem::NAME_DATA_KEY].toString(), std::move(data)); } DataSourceItemBuilder &DataSourceItemBuilder::product(const QString &name) @@ -31,7 +31,7 @@ DataSourceItemBuilder &DataSourceItemBuilder::product(const QString &name) DataSourceItemBuilder &DataSourceItemBuilder::product(QVariantHash data) { - return append(DataSourceItemType::PRODUCT, std::move(data)); + return append(DataSourceItemType::PRODUCT,data[DataSourceItem::NAME_DATA_KEY].toString(), std::move(data)); } DataSourceItemBuilder &DataSourceItemBuilder::component(const QString &name) @@ -41,7 +41,7 @@ DataSourceItemBuilder &DataSourceItemBuilder::component(const QString &name) DataSourceItemBuilder &DataSourceItemBuilder::component(QVariantHash data) { - return append(DataSourceItemType::COMPONENT, std::move(data)); + return append(DataSourceItemType::COMPONENT,data[DataSourceItem::NAME_DATA_KEY].toString(), std::move(data)); } DataSourceItemBuilder &DataSourceItemBuilder::end() @@ -57,16 +57,16 @@ std::shared_ptr DataSourceItemBuilder::build() DataSourceItemBuilder &DataSourceItemBuilder::append(DataSourceItemType type, const QString &name) { - append(type, QVariantHash{{DataSourceItem::NAME_DATA_KEY, name}}); + append(type,name, QVariantHash{{DataSourceItem::NAME_DATA_KEY, name}}); return *this; } -DataSourceItemBuilder &DataSourceItemBuilder::append(DataSourceItemType type, QVariantHash data) +DataSourceItemBuilder &DataSourceItemBuilder::append(DataSourceItemType type, const QString &name, QVariantHash data) { auto parentItem = m_Items.top(); auto insertIndex = parentItem->childCount(); - parentItem->appendChild(std::make_unique(type, std::move(data))); + parentItem->appendChild(std::make_unique(type,name, std::move(data))); m_Items.push(parentItem->child(insertIndex)); return *this; diff --git a/tests/DataSource/DataSourceItemBuilder.h b/tests/DataSource/DataSourceItemBuilder.h index ce675a4..981cd65 100644 --- a/tests/DataSource/DataSourceItemBuilder.h +++ b/tests/DataSource/DataSourceItemBuilder.h @@ -36,7 +36,7 @@ public: private: DataSourceItemBuilder& append(DataSourceItemType type, const QString &name); - DataSourceItemBuilder& append(DataSourceItemType type, QVariantHash data); + DataSourceItemBuilder& append(DataSourceItemType type,const QString &name, QVariantHash data); std::shared_ptr m_Root{nullptr}; std::stack m_Items; diff --git a/tests/DataSource/DataSourcesManualTest.cpp b/tests/DataSource/DataSourcesManualTest.cpp new file mode 100644 index 0000000..ddd74be --- /dev/null +++ b/tests/DataSource/DataSourcesManualTest.cpp @@ -0,0 +1,78 @@ +#include "DataSource/DataSourcesFilter.h" +#include "DataSource/datasources.h" +#include "TestProviders.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void fillModel(DataSources* ds, SimpleRange<1>* provider) +{ + ds->addIcon("folder", QFileIconProvider().icon(QFileIconProvider::Folder)); + ds->addIcon("computer", + QFileIconProvider().icon(QFileIconProvider::Computer)); + ds->addProvider(provider); + ds->addDataSourceItem(*provider, "/test/node1", {{"Key", "Value"}}); + ds->addDataSourceItem(*provider, "/test/node2", {}); + ds->addDataSourceItem(*provider, "/test/node3", {}); + ds->addDataSourceItem(*provider, "/test/node4", {}); + ds->setIcon("/test", "folder"); + ds->addDataSourceItem(*provider, "/test/folder/node1", {}); + ds->addDataSourceItem(*provider, "/test2/folder/node1", {}); + repeat_n( + [ds, provider](int i) { + repeat_n( + [ds, provider, i](int j) { + repeat_n( + [ds, provider, i, j](int k) { + ds->addDataSourceItem(*provider, + "/test2/folder" + QString::number(i) + + "/folder" + QString::number(j) + + "/node" + QString::number(k), + {}); + }, + 10); + }, + 10); + }, + 10); + + ds->updateNodeMetaData("/test2/folder", {{"KeyUp", "ValueUp"}}); + ds->setIcon("/test2", "computer"); +} + +int main(int argc, char** argv) +{ + SimpleRange<1>* provider = new SimpleRange<1>{}; + QApplication app(argc, argv); + auto w = new QWidget(); + auto layout = new QVBoxLayout(w); + DataSources* ds = new DataSources(); + // DataSourceFilter* filter = new DataSourceFilter(); + QSortFilterProxyModel* filter = new QSortFilterProxyModel(); + filter->setSourceModel(ds); + QTreeView* view = new QTreeView(); + QLineEdit* filterBox = new QLineEdit(); + QObject::connect( + filterBox, + static_cast(&QLineEdit::textChanged), + filter, + static_cast( + &QSortFilterProxyModel::setFilterRegExp)); + layout->addWidget(filterBox); + layout->addWidget(view); + view->setModel(filter); + w->show(); + view->setDragEnabled(true); + filter->setFilterRole(Qt::ToolTipRole); + filter->setRecursiveFilteringEnabled(true); + fillModel(ds, provider); + view->expandAll(); + return app.exec(); +} diff --git a/tests/DataSource/TestDataSourceController.cpp b/tests/DataSource/TestDataSourceController.cpp index 3e58487..9d60368 100644 --- a/tests/DataSource/TestDataSourceController.cpp +++ b/tests/DataSource/TestDataSourceController.cpp @@ -5,7 +5,7 @@ #include #include - +//TODO remove this class TestDataSourceController : public QObject { Q_OBJECT private slots: @@ -39,10 +39,10 @@ void TestDataSourceController::testSetDataSourceItem() QCOMPARE(signalSpy.count(), 1); // Try to a data source item with an unregistered uid and check that no signal has been emitted - auto unregisteredUid = QUuid::createUuid(); - dataSourceController.setDataSourceItem( - unregisteredUid, std::make_unique(DataSourceItemType::PRODUCT)); - QCOMPARE(signalSpy.count(), 1); + //auto unregisteredUid = QUuid::createUuid(); + ///dataSourceController.setDataSourceItem( + // unregisteredUid, std::make_unique(DataSourceItemType::PRODUCT)); + //QCOMPARE(signalSpy.count(), 1); } QTEST_MAIN(TestDataSourceController) diff --git a/tests/DataSource/TestDataSources.cpp b/tests/DataSource/TestDataSources.cpp index c791529..8d26ac5 100644 --- a/tests/DataSource/TestDataSources.cpp +++ b/tests/DataSource/TestDataSources.cpp @@ -3,6 +3,7 @@ #include #include +#include "TestProviders.h" class TestDataSources : public QObject { Q_OBJECT @@ -12,7 +13,15 @@ private slots: void TestDataSources::addItems() { + SimpleRange<1>* provider = new SimpleRange<1>{}; DataSources ds; + ds.addProvider(provider); + ds.addDataSourceItem(provider->id(),"/test/node1",{}); + ds.addDataSourceItem(provider->id(),"/test/node2",{}); + ds.addDataSourceItem(provider->id(),"/test/node3",{}); + ds.addDataSourceItem(provider->id(),"/test/node4",{}); + auto rc = ds.rowCount(ds.index(0,0,QModelIndex())); + QVERIFY(rc==4); } QTEST_MAIN(TestDataSources) diff --git a/tests/meson.build b/tests/meson.build index b4b8399..94ccfb4 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -7,8 +7,6 @@ TestUtils_dep = declare_dependency(link_with : TestUtils, include_directories: include_directories('TestUtils'), dependencies : [sciqlop_core, qt5test]) - - tests = [ { 'name':'TestSyncGroup', @@ -85,3 +83,5 @@ foreach unit_test : tests endforeach +datasources_manual_test_exe = executable('datasources_manual_test', 'DataSource/DataSourcesManualTest.cpp', dependencies :[sciqlop_core, +TestUtils_dep, qt5gui, qt5widgets])