316 lines
12 KiB
C++
Executable File
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
|