Initial commit

This commit is contained in:
torsten committed 2026-08-13 18:33:10 +02:00
commit b7d90b9afe
16245 files changed
+3396666

No files matched your search

@@ -0,0 +1,439 @@
/**
* @RDE_HEADER@
* HMI Plugin for OperatorManangement - Operator Overview Dialog Model
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#include "charge_table_model.h"
#include <QIcon>
#include <QJsonObject>
#include <QJsonDocument>
namespace ProjectDataManagement
{
const QVector<int> ChargeTableDialogModel::ALL_ULEIS = {ChargeTableDialogModel::DirectImpactGrandparent,
ChargeTableDialogModel::DirectImpactChild,
ChargeTableDialogModel::BurstOfFireParent,
ChargeTableDialogModel::BurstOfFireChild,
ChargeTableDialogModel::AirBurstParent,
ChargeTableDialogModel::AirBurstChild,
ChargeTableDialogModel::UnarmedParent,
ChargeTableDialogModel::UnarmedChild,
ChargeTableDialogModel::FireAndForgetParent,
ChargeTableDialogModel::FireAndForgetChild,
ChargeTableDialogModel::ShortTimeScanningParent,
ChargeTableDialogModel::ShortTimeScanningChild };
const QVector<int> ChargeTableDialogModel::ALL_TAS = {ChargeTableDialogModel::ShortTimeChild1,
ChargeTableDialogModel::ShortTimeChild2,
ChargeTableDialogModel::ShortTimeChild3,
ChargeTableDialogModel::ShortTimeChild4,
ChargeTableDialogModel::ShortTimeChild5 };
//---------------------------------
// ChargeTableDialogModel
//---------------------------------
ChargeTableDialogModel::ChargeTableDialogModel(bool isOrganiser, QObject *parent )
: LtsWidgets::LtsAbstractTableModel<ProjectDataManagement::ChargeType>({tr("Id"),
tr("Is Visible"),
tr("Predefined Name"),
tr("Short Name"),
tr("Long Name"),
tr("Direct Impact"),
tr("Top Attack"),
tr("Burst of Fire"),
tr("Air Burst"),
tr("Unarmed"),
tr("Short Time"),
tr("Fire-and-Forget"),
tr("Short-Time Scanning"),
tr("DIS Entity")},
parent)
, m_dtc(nullptr)
, m_isOrganiser(isOrganiser)
, m_logger(getLogger("ChargeTableDialogModel"))
{}
ChargeTableDialogModel::~ChargeTableDialogModel()
{}
bool ChargeTableDialogModel::initModel(const std::shared_ptr<ProjectDataManagement::Interface::Dtc> &dtc, const QSet<GearClass> &gearClasses)
{
m_dtc = dtc;
m_gearClasses = gearClasses;
connect(m_dtc.get(), &ProjectDataManagement::Interface::Dtc::chargeTypeChanged,
this, &ChargeTableDialogModel::onDataChanged);
m_dtc->chargeTypes([this](const ProjectDataManagement::ChargeType &ct)
{
if (!m_isOrganiser && !m_dtc->isVisible(ct.id()))
return;
insertRow(ct);
if (m_isOrganiser && m_dtc->isVisible(ct.id()))
m_visibleCharges.insert(ct.id());
});
return true;
}
QVariant ChargeTableDialogModel::data(const QModelIndex &index, int role) const
{
if (!indexIsValid(index))
return QVariant();
const ProjectDataManagement::ChargeType &ct = m_vecData.at(index.row());
// if (role == Qt::DecorationRole && index.column() == PredefinedName)
// return QIcon(QLatin1String(":/style/mortar_ammunition_administration.svg"));
if (role == Qt::CheckStateRole)
{
// CheckBoxes only for columns that are actually checkable
if (!flags(index).testFlag(Qt::ItemIsUserCheckable))
return QVariant();
// Organiser:
if (m_isOrganiser)
{
if (index.column() == IsVisible)
return (m_visibleCharges.contains(ct.id()) ? Qt::Checked : Qt::Unchecked);
return QVariant();
}
// Non Organiser:
qint32 tasCode = ct.id();
// TAS Codes < 2000 -> One Column fits all
if (tasCode < 2000)
{
if (index.column() == IsVisible)
return m_visibleCharges.contains(ct.id()) ? Qt::Checked : Qt::Unchecked;
// TAS Codes 1-46 exept 25 and 30 use cols DI, TA, BF, AB:
if (tasCode >= 1 && tasCode <= 46 && tasCode != 25 && tasCode != 30)
if (index.column() != DirectImpact &&
index.column() != TopAttack &&
index.column() != BurstOfFire &&
index.column() != AirBurst)
return QVariant();
// TAS Codes 25 and 30 are for FF charges:
if (tasCode == 25 || tasCode == 30)
if (index.column() != FireAndForget)
return QVariant();
// TAS Codes 77-79 are for SS charges
if (tasCode >= 77 && tasCode <=79)
if (index.column() != ShortTimeScanning)
return QVariant();
// TAS Codes 47-74 and 15xx, 16xx, 17xx, 18xx and 19xx (xx = 47-74) are ST charges
// Note: Not ommitting e.g. 13xx!
if (tasCode % 100 >= 47 && tasCode % 100 <= 76)
if (index.column() != ShortTime)
return QVariant();
// Now that all columns not relevant for charge do NOT show any CheckBoxes,
// we fill the remaining columns with synchronized checked CheckBoxes.
return m_visibleCharges.contains(ct.id()) ? Qt::Checked : Qt::Unchecked;
}
// TAS Codes > 2000
if (index.column() == IsVisible)
{
// Parent / Child are treated identically
// Direct Hit / Top Attack is the same kind
int sum = 0;
if (m_visibleCharges.contains(tasCode + DirectImpactGrandparent) || m_visibleCharges.contains(tasCode + DirectImpactChild))
++sum;
if (m_visibleCharges.contains(tasCode + BurstOfFireParent) || m_visibleCharges.contains(tasCode + BurstOfFireChild))
++sum;
if (m_visibleCharges.contains(tasCode + AirBurstParent) || m_visibleCharges.contains(tasCode + AirBurstChild))
++sum;
if (m_visibleCharges.contains(tasCode + UnarmedParent) || m_visibleCharges.contains(tasCode + UnarmedChild))
++sum;
if (m_visibleCharges.contains(tasCode + FireAndForgetParent) || m_visibleCharges.contains(tasCode + FireAndForgetChild))
++sum;
if (m_visibleCharges.contains(tasCode + ShortTimeScanningParent) || m_visibleCharges.contains(tasCode + ShortTimeScanningChild))
++sum;
// Check if all / nothing / intermediate is checked and set CheckBox accordingly:
if (sum == 0)
return Qt::Unchecked;
if (sum == 6)
return Qt::Checked;
return Qt::PartiallyChecked;
}
// Now to the single CheckBoxes:
// Direct Impact and Top Attack are treated identically:
// Do not distinguish unless Offset differs.
if (index.column() == DirectImpact || index.column() == TopAttack)
return (m_visibleCharges.contains(tasCode + DirectImpactGrandparent) || m_visibleCharges.contains(tasCode + DirectImpactChild) ? Qt::Checked : Qt::Unchecked);
if (index.column() == BurstOfFire)
return (m_visibleCharges.contains(tasCode + BurstOfFireParent) || m_visibleCharges.contains(tasCode + BurstOfFireChild) ? Qt::Checked : Qt::Unchecked);
if (index.column() == AirBurst)
return (m_visibleCharges.contains(tasCode + AirBurstParent) || m_visibleCharges.contains(tasCode + AirBurstChild) ? Qt::Checked : Qt::Unchecked);
if (index.column() == Unarmed)
return (m_visibleCharges.contains(tasCode + UnarmedParent) || m_visibleCharges.contains(tasCode + UnarmedChild) ? Qt::Checked : Qt::Unchecked);
if (index.column() == FireAndForget)
return (m_visibleCharges.contains(tasCode + FireAndForgetParent) || m_visibleCharges.contains(tasCode + FireAndForgetChild) ? Qt::Checked : Qt::Unchecked);
if (index.column() == ShortTimeScanning)
return (m_visibleCharges.contains(tasCode + ShortTimeScanningParent) || m_visibleCharges.contains(tasCode + ShortTimeScanning) ? Qt::Checked : Qt::Unchecked);
}
if (role == Qt::DisplayRole)
{
switch (index.column())
{
case IsVisible:
if (m_isOrganiser)
return m_dtc->isVisible(ct.id()) ? tr("Yes") : tr("No");
else
return ct.id();
case Id:
return QString::number(ct.id());
case PredefinedName:
return QString::fromStdString(ct.predefinedName());
case ShortName:
return QString::fromStdString(ct.shortName());
case LongName:
return QString::fromStdString(ct.name());
case DisEntity:
return QString::fromStdString(ct.disEntity());
}
}
return QVariant();
}
bool ChargeTableDialogModel::setData(const QModelIndex &idx, const QVariant &value, int role)
{
if (!indexIsValid(idx))
return false;
if (role != Qt::CheckStateRole)
return false;
bool bVal = value.toBool();
if (m_isOrganiser)
{
if (idx.column() != IsVisible)
return false;
// Get JSON Properties
ChargeType ct = getRowData(idx.row());
QJsonDocument propsDoc = QJsonDocument::fromJson(QByteArray::fromStdString(ct.properties()));
QJsonObject propsObj;
if (propsDoc.isObject()) // if the given properties are no valid JSON object, the properties will be made from scratch
propsObj = propsDoc.object();
// Update JSON Properties
if (bVal)
{
propsObj.remove(QLatin1String("suppressVisibility"));
m_visibleCharges.insert(m_vecData.at(idx.row()).id());
}
else
{
propsObj.insert(QLatin1String("suppressVisibility"), true);
m_visibleCharges.remove(m_vecData.at(idx.row()).id());
}
// Put back JSON Properties
ct.properties(QJsonDocument(propsObj).toJson(QJsonDocument::Compact).toStdString());
setRowData(idx.row(), ct);
if (m_dtc->isVisible(ct.id()) != bVal)
m_differences.insert(ct.id());
else
m_differences.remove(ct.id());
emit chargeVisibilityChanged(!m_differences.isEmpty());
return true;
}
else
{
const int tasCode = m_vecData.at(idx.row()).id();
if (tasCode < 1000)
{
if (bVal)
m_visibleCharges.insert(tasCode);
else
m_visibleCharges.remove(tasCode);
// Grandparents 47 - 76 have Children that are implicitly checked:
if (tasCode >= 47 && tasCode <= 76)
{
if (bVal)
{
for (const auto &type : ALL_TAS)
m_visibleCharges.insert(type + tasCode);
}
else
{
for (const auto &type : ALL_TAS)
m_visibleCharges.remove(type + tasCode);
}
}
}
else if (tasCode > 2000)
{
if (bVal)
{
// Check all Types
if (idx.column() == IsVisible)
{
for (const auto &type : ALL_ULEIS)
m_visibleCharges.insert(tasCode + type);
}
// For each type check both uleis codes:
if (idx.column() == DirectImpact)
{
m_visibleCharges.insert(tasCode + DirectImpactGrandparent);
m_visibleCharges.insert(tasCode + DirectImpactChild);
}
if (idx.column() == TopAttack)
{
m_visibleCharges.insert(tasCode + TopAttackGrandparent);
m_visibleCharges.insert(tasCode + TopAttackChild);
}
if (idx.column() == BurstOfFire)
{
m_visibleCharges.insert(tasCode + BurstOfFireParent);
m_visibleCharges.insert(tasCode + BurstOfFireChild);
}
if (idx.column() == AirBurst)
{
m_visibleCharges.insert(tasCode + AirBurstParent);
m_visibleCharges.insert(tasCode + AirBurstChild);
}
if (idx.column() == Unarmed)
{
m_visibleCharges.insert(tasCode + UnarmedParent);
m_visibleCharges.insert(tasCode + UnarmedChild);
}
if (idx.column() == FireAndForget)
{
m_visibleCharges.insert(tasCode + FireAndForgetParent);
m_visibleCharges.insert(tasCode + FireAndForgetChild);
}
if (idx.column() == ShortTimeScanning)
{
m_visibleCharges.insert(tasCode + ShortTimeScanningParent);
m_visibleCharges.insert(tasCode + ShortTimeScanningChild);
}
}
else
{
// Uncheck all types
if (idx.column() == IsVisible)
{
for (const auto &type : ALL_ULEIS)
m_visibleCharges.remove(tasCode + type);
}
// For each type uncheck both uleis codes:
if (idx.column() == DirectImpact)
{
m_visibleCharges.remove(tasCode + DirectImpactGrandparent);
m_visibleCharges.remove(tasCode + DirectImpactChild);
}
if (idx.column() == TopAttack)
{
m_visibleCharges.remove(tasCode + TopAttackGrandparent);
m_visibleCharges.remove(tasCode + TopAttackChild);
}
if (idx.column() == BurstOfFire)
{
m_visibleCharges.remove(tasCode + BurstOfFireParent);
m_visibleCharges.remove(tasCode + BurstOfFireChild);
}
if (idx.column() == AirBurst)
{
m_visibleCharges.remove(tasCode + AirBurstParent);
m_visibleCharges.remove(tasCode + AirBurstChild);
}
if (idx.column() == Unarmed)
{
m_visibleCharges.remove(tasCode + UnarmedParent);
m_visibleCharges.remove(tasCode + UnarmedChild);
}
if (idx.column() == FireAndForget)
{
m_visibleCharges.remove(tasCode + FireAndForgetParent);
m_visibleCharges.remove(tasCode + FireAndForgetChild);
}
if (idx.column() == ShortTimeScanning)
{
m_visibleCharges.remove(tasCode + ShortTimeScanningParent);
m_visibleCharges.remove(tasCode + ShortTimeScanningChild);
}
}
}
else
{
// Tas Code == 1000 - 2000: Do nothing, they are invalid...
}
emit dataChanged(index(idx.row(), 0), index(idx.row(), columnCount() - 1));
return true;
}
return false;
}
QVector<ChargeType> ChargeTableDialogModel::getChargeTypesWithChangedVisibility() const
{
QVector<ChargeType> cts;
for (const auto &ct : m_vecData)
if (m_differences.contains(ct.id()))
cts << ct;
return cts;
}
bool ChargeTableDialogModel::isFiltered(int chargeTypeId) const
{
// Filter anything?
if (m_isOrganiser)
return false;
if (!m_gearClasses.contains(m_dtc->gearClassFromChargeTypeId(baseCharge(chargeTypeId))))
return true;
return !isBaseCharge(chargeTypeId);
}
bool ChargeTableDialogModel::isFiltered(const ProjectDataManagement::ChargeType &data, DataModification modType) const
{
Q_UNUSED(modType);
return isFiltered(data.id());
}
QSet<int> ChargeTableDialogModel::selectedCharges() const
{
return m_visibleCharges;
}
int ChargeTableDialogModel::baseCharge(int chargeTypeId)
{
if (isBaseCharge(chargeTypeId))
return chargeTypeId;
if (chargeTypeId < 2000)
return (chargeTypeId % 100);
return ((chargeTypeId % 1000) + 2000);
}
} // namespace ProjectDataManagement