##// END OF EJS Templates
Merge pull request 184 from SCIQLOP-Initialisation develop...
leroux -
r403:756d172725c6 merge
parent child
Show More
@@ -1,43 +1,46
1 #ifndef SCIQLOP_NETWORKCONTROLLER_H
1 #ifndef SCIQLOP_NETWORKCONTROLLER_H
2 #define SCIQLOP_NETWORKCONTROLLER_H
2 #define SCIQLOP_NETWORKCONTROLLER_H
3
3
4 #include <QLoggingCategory>
4 #include <QLoggingCategory>
5 #include <QObject>
5 #include <QObject>
6 #include <QUuid>
6 #include <QUuid>
7
7
8 #include <Common/spimpl.h>
8 #include <Common/spimpl.h>
9 #include <functional>
9 #include <functional>
10
10
11 Q_DECLARE_LOGGING_CATEGORY(LOG_NetworkController)
11 Q_DECLARE_LOGGING_CATEGORY(LOG_NetworkController)
12
12
13 class QNetworkReply;
13 class QNetworkReply;
14 class QNetworkRequest;
14 class QNetworkRequest;
15
15
16 /**
16 /**
17 * @brief The NetworkController class aims to handle all network connection of SciQlop.
17 * @brief The NetworkController class aims to handle all network connection of SciQlop.
18 */
18 */
19 class NetworkController : public QObject {
19 class NetworkController : public QObject {
20 Q_OBJECT
20 Q_OBJECT
21 public:
21 public:
22 explicit NetworkController(QObject *parent = 0);
22 explicit NetworkController(QObject *parent = 0);
23
23
24 void initialize();
24 void initialize();
25 void finalize();
25 void finalize();
26
26
27 public slots:
27 public slots:
28 /// Execute request and call callback when the reply is finished. Identifier is attached to the
29 /// callback
28 void onProcessRequested(const QNetworkRequest &request, QUuid identifier,
30 void onProcessRequested(const QNetworkRequest &request, QUuid identifier,
29 std::function<void(QNetworkReply *, QUuid)> callback);
31 std::function<void(QNetworkReply *, QUuid)> callback);
32 /// Cancel the request of identifier
30 void onReplyCanceled(QUuid identifier);
33 void onReplyCanceled(QUuid identifier);
31
34
32 signals:
35 signals:
33 void replyFinished(QNetworkReply *reply, QUuid identifier);
36 void replyFinished(QNetworkReply *reply, QUuid identifier);
34 void replyDownloadProgress(QUuid identifier);
37 void replyDownloadProgress(QUuid identifier, double progress);
35
38
36 private:
39 private:
37 void waitForFinish();
40 void waitForFinish();
38
41
39 class NetworkControllerPrivate;
42 class NetworkControllerPrivate;
40 spimpl::unique_impl_ptr<NetworkControllerPrivate> impl;
43 spimpl::unique_impl_ptr<NetworkControllerPrivate> impl;
41 };
44 };
42
45
43 #endif // SCIQLOP_NETWORKCONTROLLER_H
46 #endif // SCIQLOP_NETWORKCONTROLLER_H
@@ -1,80 +1,83
1 #ifndef SCIQLOP_VARIABLECONTROLLER_H
1 #ifndef SCIQLOP_VARIABLECONTROLLER_H
2 #define SCIQLOP_VARIABLECONTROLLER_H
2 #define SCIQLOP_VARIABLECONTROLLER_H
3
3
4 #include <Data/SqpDateTime.h>
4 #include <Data/SqpDateTime.h>
5
5
6 #include <QLoggingCategory>
6 #include <QLoggingCategory>
7 #include <QObject>
7 #include <QObject>
8
8
9 #include <Common/spimpl.h>
9 #include <Common/spimpl.h>
10
10
11 class IDataProvider;
11 class IDataProvider;
12 class QItemSelectionModel;
12 class QItemSelectionModel;
13 class TimeController;
13 class TimeController;
14 class Variable;
14 class Variable;
15 class VariableModel;
15 class VariableModel;
16
16
17 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableController)
17 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableController)
18
18
19 /**
19 /**
20 * @brief The VariableController class aims to handle the variables in SciQlop.
20 * @brief The VariableController class aims to handle the variables in SciQlop.
21 */
21 */
22 class VariableController : public QObject {
22 class VariableController : public QObject {
23 Q_OBJECT
23 Q_OBJECT
24 public:
24 public:
25 explicit VariableController(QObject *parent = 0);
25 explicit VariableController(QObject *parent = 0);
26 virtual ~VariableController();
26 virtual ~VariableController();
27
27
28 VariableModel *variableModel() noexcept;
28 VariableModel *variableModel() noexcept;
29 QItemSelectionModel *variableSelectionModel() noexcept;
29 QItemSelectionModel *variableSelectionModel() noexcept;
30
30
31 void setTimeController(TimeController *timeController) noexcept;
31 void setTimeController(TimeController *timeController) noexcept;
32
32
33 /**
33 /**
34 * Deletes from the controller the variable passed in parameter.
34 * Deletes from the controller the variable passed in parameter.
35 *
35 *
36 * Delete a variable includes:
36 * Delete a variable includes:
37 * - the deletion of the various references to the variable in SciQlop
37 * - the deletion of the various references to the variable in SciQlop
38 * - the deletion of the model variable
38 * - the deletion of the model variable
39 * - the deletion of the provider associated with the variable
39 * - the deletion of the provider associated with the variable
40 * - removing the cache associated with the variable
40 * - removing the cache associated with the variable
41 *
41 *
42 * @param variable the variable to delete from the controller.
42 * @param variable the variable to delete from the controller.
43 */
43 */
44 void deleteVariable(std::shared_ptr<Variable> variable) noexcept;
44 void deleteVariable(std::shared_ptr<Variable> variable) noexcept;
45
45
46 /**
46 /**
47 * Deletes from the controller the variables passed in parameter.
47 * Deletes from the controller the variables passed in parameter.
48 * @param variables the variables to delete from the controller.
48 * @param variables the variables to delete from the controller.
49 * @sa deleteVariable()
49 * @sa deleteVariable()
50 */
50 */
51 void deleteVariables(const QVector<std::shared_ptr<Variable> > &variables) noexcept;
51 void deleteVariables(const QVector<std::shared_ptr<Variable> > &variables) noexcept;
52
52
53 signals:
53 signals:
54 /// Signal emitted when a variable is about to be deleted from the controller
54 /// Signal emitted when a variable is about to be deleted from the controller
55 void variableAboutToBeDeleted(std::shared_ptr<Variable> variable);
55 void variableAboutToBeDeleted(std::shared_ptr<Variable> variable);
56
56
57 public slots:
57 public slots:
58 /// Request the data loading of the variable whithin dateTime
58 /// Request the data loading of the variable whithin dateTime
59 void onRequestDataLoading(std::shared_ptr<Variable> variable, const SqpDateTime &dateTime);
59 void onRequestDataLoading(std::shared_ptr<Variable> variable, const SqpDateTime &dateTime);
60 /**
60 /**
61 * Creates a new variable and adds it to the model
61 * Creates a new variable and adds it to the model
62 * @param name the name of the new variable
62 * @param name the name of the new variable
63 * @param provider the data provider for the new variable
63 * @param provider the data provider for the new variable
64 */
64 */
65 void createVariable(const QString &name, std::shared_ptr<IDataProvider> provider) noexcept;
65 void createVariable(const QString &name, std::shared_ptr<IDataProvider> provider) noexcept;
66
66
67 /// Update the temporal parameters of every selected variable to dateTime
67 /// Update the temporal parameters of every selected variable to dateTime
68 void onDateTimeOnSelection(const SqpDateTime &dateTime);
68 void onDateTimeOnSelection(const SqpDateTime &dateTime);
69
69
70
71 void onVariableRetrieveDataInProgress(QUuid identifier, double progress);
72
70 void initialize();
73 void initialize();
71 void finalize();
74 void finalize();
72
75
73 private:
76 private:
74 void waitForFinish();
77 void waitForFinish();
75
78
76 class VariableControllerPrivate;
79 class VariableControllerPrivate;
77 spimpl::unique_impl_ptr<VariableControllerPrivate> impl;
80 spimpl::unique_impl_ptr<VariableControllerPrivate> impl;
78 };
81 };
79
82
80 #endif // SCIQLOP_VARIABLECONTROLLER_H
83 #endif // SCIQLOP_VARIABLECONTROLLER_H
@@ -1,63 +1,70
1 #ifndef SCIQLOP_VARIABLEMODEL_H
1 #ifndef SCIQLOP_VARIABLEMODEL_H
2 #define SCIQLOP_VARIABLEMODEL_H
2 #define SCIQLOP_VARIABLEMODEL_H
3
3
4
4
5 #include <Data/SqpDateTime.h>
5 #include <Data/SqpDateTime.h>
6
6
7 #include <QAbstractTableModel>
7 #include <QAbstractTableModel>
8 #include <QLoggingCategory>
8 #include <QLoggingCategory>
9
9
10 #include <Common/MetaTypes.h>
10 #include <Common/MetaTypes.h>
11 #include <Common/spimpl.h>
11 #include <Common/spimpl.h>
12
12
13 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableModel)
13 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableModel)
14
14
15 enum VariableRoles { ProgressRole = Qt::UserRole };
16
17
15 class IDataSeries;
18 class IDataSeries;
16 class Variable;
19 class Variable;
17
20
18 /**
21 /**
19 * @brief The VariableModel class aims to hold the variables that have been created in SciQlop
22 * @brief The VariableModel class aims to hold the variables that have been created in SciQlop
20 */
23 */
21 class VariableModel : public QAbstractTableModel {
24 class VariableModel : public QAbstractTableModel {
22 public:
25 public:
23 explicit VariableModel(QObject *parent = nullptr);
26 explicit VariableModel(QObject *parent = nullptr);
24
27
25 /**
28 /**
26 * Creates a new variable in the model
29 * Creates a new variable in the model
27 * @param name the name of the new variable
30 * @param name the name of the new variable
28 * @param dateTime the dateTime of the new variable
31 * @param dateTime the dateTime of the new variable
29 * @return the pointer to the new variable
32 * @return the pointer to the new variable
30 */
33 */
31 std::shared_ptr<Variable> createVariable(const QString &name,
34 std::shared_ptr<Variable> createVariable(const QString &name,
32 const SqpDateTime &dateTime) noexcept;
35 const SqpDateTime &dateTime) noexcept;
33
36
34 /**
37 /**
35 * Deletes a variable from the model, if it exists
38 * Deletes a variable from the model, if it exists
36 * @param variable the variable to delete
39 * @param variable the variable to delete
37 */
40 */
38 void deleteVariable(std::shared_ptr<Variable> variable) noexcept;
41 void deleteVariable(std::shared_ptr<Variable> variable) noexcept;
39
42
43
40 std::shared_ptr<Variable> variable(int index) const;
44 std::shared_ptr<Variable> variable(int index) const;
41
45
46 void setDataProgress(std::shared_ptr<Variable> variable, double progress);
47
42 // /////////////////////////// //
48 // /////////////////////////// //
43 // QAbstractTableModel methods //
49 // QAbstractTableModel methods //
44 // /////////////////////////// //
50 // /////////////////////////// //
51
45 virtual int columnCount(const QModelIndex &parent = QModelIndex{}) const override;
52 virtual int columnCount(const QModelIndex &parent = QModelIndex{}) const override;
46 virtual int rowCount(const QModelIndex &parent = QModelIndex{}) const override;
53 virtual int rowCount(const QModelIndex &parent = QModelIndex{}) const override;
47 virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
54 virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
48 virtual QVariant headerData(int section, Qt::Orientation orientation,
55 virtual QVariant headerData(int section, Qt::Orientation orientation,
49 int role = Qt::DisplayRole) const override;
56 int role = Qt::DisplayRole) const override;
50
57
51 private:
58 private:
52 class VariableModelPrivate;
59 class VariableModelPrivate;
53 spimpl::unique_impl_ptr<VariableModelPrivate> impl;
60 spimpl::unique_impl_ptr<VariableModelPrivate> impl;
54
61
55 private slots:
62 private slots:
56 /// Slot called when data of a variable has been updated
63 /// Slot called when data of a variable has been updated
57 void onVariableUpdated() noexcept;
64 void onVariableUpdated() noexcept;
58 };
65 };
59
66
60 // Registers QVector<int> metatype so it can be used in VariableModel::dataChanged() signal
67 // Registers QVector<int> metatype so it can be used in VariableModel::dataChanged() signal
61 SCIQLOP_REGISTER_META_TYPE(QVECTOR_INT_REGISTRY, QVector<int>)
68 SCIQLOP_REGISTER_META_TYPE(QVECTOR_INT_REGISTRY, QVector<int>)
62
69
63 #endif // SCIQLOP_VARIABLEMODEL_H
70 #endif // SCIQLOP_VARIABLEMODEL_H
@@ -1,88 +1,87
1 #include "Network/NetworkController.h"
1 #include "Network/NetworkController.h"
2
2
3 #include <QMutex>
3 #include <QMutex>
4 #include <QNetworkAccessManager>
4 #include <QNetworkAccessManager>
5 #include <QNetworkReply>
5 #include <QNetworkReply>
6 #include <QNetworkRequest>
6 #include <QNetworkRequest>
7 #include <QThread>
7 #include <QThread>
8
8
9 #include <unordered_map>
9 #include <unordered_map>
10
10
11 Q_LOGGING_CATEGORY(LOG_NetworkController, "NetworkController")
11 Q_LOGGING_CATEGORY(LOG_NetworkController, "NetworkController")
12
12
13 struct NetworkController::NetworkControllerPrivate {
13 struct NetworkController::NetworkControllerPrivate {
14 explicit NetworkControllerPrivate(NetworkController *parent) : m_WorkingMutex{} {}
14 explicit NetworkControllerPrivate(NetworkController *parent) : m_WorkingMutex{} {}
15 QMutex m_WorkingMutex;
15 QMutex m_WorkingMutex;
16
16
17 std::unordered_map<QNetworkReply *, QUuid> m_NetworkReplyToVariableId;
17 std::unordered_map<QNetworkReply *, QUuid> m_NetworkReplyToVariableId;
18 std::unique_ptr<QNetworkAccessManager> m_AccessManager{nullptr};
18 std::unique_ptr<QNetworkAccessManager> m_AccessManager{nullptr};
19 };
19 };
20
20
21 NetworkController::NetworkController(QObject *parent)
21 NetworkController::NetworkController(QObject *parent)
22 : QObject(parent), impl{spimpl::make_unique_impl<NetworkControllerPrivate>(this)}
22 : QObject(parent), impl{spimpl::make_unique_impl<NetworkControllerPrivate>(this)}
23 {
23 {
24 }
24 }
25
25
26 void NetworkController::onProcessRequested(const QNetworkRequest &request, QUuid identifier,
26 void NetworkController::onProcessRequested(const QNetworkRequest &request, QUuid identifier,
27 std::function<void(QNetworkReply *, QUuid)> callback)
27 std::function<void(QNetworkReply *, QUuid)> callback)
28 {
28 {
29 qCDebug(LOG_NetworkController()) << tr("NetworkController registered")
29 qCInfo(LOG_NetworkController()) << tr("NetworkController registered")
30 << QThread::currentThread();
30 << QThread::currentThread();
31 auto reply = impl->m_AccessManager->get(request);
31 auto reply = impl->m_AccessManager->get(request);
32
32
33 // Store the couple reply id
33 // Store the couple reply id
34 impl->m_NetworkReplyToVariableId[reply] = identifier;
34 impl->m_NetworkReplyToVariableId[reply] = identifier;
35
35
36 auto onReplyFinished = [reply, this, identifier, callback]() {
36 auto onReplyFinished = [reply, this, identifier, callback]() {
37
37
38 qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyFinished")
38 qCInfo(LOG_NetworkController()) << tr("NetworkController onReplyFinished")
39 << QThread::currentThread();
39 << QThread::currentThread();
40 auto it = impl->m_NetworkReplyToVariableId.find(reply);
40 auto it = impl->m_NetworkReplyToVariableId.find(reply);
41 if (it != impl->m_NetworkReplyToVariableId.cend()) {
41 if (it != impl->m_NetworkReplyToVariableId.cend()) {
42 callback(reply, identifier);
42 callback(reply, identifier);
43 }
43 }
44 };
44 };
45
45
46 auto onReplyDownloadProgress = [reply, this]() {
46 auto onReplyProgress = [reply, this](qint64 bytesRead, qint64 totalBytes) {
47
47
48 qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyDownloadProgress")
48 double progress = (bytesRead * 100.0) / totalBytes;
49 << QThread::currentThread();
50 auto it = impl->m_NetworkReplyToVariableId.find(reply);
49 auto it = impl->m_NetworkReplyToVariableId.find(reply);
51 if (it != impl->m_NetworkReplyToVariableId.cend()) {
50 if (it != impl->m_NetworkReplyToVariableId.cend()) {
52 emit this->replyDownloadProgress(it->second);
51 emit this->replyDownloadProgress(it->second, progress);
53 }
52 }
54 };
53 };
55
54
56
55
57 connect(reply, &QNetworkReply::finished, this, onReplyFinished);
56 connect(reply, &QNetworkReply::finished, this, onReplyFinished);
58 connect(reply, &QNetworkReply::downloadProgress, this, onReplyDownloadProgress);
57 connect(reply, &QNetworkReply::downloadProgress, this, onReplyProgress);
59 }
58 }
60
59
61 void NetworkController::initialize()
60 void NetworkController::initialize()
62 {
61 {
63 qCDebug(LOG_NetworkController()) << tr("NetworkController init") << QThread::currentThread();
62 qCDebug(LOG_NetworkController()) << tr("NetworkController init") << QThread::currentThread();
64 impl->m_WorkingMutex.lock();
63 impl->m_WorkingMutex.lock();
65 impl->m_AccessManager = std::make_unique<QNetworkAccessManager>();
64 impl->m_AccessManager = std::make_unique<QNetworkAccessManager>();
66 qCDebug(LOG_NetworkController()) << tr("NetworkController init END");
65 qCDebug(LOG_NetworkController()) << tr("NetworkController init END");
67 }
66 }
68
67
69 void NetworkController::finalize()
68 void NetworkController::finalize()
70 {
69 {
71 impl->m_WorkingMutex.unlock();
70 impl->m_WorkingMutex.unlock();
72 }
71 }
73
72
74 void NetworkController::onReplyCanceled(QUuid identifier)
73 void NetworkController::onReplyCanceled(QUuid identifier)
75 {
74 {
76 auto findReply = [identifier](const auto &entry) { return identifier == entry.second; };
75 auto findReply = [identifier](const auto &entry) { return identifier == entry.second; };
77
76
78 auto end = impl->m_NetworkReplyToVariableId.cend();
77 auto end = impl->m_NetworkReplyToVariableId.cend();
79 auto it = std::find_if(impl->m_NetworkReplyToVariableId.cbegin(), end, findReply);
78 auto it = std::find_if(impl->m_NetworkReplyToVariableId.cbegin(), end, findReply);
80 if (it != end) {
79 if (it != end) {
81 it->first->abort();
80 it->first->abort();
82 }
81 }
83 }
82 }
84
83
85 void NetworkController::waitForFinish()
84 void NetworkController::waitForFinish()
86 {
85 {
87 QMutexLocker locker{&impl->m_WorkingMutex};
86 QMutexLocker locker{&impl->m_WorkingMutex};
88 }
87 }
@@ -1,205 +1,216
1 #include <Variable/Variable.h>
1 #include <Variable/Variable.h>
2 #include <Variable/VariableCacheController.h>
2 #include <Variable/VariableCacheController.h>
3 #include <Variable/VariableController.h>
3 #include <Variable/VariableController.h>
4 #include <Variable/VariableModel.h>
4 #include <Variable/VariableModel.h>
5
5
6 #include <Data/DataProviderParameters.h>
6 #include <Data/DataProviderParameters.h>
7 #include <Data/IDataProvider.h>
7 #include <Data/IDataProvider.h>
8 #include <Data/IDataSeries.h>
8 #include <Data/IDataSeries.h>
9 #include <Time/TimeController.h>
9 #include <Time/TimeController.h>
10
10
11 #include <QDateTime>
11 #include <QDateTime>
12 #include <QMutex>
12 #include <QMutex>
13 #include <QThread>
13 #include <QThread>
14 #include <QUuid>
14 #include <QUuid>
15 #include <QtCore/QItemSelectionModel>
15 #include <QtCore/QItemSelectionModel>
16
16
17 #include <unordered_map>
17 #include <unordered_map>
18
18
19 Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController")
19 Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController")
20
20
21 struct VariableController::VariableControllerPrivate {
21 struct VariableController::VariableControllerPrivate {
22 explicit VariableControllerPrivate(VariableController *parent)
22 explicit VariableControllerPrivate(VariableController *parent)
23 : m_WorkingMutex{},
23 : m_WorkingMutex{},
24 m_VariableModel{new VariableModel{parent}},
24 m_VariableModel{new VariableModel{parent}},
25 m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}},
25 m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}},
26 m_VariableCacheController{std::make_unique<VariableCacheController>()}
26 m_VariableCacheController{std::make_unique<VariableCacheController>()}
27 {
27 {
28 }
28 }
29
29
30 QMutex m_WorkingMutex;
30 QMutex m_WorkingMutex;
31 /// Variable model. The VariableController has the ownership
31 /// Variable model. The VariableController has the ownership
32 VariableModel *m_VariableModel;
32 VariableModel *m_VariableModel;
33 QItemSelectionModel *m_VariableSelectionModel;
33 QItemSelectionModel *m_VariableSelectionModel;
34
34
35
35
36 TimeController *m_TimeController{nullptr};
36 TimeController *m_TimeController{nullptr};
37 std::unique_ptr<VariableCacheController> m_VariableCacheController;
37 std::unique_ptr<VariableCacheController> m_VariableCacheController;
38
38
39 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
39 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
40 m_VariableToProviderMap;
40 m_VariableToProviderMap;
41 std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToIdentifier;
41 std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToIdentifier;
42 };
42 };
43
43
44 VariableController::VariableController(QObject *parent)
44 VariableController::VariableController(QObject *parent)
45 : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)}
45 : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)}
46 {
46 {
47 qCDebug(LOG_VariableController()) << tr("VariableController construction")
47 qCDebug(LOG_VariableController()) << tr("VariableController construction")
48 << QThread::currentThread();
48 << QThread::currentThread();
49 }
49 }
50
50
51 VariableController::~VariableController()
51 VariableController::~VariableController()
52 {
52 {
53 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
53 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
54 << QThread::currentThread();
54 << QThread::currentThread();
55 this->waitForFinish();
55 this->waitForFinish();
56 }
56 }
57
57
58 VariableModel *VariableController::variableModel() noexcept
58 VariableModel *VariableController::variableModel() noexcept
59 {
59 {
60 return impl->m_VariableModel;
60 return impl->m_VariableModel;
61 }
61 }
62
62
63 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
63 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
64 {
64 {
65 return impl->m_VariableSelectionModel;
65 return impl->m_VariableSelectionModel;
66 }
66 }
67
67
68 void VariableController::setTimeController(TimeController *timeController) noexcept
68 void VariableController::setTimeController(TimeController *timeController) noexcept
69 {
69 {
70 impl->m_TimeController = timeController;
70 impl->m_TimeController = timeController;
71 }
71 }
72
72
73 void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept
73 void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept
74 {
74 {
75 if (!variable) {
75 if (!variable) {
76 qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null";
76 qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null";
77 return;
77 return;
78 }
78 }
79
79
80 // Spreads in SciQlop that the variable will be deleted, so that potential receivers can
80 // Spreads in SciQlop that the variable will be deleted, so that potential receivers can
81 // make some treatments before the deletion
81 // make some treatments before the deletion
82 emit variableAboutToBeDeleted(variable);
82 emit variableAboutToBeDeleted(variable);
83
83
84 // Deletes provider
84 // Deletes provider
85 auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable);
85 auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable);
86 qCDebug(LOG_VariableController())
86 qCDebug(LOG_VariableController())
87 << tr("Number of providers deleted for variable %1: %2")
87 << tr("Number of providers deleted for variable %1: %2")
88 .arg(variable->name(), QString::number(nbProvidersDeleted));
88 .arg(variable->name(), QString::number(nbProvidersDeleted));
89
89
90 // Clears cache
90 // Clears cache
91 impl->m_VariableCacheController->clear(variable);
91 impl->m_VariableCacheController->clear(variable);
92
92
93 // Deletes from model
93 // Deletes from model
94 impl->m_VariableModel->deleteVariable(variable);
94 impl->m_VariableModel->deleteVariable(variable);
95 }
95 }
96
96
97 void VariableController::deleteVariables(
97 void VariableController::deleteVariables(
98 const QVector<std::shared_ptr<Variable> > &variables) noexcept
98 const QVector<std::shared_ptr<Variable> > &variables) noexcept
99 {
99 {
100 for (auto variable : qAsConst(variables)) {
100 for (auto variable : qAsConst(variables)) {
101 deleteVariable(variable);
101 deleteVariable(variable);
102 }
102 }
103 }
103 }
104
104
105 void VariableController::createVariable(const QString &name,
105 void VariableController::createVariable(const QString &name,
106 std::shared_ptr<IDataProvider> provider) noexcept
106 std::shared_ptr<IDataProvider> provider) noexcept
107 {
107 {
108
108
109 if (!impl->m_TimeController) {
109 if (!impl->m_TimeController) {
110 qCCritical(LOG_VariableController())
110 qCCritical(LOG_VariableController())
111 << tr("Impossible to create variable: The time controller is null");
111 << tr("Impossible to create variable: The time controller is null");
112 return;
112 return;
113 }
113 }
114
114
115
115
116 /// @todo : for the moment :
116 /// @todo : for the moment :
117 /// - the provider is only used to retrieve data from the variable for its initialization, but
117 /// - the provider is only used to retrieve data from the variable for its initialization, but
118 /// it will be retained later
118 /// it will be retained later
119 /// - default data are generated for the variable, without taking into account the timerange set
119 /// - default data are generated for the variable, without taking into account the timerange set
120 /// in sciqlop
120 /// in sciqlop
121 auto dateTime = impl->m_TimeController->dateTime();
121 auto dateTime = impl->m_TimeController->dateTime();
122 if (auto newVariable = impl->m_VariableModel->createVariable(name, dateTime)) {
122 if (auto newVariable = impl->m_VariableModel->createVariable(name, dateTime)) {
123 auto identifier = QUuid::createUuid();
123 auto identifier = QUuid::createUuid();
124
124
125 // store the provider
125 // store the provider
126 impl->m_VariableToProviderMap[newVariable] = provider;
126 impl->m_VariableToProviderMap[newVariable] = provider;
127 impl->m_VariableToIdentifier[newVariable] = identifier;
127 impl->m_VariableToIdentifier[newVariable] = identifier;
128
128
129 auto addDateTimeAcquired = [ this, varW = std::weak_ptr<Variable>{newVariable} ](
129 auto addDateTimeAcquired = [ this, varW = std::weak_ptr<Variable>{newVariable} ](
130 QUuid identifier, auto dataSeriesAcquired, auto dateTimeToPutInCache)
130 QUuid identifier, auto dataSeriesAcquired, auto dateTimeToPutInCache)
131 {
131 {
132 if (auto variable = varW.lock()) {
132 if (auto variable = varW.lock()) {
133 auto varIdentifier = impl->m_VariableToIdentifier.at(variable);
133 auto varIdentifier = impl->m_VariableToIdentifier.at(variable);
134 if (varIdentifier == identifier) {
134 if (varIdentifier == identifier) {
135 impl->m_VariableCacheController->addDateTime(variable, dateTimeToPutInCache);
135 impl->m_VariableCacheController->addDateTime(variable, dateTimeToPutInCache);
136 variable->setDataSeries(dataSeriesAcquired);
136 variable->setDataSeries(dataSeriesAcquired);
137 }
137 }
138 }
138 }
139 };
139 };
140
140
141 connect(provider.get(), &IDataProvider::dataProvided, addDateTimeAcquired);
141 connect(provider.get(), &IDataProvider::dataProvided, addDateTimeAcquired);
142 this->onRequestDataLoading(newVariable, dateTime);
142 this->onRequestDataLoading(newVariable, dateTime);
143 }
143 }
144 }
144 }
145
145
146 void VariableController::onDateTimeOnSelection(const SqpDateTime &dateTime)
146 void VariableController::onDateTimeOnSelection(const SqpDateTime &dateTime)
147 {
147 {
148 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
148 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
149 << QThread::currentThread()->objectName();
149 << QThread::currentThread()->objectName();
150 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
150 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
151
151
152 for (const auto &selectedRow : qAsConst(selectedRows)) {
152 for (const auto &selectedRow : qAsConst(selectedRows)) {
153 if (auto selectedVariable = impl->m_VariableModel->variable(selectedRow.row())) {
153 if (auto selectedVariable = impl->m_VariableModel->variable(selectedRow.row())) {
154 selectedVariable->setDateTime(dateTime);
154 selectedVariable->setDateTime(dateTime);
155 this->onRequestDataLoading(selectedVariable, dateTime);
155 this->onRequestDataLoading(selectedVariable, dateTime);
156 }
156 }
157 }
157 }
158 }
158 }
159
159
160 void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress)
161 {
162 auto findReply = [identifier](const auto &entry) { return identifier == entry.second; };
163
164 auto end = impl->m_VariableToIdentifier.cend();
165 auto it = std::find_if(impl->m_VariableToIdentifier.cbegin(), end, findReply);
166 if (it != end) {
167 impl->m_VariableModel->setDataProgress(it->first, progress);
168 }
169 }
170
160
171
161 void VariableController::onRequestDataLoading(std::shared_ptr<Variable> variable,
172 void VariableController::onRequestDataLoading(std::shared_ptr<Variable> variable,
162 const SqpDateTime &dateTime)
173 const SqpDateTime &dateTime)
163 {
174 {
164 qCDebug(LOG_VariableController()) << "VariableController::onRequestDataLoading"
175 qCDebug(LOG_VariableController()) << "VariableController::onRequestDataLoading"
165 << QThread::currentThread()->objectName();
176 << QThread::currentThread()->objectName();
166 // we want to load data of the variable for the dateTime.
177 // we want to load data of the variable for the dateTime.
167 // First we check if the cache contains some of them.
178 // First we check if the cache contains some of them.
168 // For the other, we ask the provider to give them.
179 // For the other, we ask the provider to give them.
169 if (variable) {
180 if (variable) {
170
181
171 auto dateTimeListNotInCache
182 auto dateTimeListNotInCache
172 = impl->m_VariableCacheController->provideNotInCacheDateTimeList(variable, dateTime);
183 = impl->m_VariableCacheController->provideNotInCacheDateTimeList(variable, dateTime);
173
184
174 if (!dateTimeListNotInCache.empty()) {
185 if (!dateTimeListNotInCache.empty()) {
175 // Ask the provider for each data on the dateTimeListNotInCache
186 // Ask the provider for each data on the dateTimeListNotInCache
176 auto identifier = impl->m_VariableToIdentifier.at(variable);
187 auto identifier = impl->m_VariableToIdentifier.at(variable);
177 impl->m_VariableToProviderMap.at(variable)->requestDataLoading(
188 impl->m_VariableToProviderMap.at(variable)->requestDataLoading(
178 identifier, std::move(dateTimeListNotInCache));
189 identifier, std::move(dateTimeListNotInCache));
179 }
190 }
180 else {
191 else {
181 emit variable->updated();
192 emit variable->updated();
182 }
193 }
183 }
194 }
184 else {
195 else {
185 qCCritical(LOG_VariableController()) << tr("Impossible to load data of a variable null");
196 qCCritical(LOG_VariableController()) << tr("Impossible to load data of a variable null");
186 }
197 }
187 }
198 }
188
199
189
200
190 void VariableController::initialize()
201 void VariableController::initialize()
191 {
202 {
192 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
203 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
193 impl->m_WorkingMutex.lock();
204 impl->m_WorkingMutex.lock();
194 qCDebug(LOG_VariableController()) << tr("VariableController init END");
205 qCDebug(LOG_VariableController()) << tr("VariableController init END");
195 }
206 }
196
207
197 void VariableController::finalize()
208 void VariableController::finalize()
198 {
209 {
199 impl->m_WorkingMutex.unlock();
210 impl->m_WorkingMutex.unlock();
200 }
211 }
201
212
202 void VariableController::waitForFinish()
213 void VariableController::waitForFinish()
203 {
214 {
204 QMutexLocker locker{&impl->m_WorkingMutex};
215 QMutexLocker locker{&impl->m_WorkingMutex};
205 }
216 }
@@ -1,200 +1,236
1 #include <Variable/Variable.h>
1 #include <Variable/Variable.h>
2 #include <Variable/VariableModel.h>
2 #include <Variable/VariableModel.h>
3
3
4 #include <Data/IDataSeries.h>
4 #include <Data/IDataSeries.h>
5
5
6 #include <QDateTime>
6 #include <QDateTime>
7 #include <QSize>
7 #include <QSize>
8 #include <unordered_map>
8
9
9 Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel")
10 Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel")
10
11
11 namespace {
12 namespace {
12
13
13 // Column indexes
14 // Column indexes
14 const auto NAME_COLUMN = 0;
15 const auto NAME_COLUMN = 0;
15 const auto TSTART_COLUMN = 1;
16 const auto TSTART_COLUMN = 1;
16 const auto TEND_COLUMN = 2;
17 const auto TEND_COLUMN = 2;
17 const auto NB_COLUMNS = 3;
18 const auto NB_COLUMNS = 3;
18
19
19 // Column properties
20 // Column properties
20 const auto DEFAULT_HEIGHT = 25;
21 const auto DEFAULT_HEIGHT = 25;
21 const auto DEFAULT_WIDTH = 100;
22 const auto DEFAULT_WIDTH = 100;
22
23
23 struct ColumnProperties {
24 struct ColumnProperties {
24 ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH,
25 ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH,
25 int height = DEFAULT_HEIGHT)
26 int height = DEFAULT_HEIGHT)
26 : m_Name{name}, m_Width{width}, m_Height{height}
27 : m_Name{name}, m_Width{width}, m_Height{height}
27 {
28 {
28 }
29 }
29
30
30 QString m_Name;
31 QString m_Name;
31 int m_Width;
32 int m_Width;
32 int m_Height;
33 int m_Height;
33 };
34 };
34
35
35 const auto COLUMN_PROPERTIES
36 const auto COLUMN_PROPERTIES
36 = QHash<int, ColumnProperties>{{NAME_COLUMN, {QObject::tr("Name")}},
37 = QHash<int, ColumnProperties>{{NAME_COLUMN, {QObject::tr("Name")}},
37 {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
38 {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
38 {TEND_COLUMN, {QObject::tr("tEnd"), 180}}};
39 {TEND_COLUMN, {QObject::tr("tEnd"), 180}}};
39
40
40 /// Format for datetimes
41 /// Format for datetimes
41 const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz");
42 const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz");
42
43
44
43 } // namespace
45 } // namespace
44
46
45 struct VariableModel::VariableModelPrivate {
47 struct VariableModel::VariableModelPrivate {
46 /// Variables created in SciQlop
48 /// Variables created in SciQlop
47 std::vector<std::shared_ptr<Variable> > m_Variables;
49 std::vector<std::shared_ptr<Variable> > m_Variables;
50 std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress;
51
52
53 /// Return the row index of the variable. -1 if it's not found
54 int indexOfVariable(Variable *variable) const noexcept;
48 };
55 };
49
56
50 VariableModel::VariableModel(QObject *parent)
57 VariableModel::VariableModel(QObject *parent)
51 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
58 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
52 {
59 {
53 }
60 }
54
61
55 std::shared_ptr<Variable> VariableModel::createVariable(const QString &name,
62 std::shared_ptr<Variable> VariableModel::createVariable(const QString &name,
56 const SqpDateTime &dateTime) noexcept
63 const SqpDateTime &dateTime) noexcept
57 {
64 {
58 auto insertIndex = rowCount();
65 auto insertIndex = rowCount();
59 beginInsertRows({}, insertIndex, insertIndex);
66 beginInsertRows({}, insertIndex, insertIndex);
60
67
61 /// @todo For the moment, the other data of the variable is initialized with default values
68 /// @todo For the moment, the other data of the variable is initialized with default values
62 auto variable = std::make_shared<Variable>(name, QStringLiteral("unit"),
69 auto variable = std::make_shared<Variable>(name, QStringLiteral("unit"),
63 QStringLiteral("mission"), dateTime);
70 QStringLiteral("mission"), dateTime);
64
71
65 impl->m_Variables.push_back(variable);
72 impl->m_Variables.push_back(variable);
66 connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated);
73 connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated);
67
74
68 endInsertRows();
75 endInsertRows();
69
76
70 return variable;
77 return variable;
71 }
78 }
72
79
73 void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept
80 void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept
74 {
81 {
75 if (!variable) {
82 if (!variable) {
76 qCCritical(LOG_Variable()) << "Can't delete a null variable from the model";
83 qCCritical(LOG_Variable()) << "Can't delete a null variable from the model";
77 return;
84 return;
78 }
85 }
79
86
80 // Finds variable in the model
87 // Finds variable in the model
81 auto begin = impl->m_Variables.cbegin();
88 auto begin = impl->m_Variables.cbegin();
82 auto end = impl->m_Variables.cend();
89 auto end = impl->m_Variables.cend();
83 auto it = std::find(begin, end, variable);
90 auto it = std::find(begin, end, variable);
84 if (it != end) {
91 if (it != end) {
85 auto removeIndex = std::distance(begin, it);
92 auto removeIndex = std::distance(begin, it);
86
93
87 // Deletes variable
94 // Deletes variable
88 beginRemoveRows({}, removeIndex, removeIndex);
95 beginRemoveRows({}, removeIndex, removeIndex);
89 impl->m_Variables.erase(it);
96 impl->m_Variables.erase(it);
90 endRemoveRows();
97 endRemoveRows();
91 }
98 }
92 else {
99 else {
93 qCritical(LOG_VariableModel())
100 qCritical(LOG_VariableModel())
94 << tr("Can't delete variable %1 from the model: the variable is not in the model")
101 << tr("Can't delete variable %1 from the model: the variable is not in the model")
95 .arg(variable->name());
102 .arg(variable->name());
96 }
103 }
97 }
104 }
98
105
106
99 std::shared_ptr<Variable> VariableModel::variable(int index) const
107 std::shared_ptr<Variable> VariableModel::variable(int index) const
100 {
108 {
101 return (index >= 0 && index < impl->m_Variables.size()) ? impl->m_Variables[index] : nullptr;
109 return (index >= 0 && index < impl->m_Variables.size()) ? impl->m_Variables[index] : nullptr;
102 }
110 }
103
111
112 void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress)
113 {
114
115 impl->m_VariableToProgress[variable] = progress;
116 auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN);
117
118 emit dataChanged(modelIndex, modelIndex);
119 }
120
104 int VariableModel::columnCount(const QModelIndex &parent) const
121 int VariableModel::columnCount(const QModelIndex &parent) const
105 {
122 {
106 Q_UNUSED(parent);
123 Q_UNUSED(parent);
107
124
108 return NB_COLUMNS;
125 return NB_COLUMNS;
109 }
126 }
110
127
111 int VariableModel::rowCount(const QModelIndex &parent) const
128 int VariableModel::rowCount(const QModelIndex &parent) const
112 {
129 {
113 Q_UNUSED(parent);
130 Q_UNUSED(parent);
114
131
115 return impl->m_Variables.size();
132 return impl->m_Variables.size();
116 }
133 }
117
134
118 QVariant VariableModel::data(const QModelIndex &index, int role) const
135 QVariant VariableModel::data(const QModelIndex &index, int role) const
119 {
136 {
120 if (!index.isValid()) {
137 if (!index.isValid()) {
121 return QVariant{};
138 return QVariant{};
122 }
139 }
123
140
124 if (index.row() < 0 || index.row() >= rowCount()) {
141 if (index.row() < 0 || index.row() >= rowCount()) {
125 return QVariant{};
142 return QVariant{};
126 }
143 }
127
144
128 if (role == Qt::DisplayRole) {
145 if (role == Qt::DisplayRole) {
129 if (auto variable = impl->m_Variables.at(index.row()).get()) {
146 if (auto variable = impl->m_Variables.at(index.row()).get()) {
130 /// Lambda function that builds the variant to return for a time value
147 /// Lambda function that builds the variant to return for a time value
131 auto dateTimeVariant = [](double time) {
148 auto dateTimeVariant = [](double time) {
132 auto dateTime = QDateTime::fromMSecsSinceEpoch(time * 1000.);
149 auto dateTime = QDateTime::fromMSecsSinceEpoch(time * 1000.);
133 return dateTime.toString(DATETIME_FORMAT);
150 return dateTime.toString(DATETIME_FORMAT);
134 };
151 };
135
152
136 switch (index.column()) {
153 switch (index.column()) {
137 case NAME_COLUMN:
154 case NAME_COLUMN:
138 return variable->name();
155 return variable->name();
139 case TSTART_COLUMN:
156 case TSTART_COLUMN:
140 return dateTimeVariant(variable->dateTime().m_TStart);
157 return dateTimeVariant(variable->dateTime().m_TStart);
141 case TEND_COLUMN:
158 case TEND_COLUMN:
142 return dateTimeVariant(variable->dateTime().m_TEnd);
159 return dateTimeVariant(variable->dateTime().m_TEnd);
143 default:
160 default:
144 // No action
161 // No action
145 break;
162 break;
146 }
163 }
147
164
148 qWarning(LOG_VariableModel())
165 qWarning(LOG_VariableModel())
149 << tr("Can't get data (unknown column %1)").arg(index.column());
166 << tr("Can't get data (unknown column %1)").arg(index.column());
150 }
167 }
151 else {
168 else {
152 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
169 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
153 }
170 }
154 }
171 }
172 else if (role == VariableRoles::ProgressRole) {
173 if (auto variable = impl->m_Variables.at(index.row())) {
174
175 auto it = impl->m_VariableToProgress.find(variable);
176 if (it != impl->m_VariableToProgress.cend()) {
177 return it->second;
178 }
179 }
180 }
155
181
156 return QVariant{};
182 return QVariant{};
157 }
183 }
158
184
159 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
185 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
160 {
186 {
161 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
187 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
162 return QVariant{};
188 return QVariant{};
163 }
189 }
164
190
165 if (orientation == Qt::Horizontal) {
191 if (orientation == Qt::Horizontal) {
166 auto propertiesIt = COLUMN_PROPERTIES.find(section);
192 auto propertiesIt = COLUMN_PROPERTIES.find(section);
167 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
193 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
168 // Role is either DisplayRole or SizeHintRole
194 // Role is either DisplayRole or SizeHintRole
169 return (role == Qt::DisplayRole)
195 return (role == Qt::DisplayRole)
170 ? QVariant{propertiesIt->m_Name}
196 ? QVariant{propertiesIt->m_Name}
171 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
197 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
172 }
198 }
173 else {
199 else {
174 qWarning(LOG_VariableModel())
200 qWarning(LOG_VariableModel())
175 << tr("Can't get header data (unknown column %1)").arg(section);
201 << tr("Can't get header data (unknown column %1)").arg(section);
176 }
202 }
177 }
203 }
178
204
179 return QVariant{};
205 return QVariant{};
180 }
206 }
181
207
182 void VariableModel::onVariableUpdated() noexcept
208 void VariableModel::onVariableUpdated() noexcept
183 {
209 {
184 // Finds variable that has been updated in the model
210 // Finds variable that has been updated in the model
185 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
211 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
186 auto begin = std::cbegin(impl->m_Variables);
212 auto updatedVariableIndex = impl->indexOfVariable(updatedVariable);
187 auto end = std::cend(impl->m_Variables);
213
188 auto it = std::find_if(begin, end, [updatedVariable](const auto &variable) {
214 if (updatedVariableIndex > -1) {
189 return variable.get() == updatedVariable;
215 emit dataChanged(createIndex(updatedVariableIndex, 0),
190 });
216 createIndex(updatedVariableIndex, columnCount() - 1));
217 }
218 }
219 }
220
221 int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept
222 {
223 auto begin = std::cbegin(m_Variables);
224 auto end = std::cend(m_Variables);
225 auto it
226 = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; });
191
227
192 if (it != end) {
228 if (it != end) {
193 // Gets the index of the variable in the model: we assume here that views have the same
229 // Gets the index of the variable in the model: we assume here that views have the same
194 // order as the model
230 // order as the model
195 auto updateVariableIndex = std::distance(begin, it);
231 return std::distance(begin, it);
196 emit dataChanged(createIndex(updateVariableIndex, 0),
197 createIndex(updateVariableIndex, columnCount() - 1));
198 }
232 }
233 else {
234 return -1;
199 }
235 }
200 }
236 }
@@ -1,52 +1,56
1 #ifndef SCIQLOP_VARIABLEINSPECTORWIDGET_H
1 #ifndef SCIQLOP_VARIABLEINSPECTORWIDGET_H
2 #define SCIQLOP_VARIABLEINSPECTORWIDGET_H
2 #define SCIQLOP_VARIABLEINSPECTORWIDGET_H
3
3
4 #include <QLoggingCategory>
4 #include <QLoggingCategory>
5 #include <QMenu>
5 #include <QMenu>
6 #include <QWidget>
6 #include <QWidget>
7
7
8 #include <memory>
8 #include <memory>
9
9
10 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableInspectorWidget)
10 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableInspectorWidget)
11
11
12 class Variable;
12 class Variable;
13
13
14 class QProgressBarItemDelegate;
15
14 namespace Ui {
16 namespace Ui {
15 class VariableInspectorWidget;
17 class VariableInspectorWidget;
16 } // Ui
18 } // Ui
17
19
18 /**
20 /**
19 * @brief The VariableInspectorWidget class representes represents the variable inspector, from
21 * @brief The VariableInspectorWidget class representes represents the variable inspector, from
20 * which it is possible to view the loaded variables, handle them or trigger their display in
22 * which it is possible to view the loaded variables, handle them or trigger their display in
21 * visualization
23 * visualization
22 */
24 */
23 class VariableInspectorWidget : public QWidget {
25 class VariableInspectorWidget : public QWidget {
24 Q_OBJECT
26 Q_OBJECT
25
27
26 public:
28 public:
27 explicit VariableInspectorWidget(QWidget *parent = 0);
29 explicit VariableInspectorWidget(QWidget *parent = 0);
28 virtual ~VariableInspectorWidget();
30 virtual ~VariableInspectorWidget();
29
31
30 signals:
32 signals:
31 /**
33 /**
32 * Signal emitted before a menu concerning variables is displayed. It is used for other widgets
34 * Signal emitted before a menu concerning variables is displayed. It is used for other widgets
33 * to complete the menu.
35 * to complete the menu.
34 * @param tableMenu the menu to be completed
36 * @param tableMenu the menu to be completed
35 * @param variables the variables concerned by the menu
37 * @param variables the variables concerned by the menu
36 * @remarks To make the dynamic addition of menus work, the connections to this signal must be
38 * @remarks To make the dynamic addition of menus work, the connections to this signal must be
37 * in Qt :: DirectConnection
39 * in Qt :: DirectConnection
38 */
40 */
39 void tableMenuAboutToBeDisplayed(QMenu *tableMenu,
41 void tableMenuAboutToBeDisplayed(QMenu *tableMenu,
40 const QVector<std::shared_ptr<Variable> > &variables);
42 const QVector<std::shared_ptr<Variable> > &variables);
41
43
42 private:
44 private:
43 Ui::VariableInspectorWidget *ui;
45 Ui::VariableInspectorWidget *ui;
44
46
47 QProgressBarItemDelegate *m_ProgressBarItemDelegate;
48
45 private slots:
49 private slots:
46 /// Slot called when right clicking on an variable in the table (displays a menu)
50 /// Slot called when right clicking on an variable in the table (displays a menu)
47 void onTableMenuRequested(const QPoint &pos) noexcept;
51 void onTableMenuRequested(const QPoint &pos) noexcept;
48 /// Refreshes instantly the variable view
52 /// Refreshes instantly the variable view
49 void refresh() noexcept;
53 void refresh() noexcept;
50 };
54 };
51
55
52 #endif // SCIQLOP_VARIABLEINSPECTORWIDGET_H
56 #endif // SCIQLOP_VARIABLEINSPECTORWIDGET_H
@@ -1,140 +1,145
1 #include "SqpApplication.h"
1 #include "SqpApplication.h"
2
2
3 #include <Data/IDataProvider.h>
3 #include <Data/IDataProvider.h>
4 #include <DataSource/DataSourceController.h>
4 #include <DataSource/DataSourceController.h>
5 #include <Network/NetworkController.h>
5 #include <Network/NetworkController.h>
6 #include <QThread>
6 #include <QThread>
7 #include <Time/TimeController.h>
7 #include <Time/TimeController.h>
8 #include <Variable/Variable.h>
8 #include <Variable/Variable.h>
9 #include <Variable/VariableController.h>
9 #include <Variable/VariableController.h>
10 #include <Visualization/VisualizationController.h>
10 #include <Visualization/VisualizationController.h>
11
11
12 Q_LOGGING_CATEGORY(LOG_SqpApplication, "SqpApplication")
12 Q_LOGGING_CATEGORY(LOG_SqpApplication, "SqpApplication")
13
13
14 class SqpApplication::SqpApplicationPrivate {
14 class SqpApplication::SqpApplicationPrivate {
15 public:
15 public:
16 SqpApplicationPrivate()
16 SqpApplicationPrivate()
17 : m_DataSourceController{std::make_unique<DataSourceController>()},
17 : m_DataSourceController{std::make_unique<DataSourceController>()},
18 m_NetworkController{std::make_unique<NetworkController>()},
18 m_NetworkController{std::make_unique<NetworkController>()},
19 m_TimeController{std::make_unique<TimeController>()},
19 m_TimeController{std::make_unique<TimeController>()},
20 m_VariableController{std::make_unique<VariableController>()},
20 m_VariableController{std::make_unique<VariableController>()},
21 m_VisualizationController{std::make_unique<VisualizationController>()}
21 m_VisualizationController{std::make_unique<VisualizationController>()}
22 {
22 {
23 // /////////////////////////////// //
23 // /////////////////////////////// //
24 // Connections between controllers //
24 // Connections between controllers //
25 // /////////////////////////////// //
25 // /////////////////////////////// //
26
26
27 // VariableController <-> DataSourceController
27 // VariableController <-> DataSourceController
28 connect(m_DataSourceController.get(),
28 connect(m_DataSourceController.get(),
29 SIGNAL(variableCreationRequested(const QString &, std::shared_ptr<IDataProvider>)),
29 SIGNAL(variableCreationRequested(const QString &, std::shared_ptr<IDataProvider>)),
30 m_VariableController.get(),
30 m_VariableController.get(),
31 SLOT(createVariable(const QString &, std::shared_ptr<IDataProvider>)));
31 SLOT(createVariable(const QString &, std::shared_ptr<IDataProvider>)));
32
32
33 // VariableController <-> VisualizationController
33 // VariableController <-> VisualizationController
34 connect(m_VariableController.get(),
34 connect(m_VariableController.get(),
35 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)),
35 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)),
36 m_VisualizationController.get(),
36 m_VisualizationController.get(),
37 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), Qt::DirectConnection);
37 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), Qt::DirectConnection);
38
38
39
39
40 m_DataSourceController->moveToThread(&m_DataSourceControllerThread);
40 m_DataSourceController->moveToThread(&m_DataSourceControllerThread);
41 m_NetworkController->moveToThread(&m_NetworkControllerThread);
41 m_NetworkController->moveToThread(&m_NetworkControllerThread);
42 m_VariableController->moveToThread(&m_VariableControllerThread);
42 m_VariableController->moveToThread(&m_VariableControllerThread);
43 m_VisualizationController->moveToThread(&m_VisualizationControllerThread);
43 m_VisualizationController->moveToThread(&m_VisualizationControllerThread);
44
44
45
45
46 // Additionnal init
46 // Additionnal init
47 m_VariableController->setTimeController(m_TimeController.get());
47 m_VariableController->setTimeController(m_TimeController.get());
48 }
48 }
49
49
50 virtual ~SqpApplicationPrivate()
50 virtual ~SqpApplicationPrivate()
51 {
51 {
52 qCInfo(LOG_SqpApplication()) << tr("SqpApplicationPrivate destruction");
52 qCInfo(LOG_SqpApplication()) << tr("SqpApplicationPrivate destruction");
53 m_DataSourceControllerThread.quit();
53 m_DataSourceControllerThread.quit();
54 m_DataSourceControllerThread.wait();
54 m_DataSourceControllerThread.wait();
55
55
56 m_NetworkControllerThread.quit();
56 m_NetworkControllerThread.quit();
57 m_NetworkControllerThread.wait();
57 m_NetworkControllerThread.wait();
58
58
59 m_VariableControllerThread.quit();
59 m_VariableControllerThread.quit();
60 m_VariableControllerThread.wait();
60 m_VariableControllerThread.wait();
61
61
62 m_VisualizationControllerThread.quit();
62 m_VisualizationControllerThread.quit();
63 m_VisualizationControllerThread.wait();
63 m_VisualizationControllerThread.wait();
64 }
64 }
65
65
66 std::unique_ptr<DataSourceController> m_DataSourceController;
66 std::unique_ptr<DataSourceController> m_DataSourceController;
67 std::unique_ptr<VariableController> m_VariableController;
67 std::unique_ptr<VariableController> m_VariableController;
68 std::unique_ptr<TimeController> m_TimeController;
68 std::unique_ptr<TimeController> m_TimeController;
69 std::unique_ptr<NetworkController> m_NetworkController;
69 std::unique_ptr<NetworkController> m_NetworkController;
70 std::unique_ptr<VisualizationController> m_VisualizationController;
70 std::unique_ptr<VisualizationController> m_VisualizationController;
71 QThread m_DataSourceControllerThread;
71 QThread m_DataSourceControllerThread;
72 QThread m_NetworkControllerThread;
72 QThread m_NetworkControllerThread;
73 QThread m_VariableControllerThread;
73 QThread m_VariableControllerThread;
74 QThread m_VisualizationControllerThread;
74 QThread m_VisualizationControllerThread;
75 };
75 };
76
76
77
77
78 SqpApplication::SqpApplication(int &argc, char **argv)
78 SqpApplication::SqpApplication(int &argc, char **argv)
79 : QApplication{argc, argv}, impl{spimpl::make_unique_impl<SqpApplicationPrivate>()}
79 : QApplication{argc, argv}, impl{spimpl::make_unique_impl<SqpApplicationPrivate>()}
80 {
80 {
81 qCDebug(LOG_SqpApplication()) << tr("SqpApplication construction") << QThread::currentThread();
81 qCDebug(LOG_SqpApplication()) << tr("SqpApplication construction") << QThread::currentThread();
82
82
83 connect(&impl->m_DataSourceControllerThread, &QThread::started,
83 connect(&impl->m_DataSourceControllerThread, &QThread::started,
84 impl->m_DataSourceController.get(), &DataSourceController::initialize);
84 impl->m_DataSourceController.get(), &DataSourceController::initialize);
85 connect(&impl->m_DataSourceControllerThread, &QThread::finished,
85 connect(&impl->m_DataSourceControllerThread, &QThread::finished,
86 impl->m_DataSourceController.get(), &DataSourceController::finalize);
86 impl->m_DataSourceController.get(), &DataSourceController::finalize);
87
87
88 connect(&impl->m_NetworkControllerThread, &QThread::started, impl->m_NetworkController.get(),
88 connect(&impl->m_NetworkControllerThread, &QThread::started, impl->m_NetworkController.get(),
89 &NetworkController::initialize);
89 &NetworkController::initialize);
90 connect(&impl->m_NetworkControllerThread, &QThread::finished, impl->m_NetworkController.get(),
90 connect(&impl->m_NetworkControllerThread, &QThread::finished, impl->m_NetworkController.get(),
91 &NetworkController::finalize);
91 &NetworkController::finalize);
92
92
93 connect(&impl->m_VariableControllerThread, &QThread::started, impl->m_VariableController.get(),
93 connect(&impl->m_VariableControllerThread, &QThread::started, impl->m_VariableController.get(),
94 &VariableController::initialize);
94 &VariableController::initialize);
95 connect(&impl->m_VariableControllerThread, &QThread::finished, impl->m_VariableController.get(),
95 connect(&impl->m_VariableControllerThread, &QThread::finished, impl->m_VariableController.get(),
96 &VariableController::finalize);
96 &VariableController::finalize);
97
97
98 connect(&impl->m_VisualizationControllerThread, &QThread::started,
98 connect(&impl->m_VisualizationControllerThread, &QThread::started,
99 impl->m_VisualizationController.get(), &VisualizationController::initialize);
99 impl->m_VisualizationController.get(), &VisualizationController::initialize);
100 connect(&impl->m_VisualizationControllerThread, &QThread::finished,
100 connect(&impl->m_VisualizationControllerThread, &QThread::finished,
101 impl->m_VisualizationController.get(), &VisualizationController::finalize);
101 impl->m_VisualizationController.get(), &VisualizationController::finalize);
102
102
103 impl->m_DataSourceControllerThread.start();
103 impl->m_DataSourceControllerThread.start();
104 impl->m_NetworkControllerThread.start();
104 impl->m_NetworkControllerThread.start();
105 impl->m_VariableControllerThread.start();
105 impl->m_VariableControllerThread.start();
106 impl->m_VisualizationControllerThread.start();
106 impl->m_VisualizationControllerThread.start();
107
108 // Core connections:
109 // NetworkController <-> VariableController
110 connect(&sqpApp->networkController(), &NetworkController::replyDownloadProgress,
111 &sqpApp->variableController(), &VariableController::onVariableRetrieveDataInProgress);
107 }
112 }
108
113
109 SqpApplication::~SqpApplication()
114 SqpApplication::~SqpApplication()
110 {
115 {
111 }
116 }
112
117
113 void SqpApplication::initialize()
118 void SqpApplication::initialize()
114 {
119 {
115 }
120 }
116
121
117 DataSourceController &SqpApplication::dataSourceController() noexcept
122 DataSourceController &SqpApplication::dataSourceController() noexcept
118 {
123 {
119 return *impl->m_DataSourceController;
124 return *impl->m_DataSourceController;
120 }
125 }
121
126
122 NetworkController &SqpApplication::networkController() noexcept
127 NetworkController &SqpApplication::networkController() noexcept
123 {
128 {
124 return *impl->m_NetworkController;
129 return *impl->m_NetworkController;
125 }
130 }
126
131
127 TimeController &SqpApplication::timeController() noexcept
132 TimeController &SqpApplication::timeController() noexcept
128 {
133 {
129 return *impl->m_TimeController;
134 return *impl->m_TimeController;
130 }
135 }
131
136
132 VariableController &SqpApplication::variableController() noexcept
137 VariableController &SqpApplication::variableController() noexcept
133 {
138 {
134 return *impl->m_VariableController;
139 return *impl->m_VariableController;
135 }
140 }
136
141
137 VisualizationController &SqpApplication::visualizationController() noexcept
142 VisualizationController &SqpApplication::visualizationController() noexcept
138 {
143 {
139 return *impl->m_VisualizationController;
144 return *impl->m_VisualizationController;
140 }
145 }
@@ -1,101 +1,140
1 #include <Variable/VariableController.h>
1 #include <Variable/VariableController.h>
2 #include <Variable/VariableInspectorWidget.h>
2 #include <Variable/VariableInspectorWidget.h>
3 #include <Variable/VariableMenuHeaderWidget.h>
3 #include <Variable/VariableMenuHeaderWidget.h>
4 #include <Variable/VariableModel.h>
4 #include <Variable/VariableModel.h>
5
5
6 #include <ui_VariableInspectorWidget.h>
6 #include <ui_VariableInspectorWidget.h>
7
7
8 #include <QSortFilterProxyModel>
8 #include <QSortFilterProxyModel>
9 #include <QStyledItemDelegate>
9 #include <QWidgetAction>
10 #include <QWidgetAction>
10
11
11 #include <SqpApplication.h>
12 #include <SqpApplication.h>
12
13
13 Q_LOGGING_CATEGORY(LOG_VariableInspectorWidget, "VariableInspectorWidget")
14 Q_LOGGING_CATEGORY(LOG_VariableInspectorWidget, "VariableInspectorWidget")
14
15
16
17 class QProgressBarItemDelegate : public QStyledItemDelegate {
18
19 public:
20 QProgressBarItemDelegate(QObject *parent) : QStyledItemDelegate{parent} {}
21
22 void paint(QPainter *painter, const QStyleOptionViewItem &option,
23 const QModelIndex &index) const
24 {
25 auto data = index.data(Qt::DisplayRole);
26 auto progressData = index.data(VariableRoles::ProgressRole);
27 if (data.isValid() && progressData.isValid()) {
28 auto name = data.value<QString>();
29 auto progress = progressData.value<double>();
30 if (progress >= 0) {
31 auto progressBarOption = QStyleOptionProgressBar{};
32 progressBarOption.rect = option.rect;
33 progressBarOption.minimum = 0;
34 progressBarOption.maximum = 100;
35 progressBarOption.progress = progress;
36 progressBarOption.text
37 = QString("%1 %2").arg(name).arg(QString::number(progress, 'f', 2) + "%");
38 progressBarOption.textVisible = true;
39 progressBarOption.textAlignment = Qt::AlignCenter;
40
41 QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption,
42 painter);
43 }
44 }
45 else {
46 QStyledItemDelegate::paint(painter, option, index);
47 }
48 }
49 };
50
15 VariableInspectorWidget::VariableInspectorWidget(QWidget *parent)
51 VariableInspectorWidget::VariableInspectorWidget(QWidget *parent)
16 : QWidget{parent}, ui{new Ui::VariableInspectorWidget}
52 : QWidget{parent},
53 ui{new Ui::VariableInspectorWidget},
54 m_ProgressBarItemDelegate{new QProgressBarItemDelegate{this}}
17 {
55 {
18 ui->setupUi(this);
56 ui->setupUi(this);
19
57
20 // Sets model for table
58 // Sets model for table
21 // auto sortFilterModel = new QSortFilterProxyModel{this};
59 // auto sortFilterModel = new QSortFilterProxyModel{this};
22 // sortFilterModel->setSourceModel(sqpApp->variableController().variableModel());
60 // sortFilterModel->setSourceModel(sqpApp->variableController().variableModel());
23
61
24 auto variableModel = sqpApp->variableController().variableModel();
62 auto variableModel = sqpApp->variableController().variableModel();
25 ui->tableView->setModel(variableModel);
63 ui->tableView->setModel(variableModel);
26
64
27 // Adds extra signal/slot between view and model, so the view can be updated instantly when
65 // Adds extra signal/slot between view and model, so the view can be updated instantly when
28 // there is a change of data in the model
66 // there is a change of data in the model
29 connect(variableModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this,
67 connect(variableModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this,
30 SLOT(refresh()));
68 SLOT(refresh()));
31
69
32 ui->tableView->setSelectionModel(sqpApp->variableController().variableSelectionModel());
70 ui->tableView->setSelectionModel(sqpApp->variableController().variableSelectionModel());
71 ui->tableView->setItemDelegateForColumn(0, m_ProgressBarItemDelegate);
33
72
34 // Fixes column sizes
73 // Fixes column sizes
35 auto model = ui->tableView->model();
74 auto model = ui->tableView->model();
36 const auto count = model->columnCount();
75 const auto count = model->columnCount();
37 for (auto i = 0; i < count; ++i) {
76 for (auto i = 0; i < count; ++i) {
38 ui->tableView->setColumnWidth(
77 ui->tableView->setColumnWidth(
39 i, model->headerData(i, Qt::Horizontal, Qt::SizeHintRole).toSize().width());
78 i, model->headerData(i, Qt::Horizontal, Qt::SizeHintRole).toSize().width());
40 }
79 }
41
80
42 // Sets selection options
81 // Sets selection options
43 ui->tableView->setSelectionBehavior(QTableView::SelectRows);
82 ui->tableView->setSelectionBehavior(QTableView::SelectRows);
44 ui->tableView->setSelectionMode(QTableView::ExtendedSelection);
83 ui->tableView->setSelectionMode(QTableView::ExtendedSelection);
45
84
46 // Connection to show a menu when right clicking on the tree
85 // Connection to show a menu when right clicking on the tree
47 ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);
86 ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);
48 connect(ui->tableView, &QTableView::customContextMenuRequested, this,
87 connect(ui->tableView, &QTableView::customContextMenuRequested, this,
49 &VariableInspectorWidget::onTableMenuRequested);
88 &VariableInspectorWidget::onTableMenuRequested);
50 }
89 }
51
90
52 VariableInspectorWidget::~VariableInspectorWidget()
91 VariableInspectorWidget::~VariableInspectorWidget()
53 {
92 {
54 delete ui;
93 delete ui;
55 }
94 }
56
95
57 void VariableInspectorWidget::onTableMenuRequested(const QPoint &pos) noexcept
96 void VariableInspectorWidget::onTableMenuRequested(const QPoint &pos) noexcept
58 {
97 {
59 auto selectedRows = ui->tableView->selectionModel()->selectedRows();
98 auto selectedRows = ui->tableView->selectionModel()->selectedRows();
60
99
61 // Gets the model to retrieve the underlying selected variables
100 // Gets the model to retrieve the underlying selected variables
62 auto model = sqpApp->variableController().variableModel();
101 auto model = sqpApp->variableController().variableModel();
63 auto selectedVariables = QVector<std::shared_ptr<Variable> >{};
102 auto selectedVariables = QVector<std::shared_ptr<Variable> >{};
64 for (const auto &selectedRow : qAsConst(selectedRows)) {
103 for (const auto &selectedRow : qAsConst(selectedRows)) {
65 if (auto selectedVariable = model->variable(selectedRow.row())) {
104 if (auto selectedVariable = model->variable(selectedRow.row())) {
66 selectedVariables.push_back(selectedVariable);
105 selectedVariables.push_back(selectedVariable);
67 }
106 }
68 }
107 }
69
108
70 QMenu tableMenu{};
109 QMenu tableMenu{};
71
110
72 // Emits a signal so that potential receivers can populate the menu before displaying it
111 // Emits a signal so that potential receivers can populate the menu before displaying it
73 emit tableMenuAboutToBeDisplayed(&tableMenu, selectedVariables);
112 emit tableMenuAboutToBeDisplayed(&tableMenu, selectedVariables);
74
113
75 // Adds menu-specific actions
114 // Adds menu-specific actions
76 if (!selectedVariables.isEmpty()) {
115 if (!selectedVariables.isEmpty()) {
77 // 'Delete' action
116 // 'Delete' action
78 auto deleteFun = [&selectedVariables]() {
117 auto deleteFun = [&selectedVariables]() {
79 sqpApp->variableController().deleteVariables(selectedVariables);
118 sqpApp->variableController().deleteVariables(selectedVariables);
80 };
119 };
81
120
82 tableMenu.addSeparator();
121 tableMenu.addSeparator();
83 tableMenu.addAction(QIcon{":/icones/delete.png"}, tr("Delete"), deleteFun);
122 tableMenu.addAction(QIcon{":/icones/delete.png"}, tr("Delete"), deleteFun);
84 }
123 }
85
124
86 if (!tableMenu.isEmpty()) {
125 if (!tableMenu.isEmpty()) {
87 // Generates menu header (inserted before first action)
126 // Generates menu header (inserted before first action)
88 auto firstAction = tableMenu.actions().first();
127 auto firstAction = tableMenu.actions().first();
89 auto headerAction = new QWidgetAction{&tableMenu};
128 auto headerAction = new QWidgetAction{&tableMenu};
90 headerAction->setDefaultWidget(new VariableMenuHeaderWidget{selectedVariables, &tableMenu});
129 headerAction->setDefaultWidget(new VariableMenuHeaderWidget{selectedVariables, &tableMenu});
91 tableMenu.insertAction(firstAction, headerAction);
130 tableMenu.insertAction(firstAction, headerAction);
92
131
93 // Displays menu
132 // Displays menu
94 tableMenu.exec(mapToGlobal(pos));
133 tableMenu.exec(mapToGlobal(pos));
95 }
134 }
96 }
135 }
97
136
98 void VariableInspectorWidget::refresh() noexcept
137 void VariableInspectorWidget::refresh() noexcept
99 {
138 {
100 ui->tableView->viewport()->update();
139 ui->tableView->viewport()->update();
101 }
140 }
@@ -1,132 +1,134
1 #include "AmdaResultParser.h"
1 #include "AmdaResultParser.h"
2
2
3 #include <Data/ScalarSeries.h>
3 #include <Data/ScalarSeries.h>
4
4
5 #include <QDateTime>
5 #include <QDateTime>
6 #include <QFile>
6 #include <QFile>
7 #include <QRegularExpression>
7 #include <QRegularExpression>
8
8
9 #include <cmath>
10
9 Q_LOGGING_CATEGORY(LOG_AmdaResultParser, "AmdaResultParser")
11 Q_LOGGING_CATEGORY(LOG_AmdaResultParser, "AmdaResultParser")
10
12
11 namespace {
13 namespace {
12
14
13 /// Format for dates in result files
15 /// Format for dates in result files
14 const auto DATE_FORMAT = QStringLiteral("yyyy-MM-ddThh:mm:ss.zzz");
16 const auto DATE_FORMAT = QStringLiteral("yyyy-MM-ddThh:mm:ss.zzz");
15
17
16 /// Separator between values in a result line
18 /// Separator between values in a result line
17 const auto RESULT_LINE_SEPARATOR = QRegularExpression{QStringLiteral("\\s+")};
19 const auto RESULT_LINE_SEPARATOR = QRegularExpression{QStringLiteral("\\s+")};
18
20
19 /// Regex to find unit in a line. Examples of valid lines:
21 /// Regex to find unit in a line. Examples of valid lines:
20 /// ... - Units : nT - ...
22 /// ... - Units : nT - ...
21 /// ... -Units:nT- ...
23 /// ... -Units:nT- ...
22 /// ... -Units: mΒ²- ...
24 /// ... -Units: mΒ²- ...
23 /// ... - Units : m/s - ...
25 /// ... - Units : m/s - ...
24 const auto UNIT_REGEX = QRegularExpression{QStringLiteral("-\\s*Units\\s*:\\s*(.+?)\\s*-")};
26 const auto UNIT_REGEX = QRegularExpression{QStringLiteral("-\\s*Units\\s*:\\s*(.+?)\\s*-")};
25
27
26 /// Converts a string date to a double date
28 /// Converts a string date to a double date
27 /// @return a double that represents the date in seconds, NaN if the string date can't be converted
29 /// @return a double that represents the date in seconds, NaN if the string date can't be converted
28 double doubleDate(const QString &stringDate) noexcept
30 double doubleDate(const QString &stringDate) noexcept
29 {
31 {
30 auto dateTime = QDateTime::fromString(stringDate, DATE_FORMAT);
32 auto dateTime = QDateTime::fromString(stringDate, DATE_FORMAT);
31 return dateTime.isValid() ? (dateTime.toMSecsSinceEpoch() / 1000.)
33 return dateTime.isValid() ? (dateTime.toMSecsSinceEpoch() / 1000.)
32 : std::numeric_limits<double>::quiet_NaN();
34 : std::numeric_limits<double>::quiet_NaN();
33 }
35 }
34
36
35 /**
37 /**
36 * Reads stream to retrieve x-axis unit
38 * Reads stream to retrieve x-axis unit
37 * @param stream the stream to read
39 * @param stream the stream to read
38 * @return the unit that has been read in the stream, a default unit (time unit with no label) if an
40 * @return the unit that has been read in the stream, a default unit (time unit with no label) if an
39 * error occured during reading
41 * error occured during reading
40 */
42 */
41 Unit readXAxisUnit(QTextStream &stream)
43 Unit readXAxisUnit(QTextStream &stream)
42 {
44 {
43 QString line{};
45 QString line{};
44
46
45 if (stream.readLineInto(&line)) {
47 if (stream.readLineInto(&line)) {
46 auto match = UNIT_REGEX.match(line);
48 auto match = UNIT_REGEX.match(line);
47 if (match.hasMatch()) {
49 if (match.hasMatch()) {
48 return Unit{match.captured(1), true};
50 return Unit{match.captured(1), true};
49 }
51 }
50 else {
52 else {
51 qCWarning(LOG_AmdaResultParser())
53 qCWarning(LOG_AmdaResultParser())
52 << QObject::tr("Can't read unit: invalid line %1").arg(line);
54 << QObject::tr("Can't read unit: invalid line %1").arg(line);
53 }
55 }
54 }
56 }
55 else {
57 else {
56 qCWarning(LOG_AmdaResultParser()) << QObject::tr("Can't read unit: end of file");
58 qCWarning(LOG_AmdaResultParser()) << QObject::tr("Can't read unit: end of file");
57 }
59 }
58
60
59 // Error cases
61 // Error cases
60 return Unit{{}, true};
62 return Unit{{}, true};
61 }
63 }
62
64
63 /**
65 /**
64 * Reads stream to retrieve results
66 * Reads stream to retrieve results
65 * @param stream the stream to read
67 * @param stream the stream to read
66 * @return the pair of vectors x-axis data/values data that has been read in the stream
68 * @return the pair of vectors x-axis data/values data that has been read in the stream
67 */
69 */
68 QPair<QVector<double>, QVector<double> > readResults(QTextStream &stream)
70 QPair<QVector<double>, QVector<double> > readResults(QTextStream &stream)
69 {
71 {
70 auto xData = QVector<double>{};
72 auto xData = QVector<double>{};
71 auto valuesData = QVector<double>{};
73 auto valuesData = QVector<double>{};
72
74
73 QString line{};
75 QString line{};
74 while (stream.readLineInto(&line)) {
76 while (stream.readLineInto(&line)) {
75 auto lineData = line.split(RESULT_LINE_SEPARATOR, QString::SkipEmptyParts);
77 auto lineData = line.split(RESULT_LINE_SEPARATOR, QString::SkipEmptyParts);
76 if (lineData.size() == 2) {
78 if (lineData.size() == 2) {
77 // X : the data is converted from date to double (in secs)
79 // X : the data is converted from date to double (in secs)
78 auto x = doubleDate(lineData.at(0));
80 auto x = doubleDate(lineData.at(0));
79
81
80 // Value
82 // Value
81 bool valueOk;
83 bool valueOk;
82 auto value = lineData.at(1).toDouble(&valueOk);
84 auto value = lineData.at(1).toDouble(&valueOk);
83
85
84 // Adds result only if x and value are valid
86 // Adds result only if x and value are valid
85 if (!std::isnan(x) && !std::isnan(value) && valueOk) {
87 if (!std::isnan(x) && !std::isnan(value) && valueOk) {
86 xData.push_back(x);
88 xData.push_back(x);
87 valuesData.push_back(value);
89 valuesData.push_back(value);
88 }
90 }
89 else {
91 else {
90 qCWarning(LOG_AmdaResultParser())
92 qCWarning(LOG_AmdaResultParser())
91 << QObject::tr(
93 << QObject::tr(
92 "Can't retrieve results from line %1: x and/or value are invalid")
94 "Can't retrieve results from line %1: x and/or value are invalid")
93 .arg(line);
95 .arg(line);
94 }
96 }
95 }
97 }
96 else {
98 else {
97 qCWarning(LOG_AmdaResultParser())
99 qCWarning(LOG_AmdaResultParser())
98 << QObject::tr("Can't retrieve results from line %1: invalid line").arg(line);
100 << QObject::tr("Can't retrieve results from line %1: invalid line").arg(line);
99 }
101 }
100 }
102 }
101
103
102 return qMakePair(std::move(xData), std::move(valuesData));
104 return qMakePair(std::move(xData), std::move(valuesData));
103 }
105 }
104
106
105 } // namespace
107 } // namespace
106
108
107 std::shared_ptr<IDataSeries> AmdaResultParser::readTxt(const QString &filePath) noexcept
109 std::shared_ptr<IDataSeries> AmdaResultParser::readTxt(const QString &filePath) noexcept
108 {
110 {
109 QFile file{filePath};
111 QFile file{filePath};
110
112
111 if (!file.open(QFile::ReadOnly | QIODevice::Text)) {
113 if (!file.open(QFile::ReadOnly | QIODevice::Text)) {
112 qCCritical(LOG_AmdaResultParser())
114 qCCritical(LOG_AmdaResultParser())
113 << QObject::tr("Can't retrieve AMDA data from file %1: %2")
115 << QObject::tr("Can't retrieve AMDA data from file %1: %2")
114 .arg(filePath, file.errorString());
116 .arg(filePath, file.errorString());
115 return nullptr;
117 return nullptr;
116 }
118 }
117
119
118 QTextStream stream{&file};
120 QTextStream stream{&file};
119
121
120 // Ignore first two lines (comments lines)
122 // Ignore first two lines (comments lines)
121 stream.readLine();
123 stream.readLine();
122 stream.readLine();
124 stream.readLine();
123
125
124 // Reads x-axis unit
126 // Reads x-axis unit
125 auto xAxisUnit = readXAxisUnit(stream);
127 auto xAxisUnit = readXAxisUnit(stream);
126
128
127 // Reads results
129 // Reads results
128 auto results = readResults(stream);
130 auto results = readResults(stream);
129
131
130 return std::make_shared<ScalarSeries>(std::move(results.first), std::move(results.second),
132 return std::make_shared<ScalarSeries>(std::move(results.first), std::move(results.second),
131 xAxisUnit, Unit{});
133 xAxisUnit, Unit{});
132 }
134 }
@@ -1,179 +1,179
1 #include "AmdaResultParser.h"
1 #include "AmdaResultParser.h"
2
2
3 #include <Data/ScalarSeries.h>
3 #include <Data/ScalarSeries.h>
4
4
5 #include <QObject>
5 #include <QObject>
6 #include <QtTest>
6 #include <QtTest>
7
7
8 namespace {
8 namespace {
9
9
10 /// Path for the tests
10 /// Path for the tests
11 const auto TESTS_RESOURCES_PATH
11 const auto TESTS_RESOURCES_PATH
12 = QFileInfo{QString{AMDA_TESTS_RESOURCES_DIR}, "TestAmdaResultParser"}.absoluteFilePath();
12 = QFileInfo{QString{AMDA_TESTS_RESOURCES_DIR}, "TestAmdaResultParser"}.absoluteFilePath();
13
13
14 QString inputFilePath(const QString &inputFileName)
14 QString inputFilePath(const QString &inputFileName)
15 {
15 {
16 return QFileInfo{TESTS_RESOURCES_PATH, inputFileName}.absoluteFilePath();
16 return QFileInfo{TESTS_RESOURCES_PATH, inputFileName}.absoluteFilePath();
17 }
17 }
18
18
19 struct ExpectedResults {
19 struct ExpectedResults {
20 explicit ExpectedResults() = default;
20 explicit ExpectedResults() = default;
21
21
22 /// Ctor with QVector<QDateTime> as x-axis data. Datetimes are converted to doubles
22 /// Ctor with QVector<QDateTime> as x-axis data. Datetimes are converted to doubles
23 explicit ExpectedResults(Unit xAxisUnit, Unit valuesUnit, const QVector<QDateTime> &xAxisData,
23 explicit ExpectedResults(Unit xAxisUnit, Unit valuesUnit, const QVector<QDateTime> &xAxisData,
24 QVector<double> valuesData)
24 QVector<double> valuesData)
25 : m_ParsingOK{true},
25 : m_ParsingOK{true},
26 m_XAxisUnit{xAxisUnit},
26 m_XAxisUnit{xAxisUnit},
27 m_ValuesUnit{valuesUnit},
27 m_ValuesUnit{valuesUnit},
28 m_XAxisData{},
28 m_XAxisData{},
29 m_ValuesData{std::move(valuesData)}
29 m_ValuesData{std::move(valuesData)}
30 {
30 {
31 // Converts QVector<QDateTime> to QVector<double>
31 // Converts QVector<QDateTime> to QVector<double>
32 std::transform(xAxisData.cbegin(), xAxisData.cend(), std::back_inserter(m_XAxisData),
32 std::transform(xAxisData.cbegin(), xAxisData.cend(), std::back_inserter(m_XAxisData),
33 [](const auto &dateTime) { return dateTime.toMSecsSinceEpoch() / 1000.; });
33 [](const auto &dateTime) { return dateTime.toMSecsSinceEpoch() / 1000.; });
34 }
34 }
35
35
36 /**
36 /**
37 * Validates a DataSeries compared to the expected results
37 * Validates a DataSeries compared to the expected results
38 * @param results the DataSeries to validate
38 * @param results the DataSeries to validate
39 */
39 */
40 void validate(std::shared_ptr<IDataSeries> results)
40 void validate(std::shared_ptr<IDataSeries> results)
41 {
41 {
42 if (m_ParsingOK) {
42 if (m_ParsingOK) {
43 auto scalarSeries = dynamic_cast<ScalarSeries *>(results.get());
43 auto scalarSeries = dynamic_cast<ScalarSeries *>(results.get());
44 QVERIFY(scalarSeries != nullptr);
44 QVERIFY(scalarSeries != nullptr);
45
45
46 // Checks units
46 // Checks units
47 QVERIFY(scalarSeries->xAxisUnit() == m_XAxisUnit);
47 QVERIFY(scalarSeries->xAxisUnit() == m_XAxisUnit);
48 QVERIFY(scalarSeries->valuesUnit() == m_ValuesUnit);
48 QVERIFY(scalarSeries->valuesUnit() == m_ValuesUnit);
49
49
50 // Checks values
50 // Checks values
51 QVERIFY(scalarSeries->xAxisData()->data() == m_XAxisData);
51 QVERIFY(scalarSeries->xAxisData()->data() == m_XAxisData);
52 QVERIFY(scalarSeries->valuesData()->data() == m_ValuesData);
52 QVERIFY(scalarSeries->valuesData()->data() == m_ValuesData);
53 }
53 }
54 else {
54 else {
55 QVERIFY(results == nullptr);
55 QVERIFY(results == nullptr);
56 }
56 }
57 }
57 }
58
58
59 // Parsing was successfully completed
59 // Parsing was successfully completed
60 bool m_ParsingOK{false};
60 bool m_ParsingOK{false};
61 // Expected x-axis unit
61 // Expected x-axis unit
62 Unit m_XAxisUnit{};
62 Unit m_XAxisUnit{};
63 // Expected values unit
63 // Expected values unit
64 Unit m_ValuesUnit{};
64 Unit m_ValuesUnit{};
65 // Expected x-axis data
65 // Expected x-axis data
66 QVector<double> m_XAxisData{};
66 QVector<double> m_XAxisData{};
67 // Expected values data
67 // Expected values data
68 QVector<double> m_ValuesData{};
68 QVector<double> m_ValuesData{};
69 };
69 };
70
70
71 } // namespace
71 } // namespace
72
72
73 Q_DECLARE_METATYPE(ExpectedResults)
73 Q_DECLARE_METATYPE(ExpectedResults)
74
74
75 class TestAmdaResultParser : public QObject {
75 class TestAmdaResultParser : public QObject {
76 Q_OBJECT
76 Q_OBJECT
77 private slots:
77 private slots:
78 /// Input test data
78 /// Input test data
79 /// @sa testTxtJson()
79 /// @sa testTxtJson()
80 void testReadTxt_data();
80 void testReadTxt_data();
81
81
82 /// Tests parsing of a TXT file
82 /// Tests parsing of a TXT file
83 void testReadTxt();
83 void testReadTxt();
84 };
84 };
85
85
86 void TestAmdaResultParser::testReadTxt_data()
86 void TestAmdaResultParser::testReadTxt_data()
87 {
87 {
88 // ////////////// //
88 // ////////////// //
89 // Test structure //
89 // Test structure //
90 // ////////////// //
90 // ////////////// //
91
91
92 // Name of TXT file to read
92 // Name of TXT file to read
93 QTest::addColumn<QString>("inputFileName");
93 QTest::addColumn<QString>("inputFileName");
94 // Expected results
94 // Expected results
95 QTest::addColumn<ExpectedResults>("expectedResults");
95 QTest::addColumn<ExpectedResults>("expectedResults");
96
96
97 // ////////// //
97 // ////////// //
98 // Test cases //
98 // Test cases //
99 // ////////// //
99 // ////////// //
100
100
101 auto dateTime = [](int year, int month, int day, int hours, int minutes, int seconds) {
101 auto dateTime = [](int year, int month, int day, int hours, int minutes, int seconds) {
102 return QDateTime{{year, month, day}, {hours, minutes, seconds}};
102 return QDateTime{{year, month, day}, {hours, minutes, seconds}};
103 };
103 };
104
104
105 // Valid file
105 // Valid file
106 QTest::newRow("Valid file")
106 QTest::newRow("Valid file")
107 << QStringLiteral("ValidScalar1.txt")
107 << QStringLiteral("ValidScalar1.txt")
108 << ExpectedResults{
108 << ExpectedResults{
109 Unit{QStringLiteral("nT"), true}, Unit{},
109 Unit{QStringLiteral("nT"), true}, Unit{},
110 QVector<QDateTime>{dateTime(2013, 9, 23, 9, 0, 30), dateTime(2013, 9, 23, 9, 1, 30),
110 QVector<QDateTime>{dateTime(2013, 9, 23, 9, 0, 30), dateTime(2013, 9, 23, 9, 1, 30),
111 dateTime(2013, 9, 23, 9, 2, 30), dateTime(2013, 9, 23, 9, 3, 30),
111 dateTime(2013, 9, 23, 9, 2, 30), dateTime(2013, 9, 23, 9, 3, 30),
112 dateTime(2013, 9, 23, 9, 4, 30), dateTime(2013, 9, 23, 9, 5, 30),
112 dateTime(2013, 9, 23, 9, 4, 30), dateTime(2013, 9, 23, 9, 5, 30),
113 dateTime(2013, 9, 23, 9, 6, 30), dateTime(2013, 9, 23, 9, 7, 30),
113 dateTime(2013, 9, 23, 9, 6, 30), dateTime(2013, 9, 23, 9, 7, 30),
114 dateTime(2013, 9, 23, 9, 8, 30), dateTime(2013, 9, 23, 9, 9, 30)},
114 dateTime(2013, 9, 23, 9, 8, 30), dateTime(2013, 9, 23, 9, 9, 30)},
115 QVector<double>{-2.83950, -2.71850, -2.52150, -2.57633, -2.58050, -2.48325, -2.63025,
115 QVector<double>{-2.83950, -2.71850, -2.52150, -2.57633, -2.58050, -2.48325, -2.63025,
116 -2.55800, -2.43250, -2.42200}};
116 -2.55800, -2.43250, -2.42200}};
117
117
118 // Valid files but with some invalid lines (wrong unit, wrong values, etc.)
118 // Valid files but with some invalid lines (wrong unit, wrong values, etc.)
119 QTest::newRow("No unit file") << QStringLiteral("NoUnit.txt")
119 QTest::newRow("No unit file") << QStringLiteral("NoUnit.txt")
120 << ExpectedResults{Unit{QStringLiteral(""), true}, Unit{},
120 << ExpectedResults{Unit{QStringLiteral(""), true}, Unit{},
121 QVector<QDateTime>{}, QVector<double>{}};
121 QVector<QDateTime>{}, QVector<double>{}};
122 QTest::newRow("Wrong unit file")
122 QTest::newRow("Wrong unit file")
123 << QStringLiteral("WrongUnit.txt")
123 << QStringLiteral("WrongUnit.txt")
124 << ExpectedResults{Unit{QStringLiteral(""), true}, Unit{},
124 << ExpectedResults{Unit{QStringLiteral(""), true}, Unit{},
125 QVector<QDateTime>{dateTime(2013, 9, 23, 9, 0, 30),
125 QVector<QDateTime>{dateTime(2013, 9, 23, 9, 0, 30),
126 dateTime(2013, 9, 23, 9, 1, 30),
126 dateTime(2013, 9, 23, 9, 1, 30),
127 dateTime(2013, 9, 23, 9, 2, 30)},
127 dateTime(2013, 9, 23, 9, 2, 30)},
128 QVector<double>{-2.83950, -2.71850, -2.52150}};
128 QVector<double>{-2.83950, -2.71850, -2.52150}};
129
129
130 QTest::newRow("Wrong results file (date of first line is invalid")
130 QTest::newRow("Wrong results file (date of first line is invalid")
131 << QStringLiteral("WrongDate.txt")
131 << QStringLiteral("WrongDate.txt")
132 << ExpectedResults{
132 << ExpectedResults{
133 Unit{QStringLiteral("nT"), true}, Unit{},
133 Unit{QStringLiteral("nT"), true}, Unit{},
134 QVector<QDateTime>{dateTime(2013, 9, 23, 9, 1, 30), dateTime(2013, 9, 23, 9, 2, 30)},
134 QVector<QDateTime>{dateTime(2013, 9, 23, 9, 1, 30), dateTime(2013, 9, 23, 9, 2, 30)},
135 QVector<double>{-2.71850, -2.52150}};
135 QVector<double>{-2.71850, -2.52150}};
136
136
137 QTest::newRow("Wrong results file (too many values for first line")
137 QTest::newRow("Wrong results file (too many values for first line")
138 << QStringLiteral("TooManyValues.txt")
138 << QStringLiteral("TooManyValues.txt")
139 << ExpectedResults{
139 << ExpectedResults{
140 Unit{QStringLiteral("nT"), true}, Unit{},
140 Unit{QStringLiteral("nT"), true}, Unit{},
141 QVector<QDateTime>{dateTime(2013, 9, 23, 9, 1, 30), dateTime(2013, 9, 23, 9, 2, 30)},
141 QVector<QDateTime>{dateTime(2013, 9, 23, 9, 1, 30), dateTime(2013, 9, 23, 9, 2, 30)},
142 QVector<double>{-2.71850, -2.52150}};
142 QVector<double>{-2.71850, -2.52150}};
143
143
144 QTest::newRow("Wrong results file (value of first line is invalid")
144 QTest::newRow("Wrong results file (value of first line is invalid")
145 << QStringLiteral("WrongValue.txt")
145 << QStringLiteral("WrongValue.txt")
146 << ExpectedResults{
146 << ExpectedResults{
147 Unit{QStringLiteral("nT"), true}, Unit{},
147 Unit{QStringLiteral("nT"), true}, Unit{},
148 QVector<QDateTime>{dateTime(2013, 9, 23, 9, 1, 30), dateTime(2013, 9, 23, 9, 2, 30)},
148 QVector<QDateTime>{dateTime(2013, 9, 23, 9, 1, 30), dateTime(2013, 9, 23, 9, 2, 30)},
149 QVector<double>{-2.71850, -2.52150}};
149 QVector<double>{-2.71850, -2.52150}};
150
150
151 QTest::newRow("Wrong results file (value of first line is NaN")
151 QTest::newRow("Wrong results file (value of first line is NaN")
152 << QStringLiteral("NaNValue.txt")
152 << QStringLiteral("NaNValue.txt")
153 << ExpectedResults{
153 << ExpectedResults{
154 Unit{QStringLiteral("nT"), true}, Unit{},
154 Unit{QStringLiteral("nT"), true}, Unit{},
155 QVector<QDateTime>{dateTime(2013, 9, 23, 9, 1, 30), dateTime(2013, 9, 23, 9, 2, 30)},
155 QVector<QDateTime>{dateTime(2013, 9, 23, 9, 1, 30), dateTime(2013, 9, 23, 9, 2, 30)},
156 QVector<double>{-2.71850, -2.52150}};
156 QVector<double>{-2.71850, -2.52150}};
157
157
158 // Invalid file
158 // Invalid file
159 QTest::newRow("Invalid file (unexisting file)")
159 QTest::newRow("Invalid file (unexisting file)") << QStringLiteral("UnexistingFile.txt")
160 << QStringLiteral("UnexistingFile.txt") << ExpectedResults{};
160 << ExpectedResults{};
161 }
161 }
162
162
163 void TestAmdaResultParser::testReadTxt()
163 void TestAmdaResultParser::testReadTxt()
164 {
164 {
165 QFETCH(QString, inputFileName);
165 QFETCH(QString, inputFileName);
166 QFETCH(ExpectedResults, expectedResults);
166 QFETCH(ExpectedResults, expectedResults);
167
167
168 // Parses file
168 // Parses file
169 auto filePath = inputFilePath(inputFileName);
169 auto filePath = inputFilePath(inputFileName);
170 auto results = AmdaResultParser::readTxt(filePath);
170 auto results = AmdaResultParser::readTxt(filePath);
171
171
172 // ///////////////// //
172 // ///////////////// //
173 // Validates results //
173 // Validates results //
174 // ///////////////// //
174 // ///////////////// //
175 expectedResults.validate(results);
175 expectedResults.validate(results);
176 }
176 }
177
177
178 QTEST_MAIN(TestAmdaResultParser)
178 QTEST_MAIN(TestAmdaResultParser)
179 #include "TestAmdaResultParser.moc"
179 #include "TestAmdaResultParser.moc"
General Comments 0
You need to be logged in to leave comments. Login now