diff --git a/app/src/Main.cpp b/app/src/Main.cpp index cb3a380..1533e01 100644 --- a/app/src/Main.cpp +++ b/app/src/Main.cpp @@ -25,6 +25,16 @@ #include #include +#include +#include + +namespace { + +/// Name of the directory containing the plugins +const auto PLUGIN_DIRECTORY_NAME = QStringLiteral("plugins"); + +} // namespace + int main(int argc, char *argv[]) { SqpApplication a{argc, argv}; @@ -34,5 +44,16 @@ int main(int argc, char *argv[]) MainWindow w; w.show(); + // Loads plugins + auto pluginDir = QDir{sqpApp->applicationDirPath()}; + pluginDir.mkdir(PLUGIN_DIRECTORY_NAME); + pluginDir.cd(PLUGIN_DIRECTORY_NAME); + + qCDebug(LOG_PluginManager()) + << QObject::tr("Plugin directory: %1").arg(pluginDir.absolutePath()); + + PluginManager pluginManager{}; + pluginManager.loadPlugins(pluginDir); + return a.exec(); } diff --git a/app/src/MainWindow.cpp b/app/src/MainWindow.cpp index f0eab1a..6bf9b47 100644 --- a/app/src/MainWindow.cpp +++ b/app/src/MainWindow.cpp @@ -21,6 +21,11 @@ ----------------------------------------------------------------------------*/ #include "MainWindow.h" #include "ui_MainWindow.h" + +#include +#include +#include + #include #include #include @@ -57,6 +62,11 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), m_Ui(new Ui::Main this->menuBar()->addAction("File"); auto mainToolBar = this->addToolBar("MainToolBar"); mainToolBar->addAction("A1"); + + // Widgets / controllers connections + connect(&sqpApp->dataSourceController(), SIGNAL(dataSourceItemSet(DataSourceItem &)), + m_Ui->dataSourceWidget, SLOT(addDataSource(DataSourceItem &))); + /* QLopGUI::registerMenuBar(menuBar()); this->setWindowIcon(QIcon(":/sciqlopLOGO.svg")); this->m_progressWidget = new QWidget(); diff --git a/app/ui/MainWindow.ui b/app/ui/MainWindow.ui index 7aab4f3..c3d6abe 100644 --- a/app/ui/MainWindow.ui +++ b/app/ui/MainWindow.ui @@ -85,7 +85,7 @@ 0 - + @@ -202,6 +202,12 @@
sidepane/SqpSidePane.h
1 + + DataSourceWidget + QWidget +
DataSource/DataSourceWidget.h
+ 1 +
diff --git a/core/include/DataSource/DataSourceController.h b/core/include/DataSource/DataSourceController.h index ef886ab..33a6049 100644 --- a/core/include/DataSource/DataSourceController.h +++ b/core/include/DataSource/DataSourceController.h @@ -49,7 +49,7 @@ public slots: signals: /// Signal emitted when a structure has been set for a data source - void dataSourceItemSet(const DataSourceItem &dataSourceItem); + void dataSourceItemSet(DataSourceItem &dataSourceItem); private: void waitForFinish(); diff --git a/core/include/DataSource/DataSourceItem.h b/core/include/DataSource/DataSourceItem.h index 2f71ec6..193a495 100644 --- a/core/include/DataSource/DataSourceItem.h +++ b/core/include/DataSource/DataSourceItem.h @@ -7,6 +7,11 @@ #include /** + * Possible types of an item + */ +enum class DataSourceItemType { NODE, PRODUCT }; + +/** * @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 DataSourceItem object (root) * containing other DataSourceItem objects (children). @@ -14,7 +19,7 @@ */ class DataSourceItem { public: - explicit DataSourceItem(QVector data = {}); + explicit DataSourceItem(DataSourceItemType type, QVector data = {}); /** * Adds a child to the item. The item takes ownership of the child. @@ -44,6 +49,8 @@ public: */ DataSourceItem *parentItem() const noexcept; + DataSourceItemType type() const noexcept; + private: class DataSourceItemPrivate; spimpl::unique_impl_ptr impl; diff --git a/core/src/DataSource/DataSourceItem.cpp b/core/src/DataSource/DataSourceItem.cpp index 2d7e242..43c884b 100644 --- a/core/src/DataSource/DataSourceItem.cpp +++ b/core/src/DataSource/DataSourceItem.cpp @@ -3,18 +3,19 @@ #include struct DataSourceItem::DataSourceItemPrivate { - explicit DataSourceItemPrivate(QVector data) - : m_Parent{nullptr}, m_Children{}, m_Data{std::move(data)} + explicit DataSourceItemPrivate(DataSourceItemType type, QVector data) + : m_Parent{nullptr}, m_Children{}, m_Type{type}, m_Data{std::move(data)} { } DataSourceItem *m_Parent; std::vector > m_Children; + DataSourceItemType m_Type; QVector m_Data; }; -DataSourceItem::DataSourceItem(QVector data) - : impl{spimpl::make_unique_impl(data)} +DataSourceItem::DataSourceItem(DataSourceItemType type, QVector data) + : impl{spimpl::make_unique_impl(type, std::move(data))} { } @@ -48,3 +49,8 @@ DataSourceItem *DataSourceItem::parentItem() const noexcept { return impl->m_Parent; } + +DataSourceItemType DataSourceItem::type() const noexcept +{ + return impl->m_Type; +} diff --git a/core/tests/DataSource/TestDataSourceController.cpp b/core/tests/DataSource/TestDataSourceController.cpp index 03279dc..a8c0a24 100644 --- a/core/tests/DataSource/TestDataSourceController.cpp +++ b/core/tests/DataSource/TestDataSourceController.cpp @@ -31,7 +31,8 @@ void TestDataSourceController::testSetDataSourceItem() // Create a data source item auto source1Name = QStringLiteral("Source1"); auto source1Values = QVector{source1Name}; - auto source1Item = std::make_unique(std::move(source1Values)); + auto source1Item + = std::make_unique(DataSourceItemType::PRODUCT, std::move(source1Values)); // Add data source item to the controller and check that a signal has been emitted after setting // data source item in the controller @@ -41,7 +42,8 @@ void TestDataSourceController::testSetDataSourceItem() // 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()); + dataSourceController.setDataSourceItem( + unregisteredUid, std::make_unique(DataSourceItemType::PRODUCT)); QCOMPARE(signalSpy.count(), 1); } diff --git a/core/vera-exclusions/exclusions.txt b/core/vera-exclusions/exclusions.txt index 15b0dba..7b0007c 100644 --- a/core/vera-exclusions/exclusions.txt +++ b/core/vera-exclusions/exclusions.txt @@ -1,3 +1,6 @@ # On ignore toutes les règles vera++ pour le fichier spimpl Common/spimpl\.h:\d+:.* +# Ignore false positive relative to two class definitions in a same file +DataSourceItem\.h:\d+:.*IPSIS_S01.* + diff --git a/formatting/vera-exclusions/exclusions.txt b/formatting/vera-exclusions/exclusions.txt index 2b00cc6..18e7e8b 100644 --- a/formatting/vera-exclusions/exclusions.txt +++ b/formatting/vera-exclusions/exclusions.txt @@ -6,3 +6,7 @@ # Ignore false positive relative to 'noexcept' keyword .*IPSIS_S04_VARIABLE.*found: noexcept .*IPSIS_S06.*found: noexcept + +# Ignore false positive relative to 'override' keyword +.*IPSIS_S04_VARIABLE.*found: override +.*IPSIS_S06.*found: override diff --git a/gui/include/DataSource/DataSourceTreeWidgetItem.h b/gui/include/DataSource/DataSourceTreeWidgetItem.h new file mode 100644 index 0000000..02b0122 --- /dev/null +++ b/gui/include/DataSource/DataSourceTreeWidgetItem.h @@ -0,0 +1,32 @@ +#ifndef SCIQLOP_DATASOURCETREEWIDGETITEM_H +#define SCIQLOP_DATASOURCETREEWIDGETITEM_H + +#include + +#include +#include + +Q_DECLARE_LOGGING_CATEGORY(LOG_DataSourceTreeWidgetItem) + +class DataSourceItem; + +/** + * @brief The DataSourceTreeWidgetItem is the graphical representation of a data source item. It is + * intended to be displayed in a QTreeWidget. + * @sa DataSourceItem + */ +class DataSourceTreeWidgetItem : public QTreeWidgetItem { +public: + explicit DataSourceTreeWidgetItem(const DataSourceItem *data, int type = Type); + explicit DataSourceTreeWidgetItem(QTreeWidget *parent, const DataSourceItem *data, + int type = Type); + + virtual QVariant data(int column, int role) const override; + virtual void setData(int column, int role, const QVariant &value) override; + +private: + class DataSourceTreeWidgetItemPrivate; + spimpl::unique_impl_ptr impl; +}; + +#endif // SCIQLOP_DATASOURCETREEWIDGETITEM_H diff --git a/gui/include/DataSource/DataSourceWidget.h b/gui/include/DataSource/DataSourceWidget.h new file mode 100644 index 0000000..e0634f7 --- /dev/null +++ b/gui/include/DataSource/DataSourceWidget.h @@ -0,0 +1,33 @@ +#ifndef SCIQLOP_DATASOURCEWIDGET_H +#define SCIQLOP_DATASOURCEWIDGET_H + +#include + +#include + +class DataSourceItem; + +/** + * @brief The DataSourceWidget handles the graphical representation (as a tree) of the data sources + * attached to SciQlop. + */ +class DataSourceWidget : public QWidget { + Q_OBJECT + +public: + explicit DataSourceWidget(QWidget *parent = 0); + +public slots: + /** + * Adds a data source. An item associated to the data source is created and then added to the + * representation tree + * @param dataSource the data source to add + */ + void addDataSource(DataSourceItem &dataSource) noexcept; + +private: + class DataSourceWidgetPrivate; + spimpl::unique_impl_ptr impl; +}; + +#endif // SCIQLOP_DATASOURCEWIDGET_H diff --git a/gui/src/DataSource/DataSourceTreeWidgetItem.cpp b/gui/src/DataSource/DataSourceTreeWidgetItem.cpp new file mode 100644 index 0000000..4090b80 --- /dev/null +++ b/gui/src/DataSource/DataSourceTreeWidgetItem.cpp @@ -0,0 +1,68 @@ +#include +#include + +#include + +Q_LOGGING_CATEGORY(LOG_DataSourceTreeWidgetItem, "DataSourceTreeWidgetItem") + +namespace { + +QIcon itemIcon(const DataSourceItem *dataSource) +{ + if (dataSource) { + auto dataSourceType = dataSource->type(); + switch (dataSourceType) { + case DataSourceItemType::NODE: + return sqpApp->style()->standardIcon(QStyle::SP_DirIcon); + case DataSourceItemType::PRODUCT: + return sqpApp->style()->standardIcon(QStyle::SP_FileIcon); + default: + // No action + break; + } + } + + // Default cases + return QIcon{}; +} + +} // namespace + +struct DataSourceTreeWidgetItem::DataSourceTreeWidgetItemPrivate { + explicit DataSourceTreeWidgetItemPrivate(const DataSourceItem *data) : m_Data{data} {} + + /// Model used to retrieve data source information + const DataSourceItem *m_Data; +}; + +DataSourceTreeWidgetItem::DataSourceTreeWidgetItem(const DataSourceItem *data, int type) + : DataSourceTreeWidgetItem{nullptr, data, type} +{ +} + +DataSourceTreeWidgetItem::DataSourceTreeWidgetItem(QTreeWidget *parent, const DataSourceItem *data, + int type) + : QTreeWidgetItem{parent, type}, + impl{spimpl::make_unique_impl(data)} +{ + // Sets the icon depending on the data source + setIcon(0, itemIcon(impl->m_Data)); +} + +QVariant DataSourceTreeWidgetItem::data(int column, int role) const +{ + if (role == Qt::DisplayRole) { + return (impl->m_Data) ? impl->m_Data->data(column) : QVariant{}; + } + else { + return QTreeWidgetItem::data(column, role); + } +} + +void DataSourceTreeWidgetItem::setData(int column, int role, const QVariant &value) +{ + // Data can't be changed by edition + if (role != Qt::EditRole) { + QTreeWidgetItem::setData(column, role, value); + } +} diff --git a/gui/src/DataSource/DataSourceWidget.cpp b/gui/src/DataSource/DataSourceWidget.cpp new file mode 100644 index 0000000..20e3014 --- /dev/null +++ b/gui/src/DataSource/DataSourceWidget.cpp @@ -0,0 +1,61 @@ +#include + +#include + +#include +#include + +namespace { + +/// Number of columns displayed in the tree +const auto TREE_NB_COLUMNS = 1; + +/// Header labels for the tree +const auto TREE_HEADER_LABELS = QStringList{QObject::tr("Name")}; + +/** + * Creates the item associated to a data source + * @param dataSource the data source for which to create the item + * @return the new item + */ +DataSourceTreeWidgetItem *createTreeWidgetItem(DataSourceItem *dataSource) +{ + // Creates item for the data source + auto item = new DataSourceTreeWidgetItem{dataSource}; + + // Generates items for the children of the data source + for (auto i = 0; i < dataSource->childCount(); ++i) { + item->addChild(createTreeWidgetItem(dataSource->child(i))); + } + + return item; +} + +} // namespace + +class DataSourceWidget::DataSourceWidgetPrivate { +public: + explicit DataSourceWidgetPrivate(DataSourceWidget &widget) + : m_Ui{std::make_unique()} + { + m_Ui->setupUi(&widget); + + // Set tree properties + m_Ui->treeWidget->setColumnCount(TREE_NB_COLUMNS); + m_Ui->treeWidget->setHeaderLabels(TREE_HEADER_LABELS); + } + + std::unique_ptr m_Ui; +}; + +DataSourceWidget::DataSourceWidget(QWidget *parent) + : QWidget{parent}, impl{spimpl::make_unique_impl(*this)} +{ +} + +void DataSourceWidget::addDataSource(DataSourceItem &dataSource) noexcept +{ + // Creates the item associated to the source and adds it to the tree widget. The tree widget + // takes the ownership of the item + impl->m_Ui->treeWidget->addTopLevelItem(createTreeWidgetItem(&dataSource)); +} diff --git a/gui/ui/DataSource/DataSourceWidget.ui b/gui/ui/DataSource/DataSourceWidget.ui new file mode 100644 index 0000000..a7cf875 --- /dev/null +++ b/gui/ui/DataSource/DataSourceWidget.ui @@ -0,0 +1,24 @@ + + + DataSourceWidget + + + + 0 + 0 + 400 + 300 + + + + Data sources + + + + + + + + + + diff --git a/gui/vera-exclusions/exclusions.txt b/gui/vera-exclusions/exclusions.txt index 21506de..0bcc8be 100644 --- a/gui/vera-exclusions/exclusions.txt +++ b/gui/vera-exclusions/exclusions.txt @@ -1,8 +1,11 @@ -# Ignore false positive relative to App macro \.h:\d+:.IPSIS_S04.*found: ui qcustomplot\.h:\d+:.IPSIS qcustomplot\.cpp:\d+:.IPSIS + +# Ignore false positive relative to App macro SqpApplication\.h:\d+:.IPSIS_S03.*found: sqpApp SqpApplication\.h:\d+:.IPSIS_S04_VARIABLE.*found: sqpApp +# Ignore false positive relative to unnamed namespace +DataSourceTreeWidgetItem\.cpp:\d+:.*IPSIS_F13.*