569 lines
15 KiB
C++
Executable File
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
|