diff --git a/include/Data/IDataProvider.h b/include/Data/IDataProvider.h index 7e1f1a3..d72009c 100644 --- a/include/Data/IDataProvider.h +++ b/include/Data/IDataProvider.h @@ -34,9 +34,7 @@ class SCIQLOP_CORE_EXPORT IDataProvider : public QObject public: virtual ~IDataProvider() noexcept = default; - // virtual std::shared_ptr clone() const = 0; - // Synchronous call -> asyncGetData may be written for asynchronous get virtual TimeSeries::ITimeSerie* getData(const DataProviderParameters& parameters) = 0; @@ -54,7 +52,5 @@ signals: // Required for using shared_ptr in signals/slots SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_PTR_REGISTRY, std::shared_ptr) -SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_FUNCTION_REGISTRY, - std::function) #endif // SCIQLOP_IDATAPROVIDER_H diff --git a/include/DataSource/DataSourceItem.h b/include/DataSource/DataSourceItem.h index f2c9c0b..1ee86ab 100644 --- a/include/DataSource/DataSourceItem.h +++ b/include/DataSource/DataSourceItem.h @@ -4,11 +4,11 @@ #include "CoreGlobal.h" #include -#include #include #include -#include #include +#include +#include class DataSourceItemAction; @@ -22,8 +22,6 @@ enum class DataSourceItemType COMPONENT }; - - /** * @brief The DataSourceItem class aims to represent a structure element of a * data source. A data source has a tree structure that is made up of a main @@ -33,10 +31,11 @@ enum class DataSourceItemType */ class SCIQLOP_CORE_EXPORT DataSourceItem { - public: - using iterator_type = decltype (std::begin(std::declval>>())); - using const_iterator_type = decltype (std::cbegin(std::declval>>())); + using iterator_type = decltype( + std::begin(std::declval>>())); + using const_iterator_type = decltype(std::cbegin( + std::declval>>())); /// Key associated with the name of the item static const QString NAME_DATA_KEY; /// Key associated with the plugin of the item @@ -74,6 +73,8 @@ public: int childCount() const noexcept; + int index() const noexcept; + /** * Get the data associated to a key * @param key the key to search @@ -177,10 +178,11 @@ public: iterator_type begin() noexcept; iterator_type end() noexcept; - const_iterator_type begin()const noexcept; - const_iterator_type end()const noexcept; - const_iterator_type cbegin()const noexcept; - const_iterator_type cend()const noexcept; + const_iterator_type begin() const noexcept; + const_iterator_type end() const noexcept; + const_iterator_type cbegin() const noexcept; + const_iterator_type cend() const noexcept; + private: class DataSourceItemPrivate; spimpl::unique_impl_ptr impl; diff --git a/include/DataSource/datasources.h b/include/DataSource/datasources.h new file mode 100644 index 0000000..d6f54af --- /dev/null +++ b/include/DataSource/datasources.h @@ -0,0 +1,68 @@ + +/*------------------------------------------------------------------------------ + * -- 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 DATASOURCES_H +#define DATASOURCES_H + +#include "Data/IDataProvider.h" +#include "DataSourceItem.h" + +#include + +class DataSources : public QAbstractItemModel +{ + Q_OBJECT + +public: + enum Roles + { + CustomRole = Qt::UserRole + }; + +public: + DataSources() : _root{} {} + ~DataSources() { delete _root; } + + virtual QVariant data(const QModelIndex& index, int role) const override; + + int columnCount(const QModelIndex& parent) const override; + + virtual int rowCount(const QModelIndex& parent) const override; + + QModelIndex parent(const QModelIndex& index) const override; + + virtual QModelIndex index(int row, int column, + const QModelIndex& parent) const override; + + void addDataSourceItem(const QUuid& providerUid, const QString& path, + const QMap& metaData) noexcept; + + void addProvider(IDataProvider* provider) noexcept; + +private: + DataSourceItem* _root; + std::map> _DataProviders; +}; + +#endif // DATASOURCES_H diff --git a/meson.build b/meson.build index d3c67e2..7879638 100644 --- a/meson.build +++ b/meson.build @@ -30,6 +30,7 @@ core_moc_headers = [ './include/Settings/SqpSettingsDefs.h', './include/Settings/ISqpSettingsBindable.h', './include/DataSource/DataSourceController.h', + './include/DataSource/datasources.h', './include/DataSource/DataSourceItem.h', './include/DataSource/DataSourceItemAction.h', './include/DataSource/DataSourceItemMergeHelper.h', @@ -61,6 +62,7 @@ core_sources = ['./src/Common/MimeTypesDef.cpp', './src/DataSource/DataSourceItemMergeHelper.cpp', './src/DataSource/DataSourceItem.cpp', './src/DataSource/DataSourceController.cpp', + './src/DataSource/datasources.cpp', './src/Time/TimeController.cpp', './src/PluginManager/PluginManager.cpp', './src/Version.cpp', diff --git a/src/DataSource/DataSourceItem.cpp b/src/DataSource/DataSourceItem.cpp index 11ec225..ca39380 100644 --- a/src/DataSource/DataSourceItem.cpp +++ b/src/DataSource/DataSourceItem.cpp @@ -2,6 +2,7 @@ #include #include #include +#include const QString DataSourceItem::NAME_DATA_KEY = QStringLiteral("name"); const QString DataSourceItem::PLUGIN_DATA_KEY = QStringLiteral("plugin"); @@ -25,6 +26,12 @@ struct DataSourceItem::DataSourceItemPrivate auto end()noexcept{return m_Children.end();} auto cbegin()const noexcept{return m_Children.cbegin();} auto cend()const noexcept{return m_Children.cend();} + + 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;})); + } }; DataSourceItem::DataSourceItem(DataSourceItemType type, const QString& name) @@ -120,6 +127,15 @@ DataSourceItem* DataSourceItem::parentItem() const noexcept return impl->m_Parent; } +int DataSourceItem::index() const noexcept +{ + if(auto parent = parentItem(); parent) + { + return parent->impl->index_of(this); + } + return 0; +} + const DataSourceItem& DataSourceItem::rootItem() const noexcept { return isRoot() ? *this : parentItem()->rootItem(); diff --git a/src/DataSource/datasources.cpp b/src/DataSource/datasources.cpp new file mode 100644 index 0000000..9b242ae --- /dev/null +++ b/src/DataSource/datasources.cpp @@ -0,0 +1,144 @@ +/*------------------------------------------------------------------------------ + * -- 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 + * ----------------------------------------------------------------------------*/ +// https://doc.qt.io/qt-5/qtwidgets-itemviews-simpletreemodel-example.html + +#include "DataSource/datasources.h" + +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) +{ + std::for_each(path_list_begin, path_list_end, + [&root](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; + }); + return root; +} + +inline std::unique_ptr +make_product_item(const QVariantHash& metaData, const QUuid& dataSourceUid, + const QString& DATA_SOURCE_NAME, DataSources* dc) +{ + auto result = + std::make_unique(DataSourceItemType::PRODUCT, 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( + // QObject::tr("Load %1 product").arg(productName), + // [productName, dataSourceUid, dc](DataSourceItem& item) { + // if(dc) { dc->loadProductItem(dataSourceUid, item); } + // })); + + return result; +} + +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(); +} + +int DataSources::columnCount(const QModelIndex& parent) const +{ + (void)parent; + return 0; +} + +int DataSources::rowCount(const QModelIndex& parent) const +{ + DataSourceItem* parentItem; + if(parent.column() > 0) return 0; + if(!parent.isValid()) + parentItem = _root; + else + parentItem = static_cast(parent.internalPointer()); + return parentItem->childCount(); +} + +QModelIndex DataSources::parent(const QModelIndex& index) const +{ + if(!index.isValid()) return QModelIndex(); + DataSourceItem* childItem = + static_cast(index.internalPointer()); + DataSourceItem* parentItem = childItem->parentItem(); + if(parentItem == _root) return QModelIndex(); + return createIndex(parentItem->index(), 0, parentItem); +} + +QModelIndex DataSources::index(int row, int column, + const QModelIndex& parent) const +{ + if(!hasIndex(row, column, parent)) return QModelIndex(); + DataSourceItem* parentItem; + if(!parent.isValid()) + parentItem = _root; + else + parentItem = static_cast(parent.internalPointer()); + DataSourceItem* childItem = parentItem->child(row); + if(childItem) return createIndex(row, column, childItem); + return QModelIndex(); +} + +void DataSources::addDataSourceItem( + const QUuid& providerUid, const QString& path, + const QMap& metaData) noexcept +{ + auto path_list = path.split('/', QString::SkipEmptyParts); + auto name = *(std::cend(path_list) - 1); + auto path_item = + make_path_items(std::cbegin(path_list), std::cend(path_list) - 1, _root); + QVariantHash meta_data{{DataSourceItem::NAME_DATA_KEY, name}}; + for(auto& key : metaData.keys()) + { + meta_data[key] = metaData[key]; + } + path_item->appendChild( + make_product_item(meta_data, providerUid, "test", this)); +} + +void DataSources::addProvider(IDataProvider* provider) noexcept +{ + _DataProviders.insert( + {provider->id(), std::unique_ptr{provider}}); +} diff --git a/tests/DataSource/TestDataSources.cpp b/tests/DataSource/TestDataSources.cpp new file mode 100644 index 0000000..c791529 --- /dev/null +++ b/tests/DataSource/TestDataSources.cpp @@ -0,0 +1,19 @@ +#include +#include + +#include +#include + +class TestDataSources : public QObject { + Q_OBJECT +private slots: + void addItems(); +}; + +void TestDataSources::addItems() +{ + DataSources ds; +} + +QTEST_MAIN(TestDataSources) +#include "TestDataSources.moc" diff --git a/tests/meson.build b/tests/meson.build index b894200..1863666 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -29,6 +29,13 @@ tests = [ 'deps': [sciqlop_core, qt5test] }, { + 'name':'TestDataSources', + 'sources': [ + 'DataSource/TestDataSources.cpp' + ], + 'deps': [sciqlop_core, qt5test, TestUtils_dep] + }, + { 'name':'TestDataSourceItem', 'sources': [ 'DataSource/TestDataSourceItem.cpp',