Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
+98
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Helper funtcions for converting CnrConfigs
|
||||
* $Id: avm_combat_net_radio_dialog_model.h 60985 2023-12-01 11:53:28Z eberlein_v $
|
||||
* $HeadURL: svn://192.168.133.21/TDS/branches/product/features/optfunk/Lts/Plugins/AudioVideoManagement/Gui/CombatNetRadio/CombatNetRadioConfiguration/avm_combat_net_radio_dialog_model.h $
|
||||
* $Author: eberlein_v $
|
||||
* Created by Hannes Fritsche, ESZS, 2023-01-30
|
||||
*/
|
||||
|
||||
#include "avm_cnr_json_helper.h"
|
||||
|
||||
#include <AudioVideoManagement/avm_dtc.h>
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonDocument>
|
||||
#include <FileManagement/flm_translation.h>
|
||||
|
||||
namespace AudioVideoManagement
|
||||
{
|
||||
|
||||
QByteArray cnrConfigVectorToJson(const QVector<CnrConfig> &configVector, int32_t exerciseId)
|
||||
{
|
||||
const bool isGlobal = exerciseId == 0;
|
||||
QJsonObject obj;
|
||||
QJsonArray arr;
|
||||
|
||||
for (const CnrConfig &config : qAsConst(configVector))
|
||||
{
|
||||
if((isGlobal && config.exerciseId().is_set())
|
||||
|| (!isGlobal && !config.exerciseId().is_set()))
|
||||
continue;
|
||||
|
||||
arr += cnrConfigToJson(config);
|
||||
}
|
||||
|
||||
obj.insert(JsonKeys::XML_TYPE(), FileManagement::toString(FileManagement::XmlType::AVMCombatNetRadio));
|
||||
obj.insert(JsonKeys::CNR_CONFIGURATION(), arr);
|
||||
|
||||
const QJsonDocument doc(obj);
|
||||
|
||||
return doc.toJson(QJsonDocument::Compact);
|
||||
}
|
||||
|
||||
QJsonObject cnrConfigToJson(const CnrConfig &config)
|
||||
{
|
||||
QJsonObject cnrObj;
|
||||
|
||||
using namespace JsonKeys;
|
||||
|
||||
cnrObj.insert(CALL_SIGN(), QString::fromStdString(config.callSign()));
|
||||
cnrObj.insert(CNR_CHANNEL_ID(), config.cnrChannelId());
|
||||
cnrObj.insert(IS_GLOBAL(), !config.exerciseId().is_set());
|
||||
cnrObj.insert(RADIO_CIRCUIT(), QString::fromStdString(config.radioCircuit()));
|
||||
cnrObj.insert(IS_ACTIVE(), config.isActive());
|
||||
cnrObj.insert(RECORDING(), config.recording());
|
||||
|
||||
return cnrObj;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T jsonToCnr(const QJsonObject &cnrJson)
|
||||
{
|
||||
T cnrConfigRequest;
|
||||
|
||||
using namespace JsonKeys ;
|
||||
|
||||
cnrConfigRequest.callSign(cnrJson.value(CALL_SIGN()).toString().toStdString());
|
||||
cnrConfigRequest.cnrChannelId(cnrJson.value(CNR_CHANNEL_ID()).toInt());
|
||||
cnrConfigRequest.id(0);
|
||||
cnrConfigRequest.radioCircuit(cnrJson.value(RADIO_CIRCUIT()).toString().toStdString());
|
||||
|
||||
cnrConfigRequest.recording(cnrJson.value(RECORDING()).toBool());
|
||||
|
||||
return cnrConfigRequest;
|
||||
}
|
||||
|
||||
QVector<CnrConfig> jsonToCnrConfigVector(const QByteArray &data)
|
||||
{
|
||||
using namespace JsonKeys;
|
||||
|
||||
const QJsonDocument doc(QJsonDocument::fromJson(data));
|
||||
const QJsonObject obj(doc.object());
|
||||
const QJsonArray arr(obj.value(CNR_CONFIGURATION()).toArray());
|
||||
QVector<CnrConfig> result;
|
||||
result.reserve(arr.size());
|
||||
|
||||
for (const auto &elem : arr)
|
||||
{
|
||||
const QJsonObject obj(elem.toObject());
|
||||
|
||||
result.append(jsonToCnr<CnrConfig>(obj));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace AudioVideoManagement
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Helper funtcions for converting CnrConfigs
|
||||
* $Id: avm_combat_net_radio_dialog_model.h 60985 2023-12-01 11:53:28Z eberlein_v $
|
||||
* $HeadURL: svn://192.168.133.21/TDS/branches/product/features/optfunk/Lts/Plugins/AudioVideoManagement/Gui/CombatNetRadio/CombatNetRadioConfiguration/avm_combat_net_radio_dialog_model.h $
|
||||
* $Author: eberlein_v $
|
||||
* Created by Hannes Fritsche, ESZS, 2023-01-30
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AudioVideoManagement/avm_dtc.h>
|
||||
|
||||
namespace AudioVideoManagement
|
||||
{
|
||||
namespace JsonKeys
|
||||
{
|
||||
inline QString CALL_SIGN() { return QLatin1String("callSign"); }
|
||||
inline QString CNR_CHANNEL_ID() { return QLatin1String("cnrChannelId"); }
|
||||
inline QString CNR_CONFIGURATION() { return QLatin1String("cnrConfiguration"); }
|
||||
inline QString IS_ACTIVE() { return QLatin1String("isActive"); }
|
||||
inline QString IS_GLOBAL() { return QLatin1String("isGlobal"); }
|
||||
inline QString RADIO_CIRCUIT() { return QLatin1String("radioCircuit"); }
|
||||
inline QString RECORDING() { return QLatin1String("recording"); }
|
||||
inline QString XML_TYPE() { return QLatin1String("XmlType"); }
|
||||
} // namespace JsonKeys
|
||||
|
||||
QByteArray cnrConfigVectorToJson(const QVector<CnrConfig> &configVector, int32_t exerciseId);
|
||||
QJsonObject cnrConfigToJson(const CnrConfig &config);
|
||||
|
||||
QVector<CnrConfig> jsonToCnrConfigVector(const QByteArray &data);
|
||||
|
||||
template <typename T> // CnrConfig or ModifyCnrConfigRequest
|
||||
T jsonToCnr(const QJsonObject &cnrJson);
|
||||
} // namespace AudioVideoManagement
|
||||
+259
@@ -0,0 +1,259 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* The CombatNetRadioDialog shows all CNR configurations and offers options for creation and editing
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Hannes Baeuerle, SLSE, 2017-08-18
|
||||
*/
|
||||
|
||||
#include "avm_combat_net_radio_dialog.h"
|
||||
#include "ui_avm_combat_net_radio_dialog.h"
|
||||
#include "avm_combat_net_radio_dialog_model.h"
|
||||
#include "avm_edit_combat_net_radio_dialog.h"
|
||||
#include "avm_cnr_json_helper.h"
|
||||
#include "avm_load_combat_net_radio_dialog.h"
|
||||
|
||||
#include <LtsUtilsGuiDds/request_helper.h>
|
||||
#include <LtsSession/lts_session.h>
|
||||
|
||||
#include <LtsPrinting/printing.h>
|
||||
#include <QTreeView>
|
||||
|
||||
#include <PluginInterfaces/gui_plugin_interface.h>
|
||||
#include <FileManagement/flm_translation.h>
|
||||
|
||||
namespace AudioVideoManagement
|
||||
{
|
||||
CombatNetRadioDialog::CombatNetRadioDialog(LtsSession::LtsSession *session, const QString &menuGroup, QWidget *parent)
|
||||
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::CloseOnly)
|
||||
, m_session(session)
|
||||
, m_ui(new Ui::CombatNetRadioDialog)
|
||||
, m_menuGroup(menuGroup)
|
||||
, m_requestHelper(new LtsUtils::RequestHelper(this))
|
||||
, m_logger(getLogger("CombatNetRadioDialog"))
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
setUnchangeable(true);
|
||||
m_buttonBox->connectButton(LtsWidgets::DialogButton::Print, this, &CombatNetRadioDialog::onPrint);
|
||||
|
||||
setOnlineHelpFilename(QStringLiteral("Situation-Combat_Net_Radio_Configuration"));
|
||||
}
|
||||
|
||||
CombatNetRadioDialog::~CombatNetRadioDialog() = default;
|
||||
|
||||
void CombatNetRadioDialog::retranslate()
|
||||
{
|
||||
translate(m_ui.get(), tr("Configure Combat Net Radio"));
|
||||
}
|
||||
|
||||
void CombatNetRadioDialog::tableColumnOrganiserSetting()
|
||||
{
|
||||
//LtsColumnOrganiser
|
||||
m_ui->dataView->setColumnsOrganiserEnabled(identifier(), true);
|
||||
}
|
||||
|
||||
bool CombatNetRadioDialog::init(const std::shared_ptr<Interface::Dtc> &avmDtc,
|
||||
const std::shared_ptr<Interface::Ftc> &avmFtc,
|
||||
const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc,
|
||||
ExerciseManagement::Interface::Dtc *exmDtc)
|
||||
{
|
||||
if (!(avmDtc->enableCnrChannel() &&
|
||||
avmDtc->enableCnrConfig() &&
|
||||
ppmDtc->enableParty() &&
|
||||
ppmDtc->enableParticipant() &&
|
||||
ppmDtc->enableType() &&
|
||||
avmFtc->enableModifyCnrConfig() &&
|
||||
avmFtc->enableRemoveCnrConfig()))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Could not enable topics";
|
||||
return false;
|
||||
}
|
||||
|
||||
m_model.reset(new CombatNetRadioDialogModel(m_session->exerciseId(), this));
|
||||
m_filter.reset(new CombatNetRadioDialogFilter(m_session->exerciseId(), m_model.get()));
|
||||
|
||||
m_avmDtc = avmDtc;
|
||||
m_avmFtc = avmFtc;
|
||||
m_ppmDtc = ppmDtc;
|
||||
m_exmDtc = exmDtc;
|
||||
|
||||
m_avmDtc->waitForHistoricalDataCnrChannel(3000);
|
||||
m_ppmDtc->waitForHistoricalDataParty(3000);
|
||||
|
||||
if (!m_model->init(avmDtc, ppmDtc))
|
||||
{
|
||||
m_filter.reset();
|
||||
m_model.reset();
|
||||
ERROR_LOG(m_logger) << "Could not init model";
|
||||
return false;
|
||||
}
|
||||
|
||||
m_ui->dataView->setModel(m_filter.get());
|
||||
|
||||
m_buttonBox->connectButton(LtsWidgets::DialogButton::Add, this, &CombatNetRadioDialog::onAddClicked);
|
||||
m_buttonBox->connectButton(LtsWidgets::DialogButton::Edit, this, &CombatNetRadioDialog::onEditClicked);
|
||||
m_buttonBox->connectButton(LtsWidgets::DialogButton::Remove, this, &CombatNetRadioDialog::onRemoveClicked);
|
||||
|
||||
connect(m_ui->dataView, &LtsDataView::LtsDataView::signalSelectionChanged,
|
||||
this, &CombatNetRadioDialog::onSelectionChanged);
|
||||
|
||||
onSelectionChanged();
|
||||
|
||||
connect(m_ui->dataView, &LtsDataView::LtsDataView::signalDoubleClicked,
|
||||
this, &CombatNetRadioDialog::onEditClicked);
|
||||
|
||||
// Save/Load from Library Button
|
||||
m_buttonBox->connectLibraryButton(this,
|
||||
&CombatNetRadioDialog::onImportButtonClicked,
|
||||
&CombatNetRadioDialog::onExportButtonClicked);
|
||||
|
||||
if (!m_session->getForeignGuiInterface<FileManagement::ForeignGuiInterface>(m_flmGui))
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Library, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CombatNetRadioDialog::onRemoveCnrConfigReply(const Core::FunctionReplyObject &replyObject)
|
||||
{
|
||||
m_requestHelper->requestReply(replyObject);
|
||||
}
|
||||
|
||||
void CombatNetRadioDialog::onModifyCnrConfigReply(const Core::FunctionReplyObject &replyObject)
|
||||
{
|
||||
m_requestHelper->requestReply(replyObject);
|
||||
}
|
||||
|
||||
void CombatNetRadioDialog::onAddClicked()
|
||||
{
|
||||
EditCombatNetRadioDialog *dialog = new EditCombatNetRadioDialog(m_session->exerciseId(), m_session, m_ppmDtc, m_avmDtc, m_avmFtc, m_exmDtc, this);
|
||||
addDialog(dialog, m_menuGroup, QStringLiteral("NewCNRConfig"), LtsWidgets::LayoutArea::eDialogTab);
|
||||
}
|
||||
|
||||
void CombatNetRadioDialog::onEditClicked()
|
||||
{
|
||||
// avoid double click on table:
|
||||
if (!m_buttonBox->isButtonEnabled(LtsWidgets::DialogButton::Edit))
|
||||
return;
|
||||
|
||||
QModelIndex currentIndex = m_ui->dataView->currentIndex();
|
||||
|
||||
if (!currentIndex.isValid())
|
||||
return;
|
||||
|
||||
CnrConfig config = m_model->data(currentIndex, Qt::UserRole).value<CnrConfig>();
|
||||
|
||||
EditCombatNetRadioDialog *dialog = new EditCombatNetRadioDialog(config,
|
||||
m_session->exerciseId(),
|
||||
m_session,
|
||||
m_ppmDtc,
|
||||
m_avmDtc,
|
||||
m_avmFtc,
|
||||
m_exmDtc,
|
||||
this);
|
||||
|
||||
addDialog(dialog, m_menuGroup, QStringLiteral("EditCNRConfig%1").arg(config.id()), LtsWidgets::LayoutArea::eDialogTab);
|
||||
}
|
||||
|
||||
void CombatNetRadioDialog::onRemoveClicked()
|
||||
{
|
||||
QModelIndex currentIndex = m_ui->dataView->currentIndex();
|
||||
|
||||
if (!currentIndex.isValid())
|
||||
return;
|
||||
|
||||
Core::RemoveElementRequest request(m_model->data(currentIndex, Qt::UserRole).value<CnrConfig>().id());
|
||||
|
||||
m_requestHelper->startSingleRequest([this, request]()
|
||||
{
|
||||
return m_avmFtc->removeCnrConfigRequest(request, this);
|
||||
});
|
||||
}
|
||||
|
||||
void CombatNetRadioDialog::onSelectionChanged()
|
||||
{
|
||||
bool rowSelected = m_ui->dataView->selectionModel()->selectedRows().size() > 0;
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Edit, rowSelected);
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Remove, rowSelected);
|
||||
|
||||
QModelIndex currentIndex = m_ui->dataView->currentIndex();
|
||||
|
||||
if (!currentIndex.isValid())
|
||||
return;
|
||||
|
||||
CnrConfig config = m_model->data(currentIndex, Qt::UserRole).value<CnrConfig>();
|
||||
bool enabled = rowSelected && (config.exerciseId().is_set() || m_session->partitionType() == IDL::PartitionType::Global);
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Edit, enabled);
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Remove, enabled);
|
||||
}
|
||||
|
||||
void CombatNetRadioDialog::onPrint()
|
||||
{
|
||||
LtsPrinting::printView(m_session, this, m_ui->dataView->treeView());
|
||||
}
|
||||
|
||||
void CombatNetRadioDialog::onExportButtonClicked()
|
||||
{
|
||||
QByteArray byteArray = m_filter->modelToJson();
|
||||
|
||||
int fileId = m_flmGui->saveFileContent(this, FileManagement::FileType::Xml, m_session->exerciseId(), byteArray);
|
||||
if (fileId > 0)
|
||||
DEBUG_LOG(m_logger) << "Saved file with id = " << fileId;
|
||||
else
|
||||
ERROR_LOG(m_logger) << "Could not save file in library ";
|
||||
}
|
||||
|
||||
void CombatNetRadioDialog::onImportButtonClicked()
|
||||
{
|
||||
DEBUG_LOG(m_logger) << " onImportButtonClicked() ";
|
||||
|
||||
QByteArray content;
|
||||
int fileId = m_flmGui->loadFileContent(this, content, {FileManagement::FileType::Xml}, m_session->exerciseId(), FileManagement::toString(FileManagement::XmlType::AVMCombatNetRadio));
|
||||
|
||||
if (fileId > 0)
|
||||
{
|
||||
if (!m_flmGui->isXmlType(content, FileManagement::toString(FileManagement::XmlType::AVMCombatNetRadio)))
|
||||
{
|
||||
QHash<LtsWidgets::Button, QString> texts({{LtsWidgets::Button::Yes, tr("Ok")}});
|
||||
LtsWidgets::LtsMessageDialog::showMessage(this,
|
||||
tr("Invalid xml file content"),
|
||||
windowTitle(),
|
||||
LtsWidgets::Behaviour::Modal,
|
||||
LtsWidgets::Button::Yes,
|
||||
texts);
|
||||
}
|
||||
else
|
||||
{
|
||||
LoadCombatNetRadioDialog loadingDialog(content, m_session) ;
|
||||
loadingDialog.exec();
|
||||
|
||||
if (loadingDialog.isApplied())
|
||||
{
|
||||
const QVector<Core::RemoveElementRequest> removeRequests = loadingDialog.removeRequests();
|
||||
|
||||
for (const auto &removeRequest : removeRequests)
|
||||
{
|
||||
m_requestHelper->addRequest([this, removeRequest]()
|
||||
{
|
||||
return m_avmFtc->removeCnrConfigRequest(removeRequest, this);
|
||||
});
|
||||
}
|
||||
|
||||
const QVector<ModifyCnrConfigRequest> modifyRequests = loadingDialog.modifyRequests();
|
||||
|
||||
for (const auto &modifyRequest : modifyRequests)
|
||||
{
|
||||
m_requestHelper->addRequest([this, modifyRequest]()
|
||||
{
|
||||
return m_avmFtc->modifyCnrConfigRequest(modifyRequest, this);
|
||||
});
|
||||
}
|
||||
|
||||
if (modifyRequests.size() || removeRequests.size())
|
||||
(void) m_requestHelper->startRequests();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace AudioVideoManagement
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* The CombatNetRadioDialog shows all CNR configurations and offers options for creation and editing
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Hannes Baeuerle, SLSE, 2017-08-18
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LtsWidgets/lts_dialog.h>
|
||||
|
||||
#include <AudioVideoManagement/logger.h>
|
||||
#include <AudioVideoManagement/avm_ftc.h>
|
||||
#include <Plugins/FileManagement/flm_explorer_gui_plugin_interface.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class CombatNetRadioDialog;
|
||||
}
|
||||
|
||||
namespace LtsUtils
|
||||
{
|
||||
class RequestHelper;
|
||||
}
|
||||
|
||||
namespace AudioVideoManagement
|
||||
{
|
||||
namespace Interface
|
||||
{
|
||||
class Dtc;
|
||||
}
|
||||
}
|
||||
|
||||
namespace ParticipantManagement
|
||||
{
|
||||
namespace Interface
|
||||
{
|
||||
class Dtc;
|
||||
}
|
||||
}
|
||||
|
||||
namespace ExerciseManagement
|
||||
{
|
||||
namespace Interface
|
||||
{
|
||||
class Dtc;
|
||||
}
|
||||
}
|
||||
|
||||
namespace LtsSession
|
||||
{
|
||||
class LtsSession;
|
||||
}
|
||||
namespace AudioVideoManagement
|
||||
{
|
||||
class CombatNetRadioDialogModel;
|
||||
class CombatNetRadioDialogFilter;
|
||||
|
||||
class CombatNetRadioDialog
|
||||
: public LtsWidgets::LtsDialog
|
||||
, protected Interface::Ftc::RemoveCnrConfigReplyHandler
|
||||
, protected Interface::Ftc::ModifyCnrConfigReplyHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit CombatNetRadioDialog(LtsSession::LtsSession *session, const QString &menuGroup, QWidget *parent = nullptr);
|
||||
~CombatNetRadioDialog();
|
||||
|
||||
bool init(const std::shared_ptr<Interface::Dtc> &avmDtc, const std::shared_ptr<Interface::Ftc> &avmFtc, const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc, ExerciseManagement::Interface::Dtc *exmDtc);
|
||||
|
||||
void onRemoveCnrConfigReply(const Core::FunctionReplyObject &replyObject) override final;
|
||||
void onModifyCnrConfigReply(const Core::FunctionReplyObject &replyObject) override final;
|
||||
|
||||
private Q_SLOTS:
|
||||
void onAddClicked();
|
||||
void onEditClicked();
|
||||
void onRemoveClicked();
|
||||
void onSelectionChanged();
|
||||
void onPrint();
|
||||
void onExportButtonClicked();
|
||||
void onImportButtonClicked();
|
||||
|
||||
private: // methods
|
||||
void retranslate() override;
|
||||
void tableColumnOrganiserSetting() override;
|
||||
|
||||
private: // attributes
|
||||
LtsSession::LtsSession *m_session;
|
||||
std::unique_ptr<CombatNetRadioDialogModel> m_model;
|
||||
std::unique_ptr<CombatNetRadioDialogFilter> m_filter;
|
||||
std::unique_ptr<Ui::CombatNetRadioDialog> m_ui;
|
||||
QString m_menuGroup;
|
||||
std::unique_ptr<LtsUtils::RequestHelper> m_requestHelper;
|
||||
std::shared_ptr<Interface::Dtc> m_avmDtc;
|
||||
std::shared_ptr<Interface::Ftc> m_avmFtc;
|
||||
std::shared_ptr<ParticipantManagement::Interface::Dtc> m_ppmDtc;
|
||||
ExerciseManagement::Interface::Dtc *m_exmDtc{nullptr};
|
||||
std::shared_ptr<FileManagement::ForeignGuiInterface> m_flmGui;
|
||||
|
||||
LOGGER_T m_logger;
|
||||
|
||||
}; // class CombatNetRadioDialog
|
||||
} // namespace AudioVideoManagement
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>CombatNetRadioDialog</class>
|
||||
<widget class="QWidget" name="CombatNetRadioDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>692</width>
|
||||
<height>262</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="LtsDataView::LtsDataView" name="dataView" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>LtsDataView::LtsDataView</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>LtsDataView/lts_data_view.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
+159
@@ -0,0 +1,159 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* The CombatNetRadioDialogModel provices data for CombatNetRadioDialog
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Hannes Baeuerle, SLSE, 2017-08-18
|
||||
*/
|
||||
|
||||
#include "avm_combat_net_radio_dialog_model.h"
|
||||
#include <ParticipantManagement/ppm_translation.h>
|
||||
#include <LtsSession/lts_session_data.h>
|
||||
#include <AudioVideoManagement/avm_ftc.h>
|
||||
#include "avm_cnr_json_helper.h"
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonDocument>
|
||||
|
||||
namespace AudioVideoManagement
|
||||
{
|
||||
|
||||
CombatNetRadioDialogModel::CombatNetRadioDialogModel(int32_t exerciseId, QObject *parent)
|
||||
: LtsAbstractTableModel<CnrConfig>(
|
||||
{
|
||||
tr("Channel Number"),
|
||||
tr("Radio Circuit"),
|
||||
tr("Code Word"),
|
||||
tr("Party"),
|
||||
tr("Unit"),
|
||||
tr("Global")
|
||||
}, parent)
|
||||
, m_exerciseId(exerciseId)
|
||||
, m_logger(getLogger("CombatNetRadioDialogModel"))
|
||||
{
|
||||
}
|
||||
|
||||
QVariant CombatNetRadioDialogModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if ((role != Qt::BackgroundRole &&role != Qt::DisplayRole && role != Qt::UserRole) || !indexIsValid(index))
|
||||
return {};
|
||||
|
||||
const CnrConfig &config = m_vecData.at(index.row());
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
switch (index.column())
|
||||
{
|
||||
case CHANNEL:
|
||||
INFO_LOG(m_logger)<<"CombatNetRadioDialogModel::data role =" << role
|
||||
<< " row = " << index.row();
|
||||
return QString::fromStdString(m_cnrChannels.value(config.cnrChannelId()).name());
|
||||
case RADIO_CIRCUIT:
|
||||
return QString::fromStdString(config.radioCircuit());
|
||||
case CALL_SIGN:
|
||||
return QString::fromStdString(config.callSign());
|
||||
case PARTY:
|
||||
if(config.exerciseId().is_set() || config.partyId() > 0)
|
||||
return ParticipantManagement::trPartyName(m_parties.value(config.partyId()).name());
|
||||
else
|
||||
return QStringLiteral("-");
|
||||
case UNIT:
|
||||
{
|
||||
if (!config.unitId().is_set())
|
||||
return {};
|
||||
const int unitId = config.unitId().get();
|
||||
const auto unit = m_units.value(config.unitId().get());
|
||||
if (unit.id() != unitId)
|
||||
return {};
|
||||
|
||||
INFO_LOG(m_logger) << " config.unitId()=" << unitId
|
||||
<< " Str=" << unit.name();
|
||||
|
||||
QString unitStr;
|
||||
if (unit.designator().size() > 0)
|
||||
unitStr = QString::fromStdString(unit.designator()) + QLatin1Char('/');
|
||||
unitStr.append(QString::fromStdString(unit.tacticalIdentifier()));
|
||||
INFO_LOG(m_logger) << "unitStr = " << unitStr;
|
||||
|
||||
return unitStr;
|
||||
}
|
||||
case GLOBAL:
|
||||
return config.exerciseId().is_set() ? tr("No") : tr("Yes");
|
||||
}
|
||||
}
|
||||
else if (role == Qt::BackgroundRole)
|
||||
{
|
||||
if (config.exerciseId().is_set() && config.exerciseId().get() == m_exerciseId)
|
||||
return {};
|
||||
if (!config.exerciseId().is_set() && m_exerciseId <= 0)
|
||||
return {};
|
||||
return QColor(Qt::gray);
|
||||
}
|
||||
else if (role == Qt::UserRole)
|
||||
return QVariant::fromValue(config);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
bool CombatNetRadioDialogModel::init(const std::shared_ptr<Interface::Dtc> &avmDtc, const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc)
|
||||
{
|
||||
m_avmDtc = avmDtc;
|
||||
|
||||
m_cnrChannels = avmDtc->cnrChannels();
|
||||
|
||||
if (!ppmDtc->visibleParties(m_parties, LtsSessionData::LtsSessionData::getInstance()->getVisibleParties(m_exerciseId)))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Could not retrieve visible Parties!";
|
||||
return false;
|
||||
}
|
||||
m_units = ppmDtc->units();
|
||||
|
||||
connect(m_avmDtc.get(), &Interface::Dtc::cnrConfigChanged, this, &CombatNetRadioDialogModel::onDataChanged);
|
||||
m_avmDtc->cnrConfigs([this](const CnrConfig &c) { insertRow(c); });
|
||||
|
||||
return true;
|
||||
}
|
||||
bool CombatNetRadioDialogModel::onlyGlobals()
|
||||
{
|
||||
for(const CnrConfig &config : qAsConst(m_vecData))
|
||||
{
|
||||
if(config.exerciseId().is_set() && config.exerciseId().get() == m_exerciseId)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
QByteArray CombatNetRadioDialogFilter::modelToJson() const
|
||||
{
|
||||
QVector<CnrConfig> configs;
|
||||
configs.reserve(rowCount());
|
||||
|
||||
for (int row = 0; row < rowCount(); ++row)
|
||||
{
|
||||
int sourceRow = mapToSource(index(row, 0)).row();
|
||||
configs.append(m_sourceModel->getRowData(sourceRow));
|
||||
}
|
||||
|
||||
return cnrConfigVectorToJson(configs, m_exerciseId);
|
||||
}
|
||||
|
||||
CombatNetRadioDialogFilter::CombatNetRadioDialogFilter(int32_t exerciseId, CombatNetRadioDialogModel *sourceModel)
|
||||
: m_exerciseId(exerciseId)
|
||||
, m_sourceModel(sourceModel)
|
||||
{
|
||||
Q_ASSERT(sourceModel);
|
||||
setSourceModel(sourceModel);
|
||||
}
|
||||
|
||||
bool CombatNetRadioDialogFilter::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
|
||||
{
|
||||
CnrConfig cnrConfig = m_sourceModel->getRowData(sourceRow);
|
||||
|
||||
if (cnrConfig.exerciseId().is_set() && cnrConfig.exerciseId().get() != m_exerciseId)
|
||||
return false;
|
||||
|
||||
return LtsColumnFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent);
|
||||
}
|
||||
|
||||
} // namespace AudioVideoManagement
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* The CombatNetRadioDialogModel provices data for CombatNetRadioDialog
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Hannes Baeuerle, SLSE, 2017-08-18
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// Todo:
|
||||
#include <Proxies/CombatNetRadio/Helper/cnr_frequency_planning_helper.h>
|
||||
#include <LtsWidgets/lts_abstract_table_model.h>
|
||||
#include <LtsWidgets/lts_column_filter_proxy_model.h>
|
||||
|
||||
#include <AudioVideoManagement/logger.h>
|
||||
#include <AudioVideoManagement/avm_dtc.h>
|
||||
#include <ParticipantManagement/ppm_dtc.h>
|
||||
|
||||
#include <memory>
|
||||
#include <cstdint>
|
||||
|
||||
namespace AudioVideoManagement
|
||||
{
|
||||
|
||||
class CombatNetRadioDialogModel final
|
||||
: public LtsWidgets::LtsAbstractTableModel<CnrConfig>
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum Columns
|
||||
{
|
||||
CHANNEL,
|
||||
RADIO_CIRCUIT,
|
||||
CALL_SIGN,
|
||||
PARTY,
|
||||
UNIT,
|
||||
GLOBAL
|
||||
};
|
||||
|
||||
explicit CombatNetRadioDialogModel(int32_t exerciseId, QObject *parent = nullptr);
|
||||
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
bool init(const std::shared_ptr<Interface::Dtc> &avmDtc, const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc);
|
||||
bool onlyGlobals();
|
||||
|
||||
private:
|
||||
std::shared_ptr<Interface::Dtc> m_avmDtc;
|
||||
int32_t m_exerciseId;
|
||||
QMap<int32_t, CnrChannel> m_cnrChannels;
|
||||
QMap<int32_t, ParticipantManagement::Party> m_parties;
|
||||
QMap<int32_t, ParticipantManagement::Participant> m_units;
|
||||
|
||||
LOGGER_T m_logger;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Responsible for filtering the CnrConfigs in a way that only those get displayed
|
||||
* that are either global or local in the given exercise.
|
||||
*/
|
||||
class CombatNetRadioDialogFilter : public LtsWidgets::LtsColumnFilterProxyModel
|
||||
{
|
||||
public:
|
||||
explicit CombatNetRadioDialogFilter(int32_t exerciseId, CombatNetRadioDialogModel *sourceModel);
|
||||
|
||||
QByteArray modelToJson() const;
|
||||
|
||||
protected:
|
||||
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
|
||||
|
||||
private:
|
||||
/** Don't call directly, use the constructor instead. */
|
||||
using LtsWidgets::LtsColumnFilterProxyModel::setSourceModel;
|
||||
|
||||
int32_t m_exerciseId;
|
||||
CombatNetRadioDialogModel *m_sourceModel;
|
||||
};
|
||||
|
||||
} // namespace AudioVideoManagement
|
||||
|
||||
Q_DECLARE_METATYPE(AudioVideoManagement::CnrConfig)
|
||||
Q_DECLARE_METATYPE(AudioVideoManagement::FrequencyPlanningData)
|
||||
+612
@@ -0,0 +1,612 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* The EditCombatNetRadioDialog allows to set data for a CNR Config
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Hannes Baeuerle, SLSE, 2017-08-18
|
||||
*/
|
||||
|
||||
#include "avm_edit_combat_net_radio_dialog.h"
|
||||
#include "ui_avm_edit_combat_net_radio_dialog.h"
|
||||
#include <AudioVideoManagement/av_helper.h>
|
||||
#include <AudioVideoManagement/Shared/project_settings.h>
|
||||
#include <ParticipantManagement/ppm_translation.h>
|
||||
#include <LtsSession/lts_session_data.h>
|
||||
#include <PluginInterfaces/gui_plugin_interface.h>
|
||||
#include <FileManagement/flm_translation.h>
|
||||
#include <ExerciseManagement/exm_dtc.h>
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QJsonDocument>
|
||||
#include <QStandardItemModel>
|
||||
#include <QTimer>
|
||||
|
||||
|
||||
namespace AudioVideoManagement
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
CnrConfig toConfig(const ModifyCnrConfigRequest &modifyRequest)
|
||||
{
|
||||
return {modifyRequest.id(), modifyRequest.cnrChannelId(), modifyRequest.exerciseId(), modifyRequest.radioCircuit(),
|
||||
modifyRequest.partyId(), modifyRequest.unitId(), modifyRequest.recording(), modifyRequest.callSign(), false};
|
||||
}
|
||||
|
||||
const QString &NO_CHANNEL()
|
||||
{
|
||||
static const QString noChannel = QStringLiteral("---");
|
||||
return noChannel;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
EditCombatNetRadioDialog::EditCombatNetRadioDialog(int32_t exerciseId,
|
||||
LtsSession::LtsSession *session,
|
||||
const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc,
|
||||
const std::shared_ptr<Interface::Dtc> &avmDtc,
|
||||
const std::shared_ptr<Interface::Ftc> &avmFtc,
|
||||
ExerciseManagement::Interface::Dtc *exmDtc,
|
||||
QWidget *parent)
|
||||
: EditCombatNetRadioDialog(boost::none, exerciseId, session, ppmDtc, avmDtc, avmFtc, exmDtc, parent)
|
||||
{
|
||||
m_ui->chkRecording->setChecked(true);
|
||||
m_isGlobal = session->partitionType() == IDL::PartitionType::Global;
|
||||
|
||||
if(m_isGlobal)
|
||||
setUiValuesForGlobal();
|
||||
|
||||
initCbChannelsForCreate();
|
||||
setOnlineHelpFilename(QStringLiteral("Situation-Combat_Net_Radio_Configuration"));
|
||||
}
|
||||
|
||||
EditCombatNetRadioDialog::EditCombatNetRadioDialog(const CnrConfig &cnrConfig,
|
||||
int32_t exerciseId,
|
||||
LtsSession::LtsSession *session,
|
||||
const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc,
|
||||
const std::shared_ptr<Interface::Dtc> &avmDtc,
|
||||
const std::shared_ptr<Interface::Ftc> &avmFtc,
|
||||
ExerciseManagement::Interface::Dtc *exmDtc,
|
||||
QWidget *parent)
|
||||
: EditCombatNetRadioDialog(cnrConfig.id(), exerciseId, session, ppmDtc, avmDtc, avmFtc, exmDtc, parent)
|
||||
{
|
||||
m_channelId = cnrConfig.cnrChannelId();
|
||||
m_isGlobal = session->partitionType() == IDL::PartitionType::Global;
|
||||
setUiValues(cnrConfig);
|
||||
|
||||
setOnlineHelpFilename(QStringLiteral("Situation-Combat_Net_Radio_Configuration"));
|
||||
}
|
||||
|
||||
EditCombatNetRadioDialog::EditCombatNetRadioDialog(const boost::optional<int32_t> &id,
|
||||
int32_t exerciseId,
|
||||
LtsSession::LtsSession *session,
|
||||
const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc,
|
||||
const std::shared_ptr<Interface::Dtc> &avmDtc,
|
||||
const std::shared_ptr<Interface::Ftc> &avmFtc,
|
||||
ExerciseManagement::Interface::Dtc *exmDtc,
|
||||
QWidget *parent)
|
||||
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
|
||||
, m_ui(new Ui::EditCombatNetRadioDialog)
|
||||
, m_id(id)
|
||||
, m_exerciseId(exerciseId)
|
||||
, m_ppmDtc(ppmDtc)
|
||||
, m_avmDtc(avmDtc)
|
||||
, m_avmFtc(avmFtc)
|
||||
, m_exmDtc(exmDtc)
|
||||
, m_requestHelper(new LtsUtils::RequestHelper(this))
|
||||
, m_logger(getLogger("EditCombatNetRadioDialog"))
|
||||
{
|
||||
Q_ASSERT(ppmDtc);
|
||||
Q_ASSERT(avmDtc);
|
||||
Q_ASSERT(avmFtc);
|
||||
Q_ASSERT(exmDtc);
|
||||
|
||||
m_ui->setupUi(this);
|
||||
if (ProjectSettings::isAlwaysRecording())
|
||||
{
|
||||
m_ui->chkRecording->setChecked(true);
|
||||
m_ui->chkRecording->setEnabled(false);
|
||||
m_ui->chkRecording->hide();
|
||||
m_ui->lbRecording->hide();
|
||||
}
|
||||
init(session);
|
||||
}
|
||||
|
||||
EditCombatNetRadioDialog::~EditCombatNetRadioDialog() = default;
|
||||
|
||||
void EditCombatNetRadioDialog::retranslate()
|
||||
{
|
||||
translate(m_ui.get(), QString(), !m_id.is_initialized(), tr("Combat Net Radio"));
|
||||
}
|
||||
|
||||
void EditCombatNetRadioDialog::setUiValues(const CnrConfig &cnrConfig)
|
||||
{
|
||||
if(m_isGlobal)
|
||||
setUiValuesForGlobal();
|
||||
|
||||
m_ui->chkGlobal->setChecked(m_isGlobal);
|
||||
initCbChannels(cnrConfig.cnrChannelId());
|
||||
bool disableParty = (m_avmDtc->cnrChannel(cnrConfig.cnrChannelId()).frequencyBand() == FrequencyBand_def::REL) || m_isGlobal;
|
||||
if (!disableParty)
|
||||
{
|
||||
m_ui->cbParty->setCurrentIndex(m_ui->cbParty->findData(cnrConfig.partyId()));
|
||||
int unitId = cnrConfig.unitId().is_set() ? cnrConfig.unitId().get() : 0;
|
||||
m_ui->cbUnit->setCurrentIndex(m_ui->cbUnit->findData(unitId));
|
||||
}
|
||||
m_ui->leCallSign->setText(QString::fromStdString(cnrConfig.callSign()));
|
||||
m_ui->chkRecording->setChecked(cnrConfig.recording());
|
||||
m_ui->leRadioCircuit->setText(QString::fromStdString(cnrConfig.radioCircuit()));
|
||||
onPartyIndexChanged(cnrConfig.partyId());
|
||||
|
||||
}
|
||||
|
||||
void EditCombatNetRadioDialog::setUiValuesForGlobal()
|
||||
{
|
||||
m_ui->chkGlobal->setChecked(true);
|
||||
m_ui->cbUnit->setEnabled(false);
|
||||
m_ui->lbUnit->setEnabled(false);
|
||||
// m_ui->cbParty->addItem(QStringLiteral("-"));
|
||||
// m_ui->cbParty->setCurrentText(QStringLiteral("-"));
|
||||
m_ui->cbParty->setCurrentIndex(m_ui->cbParty->findData(1)); // Fixed on O/C as Ulli requested...
|
||||
m_ui->cbParty->setEnabled(false);
|
||||
m_ui->lbParty->setEnabled(false);
|
||||
}
|
||||
|
||||
ModifyCnrConfigRequest EditCombatNetRadioDialog::createRequest()
|
||||
{
|
||||
ModifyCnrConfigRequest request;
|
||||
|
||||
request.id(m_id.get_value_or(0));
|
||||
request.callSign(m_ui->leCallSign->text().toStdString());
|
||||
request.cnrChannelId(m_ui->cbChannel->currentData().toInt());
|
||||
request.radioCircuit(m_ui->leRadioCircuit->text().toStdString());
|
||||
request.recording(m_ui->chkRecording->isChecked());
|
||||
request.partyId(m_ui->cbParty->currentData().toInt());
|
||||
if (!m_isGlobal)
|
||||
request.exerciseId(m_exerciseId);
|
||||
if (m_ui->cbUnit->currentIndex() > 0)
|
||||
request.unitId().set(m_ui->cbUnit->currentIndex());
|
||||
return request;
|
||||
}
|
||||
|
||||
bool EditCombatNetRadioDialog::apply()
|
||||
{
|
||||
ModifyCnrConfigRequest request = createRequest();
|
||||
|
||||
if (m_ui->cbUnit->currentIndex() > 0)
|
||||
{
|
||||
request.unitId().set(m_ui->cbUnit->currentData().toInt());
|
||||
INFO_LOG(m_logger)<< "currentIndex="<<m_ui->cbUnit->currentIndex()
|
||||
<< " unitId ="<<request.unitId().get();
|
||||
}
|
||||
|
||||
return m_requestHelper->startSingleRequest([this, request]()
|
||||
{
|
||||
return m_avmFtc->modifyCnrConfigRequest(request, this);
|
||||
});
|
||||
}
|
||||
|
||||
void EditCombatNetRadioDialog::init(LtsSession::LtsSession *session)
|
||||
{
|
||||
m_units = m_ppmDtc->units();
|
||||
|
||||
QMap<qint32, ParticipantManagement::Party> parties;
|
||||
if (!m_ppmDtc->visibleParties(parties, LtsSessionData::LtsSessionData::getInstance()->getVisibleParties(m_exerciseId)))
|
||||
ERROR_LOG(m_logger) << "Could not retrieve visible Parties!";
|
||||
|
||||
for (const ParticipantManagement::Party &party : qAsConst(parties))
|
||||
m_ui->cbParty->addItem(ParticipantManagement::trPartyName(party.name()), party.id());
|
||||
|
||||
connect(m_ui->cbParty, QOverload<int>::of(&LtsWidgets::LtsComboBox::currentIndexChanged), this, &EditCombatNetRadioDialog::onPartyIndexChanged);
|
||||
connect(m_ui->cbChannel, QOverload<int>::of(&LtsWidgets::LtsComboBox::currentIndexChanged), this, &EditCombatNetRadioDialog::onChannelChanged);
|
||||
connect(m_avmDtc.get(), &Interface::Dtc::cnrConfigChanged, this, &EditCombatNetRadioDialog::updateFreeChannelsAndTakenNames);
|
||||
connect(m_exmDtc, &ExerciseManagement::Interface::Dtc::exerciseChanged, this, &EditCombatNetRadioDialog::updateFreeChannelsAndTakenNames);
|
||||
|
||||
onPartyIndexChanged(m_ui->cbParty->currentIndex());
|
||||
|
||||
// Save/Load from Library Button
|
||||
m_buttonBox->connectLibraryButton(this,
|
||||
&EditCombatNetRadioDialog::onImportButtonClicked,
|
||||
&EditCombatNetRadioDialog::onExportButtonClicked);
|
||||
|
||||
if (!session->getForeignGuiInterface<FileManagement::ForeignGuiInterface>(m_flmGui))
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Library, false);
|
||||
|
||||
|
||||
m_uiRequirements->addRequirement({m_ui->lbRadioCircuit, [this] () { return isNameValid(m_ui->leRadioCircuit->text()); }, tr("name invalid")});
|
||||
m_uiRequirements->addRequirement({m_ui->lbChannel, [this] () { return m_ui->cbChannel->currentData().toInt() > 0; }, tr("channel invalid")});
|
||||
}
|
||||
|
||||
void EditCombatNetRadioDialog::initCbChannelsForCreate()
|
||||
{
|
||||
Q_ASSERT(!m_id.is_initialized());
|
||||
Q_ASSERT(m_ui->cbChannel->count() == 0);
|
||||
updateFreeChannelsAndTakenNames();
|
||||
if (m_ui->cbChannel->count())
|
||||
m_ui->cbChannel->setCurrentIndex(0); // select the first free channel
|
||||
else
|
||||
m_ui->cbChannel->addItem(NO_CHANNEL(), -1);
|
||||
}
|
||||
|
||||
void EditCombatNetRadioDialog::initCbChannels(int channelId)
|
||||
{
|
||||
m_ui->cbChannel->clear();
|
||||
updateFreeChannelsAndTakenNames();
|
||||
m_ui->cbChannel->setCurrentIndex(m_ui->cbChannel->findData(channelId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when one of the following changed:
|
||||
* - Some Exercise
|
||||
* - Some CnrConfig
|
||||
*/
|
||||
void EditCombatNetRadioDialog::updateFreeChannelsAndTakenNames()
|
||||
{
|
||||
const auto exercisesConsider = exercisesToConsider();
|
||||
const auto exercisesIgnore = exercisesToIgnore();
|
||||
|
||||
m_takenNames.clear();
|
||||
|
||||
QVector<int> freeChannels = m_avmDtc->cnrChannels().keys().toVector();
|
||||
QMap<int, QString> channelsToDisable; //<cnrChannelId, disable reason>
|
||||
QMap<int, QString> exerciseNameCache;
|
||||
const auto allCnrConfigs = m_avmDtc->cnrConfigs();
|
||||
const ExerciseManagement::Exercise ownExercise = m_exmDtc->exercise(m_exerciseId);
|
||||
ExerciseManagement::ExerciseState ownState = m_exmDtc->exercise(m_exerciseId).state();
|
||||
|
||||
for (const AudioVideoManagement::CnrConfig &cnrConfig : allCnrConfigs)
|
||||
{
|
||||
if (m_id.is_initialized() && *m_id == cnrConfig.id())
|
||||
continue; // consider the channel of the CnrConfig we are editing right now as free
|
||||
|
||||
if (ownExercise.state() == ExerciseManagement::ExerciseState::Created && cnrConfig.exerciseId() != m_exerciseId)
|
||||
{
|
||||
if (ownExercise.linkedExerciseId() < 1 || cnrConfig.exerciseId() != ownExercise.linkedExerciseId())
|
||||
continue;
|
||||
|
||||
if (!exerciseNameCache.contains(ownExercise.linkedExerciseId()))
|
||||
exerciseNameCache.insert(ownExercise.linkedExerciseId(), QString::fromStdString(m_exmDtc->exercise(ownExercise.linkedExerciseId()).name()));
|
||||
|
||||
channelsToDisable.insert(cnrConfig.cnrChannelId(), tr("(already taken in %1)").arg(exerciseNameCache.value(ownExercise.linkedExerciseId())));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ownExercise.state() == ExerciseManagement::ExerciseState::Started || ownExercise.state() == ExerciseManagement::ExerciseState::Paused)
|
||||
{
|
||||
if (cnrConfig.exerciseId().is_set())
|
||||
{
|
||||
int cnrExerciseId = cnrConfig.exerciseId().get();
|
||||
|
||||
if (exercisesConsider.contains(cnrExerciseId) && cnrExerciseId != m_exerciseId)
|
||||
{
|
||||
if (!exerciseNameCache.contains(cnrExerciseId))
|
||||
exerciseNameCache.insert(cnrExerciseId, QString::fromStdString(m_exmDtc->exercise(cnrExerciseId).name()));
|
||||
|
||||
channelsToDisable.insert(cnrConfig.cnrChannelId(), tr("(already taken in %1)").arg(exerciseNameCache.value(cnrExerciseId)));
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_isGlobal)
|
||||
{
|
||||
if (cnrConfig.exerciseId().is_set() && !exercisesConsider.contains(cnrConfig.exerciseId().get()))
|
||||
continue;
|
||||
|
||||
if (!cnrConfig.exerciseId().is_set() && ownState != ExerciseManagement::ExerciseState::Created)
|
||||
{
|
||||
channelsToDisable.insert(cnrConfig.cnrChannelId(), tr("(already taken in global exercise)"));
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_isGlobal && cnrConfig.exerciseId().is_set() && exercisesConsider.contains(cnrConfig.exerciseId().get()))
|
||||
{
|
||||
int exerciseId = cnrConfig.exerciseId().get();
|
||||
|
||||
if (!exerciseNameCache.contains(exerciseId))
|
||||
exerciseNameCache.insert(exerciseId, QString::fromStdString(m_exmDtc->exercise(exerciseId).name()));
|
||||
|
||||
channelsToDisable.insert(cnrConfig.cnrChannelId(), tr("(already taken in %1)").arg(exerciseNameCache.value(exerciseId)));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cnrConfig.exerciseId().is_set() && exercisesIgnore.contains(cnrConfig.exerciseId().get()))
|
||||
continue;
|
||||
|
||||
m_takenNames.push_back(QString::fromStdString(cnrConfig.radioCircuit()));
|
||||
|
||||
freeChannels.removeOne(cnrConfig.cnrChannelId());
|
||||
}
|
||||
|
||||
if (m_id.is_initialized())
|
||||
{
|
||||
if (freeChannels.contains(*m_channelId))
|
||||
updateCbChannels({*m_channelId}, {});
|
||||
else
|
||||
updateCbChannels({},{});
|
||||
}
|
||||
else
|
||||
updateCbChannels(std::move(freeChannels), std::move(channelsToDisable));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the channel-Combobox with the given freeChannels and keep the currently
|
||||
* selected channel if possible.
|
||||
*/
|
||||
void EditCombatNetRadioDialog::updateCbChannels(QVector<int> &&freeChannels, QMap<int, QString> &&channelsToDisable)
|
||||
{
|
||||
const auto allChannels = m_avmDtc->cnrChannels();
|
||||
|
||||
const auto byName = [&allChannels] (int leftChannelId, int rightChannelId) { return QLatin1String(allChannels[leftChannelId].name().c_str()) < QLatin1String(allChannels[rightChannelId].name().c_str()); };
|
||||
std::sort(freeChannels.begin(), freeChannels.end(), byName);
|
||||
|
||||
bool bOk;
|
||||
int currentlySelectedChannelId = m_ui->cbChannel->currentData().toInt(&bOk); // -1 when no channel was selected
|
||||
|
||||
if (!bOk)
|
||||
{
|
||||
currentlySelectedChannelId = -1;
|
||||
|
||||
if (freeChannels.count() && channelsToDisable.contains(freeChannels.at(0)))
|
||||
{
|
||||
currentlySelectedChannelId = freeChannels.at(0);
|
||||
|
||||
while (channelsToDisable.contains(currentlySelectedChannelId))
|
||||
{
|
||||
int channelIndex = freeChannels.indexOf(currentlySelectedChannelId);
|
||||
|
||||
if (channelIndex == freeChannels.size() - 1)
|
||||
{
|
||||
currentlySelectedChannelId = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
currentlySelectedChannelId = freeChannels.at(channelIndex + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_ui->cbChannel->clear();
|
||||
for (const auto &channelId : freeChannels)
|
||||
{
|
||||
QString channelName = QString::fromStdString(allChannels[channelId].name());
|
||||
|
||||
if (channelsToDisable.contains(channelId))
|
||||
{
|
||||
QString text = QLatin1String("%1 %2").arg(channelName).arg(channelsToDisable.value(channelId));
|
||||
m_ui->cbChannel->addItem(text, channelId);
|
||||
|
||||
auto * model = qobject_cast<QStandardItemModel*>(m_ui->cbChannel->model());
|
||||
|
||||
if(!model)
|
||||
continue;
|
||||
|
||||
auto * item = model->item(m_ui->cbChannel->count() - 1);
|
||||
|
||||
if(!item)
|
||||
continue;
|
||||
|
||||
item->setEnabled(false);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
m_ui->cbChannel->addItem(channelName, channelId);
|
||||
}
|
||||
|
||||
if (!m_ui->cbChannel->count())
|
||||
m_ui->cbChannel->addItem(NO_CHANNEL(), -1);
|
||||
else if (freeChannels.size() == 1)
|
||||
m_ui->cbChannel->setCurrentIndex(m_ui->cbChannel->findData(currentlySelectedChannelId));
|
||||
else if (currentlySelectedChannelId != -1)
|
||||
QTimer::singleShot(100, this, [this, currentlySelectedChannelId] () { m_ui->cbChannel->setCurrentIndex(m_ui->cbChannel->findData(currentlySelectedChannelId)); });
|
||||
}
|
||||
|
||||
/**
|
||||
* If the current exercise is active or ex_0, return all active exercises.
|
||||
* If the current exercise is planned but linked to another exercise, return the linked exercise.
|
||||
* Otherwise, return only the current exercise.
|
||||
*/
|
||||
QVector<int> EditCombatNetRadioDialog::exercisesToConsider() const
|
||||
{
|
||||
auto isActive = [](ExerciseManagement::ExerciseState state) -> bool
|
||||
{
|
||||
return (state == ExerciseManagement::ExerciseState::Started ||
|
||||
state == ExerciseManagement::ExerciseState::Paused);
|
||||
};
|
||||
|
||||
const auto allExercises = m_exmDtc->exercises();
|
||||
const ExerciseManagement::Exercise ¤tExercise = allExercises.value(m_exerciseId);
|
||||
QVector<int> toBeConsidered;
|
||||
toBeConsidered.reserve(allExercises.size());
|
||||
|
||||
if (!m_isGlobal && currentExercise.state() == ExerciseManagement::ExerciseState::Created)
|
||||
{
|
||||
toBeConsidered.append(currentExercise.id());
|
||||
|
||||
if (currentExercise.linkedExerciseId() > 0)
|
||||
toBeConsidered.append(currentExercise.linkedExerciseId());
|
||||
|
||||
return toBeConsidered;
|
||||
}
|
||||
|
||||
if (!m_isGlobal && !isActive(allExercises[m_exerciseId].state()))
|
||||
return {m_exerciseId};
|
||||
|
||||
for (const auto &exercise : allExercises)
|
||||
{
|
||||
if (isActive(exercise.state()))
|
||||
toBeConsidered.append(exercise.id());
|
||||
}
|
||||
|
||||
return toBeConsidered;
|
||||
}
|
||||
|
||||
QVector<int> EditCombatNetRadioDialog::exercisesToIgnore() const
|
||||
{
|
||||
const auto allExercises = m_exmDtc->exercises();
|
||||
|
||||
auto canBeIgnored = [this] (const ExerciseManagement::Exercise &ex) -> bool
|
||||
{
|
||||
if (m_isGlobal)
|
||||
{
|
||||
return (ex.state() == ExerciseManagement::ExerciseState::Created ||
|
||||
ex.state() == ExerciseManagement::ExerciseState::Stopped ||
|
||||
ex.state() == ExerciseManagement::ExerciseState::Terminated ||
|
||||
ex.isDeleted());
|
||||
}
|
||||
return (ex.state() == ExerciseManagement::ExerciseState::Stopped ||
|
||||
ex.state() == ExerciseManagement::ExerciseState::Terminated ||
|
||||
ex.isDeleted());
|
||||
};
|
||||
|
||||
QVector<int> exercisesToIgnore;
|
||||
for (const auto &ex : allExercises)
|
||||
{
|
||||
if (canBeIgnored(ex))
|
||||
exercisesToIgnore += ex.id();
|
||||
}
|
||||
return exercisesToIgnore;
|
||||
}
|
||||
|
||||
|
||||
bool EditCombatNetRadioDialog::isNameValid(const QString &name) const
|
||||
{
|
||||
if (!isStreamNameValid(name))
|
||||
return false;
|
||||
if (m_takenNames.contains(name))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void EditCombatNetRadioDialog::onPartyIndexChanged(int index)
|
||||
{
|
||||
m_ui->cbUnit->clear();
|
||||
|
||||
m_ui->cbUnit->addItem(QLatin1String("-"), QVariant::fromValue(0));
|
||||
|
||||
int32_t partyId = m_ui->cbParty->itemData(index).toInt();
|
||||
|
||||
for (const ParticipantManagement::Participant &unit : qAsConst(m_units))
|
||||
{
|
||||
QString unitStr;
|
||||
if (unit.partyId() == partyId)
|
||||
{
|
||||
if (unit.designator().size() > 0)
|
||||
{
|
||||
unitStr = QString::fromStdString(unit.designator()) + QLatin1Char('/');
|
||||
INFO_LOG(m_logger)<<"Designator != leer: unitStr = " << unitStr;
|
||||
}
|
||||
unitStr += QString::fromStdString(unit.tacticalIdentifier());
|
||||
INFO_LOG(m_logger) << "unitStr =" << unitStr
|
||||
<< " id =" << unit.id();
|
||||
|
||||
m_ui->cbUnit->addItem(unitStr, unit.id());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EditCombatNetRadioDialog::onChannelChanged(int index)
|
||||
{
|
||||
int channelId = m_ui->cbChannel->itemData(index).toInt();
|
||||
|
||||
bool disableParty = (m_avmDtc->cnrChannel(channelId).frequencyBand() == FrequencyBand_def::REL) || m_isGlobal;
|
||||
m_ui->cbUnit->setDisabled(disableParty);
|
||||
m_ui->lbUnit->setDisabled(disableParty);
|
||||
m_ui->cbParty->setDisabled(disableParty);
|
||||
m_ui->lbParty->setDisabled(disableParty);
|
||||
if(disableParty && !m_isGlobal)
|
||||
{
|
||||
m_ui->cbParty->addItem(QStringLiteral("-"));
|
||||
m_ui->cbParty->setCurrentText(QStringLiteral("-"));
|
||||
}
|
||||
|
||||
}
|
||||
// REGG-4433: We need to revise in which way we store the CNR configs in the library.
|
||||
QByteArray EditCombatNetRadioDialog::cnrConfigRequestToJson()
|
||||
{
|
||||
ModifyCnrConfigRequest req = createRequest();
|
||||
|
||||
QJsonObject obj;
|
||||
obj[QStringLiteral("id")] = req.id();
|
||||
obj[QStringLiteral("XmlType")] = FileManagement::toString(FileManagement::XmlType::AVMEditCombatNetRadio);
|
||||
obj[QStringLiteral("callSign")] = QString::fromStdString(req.callSign());
|
||||
obj[QStringLiteral("cnrChannelId")] = req.cnrChannelId();
|
||||
obj[QStringLiteral("radioCircuit")] = QString::fromStdString(req.radioCircuit());
|
||||
obj[QStringLiteral("recording")] = req.recording();
|
||||
obj[QStringLiteral("partyId")] = req.partyId();
|
||||
obj[QStringLiteral("isGlobal")] = !req.exerciseId().is_set();
|
||||
if (req.unitId().is_set())
|
||||
obj[QStringLiteral("unitId")] = req.unitId().get();
|
||||
QJsonDocument doc(obj);
|
||||
return doc.toJson(QJsonDocument::Compact);
|
||||
}
|
||||
|
||||
ModifyCnrConfigRequest EditCombatNetRadioDialog::jsonToModifyCnrConfig(const QByteArray &content)
|
||||
{
|
||||
ModifyCnrConfigRequest result;
|
||||
const QJsonDocument doc(QJsonDocument::fromJson(content));
|
||||
const QJsonObject obj(doc.object());
|
||||
|
||||
result.id(obj[QStringLiteral("id")].toInt()); //TODO Library: check id = 0?
|
||||
result.callSign(obj[QStringLiteral("callSign")].toString().toStdString());
|
||||
result.cnrChannelId(obj[QStringLiteral("cnrChannelId")].toInt());
|
||||
result.radioCircuit(obj[QStringLiteral("radioCircuit")].toString().toStdString());
|
||||
result.recording(obj[QStringLiteral("recording")].toInt());
|
||||
result.partyId(obj[QStringLiteral("partyId")].toInt());
|
||||
if (!obj.contains(QLatin1String("isGlobal")) || !obj[QLatin1String("isGlobal")].toBool())
|
||||
result.exerciseId(m_exerciseId);
|
||||
if (obj.contains(QStringLiteral("unitId")))
|
||||
result.unitId(obj[QStringLiteral("unitId")].toInt());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void EditCombatNetRadioDialog::onExportButtonClicked()
|
||||
{
|
||||
QByteArray byteArray = cnrConfigRequestToJson();
|
||||
int fileId = m_flmGui->saveFileContent(this, FileManagement::FileType::Xml, m_exerciseId, byteArray);
|
||||
if (fileId > 0)
|
||||
DEBUG_LOG(m_logger) << "Saved file with id = " << fileId;
|
||||
else
|
||||
ERROR_LOG(m_logger) << "Could not save file in library ";
|
||||
}
|
||||
|
||||
void EditCombatNetRadioDialog::onImportButtonClicked()
|
||||
{
|
||||
DEBUG_LOG(m_logger) << " onImportButtonClicked() ";
|
||||
|
||||
QByteArray content;
|
||||
int fileId = m_flmGui->loadFileContent(this, content, {FileManagement::FileType::Xml}, m_exerciseId, FileManagement::toString(FileManagement::XmlType::AVMEditCombatNetRadio));
|
||||
if (fileId > 0)
|
||||
{
|
||||
if (!m_flmGui->isXmlType(content, FileManagement::toString(FileManagement::XmlType::AVMEditCombatNetRadio)))
|
||||
{
|
||||
QHash<LtsWidgets::Button, QString> texts({{LtsWidgets::Button::Yes, tr("Ok")}});
|
||||
LtsWidgets::LtsMessageDialog::showMessage(this,
|
||||
tr("Invalid xml file content"),
|
||||
windowTitle(),
|
||||
LtsWidgets::Behaviour::Modal,
|
||||
LtsWidgets::Button::Yes,
|
||||
texts);
|
||||
}
|
||||
else
|
||||
{
|
||||
ModifyCnrConfigRequest req = jsonToModifyCnrConfig(content);
|
||||
setUiValues(toConfig(req));
|
||||
INFO_LOG(m_logger) << "--- onImportButtonClicked() ";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace AudioVideoManagement
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* The EditCombatNetRadioDialog allows to set data for a CNR Config
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Hannes Baeuerle, SLSE, 2017-08-18
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LtsWidgets/lts_dialog.h>
|
||||
|
||||
#include <AudioVideoManagement/logger.h>
|
||||
#include <ParticipantManagement/ppm_dtc.h>
|
||||
#include <AudioVideoManagement/avm_dtc.h>
|
||||
#include <AudioVideoManagement/avm_ftc.h>
|
||||
#include <LtsUtilsGuiDds/request_helper.h>
|
||||
#include <LtsSession/lts_session.h>
|
||||
#include <Plugins/FileManagement/flm_explorer_gui_plugin_interface.h>
|
||||
#include <QVector>
|
||||
#include <QString>
|
||||
#include <boost/optional.hpp>
|
||||
#include <memory>
|
||||
|
||||
class QCheckBox;
|
||||
|
||||
namespace ExerciseManagement
|
||||
{
|
||||
namespace Interface
|
||||
{
|
||||
class Dtc;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class EditCombatNetRadioDialog;
|
||||
}
|
||||
|
||||
namespace AudioVideoManagement
|
||||
{
|
||||
class EditCombatNetRadioDialog
|
||||
: public LtsWidgets::LtsDialog
|
||||
, protected Interface::Ftc::ModifyCnrConfigReplyHandler
|
||||
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
/**
|
||||
* Used to create a new CnrConfig.
|
||||
*/
|
||||
explicit EditCombatNetRadioDialog(int32_t exerciseId,
|
||||
LtsSession::LtsSession *session,
|
||||
const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc,
|
||||
const std::shared_ptr<Interface::Dtc> &avmDtc,
|
||||
const std::shared_ptr<Interface::Ftc> &avmFtc,
|
||||
ExerciseManagement::Interface::Dtc *exmDtc,
|
||||
QWidget *parent);
|
||||
|
||||
/**
|
||||
* Used for modifying an existing CnrConfig.
|
||||
*/
|
||||
explicit EditCombatNetRadioDialog(const CnrConfig &cnrConfig,
|
||||
int32_t exerciseId,
|
||||
LtsSession::LtsSession *session,
|
||||
const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc,
|
||||
const std::shared_ptr<Interface::Dtc> &avmDtc,
|
||||
const std::shared_ptr<Interface::Ftc> &avmFtc,
|
||||
ExerciseManagement::Interface::Dtc *exmDtc,
|
||||
QWidget *parent);
|
||||
|
||||
~EditCombatNetRadioDialog();
|
||||
|
||||
void retranslate() override;
|
||||
|
||||
void onModifyCnrConfigReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
|
||||
|
||||
protected:
|
||||
bool apply() override;
|
||||
|
||||
private: // methods
|
||||
EditCombatNetRadioDialog(const boost::optional<int32_t> &id,
|
||||
int32_t exerciseId,
|
||||
LtsSession::LtsSession *session,
|
||||
const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc,
|
||||
const std::shared_ptr<Interface::Dtc> &avmDtc,
|
||||
const std::shared_ptr<Interface::Ftc> &avmFtc,
|
||||
ExerciseManagement::Interface::Dtc *exmDtc,
|
||||
QWidget *parent);
|
||||
|
||||
void init(LtsSession::LtsSession *session);
|
||||
|
||||
void initCbChannelsForCreate();
|
||||
void initCbChannels(int channelId);
|
||||
void updateFreeChannelsAndTakenNames();
|
||||
void updateCbChannels(QVector<int> &&freeChannels, QMap<int, QString> &&channelsToDisable);
|
||||
QVector<int> exercisesToConsider() const;
|
||||
QVector<int> exercisesToIgnore() const;
|
||||
bool isNameValid(const QString &name) const;
|
||||
|
||||
QByteArray cnrConfigRequestToJson();
|
||||
ModifyCnrConfigRequest createRequest();
|
||||
ModifyCnrConfigRequest jsonToModifyCnrConfig(const QByteArray &content);
|
||||
void setUiValues(const CnrConfig &cnrConfig);
|
||||
void setUiValuesForGlobal();
|
||||
|
||||
private Q_SLOTS:
|
||||
void onPartyIndexChanged(int index);
|
||||
void onExportButtonClicked();
|
||||
void onImportButtonClicked();
|
||||
void onChannelChanged(int index);
|
||||
|
||||
private: // attributes
|
||||
std::unique_ptr<Ui::EditCombatNetRadioDialog> m_ui;
|
||||
boost::optional<int32_t> m_id; //!< only set when editing
|
||||
int32_t m_exerciseId;
|
||||
boost::optional<int32_t> m_channelId; //!< only set when editing
|
||||
std::shared_ptr<ParticipantManagement::Interface::Dtc> m_ppmDtc;
|
||||
std::shared_ptr<Interface::Dtc> m_avmDtc;
|
||||
std::shared_ptr<Interface::Ftc> m_avmFtc;
|
||||
ExerciseManagement::Interface::Dtc *m_exmDtc;
|
||||
std::shared_ptr<FileManagement::ForeignGuiInterface> m_flmGui;
|
||||
QMap<int32_t, ParticipantManagement::Participant> m_units;
|
||||
QVector<QString> m_takenNames;
|
||||
std::unique_ptr<LtsUtils::RequestHelper> m_requestHelper;
|
||||
bool m_isGlobal;
|
||||
|
||||
LOGGER_T m_logger;
|
||||
}; // class EditCombatNetRadioDialog
|
||||
} // namespace AudioVideoManagement
|
||||
+164
@@ -0,0 +1,164 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>EditCombatNetRadioDialog</class>
|
||||
<widget class="QWidget" name="EditCombatNetRadioDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>459</width>
|
||||
<height>275</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">Asset Stocks</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="lbChannel">
|
||||
<property name="text">
|
||||
<string>Channel Number:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="LtsWidgets::LtsComboBox" name="cbChannel"/>
|
||||
</item>
|
||||
<item row="0" column="2" rowspan="4">
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QLabel" name="lbRecording">
|
||||
<property name="text">
|
||||
<string>Recording:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<widget class="QCheckBox" name="chkRecording">
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="lbRadioCircuit">
|
||||
<property name="text">
|
||||
<string>Radio Circuit:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="leRadioCircuit">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Radio Circuit</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<widget class="QLabel" name="lbParty">
|
||||
<property name="text">
|
||||
<string>Party:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="4">
|
||||
<widget class="LtsWidgets::LtsComboBox" name="cbParty">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="lbCallSign">
|
||||
<property name="text">
|
||||
<string>Code Word:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="leCallSign">
|
||||
<property name="toolTip">
|
||||
<string>Code Word</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
<widget class="QLabel" name="lbUnit">
|
||||
<property name="text">
|
||||
<string>Unit:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="4">
|
||||
<widget class="LtsWidgets::LtsComboBox" name="cbUnit"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="lbGlobal">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Global:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="chkGlobal">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>LtsWidgets::LtsComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>LtsWidgets/lts_combo_box.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>cbChannel</tabstop>
|
||||
<tabstop>leRadioCircuit</tabstop>
|
||||
<tabstop>leCallSign</tabstop>
|
||||
<tabstop>cbParty</tabstop>
|
||||
<tabstop>cbUnit</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* The LoadCombatNetRadioDialog allows to solve config for loaded CNR Configs
|
||||
* $Id: avm_edit_combat_net_radio_dialog.h 60982 2023-12-01 10:18:25Z eberlein_v $
|
||||
* $HeadURL: svn://192.168.133.21/TDS/branches/product/features/optfunk/Lts/Plugins/AudioVideoManagement/Gui/CombatNetRadio/CombatNetRadioConfiguration/avm_edit_combat_net_radio_dialog.h $
|
||||
* $Author: eberlein_v $
|
||||
* Created by Hannes Fritsche, ESZS, 2024-01-30
|
||||
*/
|
||||
|
||||
#include "avm_load_combat_net_radio_dialog.h"
|
||||
#include "ui_avm_load_combat_net_radio_dialog.h"
|
||||
|
||||
#include "avm_cnr_json_helper.h"
|
||||
#include "avm_load_combat_net_radio_dialog_model.h"
|
||||
|
||||
namespace AudioVideoManagement
|
||||
{
|
||||
LoadCombatNetRadioDialog::LoadCombatNetRadioDialog(const QByteArray &data,
|
||||
LtsSession::LtsSession *session,
|
||||
QWidget *parent)
|
||||
: LtsWidgets::LtsFramelessDialog(parent, LtsWidgets::Behaviour::Modal)
|
||||
, m_ui(new Ui::LoadCombatNetRadioDialog)
|
||||
, m_model(new LoadCombatNetRadioDialogModel(data, session))
|
||||
, m_logger(getLogger("LoadCombatNetRadioDialog"))
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
m_ui->dataView->setModel(m_model);
|
||||
m_ui->cbAll->setChecked(m_model->allChecked());
|
||||
|
||||
connect(m_ui->cbAll, &QCheckBox::clicked,
|
||||
m_model, &LoadCombatNetRadioDialogModel::setCheckState);
|
||||
connect(m_model, &LoadCombatNetRadioDialogModel::dataChanged,
|
||||
this, [this](const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles)
|
||||
{
|
||||
if (!roles.contains(Qt::CheckStateRole)
|
||||
|| topLeft.column() != 0
|
||||
|| bottomRight.column() != 0
|
||||
|| m_ui->cbAll->isChecked() == m_model->allChecked())
|
||||
return;
|
||||
|
||||
const QSignalBlocker blocker(m_ui->cbAll);
|
||||
|
||||
Q_UNUSED(blocker);
|
||||
|
||||
m_ui->cbAll->setChecked(!m_ui->cbAll->isChecked());
|
||||
});
|
||||
connect(m_ui->pbOk, &QPushButton::clicked,
|
||||
this, &LoadCombatNetRadioDialog::onOk);
|
||||
connect(m_ui->pbCancel, &QPushButton::clicked,
|
||||
this, &LoadCombatNetRadioDialog::close);
|
||||
}
|
||||
|
||||
QVector<Core::RemoveElementRequest> LoadCombatNetRadioDialog::removeRequests() const
|
||||
{
|
||||
if (m_isApplied)
|
||||
return m_model->removeRequests();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
QVector<ModifyCnrConfigRequest> LoadCombatNetRadioDialog::modifyRequests() const
|
||||
{
|
||||
if (m_isApplied)
|
||||
return m_model->modifyRequests();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
bool LoadCombatNetRadioDialog::isApplied() const
|
||||
{
|
||||
return m_isApplied;
|
||||
}
|
||||
|
||||
void LoadCombatNetRadioDialog::onOk()
|
||||
{
|
||||
m_isApplied = true;
|
||||
close();
|
||||
}
|
||||
|
||||
LoadCombatNetRadioDialog::~LoadCombatNetRadioDialog() = default;
|
||||
|
||||
} // namespace AudioVideoManagement
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* The LoadCombatNetRadioDialog allows to solve config for loaded CNR Configs
|
||||
* $Id: avm_edit_combat_net_radio_dialog.h 60982 2023-12-01 10:18:25Z eberlein_v $
|
||||
* $HeadURL: svn://192.168.133.21/TDS/branches/product/features/optfunk/Lts/Plugins/AudioVideoManagement/Gui/CombatNetRadio/CombatNetRadioConfiguration/avm_edit_combat_net_radio_dialog.h $
|
||||
* $Author: eberlein_v $
|
||||
* Created by Hannes Fritsche, ESZS, 2024-01-30
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LtsWidgets/lts_frameless_dialog.h>
|
||||
#include <AudioVideoManagement/avm_dtc.h>
|
||||
#include <AudioVideoManagement/logger.h>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class LoadCombatNetRadioDialog;
|
||||
}
|
||||
|
||||
namespace LtsSession
|
||||
{
|
||||
class LtsSession;
|
||||
}
|
||||
|
||||
namespace ParticipantManagement
|
||||
{
|
||||
namespace Interface
|
||||
{
|
||||
class Dtc;
|
||||
}
|
||||
}
|
||||
|
||||
namespace ExerciseManagement
|
||||
{
|
||||
namespace Interface
|
||||
{
|
||||
class Dtc;
|
||||
}
|
||||
}
|
||||
|
||||
namespace AudioVideoManagement
|
||||
{
|
||||
class LoadCombatNetRadioDialogModel;
|
||||
|
||||
class LoadCombatNetRadioDialog
|
||||
: public LtsWidgets::LtsFramelessDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit LoadCombatNetRadioDialog(const QByteArray &data,
|
||||
LtsSession::LtsSession *session,
|
||||
QWidget *parent = nullptr);
|
||||
|
||||
~LoadCombatNetRadioDialog();
|
||||
|
||||
QVector<Core::RemoveElementRequest> removeRequests() const;
|
||||
QVector<ModifyCnrConfigRequest> modifyRequests() const;
|
||||
|
||||
bool isApplied() const;
|
||||
|
||||
private Q_SLOTS:
|
||||
void onOk();
|
||||
|
||||
private: // attributes
|
||||
std::unique_ptr<Ui::LoadCombatNetRadioDialog> m_ui;
|
||||
LoadCombatNetRadioDialogModel *m_model;
|
||||
bool m_isApplied = false;
|
||||
|
||||
LOGGER_T m_logger;
|
||||
}; // class LoadCombatNetRadioDialog
|
||||
} // namespace AudioVideoManagement
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>LoadCombatNetRadioDialog</class>
|
||||
<widget class="QWidget" name="LoadCombatNetRadioDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>922</width>
|
||||
<height>376</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">Load Cnr Configs</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="cbAll">
|
||||
<property name="text">
|
||||
<string>Check/Uncheck all</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="LtsDataView::LtsDataView" name="dataView" native="true"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbOk">
|
||||
<property name="text">
|
||||
<string>Ok</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbCancel">
|
||||
<property name="text">
|
||||
<string>Cancel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>LtsDataView::LtsDataView</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>LtsDataView/lts_data_view.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
+434
@@ -0,0 +1,434 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* The LoadCombatNetRadioDialogModel provices data for LoadCombatNetRadioDialog
|
||||
* $Id: avm_combat_net_radio_dialog_model.h 60985 2023-12-01 11:53:28Z eberlein_v $
|
||||
* $HeadURL: svn://192.168.133.21/TDS/branches/product/features/optfunk/Lts/Plugins/AudioVideoManagement/Gui/CombatNetRadio/CombatNetRadioConfiguration/avm_combat_net_radio_dialog_model.h $
|
||||
* $Author: eberlein_v $
|
||||
* Created by Hannes Fritsche, ESZS, 2023-01-30
|
||||
*/
|
||||
|
||||
#include "avm_load_combat_net_radio_dialog_model.h"
|
||||
#include <ParticipantManagement/ppm_translation.h>
|
||||
#include <LtsSession/lts_session_data.h>
|
||||
#include <AudioVideoManagement/avm_ftc.h>
|
||||
#include <Core/core.hpp>
|
||||
|
||||
#include <FileManagement/flm_translation.h>
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonDocument>
|
||||
#include "avm_cnr_json_helper.h"
|
||||
|
||||
#include <LtsSession/lts_session.h>
|
||||
|
||||
#include <ExerciseManagement/exm_data_plugin_interface.h>
|
||||
#include <AudioVideoManagement/avm_data_plugin_interface.h>
|
||||
|
||||
namespace AudioVideoManagement
|
||||
{
|
||||
|
||||
LoadCombatNetRadioDialogModel::LoadCombatNetRadioDialogModel(const QByteArray &data,
|
||||
LtsSession::LtsSession *session,
|
||||
QObject *parent)
|
||||
: LtsAbstractTableModel<CnrConfig>(
|
||||
{
|
||||
tr("Include"),
|
||||
tr("Channel"),
|
||||
tr("Radio Circuit"),
|
||||
tr("Code Word"),
|
||||
tr("Conflict(s)")
|
||||
}, parent)
|
||||
, m_exerciseId(session == nullptr ? 0 : session->exerciseId())
|
||||
, m_logger(getLogger("LoadCombatNetRadioDialogModel"))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Own exercise id: " << m_exerciseId;
|
||||
|
||||
if (session != nullptr)
|
||||
{
|
||||
std::shared_ptr<AudioVideoManagement::Interface::Dtc> avmDtc;
|
||||
|
||||
if (!session->getDtc<AudioVideoManagement::DataInterface>(avmDtc)
|
||||
|| !avmDtc->enableCnrChannel()
|
||||
|| !avmDtc->enableCnrConfig())
|
||||
ERROR_LOG(m_logger) << "Could not get AVM data";
|
||||
else
|
||||
{
|
||||
m_cnrChannels = avmDtc->cnrChannels();
|
||||
m_cnrConfigs = avmDtc->cnrConfigs();
|
||||
}
|
||||
|
||||
DEBUG_LOG(m_logger) << "cnrconfigs: " << m_cnrConfigs.size();
|
||||
DEBUG_LOG(m_logger) << "ownExerciseId: " << m_exerciseId;
|
||||
|
||||
std::shared_ptr<ExerciseManagement::Interface::Dtc> exmDtc;
|
||||
|
||||
if (!session->getDtc<ExerciseManagement::DataInterface>(exmDtc)
|
||||
|| !exmDtc->enableExercise())
|
||||
ERROR_LOG(m_logger) << "Could not get EXM data";
|
||||
else
|
||||
m_exercises = exmDtc->exercises();
|
||||
|
||||
DEBUG_LOG(m_logger) << "exercises: " << m_exercises.size();
|
||||
}
|
||||
else
|
||||
ERROR_LOG(m_logger) << "Got invalid session.";
|
||||
|
||||
m_vecData = jsonToCnrConfigVector(data);
|
||||
|
||||
m_includeStates.reserve(m_vecData.size());
|
||||
m_conflicts.reserve(m_vecData.size());
|
||||
|
||||
for (int32_t idxCounter = 0; idxCounter < m_vecData.size(); ++idxCounter)
|
||||
{
|
||||
Conflicts conflicts = getConflicts(idxCounter, m_vecData.at(idxCounter));
|
||||
|
||||
m_conflicts.append(conflicts);
|
||||
m_includeStates.append(conflicts == NO_CONFLICT ? Qt::Checked : Qt::Unchecked);
|
||||
|
||||
if (conflicts & CHANNEL_TAKEN_IN_GLOBAL || conflicts & RADIO_CIRCUIT_TAKEN_IN_GLOBAL) // these conflicts must not be solved, so we disable the rows
|
||||
m_disabledRows.append(idxCounter);
|
||||
}
|
||||
}
|
||||
|
||||
Qt::ItemFlags LoadCombatNetRadioDialogModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
if (indexIsValid(index) && m_disabledRows.contains(index.row()))
|
||||
return Qt::NoItemFlags;
|
||||
|
||||
if (index.column() > 0)
|
||||
return LtsAbstractTableModel::flags(index);
|
||||
|
||||
return Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | LtsAbstractTableModel::flags(index);
|
||||
}
|
||||
|
||||
bool LoadCombatNetRadioDialogModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
if (indexIsValid(index)
|
||||
&& role == Qt::CheckStateRole
|
||||
&& index.column() == 0
|
||||
&& value.canConvert<Qt::CheckState>())
|
||||
{
|
||||
m_includeStates[index.row()] = value.value<Qt::CheckState>();
|
||||
|
||||
emit dataChanged(index, index, {role});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return QAbstractTableModel::setData(index, value, role);
|
||||
}
|
||||
|
||||
QVariant LoadCombatNetRadioDialogModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!indexIsValid(index))
|
||||
return QVariant();
|
||||
|
||||
switch (role)
|
||||
{
|
||||
case Qt::DisplayRole:
|
||||
{
|
||||
const CnrConfig &config = m_vecData.at(index.row());
|
||||
switch (index.column())
|
||||
{
|
||||
case CHANNEL:
|
||||
return QString::fromStdString(m_cnrChannels.value(config.cnrChannelId()).name());
|
||||
case RADIO_CIRCUIT:
|
||||
return QString::fromStdString(config.radioCircuit());
|
||||
case CALL_SIGN:
|
||||
return QString::fromStdString(config.callSign());
|
||||
case CONFLICTS:
|
||||
return conflictsText(m_conflicts.at(index.row()));
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
case Qt::CheckStateRole:
|
||||
if (index.column() != 0)
|
||||
return QVariant();
|
||||
return m_includeStates.at(index.row());
|
||||
case Qt::BackgroundRole:
|
||||
return getConflictsRowColor(m_conflicts.at(index.row()));
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
bool LoadCombatNetRadioDialogModel::allChecked() const
|
||||
{
|
||||
for (int32_t row = 0; row < m_includeStates.size(); ++row)
|
||||
{
|
||||
if (m_disabledRows.contains(row))
|
||||
continue;
|
||||
|
||||
if (m_includeStates.at(row) == Qt::Unchecked)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void LoadCombatNetRadioDialogModel::setCheckState(bool isChecked)
|
||||
{
|
||||
const QVariant data = QVariant(isChecked ? Qt::Checked : Qt::Unchecked);
|
||||
const int role = Qt::CheckStateRole;
|
||||
|
||||
for (int32_t row = 0; row < rowCount(); ++row)
|
||||
{
|
||||
if (m_disabledRows.contains(row))
|
||||
continue;
|
||||
|
||||
setData(createIndex(row, 0), data, role);
|
||||
}
|
||||
}
|
||||
|
||||
LoadCombatNetRadioDialogModel::Conflicts LoadCombatNetRadioDialogModel::getConflicts(int32_t row, const CnrConfig &config)
|
||||
{
|
||||
Conflicts conflicts = NO_CONFLICT;
|
||||
|
||||
for (auto it = m_cnrConfigs.constBegin(); it != m_cnrConfigs.constEnd(); ++it)
|
||||
{
|
||||
if (!(conflicts & RADIO_CIRCUIT_TAKEN_IN_OWN_CONFIG) && isRadioCircuitTakenInOwnConfig(config, it.value()))
|
||||
{
|
||||
conflicts |= RADIO_CIRCUIT_TAKEN_IN_OWN_CONFIG;
|
||||
addConflictedCnr(row, it.value().id());
|
||||
}
|
||||
|
||||
if (!(conflicts & RADIO_CIRCUIT_TAKEN_IN_ANOTHER_EXERCISE) && isRadioCircuitTakenInAnotherExercise(config, it.value()))
|
||||
{
|
||||
conflicts |= RADIO_CIRCUIT_TAKEN_IN_ANOTHER_EXERCISE;
|
||||
addConflictedCnr(row, it.value().id());
|
||||
}
|
||||
|
||||
if (!(conflicts & CHANNEL_TAKEN_IN_ACTIVE_EXERCISE) && isChannelTakenInActiveExercise(config, it.value()))
|
||||
{
|
||||
conflicts |= CHANNEL_TAKEN_IN_ACTIVE_EXERCISE;
|
||||
addConflictedCnr(row, it.value().id());
|
||||
}
|
||||
|
||||
if (!(conflicts & CHANNEL_TAKEN_IN_LINKED_EXERCISE) && isChannelTakenInLinkedExercise(config, it.value()))
|
||||
{
|
||||
conflicts |= CHANNEL_TAKEN_IN_LINKED_EXERCISE;
|
||||
addConflictedCnr(row, it.value().id());
|
||||
}
|
||||
|
||||
if (!(conflicts & CHANNEL_TAKEN_IN_OWN_CONFIG) && isChannelTakenInOwnConfig(config, it.value()))
|
||||
{
|
||||
conflicts |= CHANNEL_TAKEN_IN_OWN_CONFIG;
|
||||
addConflictedCnr(row, it.value().id());
|
||||
}
|
||||
|
||||
if (!(conflicts & CHANNEL_TAKEN_IN_GLOBAL) && isChannelTakenInGlobal(config, it.value()))
|
||||
{
|
||||
conflicts |= CHANNEL_TAKEN_IN_GLOBAL;
|
||||
addConflictedCnr(row, it.value().id());
|
||||
}
|
||||
|
||||
if (!(conflicts & RADIO_CIRCUIT_TAKEN_IN_GLOBAL) && isRadioCircuitTakenInGlobal(config, it.value()))
|
||||
{
|
||||
conflicts |= RADIO_CIRCUIT_TAKEN_IN_GLOBAL;
|
||||
addConflictedCnr(row, it.value().id());
|
||||
}
|
||||
}
|
||||
|
||||
return conflicts;
|
||||
}
|
||||
|
||||
QString LoadCombatNetRadioDialogModel::conflictsText(Conflicts conflicts) const
|
||||
{
|
||||
QStringList conflictTexts;
|
||||
|
||||
if (conflicts & RADIO_CIRCUIT_TAKEN_IN_OWN_CONFIG)
|
||||
conflictTexts.append(tr("Radio Circuit is already taken in own config."));
|
||||
|
||||
if (conflicts & RADIO_CIRCUIT_TAKEN_IN_ANOTHER_EXERCISE)
|
||||
conflictTexts.append(tr("Radio Circuit is already taken in another exercise."));
|
||||
|
||||
if (conflicts & CHANNEL_TAKEN_IN_ACTIVE_EXERCISE)
|
||||
conflictTexts.append(tr("Channel already taken in active exercise."));
|
||||
|
||||
if (conflicts & CHANNEL_TAKEN_IN_LINKED_EXERCISE)
|
||||
conflictTexts.append(tr("Channel already taken in linked exercise."));
|
||||
|
||||
if (conflicts & CHANNEL_TAKEN_IN_OWN_CONFIG)
|
||||
conflictTexts.append(tr("Channel is already taken in own Cnr Config."));
|
||||
|
||||
if (conflicts & CHANNEL_TAKEN_IN_GLOBAL)
|
||||
conflictTexts.append(tr("Channel already taken in global Cnr Config."));
|
||||
|
||||
if (conflicts & RADIO_CIRCUIT_TAKEN_IN_GLOBAL)
|
||||
conflictTexts.append(tr("Radio Circuit already taken in global Cnr Config."));
|
||||
|
||||
return conflictTexts.isEmpty() ? QLatin1String("-") : conflictTexts.join(QLatin1Char('\n'));
|
||||
}
|
||||
|
||||
void LoadCombatNetRadioDialogModel::addConflictedCnr(int32_t row, int32_t cnrConfigId)
|
||||
{
|
||||
m_conflictedCnrIds[row].append(cnrConfigId);
|
||||
}
|
||||
|
||||
bool LoadCombatNetRadioDialogModel::isActiveExercise(int32_t exerciseId) const
|
||||
{
|
||||
if (exerciseId == 0) // the global exercise is always active
|
||||
return true;
|
||||
|
||||
using namespace ExerciseManagement;
|
||||
|
||||
ExerciseState exerciseState = m_exercises.value(exerciseId).state();
|
||||
|
||||
return exerciseState == ExerciseState::Started || exerciseState == ExerciseState::Paused;
|
||||
}
|
||||
|
||||
QColor LoadCombatNetRadioDialogModel::getConflictsRowColor(Conflicts conflicts) const
|
||||
{
|
||||
if (conflicts >= CHANNEL_TAKEN_IN_GLOBAL)
|
||||
return QColor(Qt::red).lighter();
|
||||
|
||||
if (conflicts > NO_CONFLICT)
|
||||
return QColor(Qt::yellow).lighter();
|
||||
|
||||
return QColor(Qt::green).lighter();
|
||||
}
|
||||
|
||||
bool LoadCombatNetRadioDialogModel::isRadioCircuitTakenInOwnConfig(const CnrConfig &loadConfig, const CnrConfig &existingConfig) const
|
||||
{
|
||||
if (m_exerciseId == 0)
|
||||
return !existingConfig.exerciseId().is_set() && existingConfig.radioCircuit() == loadConfig.radioCircuit();
|
||||
|
||||
if (!existingConfig.exerciseId().is_set()
|
||||
|| existingConfig.exerciseId().get() != m_exerciseId
|
||||
|| existingConfig.radioCircuit() != loadConfig.radioCircuit())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LoadCombatNetRadioDialogModel::isRadioCircuitTakenInAnotherExercise(const CnrConfig &loadConfig, const CnrConfig &existingConfig) const
|
||||
{
|
||||
if (!isActiveExercise(m_exerciseId)
|
||||
|| !existingConfig.exerciseId().is_set()
|
||||
|| !isActiveExercise(existingConfig.exerciseId().get())
|
||||
|| existingConfig.exerciseId().get() == m_exerciseId
|
||||
|| existingConfig.radioCircuit() != loadConfig.radioCircuit())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LoadCombatNetRadioDialogModel::isChannelTakenInActiveExercise(const CnrConfig &loadConfig, const CnrConfig &existingConfig) const
|
||||
{
|
||||
int32_t exerciseId = existingConfig.exerciseId().is_set() ? existingConfig.exerciseId().get() : 0;
|
||||
|
||||
if (!isActiveExercise(m_exerciseId)
|
||||
|| exerciseId == 0
|
||||
|| exerciseId == m_exerciseId
|
||||
|| !isActiveExercise(exerciseId)
|
||||
|| existingConfig.cnrChannelId() != loadConfig.cnrChannelId()
|
||||
|| !isActiveExercise(exerciseId))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LoadCombatNetRadioDialogModel::isChannelTakenInLinkedExercise(const CnrConfig &loadConfig, const CnrConfig &existingConfig) const
|
||||
{
|
||||
if (m_exerciseId == 0 || m_exercises.value(m_exerciseId).linkedExerciseId() == 0)
|
||||
return false;
|
||||
|
||||
int32_t linkedExerciseId = m_exercises.value(m_exerciseId).linkedExerciseId();
|
||||
|
||||
int32_t exerciseId = existingConfig.exerciseId().is_set() ? existingConfig.exerciseId().get() : 0;
|
||||
|
||||
if (exerciseId != linkedExerciseId || existingConfig.cnrChannelId() != loadConfig.cnrChannelId())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LoadCombatNetRadioDialogModel::isChannelTakenInOwnConfig(const CnrConfig &loadConfig, const CnrConfig &existingConfig) const
|
||||
{
|
||||
int32_t exerciseId = existingConfig.exerciseId().is_set() ? existingConfig.exerciseId().get() : 0;
|
||||
|
||||
return existingConfig.cnrChannelId() == loadConfig.cnrChannelId() && exerciseId == m_exerciseId;
|
||||
}
|
||||
|
||||
bool LoadCombatNetRadioDialogModel::isChannelTakenInGlobal(const CnrConfig &loadConfig, const CnrConfig &existingConfig) const
|
||||
{
|
||||
if (!isActiveExercise(m_exerciseId)
|
||||
|| m_exerciseId == 0
|
||||
|| existingConfig.exerciseId().is_set()
|
||||
|| existingConfig.cnrChannelId() != loadConfig.cnrChannelId())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LoadCombatNetRadioDialogModel::isRadioCircuitTakenInGlobal(const CnrConfig &loadConfig, const CnrConfig &existingConfig) const
|
||||
{
|
||||
if (!isActiveExercise(m_exerciseId)
|
||||
|| m_exerciseId == 0
|
||||
|| existingConfig.exerciseId().is_set()
|
||||
|| existingConfig.radioCircuit() != loadConfig.radioCircuit())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QVector<Core::RemoveElementRequest> LoadCombatNetRadioDialogModel::removeRequests() const
|
||||
{
|
||||
QVector<Core::RemoveElementRequest> removeRequestsVec;
|
||||
|
||||
for (int32_t idxCounter = 0; idxCounter < m_includeStates.size(); ++idxCounter)
|
||||
{
|
||||
if (m_includeStates.at(idxCounter) == Qt::Checked && m_conflicts.at(idxCounter) != NO_CONFLICT)
|
||||
{
|
||||
if (!m_conflictedCnrIds.contains(idxCounter))
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Tried to get remove request for row " << idxCounter << " but it is not present.";
|
||||
continue;
|
||||
}
|
||||
|
||||
const QVector<int32_t> cnrConfigIds = m_conflictedCnrIds.value(idxCounter);
|
||||
|
||||
for (int32_t cnrConfigId : cnrConfigIds)
|
||||
{
|
||||
Core::RemoveElementRequest removeRequest(cnrConfigId);
|
||||
|
||||
if (!removeRequestsVec.contains(removeRequest))
|
||||
removeRequestsVec.append(removeRequest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return removeRequestsVec;
|
||||
}
|
||||
|
||||
QVector<ModifyCnrConfigRequest> LoadCombatNetRadioDialogModel::modifyRequests() const
|
||||
{
|
||||
const dds::core::optional<int32_t> exerciseId = m_exerciseId == 0 ? dds::core::optional<int32_t>() : dds::core::optional<int32_t>(m_exerciseId);
|
||||
const int32_t partyId = m_exerciseId == 0 ? 1 : 0;
|
||||
QVector<ModifyCnrConfigRequest> modifyRequestsVec;
|
||||
|
||||
modifyRequestsVec.reserve(m_includeStates.size());
|
||||
|
||||
for (int32_t row = 0; row < m_includeStates.size(); ++row)
|
||||
{
|
||||
if (m_includeStates.at(row) != Qt::Checked)
|
||||
continue;
|
||||
|
||||
const CnrConfig &cnrConfig = m_vecData.at(row);
|
||||
|
||||
modifyRequestsVec.append({0,
|
||||
cnrConfig.cnrChannelId(),
|
||||
exerciseId,
|
||||
cnrConfig.radioCircuit(),
|
||||
cnrConfig.recording(),
|
||||
{},
|
||||
partyId,
|
||||
cnrConfig.callSign()});
|
||||
}
|
||||
|
||||
return modifyRequestsVec;
|
||||
}
|
||||
|
||||
} // namespace AudioVideoManagement
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* The LoadCombatNetRadioDialogModel provices data for LoadCombatNetRadioDialog
|
||||
* $Id: avm_combat_net_radio_dialog_model.h 60985 2023-12-01 11:53:28Z eberlein_v $
|
||||
* $HeadURL: svn://192.168.133.21/TDS/branches/product/features/optfunk/Lts/Plugins/AudioVideoManagement/Gui/CombatNetRadio/CombatNetRadioConfiguration/avm_combat_net_radio_dialog_model.h $
|
||||
* $Author: eberlein_v $
|
||||
* Created by Hannes Fritsche, ESZS, 2023-01-30
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Proxies/CombatNetRadio/Helper/cnr_frequency_planning_helper.h>
|
||||
#include <LtsWidgets/lts_abstract_table_model.h>
|
||||
#include <LtsWidgets/lts_column_filter_proxy_model.h>
|
||||
#include <AudioVideoManagement/logger.h>
|
||||
#include <AudioVideoManagement/avm_dtc.h>
|
||||
#include <ExerciseManagement/exm_dtc.h>
|
||||
|
||||
namespace Core
|
||||
{
|
||||
class RemoveElementRequest;
|
||||
}
|
||||
|
||||
namespace ExerciseManagement
|
||||
{
|
||||
namespace Interface
|
||||
{
|
||||
class Dtc;
|
||||
}
|
||||
}
|
||||
|
||||
namespace LtsSession
|
||||
{
|
||||
class LtsSession;
|
||||
}
|
||||
|
||||
namespace AudioVideoManagement
|
||||
{
|
||||
|
||||
class LoadCombatNetRadioDialogModel final
|
||||
: public LtsWidgets::LtsAbstractTableModel<CnrConfig>
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum Columns
|
||||
{
|
||||
INCLUDE,
|
||||
CHANNEL,
|
||||
RADIO_CIRCUIT,
|
||||
CALL_SIGN,
|
||||
CONFLICTS
|
||||
};
|
||||
|
||||
enum Conflict
|
||||
{
|
||||
NO_CONFLICT = 0,
|
||||
RADIO_CIRCUIT_TAKEN_IN_OWN_CONFIG = 0b00000001,
|
||||
RADIO_CIRCUIT_TAKEN_IN_ANOTHER_EXERCISE = 0b00000010,
|
||||
CHANNEL_TAKEN_IN_ACTIVE_EXERCISE = 0b00000100,
|
||||
CHANNEL_TAKEN_IN_LINKED_EXERCISE = 0b00001000,
|
||||
CHANNEL_TAKEN_IN_OWN_CONFIG = 0b00010000,
|
||||
|
||||
// not solvable
|
||||
CHANNEL_TAKEN_IN_GLOBAL = 0b00100000,
|
||||
RADIO_CIRCUIT_TAKEN_IN_GLOBAL = 0b01000000,
|
||||
};
|
||||
Q_DECLARE_FLAGS(Conflicts, Conflict)
|
||||
|
||||
explicit LoadCombatNetRadioDialogModel(const QByteArray &data,
|
||||
LtsSession::LtsSession *session,
|
||||
QObject *parent = nullptr);
|
||||
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
|
||||
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
|
||||
bool allChecked() const;
|
||||
|
||||
QVector<Core::RemoveElementRequest> removeRequests() const;
|
||||
QVector<AudioVideoManagement::ModifyCnrConfigRequest> modifyRequests() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void setCheckState(bool isChecked);
|
||||
|
||||
private: // methods
|
||||
|
||||
LoadCombatNetRadioDialogModel::Conflicts getConflicts(int32_t row, const CnrConfig &config);
|
||||
QString conflictsText(Conflicts conflicts) const;
|
||||
|
||||
bool isRadioCircuitTakenInOwnConfig(const CnrConfig &loadConfig, const CnrConfig &existingConfig) const;
|
||||
bool isRadioCircuitTakenInAnotherExercise(const CnrConfig &loadConfig, const CnrConfig &existingConfig) const;
|
||||
bool isChannelTakenInActiveExercise(const CnrConfig &loadConfig, const CnrConfig &existingConfig) const;
|
||||
bool isChannelTakenInLinkedExercise(const CnrConfig &loadConfig, const CnrConfig &existingConfig) const;
|
||||
bool isChannelTakenInOwnConfig(const CnrConfig &loadConfig, const CnrConfig &existingConfig) const;
|
||||
bool isChannelTakenInGlobal(const CnrConfig &loadConfig, const CnrConfig &existingConfig) const;
|
||||
bool isRadioCircuitTakenInGlobal(const CnrConfig &loadConfig, const CnrConfig &existingConfig) const;
|
||||
|
||||
void addConflictedCnr(int32_t row, int32_t cnrConfigId);
|
||||
|
||||
bool isActiveExercise(int32_t exerciseId) const;
|
||||
|
||||
QColor getConflictsRowColor(Conflicts conflicts) const;
|
||||
|
||||
private: // attributes
|
||||
int32_t m_exerciseId;
|
||||
QMap<int32_t, CnrChannel> m_cnrChannels;
|
||||
QMap<int32_t, CnrConfig> m_cnrConfigs;
|
||||
QMap<int32_t, ExerciseManagement::Exercise> m_exercises;
|
||||
QMap<int32_t, QVector<int32_t> > m_conflictedCnrIds; // <row, QVector<CnrConfig::id>>
|
||||
QVector<Qt::CheckState> m_includeStates;
|
||||
QVector<int32_t> m_disabledRows;
|
||||
QVector<Conflicts> m_conflicts;
|
||||
|
||||
LOGGER_T m_logger;
|
||||
};
|
||||
} // namespace AudioVideoManagement
|
||||
Reference in new issue
Block a user