Files
qt5-legatus-legacy/Lts/Plugins/ExerciseManagement/Gui/ExerciseEdit/exm_dialog_model.cpp
T
2026-08-13 18:33:10 +02:00

316 lines
12 KiB
C++
Executable File

/**
* @RDE_HEADER@
* HMI Plugin for ExerciseManangement - Exercise Overview Dialog Model
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#include "exm_dialog_model.h"
#include <LtsUtilsCore/dds_vector.h>
#include <ExerciseManagement/exm_translation.h>
#include <QTimer>
namespace ExerciseManagement
{
//---------------------------------
// ExerciseManagementDialogModel
//---------------------------------
ExerciseManagementDialogModel::ExerciseManagementDialogModel(QObject *parent)
: LtsWidgets::LtsAbstractTableModel<ExerciseManagement::Exercise>({tr("Id"),
tr("Name"),
tr("Training Area"),
tr("Begin"),
tr("End"),
tr("Started"),
tr("Stopped"),
tr("Status"),
tr("Radio Group"),
tr("Active Phase"),
tr("Created"),
tr("Time Zone"),
tr("Forces"),
tr("Description"),
tr("Linked Exercise"),
tr("Transferred"),
tr("HLA"),
tr("Image")},
parent)
, m_exmDtc(nullptr)
, m_asmDtc(nullptr)
, m_pdmDtc(nullptr)
, m_logger(getLogger("ExerciseManagementDialogModel"))
{}
bool ExerciseManagementDialogModel::initModel(const std::shared_ptr<ExerciseManagement::Interface::Dtc> &dtc,
const std::shared_ptr<ExerciseManagement::Interface::Ftc> &ftc,
const std::shared_ptr<AssetManagement::Interface::Dtc> &asmDtc,
const std::shared_ptr<ProjectDataManagement::Interface::Dtc> &pdmDtc,
bool addAdminExercise,
bool preloadExerciseImages)
{
m_exmDtc = dtc;
m_exmFtc = ftc;
m_asmDtc = asmDtc;
m_pdmDtc = pdmDtc;
connect(m_exmDtc.get(), &ExerciseManagement::Interface::Dtc::exerciseChanged,
this, [this, preloadExerciseImages](const ExerciseManagement::Exercise &ex, DataModification mod)
{
onDataChanged(ex, mod);
if (mod != DataModification::eAdded)
return;
if (preloadExerciseImages)
addImagePreload(ex.id());
});
if (addAdminExercise)
{
// insert admin session manually
ExerciseManagement::Exercise adminExercise;
adminExercise.name(tr("Superordinate Config / Administration").toStdString());
adminExercise.id(0);
insertRow(adminExercise);
}
// insert Model
m_exmDtc->exercises([this, preloadExerciseImages](const ExerciseManagement::Exercise &ex)
{
insertRow(ex);
if (preloadExerciseImages)
addImagePreload(ex.id());
});
INFO_LOG(m_logger) << "initModel - #exercises: " << m_vecData.size();
return true;
}
int ExerciseManagementDialogModel::getId(const ExerciseManagement::Exercise &data) const
{
return data.id();
}
void ExerciseManagementDialogModel::addImagePreload(int32_t exId) // one image at a time - only fetch next image if last one already received
{
if (m_exerciseImages.contains(exId)) // don't preload mages that are already loaded
return;
m_preloadImages += exId;
if (m_imagePreloadPending) // only start preloading if not currently preloading one currently
return;
m_imagePreloadPending = true;
preloadNextImage();
}
void ExerciseManagementDialogModel::preloadNextImage()
{
if (m_preloadImages.isEmpty())
return;
m_exmFtc->enableGetExerciseImage();
m_exmFtc->getExerciseImageRequest(GetExerciseImageRequest(m_preloadImages.takeFirst(), m_imageSize.height(), m_imageSize.width(), false),
createGetExerciseImageRequester());
}
GetExerciseImageRequester *ExerciseManagementDialogModel::createGetExerciseImageRequester()
{
auto r = GetExerciseImageRequester::createGetExerciseImageRequester();
connect(r, &GetExerciseImageRequester::signalDone,
this, [this, r]()
{
m_imagePreloadPending = false;
const GetExerciseImageReply &reply(r->reply());
if (reply.errorString().empty())
{
m_exerciseImages.insert(reply.id(), LtsUtils::toQByteArray(reply.imageData()));
// tell the view that it should reload the image
QModelIndex idx(findIndexForId(reply.id(), 0)); // XXX: Florian's Workaround - dataChanged works with column 0, but not with Columns::Image! Works for now! Better than resetting the model.
emit dataChanged(idx, idx, { Qt::DisplayRole });
}
else
{
QString msg(QString::fromStdString(reply.errorString()));
for (const std::string &arg : qAsConst(reply.errorParams()))
msg = msg.arg(QString::fromStdString(arg));
ERROR_LOG(m_logger) << "image preload failed: " << msg;
}
QTimer::singleShot(1, this, &ExerciseManagementDialogModel::preloadNextImage); // schedule requester deletion before asking for the next image (not really necessary but 100 times cleaner)
});
return r;
}
void ExerciseManagementDialogModel::setImageSizeConstraints(const QSize &size)
{
m_imageSize = size;
}
QVariant ExerciseManagementDialogModel::data(const QModelIndex &index, int role) const
{
if ((role != Qt::DisplayRole && role != Qt::UserRole && role != Qt::TextColorRole) || !indexIsValid(index))
return QVariant();
const ExerciseManagement::Exercise &ex = m_vecData.at(index.row());
if (role == Qt::DisplayRole)
{
switch (index.column())
{
case ExerciseManagementDialogModel::Columns::Name:
return QString::fromStdString(ex.name());
case ExerciseManagementDialogModel::Columns::TrainingArea:
{
const AssetManagement::TrainingArea ta = m_asmDtc->trainingArea(ex.trainingAreaId());
return QString::fromStdString(ta.name());
}
case ExerciseManagementDialogModel::Columns::Begin:
return QDateTime::fromMSecsSinceEpoch(ex.beginTime());
case ExerciseManagementDialogModel::Columns::End:
return QDateTime::fromMSecsSinceEpoch(ex.endTime());
case ExerciseManagementDialogModel::Columns::Started:
return QDateTime::fromMSecsSinceEpoch(ex.startTime());
case ExerciseManagementDialogModel::Columns::Stopped:
return QDateTime::fromMSecsSinceEpoch(ex.stopTime());
case ExerciseManagementDialogModel::Columns::Status:
return ExerciseManagement::toString(ex.state());
case ExerciseManagementDialogModel::Columns::RadioGroup:
if (ex.radioGroupId().is_set())
return m_pdmDtc->trRadioGroupName(ex.radioGroupId().get());
return QStringLiteral(" - ");
case ExerciseManagementDialogModel::Columns::ActivePhase:
return QString::fromStdString(m_exmDtc->exercisePhase(ex.activePhaseId()).name());
case ExerciseManagementDialogModel::Columns::Created:
return QDateTime::fromMSecsSinceEpoch(ex.created());
case ExerciseManagementDialogModel::Columns::TimeZone:
return (ex.defaultTimeZone() == 0) ? QStringLiteral("-") : QString(QLatin1Char(ex.defaultTimeZone()));
case ExerciseManagementDialogModel::Columns::Forces:
return QString::fromStdString(ex.forces());
case ExerciseManagementDialogModel::Columns::Description:
return QString::fromStdString(ex.description());
case ExerciseManagementDialogModel::Columns::Image:
return m_exerciseImages.value(ex.id());
case ExerciseManagementDialogModel::Columns::Id:
return ex.id();
case ExerciseManagementDialogModel::Columns::LinkedId:
{
if (ex.linkedExerciseId() == 0)
return QVariant();
const int row = findRowForId(ex.linkedExerciseId());
if (row < 0)
return QStringLiteral("????? - %1").arg(ex.linkedExerciseId());
return QString(QString::fromStdString(m_vecData.at(row).name()) +
QStringLiteral(" (%1)").arg(ex.linkedExerciseId()));
}
case ExerciseManagementDialogModel::Columns::Transferred:
return ex.transferred() ? tr("Yes") : tr("No");
case ExerciseManagementDialogModel::Columns::HasHlaInterface:
return ex.hasHlaInterface() ? tr("Yes") : tr("No");
}
}
else if (role == Qt::UserRole) // sorting order
{
if (ex.id() == 0)
return 0;
switch (ex.state().underlying())
{
case ExerciseState::Unknown: return 6;
case ExerciseState::Created: return 3;
case ExerciseState::Started: return 1;
case ExerciseState::Paused: return 2;
case ExerciseState::Stopped: return 4;
case ExerciseState::Terminated: return 5;
}
return 99;
}
else if (role == Qt::TextColorRole)
{
if (index.column() == ExerciseManagementDialogModel::Columns::Status)
{
switch (ex.state().underlying())
{
case ExerciseState::Unknown: return QColor(Qt::black);
case ExerciseState::Created: return QColor(Qt::cyan);
case ExerciseState::Started: return QColor(Qt::darkGreen);
case ExerciseState::Paused: return QColor(Qt::darkYellow);
case ExerciseState::Stopped: return QColor(Qt::magenta);
case ExerciseState::Terminated: return QColor(Qt::red);
}
}
}
return QVariant();
}
//
// ExerciseManagementProxyModel
//
void ExerciseManagementProxyModel::setAdminExerciseVisible(bool bAdminVisible)
{
if (m_bAdminVisible == bAdminVisible)
return;
m_bAdminVisible = bAdminVisible;
invalidateFilter();
}
void ExerciseManagementProxyModel::setVisibleExerciseIds(const QVector<int> &exIds)
{
if (m_exIds == exIds)
return;
m_exIds = exIds;
invalidateFilter();
}
void ExerciseManagementProxyModel::setVisibleExerciseStates(const QVector<ExerciseState> &visibleStates)
{
if (m_visibleStates == visibleStates)
return;
m_visibleStates = visibleStates;
invalidateFilter();
}
void ExerciseManagementProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
{
m_sourceModel = qobject_cast<ExerciseManagementDialogModel*>(sourceModel);
LtsWidgets::LtsColumnFilterProxyModel::setSourceModel(sourceModel);
}
bool ExerciseManagementProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{
if (!m_sourceModel || source_parent.isValid() || source_row < 0 || source_row >= m_sourceModel->m_vecData.size())
return LtsWidgets::LtsColumnFilterProxyModel::filterAcceptsRow(source_row, source_parent);
const auto &ex = m_sourceModel->m_vecData.at(source_row);
if (ex.id() == 0)
{
if (!m_bAdminVisible)
return false;
return LtsWidgets::LtsColumnFilterProxyModel::filterAcceptsRow(source_row, source_parent);
}
if (!m_exIds.contains(ex.id()) && !m_exIds.contains(-1))
return false;
if (!m_visibleStates.contains(ex.state()) && !m_visibleStates.isEmpty())
return false;
return LtsWidgets::LtsColumnFilterProxyModel::filterAcceptsRow(source_row, source_parent);
}
} // namespace ExerciseManagement