##// END OF EJS Templates
Merge branch 'feature/VariableColumns' into develop
Alexandre Leroux -
r552:780b372cbdd1 merge
parent child
Show More
@@ -1,96 +1,102
1 #ifndef SCIQLOP_DATASOURCEITEM_H
1 #ifndef SCIQLOP_DATASOURCEITEM_H
2 #define SCIQLOP_DATASOURCEITEM_H
2 #define SCIQLOP_DATASOURCEITEM_H
3
3
4 #include "CoreGlobal.h"
4 #include "CoreGlobal.h"
5
5
6 #include <Common/spimpl.h>
6 #include <Common/spimpl.h>
7
7
8 #include <QVariant>
8 #include <QVariant>
9 #include <QVector>
9 #include <QVector>
10
10
11 class DataSourceItemAction;
11 class DataSourceItemAction;
12
12
13 /**
13 /**
14 * Possible types of an item
14 * Possible types of an item
15 */
15 */
16 enum class DataSourceItemType { NODE, PRODUCT, COMPONENT };
16 enum class DataSourceItemType { NODE, PRODUCT, COMPONENT };
17
17
18 /**
18 /**
19 * @brief The DataSourceItem class aims to represent a structure element of a data source.
19 * @brief The DataSourceItem class aims to represent a structure element of a data source.
20 * A data source has a tree structure that is made up of a main DataSourceItem object (root)
20 * A data source has a tree structure that is made up of a main DataSourceItem object (root)
21 * containing other DataSourceItem objects (children).
21 * containing other DataSourceItem objects (children).
22 * For each DataSourceItem can be associated a set of data representing it.
22 * For each DataSourceItem can be associated a set of data representing it.
23 */
23 */
24 class SCIQLOP_CORE_EXPORT DataSourceItem {
24 class SCIQLOP_CORE_EXPORT DataSourceItem {
25 public:
25 public:
26 /// Key associated with the name of the item
26 /// Key associated with the name of the item
27 static const QString NAME_DATA_KEY;
27 static const QString NAME_DATA_KEY;
28
28
29 explicit DataSourceItem(DataSourceItemType type, const QString &name);
29 explicit DataSourceItem(DataSourceItemType type, const QString &name);
30 explicit DataSourceItem(DataSourceItemType type, QVariantHash data = {});
30 explicit DataSourceItem(DataSourceItemType type, QVariantHash data = {});
31
31
32 /// @return the actions of the item as a vector
32 /// @return the actions of the item as a vector
33 QVector<DataSourceItemAction *> actions() const noexcept;
33 QVector<DataSourceItemAction *> actions() const noexcept;
34
34
35 /**
35 /**
36 * Adds an action to the item. The item takes ownership of the action, and the action is
36 * Adds an action to the item. The item takes ownership of the action, and the action is
37 * automatically associated to the item
37 * automatically associated to the item
38 * @param action the action to add
38 * @param action the action to add
39 */
39 */
40 void addAction(std::unique_ptr<DataSourceItemAction> action) noexcept;
40 void addAction(std::unique_ptr<DataSourceItemAction> action) noexcept;
41
41
42 /**
42 /**
43 * Adds a child to the item. The item takes ownership of the child.
43 * Adds a child to the item. The item takes ownership of the child.
44 * @param child the child to add
44 * @param child the child to add
45 */
45 */
46 void appendChild(std::unique_ptr<DataSourceItem> child) noexcept;
46 void appendChild(std::unique_ptr<DataSourceItem> child) noexcept;
47
47
48 /**
48 /**
49 * Returns the item's child associated to an index
49 * Returns the item's child associated to an index
50 * @param childIndex the index to search
50 * @param childIndex the index to search
51 * @return a pointer to the child if index is valid, nullptr otherwise
51 * @return a pointer to the child if index is valid, nullptr otherwise
52 */
52 */
53 DataSourceItem *child(int childIndex) const noexcept;
53 DataSourceItem *child(int childIndex) const noexcept;
54
54
55 int childCount() const noexcept;
55 int childCount() const noexcept;
56
56
57 /**
57 /**
58 * Get the data associated to a key
58 * Get the data associated to a key
59 * @param key the key to search
59 * @param key the key to search
60 * @return the data found if key is valid, default QVariant otherwise
60 * @return the data found if key is valid, default QVariant otherwise
61 */
61 */
62 QVariant data(const QString &key) const noexcept;
62 QVariant data(const QString &key) const noexcept;
63
63
64 /// Gets all data
64 /// Gets all data
65 QVariantHash data() const noexcept;
65 QVariantHash data() const noexcept;
66
66
67 bool isRoot() const noexcept;
67 bool isRoot() const noexcept;
68
68
69 QString name() const noexcept;
69 QString name() const noexcept;
70
70
71 /**
71 /**
72 * Get the item's parent
72 * Get the item's parent
73 * @return a pointer to the parent if it exists, nullptr if the item is a root
73 * @return a pointer to the parent if it exists, nullptr if the item is a root
74 */
74 */
75 DataSourceItem *parentItem() const noexcept;
75 DataSourceItem *parentItem() const noexcept;
76
76
77 /**
77 /**
78 * Gets the item's root
79 * @return the top parent, the item itself if it's the root item
80 */
81 const DataSourceItem &rootItem() const noexcept;
82
83 /**
78 * Sets or appends a value to a key
84 * Sets or appends a value to a key
79 * @param key the key
85 * @param key the key
80 * @param value the value
86 * @param value the value
81 * @param append if true, the value is added to the values already existing for the key,
87 * @param append if true, the value is added to the values already existing for the key,
82 * otherwise it replaces the existing values
88 * otherwise it replaces the existing values
83 */
89 */
84 void setData(const QString &key, const QVariant &value, bool append = false) noexcept;
90 void setData(const QString &key, const QVariant &value, bool append = false) noexcept;
85
91
86 DataSourceItemType type() const noexcept;
92 DataSourceItemType type() const noexcept;
87
93
88 bool operator==(const DataSourceItem &other);
94 bool operator==(const DataSourceItem &other);
89 bool operator!=(const DataSourceItem &other);
95 bool operator!=(const DataSourceItem &other);
90
96
91 private:
97 private:
92 class DataSourceItemPrivate;
98 class DataSourceItemPrivate;
93 spimpl::unique_impl_ptr<DataSourceItemPrivate> impl;
99 spimpl::unique_impl_ptr<DataSourceItemPrivate> impl;
94 };
100 };
95
101
96 #endif // SCIQLOP_DATASOURCEITEMMODEL_H
102 #endif // SCIQLOP_DATASOURCEITEMMODEL_H
@@ -1,120 +1,143
1 #include "DataSource/DataSourceController.h"
1 #include "DataSource/DataSourceController.h"
2 #include "DataSource/DataSourceItem.h"
2 #include "DataSource/DataSourceItem.h"
3
3
4 #include <Data/IDataProvider.h>
4 #include <Data/IDataProvider.h>
5
5
6 #include <QMutex>
6 #include <QMutex>
7 #include <QThread>
7 #include <QThread>
8
8
9 #include <QDir>
9 #include <QDir>
10 #include <QStandardPaths>
10 #include <QStandardPaths>
11
11
12 Q_LOGGING_CATEGORY(LOG_DataSourceController, "DataSourceController")
12 Q_LOGGING_CATEGORY(LOG_DataSourceController, "DataSourceController")
13
13
14 namespace {
15
16 /**
17 * Builds the metadata of the variable that will be generated from the loading of an item
18 * @param dataSourceItem the data source item from which to generate the metadata
19 * @return the metadata of the variable
20 */
21 QVariantHash variableMetadata(const DataSourceItem &dataSourceItem)
22 {
23 // Variable metadata contains...
24
25 // ... all metadata of the item
26 auto result = dataSourceItem.data();
27
28 // ... and the name of the plugin, recovered from root item
29 result.insert(QStringLiteral("plugin"), dataSourceItem.rootItem().name());
30
31 return result;
32 }
33
34 } // namespace
35
14 class DataSourceController::DataSourceControllerPrivate {
36 class DataSourceController::DataSourceControllerPrivate {
15 public:
37 public:
16 QMutex m_WorkingMutex;
38 QMutex m_WorkingMutex;
17 /// Data sources registered
39 /// Data sources registered
18 QHash<QUuid, QString> m_DataSources;
40 QHash<QUuid, QString> m_DataSources;
19 /// Data sources structures
41 /// Data sources structures
20 std::map<QUuid, std::unique_ptr<DataSourceItem> > m_DataSourceItems;
42 std::map<QUuid, std::unique_ptr<DataSourceItem> > m_DataSourceItems;
21 /// Data providers registered
43 /// Data providers registered
22 /// @remarks Data providers are stored as shared_ptr as they can be sent to a variable and
44 /// @remarks Data providers are stored as shared_ptr as they can be sent to a variable and
23 /// continue to live without necessarily the data source controller
45 /// continue to live without necessarily the data source controller
24 std::map<QUuid, std::shared_ptr<IDataProvider> > m_DataProviders;
46 std::map<QUuid, std::shared_ptr<IDataProvider> > m_DataProviders;
25 };
47 };
26
48
27 DataSourceController::DataSourceController(QObject *parent)
49 DataSourceController::DataSourceController(QObject *parent)
28 : impl{spimpl::make_unique_impl<DataSourceControllerPrivate>()}
50 : impl{spimpl::make_unique_impl<DataSourceControllerPrivate>()}
29 {
51 {
30 qCDebug(LOG_DataSourceController()) << tr("DataSourceController construction")
52 qCDebug(LOG_DataSourceController()) << tr("DataSourceController construction")
31 << QThread::currentThread();
53 << QThread::currentThread();
32 }
54 }
33
55
34 DataSourceController::~DataSourceController()
56 DataSourceController::~DataSourceController()
35 {
57 {
36 qCDebug(LOG_DataSourceController()) << tr("DataSourceController destruction")
58 qCDebug(LOG_DataSourceController()) << tr("DataSourceController destruction")
37 << QThread::currentThread();
59 << QThread::currentThread();
38 this->waitForFinish();
60 this->waitForFinish();
39 }
61 }
40
62
41 QUuid DataSourceController::registerDataSource(const QString &dataSourceName) noexcept
63 QUuid DataSourceController::registerDataSource(const QString &dataSourceName) noexcept
42 {
64 {
43 auto dataSourceUid = QUuid::createUuid();
65 auto dataSourceUid = QUuid::createUuid();
44 impl->m_DataSources.insert(dataSourceUid, dataSourceName);
66 impl->m_DataSources.insert(dataSourceUid, dataSourceName);
45
67
46 return dataSourceUid;
68 return dataSourceUid;
47 }
69 }
48
70
49 void DataSourceController::setDataSourceItem(
71 void DataSourceController::setDataSourceItem(
50 const QUuid &dataSourceUid, std::unique_ptr<DataSourceItem> dataSourceItem) noexcept
72 const QUuid &dataSourceUid, std::unique_ptr<DataSourceItem> dataSourceItem) noexcept
51 {
73 {
52 if (!dataSourceItem) {
74 if (!dataSourceItem) {
53 qCWarning(LOG_DataSourceController())
75 qCWarning(LOG_DataSourceController())
54 << tr("Data source item can't be registered (null item)");
76 << tr("Data source item can't be registered (null item)");
55 return;
77 return;
56 }
78 }
57
79
58 if (impl->m_DataSources.contains(dataSourceUid)) {
80 if (impl->m_DataSources.contains(dataSourceUid)) {
59 // The data provider is implicitly converted to a shared_ptr
81 // The data provider is implicitly converted to a shared_ptr
60 impl->m_DataSourceItems.insert(std::make_pair(dataSourceUid, std::move(dataSourceItem)));
82 impl->m_DataSourceItems.insert(std::make_pair(dataSourceUid, std::move(dataSourceItem)));
61
83
62 // Retrieves the data source item to emit the signal with it
84 // Retrieves the data source item to emit the signal with it
63 auto it = impl->m_DataSourceItems.find(dataSourceUid);
85 auto it = impl->m_DataSourceItems.find(dataSourceUid);
64 if (it != impl->m_DataSourceItems.end()) {
86 if (it != impl->m_DataSourceItems.end()) {
65 emit dataSourceItemSet(it->second.get());
87 emit dataSourceItemSet(it->second.get());
66 }
88 }
67 }
89 }
68 else {
90 else {
69 qCWarning(LOG_DataSourceController()) << tr("Can't set data source item for uid %1 : no "
91 qCWarning(LOG_DataSourceController()) << tr("Can't set data source item for uid %1 : no "
70 "data source has been registered with the uid")
92 "data source has been registered with the uid")
71 .arg(dataSourceUid.toString());
93 .arg(dataSourceUid.toString());
72 }
94 }
73 }
95 }
74
96
75 void DataSourceController::setDataProvider(const QUuid &dataSourceUid,
97 void DataSourceController::setDataProvider(const QUuid &dataSourceUid,
76 std::unique_ptr<IDataProvider> dataProvider) noexcept
98 std::unique_ptr<IDataProvider> dataProvider) noexcept
77 {
99 {
78 if (impl->m_DataSources.contains(dataSourceUid)) {
100 if (impl->m_DataSources.contains(dataSourceUid)) {
79 impl->m_DataProviders.insert(std::make_pair(dataSourceUid, std::move(dataProvider)));
101 impl->m_DataProviders.insert(std::make_pair(dataSourceUid, std::move(dataProvider)));
80 }
102 }
81 else {
103 else {
82 qCWarning(LOG_DataSourceController()) << tr("Can't set data provider for uid %1 : no data "
104 qCWarning(LOG_DataSourceController()) << tr("Can't set data provider for uid %1 : no data "
83 "source has been registered with the uid")
105 "source has been registered with the uid")
84 .arg(dataSourceUid.toString());
106 .arg(dataSourceUid.toString());
85 }
107 }
86 }
108 }
87
109
88 void DataSourceController::loadProductItem(const QUuid &dataSourceUid,
110 void DataSourceController::loadProductItem(const QUuid &dataSourceUid,
89 const DataSourceItem &productItem) noexcept
111 const DataSourceItem &productItem) noexcept
90 {
112 {
91 if (productItem.type() == DataSourceItemType::PRODUCT
113 if (productItem.type() == DataSourceItemType::PRODUCT
92 || productItem.type() == DataSourceItemType::COMPONENT) {
114 || productItem.type() == DataSourceItemType::COMPONENT) {
93 /// Retrieves the data provider of the data source (if any)
115 /// Retrieves the data provider of the data source (if any)
94 auto it = impl->m_DataProviders.find(dataSourceUid);
116 auto it = impl->m_DataProviders.find(dataSourceUid);
95 auto dataProvider = (it != impl->m_DataProviders.end()) ? it->second : nullptr;
117 auto dataProvider = (it != impl->m_DataProviders.end()) ? it->second : nullptr;
96
118
97 emit variableCreationRequested(productItem.name(), productItem.data(), dataProvider);
119 emit variableCreationRequested(productItem.name(), variableMetadata(productItem),
120 dataProvider);
98 }
121 }
99 else {
122 else {
100 qCWarning(LOG_DataSourceController()) << tr("Can't load an item that is not a product");
123 qCWarning(LOG_DataSourceController()) << tr("Can't load an item that is not a product");
101 }
124 }
102 }
125 }
103
126
104 void DataSourceController::initialize()
127 void DataSourceController::initialize()
105 {
128 {
106 qCDebug(LOG_DataSourceController()) << tr("DataSourceController init")
129 qCDebug(LOG_DataSourceController()) << tr("DataSourceController init")
107 << QThread::currentThread();
130 << QThread::currentThread();
108 impl->m_WorkingMutex.lock();
131 impl->m_WorkingMutex.lock();
109 qCDebug(LOG_DataSourceController()) << tr("DataSourceController init END");
132 qCDebug(LOG_DataSourceController()) << tr("DataSourceController init END");
110 }
133 }
111
134
112 void DataSourceController::finalize()
135 void DataSourceController::finalize()
113 {
136 {
114 impl->m_WorkingMutex.unlock();
137 impl->m_WorkingMutex.unlock();
115 }
138 }
116
139
117 void DataSourceController::waitForFinish()
140 void DataSourceController::waitForFinish()
118 {
141 {
119 QMutexLocker locker{&impl->m_WorkingMutex};
142 QMutexLocker locker{&impl->m_WorkingMutex};
120 }
143 }
@@ -1,140 +1,145
1 #include <DataSource/DataSourceItem.h>
1 #include <DataSource/DataSourceItem.h>
2 #include <DataSource/DataSourceItemAction.h>
2 #include <DataSource/DataSourceItemAction.h>
3
3
4 #include <QVector>
4 #include <QVector>
5
5
6 const QString DataSourceItem::NAME_DATA_KEY = QStringLiteral("name");
6 const QString DataSourceItem::NAME_DATA_KEY = QStringLiteral("name");
7
7
8 struct DataSourceItem::DataSourceItemPrivate {
8 struct DataSourceItem::DataSourceItemPrivate {
9 explicit DataSourceItemPrivate(DataSourceItemType type, QVariantHash data)
9 explicit DataSourceItemPrivate(DataSourceItemType type, QVariantHash data)
10 : m_Parent{nullptr}, m_Children{}, m_Type{type}, m_Data{std::move(data)}, m_Actions{}
10 : m_Parent{nullptr}, m_Children{}, m_Type{type}, m_Data{std::move(data)}, m_Actions{}
11 {
11 {
12 }
12 }
13
13
14 DataSourceItem *m_Parent;
14 DataSourceItem *m_Parent;
15 std::vector<std::unique_ptr<DataSourceItem> > m_Children;
15 std::vector<std::unique_ptr<DataSourceItem> > m_Children;
16 DataSourceItemType m_Type;
16 DataSourceItemType m_Type;
17 QVariantHash m_Data;
17 QVariantHash m_Data;
18 std::vector<std::unique_ptr<DataSourceItemAction> > m_Actions;
18 std::vector<std::unique_ptr<DataSourceItemAction> > m_Actions;
19 };
19 };
20
20
21 DataSourceItem::DataSourceItem(DataSourceItemType type, const QString &name)
21 DataSourceItem::DataSourceItem(DataSourceItemType type, const QString &name)
22 : DataSourceItem{type, QVariantHash{{NAME_DATA_KEY, name}}}
22 : DataSourceItem{type, QVariantHash{{NAME_DATA_KEY, name}}}
23 {
23 {
24 }
24 }
25
25
26 DataSourceItem::DataSourceItem(DataSourceItemType type, QVariantHash data)
26 DataSourceItem::DataSourceItem(DataSourceItemType type, QVariantHash data)
27 : impl{spimpl::make_unique_impl<DataSourceItemPrivate>(type, std::move(data))}
27 : impl{spimpl::make_unique_impl<DataSourceItemPrivate>(type, std::move(data))}
28 {
28 {
29 }
29 }
30
30
31 QVector<DataSourceItemAction *> DataSourceItem::actions() const noexcept
31 QVector<DataSourceItemAction *> DataSourceItem::actions() const noexcept
32 {
32 {
33 auto result = QVector<DataSourceItemAction *>{};
33 auto result = QVector<DataSourceItemAction *>{};
34
34
35 std::transform(std::cbegin(impl->m_Actions), std::cend(impl->m_Actions),
35 std::transform(std::cbegin(impl->m_Actions), std::cend(impl->m_Actions),
36 std::back_inserter(result), [](const auto &action) { return action.get(); });
36 std::back_inserter(result), [](const auto &action) { return action.get(); });
37
37
38 return result;
38 return result;
39 }
39 }
40
40
41 void DataSourceItem::addAction(std::unique_ptr<DataSourceItemAction> action) noexcept
41 void DataSourceItem::addAction(std::unique_ptr<DataSourceItemAction> action) noexcept
42 {
42 {
43 action->setDataSourceItem(this);
43 action->setDataSourceItem(this);
44 impl->m_Actions.push_back(std::move(action));
44 impl->m_Actions.push_back(std::move(action));
45 }
45 }
46
46
47 void DataSourceItem::appendChild(std::unique_ptr<DataSourceItem> child) noexcept
47 void DataSourceItem::appendChild(std::unique_ptr<DataSourceItem> child) noexcept
48 {
48 {
49 child->impl->m_Parent = this;
49 child->impl->m_Parent = this;
50 impl->m_Children.push_back(std::move(child));
50 impl->m_Children.push_back(std::move(child));
51 }
51 }
52
52
53 DataSourceItem *DataSourceItem::child(int childIndex) const noexcept
53 DataSourceItem *DataSourceItem::child(int childIndex) const noexcept
54 {
54 {
55 if (childIndex < 0 || childIndex >= childCount()) {
55 if (childIndex < 0 || childIndex >= childCount()) {
56 return nullptr;
56 return nullptr;
57 }
57 }
58 else {
58 else {
59 return impl->m_Children.at(childIndex).get();
59 return impl->m_Children.at(childIndex).get();
60 }
60 }
61 }
61 }
62
62
63 int DataSourceItem::childCount() const noexcept
63 int DataSourceItem::childCount() const noexcept
64 {
64 {
65 return impl->m_Children.size();
65 return impl->m_Children.size();
66 }
66 }
67
67
68 QVariant DataSourceItem::data(const QString &key) const noexcept
68 QVariant DataSourceItem::data(const QString &key) const noexcept
69 {
69 {
70 return impl->m_Data.value(key);
70 return impl->m_Data.value(key);
71 }
71 }
72
72
73 QVariantHash DataSourceItem::data() const noexcept
73 QVariantHash DataSourceItem::data() const noexcept
74 {
74 {
75 return impl->m_Data;
75 return impl->m_Data;
76 }
76 }
77
77
78 bool DataSourceItem::isRoot() const noexcept
78 bool DataSourceItem::isRoot() const noexcept
79 {
79 {
80 return impl->m_Parent == nullptr;
80 return impl->m_Parent == nullptr;
81 }
81 }
82
82
83 QString DataSourceItem::name() const noexcept
83 QString DataSourceItem::name() const noexcept
84 {
84 {
85 return data(NAME_DATA_KEY).toString();
85 return data(NAME_DATA_KEY).toString();
86 }
86 }
87
87
88 DataSourceItem *DataSourceItem::parentItem() const noexcept
88 DataSourceItem *DataSourceItem::parentItem() const noexcept
89 {
89 {
90 return impl->m_Parent;
90 return impl->m_Parent;
91 }
91 }
92
92
93 const DataSourceItem &DataSourceItem::rootItem() const noexcept
94 {
95 return isRoot() ? *this : parentItem()->rootItem();
96 }
97
93 void DataSourceItem::setData(const QString &key, const QVariant &value, bool append) noexcept
98 void DataSourceItem::setData(const QString &key, const QVariant &value, bool append) noexcept
94 {
99 {
95 auto it = impl->m_Data.constFind(key);
100 auto it = impl->m_Data.constFind(key);
96 if (append && it != impl->m_Data.constEnd()) {
101 if (append && it != impl->m_Data.constEnd()) {
97 // Case of an existing value to which we want to add to the new value
102 // Case of an existing value to which we want to add to the new value
98 if (it->canConvert<QVariantList>()) {
103 if (it->canConvert<QVariantList>()) {
99 auto variantList = it->value<QVariantList>();
104 auto variantList = it->value<QVariantList>();
100 variantList.append(value);
105 variantList.append(value);
101
106
102 impl->m_Data.insert(key, variantList);
107 impl->m_Data.insert(key, variantList);
103 }
108 }
104 else {
109 else {
105 impl->m_Data.insert(key, QVariantList{*it, value});
110 impl->m_Data.insert(key, QVariantList{*it, value});
106 }
111 }
107 }
112 }
108 else {
113 else {
109 // Other cases :
114 // Other cases :
110 // - new value in map OR
115 // - new value in map OR
111 // - replacement of an existing value (not appending)
116 // - replacement of an existing value (not appending)
112 impl->m_Data.insert(key, value);
117 impl->m_Data.insert(key, value);
113 }
118 }
114 }
119 }
115
120
116 DataSourceItemType DataSourceItem::type() const noexcept
121 DataSourceItemType DataSourceItem::type() const noexcept
117 {
122 {
118 return impl->m_Type;
123 return impl->m_Type;
119 }
124 }
120
125
121 bool DataSourceItem::operator==(const DataSourceItem &other)
126 bool DataSourceItem::operator==(const DataSourceItem &other)
122 {
127 {
123 // Compares items' attributes
128 // Compares items' attributes
124 if (std::tie(impl->m_Type, impl->m_Data) == std::tie(other.impl->m_Type, other.impl->m_Data)) {
129 if (std::tie(impl->m_Type, impl->m_Data) == std::tie(other.impl->m_Type, other.impl->m_Data)) {
125 // Compares contents of items' children
130 // Compares contents of items' children
126 return std::equal(std::cbegin(impl->m_Children), std::cend(impl->m_Children),
131 return std::equal(std::cbegin(impl->m_Children), std::cend(impl->m_Children),
127 std::cbegin(other.impl->m_Children),
132 std::cbegin(other.impl->m_Children),
128 [](const auto &itemChild, const auto &otherChild) {
133 [](const auto &itemChild, const auto &otherChild) {
129 return *itemChild == *otherChild;
134 return *itemChild == *otherChild;
130 });
135 });
131 }
136 }
132 else {
137 else {
133 return false;
138 return false;
134 }
139 }
135 }
140 }
136
141
137 bool DataSourceItem::operator!=(const DataSourceItem &other)
142 bool DataSourceItem::operator!=(const DataSourceItem &other)
138 {
143 {
139 return !(*this == other);
144 return !(*this == other);
140 }
145 }
@@ -1,249 +1,258
1 #include <Variable/Variable.h>
1 #include <Variable/Variable.h>
2 #include <Variable/VariableModel.h>
2 #include <Variable/VariableModel.h>
3
3
4 #include <Common/DateUtils.h>
4 #include <Common/DateUtils.h>
5
5
6 #include <Data/IDataSeries.h>
6 #include <Data/IDataSeries.h>
7
7
8 #include <QSize>
8 #include <QSize>
9 #include <unordered_map>
9 #include <unordered_map>
10
10
11 Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel")
11 Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel")
12
12
13 namespace {
13 namespace {
14
14
15 // Column indexes
15 // Column indexes
16 const auto NAME_COLUMN = 0;
16 const auto NAME_COLUMN = 0;
17 const auto TSTART_COLUMN = 1;
17 const auto TSTART_COLUMN = 1;
18 const auto TEND_COLUMN = 2;
18 const auto TEND_COLUMN = 2;
19 const auto NB_COLUMNS = 3;
19 const auto UNIT_COLUMN = 3;
20 const auto MISSION_COLUMN = 4;
21 const auto PLUGIN_COLUMN = 5;
22 const auto NB_COLUMNS = 6;
20
23
21 // Column properties
24 // Column properties
22 const auto DEFAULT_HEIGHT = 25;
25 const auto DEFAULT_HEIGHT = 25;
23 const auto DEFAULT_WIDTH = 100;
26 const auto DEFAULT_WIDTH = 100;
24
27
25 struct ColumnProperties {
28 struct ColumnProperties {
26 ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH,
29 ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH,
27 int height = DEFAULT_HEIGHT)
30 int height = DEFAULT_HEIGHT)
28 : m_Name{name}, m_Width{width}, m_Height{height}
31 : m_Name{name}, m_Width{width}, m_Height{height}
29 {
32 {
30 }
33 }
31
34
32 QString m_Name;
35 QString m_Name;
33 int m_Width;
36 int m_Width;
34 int m_Height;
37 int m_Height;
35 };
38 };
36
39
37 const auto COLUMN_PROPERTIES
40 const auto COLUMN_PROPERTIES = QHash<int, ColumnProperties>{
38 = QHash<int, ColumnProperties>{{NAME_COLUMN, {QObject::tr("Name")}},
41 {NAME_COLUMN, {QObject::tr("Name")}}, {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
39 {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
42 {TEND_COLUMN, {QObject::tr("tEnd"), 180}}, {UNIT_COLUMN, {QObject::tr("Unit")}},
40 {TEND_COLUMN, {QObject::tr("tEnd"), 180}}};
43 {MISSION_COLUMN, {QObject::tr("Mission")}}, {PLUGIN_COLUMN, {QObject::tr("Plugin")}}};
41
44
42 /// Format for datetimes
45 /// Format for datetimes
43 const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz");
46 const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz");
44
47
45
48
46 } // namespace
49 } // namespace
47
50
48 struct VariableModel::VariableModelPrivate {
51 struct VariableModel::VariableModelPrivate {
49 /// Variables created in SciQlop
52 /// Variables created in SciQlop
50 std::vector<std::shared_ptr<Variable> > m_Variables;
53 std::vector<std::shared_ptr<Variable> > m_Variables;
51 std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress;
54 std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress;
52
55
53 /// Return the row index of the variable. -1 if it's not found
56 /// Return the row index of the variable. -1 if it's not found
54 int indexOfVariable(Variable *variable) const noexcept;
57 int indexOfVariable(Variable *variable) const noexcept;
55 };
58 };
56
59
57 VariableModel::VariableModel(QObject *parent)
60 VariableModel::VariableModel(QObject *parent)
58 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
61 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
59 {
62 {
60 }
63 }
61
64
62 std::shared_ptr<Variable> VariableModel::createVariable(const QString &name,
65 std::shared_ptr<Variable> VariableModel::createVariable(const QString &name,
63 const SqpRange &dateTime,
66 const SqpRange &dateTime,
64 const QVariantHash &metadata) noexcept
67 const QVariantHash &metadata) noexcept
65 {
68 {
66 auto insertIndex = rowCount();
69 auto insertIndex = rowCount();
67 beginInsertRows({}, insertIndex, insertIndex);
70 beginInsertRows({}, insertIndex, insertIndex);
68
71
69 auto variable = std::make_shared<Variable>(name, dateTime, metadata);
72 auto variable = std::make_shared<Variable>(name, dateTime, metadata);
70
73
71 impl->m_Variables.push_back(variable);
74 impl->m_Variables.push_back(variable);
72 connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated);
75 connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated);
73
76
74 endInsertRows();
77 endInsertRows();
75
78
76 return variable;
79 return variable;
77 }
80 }
78
81
79 void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept
82 void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept
80 {
83 {
81 if (!variable) {
84 if (!variable) {
82 qCCritical(LOG_Variable()) << "Can't delete a null variable from the model";
85 qCCritical(LOG_Variable()) << "Can't delete a null variable from the model";
83 return;
86 return;
84 }
87 }
85
88
86 // Finds variable in the model
89 // Finds variable in the model
87 auto begin = impl->m_Variables.cbegin();
90 auto begin = impl->m_Variables.cbegin();
88 auto end = impl->m_Variables.cend();
91 auto end = impl->m_Variables.cend();
89 auto it = std::find(begin, end, variable);
92 auto it = std::find(begin, end, variable);
90 if (it != end) {
93 if (it != end) {
91 auto removeIndex = std::distance(begin, it);
94 auto removeIndex = std::distance(begin, it);
92
95
93 // Deletes variable
96 // Deletes variable
94 beginRemoveRows({}, removeIndex, removeIndex);
97 beginRemoveRows({}, removeIndex, removeIndex);
95 impl->m_Variables.erase(it);
98 impl->m_Variables.erase(it);
96 endRemoveRows();
99 endRemoveRows();
97 }
100 }
98 else {
101 else {
99 qCritical(LOG_VariableModel())
102 qCritical(LOG_VariableModel())
100 << tr("Can't delete variable %1 from the model: the variable is not in the model")
103 << tr("Can't delete variable %1 from the model: the variable is not in the model")
101 .arg(variable->name());
104 .arg(variable->name());
102 }
105 }
103
106
104 // Removes variable from progress map
107 // Removes variable from progress map
105 impl->m_VariableToProgress.erase(variable);
108 impl->m_VariableToProgress.erase(variable);
106 }
109 }
107
110
108
111
109 std::shared_ptr<Variable> VariableModel::variable(int index) const
112 std::shared_ptr<Variable> VariableModel::variable(int index) const
110 {
113 {
111 return (index >= 0 && index < impl->m_Variables.size()) ? impl->m_Variables[index] : nullptr;
114 return (index >= 0 && index < impl->m_Variables.size()) ? impl->m_Variables[index] : nullptr;
112 }
115 }
113
116
114 void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress)
117 void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress)
115 {
118 {
116 if (progress > 0.0) {
119 if (progress > 0.0) {
117 impl->m_VariableToProgress[variable] = progress;
120 impl->m_VariableToProgress[variable] = progress;
118 }
121 }
119 else {
122 else {
120 impl->m_VariableToProgress.erase(variable);
123 impl->m_VariableToProgress.erase(variable);
121 }
124 }
122 auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN);
125 auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN);
123
126
124 emit dataChanged(modelIndex, modelIndex);
127 emit dataChanged(modelIndex, modelIndex);
125 }
128 }
126
129
127 int VariableModel::columnCount(const QModelIndex &parent) const
130 int VariableModel::columnCount(const QModelIndex &parent) const
128 {
131 {
129 Q_UNUSED(parent);
132 Q_UNUSED(parent);
130
133
131 return NB_COLUMNS;
134 return NB_COLUMNS;
132 }
135 }
133
136
134 int VariableModel::rowCount(const QModelIndex &parent) const
137 int VariableModel::rowCount(const QModelIndex &parent) const
135 {
138 {
136 Q_UNUSED(parent);
139 Q_UNUSED(parent);
137
140
138 return impl->m_Variables.size();
141 return impl->m_Variables.size();
139 }
142 }
140
143
141 QVariant VariableModel::data(const QModelIndex &index, int role) const
144 QVariant VariableModel::data(const QModelIndex &index, int role) const
142 {
145 {
143 if (!index.isValid()) {
146 if (!index.isValid()) {
144 return QVariant{};
147 return QVariant{};
145 }
148 }
146
149
147 if (index.row() < 0 || index.row() >= rowCount()) {
150 if (index.row() < 0 || index.row() >= rowCount()) {
148 return QVariant{};
151 return QVariant{};
149 }
152 }
150
153
151 if (role == Qt::DisplayRole) {
154 if (role == Qt::DisplayRole) {
152 if (auto variable = impl->m_Variables.at(index.row()).get()) {
155 if (auto variable = impl->m_Variables.at(index.row()).get()) {
153 /// Lambda function that builds the variant to return for a time value
156 /// Lambda function that builds the variant to return for a time value
154 auto dateTimeVariant = [](double secs) {
157 auto dateTimeVariant = [](double secs) {
155 auto dateTime = DateUtils::dateTime(secs);
158 auto dateTime = DateUtils::dateTime(secs);
156 return dateTime.toString(DATETIME_FORMAT);
159 return dateTime.toString(DATETIME_FORMAT);
157 };
160 };
158
161
159 switch (index.column()) {
162 switch (index.column()) {
160 case NAME_COLUMN:
163 case NAME_COLUMN:
161 return variable->name();
164 return variable->name();
162 case TSTART_COLUMN:
165 case TSTART_COLUMN:
163 return dateTimeVariant(variable->range().m_TStart);
166 return dateTimeVariant(variable->range().m_TStart);
164 case TEND_COLUMN:
167 case TEND_COLUMN:
165 return dateTimeVariant(variable->range().m_TEnd);
168 return dateTimeVariant(variable->range().m_TEnd);
169 case UNIT_COLUMN:
170 return variable->metadata().value(QStringLiteral("units"));
171 case MISSION_COLUMN:
172 return variable->metadata().value(QStringLiteral("mission"));
173 case PLUGIN_COLUMN:
174 return variable->metadata().value(QStringLiteral("plugin"));
166 default:
175 default:
167 // No action
176 // No action
168 break;
177 break;
169 }
178 }
170
179
171 qWarning(LOG_VariableModel())
180 qWarning(LOG_VariableModel())
172 << tr("Can't get data (unknown column %1)").arg(index.column());
181 << tr("Can't get data (unknown column %1)").arg(index.column());
173 }
182 }
174 else {
183 else {
175 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
184 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
176 }
185 }
177 }
186 }
178 else if (role == VariableRoles::ProgressRole) {
187 else if (role == VariableRoles::ProgressRole) {
179 if (auto variable = impl->m_Variables.at(index.row())) {
188 if (auto variable = impl->m_Variables.at(index.row())) {
180
189
181 auto it = impl->m_VariableToProgress.find(variable);
190 auto it = impl->m_VariableToProgress.find(variable);
182 if (it != impl->m_VariableToProgress.cend()) {
191 if (it != impl->m_VariableToProgress.cend()) {
183 return it->second;
192 return it->second;
184 }
193 }
185 }
194 }
186 }
195 }
187
196
188 return QVariant{};
197 return QVariant{};
189 }
198 }
190
199
191 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
200 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
192 {
201 {
193 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
202 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
194 return QVariant{};
203 return QVariant{};
195 }
204 }
196
205
197 if (orientation == Qt::Horizontal) {
206 if (orientation == Qt::Horizontal) {
198 auto propertiesIt = COLUMN_PROPERTIES.find(section);
207 auto propertiesIt = COLUMN_PROPERTIES.find(section);
199 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
208 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
200 // Role is either DisplayRole or SizeHintRole
209 // Role is either DisplayRole or SizeHintRole
201 return (role == Qt::DisplayRole)
210 return (role == Qt::DisplayRole)
202 ? QVariant{propertiesIt->m_Name}
211 ? QVariant{propertiesIt->m_Name}
203 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
212 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
204 }
213 }
205 else {
214 else {
206 qWarning(LOG_VariableModel())
215 qWarning(LOG_VariableModel())
207 << tr("Can't get header data (unknown column %1)").arg(section);
216 << tr("Can't get header data (unknown column %1)").arg(section);
208 }
217 }
209 }
218 }
210
219
211 return QVariant{};
220 return QVariant{};
212 }
221 }
213
222
214 void VariableModel::abortProgress(const QModelIndex &index)
223 void VariableModel::abortProgress(const QModelIndex &index)
215 {
224 {
216 if (auto variable = impl->m_Variables.at(index.row())) {
225 if (auto variable = impl->m_Variables.at(index.row())) {
217 emit abortProgessRequested(variable);
226 emit abortProgessRequested(variable);
218 }
227 }
219 }
228 }
220
229
221 void VariableModel::onVariableUpdated() noexcept
230 void VariableModel::onVariableUpdated() noexcept
222 {
231 {
223 // Finds variable that has been updated in the model
232 // Finds variable that has been updated in the model
224 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
233 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
225 auto updatedVariableIndex = impl->indexOfVariable(updatedVariable);
234 auto updatedVariableIndex = impl->indexOfVariable(updatedVariable);
226
235
227 if (updatedVariableIndex > -1) {
236 if (updatedVariableIndex > -1) {
228 emit dataChanged(createIndex(updatedVariableIndex, 0),
237 emit dataChanged(createIndex(updatedVariableIndex, 0),
229 createIndex(updatedVariableIndex, columnCount() - 1));
238 createIndex(updatedVariableIndex, columnCount() - 1));
230 }
239 }
231 }
240 }
232 }
241 }
233
242
234 int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept
243 int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept
235 {
244 {
236 auto begin = std::cbegin(m_Variables);
245 auto begin = std::cbegin(m_Variables);
237 auto end = std::cend(m_Variables);
246 auto end = std::cend(m_Variables);
238 auto it
247 auto it
239 = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; });
248 = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; });
240
249
241 if (it != end) {
250 if (it != end) {
242 // Gets the index of the variable in the model: we assume here that views have the same
251 // Gets the index of the variable in the model: we assume here that views have the same
243 // order as the model
252 // order as the model
244 return std::distance(begin, it);
253 return std::distance(begin, it);
245 }
254 }
246 else {
255 else {
247 return -1;
256 return -1;
248 }
257 }
249 }
258 }
General Comments 0
You need to be logged in to leave comments. Login now