Files
qt5-legatus-legacy/Lts/Plugins/AudioVideoManagement/Gui/Eloka/avm_eloka_edit_dialog.cpp
T
2026-08-13 18:33:10 +02:00

569 lines
15 KiB
C++
Executable File

/**
* @RDE_HEADER@
* The ElokaEditDialog adds and updates electronic warfare
* $Id$
* $HeadURL$
* $Author$
* Created by Astrid Mueller, SGAS, 2017-10-17
*/
#include <LtsSession/lts_session_data.h>
#include "avm_eloka_edit_dialog.h"
#include "ui_avm_eloka_edit_dialog.h"
#include <AudioVideoManagement/ava_session.h>
#include <AudioVideoManagement/ava_control.h>
#include <AudioVideoManagement/stream_name_mapping.h>
#include <boost/optional.hpp>
namespace
{
/**
* Used as UserData for the entries in cmbCircuit.
*/
struct ComboBoxUserData
{
QString internalName; // the text itself in the ComboBox is the displayName
AudioVideoManagement::ElokaCircuitType circuitType;
int id;
};
ComboBoxUserData userDataAt(QComboBox *cb, int index)
{
Q_ASSERT(cb);
Q_ASSERT(index >= 0 && index < cb->count());
QVariant userData = cb->itemData(index);
Q_ASSERT(userData.canConvert<ComboBoxUserData>());
return userData.value<ComboBoxUserData>();
}
ComboBoxUserData currentUserData(QComboBox* cb)
{
Q_ASSERT(cb);
return userDataAt(cb, cb->currentIndex());
}
/**
* Get the id of the currently selected item in the ComboBox.
* @return boost::none if there is no item selected or its type does not match circuitType
*/
boost::optional<int> currentId(QComboBox *comboBox, AudioVideoManagement::ElokaCircuitType circuitType)
{
Q_ASSERT(comboBox);
int selectedIndex = comboBox->currentIndex();
if (selectedIndex == -1)
return boost::none;
QVariant userData_ = comboBox->itemData(selectedIndex);
Q_ASSERT(userData_.canConvert<ComboBoxUserData>());
ComboBoxUserData userData = userData_.value<ComboBoxUserData>();
if (userData.circuitType != circuitType)
return boost::none;
return userData.id;
}
/**
* Try to select the item with the given id.
* If no id is given or the item is not available for selection the first item is selected.
*/
void selectItemWithId(QComboBox *comboBox, boost::optional<int> id)
{
Q_ASSERT(comboBox);
if (comboBox->count() == 0)
return;
if (!id.is_initialized())
{
comboBox->setCurrentIndex(0);
return;
}
for (int i = 0; i < comboBox->count(); ++i)
{
QVariant userData_ = comboBox->itemData(i);
Q_ASSERT(userData_.canConvert<ComboBoxUserData>());
ComboBoxUserData userData = userData_.value<ComboBoxUserData>();
if (userData.id == *id)
{
comboBox->setCurrentIndex(i);
return;
}
}
comboBox->setCurrentIndex(0);
}
} // anonymous namespace
// in order to use it with QVariant
Q_DECLARE_METATYPE(ComboBoxUserData)
namespace AudioVideoManagement
{
ElokaEditDialog::ElokaEditDialog(LtsSession::LtsSession *session, AvaSession *avaSession, Interface::Dtc *avmDtc, StreamNameMapping *streamNameMapping,
const ElokaData &data, QWidget *parent)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
, m_ui(new Ui::ElokaEditDialog)
, m_session(session)
, m_streamNameMapping(streamNameMapping)
, m_avaCtrl(avaSession->control())
, m_avmDtc(avmDtc)
, m_elokaData(data)
, m_cnrConfigMap()
, m_tvcConfigMap()
, m_announcementMap()
, m_userProfile()
, m_logger(getLogger("ElokaEditDialog"))
{
Q_ASSERT(session);
Q_ASSERT(avaSession);
Q_ASSERT(streamNameMapping);
Q_ASSERT(avmDtc);
m_ui->setupUi(this);
m_uiRequirements->addRequirement( { m_ui->lbAction, [this]() { return !m_ui->cmbAction->currentText().isEmpty(); } });
m_uiRequirements->addRequirement( { m_ui->lbCircuit, [this]() { return !m_ui->cmbCircuit->currentText().isEmpty(); } });
setOnlineHelpFilename(QStringLiteral("Situation-Electronic_Warfare_Measures"));
}
ElokaEditDialog::~ElokaEditDialog()
{
delete m_ui;
}
void ElokaEditDialog::retranslate()
{
bool isNew = true;
if (!m_elokaData.internalName.isEmpty())
isNew = false;
translate(m_ui, QString(), isNew, tr("Eloka"));
}
bool ElokaEditDialog::init(const std::vector<qint32> &usedCnr,
const std::vector<qint32> &usedTvc,
const std::vector<qint32> &usedAnnouncement)
{
setUnchangeable(true);
#ifndef LTS_DEBUG
m_ui->rbTvc->hide();
#endif
// get the user profile of the accessible radio circuits
getUserProfile();
// get all CNR's
getActiveCnrs();
// new CNR
if (m_elokaData.internalName.isEmpty())
{
for (int used : usedCnr)
m_cnrConfigMap.remove(used);
}
else // edit CNR
{
m_cnrConfigMap.remove(m_elokaData.id);
}
// get all TVC's
m_tvcConfigMap = m_avmDtc->tvcConfigs();
// new TVC
if (m_elokaData.internalName.isEmpty())
{
for (int used : usedTvc)
m_tvcConfigMap.remove(used);
}
else // edit TVC
{
m_tvcConfigMap.remove(m_elokaData.id);
}
// get all Announcements
const QMap<qint32, Stream> streams = m_avmDtc->streams();
for (const Stream &stream : streams)
{
if ((stream.type() == StreamType_def::AudioOut) ||
(stream.type() == StreamType_def::AudioInOut))
m_announcementMap.insert(stream.id(), stream);
}
// new announcement
if (m_elokaData.internalName.isEmpty())
{
for (int used : usedAnnouncement)
m_announcementMap.remove(used);
}
else // edit announcement
{
m_announcementMap.remove(m_elokaData.id);
}
connect(m_avmDtc,
&AudioVideoManagement::Interface::Dtc::cnrConfigChanged,
this, &ElokaEditDialog::onCnrConfigChanged);
connect(m_avmDtc,
&AudioVideoManagement::Interface::Dtc::tvcConfigChanged,
this, &ElokaEditDialog::onTvcConfigChanged);
connect(m_avmDtc,
&AudioVideoManagement::Interface::Dtc::cnrTvcProfileChanged,
this, &ElokaEditDialog::onCnrTvcProfileChanged);
connect(m_avmDtc,
&AudioVideoManagement::Interface::Dtc::streamChanged,
this, &ElokaEditDialog::onStreamChanged);
connect(m_ui->cmbCircuit,
QOverload<int>::of(&LtsWidgets::LtsComboBox::currentIndexChanged),
this, &ElokaEditDialog::onCmbCircuitChanged);
connect(m_ui->rbCnr, &QRadioButton::toggled,
this, &ElokaEditDialog::onCbCnrToggled);
connect(m_ui->rbAnnouncement, &QRadioButton::toggled,
this, &ElokaEditDialog::onCbAnnouncementToggled);
connect(m_ui->rbTvc, &QRadioButton::toggled,
this, &ElokaEditDialog::onCbTvcToggled);
connect(m_avaCtrl, &AvaControl::getElokaListResponse,
this, &ElokaEditDialog::onGetElokaListResponse);
if (m_elokaData.internalName.isEmpty())
{
// get as default CNR
checkedRadioButtons(true, false, false);
enabledRadioButtons(true, true, true);
}
else
{
if (m_elokaData.circuitType == ElokaCircuitType::Cnr)
{
checkedRadioButtons(true, false, false);
enabledRadioButtons(true, false, false);
}
if (m_elokaData.circuitType == ElokaCircuitType::Tvc)
{
checkedRadioButtons(false, true, false);
enabledRadioButtons(false, true, false);
}
if (m_elokaData.circuitType == ElokaCircuitType::Announcement)
{
checkedRadioButtons(false, false, true);
enabledRadioButtons(false, false, true);
}
if (m_elokaData.mode == AvaElokaMode::EndlessLoop)
m_ui->chbEndlessPlayback->setChecked(true);
setCurrentCircuit(m_elokaData);
m_ui->cmbAction->setCurrentText(m_elokaData.action);
}
setUnchangeable(false);
return true;
}
void ElokaEditDialog::checkedRadioButtons(bool cnr, bool tvc, bool announcement)
{
m_ui->rbCnr->setChecked(cnr);
m_ui->rbTvc->setChecked(tvc);
m_ui->rbAnnouncement->setChecked(announcement);
}
void ElokaEditDialog::enabledRadioButtons(bool cnr, bool tvc, bool announcement)
{
m_ui->rbCnr->setEnabled(cnr);
m_ui->rbTvc->setEnabled(tvc);
m_ui->rbAnnouncement->setEnabled(announcement);
}
void ElokaEditDialog::onCmbCircuitChanged(int index)
{
Q_UNUSED(index);
m_ui->cmbAction->clear();
if (m_ui->cmbCircuit->currentText().isEmpty())
return;
// get Actions from AVS Workstation
ComboBoxUserData userData = currentUserData(m_ui->cmbCircuit);
m_avaCtrl->getElokaList(userData.internalName);
}
bool ElokaEditDialog::apply()
{
ComboBoxUserData userData = currentUserData(m_ui->cmbCircuit);
ElokaData data;
data.id = userData.id;
data.internalName = userData.internalName;
data.displayName = m_ui->cmbCircuit->currentText();
data.party = -1;
data.exerciseId = m_session->exerciseId();
data.circuitType = userData.circuitType;
data.action = m_ui->cmbAction->currentText();
data.mode = m_ui->chbEndlessPlayback->isChecked() ? AvaElokaMode::EndlessLoop : AvaElokaMode::Once;
data.startTime = m_session->partitionTime();
if (userData.circuitType == ElokaCircuitType::Cnr)
data.party = m_cnrConfigMap.value(userData.id).partyId();
if (m_elokaData.internalName.isEmpty())
m_avaCtrl->chooseEloka(data.internalName, data.action, data.mode);
else if (m_elokaData.action != data.action)
{
m_avaCtrl->releaseEloka(m_elokaData.internalName);
m_avaCtrl->chooseEloka(data.internalName, data.action, data.mode);
}
m_elokaData = data;
emit signalNewEloka(data);
return true;
}
void ElokaEditDialog::onCbCnrToggled(bool checked)
{
if (!checked)
return;
fillComboBoxCircuit(ElokaCircuitType::Cnr);
}
void ElokaEditDialog::onCbAnnouncementToggled(bool checked)
{
if (!checked)
return;
fillComboBoxCircuit(ElokaCircuitType::Announcement);
}
void ElokaEditDialog::onCbTvcToggled(bool checked)
{
if (!checked)
return;
fillComboBoxCircuit(ElokaCircuitType::Tvc);
}
void ElokaEditDialog::getActiveCnrs()
{
const QMap<qint32, CnrConfig> cnrs = m_avmDtc->cnrConfigs();
for (const CnrConfig &cnr : cnrs)
{
if (cnr.isActive() == true)
m_cnrConfigMap.insert(cnr.id(), cnr);
}
}
void ElokaEditDialog::onCnrConfigChanged(const CnrConfig &data,
DataModification modType)
{
DEBUG_LOG(m_logger) << "onCnrConfigChanged";
switch (modType)
{
case DataModification::eAdded:
case DataModification::eModified:
{
m_cnrConfigMap.insert(data.id(), data);
break;
}
case DataModification::eRemoved:
{
m_cnrConfigMap.remove(data.id());
break;
}
} // end switch
if (m_ui->rbCnr->isChecked())
fillComboBoxCircuit(ElokaCircuitType::Cnr);
}
void ElokaEditDialog::onTvcConfigChanged(const TvcConfig &data,
DataModification modType)
{
DEBUG_LOG(m_logger) << "onTvcConfigChanged";
switch (modType)
{
case DataModification::eAdded:
case DataModification::eModified:
{
m_tvcConfigMap.insert(data.id(), data);
break;
}
case DataModification::eRemoved:
{
m_tvcConfigMap.remove(data.id());
break;
}
} // end switch
if (m_ui->rbTvc->isChecked())
fillComboBoxCircuit(ElokaCircuitType::Tvc);
}
void ElokaEditDialog::onStreamChanged(const Stream &data,
DataModification modType)
{
DEBUG_LOG(m_logger) << "onStreamChanged";
if ((data.type() != StreamType_def::AudioOut) &&
(data.type() != StreamType_def::AudioInOut))
return;
switch (modType)
{
case DataModification::eAdded:
case DataModification::eModified:
{
m_announcementMap.insert(data.id(), data);
break;
}
case DataModification::eRemoved:
{
m_announcementMap.remove(data.id());
break;
}
} // end switch
if (m_ui->rbAnnouncement->isChecked())
fillComboBoxCircuit(ElokaCircuitType::Announcement);
}
void ElokaEditDialog::onCnrTvcProfileChanged(const CnrTvcProfile &data,
DataModification modType)
{
Q_UNUSED(modType);
DEBUG_LOG(m_logger) << "onCnrTvcProfileChanged";
if (data.exerciseId() != m_session->exerciseId() ||
data.operatorId() != LtsSessionData::LtsSessionData::getInstance()->getOperatorId())
return;
getUserProfile();
if (m_ui->rbCnr->isChecked())
fillComboBoxCircuit(ElokaCircuitType::Cnr);
else if (m_ui->rbTvc->isChecked())
fillComboBoxCircuit(ElokaCircuitType::Tvc);
}
void ElokaEditDialog::getUserProfile()
{
m_userProfile.clear();
const QMap<qint32, AudioVideoManagement::CnrTvcProfile> cnrTvcProfiles = m_avmDtc->cnrTvcProfiles();
int operatorId = LtsSessionData::LtsSessionData::getInstance()->getOperatorId();
int exerciseId = m_session->exerciseId();
for (const auto &cnrTvcProfile : cnrTvcProfiles)
{
if (cnrTvcProfile.exerciseId() == exerciseId &&
cnrTvcProfile.operatorId() == operatorId)
{
for (const auto &cnrTvcProfileData : cnrTvcProfile.data())
if (cnrTvcProfileData.radioSystemId() == RadioSystem::inner_enum::Cnr)
m_userProfile.insert(cnrTvcProfileData.radioCircuitId(), ElokaCircuitType::Cnr);
else
m_userProfile.insert(cnrTvcProfileData.radioCircuitId(), ElokaCircuitType::Tvc);
break;
}
}
}
void ElokaEditDialog::fillComboBoxCircuit(ElokaCircuitType type)
{
boost::optional<int> selectedId = currentId(m_ui->cmbCircuit, type);
m_ui->cmbCircuit->clear();
switch (type)
{
case ElokaCircuitType::Cnr:
{
for (const CnrConfig &cnr : qAsConst(m_cnrConfigMap))
{
if (!m_userProfile.contains(cnr.id(), ElokaCircuitType::Cnr))
continue;
QString internalName = QString::fromStdString(cnr.radioCircuit());
QVariant userData = QVariant::fromValue(ComboBoxUserData{internalName, ElokaCircuitType::Cnr, cnr.id()});
m_ui->cmbCircuit->addItem(internalName, userData);
}
break;
}
case ElokaCircuitType::Tvc:
{
for (const TvcConfig &tvc : qAsConst(m_tvcConfigMap))
{
if (!m_userProfile.contains(tvc.id(), ElokaCircuitType::Tvc))
continue;
QString internalName = QString::fromStdString(tvc.radioCircuit());
QVariant userData = QVariant::fromValue(ComboBoxUserData{internalName, ElokaCircuitType::Tvc, tvc.id()});
m_ui->cmbCircuit->addItem(internalName, userData);
}
break;
}
case ElokaCircuitType::Announcement:
{
for (const Stream &stream : qAsConst(m_announcementMap))
{
QString internalName = QString::fromStdString(stream.name());
QString displayName = m_streamNameMapping->displayName(internalName);
QVariant userData = QVariant::fromValue(ComboBoxUserData{internalName, ElokaCircuitType::Announcement, stream.id()});
m_ui->cmbCircuit->addItem(displayName, userData);
}
break;
}
} // end switch
m_ui->cmbCircuit->model()->sort(0);
selectItemWithId(m_ui->cmbCircuit, selectedId);
}
void ElokaEditDialog::setCurrentCircuit(const ElokaData &data)
{
for (int i = 0; i < m_ui->cmbCircuit->count(); ++i)
{
ComboBoxUserData userData = userDataAt(m_ui->cmbCircuit, i);
if (userData.circuitType != data.circuitType)
continue;
if (userData.id != data.id)
continue;
m_ui->cmbCircuit->setCurrentIndex(i);
return;
}
Q_ASSERT(false);
}
void ElokaEditDialog::onGetElokaListResponse(const QVector<QString> &actions)
{
DEBUG_LOG(m_logger) << "onGetElokaListResponse";
if (!m_elokaData.internalName.isEmpty())
setUnchangeable(true);
m_ui->cmbAction->clear();
if (actions.isEmpty())
return;
for (const QString &action : actions)
m_ui->cmbAction->addItem(action);
if(m_elokaData.action.isEmpty() == false)
m_ui->cmbAction->setCurrentText(m_elokaData.action);
if (!m_elokaData.internalName.isEmpty())
setUnchangeable(false);
}
} // namespace AudioVideoManagement