##// END OF EJS Templates
Merge branch 'feature/InitDataSource' into develop
Alexandre Leroux -
r40:59a87dfdf45b merge
parent child
Show More
@@ -0,0 +1,3
1 # Ignore false positive relative to sqpApp macro
2 SqpApplication\.h:\d+:.IPSIS_S03.*found: sqpApp
3 SqpApplication\.h:\d+:.IPSIS_S04_VARIABLE.*found: sqpApp
@@ -0,0 +1,52
1 #ifndef SCIQLOP_DATASOURCEITEM_H
2 #define SCIQLOP_DATASOURCEITEM_H
3
4 #include <Common/spimpl.h>
5
6 #include <QVariant>
7 #include <QVector>
8
9 /**
10 * @brief The DataSourceItem class aims to represent a structure element of a data source.
11 * A data source has a tree structure that is made up of a main DataSourceItem object (root)
12 * containing other DataSourceItem objects (children).
13 * For each DataSourceItem can be associated a set of data representing it.
14 */
15 class DataSourceItem {
16 public:
17 explicit DataSourceItem(QVector<QVariant> data = {});
18
19 /**
20 * Adds a child to the item. The item takes ownership of the child.
21 * @param child the child to add
22 */
23 void appendChild(std::unique_ptr<DataSourceItem> child) noexcept;
24
25 /**
26 * Returns the item's child associated to an index
27 * @param childIndex the index to search
28 * @return a pointer to the child if index is valid, nullptr otherwise
29 */
30 DataSourceItem *child(int childIndex) const noexcept;
31
32 int childCount() const noexcept;
33
34 /**
35 * Get the data associated to an index
36 * @param dataIndex the index to search
37 * @return the data found if index is valid, default QVariant otherwise
38 */
39 QVariant data(int dataIndex) const noexcept;
40
41 /**
42 * Get the item's parent
43 * @return a pointer to the parent if it exists, nullptr if the item is a root
44 */
45 DataSourceItem *parentItem() const noexcept;
46
47 private:
48 class DataSourceItemPrivate;
49 spimpl::unique_impl_ptr<DataSourceItemPrivate> impl;
50 };
51
52 #endif // SCIQLOP_DATASOURCEITEMMODEL_H
@@ -0,0 +1,50
1 #include <DataSource/DataSourceItem.h>
2
3 #include <QVector>
4
5 struct DataSourceItem::DataSourceItemPrivate {
6 explicit DataSourceItemPrivate(QVector<QVariant> data)
7 : m_Parent{nullptr}, m_Children{}, m_Data{std::move(data)}
8 {
9 }
10
11 DataSourceItem *m_Parent;
12 std::vector<std::unique_ptr<DataSourceItem> > m_Children;
13 QVector<QVariant> m_Data;
14 };
15
16 DataSourceItem::DataSourceItem(QVector<QVariant> data)
17 : impl{spimpl::make_unique_impl<DataSourceItemPrivate>(data)}
18 {
19 }
20
21 void DataSourceItem::appendChild(std::unique_ptr<DataSourceItem> child) noexcept
22 {
23 child->impl->m_Parent = this;
24 impl->m_Children.push_back(std::move(child));
25 }
26
27 DataSourceItem *DataSourceItem::child(int childIndex) const noexcept
28 {
29 if (childIndex < 0 || childIndex >= childCount()) {
30 return nullptr;
31 }
32 else {
33 return impl->m_Children.at(childIndex).get();
34 }
35 }
36
37 int DataSourceItem::childCount() const noexcept
38 {
39 return impl->m_Children.size();
40 }
41
42 QVariant DataSourceItem::data(int dataIndex) const noexcept
43 {
44 return impl->m_Data.value(dataIndex);
45 }
46
47 DataSourceItem *DataSourceItem::parentItem() const noexcept
48 {
49 return impl->m_Parent;
50 }
@@ -0,0 +1,49
1 #include <DataSource/DataSourceController.h>
2 #include <DataSource/DataSourceItem.h>
3
4 #include <QObject>
5 #include <QtTest>
6
7 #include <memory>
8
9 class TestDataSourceController : public QObject {
10 Q_OBJECT
11 private slots:
12 void testRegisterDataSource();
13 void testSetDataSourceItem();
14 };
15
16 void TestDataSourceController::testRegisterDataSource()
17 {
18 DataSourceController dataSourceController{};
19
20 auto uid = dataSourceController.registerDataSource(QStringLiteral("Source1"));
21 QVERIFY(!uid.isNull());
22 }
23
24 void TestDataSourceController::testSetDataSourceItem()
25 {
26 DataSourceController dataSourceController{};
27
28 // Spy to test controllers' signals
29 QSignalSpy signalSpy{&dataSourceController, SIGNAL(dataSourceItemSet(const DataSourceItem &))};
30
31 // Create a data source item
32 auto source1Name = QStringLiteral("Source1");
33 auto source1Values = QVector<QVariant>{source1Name};
34 auto source1Item = std::make_unique<DataSourceItem>(std::move(source1Values));
35
36 // Add data source item to the controller and check that a signal has been emitted after setting
37 // data source item in the controller
38 auto source1Uid = dataSourceController.registerDataSource(source1Name);
39 dataSourceController.setDataSourceItem(source1Uid, std::move(source1Item));
40 QCOMPARE(signalSpy.count(), 1);
41
42 // Try to a data source item with an unregistered uid and check that no signal has been emitted
43 auto unregisteredUid = QUuid::createUuid();
44 dataSourceController.setDataSourceItem(unregisteredUid, std::make_unique<DataSourceItem>());
45 QCOMPARE(signalSpy.count(), 1);
46 }
47
48 QTEST_MAIN(TestDataSourceController)
49 #include "TestDataSourceController.moc"
@@ -1,3 +1,5
1 1 build/
2 2 CMakeLists.txt.user
3 3 /.project
4 core/src/Version.cpp
5 core/include/Version.h
@@ -75,7 +75,7 qt5_use_modules(${EXECUTABLE_NAME} Core Widgets)
75 75 LIST(APPEND CHECKSTYLE_INPUT_FILES ${APPLICATION_SOURCES})
76 76 SCIQLOP_SET_TO_PARENT_SCOPE(CHECKSTYLE_INPUT_FILES)
77 77 # Vera++ exclusion files
78 #LIST(APPEND CHECKSTYLE_EXCLUSION_FILES ${CMAKE_CURRENT_SOURCE_DIR}/path/to/exclusionFiles.tcl)
78 LIST(APPEND CHECKSTYLE_EXCLUSION_FILES ${CMAKE_CURRENT_SOURCE_DIR}/vera-exclusions/exclusions.txt)
79 79 SCIQLOP_SET_TO_PARENT_SCOPE(CHECKSTYLE_EXCLUSION_FILES)
80 80
81 81 #
@@ -27,8 +27,7
27 27
28 28 int main(int argc, char *argv[])
29 29 {
30 int ad;
31 SqpApplication a(argc, argv);
30 SqpApplication a{argc, argv};
32 31 SqpApplication::setOrganizationName("LPP");
33 32 SqpApplication::setOrganizationDomain("lpp.fr");
34 33 SqpApplication::setApplicationName("SciQLop");
@@ -79,10 +79,12 IF(BUILD_TESTS)
79 79 ${testDirectory}/*.c
80 80 ${testDirectory}/*.cpp
81 81 ${testDirectory}/*.h)
82 LIST (REMOVE_ITEM currentTestSources ${TESTS_SOURCES})
83 LIST (REMOVE_ITEM currentTestSources ${TESTS_HEADERS})
82 LIST (REMOVE_ITEM currentTestSources ${TESTS_SOURCES})
83 # LIST (REMOVE_ITEM currentTestSources ${TESTS_HEADERS})
84 84
85 85 ADD_EXECUTABLE(${testName} ${testFile} ${currentTestSources})
86 set_property(TARGET ${testName} PROPERTY CXX_STANDARD 14)
87 set_property(TARGET ${testName} PROPERTY CXX_STANDARD_REQUIRED ON)
86 88 TARGET_LINK_LIBRARIES( ${testName} ${TEST_LIBRARIES} )
87 89 qt5_use_modules(${testName} Test)
88 90
@@ -89,8 +89,9 using default_copier_t = typename default_copier<T>::type;
89 89
90 90 template <class T, class D, class C>
91 91 struct is_default_manageable
92 : public std::integral_constant<bool, std::is_same<D, default_deleter_t<T> >::value
93 && std::is_same<C, default_copier_t<T> >::value> {
92 : public std::integral_constant<bool,
93 std::is_same<D, default_deleter_t<T> >::value
94 && std::is_same<C, default_copier_t<T> >::value> {
94 95 };
95 96 }
96 97
@@ -131,10 +132,11 public:
131 132 }
132 133
133 134 template <class U>
134 impl_ptr(U *u, typename std::enable_if<std::is_convertible<U *, pointer>::value
135 && is_default_manageable::value,
136 dummy_t_>::type
137 = dummy_t_()) SPIMPL_NOEXCEPT
135 impl_ptr(U *u,
136 typename std::enable_if<std::is_convertible<U *, pointer>::value
137 && is_default_manageable::value,
138 dummy_t_>::type
139 = dummy_t_()) SPIMPL_NOEXCEPT
138 140 : impl_ptr(u, &details::default_delete<T>, &details::default_copy<T>)
139 141 {
140 142 }
@@ -151,12 +153,12 public:
151 153
152 154 #ifdef SPIMPL_HAS_AUTO_PTR
153 155 template <class U>
154 impl_ptr(std::auto_ptr<U> &&u, typename std::enable_if<std::is_convertible<U *, pointer>::value
155 && is_default_manageable::value,
156 dummy_t_>::type
157 = dummy_t_()) SPIMPL_NOEXCEPT
158 : ptr_(u.release(), &details::default_delete<T>),
159 copier_(&details::default_copy<T>)
156 impl_ptr(std::auto_ptr<U> &&u,
157 typename std::enable_if<std::is_convertible<U *, pointer>::value
158 && is_default_manageable::value,
159 dummy_t_>::type
160 = dummy_t_()) SPIMPL_NOEXCEPT : ptr_(u.release(), &details::default_delete<T>),
161 copier_(&details::default_copy<T>)
160 162 {
161 163 }
162 164 #endif
@@ -1,22 +1,22
1 1 #ifndef SCIQLOP_DATASOURCECONTROLLER_H
2 2 #define SCIQLOP_DATASOURCECONTROLLER_H
3 3
4 #include "DataSourceController.h"
5
6 4 #include <QLoggingCategory>
7 5 #include <QObject>
6 #include <QUuid>
8 7
9 8 #include <Common/spimpl.h>
10 9
11 10 Q_DECLARE_LOGGING_CATEGORY(LOG_DataSourceController)
12 11
12 class DataSourceItem;
13
13 14 /**
14 * @brief The DataSourceController class aims to make the link between SciQlop
15 * and its plugins. This is the intermediate class that SciQlop have to use
16 * in the way to connect a data source. Please first use load method to intialize
17 * a plugin specified by its metadata name (JSON plugin source) then others specifics
18 * method will ba able to access it.
19 * You can load a data source driver plugin then create a data source.
15 * @brief The DataSourceController class aims to make the link between SciQlop and its plugins. This
16 * is the intermediate class that SciQlop has to use in the way to connect a data source. Please
17 * first use register method to initialize a plugin specified by its metadata name (JSON plugin
18 * source) then others specifics method will be able to access it. You can load a data source driver
19 * plugin then create a data source.
20 20 */
21 21 class DataSourceController : public QObject {
22 22 Q_OBJECT
@@ -24,11 +24,33 public:
24 24 explicit DataSourceController(QObject *parent = 0);
25 25 virtual ~DataSourceController();
26 26
27 /**
28 * Registers a data source. The method delivers a unique id that can be used afterwards to
29 * access to the data source properties (structure, connection parameters, data provider, etc.)
30 * @param dataSourceName the name of the data source
31 * @return the unique id with which the data source has been registered
32 */
33 QUuid registerDataSource(const QString &dataSourceName) noexcept;
34
35 /**
36 * Sets the structure of a data source. The controller takes ownership of the structure.
37 * @param dataSourceUid the unique id with which the data source has been registered into the
38 * controller. If it is invalid, the method has no effect.
39 * @param dataSourceItem the structure of the data source
40 * @sa registerDataSource()
41 */
42 void setDataSourceItem(const QUuid &dataSourceUid,
43 std::unique_ptr<DataSourceItem> dataSourceItem) noexcept;
44
27 45 public slots:
28 46 /// Manage init/end of the controller
29 47 void initialize();
30 48 void finalize();
31 49
50 signals:
51 /// Signal emitted when a structure has been set for a data source
52 void dataSourceItemSet(const DataSourceItem &dataSourceItem);
53
32 54 private:
33 55 void waitForFinish();
34 56
@@ -1,4 +1,5
1 #include "DataSource/DataSourceController.h"
1 #include <DataSource/DataSourceController.h>
2 #include <DataSource/DataSourceItem.h>
2 3
3 4 #include <QMutex>
4 5 #include <QThread>
@@ -10,31 +11,60 Q_LOGGING_CATEGORY(LOG_DataSourceController, "DataSourceController")
10 11
11 12 class DataSourceController::DataSourceControllerPrivate {
12 13 public:
13 DataSourceControllerPrivate() {}
14
15 14 QMutex m_WorkingMutex;
15 /// Data sources registered
16 QHash<QUuid, QString> m_DataSources;
17 /// Data sources structures
18 std::map<QUuid, std::unique_ptr<DataSourceItem> > m_DataSourceItems;
16 19 };
17 20
18 21 DataSourceController::DataSourceController(QObject *parent)
19 22 : impl{spimpl::make_unique_impl<DataSourceControllerPrivate>()}
20 23 {
21 qCDebug(LOG_DataSourceController()) << tr("Construction du DataSourceController")
22 << QThread::currentThread();
24 qCDebug(LOG_DataSourceController())
25 << tr("DataSourceController construction") << QThread::currentThread();
23 26 }
24 27
25 28 DataSourceController::~DataSourceController()
26 29 {
27 qCDebug(LOG_DataSourceController()) << tr("Desctruction du DataSourceController")
28 << QThread::currentThread();
30 qCDebug(LOG_DataSourceController())
31 << tr("DataSourceController destruction") << QThread::currentThread();
29 32 this->waitForFinish();
30 33 }
31 34
35 QUuid DataSourceController::registerDataSource(const QString &dataSourceName) noexcept
36 {
37 auto dataSourceUid = QUuid::createUuid();
38 impl->m_DataSources.insert(dataSourceUid, dataSourceName);
39
40 return dataSourceUid;
41 }
42
43 void DataSourceController::setDataSourceItem(
44 const QUuid &dataSourceUid, std::unique_ptr<DataSourceItem> dataSourceItem) noexcept
45 {
46 if (impl->m_DataSources.contains(dataSourceUid)) {
47 impl->m_DataSourceItems.insert(std::make_pair(dataSourceUid, std::move(dataSourceItem)));
48
49 // Retrieves the data source item to emit the signal with it
50 auto it = impl->m_DataSourceItems.find(dataSourceUid);
51 if (it != impl->m_DataSourceItems.end()) {
52 emit dataSourceItemSet(*it->second);
53 }
54 }
55 else {
56 qCWarning(LOG_DataSourceController()) << tr("Can't set data source item for uid %1 : no "
57 "data source has been registered with the uid")
58 .arg(dataSourceUid.toString());
59 }
60 }
61
32 62 void DataSourceController::initialize()
33 63 {
34 qCDebug(LOG_DataSourceController()) << tr("initialize du DataSourceController")
35 << QThread::currentThread();
64 qCDebug(LOG_DataSourceController())
65 << tr("DataSourceController init") << QThread::currentThread();
36 66 impl->m_WorkingMutex.lock();
37 qCDebug(LOG_DataSourceController()) << tr("initialize du DataSourceController END");
67 qCDebug(LOG_DataSourceController()) << tr("DataSourceController init END");
38 68 }
39 69
40 70 void DataSourceController::finalize()
@@ -44,5 +74,5 void DataSourceController::finalize()
44 74
45 75 void DataSourceController::waitForFinish()
46 76 {
47 QMutexLocker locker(&impl->m_WorkingMutex);
77 QMutexLocker locker{&impl->m_WorkingMutex};
48 78 }
@@ -2,3 +2,7
2 2
3 3 .*IPSIS_S04_METHOD.*found: Q_DECLARE_LOGGING_CATEGORY.*
4 4 .*IPSIS_S04_VARIABLE.*found: impl.*
5
6 # Ignore false positive relative to 'noexcept' keyword
7 .*IPSIS_S04_VARIABLE.*found: noexcept
8 .*IPSIS_S06.*found: noexcept
@@ -110,9 +110,11 IF(BUILD_TESTS)
110 110 ${testDirectory}/*.cpp
111 111 ${testDirectory}/*.h)
112 112 LIST (REMOVE_ITEM currentTestSources ${TESTS_SOURCES})
113 LIST (REMOVE_ITEM currentTestSources ${TESTS_HEADERS})
113 # LIST (REMOVE_ITEM currentTestSources ${TESTS_HEADERS})
114 114
115 115 ADD_EXECUTABLE(${testName} ${testFile} ${currentTestSources})
116 set_property(TARGET ${testName} PROPERTY CXX_STANDARD 14)
117 set_property(TARGET ${testName} PROPERTY CXX_STANDARD_REQUIRED ON)
116 118 TARGET_LINK_LIBRARIES( ${testName} ${TEST_LIBRARIES} )
117 119 qt5_use_modules(${testName} Test)
118 120
@@ -10,12 +10,19
10 10
11 11 Q_DECLARE_LOGGING_CATEGORY(LOG_SqpApplication)
12 12
13 #if defined(sqpApp)
14 #undef sqpApp
15 #endif
16 #define sqpApp (static_cast<SqpApplication *>(QCoreApplication::instance()))
17
18 class DataSourceController;
19
13 20 /**
14 21 * @brief The SqpApplication class aims to make the link between SciQlop
15 * and its plugins. This is the intermediate class that SciQlop have to use
16 * in the way to connect a data source. Please first use load method to intialize
22 * and its plugins. This is the intermediate class that SciQlop has to use
23 * in the way to connect a data source. Please first use load method to initialize
17 24 * a plugin specified by its metadata name (JSON plugin source) then others specifics
18 * method will ba able to access it.
25 * method will be able to access it.
19 26 * You can load a data source driver plugin then create a data source.
20 27 */
21 28
@@ -26,6 +33,8 public:
26 33 virtual ~SqpApplication();
27 34 void initialize();
28 35
36 DataSourceController &dataSourceController() const noexcept;
37
29 38 private:
30 39 class SqpApplicationPrivate;
31 40 spimpl::unique_impl_ptr<SqpApplicationPrivate> impl;
@@ -7,10 +7,14 Q_LOGGING_CATEGORY(LOG_SqpApplication, "SqpApplication")
7 7
8 8 class SqpApplication::SqpApplicationPrivate {
9 9 public:
10 SqpApplicationPrivate() {}
10 SqpApplicationPrivate() : m_DataSourceController{std::make_unique<DataSourceController>()}
11 {
12 m_DataSourceController->moveToThread(&m_DataSourceControllerThread);
13 }
14
11 15 virtual ~SqpApplicationPrivate()
12 16 {
13 qCInfo(LOG_SqpApplication()) << tr("Desctruction du SqpApplicationPrivate");
17 qCInfo(LOG_SqpApplication()) << tr("SqpApplicationPrivate destruction");
14 18 m_DataSourceControllerThread.quit();
15 19 m_DataSourceControllerThread.wait();
16 20 }
@@ -21,12 +25,9 public:
21 25
22 26
23 27 SqpApplication::SqpApplication(int &argc, char **argv)
24 : QApplication(argc, argv), impl{spimpl::make_unique_impl<SqpApplicationPrivate>()}
28 : QApplication{argc, argv}, impl{spimpl::make_unique_impl<SqpApplicationPrivate>()}
25 29 {
26 qCInfo(LOG_SqpApplication()) << tr("Construction du SqpApplication");
27
28 impl->m_DataSourceController = std::make_unique<DataSourceController>();
29 impl->m_DataSourceController->moveToThread(&impl->m_DataSourceControllerThread);
30 qCInfo(LOG_SqpApplication()) << tr("SqpApplication construction");
30 31
31 32 connect(&impl->m_DataSourceControllerThread, &QThread::started,
32 33 impl->m_DataSourceController.get(), &DataSourceController::initialize);
@@ -43,3 +44,8 SqpApplication::~SqpApplication()
43 44 void SqpApplication::initialize()
44 45 {
45 46 }
47
48 DataSourceController &SqpApplication::dataSourceController() const noexcept
49 {
50 return *impl->m_DataSourceController;
51 }
General Comments 0
You need to be logged in to leave comments. Login now