diff --git a/core/include/Network/NetworkController.h b/core/include/Network/NetworkController.h index dd4fca5..2778624 100644 --- a/core/include/Network/NetworkController.h +++ b/core/include/Network/NetworkController.h @@ -25,13 +25,16 @@ public: void finalize(); public slots: + /// Execute request and call callback when the reply is finished. Identifier is attached to the + /// callback void onProcessRequested(const QNetworkRequest &request, QUuid identifier, std::function callback); + /// Cancel the request of identifier void onReplyCanceled(QUuid identifier); signals: void replyFinished(QNetworkReply *reply, QUuid identifier); - void replyDownloadProgress(QUuid identifier); + void replyDownloadProgress(QUuid identifier, double progress); private: void waitForFinish(); diff --git a/core/include/Variable/VariableController.h b/core/include/Variable/VariableController.h index da022c3..dc7ef23 100644 --- a/core/include/Variable/VariableController.h +++ b/core/include/Variable/VariableController.h @@ -67,6 +67,9 @@ public slots: /// Update the temporal parameters of every selected variable to dateTime void onDateTimeOnSelection(const SqpDateTime &dateTime); + + void onVariableRetrieveDataInProgress(QUuid identifier, double progress); + void initialize(); void finalize(); diff --git a/core/include/Variable/VariableModel.h b/core/include/Variable/VariableModel.h index 3a89ad2..d2ece46 100644 --- a/core/include/Variable/VariableModel.h +++ b/core/include/Variable/VariableModel.h @@ -12,6 +12,9 @@ Q_DECLARE_LOGGING_CATEGORY(LOG_VariableModel) +enum VariableRoles { progressRole = Qt::UserRole }; + + class IDataSeries; class Variable; @@ -37,11 +40,15 @@ public: */ void deleteVariable(std::shared_ptr variable) noexcept; + std::shared_ptr variable(int index) const; + void setDataProgress(std::shared_ptr variable, double progress); + // /////////////////////////// // // QAbstractTableModel methods // // /////////////////////////// // + virtual int columnCount(const QModelIndex &parent = QModelIndex{}) const override; virtual int rowCount(const QModelIndex &parent = QModelIndex{}) const override; virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; diff --git a/core/src/Network/NetworkController.cpp b/core/src/Network/NetworkController.cpp index eadc56b..64c0bb8 100644 --- a/core/src/Network/NetworkController.cpp +++ b/core/src/Network/NetworkController.cpp @@ -26,8 +26,8 @@ NetworkController::NetworkController(QObject *parent) void NetworkController::onProcessRequested(const QNetworkRequest &request, QUuid identifier, std::function callback) { - qCDebug(LOG_NetworkController()) << tr("NetworkController registered") - << QThread::currentThread(); + qCInfo(LOG_NetworkController()) << tr("NetworkController registered") + << QThread::currentThread(); auto reply = impl->m_AccessManager->get(request); // Store the couple reply id @@ -35,27 +35,26 @@ void NetworkController::onProcessRequested(const QNetworkRequest &request, QUuid auto onReplyFinished = [reply, this, identifier, callback]() { - qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyFinished") - << QThread::currentThread(); + qCInfo(LOG_NetworkController()) << tr("NetworkController onReplyFinished") + << QThread::currentThread(); auto it = impl->m_NetworkReplyToVariableId.find(reply); if (it != impl->m_NetworkReplyToVariableId.cend()) { callback(reply, identifier); } }; - auto onReplyDownloadProgress = [reply, this]() { + auto onReplyProgress = [reply, this](qint64 bytesRead, qint64 totalBytes) { - qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyDownloadProgress") - << QThread::currentThread(); + double progress = (bytesRead * 100.0) / totalBytes; auto it = impl->m_NetworkReplyToVariableId.find(reply); if (it != impl->m_NetworkReplyToVariableId.cend()) { - emit this->replyDownloadProgress(it->second); + emit this->replyDownloadProgress(it->second, progress); } }; connect(reply, &QNetworkReply::finished, this, onReplyFinished); - connect(reply, &QNetworkReply::downloadProgress, this, onReplyDownloadProgress); + connect(reply, &QNetworkReply::downloadProgress, this, onReplyProgress); } void NetworkController::initialize() diff --git a/core/src/Variable/VariableController.cpp b/core/src/Variable/VariableController.cpp index 3039def..8611fb4 100644 --- a/core/src/Variable/VariableController.cpp +++ b/core/src/Variable/VariableController.cpp @@ -157,6 +157,17 @@ void VariableController::onDateTimeOnSelection(const SqpDateTime &dateTime) } } +void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress) +{ + auto findReply = [identifier](const auto &entry) { return identifier == entry.second; }; + + auto end = impl->m_VariableToIdentifier.cend(); + auto it = std::find_if(impl->m_VariableToIdentifier.cbegin(), end, findReply); + if (it != end) { + impl->m_VariableModel->setDataProgress(it->first, progress); + } +} + void VariableController::onRequestDataLoading(std::shared_ptr variable, const SqpDateTime &dateTime) diff --git a/core/src/Variable/VariableModel.cpp b/core/src/Variable/VariableModel.cpp index b2e6327..8acdcf7 100644 --- a/core/src/Variable/VariableModel.cpp +++ b/core/src/Variable/VariableModel.cpp @@ -5,6 +5,7 @@ #include #include +#include Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel") @@ -40,11 +41,17 @@ const auto COLUMN_PROPERTIES /// Format for datetimes const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz"); + } // namespace struct VariableModel::VariableModelPrivate { /// Variables created in SciQlop std::vector > m_Variables; + std::unordered_map, double> m_VariableToProgress; + + + /// Return te row index of the variable + int indexOfVariable(Variable *variable) const noexcept; }; VariableModel::VariableModel(QObject *parent) @@ -96,11 +103,21 @@ void VariableModel::deleteVariable(std::shared_ptr variable) noexcept } } + std::shared_ptr VariableModel::variable(int index) const { return (index >= 0 && index < impl->m_Variables.size()) ? impl->m_Variables[index] : nullptr; } +void VariableModel::setDataProgress(std::shared_ptr variable, double progress) +{ + + impl->m_VariableToProgress[variable] = progress; + auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN); + + emit dataChanged(modelIndex, modelIndex); +} + int VariableModel::columnCount(const QModelIndex &parent) const { Q_UNUSED(parent); @@ -152,6 +169,15 @@ QVariant VariableModel::data(const QModelIndex &index, int role) const qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)"); } } + else if (role == VariableRoles::progressRole) { + if (auto variable = impl->m_Variables.at(index.row())) { + + auto it = impl->m_VariableToProgress.find(variable); + if (it != impl->m_VariableToProgress.cend()) { + return it->second; + } + } + } return QVariant{}; } @@ -183,18 +209,28 @@ void VariableModel::onVariableUpdated() noexcept { // Finds variable that has been updated in the model if (auto updatedVariable = dynamic_cast(sender())) { - auto begin = std::cbegin(impl->m_Variables); - auto end = std::cend(impl->m_Variables); - auto it = std::find_if(begin, end, [updatedVariable](const auto &variable) { - return variable.get() == updatedVariable; - }); - - if (it != end) { - // Gets the index of the variable in the model: we assume here that views have the same - // order as the model - auto updateVariableIndex = std::distance(begin, it); - emit dataChanged(createIndex(updateVariableIndex, 0), - createIndex(updateVariableIndex, columnCount() - 1)); + auto updatedVariableIndex = impl->indexOfVariable(updatedVariable); + + if (updatedVariableIndex > -1) { + emit dataChanged(createIndex(updatedVariableIndex, 0), + createIndex(updatedVariableIndex, columnCount() - 1)); } } } + +int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept +{ + auto begin = std::cbegin(m_Variables); + auto end = std::cend(m_Variables); + auto it + = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; }); + + if (it != end) { + // Gets the index of the variable in the model: we assume here that views have the same + // order as the model + return std::distance(begin, it); + } + else { + return -1; + } +} diff --git a/gui/include/Variable/VariableInspectorWidget.h b/gui/include/Variable/VariableInspectorWidget.h index cc98294..f8e249c 100644 --- a/gui/include/Variable/VariableInspectorWidget.h +++ b/gui/include/Variable/VariableInspectorWidget.h @@ -11,6 +11,8 @@ Q_DECLARE_LOGGING_CATEGORY(LOG_VariableInspectorWidget) class Variable; +class QProgressBarItemDelegate; + namespace Ui { class VariableInspectorWidget; } // Ui @@ -42,6 +44,8 @@ signals: private: Ui::VariableInspectorWidget *ui; + QProgressBarItemDelegate *m_ProgressBarItemDelegate; + private slots: /// Slot called when right clicking on an variable in the table (displays a menu) void onTableMenuRequested(const QPoint &pos) noexcept; diff --git a/gui/src/SqpApplication.cpp b/gui/src/SqpApplication.cpp index 597a3a3..0ec169f 100644 --- a/gui/src/SqpApplication.cpp +++ b/gui/src/SqpApplication.cpp @@ -104,6 +104,11 @@ SqpApplication::SqpApplication(int &argc, char **argv) impl->m_NetworkControllerThread.start(); impl->m_VariableControllerThread.start(); impl->m_VisualizationControllerThread.start(); + + // Core connections: + // NetworkController <-> VariableController + connect(&sqpApp->networkController(), &NetworkController::replyDownloadProgress, + &sqpApp->variableController(), &VariableController::onVariableRetrieveDataInProgress); } SqpApplication::~SqpApplication() diff --git a/gui/src/Variable/VariableInspectorWidget.cpp b/gui/src/Variable/VariableInspectorWidget.cpp index 93b38c8..cded64b 100644 --- a/gui/src/Variable/VariableInspectorWidget.cpp +++ b/gui/src/Variable/VariableInspectorWidget.cpp @@ -6,14 +6,52 @@ #include #include +#include #include #include Q_LOGGING_CATEGORY(LOG_VariableInspectorWidget, "VariableInspectorWidget") + +class QProgressBarItemDelegate : public QStyledItemDelegate { + +public: + QProgressBarItemDelegate(QObject *parent) : QStyledItemDelegate(parent) {} + + void paint(QPainter *painter, const QStyleOptionViewItem &option, + const QModelIndex &index) const + { + auto data = index.data(Qt::DisplayRole); + auto progressData = index.data(VariableRoles::progressRole); + if (data.isValid() && progressData.isValid()) { + auto name = data.value(); + auto progress = progressData.value(); + if (progress >= 0) { + auto progressBarOption = QStyleOptionProgressBar{}; + progressBarOption.rect = option.rect; + progressBarOption.minimum = 0; + progressBarOption.maximum = 100; + progressBarOption.progress = progress; + progressBarOption.text + = QString("%1 %2").arg(name).arg(QString::number(progress, 'f', 2) + "%"); + progressBarOption.textVisible = true; + progressBarOption.textAlignment = Qt::AlignCenter; + + QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, + painter); + } + } + else { + QStyledItemDelegate::paint(painter, option, index); + } + } +}; + VariableInspectorWidget::VariableInspectorWidget(QWidget *parent) - : QWidget{parent}, ui{new Ui::VariableInspectorWidget} + : QWidget{parent}, + ui{new Ui::VariableInspectorWidget}, + m_ProgressBarItemDelegate{new QProgressBarItemDelegate(this)} { ui->setupUi(this); @@ -30,6 +68,7 @@ VariableInspectorWidget::VariableInspectorWidget(QWidget *parent) SLOT(refresh())); ui->tableView->setSelectionModel(sqpApp->variableController().variableSelectionModel()); + ui->tableView->setItemDelegateForColumn(0, m_ProgressBarItemDelegate); // Fixes column sizes auto model = ui->tableView->model();