/** * @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 #include #include #include 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::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 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::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 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 &streams) { slotChangesMade(); m_filterAvailable->addAllocatedStreams(streams); m_modelAllocated->setStreamChanged(streams); m_modelAvailable->setStreamChanged(streams); } void AudioSettingsDialog::onDroppedInAvailable(const QVector &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