##// 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 build/
1 build/
2 CMakeLists.txt.user
2 CMakeLists.txt.user
3 /.project
3 /.project
4 core/src/Version.cpp
5 core/include/Version.h
@@ -75,7 +75,7 qt5_use_modules(${EXECUTABLE_NAME} Core Widgets)
75 LIST(APPEND CHECKSTYLE_INPUT_FILES ${APPLICATION_SOURCES})
75 LIST(APPEND CHECKSTYLE_INPUT_FILES ${APPLICATION_SOURCES})
76 SCIQLOP_SET_TO_PARENT_SCOPE(CHECKSTYLE_INPUT_FILES)
76 SCIQLOP_SET_TO_PARENT_SCOPE(CHECKSTYLE_INPUT_FILES)
77 # Vera++ exclusion files
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 SCIQLOP_SET_TO_PARENT_SCOPE(CHECKSTYLE_EXCLUSION_FILES)
79 SCIQLOP_SET_TO_PARENT_SCOPE(CHECKSTYLE_EXCLUSION_FILES)
80
80
81 #
81 #
@@ -27,8 +27,7
27
27
28 int main(int argc, char *argv[])
28 int main(int argc, char *argv[])
29 {
29 {
30 int ad;
30 SqpApplication a{argc, argv};
31 SqpApplication a(argc, argv);
32 SqpApplication::setOrganizationName("LPP");
31 SqpApplication::setOrganizationName("LPP");
33 SqpApplication::setOrganizationDomain("lpp.fr");
32 SqpApplication::setOrganizationDomain("lpp.fr");
34 SqpApplication::setApplicationName("SciQLop");
33 SqpApplication::setApplicationName("SciQLop");
@@ -79,10 +79,12 IF(BUILD_TESTS)
79 ${testDirectory}/*.c
79 ${testDirectory}/*.c
80 ${testDirectory}/*.cpp
80 ${testDirectory}/*.cpp
81 ${testDirectory}/*.h)
81 ${testDirectory}/*.h)
82 LIST (REMOVE_ITEM currentTestSources ${TESTS_SOURCES})
82 LIST (REMOVE_ITEM currentTestSources ${TESTS_SOURCES})
83 LIST (REMOVE_ITEM currentTestSources ${TESTS_HEADERS})
83 # LIST (REMOVE_ITEM currentTestSources ${TESTS_HEADERS})
84
84
85 ADD_EXECUTABLE(${testName} ${testFile} ${currentTestSources})
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 TARGET_LINK_LIBRARIES( ${testName} ${TEST_LIBRARIES} )
88 TARGET_LINK_LIBRARIES( ${testName} ${TEST_LIBRARIES} )
87 qt5_use_modules(${testName} Test)
89 qt5_use_modules(${testName} Test)
88
90
@@ -89,8 +89,9 using default_copier_t = typename default_copier<T>::type;
89
89
90 template <class T, class D, class C>
90 template <class T, class D, class C>
91 struct is_default_manageable
91 struct is_default_manageable
92 : public std::integral_constant<bool, std::is_same<D, default_deleter_t<T> >::value
92 : public std::integral_constant<bool,
93 && std::is_same<C, default_copier_t<T> >::value> {
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 template <class U>
134 template <class U>
134 impl_ptr(U *u, typename std::enable_if<std::is_convertible<U *, pointer>::value
135 impl_ptr(U *u,
135 && is_default_manageable::value,
136 typename std::enable_if<std::is_convertible<U *, pointer>::value
136 dummy_t_>::type
137 && is_default_manageable::value,
137 = dummy_t_()) SPIMPL_NOEXCEPT
138 dummy_t_>::type
139 = dummy_t_()) SPIMPL_NOEXCEPT
138 : impl_ptr(u, &details::default_delete<T>, &details::default_copy<T>)
140 : impl_ptr(u, &details::default_delete<T>, &details::default_copy<T>)
139 {
141 {
140 }
142 }
@@ -151,12 +153,12 public:
151
153
152 #ifdef SPIMPL_HAS_AUTO_PTR
154 #ifdef SPIMPL_HAS_AUTO_PTR
153 template <class U>
155 template <class U>
154 impl_ptr(std::auto_ptr<U> &&u, typename std::enable_if<std::is_convertible<U *, pointer>::value
156 impl_ptr(std::auto_ptr<U> &&u,
155 && is_default_manageable::value,
157 typename std::enable_if<std::is_convertible<U *, pointer>::value
156 dummy_t_>::type
158 && is_default_manageable::value,
157 = dummy_t_()) SPIMPL_NOEXCEPT
159 dummy_t_>::type
158 : ptr_(u.release(), &details::default_delete<T>),
160 = dummy_t_()) SPIMPL_NOEXCEPT : ptr_(u.release(), &details::default_delete<T>),
159 copier_(&details::default_copy<T>)
161 copier_(&details::default_copy<T>)
160 {
162 {
161 }
163 }
162 #endif
164 #endif
@@ -1,22 +1,22
1 #ifndef SCIQLOP_DATASOURCECONTROLLER_H
1 #ifndef SCIQLOP_DATASOURCECONTROLLER_H
2 #define SCIQLOP_DATASOURCECONTROLLER_H
2 #define SCIQLOP_DATASOURCECONTROLLER_H
3
3
4 #include "DataSourceController.h"
5
6 #include <QLoggingCategory>
4 #include <QLoggingCategory>
7 #include <QObject>
5 #include <QObject>
6 #include <QUuid>
8
7
9 #include <Common/spimpl.h>
8 #include <Common/spimpl.h>
10
9
11 Q_DECLARE_LOGGING_CATEGORY(LOG_DataSourceController)
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 * @brief The DataSourceController class aims to make the link between SciQlop and its plugins. This
15 * and its plugins. This is the intermediate class that SciQlop have to use
16 * is the intermediate class that SciQlop has to use in the way to connect a data source. Please
16 * in the way to connect a data source. Please first use load method to intialize
17 * first use register method to initialize a plugin specified by its metadata name (JSON plugin
17 * a plugin specified by its metadata name (JSON plugin source) then others specifics
18 * source) then others specifics method will be able to access it. You can load a data source driver
18 * method will ba able to access it.
19 * plugin then create a data source.
19 * You can load a data source driver plugin then create a data source.
20 */
20 */
21 class DataSourceController : public QObject {
21 class DataSourceController : public QObject {
22 Q_OBJECT
22 Q_OBJECT
@@ -24,11 +24,33 public:
24 explicit DataSourceController(QObject *parent = 0);
24 explicit DataSourceController(QObject *parent = 0);
25 virtual ~DataSourceController();
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 public slots:
45 public slots:
28 /// Manage init/end of the controller
46 /// Manage init/end of the controller
29 void initialize();
47 void initialize();
30 void finalize();
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 private:
54 private:
33 void waitForFinish();
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 #include <QMutex>
4 #include <QMutex>
4 #include <QThread>
5 #include <QThread>
@@ -10,31 +11,60 Q_LOGGING_CATEGORY(LOG_DataSourceController, "DataSourceController")
10
11
11 class DataSourceController::DataSourceControllerPrivate {
12 class DataSourceController::DataSourceControllerPrivate {
12 public:
13 public:
13 DataSourceControllerPrivate() {}
14
15 QMutex m_WorkingMutex;
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 DataSourceController::DataSourceController(QObject *parent)
21 DataSourceController::DataSourceController(QObject *parent)
19 : impl{spimpl::make_unique_impl<DataSourceControllerPrivate>()}
22 : impl{spimpl::make_unique_impl<DataSourceControllerPrivate>()}
20 {
23 {
21 qCDebug(LOG_DataSourceController()) << tr("Construction du DataSourceController")
24 qCDebug(LOG_DataSourceController())
22 << QThread::currentThread();
25 << tr("DataSourceController construction") << QThread::currentThread();
23 }
26 }
24
27
25 DataSourceController::~DataSourceController()
28 DataSourceController::~DataSourceController()
26 {
29 {
27 qCDebug(LOG_DataSourceController()) << tr("Desctruction du DataSourceController")
30 qCDebug(LOG_DataSourceController())
28 << QThread::currentThread();
31 << tr("DataSourceController destruction") << QThread::currentThread();
29 this->waitForFinish();
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 void DataSourceController::initialize()
62 void DataSourceController::initialize()
33 {
63 {
34 qCDebug(LOG_DataSourceController()) << tr("initialize du DataSourceController")
64 qCDebug(LOG_DataSourceController())
35 << QThread::currentThread();
65 << tr("DataSourceController init") << QThread::currentThread();
36 impl->m_WorkingMutex.lock();
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 void DataSourceController::finalize()
70 void DataSourceController::finalize()
@@ -44,5 +74,5 void DataSourceController::finalize()
44
74
45 void DataSourceController::waitForFinish()
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 .*IPSIS_S04_METHOD.*found: Q_DECLARE_LOGGING_CATEGORY.*
3 .*IPSIS_S04_METHOD.*found: Q_DECLARE_LOGGING_CATEGORY.*
4 .*IPSIS_S04_VARIABLE.*found: impl.*
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 ${testDirectory}/*.cpp
110 ${testDirectory}/*.cpp
111 ${testDirectory}/*.h)
111 ${testDirectory}/*.h)
112 LIST (REMOVE_ITEM currentTestSources ${TESTS_SOURCES})
112 LIST (REMOVE_ITEM currentTestSources ${TESTS_SOURCES})
113 LIST (REMOVE_ITEM currentTestSources ${TESTS_HEADERS})
113 # LIST (REMOVE_ITEM currentTestSources ${TESTS_HEADERS})
114
114
115 ADD_EXECUTABLE(${testName} ${testFile} ${currentTestSources})
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 TARGET_LINK_LIBRARIES( ${testName} ${TEST_LIBRARIES} )
118 TARGET_LINK_LIBRARIES( ${testName} ${TEST_LIBRARIES} )
117 qt5_use_modules(${testName} Test)
119 qt5_use_modules(${testName} Test)
118
120
@@ -10,12 +10,19
10
10
11 Q_DECLARE_LOGGING_CATEGORY(LOG_SqpApplication)
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 * @brief The SqpApplication class aims to make the link between SciQlop
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
22 * and its plugins. This is the intermediate class that SciQlop has to use
16 * in the way to connect a data source. Please first use load method to intialize
23 * in the way to connect a data source. Please first use load method to initialize
17 * a plugin specified by its metadata name (JSON plugin source) then others specifics
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 * You can load a data source driver plugin then create a data source.
26 * You can load a data source driver plugin then create a data source.
20 */
27 */
21
28
@@ -26,6 +33,8 public:
26 virtual ~SqpApplication();
33 virtual ~SqpApplication();
27 void initialize();
34 void initialize();
28
35
36 DataSourceController &dataSourceController() const noexcept;
37
29 private:
38 private:
30 class SqpApplicationPrivate;
39 class SqpApplicationPrivate;
31 spimpl::unique_impl_ptr<SqpApplicationPrivate> impl;
40 spimpl::unique_impl_ptr<SqpApplicationPrivate> impl;
@@ -7,10 +7,14 Q_LOGGING_CATEGORY(LOG_SqpApplication, "SqpApplication")
7
7
8 class SqpApplication::SqpApplicationPrivate {
8 class SqpApplication::SqpApplicationPrivate {
9 public:
9 public:
10 SqpApplicationPrivate() {}
10 SqpApplicationPrivate() : m_DataSourceController{std::make_unique<DataSourceController>()}
11 {
12 m_DataSourceController->moveToThread(&m_DataSourceControllerThread);
13 }
14
11 virtual ~SqpApplicationPrivate()
15 virtual ~SqpApplicationPrivate()
12 {
16 {
13 qCInfo(LOG_SqpApplication()) << tr("Desctruction du SqpApplicationPrivate");
17 qCInfo(LOG_SqpApplication()) << tr("SqpApplicationPrivate destruction");
14 m_DataSourceControllerThread.quit();
18 m_DataSourceControllerThread.quit();
15 m_DataSourceControllerThread.wait();
19 m_DataSourceControllerThread.wait();
16 }
20 }
@@ -21,12 +25,9 public:
21
25
22
26
23 SqpApplication::SqpApplication(int &argc, char **argv)
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");
30 qCInfo(LOG_SqpApplication()) << tr("SqpApplication construction");
27
28 impl->m_DataSourceController = std::make_unique<DataSourceController>();
29 impl->m_DataSourceController->moveToThread(&impl->m_DataSourceControllerThread);
30
31
31 connect(&impl->m_DataSourceControllerThread, &QThread::started,
32 connect(&impl->m_DataSourceControllerThread, &QThread::started,
32 impl->m_DataSourceController.get(), &DataSourceController::initialize);
33 impl->m_DataSourceController.get(), &DataSourceController::initialize);
@@ -43,3 +44,8 SqpApplication::~SqpApplication()
43 void SqpApplication::initialize()
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