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

441 lines
14 KiB
C++
Executable File

/**
* @RDE_HEADER@
* OperatorManagement - Operator Edit Dialog
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#include "audio_settings_dialog.h"
#include "ui_audio_settings_dialog.h"
#include "audio_settings_avail_streams_model.h"
#include "audio_settings_used_streams_model.h"
#include "audio_stream_type.h"
#include <LtsWidgets/lts_message_dialog.h>
#include <LtsSession/lts_session_data_dds.h>
#include <LtsSession/lts_session_data.h>
#include <AudioVideoManagement/avm_ftc_types.h>
namespace AudioVideoManagement
{
AudioSettingsDialog::AudioSettingsDialog(QWidget *parent)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
, m_ui(new Ui::AudioSettingsDialog)
, m_requestHelper(new LtsUtils::RequestHelper(this))
, m_logger(getLogger("AudioSettingsDialog"))
{
m_ui->setupUi(this);
setAttribute(Qt::WA_DeleteOnClose);
setOnlineHelpFilename(QStringLiteral("Situation-Voice_Communication_Access"));
}
AudioSettingsDialog::~AudioSettingsDialog()
{
delete m_ui;
}
bool AudioSettingsDialog::init(OperatorManagement::Interface::Dtc *opmDtc,
Interface::Dtc *avmDtc,
Interface::Ftc *avmFtc,
LtsSession::LtsSessionDataDds *session)
{
Q_ASSERT(opmDtc);
Q_ASSERT(avmDtc);
Q_ASSERT(avmFtc);
Q_ASSERT(session);
setUnchangeable(true);
m_session = session;
m_avmDtc = avmDtc;
m_avmFtc = avmFtc;
////////////
// Create Model
m_modelAvailable = new AvailStreamsModel(avmDtc, m_session->exerciseId(), this);
if (!m_modelAvailable->initModel())
return false;
m_filterAvailable = new AvailStreamsFilter(m_modelAvailable, this);
m_modelAllocated = new AllocatedStreamsModel(this);
connect(m_modelAvailable, &AvailStreamsModel::droppedStreamNames, this, &AudioSettingsDialog::onDroppedInAvailable); // Drag and Drop from allocated -> available
connect(m_modelAllocated, &AllocatedStreamsModel::droppedStreamNames, this, &AudioSettingsDialog::onDroppedInAllocated); // Drag and Drop from available -> allocated
connect(m_modelAvailable, &AvailStreamsModel::updateEntry, m_modelAllocated, &AllocatedStreamsModel::updateEntry);
connect(m_modelAvailable, &AvailStreamsModel::removeEntry, this, &AudioSettingsDialog::onEntryRemoved);
// Glue model and view together
m_ui->treeViewAvailable->setModel(m_filterAvailable);
m_ui->treeViewAvailable->expandAll();
m_ui->treeViewAllocated->setModel(m_modelAllocated);
// Operator Management to get Name from operator
connect(opmDtc, &OperatorManagement::Interface::Dtc::userChanged,
this, &AudioSettingsDialog::onOperatorChanged);
auto cbOperator = [this](const OperatorManagement::User & u)
{
onOperatorChanged(u, DataModification::eAdded);
};
opmDtc->users(cbOperator);
fillOperatorBox();
connect(m_avmDtc, &Interface::Dtc::cnrTvcProfileChanged,
this, &AudioSettingsDialog::onCnrTvcProfileChanged);
auto cbRadioCircuits = [this](const CnrTvcProfile & rc)
{
onCnrTvcProfileChanged(rc, DataModification::eAdded);
};
m_avmDtc->cnrTvcProfiles(cbRadioCircuits);
connect(m_ui->pushButtonUp, &QPushButton::clicked, this, &AudioSettingsDialog::onUpButtonClicked);
connect(m_ui->pushButtonDown, &QPushButton::clicked, this, &AudioSettingsDialog::onDownButtonClicked);
connect(m_ui->operatorComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &AudioSettingsDialog::onSelectionOperatorChanged);
connect(m_ui->treeViewAllocated->selectionModel(), &QItemSelectionModel::selectionChanged, this, &AudioSettingsDialog::onSelectionChangedAllocation);
// Populate our Model
m_ui->treeViewAllocated->setSelectionMode(QAbstractItemView::MultiSelection);
m_ui->treeViewAvailable->setSelectionMode(QAbstractItemView::MultiSelection);
m_ui->treeViewAllocated->setSelectionMode(QAbstractItemView::ExtendedSelection);
m_ui->treeViewAvailable->setSelectionMode(QAbstractItemView::ExtendedSelection);
//m_ui->treeViewAllocated->setSortingEnabled(true);
//m_ui->treeViewAllocated->sortByColumn(0,Qt::AscendingOrder );
m_ui->pushButtonUp->setEnabled(false);
m_ui->pushButtonDown->setEnabled(false);
m_avmFtc->enableAll();
int opId = LtsSessionData::LtsSessionData::getInstance()->getOperatorId();
if (m_ui->operatorComboBox->currentIndex() != m_ui->operatorComboBox->findData(opId))
m_ui->operatorComboBox->setCurrentIndex(m_ui->operatorComboBox->findData(opId));
else
onSelectionOperatorChanged(0); //param is unused
setUnchangeable(false);
return true;
} // end of init
void AudioSettingsDialog::retranslate()
{
translate(m_ui, tr("Voice Communication Access"));
} // end of retranslate
void AudioSettingsDialog::onOperatorChanged(const OperatorManagement::User &data, DataModification modType)
{
// Table: opm.opm_operator
DEBUG_LOG(m_logger) << "************** onOperatorChanged ";
switch (modType)
{
case DataModification::eRemoved:
{
Q_ASSERT(m_operatorMap.contains(data.id()));
// Check, if Operator is currently open, if yes, reset any changes
if (m_ui->operatorComboBox->currentData().toInt() == data.id())
{
__unchange__();
m_modelAllocated->resetChangeState();
m_modelAvailable->resetChangeState();
m_filterAvailable->invalidate();
}
m_operatorMap.remove(data.id());
m_ui->operatorComboBox->removeItem(m_ui->operatorComboBox->findData(data.id()));
break;
}
case DataModification::eAdded:
{
Q_ASSERT(!m_operatorMap.contains(data.id()));
const QString operatorName = QString::fromStdString(data.name());
m_operatorMap.insert(data.id(), operatorName);
m_ui->operatorComboBox->addItem(operatorName, data.id());
m_ui->operatorComboBox->model()->sort(0);
break;
}
case DataModification::eModified:
{
Q_ASSERT(m_operatorMap.contains(data.id()));
const QString operatorName = QString::fromStdString(data.name());
m_operatorMap.insert(data.id(), operatorName);
int i = m_ui->operatorComboBox->findData(data.id());
Q_ASSERT(i != -1);
m_ui->operatorComboBox->setItemText(i, operatorName);
m_ui->operatorComboBox->model()->sort(0);
break;
}
}
} // end of onOperatorChanged
void AudioSettingsDialog::onCnrTvcProfileChanged(const CnrTvcProfile &data, DataModification modType)
{
if (m_session->exerciseId() == data.exerciseId())
{
if (modType == DataModification::eRemoved)
{
m_cnrTvcProfileMap.remove(data.id());
}
else
{
m_cnrTvcProfileMap.insert(data.id(), data);
fillOperatorList();
}
}
} // end of onCnrTvcProfileChanged
void AudioSettingsDialog::fillOperatorList()
{
QVector<StreamData> newStreamData;
for (const auto &rc : qAsConst(m_cnrTvcProfileMap))
{
if ((rc.exerciseId() != m_session->exerciseId())
|| (rc.operatorId() != m_ui->operatorComboBox->currentData().toInt()))
continue;
// insert entry in Allocated
newStreamData.reserve(rc.data().size());
for (const CnrTvcProfileData &profileEntry : rc.data())
newStreamData += toStreamData(profileEntry);
break;
}
m_modelAllocated->setNewStreamData(newStreamData);
m_filterAvailable->setAllocatedStreams(newStreamData);
} // end of fillOperatorList
void AudioSettingsDialog::fillOperatorBox()
{
m_ui->operatorComboBox->clear();
QMap<int, QString>::iterator i = m_operatorMap.begin();
while (i != m_operatorMap.end())
{
m_ui->operatorComboBox->addItem(i.value(), i.key());
++i;
}
m_ui->operatorComboBox->model()->sort(0);
}
void AudioSettingsDialog::onUpButtonClicked()
{
const QModelIndexList mil = m_ui->treeViewAllocated->selectionModel()->selectedIndexes();
if (mil.isEmpty())
return;
m_modelAllocated->changeOrder(mil.first(), true);
if (mil.first().row() > 0)
{
const QModelIndex newRow = m_modelAllocated->index(mil.first().row() - 1, 0);
m_ui->treeViewAllocated->setCurrentIndex(newRow);
}
slotChangesMade();
} // end of onUpButtonClicked
void AudioSettingsDialog::onDownButtonClicked()
{
const QModelIndexList mil = m_ui->treeViewAllocated->selectionModel()->selectedIndexes();
if (mil.isEmpty())
return;
m_modelAllocated->changeOrder(mil.first(), false);
const QModelIndex newRow = m_modelAllocated->index(mil.first().row() + 1, 0);
m_ui->treeViewAllocated->setCurrentIndex(newRow);
slotChangesMade();
} // end of onDownButtonClicked
void AudioSettingsDialog::onSelectionChangedAllocation(const QItemSelection &selected, const QItemSelection &deselected)
{
DEBUG_LOG(m_logger) << "onSelectionChangedAllocation selected.isEmpty()=" << selected.isEmpty();
Q_UNUSED(deselected);
QModelIndex first = m_ui->treeViewAllocated->model()->index(0, 0);
int rowCnt = m_ui->treeViewAllocated->model()->rowCount();
QModelIndex last = m_ui->treeViewAllocated->model()->index(rowCnt - 1, 0);
QModelIndexList selectedRows = m_ui->treeViewAllocated->selectionModel()->selectedIndexes();
const int cntSelectedRows = selectedRows.size();
if (cntSelectedRows > 1)
{
m_ui->pushButtonUp->setEnabled(false);
m_ui->pushButtonDown->setEnabled(false);
return;
}
if (selected.size() > 0)
{
m_ui->pushButtonUp->setEnabled(selected.first().indexes().first() != first);
m_ui->pushButtonDown->setEnabled(selected.first().indexes().first() != last);
}
} // end of onSelectionAllocationChanged
bool AudioSettingsDialog::apply()
{
if (m_modelAllocated->getStreamDataVector().isEmpty())
applyRemove();
else
applyModify();
m_modelAllocated->resetChangeState();
m_modelAvailable->resetChangeState();
m_filterAvailable->invalidate();
return true;
}
bool AudioSettingsDialog::applyRemove()
{
RemoveCnrTvcProfileRequest removeRequest;
DEBUG_LOG(m_logger) << "AudioSettingsDialog::applyRemove";
for (const auto &profile : qAsConst(m_cnrTvcProfileMap))
{
if (profile.operatorId() != m_operatorId)
continue;
removeRequest.id(profile.id());
break;
}
if (removeRequest.id() <= 0)
return true;
m_requestHelper->startSingleRequest([this, removeRequest]()
{
return m_avmFtc->removeCnrTvcProfileRequest(removeRequest, this);
});
return true;
} // end of applyRemove
bool AudioSettingsDialog::applyModify()
{
ModifyCnrTvcProfileRequest modifyRequest;
DEBUG_LOG(m_logger) << "AudioSettingsDialog::applyModify";
for (const auto &profile : qAsConst(m_cnrTvcProfileMap))
{
if (profile.operatorId() != m_operatorId)
continue;
modifyRequest.id(profile.id());
break;
}
modifyRequest.exerciseId(m_session->exerciseId());
modifyRequest.operatorId(m_operatorId);
const QVector<StreamData> allocatedList = m_modelAllocated->getStreamDataVector();
modifyRequest.data().reserve(allocatedList.size());
for (const StreamData &stream : allocatedList)
{
CnrTvcProfileData circuitData;
circuitData.radioSystemId(stream.bIsCnr ? RadioSystem::Cnr : RadioSystem::Tvc);
circuitData.radioCircuitId(stream.topicId);
modifyRequest.data().push_back(std::move(circuitData));
}
m_requestHelper->startSingleRequest([this, modifyRequest]()
{
return m_avmFtc->modifyCnrTvcProfileRequest(modifyRequest, this);
});
return true;
} // end of applyModify
void AudioSettingsDialog::onModifyCnrTvcProfileReply(const Core::FunctionReplyObject &replyObject)
{
__unchange__();
m_requestHelper->requestReply(replyObject);
} // end of onCreateRadioCircuitsReply
//-----------------------------------------------------------------------------
void AudioSettingsDialog::onRemoveCnrTvcProfileReply(const Core::FunctionReplyObject &replyObject)
{
__unchange__();
m_requestHelper->requestReply(replyObject);
} // end of onRemoveRadioCircuitsReply
//-----------------------------------------------------------------------------
void AudioSettingsDialog::onSelectionOperatorChanged(const int index)
{
Q_UNUSED(index);
if (hasUnsavedChanges() ||
m_modelAllocated->getChangeState() ||
m_modelAvailable->getChangeState())
{
switch (askApplyDiscardCancel())
{
case LtsWidgets::Button::Apply:
if (!apply())
return;
break;
case LtsWidgets::Button::Cancel:
{
// cfroebel 2019-06-26:
// Setting back the operator would cause this slot to be called again.
// Thus we avoid this by blocking signals.
{
QSignalBlocker blockSignals(m_ui->operatorComboBox);
m_ui->operatorComboBox->setCurrentIndex(m_ui->operatorComboBox->findData(m_operatorId)); // reset position
}
return;
}
case LtsWidgets::Button::Discard:
__unchange__(); // can't call resetChanges() by myself :(
break;
default:
break;
}
}
m_ui->pushButtonUp->setEnabled(false);
m_ui->pushButtonDown->setEnabled(false);
m_operatorId = m_ui->operatorComboBox->currentData().toInt();
DEBUG_LOG(m_logger) << "onSelectionOperatorChanged" << " operatorStr=" << m_ui->operatorComboBox->currentText() << " m_operatorId= " << m_operatorId;
fillOperatorList();
m_modelAllocated->resetChangeState();
m_modelAvailable->resetChangeState();
m_filterAvailable->invalidate();
}
void AudioSettingsDialog::onDroppedInAllocated(const QVector<StreamData> &streams)
{
slotChangesMade();
m_filterAvailable->addAllocatedStreams(streams);
m_modelAllocated->setStreamChanged(streams);
m_modelAvailable->setStreamChanged(streams);
}
void AudioSettingsDialog::onDroppedInAvailable(const QVector<StreamData> &streams)
{
slotChangesMade();
m_filterAvailable->removeAllocatedStreams(streams);
m_modelAllocated->setStreamChanged(streams);
m_modelAvailable->setStreamChanged(streams);
}
void AudioSettingsDialog::onEntryRemoved(const StreamData &stream)
{
m_modelAllocated->removeEntry(stream);
m_filterAvailable->removeAllocatedStreams({stream}); // in case the stream was allocated forget about it
}
StreamData AudioSettingsDialog::toStreamData(const CnrTvcProfileData &profileEntry) const
{
int configId = profileEntry.radioCircuitId();
StreamData streamData;
streamData.topicId = configId;
if (profileEntry.radioSystemId() == RadioSystem::Cnr)
{
streamData.name = QString::fromStdString(m_avmDtc->cnrConfig(configId).radioCircuit());
streamData.bIsCnr = true;
}
else
{
streamData.name = QString::fromStdString(m_avmDtc->tvcConfig(configId).radioCircuit());
streamData.bIsCnr = false;
}
return streamData;
}
} // namespace AudioVideoManagement