Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
Executable
+20
@@ -0,0 +1,20 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
# Created by Christian Ehrlicher, SLSE, 2016-03-01
|
||||
#
|
||||
|
||||
ADD_SUBDIRECTORY(Data)
|
||||
ADD_SUBDIRECTORY(Gui)
|
||||
|
||||
|
||||
#
|
||||
# Data Plugin Interface
|
||||
#
|
||||
ADD_INTERFACE_LIBRARY(TgtDataPluginInterface
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tgt_data_plugin_interface.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../
|
||||
DataPluginInterface
|
||||
svcTgtCommon
|
||||
)
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
# Created by Mike Wille, SLSE, 2016-09-06
|
||||
#
|
||||
|
||||
#
|
||||
# Data Plugin
|
||||
#
|
||||
NGL_ADD_LIBRARY(WS TgtDataPlugin MODULE tgt_data_plugin.cpp tgt_data_plugin.h)
|
||||
NGL_TARGET_LINK_LIBRARIES(TgtDataPlugin
|
||||
Qt5::Core
|
||||
TgtDataPluginInterface
|
||||
svcTgtClient
|
||||
NGLLogger
|
||||
LtsSessionDataDds
|
||||
)
|
||||
NGL_INSTALL_TARGET(TgtDataPlugin)
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Data Plugin for TargetManagement
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Christian Ehrlicher, SLSE, 2016-02-29
|
||||
*/
|
||||
|
||||
#include "tgt_data_plugin.h"
|
||||
|
||||
#include <DDS/DDSConnector/dds_connector.h>
|
||||
#include <LtsSession/lts_session_data_dds.h>
|
||||
|
||||
namespace TargetManagement
|
||||
{
|
||||
std::shared_ptr<DataPluginBase::Interface> DataPlugin::createDataInterface(LtsSession::LtsSessionDataDds *session)
|
||||
{
|
||||
std::shared_ptr<TargetManagement::Interface::Dtc> dtc;
|
||||
std::shared_ptr<TargetManagement::Interface::Ftc> ftc;
|
||||
if (!session->createTopicClient(dtc, ftc))
|
||||
return std::shared_ptr<DataPluginBase::Interface>();
|
||||
|
||||
return std::make_shared<DataInterfaceImpl>(dtc, ftc);
|
||||
}
|
||||
|
||||
DataInterfaceImpl::DataInterfaceImpl(const std::shared_ptr<TargetManagement::Interface::Dtc> &dtc,
|
||||
const std::shared_ptr<TargetManagement::Interface::Ftc> &ftc)
|
||||
: DataInterface()
|
||||
, m_dtc(dtc)
|
||||
, m_ftc(ftc)
|
||||
{}
|
||||
|
||||
} // namespace TargetManagement
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Data Plugin for TargetManagement
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Christian Ehrlicher, SLSE, 2016-02-29
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <PluginInterfaces/data_plugin_interface.h>
|
||||
#include <Plugins/TargetManagement/tgt_data_plugin_interface.h>
|
||||
|
||||
|
||||
namespace TargetManagement
|
||||
{
|
||||
|
||||
class DataPlugin final : public QObject, public DataPluginBase::Plugin
|
||||
{
|
||||
Q_PLUGIN_METADATA(IID "data:3:tgt")
|
||||
Q_INTERFACES(DataPluginBase::Plugin)
|
||||
|
||||
Q_OBJECT
|
||||
public:
|
||||
DataPlugin() = default;
|
||||
~DataPlugin() = default;
|
||||
|
||||
QString pluginName() const override { return QStringLiteral("TargetManagement"); }
|
||||
std::shared_ptr<DataPluginBase::Interface> createDataInterface(LtsSession::LtsSessionDataDds *session) override;
|
||||
bool availableInPartition(IDL::PartitionType partition) const override
|
||||
{
|
||||
return partition == IDL::PartitionType::Exercise ||
|
||||
partition == IDL::PartitionType::Replay ||
|
||||
partition == IDL::PartitionType::Global;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class DataInterfaceImpl final : public DataInterface
|
||||
{
|
||||
public:
|
||||
DataInterfaceImpl(const std::shared_ptr<TargetManagement::Interface::Dtc> &dtc,
|
||||
const std::shared_ptr<TargetManagement::Interface::Ftc> &ftc);
|
||||
|
||||
std::shared_ptr<TargetManagement::Interface::Dtc> getDtc() override { return m_dtc; }
|
||||
std::shared_ptr<TargetManagement::Interface::Ftc> getFtc() override { return m_ftc; }
|
||||
|
||||
private:
|
||||
std::shared_ptr<TargetManagement::Interface::Dtc> m_dtc;
|
||||
std::shared_ptr<TargetManagement::Interface::Ftc> m_ftc;
|
||||
};
|
||||
|
||||
} // namespace TargetManagement
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
# Created by Norbert Thoden, NLE, 2020-05-28
|
||||
#
|
||||
|
||||
ADD_SUBDIRECTORY(ShootbackTargetConfiguration)
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
# Created by Norbert Thoden, NLE, 2020-05-28
|
||||
#
|
||||
|
||||
SET(tgt_gui_SRCS
|
||||
# common
|
||||
tgt_target_gui_plugin.cpp
|
||||
tgt_target_gui_plugin.h
|
||||
tgt_telegrams.cpp
|
||||
tgt_telegrams.h
|
||||
tgt_common.cpp
|
||||
tgt_common.h
|
||||
|
||||
# target
|
||||
tgt_participant_handler.cpp
|
||||
tgt_participant_handler.h
|
||||
tgt_target_part_model.cpp
|
||||
tgt_target_part_model.h
|
||||
tgt_target_part_dialog.cpp
|
||||
tgt_target_part_dialog.h
|
||||
tgt_shootback_target_edit.cpp
|
||||
tgt_shootback_target_edit.h
|
||||
|
||||
# assignment
|
||||
tgt_assignment_part_model.cpp
|
||||
tgt_assignment_part_model.h
|
||||
tgt_target_area_assignment_dialog.cpp
|
||||
tgt_target_area_assignment_dialog.h
|
||||
tgt_target_area_assignment_edit.cpp
|
||||
tgt_target_area_assignment_edit.h
|
||||
|
||||
# area
|
||||
tgt_area_dialog.cpp
|
||||
tgt_area_dialog.h
|
||||
tgt_area_edit.cpp
|
||||
tgt_area_edit.h
|
||||
tgt_area_model.cpp
|
||||
tgt_area_model.h
|
||||
|
||||
)
|
||||
|
||||
NGL_WRAP_UI(tgt_gui_SRCS
|
||||
tgt_shootback_target_edit.ui
|
||||
tgt_target_part_dialog.ui
|
||||
tgt_target_area_assignment_dialog.ui
|
||||
tgt_target_area_assignment_edit.ui
|
||||
tgt_area_dialog.ui
|
||||
tgt_area_edit.ui
|
||||
)
|
||||
|
||||
NGL_ADD_LIBRARY(WS TgtTargetGuiPlugin MODULE ${tgt_gui_SRCS})
|
||||
NGL_TARGET_LINK_LIBRARIES(TgtTargetGuiPlugin
|
||||
NGLLogger
|
||||
LtsPrinting
|
||||
LtsSession
|
||||
|
||||
svcTgtClient
|
||||
Qt5::Widgets
|
||||
LtsCoordTrans
|
||||
ltsCoordWidget
|
||||
LtsWidgets
|
||||
LtsDataView
|
||||
LtsSessionData
|
||||
LtsUtilsCore
|
||||
LtsUtilsGuiDds
|
||||
LtsUtilsSettings
|
||||
|
||||
advancedSymbology
|
||||
FlmDataPluginInterface #flm_translation
|
||||
|
||||
PpmGuiComboboxPluginInterface
|
||||
svcExmCommon
|
||||
svcPpmCommon
|
||||
)
|
||||
|
||||
NGL_INSTALL_TARGET(TgtTargetGuiPlugin)
|
||||
@@ -0,0 +1,155 @@
|
||||
#
|
||||
# Hinweise fuer ShootbackTargets (Projekt L400)
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
|
||||
N. Thoden, 16.07.2020
|
||||
|
||||
Facts
|
||||
============================================================
|
||||
- Die Shootbacktargets im Projekt L400 besitzen kaum eigene Intelligenz.
|
||||
- Einige der Shootbacktargets können sich bewegen.
|
||||
- Sie haben unterschiedliche Silouetten.
|
||||
-
|
||||
|
||||
Statik
|
||||
============================================================
|
||||
Im namespace TargetManagement existieren 3 wesentliche Objekte/Topics:
|
||||
|
||||
1) ShootbackTarget
|
||||
Es wird "assigned" mit einem Participant aus den ORBAT (Teilnehmerbaum). Diese muss ein WmsTypeClass (TargetVehicle|TargetHuman) haben.
|
||||
Beim Zuordnen zu eine Teilnehmer (aus dem ORBAT) kann/muss eine TargetConfiguration vorgenommen werden: activateLaserDesignation etc.
|
||||
|
||||
2) ShootbackArea
|
||||
Die Area wird per center, width, height definiert. Ist also nordausgerichtet.
|
||||
|
||||
3) TargetAreaAssignment (inkl. (Shootback)-Configuration)
|
||||
Das Assignment zw. 1) und 2) beinhaltet zusätzlich die (Shootback)-Configuration, die das Verhalten definiert: PreWarning-interval, hitsToKill etc.
|
||||
Diese (Shootback)-Configuration kann per CheckBox "assigned" aktiviert oder deaktiviert werden (DDS: TargetAreaAssignment.isActive())
|
||||
!!! Somit hat nicht ein Target nicht genau EINE (Shootback)-Configuration, sondern jedes einzelnes Assignment !!!
|
||||
|
||||
|
||||
|
||||
Ablauf / Best Practise
|
||||
============================================================
|
||||
PreCondition:
|
||||
Zunächst sollte sichergestellt sein, dass der ORBAT einige Targets enthält. Ggf. sollten entsprechende Typen/template eingefügt werden.
|
||||
|
||||
Step 1: TargetConfiguration
|
||||
Im Dialog "Assign/Configure Targets" kann man die grundsätzliche TargetConfiguration pro Teilnehmer erstellen (activateLaserDesignation etc.)
|
||||
Anmerkung:
|
||||
- Es muss nicht für jeden im ORBAT als "Target" konfigurierten Particpant eine TargetConfiguration erstellt werden.
|
||||
- Es muss aber für jedes "Target" im ORBAT eine TargetConfiguration erstellt werden, wenn es einer Area zugeordnet werden soll.
|
||||
|
||||
Step 2: ShootbackArea
|
||||
Im Dialog "Configure Areas" können die Areas erstellt werden.
|
||||
|
||||
Step 3: Zuordnungen vornehmen
|
||||
Hierfür gibt es 3 mögliche Wege:
|
||||
Step 3a)
|
||||
Shootback Overview
|
||||
Dieser Dialog zeigt in Tabellenform alle aktiven Zuordnungen. Zunächst sind keine vorhanden.
|
||||
Per Add kann zum einen eine Zuordnung zw. einem Target und einer Area erstellt und andererseits die (Shootback)-Configuration vorgenommen werden.
|
||||
|
||||
Step 3b)
|
||||
Assign Area
|
||||
Im Target-ÜbersichtsDialog kann ein Target selektiert und dann per Btn "Assign Area" ein weiterführender Dialog geöfnet werden "Edit Areas assigned to <Targetname>"
|
||||
Dieser Zuordnungs-Dialog zeigt in Tabellenform nur die für dieses Target relevanten Zuordnungen.
|
||||
Es werden die bestehenden mit "Assigned" = "Yes" dargestellt.
|
||||
Darüberhinaus sind die noch möglichen Areas mit "Assigned" = "No" aufgeführt. Mit Klick auf "No" wird es assigned.
|
||||
Wenn die (Shootback)-Configuration aber ungültig (derzeit == default) ist, wird die Zeile rot hinterlegt und ein "Apply" ist nicht möglich.
|
||||
Per "Edit" kann die (Shootback)-Configuration vorgenommen werden.
|
||||
|
||||
Step 3c)
|
||||
Assign Target
|
||||
Hier verhält es sich analog zu Step 3b):
|
||||
Im Area-ÜbersichtsDialog kann ein Area selektiert und dann per Btn "Assign Target" ein weiterführender Dialog geöfnet werden "Edit targets assigned to <Areaname>"
|
||||
Dieser Zuordnungs-Dialog zeigt in Tabellenform nur die für dieses Area relevanten Zuordnungen.
|
||||
Es werden die bestehenden mit "Assigned" = "Yes" dargestellt.
|
||||
Darüberhinaus sind die noch möglichen Targets mit "Assigned" = "No" aufgeführt. Mit Klick auf "No" wird es assigned.
|
||||
Wenn die (Shootback)-Configuration aber ungültig (derzeit == default) ist, wird die Zeile rot hinterlegt und ein "Apply" ist nicht möglich.
|
||||
Per "Edit" kann die (Shootback)-Configuration vorgenommen werden.
|
||||
|
||||
Anmerkungen:
|
||||
- Für alle Step 3 Varianten gilt: Der ÜbersichtsDialog muss mit "Apply" abgeschlossen werden, um die Daten wirksam zu übernehmen.
|
||||
- Sowohl eine fehlende TargetConfiguration als auch eine fehlende (Shootback)-Configuration wird in den Tabellen farblich dargestellt.
|
||||
|
||||
|
||||
Convenience
|
||||
============================================================
|
||||
- Tooltips in Tabellen, ComboBoxen
|
||||
- Selektiert man eine Area, Target oder Assignment, so wird in der Karten das zugehörige Objekt per Pfeil markiert (MapObjectIndicator) und selektiert dargestellt.
|
||||
Die dem Area oder Target zugeordneten Objekte werden ebenfalls selektiert dargestellt.
|
||||
- Per "Center Map" wird die Karten auf das selektiert Objekt zentriert.
|
||||
Dies kann auch mit der gedrückten Shift-Taste bei selektieren in der Tabelle erreicht werden.
|
||||
- Per "Zoom to " zoomt die die Karten auf das selektiert Objekt und dessen zugeordneten Objekte.
|
||||
|
||||
- Einige Dialog haben die Möglichkeit, die Daten in die Library zu exportieren, bzw. von diort zu importieren.
|
||||
Beim Importieren werden die aktuellen Daten überschrieben (Warn-Meldung ist vorhanden)
|
||||
|
||||
Um Irritationen zu vermeiden, empfiehlt es sich, erst die Targets und Areas zu importieren und erst danach die Zuordnungen zu importieren.
|
||||
|
||||
|
||||
Todo:
|
||||
============================================================
|
||||
- EA:
|
||||
- Umbenennung des Topics TargetAreaConfiguration in ShootbackConfiguration (Done)
|
||||
- ForeignKeys entfernen (Done)
|
||||
|
||||
- Die dynamischen Daten "Position" und visibleParticpants evtl. in seperates Topic auslagern.
|
||||
(Derzeit im Target)
|
||||
|
||||
-SVC:
|
||||
- ModulTests anpassen
|
||||
|
||||
--->
|
||||
--->
|
||||
- Es ist derzeit die Höhenkarten für Bremen hart programmiert.
|
||||
Es muss dafür gesort werden (Ablauf) wie TrainingAreas mit den Basemaps UND
|
||||
ElevationMaps augf den System (INKL. Server kommen), damit auch die Services
|
||||
diese Dateien nutzen können.
|
||||
Derzeit ist dort viel getrickst.... :-(
|
||||
<-----
|
||||
<-----
|
||||
|
||||
|
||||
- GUI
|
||||
- Yes/No Icons durchgängig machen (Done)
|
||||
- Filter der LtsDataViews vervollständigen (Done, mit Bug)
|
||||
- "Name" -> "Designation"
|
||||
- Spalten sortieren, umbenennen
|
||||
- Silouetten einbinden
|
||||
- "ZoomTo" SVG erstellen (ButtonBox) (Done)
|
||||
- Evtl. "Experten"-Modus beim Dlg "Targets per Area"???
|
||||
- I18N
|
||||
|
||||
- SOURCEN
|
||||
- Konsistenten Datei- und Klassen-Bezeichnungen herstellen. Ist derzeit kaum wartbar.
|
||||
- LogMessages auf passenden Level stellen (Done)
|
||||
- Links zur OnlineHilfe setzen/korrigieren (setOnlineHelpFilename)
|
||||
|
||||
- seperate APP erzeugen: "ShootbackApp"
|
||||
|
||||
|
||||
Ideen
|
||||
============================================================
|
||||
- Beim Dlg "Assign/Configure Targets" einen Defaultwert eintragen/anzeigen: Takt. Bezeichner des Participants.
|
||||
Btn. "Use Tact. Identifier als Designation" kopiert den Wert in das LineEdit...
|
||||
|
||||
|
||||
|
||||
|
||||
Known Problems/Bugs:
|
||||
============================================================
|
||||
- Einige Filter der LtsDataViews (Dlg "Targets per Area" und "Areas per Target" enthalten Values, die nicht gefiltert werden können.
|
||||
Problem in AssignmentParticipantModel::updateColumnFilter()
|
||||
- Wenn das Target nicht modifiziert werden darf, ist die ComboBox disabled. Leider ist dann auch das Icon dunkel...
|
||||
(Label mit Icon statt ComboBox)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Executable
+118
@@ -0,0 +1,118 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* HMI Plugin for ParticipantManagement - Party Overview Model
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Norbert Thoden, NLE, 2020-05-29
|
||||
*/
|
||||
|
||||
#include "tgt_shootback_target_model.h"
|
||||
#include <LtsCoordTrans/lts_coord_trans.h>
|
||||
|
||||
namespace TargetMa nagement
|
||||
{
|
||||
//---------------------------------
|
||||
// ShootbackTargetModel
|
||||
//---------------------------------
|
||||
ShootbackTargetModel::ShootbackTargetModel(QObject *parent)
|
||||
: BaseClass({tr("Id"),
|
||||
tr("TargetId"),
|
||||
tr("Name"),
|
||||
tr("TargetParticipantId"),
|
||||
tr("Position"),
|
||||
tr("ActivateLaserDesignation"),
|
||||
tr("ActivateLights"),
|
||||
tr("ActivatePopupAutomatic"),
|
||||
tr("HitsToKill"),
|
||||
tr("PermanentInstalledTarget"),
|
||||
tr("VisibleParticipants"),
|
||||
tr("Is Used")},
|
||||
parent)
|
||||
, m_dtc(nullptr)
|
||||
, m_logger(getLogger("ShootbackTargetModel"))
|
||||
{}
|
||||
|
||||
bool ShootbackTargetModel::initModel(const std::shared_ptr<TargetManagement::Interface::Dtc> &dtc)
|
||||
{
|
||||
if (!dtc)
|
||||
return false;
|
||||
|
||||
m_dtc = dtc;
|
||||
|
||||
connect(m_dtc.get(), &TargetManagement::Interface::Dtc::shootbackTargetChanged,
|
||||
this, &ShootbackTargetModel::onDataChanged);
|
||||
|
||||
connect(m_dtc.get(), &TargetManagement::Interface::Dtc::shootbackTargetChanged, [](const TargetManagement::ShootbackTarget &data, DataModification modType) {
|
||||
ShootbackTargetModel::onDataChanged(data, modType);
|
||||
});
|
||||
|
||||
|
||||
m_dtc->shootbackTargets([this](const TargetManagement::ShootbackTarget & shootbackTarget)
|
||||
{
|
||||
insertRow(shootbackTarget);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
QString toStringLocal(const std::vector< int32_t > &ids)
|
||||
{
|
||||
QString ret;
|
||||
for (auto id : ids)
|
||||
ret.append(QString::number(id));
|
||||
return ret;
|
||||
}
|
||||
|
||||
QVariant ShootbackTargetModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!indexIsValid(index))
|
||||
return QVariant();
|
||||
|
||||
const TargetManagement::ShootbackTarget &shootbackTarget = m_vecData.at(index.row());
|
||||
// if (role == Qt::BackgroundRole)
|
||||
// {
|
||||
// switch(index.column())
|
||||
// {
|
||||
// case Color:
|
||||
// return QColor::fromRgb(QRgb(shootbackTarget.color()));
|
||||
// case FadedColor:
|
||||
// return QColor::fromRgb(QRgb(shootbackTarget.fadingColor()));
|
||||
// }
|
||||
// }
|
||||
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
switch (index.column())
|
||||
{
|
||||
case Id:
|
||||
return shootbackTarget.id();
|
||||
case TargetDataId:
|
||||
return shootbackTarget.targetDataId();
|
||||
case Name:
|
||||
return QString::fromStdString(shootbackTarget.name());
|
||||
case TargetParticipantId:
|
||||
return shootbackTarget.targetParticipantId();
|
||||
case Position:
|
||||
{
|
||||
const Core::GeoPosition2D &pos = shootbackTarget.position();
|
||||
return LtsCoordTrans::mgrsFromGeographic(pos.lon(), pos.lat());
|
||||
}
|
||||
case ActivateLaserDesignation:
|
||||
return shootbackTarget.activateLaserDesignation() ? tr("Yes") : tr("No");
|
||||
case ActivateLights:
|
||||
return shootbackTarget.activateLights() ? tr("Yes") : tr("No");
|
||||
case ActivatePopupAutomatic:
|
||||
return shootbackTarget.activatePopupAutomatic() ? tr("Yes") : tr("No");
|
||||
case HitsToKill:
|
||||
return shootbackTarget.hitsToKill();
|
||||
case PermanentInstalledTarget:
|
||||
return shootbackTarget.permanentInstalledTarget() ? tr("Yes") : tr("No");
|
||||
case VisibleParticipants:
|
||||
return TargetManagement::toStringLocal(shootbackTarget.visibleParticipants());
|
||||
case IsUsedBy:
|
||||
return shootbackTarget.isUsed() ? tr("Yes") : tr("No");
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
} // namespace TargetManagement
|
||||
Executable
+61
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* HMI Plugin for ParticipantManagement - Party Overview Model
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Norbert Thoden, NLE, 2020-05-29
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Services/TargetManagement/tgt_dtc.h>
|
||||
#include <LtsWidgets/lts_abstract_table_model.h>
|
||||
#include <TargetManagement/logger.h>
|
||||
|
||||
|
||||
namespace TargetManagement
|
||||
{
|
||||
// --------------------------------------------------------
|
||||
// ShootbackTargetModel
|
||||
// --------------------------------------------------------
|
||||
class ShootbackTargetModel final : public LtsWidgets::LtsAbstractTableModel<TargetManagement::ShootbackTarget>
|
||||
{
|
||||
using BaseClass = LtsWidgets::LtsAbstractTableModel<TargetManagement::ShootbackTarget>;
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Columns
|
||||
{
|
||||
Id,
|
||||
TargetDataId,
|
||||
Name,
|
||||
|
||||
// ExerciseId,
|
||||
TargetParticipantId,
|
||||
|
||||
Position,
|
||||
ActivateLaserDesignation,
|
||||
ActivateLights,
|
||||
ActivatePopupAutomatic,
|
||||
HitsToKill,
|
||||
PermanentInstalledTarget,
|
||||
VisibleParticipants,
|
||||
IsUsedBy
|
||||
};
|
||||
|
||||
explicit ShootbackTargetModel(QObject *parent = nullptr);
|
||||
|
||||
bool initModel(const std::shared_ptr<TargetManagement::Interface::Dtc> &dtc);
|
||||
|
||||
QVariant data(const QModelIndex &, int) const override;
|
||||
|
||||
protected:
|
||||
bool isFiltered(const ShootbackTarget &data, DataModification modType) const override
|
||||
{
|
||||
return BaseClass::isFiltered(data, modType);
|
||||
}
|
||||
private:
|
||||
std::shared_ptr<TargetManagement::Interface::Dtc> m_dtc;
|
||||
LOGGER_T m_logger;
|
||||
};
|
||||
} //namespace TargetManagement
|
||||
Executable
+213
@@ -0,0 +1,213 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* HMI Plugin for ParticipantManagement - Party View
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Norbert Thoden, NLE, 2020-05-29
|
||||
*/
|
||||
|
||||
#include "tgt_shootback_target_view.h"
|
||||
#include "ui_tgt_shootback_target_view.h"
|
||||
//#include "CustomView/ppm_party.h"
|
||||
#include "tgt_shootback_target_edit.h"
|
||||
|
||||
#include <LtsPrinting/printing.h>
|
||||
#include <QTreeView>
|
||||
|
||||
namespace TargetManagement
|
||||
{
|
||||
|
||||
ShootbackTargetView::ShootbackTargetView(const QString &menuGroup, LtsSession::LtsSession *session, QWidget *parent)
|
||||
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::CloseOnly)
|
||||
, m_menuGroup(menuGroup)
|
||||
, m_requestHelper(new LtsUtils::RequestHelper(this))
|
||||
, m_session(session)
|
||||
, m_ui(new Ui::ShootbackTargetView)
|
||||
, m_logger(getLogger("ShootbackTargetView"))
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
m_ui->widget->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
|
||||
|
||||
connect(m_ui->widget, &LtsDataView::LtsDataView::signalSelectionChanged,
|
||||
this, &ShootbackTargetView::enaDisa);
|
||||
|
||||
connect(m_ui->widget, &LtsDataView::LtsDataView::signalDoubleClicked, this, &ShootbackTargetView::onEditShootbackTarget);
|
||||
connect(m_ui->widget, &LtsDataView::LtsDataView::signalEnterPressed, this, &ShootbackTargetView::onEditShootbackTarget);
|
||||
|
||||
m_buttonBox->connectButton(LtsWidgets::DialogButton::Edit, this, &ShootbackTargetView::onEditShootbackTarget);
|
||||
|
||||
// m_buttonBox->connectButton(LtsWidgets::DialogButton::Add, this, &ShootbackTargetView::onAddParty);
|
||||
|
||||
// m_buttonBox->connectButton(LtsWidgets::DialogButton::Remove, this, &ShootbackTargetView::onRemoveParty);
|
||||
|
||||
m_buttonBox->connectButton(LtsWidgets::DialogButton::Print, this, &ShootbackTargetView::onPrint);
|
||||
|
||||
// m_buttonBox->connectButton(LtsWidgets::DialogButton::Load, this, &ShootbackTargetView::onSyncParties);
|
||||
m_buttonBox->setText(LtsWidgets::DialogButton::Load, tr("Synchronize Parties"));
|
||||
|
||||
setOnlineHelpFilename(QStringLiteral("Administrator-ShootbackTargets"));
|
||||
}
|
||||
|
||||
ShootbackTargetView::~ShootbackTargetView()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
void ShootbackTargetView::retranslate()
|
||||
{
|
||||
translate(m_ui, tr("ShootbackTargets"));
|
||||
}
|
||||
|
||||
bool ShootbackTargetView::init(const std::shared_ptr<TargetManagement::Interface::Dtc> &dtc,
|
||||
const std::shared_ptr<TargetManagement::Interface::Ftc> &ftc)
|
||||
{
|
||||
if (!dtc || !ftc)
|
||||
return false;
|
||||
|
||||
m_dtc = dtc;
|
||||
m_ftc = ftc;
|
||||
m_model = new ShootbackTargetModel(this);
|
||||
m_model->initModel(m_dtc);
|
||||
m_ui->widget->setModel(m_model);
|
||||
// m_ui->widget->setModel(m_model, [this]() { return new CustomViewParty(this); });
|
||||
|
||||
#ifndef LTS_DEBUG
|
||||
m_ui->widget->hideColumn(ShootbackTargetModel::Id);
|
||||
#endif
|
||||
|
||||
m_ui->widget->setSortingEnabled(false);
|
||||
|
||||
connect(m_model, &ShootbackTargetModel::rowsInserted, this, &ShootbackTargetView::enaDisa);
|
||||
connect(m_model, &ShootbackTargetModel::rowsRemoved, this, &ShootbackTargetView::enaDisa);
|
||||
|
||||
enaDisa();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ShootbackTargetView::enaDisa()
|
||||
{
|
||||
//const QModelIndex idx = m_ui->widget->currentIndex();
|
||||
|
||||
bool bAddVisible = false;
|
||||
bool bEditEnabled = false;
|
||||
bool bRemoveEnabled = false;
|
||||
bool bRemoveVisible = false;
|
||||
bool bLoadEnabled = true;
|
||||
bool bLoadVisible = (m_session->exerciseId() > 0);
|
||||
|
||||
/*
|
||||
* const int row = idx.row();
|
||||
if (m_ui->widget->selectedRows().size() == 0 || row < 0)
|
||||
{
|
||||
bEditEnabled = false;
|
||||
bRemoveEnabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
const ParticipantManagement::Party party = m_model->getRowData(row);
|
||||
bEditEnabled = party.id() > 0; // all but not pool
|
||||
bRemoveEnabled = !party.isUsedBy();
|
||||
}
|
||||
|
||||
if (m_session->exerciseId() > 0)
|
||||
{
|
||||
// no add parties in ex_N, they need to be added in ex_0 and synchronized. Last updated: 2018.04.12
|
||||
bAddVisible = false;
|
||||
|
||||
// sync possible only in preparing exercise
|
||||
const bool bInPreparation = (m_session->exerciseState() == LtsWidgets::ExerciseState::eCreated);
|
||||
if (bInPreparation)
|
||||
{
|
||||
// sync possible only in preparing exercise
|
||||
bLoadEnabled = true;
|
||||
bLoadVisible = true;
|
||||
bRemoveVisible = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// sync and delete not possible after starting exercise
|
||||
bLoadEnabled = false;
|
||||
bLoadVisible = false;
|
||||
bRemoveVisible = false;
|
||||
bRemoveEnabled = false;
|
||||
}
|
||||
}
|
||||
*/
|
||||
m_buttonBox->setButtonVisible(LtsWidgets::DialogButton::Add, bAddVisible);
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Edit, bEditEnabled);
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Remove, bRemoveEnabled);
|
||||
m_buttonBox->setButtonVisible(LtsWidgets::DialogButton::Remove, bRemoveVisible);
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Load, bLoadEnabled);
|
||||
m_buttonBox->setButtonVisible(LtsWidgets::DialogButton::Load, bLoadVisible);
|
||||
}
|
||||
|
||||
void ShootbackTargetView::onEditShootbackTarget()
|
||||
{
|
||||
const QModelIndex idx = m_ui->widget->currentIndex();
|
||||
|
||||
int row = idx.row();
|
||||
if (row < 0)
|
||||
return;
|
||||
|
||||
const TargetManagement::ShootbackTarget &target = m_model->getRowData(row);
|
||||
ShootbackTargetEdit *dialog = new ShootbackTargetEdit(this);
|
||||
dialog->init(m_dtc, m_ftc, nullptr, target);
|
||||
|
||||
addDialog(dialog, m_menuGroup, QLatin1String("tgtShootbackTarget") + QString::number(target.id()), LtsWidgets::LayoutArea::eDialogTab);
|
||||
}
|
||||
|
||||
void ShootbackTargetView::onAddParty()
|
||||
{
|
||||
// PartyEdit *dialog = new PartyEdit(this);
|
||||
// dialog->init(-1 , m_dtc, m_ftc, m_ppmGuiCbxIfc);
|
||||
|
||||
// addDialog(dialog, m_menuGroup, QLatin1String("ppmAddParty"), LtsWidgets::LayoutArea::eDialogTab);
|
||||
}
|
||||
|
||||
void ShootbackTargetView::onRemoveParty()
|
||||
{
|
||||
// const QModelIndex curIdx = m_ui->widget->currentIndex();
|
||||
// if (!curIdx.isValid())
|
||||
// return;
|
||||
// const Party party = m_model->getRowData(curIdx.row());
|
||||
// if (party.id() < 0)
|
||||
// return;
|
||||
// RemovePartyRequest req;
|
||||
// req.partyId(party.id());
|
||||
// m_requestHelper->startSingleRequest([req, this]()
|
||||
// {
|
||||
// return m_ftc->removePartyRequest(req, this);
|
||||
// });
|
||||
// enaDisa();
|
||||
}
|
||||
|
||||
void ShootbackTargetView::onPrint()
|
||||
{
|
||||
LtsPrinting::printView(m_session, this, m_ui->widget->treeView());
|
||||
}
|
||||
|
||||
void ShootbackTargetView::onSyncParties()
|
||||
{
|
||||
// LtsWidgets::Button button = LtsWidgets::LtsMessageDialog::showMessage(this,tr("Changes in this exercise will be lost. Do you wish to continue?"), tr("Warning"),
|
||||
// LtsWidgets::Behaviour::Modal, LtsWidgets::Button::Yes | LtsWidgets::Button::No);
|
||||
|
||||
// if (button == LtsWidgets::Button::Yes)
|
||||
// {
|
||||
// m_requestHelper->startSingleRequest([this]()
|
||||
// {
|
||||
// SyncPartiesRequest req;
|
||||
// req.exerciseId(m_session->exerciseId());
|
||||
|
||||
// DEBUG_LOG(m_logger) << "Sync parties for exercise " << req.exerciseId();
|
||||
|
||||
// return m_ftc->syncPartiesRequest(req, this);
|
||||
// });
|
||||
// }
|
||||
// enaDisa();
|
||||
}
|
||||
|
||||
|
||||
} // namespace TargetManagement
|
||||
Executable
+69
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* HMI Plugin for ParticipantManagement - Party View
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Norbert Thoden, NLE, 2020-05-29
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "tgt_shootback_target_model.h"
|
||||
#include <TargetManagement/logger.h>
|
||||
#include <Services/TargetManagement/tgt_dtc.h>
|
||||
#include <Services/TargetManagement/tgt_ftc.h>
|
||||
//#include <Services/ExerciseManagement/exm_dtc.h>
|
||||
#include <LtsWidgets/lts_dialog.h>
|
||||
#include <LtsSession/lts_session.h>
|
||||
#include <LtsUtilsGuiDds/request_helper.h>
|
||||
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class ShootbackTargetView;
|
||||
}
|
||||
|
||||
namespace TargetManagement
|
||||
{
|
||||
|
||||
class ShootbackTargetView : public LtsWidgets::LtsDialog
|
||||
// , protected ParticipantManagement::Interface::Ftc::ModifyPartyDataReplyHandler
|
||||
// , protected ParticipantManagement::Interface::Ftc::RemovePartyReplyHandler
|
||||
// , protected ParticipantManagement::Interface::Ftc::SyncPartiesReplyHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ShootbackTargetView(const QString &menuGroup, LtsSession::LtsSession *session, QWidget *parent = nullptr);
|
||||
~ShootbackTargetView();
|
||||
bool init(const std::shared_ptr<TargetManagement::Interface::Dtc> &dtc,
|
||||
const std::shared_ptr<TargetManagement::Interface::Ftc> &ftc);
|
||||
|
||||
private:
|
||||
void retranslate() override;
|
||||
// void onModifyPartyDataReply(const Core::FunctionReplyObject &replyObject) override { m_requestHelper->requestReply(replyObject); }
|
||||
// void onRemovePartyReply(const Core::FunctionReplyObject &replyObject) override { m_requestHelper->requestReply(replyObject); }
|
||||
// void onSyncPartiesReply(const Core::FunctionReplyObject &replyObject) override { m_requestHelper->requestReply(replyObject); }
|
||||
|
||||
void enaDisa();
|
||||
void onEditShootbackTarget();
|
||||
void onAddParty();
|
||||
void onRemoveParty();
|
||||
void onPrint();
|
||||
void onSyncParties();
|
||||
|
||||
private:
|
||||
QString m_menuGroup;
|
||||
ShootbackTargetModel *m_model{nullptr};
|
||||
std::shared_ptr<TargetManagement::Interface::Dtc> m_dtc;
|
||||
std::shared_ptr<TargetManagement::Interface::Ftc> m_ftc;
|
||||
LtsUtils::RequestHelper *m_requestHelper{nullptr};
|
||||
|
||||
LtsSession::LtsSession *m_session{nullptr};
|
||||
Ui::ShootbackTargetView *m_ui{nullptr};
|
||||
|
||||
LOGGER_T m_logger;
|
||||
};
|
||||
|
||||
} // namespace ParticipantManagement
|
||||
Executable
+45
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ShootbackTargetView</class>
|
||||
<widget class="QWidget" name="ShootbackTargetView">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>455</width>
|
||||
<height>341</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="LtsDataView::LtsDataView" name="widget" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>250</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</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>
|
||||
+487
@@ -0,0 +1,487 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Target Configuration
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Norbert Thoden, NLE, 2020-06-29
|
||||
*/
|
||||
|
||||
#include "tgt_area_dialog.h"
|
||||
#include "ui_tgt_area_dialog.h"
|
||||
#include "tgt_area_edit.h"
|
||||
#include "tgt_telegrams.h"
|
||||
#include <LtsSession/lts_session_data.h>
|
||||
#include <FileManagement/flm_translation.h>
|
||||
|
||||
#include <PluginInterfaces/gui_plugin_interface.h>
|
||||
#include <Plugins/TargetManagement/tgt_data_plugin_interface.h>
|
||||
#include <Plugins/FileManagement/flm_explorer_gui_plugin_interface.h>
|
||||
#include <Plugins/SituationMapPlugin/situation_map_gui_plugin_interface.h>
|
||||
|
||||
#include "tgt_target_area_assignment_dialog.h"
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
|
||||
namespace TargetManagement
|
||||
{
|
||||
|
||||
AreaDialog::AreaDialog(const QString &menuGroup, LtsSession::LtsSession *session, QWidget *parent)
|
||||
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
|
||||
, m_session(session)
|
||||
, m_ui(new Ui::AreaDialog)
|
||||
, m_menuGroup(menuGroup)
|
||||
, m_requestHelper(new LtsUtils::RequestHelper(this))
|
||||
, m_logger(getLogger("AreaDialog"))
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
setOnlineHelpFilename(QStringLiteral("Situation-Assign/Configure_Targets"));
|
||||
}
|
||||
|
||||
AreaDialog::~AreaDialog()
|
||||
{
|
||||
clearSelectionOfMapObjects();
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
bool AreaDialog::init()
|
||||
{
|
||||
if (!m_session)
|
||||
return false;
|
||||
|
||||
if (!m_session->getDtc<TargetManagement::DataInterface>(m_dtc))
|
||||
return false;
|
||||
if (!m_session->getFtc<TargetManagement::DataInterface>(m_ftc))
|
||||
return false;
|
||||
if (!m_session->getForeignGuiInterface<FileManagement::ForeignGuiInterface>(m_flmGui))
|
||||
return false;
|
||||
if (!m_session->getForeignGuiInterface<SituationMap::ForeignGuiInterface>(m_sitMapGuiIfc))
|
||||
return false;
|
||||
|
||||
// initialize model:
|
||||
INFO_LOG(m_logger) << "AreaDialog::init";
|
||||
m_areaModel = new AreaModel(this);
|
||||
m_areaModel->initModel(m_dtc);
|
||||
|
||||
// proxyModel:
|
||||
auto proxyModel = new AreaProxyModel(this);
|
||||
proxyModel->setSourceModel(m_areaModel);
|
||||
proxyModel->setDynamicSortFilter(false);
|
||||
|
||||
// set view: (LtsDataView)
|
||||
m_ui->widget->setModel(proxyModel);
|
||||
|
||||
// to allow remove off some rows at once. Anoying in all other cases -> stay at singleSelection
|
||||
// m_ui->widget->setSelectionMode(QAbstractItemView::SelectionMode::MultiSelection);
|
||||
|
||||
|
||||
m_assignTargetBtn = m_buttonBox->getButton(LtsWidgets::DialogButton::Import);
|
||||
m_buttonBox->connectButton(LtsWidgets::DialogButton::Import, this, &AreaDialog::onAssignTargetButtonClicked);
|
||||
|
||||
// connects for gui
|
||||
connect(m_ui->widget, &LtsDataView::LtsDataView::signalSelectionChanged,
|
||||
this, &AreaDialog::onSelectionChanged);
|
||||
connect(m_ui->widget, &LtsDataView::LtsDataView::signalDoubleClicked,
|
||||
this, &AreaDialog::onEditArea);
|
||||
connect(this, &AreaDialog::escapePressed, this,
|
||||
&AreaDialog::onEscapePressed, Qt::UniqueConnection);
|
||||
|
||||
// Create Add-Button
|
||||
m_buttonBox->connectButton(LtsWidgets::DialogButton::Add, this, &AreaDialog::onNewArea);
|
||||
|
||||
// Create Remove-Button
|
||||
m_buttonBox->connectButton(LtsWidgets::DialogButton::Remove, this, &AreaDialog::onRemoveArea);
|
||||
|
||||
// Create Modify-Button
|
||||
m_buttonBox->connectButton(LtsWidgets::DialogButton::Edit, this, &AreaDialog::onEditArea);
|
||||
|
||||
// connect signals of TableView/CustomView:
|
||||
connect(m_ui->widget, &LtsDataView::LtsDataView::clicked, this, &AreaDialog::onTableViewClicked);
|
||||
// it´s possible to evaluate signalEntered, but seems to be overkill here:
|
||||
// connect(m_ui->widget, &LtsDataView::LtsDataView::signalEntered, this, &AreaDialog::onObjectEntered);
|
||||
|
||||
|
||||
#ifndef LTS_DEBUG
|
||||
m_ui->widget->hideColumn(AreaModel::Columns::Id);
|
||||
#endif
|
||||
|
||||
// Save/Load from Library Button
|
||||
m_buttonBox->connectLibraryButton(this,
|
||||
&AreaDialog::onImportButtonClicked,
|
||||
&AreaDialog::onExportButtonClicked);
|
||||
if (!m_flmGui)
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Library, false);
|
||||
|
||||
// 'Map' Button(s)
|
||||
m_buttonBox->connectButton(LtsWidgets::DialogButton::CenterMap, this, &AreaDialog::onMapCenterClicked);
|
||||
m_buttonBox->connectButton(LtsWidgets::DialogButton::ZoomMapTo, this, &AreaDialog::onMapZoomToClicked);
|
||||
|
||||
if (!m_sitMapGuiIfc)
|
||||
{
|
||||
m_buttonBox->setButtonVisible(LtsWidgets::DialogButton::CenterMap, false);
|
||||
m_buttonBox->setButtonVisible(LtsWidgets::DialogButton::ZoomMapTo, false);
|
||||
}
|
||||
|
||||
// call eneDisa / onSelectionChanged once:
|
||||
onSelectionChanged();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AreaDialog::retranslate()
|
||||
{
|
||||
translate(m_ui, tr("Configure Areas"));
|
||||
m_assignTargetBtn->setText(tr("Assign Targets"));
|
||||
}
|
||||
|
||||
void AreaDialog::keyPressEvent(QKeyEvent *event)
|
||||
{
|
||||
if (event->key() == Qt::Key_Escape)
|
||||
emit escapePressed();
|
||||
return BaseClass::keyPressEvent(event);
|
||||
}
|
||||
|
||||
void AreaDialog::onNewArea()
|
||||
{
|
||||
INFO_LOG(m_logger) << "onNewArea";
|
||||
|
||||
AreaEdit *dialog = new AreaEdit(this);
|
||||
|
||||
if (!dialog->init(m_dtc, m_ftc, m_sitMapGuiIfc, m_areaModel))
|
||||
{
|
||||
ERROR_LOG(m_logger) << QLatin1String("Can't initialize AreaEdit!");
|
||||
delete dialog;
|
||||
return;
|
||||
}
|
||||
addDialog(dialog, m_menuGroup, QStringLiteral("Add Target"), LtsWidgets::LayoutArea::eDialogTab, true, true);
|
||||
}
|
||||
|
||||
void AreaDialog::onRemoveArea()
|
||||
{
|
||||
const QModelIndexList &selectedRows = m_ui->widget->selectedRows();
|
||||
for (const auto &mi : selectedRows)
|
||||
{
|
||||
Core::RemoveElementRequest req;
|
||||
req.id(m_areaModel->getRowData(mi.row()).id());
|
||||
m_requestHelper->addRequest([req, this]()
|
||||
{
|
||||
return m_ftc->shootbackAreaRemoveRequest(req, this);
|
||||
});
|
||||
}
|
||||
m_requestHelper->startRequests();
|
||||
}
|
||||
|
||||
void AreaDialog::onEditArea()
|
||||
{
|
||||
QModelIndexList selectedRows = m_ui->widget->selectedRows();
|
||||
if (selectedRows.isEmpty())
|
||||
return;
|
||||
const QModelIndex curIdx = selectedRows.first();
|
||||
if (!curIdx.isValid())
|
||||
return;
|
||||
INFO_LOG(m_logger) << " onEditTargetPart";
|
||||
|
||||
AreaEdit *dialog = new AreaEdit(this);
|
||||
|
||||
const TargetManagement::ShootbackArea &area = m_areaModel->getRowData(curIdx.row());
|
||||
|
||||
if (!dialog->init(m_dtc, m_ftc, m_sitMapGuiIfc, m_areaModel, area))
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << QLatin1String("Can't initialize AreaEdit!");
|
||||
delete dialog;
|
||||
return;
|
||||
}
|
||||
addDialog(dialog, m_menuGroup, QStringLiteral("Edit Area"), LtsWidgets::LayoutArea::eDialogTab, true, true);
|
||||
}
|
||||
|
||||
|
||||
QByteArray AreaDialog::toJson() const
|
||||
{
|
||||
QJsonObject obj;
|
||||
|
||||
// operatorId just for convenience:
|
||||
const int operatorId = LtsSessionData::LtsSessionData::getInstance()->getOperatorId();
|
||||
obj[QStringLiteral("OperatorId")] = operatorId;
|
||||
obj[QStringLiteral("XmlType")] = FileManagement::toString(FileManagement::XmlType::TGTShootbackArea);
|
||||
|
||||
{
|
||||
const QVector<TargetManagement::ShootbackArea>& modelData = m_areaModel->getData();
|
||||
QJsonArray jArray;
|
||||
for (const TargetManagement::ShootbackArea &area : modelData)
|
||||
{
|
||||
ShootbackAreaData sbad;
|
||||
sbad.id = area.id();
|
||||
sbad.name = QString::fromStdString(area.name());
|
||||
sbad.position = GeoPosition2D(area.position());
|
||||
sbad.width = area.width();
|
||||
sbad.height = area.height();
|
||||
jArray.append(sbad.toJson());
|
||||
}
|
||||
obj[QStringLiteral("ShootbackAreas")] = jArray;
|
||||
}
|
||||
|
||||
QJsonDocument doc(obj);
|
||||
|
||||
DEBUG_LOG(m_logger) << " json = " << doc.toJson();
|
||||
|
||||
return doc.toJson(QJsonDocument::Compact);
|
||||
}
|
||||
|
||||
QVector<ShootbackArea> AreaDialog::fromJson(const QByteArray &content)
|
||||
{
|
||||
const QJsonDocument doc(QJsonDocument::fromJson(content));
|
||||
const QJsonObject obj(doc.object());
|
||||
|
||||
// operatorId just for convenience:
|
||||
const int operatorId = obj[QStringLiteral("operatorId")].toInt();
|
||||
Q_UNUSED(operatorId);
|
||||
|
||||
const QJsonArray &jArray = obj[QStringLiteral("ShootbackAreas")].toArray();
|
||||
QVector<TargetManagement::ShootbackArea> vecData;
|
||||
vecData.reserve(jArray.size());
|
||||
for (const auto &item : jArray)
|
||||
{
|
||||
const ShootbackAreaData &sbad = ShootbackAreaData::fromJson(item.toObject());
|
||||
TargetManagement::ShootbackArea area;
|
||||
area.id(sbad.id);
|
||||
area.name(sbad.name.toStdString());
|
||||
area.position({sbad.position.lon, sbad.position.lat}); // GeoPosition2D( double lon, double lat);
|
||||
area.width(sbad.width);
|
||||
area.height(sbad.height);
|
||||
vecData.push_back(std::move(area));
|
||||
}
|
||||
return vecData;
|
||||
}
|
||||
|
||||
void AreaDialog::onEscapePressed()
|
||||
{
|
||||
m_ui->widget->clearSelection();
|
||||
}
|
||||
|
||||
void AreaDialog::onExportButtonClicked()
|
||||
{
|
||||
QByteArray byteArray = toJson();
|
||||
int fileId = m_flmGui->saveFileContent(this, FileManagement::FileType::Xml, m_session->exerciseId(), byteArray);
|
||||
if (fileId > 0)
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << "Saved file with id = " << fileId;
|
||||
else
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << "Could not save file in library ";
|
||||
}
|
||||
|
||||
void AreaDialog::onImportButtonClicked()
|
||||
{
|
||||
QHash<LtsWidgets::Button, QString> buttonTexts;
|
||||
buttonTexts.insert(LtsWidgets::Button::Ok, tr("Overwrite"));
|
||||
buttonTexts.insert(LtsWidgets::Button::Cancel, tr("Cancel"));
|
||||
|
||||
LtsWidgets::LtsMessageDialogNew *dlg = new LtsWidgets::LtsMessageDialogNew(this,
|
||||
tr("Overwrite existing data?"),
|
||||
tr("Load from Library"),
|
||||
LtsWidgets::Behaviour::Popup,
|
||||
LtsWidgets::Button::Ok | LtsWidgets::Button::Cancel,
|
||||
buttonTexts);
|
||||
connect(dlg, &LtsWidgets::LtsMessageDialogNew::ok,
|
||||
this, &AreaDialog::onImport);
|
||||
}
|
||||
|
||||
void AreaDialog::onImport()
|
||||
{
|
||||
INFO_LOG(m_logger) << LOGFUNCTION << "--- onImportButtonClicked() ";
|
||||
|
||||
QByteArray content;
|
||||
int fileId = m_flmGui->loadFileContent(this, content, {FileManagement::FileType::Xml},
|
||||
m_session->exerciseId(),
|
||||
FileManagement::toString(FileManagement::XmlType::TGTShootbackArea));
|
||||
if (fileId > 0)
|
||||
{
|
||||
if (!m_flmGui->isXmlType(content, FileManagement::toString(FileManagement::XmlType::TGTShootbackArea)))
|
||||
{
|
||||
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
|
||||
{
|
||||
// update svc via clear and (re-)insert:
|
||||
// 1) clear svc:
|
||||
const QVector<ShootbackArea> &curData = m_areaModel->getData();
|
||||
for (auto item : curData)
|
||||
{
|
||||
Core::RemoveElementRequest req(item.id());
|
||||
m_requestHelper->addRequest([this, req]()
|
||||
{
|
||||
return m_ftc->shootbackAreaRemoveRequest(req, this);
|
||||
});
|
||||
}
|
||||
|
||||
// 2) re-insert:
|
||||
const QVector<TargetManagement::ShootbackArea> vecDataCandidate(fromJson(content));
|
||||
for (ShootbackArea area : vecDataCandidate)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "area " <<area;
|
||||
|
||||
area.id(0); // force create
|
||||
m_requestHelper->addRequest([this, area]()
|
||||
{
|
||||
return m_ftc->shootbackAreaModifyRequest(area, this);
|
||||
});
|
||||
}
|
||||
|
||||
// clear view *before* performing the requests:
|
||||
m_areaModel->clear();
|
||||
|
||||
m_requestHelper->startRequests();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AreaDialog::onAssignTargetButtonClicked()
|
||||
{
|
||||
QModelIndexList selectedRows = m_ui->widget->selectedRows();
|
||||
if (selectedRows.isEmpty())
|
||||
return;
|
||||
const QModelIndex curIdx = selectedRows.first();
|
||||
if (!curIdx.isValid())
|
||||
return;
|
||||
|
||||
const int areaId = m_areaModel->getRowData(curIdx.row()).id();
|
||||
|
||||
// instead of emit a signal, create the according dialog frome here directly
|
||||
// emit assignTargetsRequested(areaId);
|
||||
|
||||
auto dlg = new AssignmentDialog(menuGroup(), m_session, this->parentWidget());
|
||||
if (!dlg->init(AssignmentDialog::MODE::FILTERED_TO_SINGLE_AREA, areaId))
|
||||
{
|
||||
dlg->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_session->addWidget(dlg, menuGroup(), QStringLiteral("ConfigureTargetsToAreaId_%1").arg(areaId), LtsWidgets::LayoutArea::eDialogTab))
|
||||
dlg->deleteLater();
|
||||
}
|
||||
|
||||
void AreaDialog::onMapCenterClicked()
|
||||
{
|
||||
if (!m_sitMapGuiIfc)
|
||||
return;
|
||||
QModelIndexList selectedRows = m_ui->widget->selectedRows();
|
||||
if (selectedRows.isEmpty())
|
||||
return;
|
||||
const QModelIndex curIdx = selectedRows.first();
|
||||
if (!curIdx.isValid())
|
||||
return;
|
||||
|
||||
const int id = m_areaModel->getRowData(curIdx.row()).id();
|
||||
m_sitMapGuiIfc->centerMapToMapObject(SituationMap::MapObjectType::MOT_ShootbackArea, id);
|
||||
}
|
||||
|
||||
void AreaDialog::onMapZoomToClicked()
|
||||
{
|
||||
QModelIndexList selectedRows = m_ui->widget->selectedRows();
|
||||
if (selectedRows.isEmpty())
|
||||
return;
|
||||
QModelIndex index = selectedRows.first();
|
||||
if (!index.isValid())
|
||||
return;
|
||||
|
||||
if (!m_areaModel || !m_sitMapGuiIfc)
|
||||
return;
|
||||
|
||||
int areaId = m_areaModel->getRowData(index.row()).id();
|
||||
if (areaId<=0)
|
||||
return;
|
||||
|
||||
// Assigned Targets:
|
||||
QVector<int> assignedTargets;
|
||||
auto cb = [areaId, &assignedTargets](const TargetManagement::TargetAreaAssignment &assignment)
|
||||
{
|
||||
if (assignment.areaId() == areaId)
|
||||
assignedTargets.push_back(assignment.targetParticipantId());
|
||||
};
|
||||
m_dtc->targetAreaAssignments(cb);
|
||||
|
||||
{
|
||||
QVector<QPair<SituationMap::MapObjectType, int>> entities;
|
||||
entities.reserve(assignedTargets.size()+1);
|
||||
entities.push_back({SituationMap::MapObjectType::MOT_ShootbackArea, areaId});
|
||||
|
||||
for (auto item : assignedTargets)
|
||||
entities.push_back({SituationMap::MapObjectType::MOT_Participant, item});
|
||||
|
||||
m_sitMapGuiIfc->zoomMapTo(entities);
|
||||
}
|
||||
}
|
||||
|
||||
void AreaDialog::onObjectEntered(const QModelIndex &index)
|
||||
{
|
||||
if (!m_sitMapGuiIfc)
|
||||
return;
|
||||
if (!index.isValid())
|
||||
{
|
||||
m_sitMapGuiIfc->removeObjectIndicator();
|
||||
return;
|
||||
}
|
||||
int areaId = m_areaModel->getRowData(index.row()).id();
|
||||
if (areaId>0)
|
||||
{
|
||||
// Area
|
||||
m_sitMapGuiIfc->objectIndicatorToMapObject(SituationMap::MapObjectType::MOT_ShootbackArea, areaId, true);
|
||||
|
||||
// Assigned Targets:
|
||||
QVector<int> assignedTargets;
|
||||
auto cb = [areaId, &assignedTargets](const TargetManagement::TargetAreaAssignment &assignment)
|
||||
{
|
||||
if (assignment.areaId() == areaId)
|
||||
assignedTargets.push_back(assignment.targetParticipantId());
|
||||
};
|
||||
m_dtc->targetAreaAssignments(cb);
|
||||
m_sitMapGuiIfc->setMapObjectSelected(SituationMap::MapObjectType::MOT_Participant, assignedTargets, true);
|
||||
}
|
||||
else
|
||||
m_sitMapGuiIfc->removeObjectIndicator();
|
||||
}
|
||||
|
||||
void AreaDialog::onTableViewClicked(const QModelIndex &index)
|
||||
{
|
||||
if (!index.isValid())
|
||||
return;
|
||||
|
||||
if (QGuiApplication::keyboardModifiers().testFlag(Qt::KeyboardModifier::ShiftModifier))
|
||||
onMapCenterClicked();
|
||||
}
|
||||
|
||||
void AreaDialog::clearSelectionOfMapObjects()
|
||||
{
|
||||
if (!m_sitMapGuiIfc)
|
||||
return;
|
||||
// remove MapObjectIndicator:
|
||||
m_sitMapGuiIfc->removeObjectIndicator();
|
||||
}
|
||||
|
||||
void AreaDialog::onSelectionChanged()
|
||||
{
|
||||
QModelIndexList selectedRows = m_ui->widget->selectedRows();
|
||||
const int cntSelectedRows = selectedRows.size();
|
||||
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Remove, cntSelectedRows >= 1);
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Edit, cntSelectedRows == 1);
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::CenterMap, cntSelectedRows == 1);
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::ZoomMapTo, cntSelectedRows == 1);
|
||||
m_assignTargetBtn->setEnabled(cntSelectedRows == 1); // LtsWidgets::DialogButton::Library
|
||||
|
||||
if (selectedRows.isEmpty())
|
||||
onObjectEntered({}); // use invalid Idx to removeObjectIndicator
|
||||
else
|
||||
onObjectEntered(selectedRows.first());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
} // namespace TargetManagement
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Target Configuration
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Norbert Thoden, NLE, 2020-06-29
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LtsWidgets/lts_dialog.h>
|
||||
#include <TargetManagement/tgt_dtc.h>
|
||||
#include <TargetManagement/tgt_ftc.h>
|
||||
#include <LtsUtilsGuiDds/request_helper.h>
|
||||
#include <TargetManagement/logger.h>
|
||||
#include <Plugins/TargetManagement/Gui/ShootbackTargetConfiguration/tgt_area_model.h>
|
||||
#include <Plugins/FileManagement/flm_explorer_gui_plugin_interface.h>
|
||||
#include <Plugins/SituationMapPlugin/situation_map_gui_plugin_interface.h>
|
||||
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class AreaDialog;
|
||||
}
|
||||
|
||||
namespace TargetManagement
|
||||
{
|
||||
|
||||
class AreaDialog final : public LtsWidgets::LtsDialog
|
||||
, protected TargetManagement::Interface::Ftc::ShootbackAreaModifyReplyHandler
|
||||
, protected TargetManagement::Interface::Ftc::ShootbackAreaRemoveReplyHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
using BaseClass = LtsWidgets::LtsDialog;
|
||||
|
||||
explicit AreaDialog(const QString &menuGroup, LtsSession::LtsSession *session, QWidget *parent = nullptr);
|
||||
~AreaDialog();
|
||||
|
||||
bool init();
|
||||
|
||||
void retranslate() override;
|
||||
|
||||
Q_SIGNALS:
|
||||
void escapePressed();
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent *event) override final;
|
||||
void onShootbackAreaModifyReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
|
||||
void onShootbackAreaRemoveReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
|
||||
|
||||
QByteArray toJson() const;
|
||||
QVector<ShootbackArea> fromJson(const QByteArray &content);
|
||||
|
||||
private Q_SLOTS:
|
||||
void onEscapePressed();
|
||||
void onSelectionChanged();
|
||||
void onNewArea();
|
||||
void onRemoveArea();
|
||||
void onEditArea();
|
||||
|
||||
void onExportButtonClicked();
|
||||
void onImportButtonClicked();
|
||||
void onImport();
|
||||
|
||||
void onAssignTargetButtonClicked();
|
||||
|
||||
void onMapCenterClicked();
|
||||
void onMapZoomToClicked();
|
||||
|
||||
void onObjectEntered(const QModelIndex &index);
|
||||
void onTableViewClicked(const QModelIndex &index);
|
||||
|
||||
void clearSelectionOfMapObjects();
|
||||
|
||||
private:
|
||||
QPushButton *m_assignTargetBtn{nullptr};
|
||||
AreaModel *m_areaModel{nullptr};
|
||||
|
||||
std::shared_ptr<TargetManagement::Interface::Dtc> m_dtc;
|
||||
std::shared_ptr<TargetManagement::Interface::Ftc> m_ftc;
|
||||
std::shared_ptr<FileManagement::ForeignGuiInterface> m_flmGui;
|
||||
std::shared_ptr<SituationMap::ForeignGuiInterface> m_sitMapGuiIfc;
|
||||
|
||||
LtsSession::LtsSession *m_session{nullptr};
|
||||
Ui::AreaDialog *m_ui{nullptr};
|
||||
QString m_menuGroup;
|
||||
LtsUtils::RequestHelper *m_requestHelper{nullptr};
|
||||
LOGGER_T m_logger;
|
||||
};
|
||||
|
||||
} // namespace TargetManagement
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AreaDialog</class>
|
||||
<widget class="QWidget" name="AreaDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>455</width>
|
||||
<height>341</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">AlarmView</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="LtsDataView::LtsDataView" name="widget" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>250</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</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>
|
||||
+174
@@ -0,0 +1,174 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* TargetManagement - Target Edit Dialog
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Norbert Thoden, NLE, 2020-05-29
|
||||
*/
|
||||
|
||||
#include "tgt_area_edit.h"
|
||||
#include "tgt_area_model.h"
|
||||
#include "ui_tgt_area_edit.h"
|
||||
|
||||
#include <LtsUtilsSettings/settings.h>
|
||||
|
||||
|
||||
namespace TargetManagement
|
||||
{
|
||||
|
||||
AreaEdit::AreaEdit(QWidget *parent)
|
||||
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
|
||||
, m_requestHelper(new LtsUtils::RequestHelper(this))
|
||||
, m_ui(new Ui::AreaEdit)
|
||||
, m_logger(getLogger("AreaEdit"))
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
m_ui->sbWidth->setMinimum(s_minWidth);
|
||||
m_ui->sbWidth->setMaximum(s_maxWidth);
|
||||
m_ui->sbWidth->setSingleStep(s_stepWidth);
|
||||
m_ui->sbHeight->setMinimum(s_minHeight);
|
||||
m_ui->sbHeight->setMaximum(s_maxHeight);
|
||||
m_ui->sbHeight->setSingleStep(s_stepHeight);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
AreaEdit::~AreaEdit()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void AreaEdit::retranslate()
|
||||
{
|
||||
translate(m_ui, m_area, tr("ShootbackArea"));
|
||||
}
|
||||
|
||||
bool AreaEdit::init(const std::shared_ptr<TargetManagement::Interface::Dtc> &dtc,
|
||||
const std::shared_ptr<TargetManagement::Interface::Ftc> &ftc,
|
||||
const std::shared_ptr<SituationMap::ForeignGuiInterface> &sitMapGuiIfc,
|
||||
AreaModel *areaModel,
|
||||
const ShootbackArea &area)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "AreaEdit::init()";
|
||||
|
||||
if (!dtc || !ftc || !sitMapGuiIfc)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "AreaEdit::init() Invalid shared_ptr!";
|
||||
return false;
|
||||
}
|
||||
|
||||
m_dtc = dtc;
|
||||
m_ftc = ftc;
|
||||
m_sitMapGuiIfc = sitMapGuiIfc;
|
||||
m_areaModel = areaModel;
|
||||
setData(area);
|
||||
|
||||
if (m_sitMapGuiIfc)
|
||||
connect(m_ui->pbPosition, &QPushButton::clicked, this, &AreaEdit::getPosition);
|
||||
else
|
||||
m_ui->pbPosition->setEnabled(false);
|
||||
|
||||
connect(m_ui->pbClear, &QPushButton::clicked,
|
||||
m_ui->positionEdit, &LtsCoordWidget::LtsCoordWidget::clear);
|
||||
|
||||
setOnlineHelpFilename(QStringLiteral("Situation-Targets"));
|
||||
|
||||
// if (m_area.id() <= 0)
|
||||
// slotChangesMade();
|
||||
|
||||
enaDisa();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AreaEdit::enaDisa()
|
||||
{
|
||||
m_ui->pbPosition->setEnabled(m_sitMapGuiIfc.get());
|
||||
}
|
||||
|
||||
//slots
|
||||
|
||||
bool AreaEdit::apply()
|
||||
{
|
||||
m_area.name(m_ui->leName->text().toStdString());
|
||||
const QPointF &coord = m_ui->positionEdit->coordinate();
|
||||
m_area.position({coord.x(), coord.y()});
|
||||
m_area.width(m_ui->sbWidth->value());
|
||||
m_area.height(m_ui->sbHeight->value());
|
||||
|
||||
m_requestHelper->addRequest([this]()
|
||||
{
|
||||
return m_ftc->shootbackAreaModifyRequest(m_area, this);
|
||||
});
|
||||
|
||||
return m_requestHelper->startRequests();
|
||||
}
|
||||
|
||||
void AreaEdit::getPosition()
|
||||
{
|
||||
if (!has2DMap())
|
||||
return;
|
||||
|
||||
m_sitMapGuiIfc->getRectangleNorth(this,
|
||||
SLOT(onRectData(QPointF,double,double,QPolygonF)),
|
||||
nullptr,
|
||||
s_minWidth,
|
||||
s_maxWidth,
|
||||
s_minHeight,
|
||||
s_maxHeight,
|
||||
m_ui->positionEdit->coordinate(),
|
||||
m_ui->sbWidth->value(),
|
||||
m_ui->sbHeight->value());
|
||||
}
|
||||
|
||||
void AreaEdit::onRectData(const QPointF ¢erPoint, double width, double height, const QPolygonF &coordinates)
|
||||
{
|
||||
m_previewPolygon = coordinates;
|
||||
m_ui->positionEdit->setCoordinate(centerPoint);
|
||||
m_ui->sbWidth->setValue(width);
|
||||
m_ui->sbHeight->setValue(height);
|
||||
DEBUG_LOG(m_logger) << "Pos X: " << centerPoint.x() << " Y: " << centerPoint.y() << " W: " << width << " H: " << height;
|
||||
|
||||
showPreviewObject();
|
||||
}
|
||||
|
||||
|
||||
//private
|
||||
bool AreaEdit::has2DMap()
|
||||
{
|
||||
if (!m_sitMapGuiIfc)
|
||||
return false;
|
||||
if (m_sitMapGuiIfc->mapMode() != SituationMap::MapMode::MapMode_2D)
|
||||
{
|
||||
LtsWidgets::LtsMessageDialog::showMessage(this, tr("Only available in 2D mode"));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void AreaEdit::showPreviewObject()
|
||||
{
|
||||
if (!m_sitMapGuiIfc)
|
||||
return;
|
||||
if (m_previewPolygon.isEmpty())
|
||||
return;
|
||||
m_sitMapGuiIfc->displayPreviewObject(this, m_previewPolygon, true);
|
||||
}
|
||||
|
||||
|
||||
void AreaEdit::setData(const ShootbackArea &area)
|
||||
{
|
||||
m_area = area;
|
||||
|
||||
if (m_area.id() > 0)
|
||||
{
|
||||
m_ui->leName->setText(QString::fromStdString(m_area.name()));
|
||||
m_ui->positionEdit->setCoordinate(m_area.position().lon(), m_area.position().lat());
|
||||
m_ui->sbWidth->setValue(m_area.width());
|
||||
m_ui->sbHeight->setValue(m_area.height());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* TargetManagement - Target Edit Dialog
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Norbert Thoden, NLE, 2020-05-29
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LtsWidgets/lts_dialog.h>
|
||||
|
||||
#include <Services/TargetManagement/tgt_dtc.h>
|
||||
#include <Services/TargetManagement/tgt_ftc.h>
|
||||
#include <Plugins/SituationMapPlugin/situation_map_gui_plugin_interface.h>
|
||||
|
||||
#include <TargetManagement/logger.h>
|
||||
#include <LtsUtilsGuiDds/request_helper.h>
|
||||
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class AreaEdit;
|
||||
}
|
||||
|
||||
namespace TargetManagement
|
||||
{
|
||||
class AreaModel;
|
||||
|
||||
class AreaEdit : public LtsWidgets::LtsDialog,
|
||||
protected TargetManagement::Interface::Ftc::ShootbackAreaModifyReplyHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AreaEdit(QWidget *parent = nullptr);
|
||||
~AreaEdit();
|
||||
|
||||
bool init(const std::shared_ptr<TargetManagement::Interface::Dtc> &dtc,
|
||||
const std::shared_ptr<TargetManagement::Interface::Ftc> &ftc,
|
||||
const std::shared_ptr<SituationMap::ForeignGuiInterface> &sitMapGuiIfc,
|
||||
AreaModel *areaModel,
|
||||
const ShootbackArea &area = ShootbackArea());
|
||||
|
||||
|
||||
//virtual functions from TargetManagement::Interface::Ftc::..
|
||||
void onShootbackAreaModifyReply(const Core::FunctionReplyObject &replyObject) override { m_requestHelper->requestReply(replyObject); }
|
||||
|
||||
public Q_SLOTS:
|
||||
|
||||
private Q_SLOTS:
|
||||
void enaDisa();
|
||||
void getPosition();
|
||||
void onRectData(const QPointF ¢erPoint, double width, double height, const QPolygonF &coordinates);
|
||||
|
||||
private:
|
||||
bool has2DMap();
|
||||
void showPreviewObject();
|
||||
|
||||
void setData(const ShootbackArea &area);
|
||||
bool apply() override;
|
||||
void retranslate() override;
|
||||
|
||||
static constexpr double s_minWidth {10};
|
||||
static constexpr double s_maxWidth {1000};
|
||||
static constexpr double s_stepWidth {5};
|
||||
static constexpr double s_minHeight {10};
|
||||
static constexpr double s_maxHeight {1000};
|
||||
static constexpr double s_stepHeight {5};
|
||||
|
||||
ShootbackArea m_area;
|
||||
QPolygonF m_previewPolygon;
|
||||
AreaModel *m_areaModel{nullptr};
|
||||
|
||||
std::shared_ptr<TargetManagement::Interface::Dtc> m_dtc;
|
||||
std::shared_ptr<TargetManagement::Interface::Ftc> m_ftc;
|
||||
std::shared_ptr<SituationMap::ForeignGuiInterface> m_sitMapGuiIfc;
|
||||
LtsUtils::RequestHelper *m_requestHelper{nullptr};
|
||||
Ui::AreaEdit *m_ui{nullptr};
|
||||
LOGGER_T m_logger;
|
||||
};
|
||||
|
||||
} //namespace TargetManagement
|
||||
+143
@@ -0,0 +1,143 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AreaEdit</class>
|
||||
<widget class="QWidget" name="AreaEdit">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>963</width>
|
||||
<height>318</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="lbl_name">
|
||||
<property name="text">
|
||||
<string>Name:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2" colspan="4">
|
||||
<widget class="QLineEdit" name="leName"/>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QLabel" name="lblPosition">
|
||||
<property name="toolTip">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Center Point:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="LtsCoordWidget::LtsCoordWidget" name="positionEdit" native="true">
|
||||
<property name="toolTip">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3" colspan="2">
|
||||
<widget class="QPushButton" name="pbPosition">
|
||||
<property name="toolTip">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>:/style/position.svg</normaloff>:/style/position.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="5">
|
||||
<widget class="QPushButton" name="pbClear">
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>:/style/remove.svg</normaloff>:/style/remove.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="6">
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>690</width>
|
||||
<height>33</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QLabel" name="lblDimensions">
|
||||
<property name="toolTip">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Dimensions [m]:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2" colspan="2">
|
||||
<widget class="LtsWidgets::LtsSpinBox" name="sbWidth"/>
|
||||
</item>
|
||||
<item row="2" column="4" colspan="2">
|
||||
<widget class="LtsWidgets::LtsSpinBox" name="sbHeight"/>
|
||||
</item>
|
||||
<item row="2" column="6">
|
||||
<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 row="3" column="1">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>181</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>LtsCoordWidget::LtsCoordWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>LtsCoordTrans/lts_coord_widget.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>LtsWidgets::LtsSpinBox</class>
|
||||
<extends>QSpinBox</extends>
|
||||
<header>LtsWidgets/lts_spinbox.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>leName</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
+203
@@ -0,0 +1,203 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* AreaModel
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Norbert Thoden, NLE, 2020-06-29
|
||||
*/
|
||||
|
||||
#include "tgt_area_model.h"
|
||||
#include "tgt_common.h"
|
||||
|
||||
#include <LtsUtilsCore/variant_operators.h>
|
||||
#include <LtsCoordTrans/lts_coord_trans.h>
|
||||
#include <ParticipantManagement/ppm_translation.h>
|
||||
|
||||
#include <QApplication> // pixelMetric
|
||||
#include <QBuffer>
|
||||
|
||||
namespace TargetManagement
|
||||
{
|
||||
|
||||
//---------------------------------
|
||||
// AreaModel
|
||||
//---------------------------------
|
||||
AreaModel::AreaModel(QObject *parent)
|
||||
: BaseClass(
|
||||
{
|
||||
tr("Id"),
|
||||
tr("Name"),
|
||||
|
||||
// main config
|
||||
tr("Center"),
|
||||
tr("Width"),
|
||||
tr("Height"),
|
||||
},
|
||||
parent)
|
||||
, m_logger(getLogger("AreaModel"))
|
||||
{}
|
||||
|
||||
|
||||
bool AreaModel::initModel(const std::shared_ptr<TargetManagement::Interface::Dtc> &tgtDtc)
|
||||
{
|
||||
m_tgt_dtc = tgtDtc;
|
||||
|
||||
// insert Model
|
||||
const QMap<qint32, TargetManagement::ShootbackArea> areas = m_tgt_dtc->shootbackAreas();
|
||||
INFO_LOG(m_logger) << "initModel - #AreaModel: " << areas.size();
|
||||
|
||||
connect(m_tgt_dtc.get(), &Interface::Dtc::shootbackAreaChanged,
|
||||
this, &AreaModel::onShootbackAreaChanged);
|
||||
|
||||
auto cb = [this](const TargetManagement::ShootbackArea & d) { onShootbackAreaChanged(d, DataModification::eAdded); };
|
||||
m_tgt_dtc->shootbackAreas(cb);
|
||||
|
||||
// updateColumnFilter
|
||||
connect(this, &AreaModel::rowsInserted, this, &AreaModel::updateColumnFilter);
|
||||
connect(this, &AreaModel::rowsRemoved, this, &AreaModel::updateColumnFilter);
|
||||
connect(this, &AreaModel::modelReset, this, &AreaModel::updateColumnFilter);
|
||||
// in case of changing value like hitsToKill:
|
||||
connect(this, &AreaModel::dataChanged, this, &AreaModel::updateColumnFilter);
|
||||
updateColumnFilter();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariant AreaModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (role == LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole &&
|
||||
orientation == Qt::Horizontal)
|
||||
{
|
||||
// a few QSet<QString> ==>
|
||||
const auto processString = [](const QSet<QString> &usedXYCont) -> QVariant
|
||||
{
|
||||
LtsWidgets::ComboboxFilterContent cfc;
|
||||
cfc.data.reserve(usedXYCont.size());
|
||||
LtsWidgets::ComboboxFilterData cfd;
|
||||
|
||||
for (const QString &value : usedXYCont)
|
||||
{
|
||||
cfd.data = value;
|
||||
cfd.text = value;
|
||||
cfc.data.push_back(cfd);
|
||||
}
|
||||
cfc.sortItems = true;
|
||||
return cfc.toVariant();
|
||||
};
|
||||
|
||||
if (section == Name)
|
||||
return processString(m_usedNames);
|
||||
}
|
||||
return BaseClass::headerData(section, orientation, role);
|
||||
}
|
||||
|
||||
QVariant AreaModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
INFO_LOG(m_logger) << LOGFUNCTION << " role=" << role
|
||||
<< " index = " << index.column();
|
||||
|
||||
if (!indexIsValid(index))
|
||||
return QVariant();
|
||||
if (role != Qt::DisplayRole &&
|
||||
role != Qt::DecorationRole &&
|
||||
role != Qt::BackgroundRole &&
|
||||
role != Qt::ToolTipRole &&
|
||||
role != LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole)
|
||||
return QVariant();
|
||||
|
||||
const TargetManagement::ShootbackArea &shootbackArea = m_vecData.at(index.row());
|
||||
|
||||
if (role == Qt::BackgroundRole)
|
||||
{
|
||||
if ((index.column() == Center) &&
|
||||
((shootbackArea.position().lat() <= 0) || (shootbackArea.position().lon() <= 0)))
|
||||
return getWarningBackgroundRole(); // orange
|
||||
if (index.column() == Width && shootbackArea.width() <= 0)
|
||||
return getWarningBackgroundRole(); // orange
|
||||
if (index.column() == Height && shootbackArea.height() <= 0)
|
||||
return getWarningBackgroundRole(); // orange
|
||||
}
|
||||
else
|
||||
|
||||
if (role == LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole)
|
||||
{
|
||||
if (index.column() == Name)
|
||||
return QString::fromStdString(shootbackArea.name());
|
||||
}
|
||||
|
||||
switch (index.column())
|
||||
{
|
||||
case Id:
|
||||
return shootbackArea.id();
|
||||
case Name:
|
||||
return QString::fromStdString(shootbackArea.name());
|
||||
case Center:
|
||||
{
|
||||
const Core::GeoPosition2D &pos = shootbackArea.position();
|
||||
return LtsCoordTrans::mgrsFromGeographic(pos.lon(), pos.lat());
|
||||
}
|
||||
case Width:
|
||||
return shootbackArea.width();
|
||||
case Height:
|
||||
return shootbackArea.height();
|
||||
} // switch
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void AreaModel::onShootbackAreaChanged(const TargetManagement::ShootbackArea &data,
|
||||
const DataModification modType)
|
||||
{
|
||||
BaseClass::onDataChanged(data, modType);
|
||||
emit signalAreaNamesChanged();
|
||||
}
|
||||
|
||||
void AreaModel::updateColumnFilter()
|
||||
{
|
||||
m_usedNames.clear();
|
||||
for (const ShootbackArea &item : qAsConst(m_vecData))
|
||||
m_usedNames.insert(QString::fromStdString(item.name()));
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------
|
||||
// AreaProxyModel
|
||||
// --------------------------------------------------------
|
||||
void AreaProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
|
||||
{
|
||||
m_sourceModel = qobject_cast<AreaModel *>(sourceModel);
|
||||
BaseClass::setSourceModel(sourceModel);
|
||||
}
|
||||
|
||||
bool AreaProxyModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
|
||||
{
|
||||
if (!m_sourceModel ||
|
||||
source_left.column() != source_right.column() ||
|
||||
source_left.row() < 0 || source_left.row() >= m_sourceModel->m_vecData.size() ||
|
||||
source_right.row() < 0 || source_right.row() >= m_sourceModel->m_vecData.size()
|
||||
)
|
||||
return BaseClass::lessThan(source_left, source_right);
|
||||
|
||||
const TargetManagement::ShootbackArea &left = m_sourceModel->m_vecData.at(source_left.row());
|
||||
const TargetManagement::ShootbackArea &right = m_sourceModel->m_vecData.at(source_right.row());
|
||||
switch (source_left.column())
|
||||
{
|
||||
case AreaModel::Columns::Id:
|
||||
return left.id() < right.id();
|
||||
case AreaModel::Columns::Name:
|
||||
return left.name() < right.name();
|
||||
case AreaModel::Columns::Width:
|
||||
return left.width() < right.width();
|
||||
case AreaModel::Columns::Height:
|
||||
return left.height() < right.height();
|
||||
|
||||
case AreaModel::Columns::Center:
|
||||
// QString compare
|
||||
return LtsUtils::lessThan(source_left.data(), source_right.data());
|
||||
}
|
||||
return BaseClass::lessThan(source_left, source_right);
|
||||
}
|
||||
|
||||
|
||||
} // namespace TargetManagement
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* AreaModel
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Norbert Thoden, NLE, 2020-06-29
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "tgt_participant_handler.h"
|
||||
#include <TargetManagement/tgt_dtc.h>
|
||||
#include <TargetManagement/logger.h>
|
||||
|
||||
#include <LtsWidgets/lts_abstract_table_model.h>
|
||||
#include <LtsWidgets/lts_column_filter_proxy_model.h>
|
||||
#include <LtsSession/lts_session.h>
|
||||
|
||||
namespace TargetManagement
|
||||
{
|
||||
|
||||
// Forward:
|
||||
class ParticipantHandler;
|
||||
|
||||
// --------------------------------------------------------
|
||||
// AreaModel
|
||||
// --------------------------------------------------------
|
||||
class AreaModel final : public LtsWidgets::LtsAbstractTableModel<TargetManagement::ShootbackArea>
|
||||
{
|
||||
Q_OBJECT
|
||||
using BaseClass = LtsWidgets::LtsAbstractTableModel<TargetManagement::ShootbackArea>;
|
||||
|
||||
public:
|
||||
enum Columns
|
||||
{
|
||||
Id,
|
||||
Name,
|
||||
|
||||
// main config
|
||||
Center,
|
||||
Width,
|
||||
Height
|
||||
};
|
||||
|
||||
explicit AreaModel(QObject *parent = nullptr);
|
||||
|
||||
bool initModel(const std::shared_ptr<Interface::Dtc> &tgtDtc);
|
||||
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const override final;
|
||||
QVariant data(const QModelIndex &, int) const override;
|
||||
|
||||
const QVector<ShootbackArea> &getData() const { return m_vecData; }
|
||||
|
||||
Q_SIGNALS:
|
||||
void signalAreaNamesChanged();
|
||||
|
||||
private Q_SLOTS:
|
||||
void onShootbackAreaChanged(const TargetManagement::ShootbackArea &data,
|
||||
const DataModification modType);
|
||||
void updateColumnFilter();
|
||||
|
||||
private:
|
||||
friend class AreaProxyModel;
|
||||
std::shared_ptr<TargetManagement::Interface::Dtc> m_tgt_dtc;
|
||||
|
||||
// column filter
|
||||
QSet<QString> m_usedNames;
|
||||
|
||||
LOGGER_T m_logger;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------
|
||||
// AreaProxyModel
|
||||
// --------------------------------------------------------
|
||||
class AreaProxyModel : public LtsWidgets::LtsColumnFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
using BaseClass = LtsWidgets::LtsColumnFilterProxyModel;
|
||||
|
||||
public:
|
||||
using LtsWidgets::LtsColumnFilterProxyModel::LtsColumnFilterProxyModel;
|
||||
void setSourceModel(QAbstractItemModel *sourceModel) override;
|
||||
|
||||
protected:
|
||||
bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override;
|
||||
|
||||
protected:
|
||||
AreaModel *m_sourceModel{nullptr};
|
||||
};
|
||||
|
||||
} //namespace TargetManagement
|
||||
Executable
+703
@@ -0,0 +1,703 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* AssignmentParticipantModel
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Norbert Thoden, NLE, 2020-06-29
|
||||
*/
|
||||
|
||||
#include "tgt_assignment_part_model.h"
|
||||
#include "tgt_common.h"
|
||||
|
||||
#include <LtsUtilsCore/variant_operators.h>
|
||||
#include <LtsCoordTrans/lts_coord_trans.h>
|
||||
#include <ParticipantManagement/ppm_translation.h>
|
||||
|
||||
#include <QApplication> // pixelMetric
|
||||
#include <QBuffer>
|
||||
|
||||
namespace TargetManagement
|
||||
{
|
||||
// some helper
|
||||
bool isEqual(const ShootbackConfiguration &c1, const ShootbackConfiguration &c2)
|
||||
{
|
||||
return (
|
||||
(c1.interval1() == c2.interval1()) &&
|
||||
(c1.flash1() == c2.flash1()) &&
|
||||
(c1.effect1() == c2.effect1()) &&
|
||||
(c1.interval2() == c2.interval2()) &&
|
||||
(c1.flash2() == c2.flash2()) &&
|
||||
(c1.effect2() == c2.effect2())
|
||||
);
|
||||
}
|
||||
|
||||
bool isDefault(const ShootbackConfiguration &c) { return isEqual(c, ShootbackConfiguration()); }
|
||||
|
||||
bool isEqual(const TargetAreaAssignment &a1, const TargetAreaAssignment &a2, bool ignoringAreaIdAndParticipantId)
|
||||
{
|
||||
return (
|
||||
(a1.id() == a2.id()) &&
|
||||
(a1.name() == a2.name()) &&
|
||||
(ignoringAreaIdAndParticipantId || (a1.areaId() == a2.areaId())) &&
|
||||
(ignoringAreaIdAndParticipantId || (a1.targetParticipantId() == a2.targetParticipantId())) &&
|
||||
(a1.isActive() == a2.isActive()) &&
|
||||
isEqual(a1.configuration(), a2.configuration())
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------
|
||||
// AssignmentParticipantModel
|
||||
//---------------------------------
|
||||
AssignmentParticipantModel::AssignmentParticipantModel(QObject *parent)
|
||||
: BaseClass(
|
||||
{
|
||||
tr("Id"),
|
||||
tr("Assignment Name"),
|
||||
tr("Assigned"), // isActive
|
||||
|
||||
// associated target:
|
||||
tr("TargetId"),
|
||||
tr("TargetName"),
|
||||
// associated participant:
|
||||
tr("Participant Id"),
|
||||
tr("Equipmentnumber"),
|
||||
tr("Participant"),
|
||||
|
||||
// associated Area
|
||||
tr("AreaId"),
|
||||
tr("AreaName"),
|
||||
|
||||
// configuration
|
||||
tr("Interval_1"),
|
||||
tr("Flash_1"),
|
||||
tr("Effect_1"),
|
||||
tr("Interval_2"),
|
||||
tr("Flash_2"),
|
||||
tr("Effect_2")
|
||||
},
|
||||
parent)
|
||||
, m_logger(getLogger("AssignmentParticipantModel"))
|
||||
{}
|
||||
|
||||
|
||||
bool AssignmentParticipantModel::initModel(const std::shared_ptr<TargetManagement::Interface::Dtc> &tgtDtc,
|
||||
const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc,
|
||||
const std::shared_ptr<ParticipantManagement::ForeignGuiComboboxInterface> &ppmGuiCbxIfc,
|
||||
LtsSession::LtsSession *session)
|
||||
{
|
||||
m_tgt_dtc = tgtDtc;
|
||||
m_session = session;
|
||||
|
||||
delete m_participantHandler;
|
||||
m_participantHandler = new ParticipantHandler(this);
|
||||
|
||||
m_participantHandler->init(m_tgt_dtc, ppmDtc, ppmGuiCbxIfc /*, exmDtc*/); // exercises are no relavant yet
|
||||
|
||||
connect(m_participantHandler, &ParticipantHandler::signalParticipantNamesChanged,
|
||||
this, &AssignmentParticipantModel::signalParticipantNamesChanged);
|
||||
connect(m_participantHandler, &ParticipantHandler::signalParticipantChanged,
|
||||
this, &AssignmentParticipantModel::update);
|
||||
|
||||
// insert Model
|
||||
const QMap<qint32, TargetManagement::TargetAreaAssignment> targetAreaAssignments = m_tgt_dtc->targetAreaAssignments();
|
||||
INFO_LOG(m_logger) << "initModel - #targetAreaAssignments.size(): " << targetAreaAssignments.size();
|
||||
|
||||
connect(m_tgt_dtc.get(), &Interface::Dtc::targetAreaAssignmentChanged,
|
||||
this, &AssignmentParticipantModel::onTargetAreaAssignmentChanged);
|
||||
|
||||
{
|
||||
auto cb = [this](const TargetManagement::TargetAreaAssignment & d) { onTargetAreaAssignmentChanged(d, DataModification::eAdded); };
|
||||
m_tgt_dtc->targetAreaAssignments(cb);
|
||||
}
|
||||
INFO_LOG(m_logger) << "initModel - #targetAreaAssignments.size(): " << targetAreaAssignments.size() << " DONE";
|
||||
|
||||
// updateColumnFilter
|
||||
connect(this, &AssignmentParticipantModel::rowsInserted, this, &AssignmentParticipantModel::updateColumnFilter);
|
||||
connect(this, &AssignmentParticipantModel::rowsRemoved, this, &AssignmentParticipantModel::updateColumnFilter);
|
||||
connect(this, &AssignmentParticipantModel::modelReset, this, &AssignmentParticipantModel::updateColumnFilter);
|
||||
// in case of changing value like hitsToKill:
|
||||
connect(this, &AssignmentParticipantModel::dataChanged, this, &AssignmentParticipantModel::updateColumnFilter);
|
||||
updateColumnFilter();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariant AssignmentParticipantModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (role == LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole &&
|
||||
orientation == Qt::Horizontal)
|
||||
{
|
||||
// a few QSet<QString> ==>
|
||||
const auto processString = [](const QSet<QString> &usedXYCont) -> QVariant
|
||||
{
|
||||
LtsWidgets::ComboboxFilterContent cfc;
|
||||
cfc.data.reserve(usedXYCont.size());
|
||||
LtsWidgets::ComboboxFilterData cfd;
|
||||
|
||||
for (const QString &value : usedXYCont)
|
||||
{
|
||||
cfd.data = value;
|
||||
cfd.text = value;
|
||||
cfc.data.push_back(cfd);
|
||||
}
|
||||
cfc.sortItems = true;
|
||||
return cfc.toVariant();
|
||||
};
|
||||
|
||||
// a few Set<int> ==>
|
||||
const auto processBoolean = [this](const QSet<int> &usedXYCont) -> QVariant
|
||||
{
|
||||
LtsWidgets::ComboboxFilterContent cfc;
|
||||
cfc.data.reserve(usedXYCont.size());
|
||||
LtsWidgets::ComboboxFilterData cfd;
|
||||
|
||||
for (int value : usedXYCont)
|
||||
{
|
||||
cfd.data = value;
|
||||
cfd.text = value ? tr("Yes") : tr("No");
|
||||
cfd.icon = value ? m_yes : m_no;
|
||||
cfc.data.push_back(cfd);
|
||||
}
|
||||
cfc.sortItems = true;
|
||||
return cfc.toVariant();
|
||||
};
|
||||
|
||||
// a few Set<int> ==>
|
||||
const auto processInt = [](const QSet<int> &usedXYCont) -> QVariant
|
||||
{
|
||||
LtsWidgets::ComboboxFilterContent cfc;
|
||||
cfc.data.reserve(usedXYCont.size());
|
||||
LtsWidgets::ComboboxFilterData cfd;
|
||||
|
||||
for (int value : usedXYCont)
|
||||
{
|
||||
cfd.data = value;
|
||||
cfd.text = QString::number(value);
|
||||
cfc.data.push_back(cfd);
|
||||
}
|
||||
cfc.sortItems = true;
|
||||
return cfc.toVariant();
|
||||
};
|
||||
|
||||
if (section == IsActive)
|
||||
return processBoolean(m_usedIsActive);
|
||||
|
||||
else if (section == AreaId)
|
||||
return processInt(m_usedAreaIds);
|
||||
else if (section == AreaName)
|
||||
return processString(m_usedAreas);
|
||||
|
||||
else if (section == TargetId)
|
||||
return processInt(m_usedTargetIds);
|
||||
else if (section == TargetName)
|
||||
return processString(m_usedTargets);
|
||||
|
||||
else if (section == TargetPartipantId)
|
||||
return processInt(m_usedTargetParticipantIds);
|
||||
else if (section == TargetPartipantEquipmentNumber)
|
||||
return processInt(m_usedParticipantEqNo);
|
||||
else if (section == Participant)
|
||||
return processString(m_usedParticipants);
|
||||
}
|
||||
return BaseClass::headerData(section, orientation, role);
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
QVariant handleIsDefault(const TargetManagement::TargetAreaAssignment &assignment, const T &value)
|
||||
{
|
||||
if (isDefault(assignment.configuration()))
|
||||
return QStringLiteral("-");
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
QVariant AssignmentParticipantModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
INFO_LOG(m_logger) << LOGFUNCTION << " role=" << role
|
||||
<< " index = " << index.column();
|
||||
|
||||
if (!indexIsValid(index))
|
||||
return QVariant();
|
||||
if (role != Qt::DisplayRole &&
|
||||
role != Qt::EditRole &&
|
||||
role != Qt::CheckStateRole &&
|
||||
role != Qt::DecorationRole &&
|
||||
role != Qt::ForegroundRole &&
|
||||
role != Qt::BackgroundRole &&
|
||||
role != Qt::ToolTipRole &&
|
||||
role != LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole)
|
||||
return QVariant();
|
||||
|
||||
const TargetManagement::TargetAreaAssignment &assignment = m_vecData.at(index.row());
|
||||
|
||||
if (role == Qt::CheckStateRole)
|
||||
{
|
||||
// CheckBoxes only for columns that are actually checkable
|
||||
if (!flags(index).testFlag(Qt::ItemIsUserCheckable))
|
||||
return QVariant();
|
||||
return assignment.isActive() ? Qt::Checked : Qt::Unchecked;
|
||||
}
|
||||
else if (role == Qt::DecorationRole)
|
||||
{
|
||||
if (index.column() == Participant)
|
||||
{
|
||||
static const int pmSize = QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize);
|
||||
const QPixmap &pm = m_participantHandler->getParticipantDecoration(assignment.targetParticipantId());
|
||||
if (!pm.isNull())
|
||||
return pm.scaled(pmSize, pmSize);
|
||||
}
|
||||
else if ((index.column() == Flash_1))
|
||||
return assignment.configuration().flash1() ? m_yes : m_no;
|
||||
else if ((index.column() == Flash_2))
|
||||
return assignment.configuration().flash2() ? m_yes : m_no;
|
||||
return QVariant();
|
||||
}
|
||||
else if (role == Qt::BackgroundRole)
|
||||
{
|
||||
if ((index.column() == TargetId) || (index.column() == TargetName))
|
||||
{
|
||||
int targetId = m_participantHandler->getParticipantIdToTargetId(assignment.targetParticipantId());
|
||||
if (targetId <= 0)
|
||||
return getNoParticipantColor(); // orange
|
||||
}
|
||||
|
||||
else if ((index.column() == AreaId) || (index.column() == AreaName))
|
||||
{
|
||||
if (m_tgt_dtc->shootbackArea(assignment.areaId()).id()<=0)
|
||||
return getNoParticipantColor(); // orange
|
||||
}
|
||||
|
||||
|
||||
else if ((index.column() == TargetPartipantId) && (assignment.targetParticipantId() <= 0))
|
||||
return getNoParticipantColor(); // orange
|
||||
else if (index.column() == TargetPartipantEquipmentNumber)
|
||||
{
|
||||
const int eqNo = m_participantHandler->getParticipantIdToEquipmentNumber(assignment.targetParticipantId());
|
||||
if (eqNo <= 0)
|
||||
return getNoParticipantColor(); // orange
|
||||
}
|
||||
// no else here
|
||||
if (assignment.isActive() && isDefault(assignment.configuration()))
|
||||
return getAssignedButNoConfigurationColor(); // lightRed
|
||||
}
|
||||
else if (role == Qt::ForegroundRole)
|
||||
{
|
||||
if (!assignment.isActive() && (index.column() != Participant))
|
||||
return QColor(Qt::gray);
|
||||
}
|
||||
else if (role == Qt::ToolTipRole)
|
||||
{
|
||||
if (index.column() == Participant)
|
||||
{
|
||||
QString tooltip(QStringLiteral("<html>"));
|
||||
|
||||
const QPixmap &img = m_participantHandler->getParticipantDecoration(assignment.targetParticipantId());
|
||||
if (!img.isNull())
|
||||
{
|
||||
// without a temporary file:
|
||||
QByteArray data;
|
||||
QBuffer buffer(&data);
|
||||
img.save(&buffer, "PNG", 100);
|
||||
tooltip.append(QStringLiteral("<center><img src='data:image/png;base64,%1'></center>").arg(QString::fromLatin1(data.toBase64())));
|
||||
|
||||
QString hdr = this->headerData(AssignmentName, Qt::Horizontal, Qt::DisplayRole).toString();
|
||||
tooltip.append(QStringLiteral("<p>%1: %2</p>").arg(hdr, QString::fromStdString(assignment.name())));
|
||||
|
||||
hdr = this->headerData(Participant, Qt::Horizontal, Qt::DisplayRole).toString();
|
||||
const QString &val = m_participantHandler->getParticipantHierarchie(assignment.targetParticipantId());
|
||||
tooltip.append(QStringLiteral("<p>%1: %2</p>").arg(hdr, val));
|
||||
|
||||
tooltip.append(QStringLiteral("</html>"));
|
||||
return tooltip;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (role == LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole)
|
||||
{
|
||||
// following static_cast<int> are important!!!
|
||||
if (index.column() == IsActive)
|
||||
return static_cast<int>(assignment.isActive());
|
||||
if (index.column() == AreaId)
|
||||
return assignment.areaId();
|
||||
if (index.column() == TargetPartipantId)
|
||||
return assignment.targetParticipantId();
|
||||
}
|
||||
|
||||
switch (index.column())
|
||||
{
|
||||
case Id:
|
||||
return assignment.id();
|
||||
|
||||
case AssignmentName:
|
||||
return QString::fromStdString(assignment.name());
|
||||
case IsActive:
|
||||
return assignment.isActive() ? tr("Yes") : tr("No");
|
||||
|
||||
case TargetId:
|
||||
{
|
||||
int targetId = m_participantHandler->getParticipantIdToTargetId(assignment.targetParticipantId());
|
||||
return targetId;
|
||||
}
|
||||
|
||||
case TargetName:
|
||||
{
|
||||
int targetId = m_participantHandler->getParticipantIdToTargetId(assignment.targetParticipantId());
|
||||
if (targetId <= 0)
|
||||
return QStringLiteral("-");
|
||||
const ShootbackTarget &st = m_tgt_dtc->shootbackTarget(targetId);
|
||||
if (st.id() != targetId)
|
||||
return QStringLiteral("-");
|
||||
return QString::fromStdString(st.name());
|
||||
}
|
||||
|
||||
// associated participant:
|
||||
case TargetPartipantId:
|
||||
return assignment.targetParticipantId();
|
||||
case TargetPartipantEquipmentNumber:
|
||||
{
|
||||
const int eqNo = m_participantHandler->getParticipantIdToEquipmentNumber(assignment.targetParticipantId());
|
||||
if (eqNo <= 0)
|
||||
return QStringLiteral("-");
|
||||
return eqNo;
|
||||
}
|
||||
|
||||
case Participant:
|
||||
return m_participantHandler->getParticipantHierarchie(assignment.targetParticipantId());
|
||||
|
||||
// associated area:
|
||||
case AreaId:
|
||||
return assignment.areaId();
|
||||
case AreaName:
|
||||
return QString::fromStdString(m_tgt_dtc->shootbackArea(assignment.areaId()).name());
|
||||
|
||||
// configuration:
|
||||
case Interval_1:
|
||||
return handleIsDefault(assignment, assignment.configuration().interval1());
|
||||
case Flash_1:
|
||||
return handleIsDefault(assignment, assignment.configuration().flash1());
|
||||
case Effect_1:
|
||||
return handleIsDefault(assignment, effectToString(assignment.configuration().effect1()));
|
||||
case Interval_2:
|
||||
return handleIsDefault(assignment, assignment.configuration().interval2());
|
||||
case Flash_2:
|
||||
return handleIsDefault(assignment, assignment.configuration().flash2());
|
||||
case Effect_2:
|
||||
return handleIsDefault(assignment, effectToString(assignment.configuration().effect2()));
|
||||
|
||||
} // switch
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool AssignmentParticipantModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
if (!indexIsValid(index))
|
||||
return false;
|
||||
|
||||
if (role != Qt::CheckStateRole)
|
||||
return false;
|
||||
|
||||
if (!value.canConvert<bool>())
|
||||
return false;
|
||||
|
||||
bool bVal = value.toBool();
|
||||
|
||||
TargetAreaAssignment &data = m_vecData[index.row()];
|
||||
if (data.isActive() != bVal)
|
||||
{
|
||||
data.isActive(bVal);
|
||||
emit dataChanged(index, index);
|
||||
emit signalEditableItemChanged();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Qt::ItemFlags AssignmentParticipantModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
auto f = QAbstractTableModel::flags(index);
|
||||
if (!index.isValid() || index.row() >= m_vecData.size())
|
||||
return f;
|
||||
if (index.column() == Columns::IsActive)
|
||||
{
|
||||
f.setFlag(Qt::ItemIsUserCheckable);
|
||||
return f;
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
QSet<int> AssignmentParticipantModel::getAssociatedParticipantIds() const
|
||||
{
|
||||
QSet<int> ret;
|
||||
ret.reserve(m_vecData.size());
|
||||
for (const TargetManagement::TargetAreaAssignment &data : m_vecData)
|
||||
ret += data.targetParticipantId();
|
||||
return ret;
|
||||
}
|
||||
|
||||
QSet<int> AssignmentParticipantModel::getAssociatedParticipantIdsForArea(int areaId) const
|
||||
{
|
||||
QSet<int> ret;
|
||||
ret.reserve(m_vecData.size());
|
||||
for (const TargetManagement::TargetAreaAssignment &data : m_vecData)
|
||||
if (data.areaId() == areaId)
|
||||
ret += data.targetParticipantId();
|
||||
return ret;
|
||||
}
|
||||
|
||||
QSet<int> AssignmentParticipantModel::getAssociatedAreasIdsForParticipantId(int participantId) const
|
||||
{
|
||||
QSet<int> ret;
|
||||
ret.reserve(m_vecData.size());
|
||||
for (const TargetManagement::TargetAreaAssignment &data : m_vecData)
|
||||
if (data.targetParticipantId() == participantId)
|
||||
ret += data.areaId();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int AssignmentParticipantModel::findRowForAreaTargetParticipantId(int areaId, int targetParticipantId)
|
||||
{
|
||||
for (int i = 0; i < m_vecData.size(); ++i) // clazy:exclude=range-loop
|
||||
{
|
||||
const TargetAreaAssignment &curAssignment = m_vecData.at(i);
|
||||
if ((curAssignment.areaId() == areaId) && (curAssignment.targetParticipantId() == targetParticipantId))
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void AssignmentParticipantModel::addGapFillerForArea(int areaId)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << " START, areaId=" << areaId;
|
||||
|
||||
const QSet<int> &associatedParticipantIds = getAssociatedParticipantIdsForArea(areaId);
|
||||
|
||||
QVector<TargetManagement::TargetAreaAssignment> gapFillers;
|
||||
|
||||
#define USE_PARTICIPANTS_OF_ORBAT
|
||||
#ifdef USE_PARTICIPANTS_OF_ORBAT
|
||||
// participantIds with EquipmentType (WmsTypeClass::TargetVehicle||WmsTypeClass::TargetHuman)
|
||||
QList<int> pIds = getParticipantHierarchies().keys();
|
||||
|
||||
for (auto pId : qAsConst(pIds))
|
||||
{
|
||||
if (!associatedParticipantIds.contains(pId))
|
||||
{
|
||||
TargetManagement::TargetAreaAssignment gapFiller;
|
||||
gapFiller.areaId(areaId);
|
||||
gapFiller.targetParticipantId(pId);
|
||||
gapFiller.isActive(false);
|
||||
gapFillers.push_back(gapFiller);
|
||||
}
|
||||
} // for
|
||||
|
||||
#else // USE_PARTICIPANTS_OF_ORBAT
|
||||
|
||||
// use just the (base)configured targets:
|
||||
auto cb = [associatedParticipantIds, areaId, &gapFillers](const TargetManagement::ShootbackTarget & targets)
|
||||
{
|
||||
if (targets.targetParticipantId() <= 0)
|
||||
return;
|
||||
|
||||
if (!associatedParticipantIds.contains(targets.targetParticipantId()))
|
||||
{
|
||||
TargetManagement::TargetAreaAssignment gapFiller;
|
||||
gapFiller.areaId(areaId);
|
||||
gapFiller.targetParticipantId(targets.targetParticipantId());
|
||||
gapFiller.isActive(false);
|
||||
gapFillers.push_back(gapFiller);
|
||||
}
|
||||
};
|
||||
m_tgt_dtc->shootbackTargets(cb);
|
||||
#endif
|
||||
|
||||
this->insertRows(gapFillers);
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << " END, areaId=" << areaId;
|
||||
}
|
||||
|
||||
void AssignmentParticipantModel::addGapFillerForTargetParticipantId(int targetParticipantId)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << " START, targetParticipantId=" << targetParticipantId;
|
||||
|
||||
const QSet<int> &associatedAreaIds = getAssociatedAreasIdsForParticipantId(targetParticipantId);
|
||||
|
||||
QVector<TargetManagement::TargetAreaAssignment> gapFillers;
|
||||
// gapFillers.reserve(1000);
|
||||
|
||||
auto cb = [associatedAreaIds, targetParticipantId, &gapFillers](const TargetManagement::ShootbackArea & area)
|
||||
{
|
||||
if (!associatedAreaIds.contains(area.id()))
|
||||
{
|
||||
TargetManagement::TargetAreaAssignment gapFiller;
|
||||
gapFiller.areaId(area.id());
|
||||
gapFiller.targetParticipantId(targetParticipantId);
|
||||
gapFiller.isActive(false);
|
||||
gapFillers.push_back(gapFiller);
|
||||
}
|
||||
};
|
||||
m_tgt_dtc->shootbackAreas(cb);
|
||||
|
||||
this->insertRows(gapFillers);
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << " END, targetParticipantId=" << targetParticipantId;
|
||||
}
|
||||
|
||||
void AssignmentParticipantModel::onTargetAreaAssignmentChanged(const TargetManagement::TargetAreaAssignment &data,
|
||||
DataModification modType)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << " modType=" << modType << " data=" << data;
|
||||
|
||||
// avoid adding an assignment which already exists:
|
||||
if (modType == DataModification::eAdded)
|
||||
{
|
||||
int row = findRowForAreaTargetParticipantId(data.areaId(), data.targetParticipantId());
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << " row=" << row;
|
||||
if (row >= 0)
|
||||
{
|
||||
setRowData(row, data);
|
||||
emit signalParticipantNamesChanged();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
BaseClass::onDataChanged(data, modType);
|
||||
|
||||
emit signalParticipantNamesChanged();
|
||||
}
|
||||
|
||||
void AssignmentParticipantModel::updateColumnFilter()
|
||||
{
|
||||
m_usedIsActive.clear();
|
||||
|
||||
m_usedAreaIds.clear();
|
||||
m_usedAreas.clear();
|
||||
|
||||
m_usedTargetIds.clear();
|
||||
m_usedTargets.clear();
|
||||
|
||||
m_usedTargetParticipantIds.clear();
|
||||
m_usedParticipantEqNo.clear();
|
||||
m_usedParticipants.clear();
|
||||
|
||||
int row = -1;
|
||||
for (const TargetAreaAssignment &assignment : qAsConst(m_vecData))
|
||||
{
|
||||
++row;
|
||||
// This loops over ALL item, even if some of them are filtered by the AssignmentParticipantProxyModel (areaId, ..)
|
||||
m_usedIsActive.insert(assignment.isActive());
|
||||
|
||||
m_usedAreaIds.insert(assignment.areaId());
|
||||
m_usedAreas.insert( QString::fromStdString(m_tgt_dtc->shootbackArea(assignment.areaId()).name()) );
|
||||
|
||||
int targetId = m_participantHandler->getParticipantIdToTargetId(assignment.targetParticipantId());
|
||||
m_usedTargetIds.insert(targetId);
|
||||
m_usedTargets.insert(this->data(index(row, TargetName), Qt::DisplayRole).toString());
|
||||
|
||||
m_usedTargetParticipantIds.insert(assignment.targetParticipantId());
|
||||
const int eqNo = m_participantHandler->getParticipantIdToEquipmentNumber(assignment.targetParticipantId());
|
||||
m_usedParticipantEqNo.insert(eqNo);
|
||||
m_usedParticipants.insert(m_participantHandler->getParticipantHierarchie(assignment.targetParticipantId()));
|
||||
}
|
||||
}
|
||||
|
||||
QString AssignmentParticipantModel::effectToString(const Effect &effect) const
|
||||
{
|
||||
switch (effect.underlying())
|
||||
{
|
||||
case TargetManagement::Effect_def::NearMiss:
|
||||
return tr("NearMiss");
|
||||
case TargetManagement::Effect_def::MobilityKill:
|
||||
return tr("MobilityKill");
|
||||
case TargetManagement::Effect_def::WeaponKill:
|
||||
return tr("WeaponKill");
|
||||
default:
|
||||
{
|
||||
// empty
|
||||
}
|
||||
}
|
||||
return QStringLiteral("-");
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------
|
||||
// AssignmentParticipantProxyModel
|
||||
// --------------------------------------------------------
|
||||
void AssignmentParticipantProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
|
||||
{
|
||||
m_sourceModel = qobject_cast<AssignmentParticipantModel *>(sourceModel);
|
||||
BaseClass::setSourceModel(sourceModel);
|
||||
}
|
||||
|
||||
void AssignmentParticipantProxyModel::filterToAreaId(int areaId)
|
||||
{
|
||||
m_areaId = areaId;
|
||||
m_targetParticipantId = -1;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
void AssignmentParticipantProxyModel::filterToTargetParticpantId(int targetParticpantId)
|
||||
{
|
||||
m_targetParticipantId = targetParticpantId;
|
||||
m_areaId = -1;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
bool AssignmentParticipantProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
|
||||
{
|
||||
if (!m_sourceModel)
|
||||
return BaseClass::filterAcceptsRow(source_row, source_parent);
|
||||
|
||||
if (m_areaId > 0)
|
||||
{
|
||||
const TargetManagement::TargetAreaAssignment &item = m_sourceModel->m_vecData.at(source_row);
|
||||
return (item.areaId() == m_areaId) && BaseClass::filterAcceptsRow(source_row, source_parent);
|
||||
}
|
||||
else if ((m_targetParticipantId > 0))
|
||||
{
|
||||
const TargetManagement::TargetAreaAssignment &item = m_sourceModel->m_vecData.at(source_row);
|
||||
return (item.targetParticipantId() == m_targetParticipantId) && BaseClass::filterAcceptsRow(source_row, source_parent);;
|
||||
}
|
||||
return BaseClass::filterAcceptsRow(source_row, source_parent);
|
||||
}
|
||||
|
||||
bool AssignmentParticipantProxyModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
|
||||
{
|
||||
if (!m_sourceModel || !m_sourceModel->m_participantHandler ||
|
||||
source_left.column() != source_right.column() ||
|
||||
source_left.row() < 0 || source_left.row() >= m_sourceModel->m_vecData.size() ||
|
||||
source_right.row() < 0 || source_right.row() >= m_sourceModel->m_vecData.size()
|
||||
)
|
||||
return BaseClass::lessThan(source_left, source_right);
|
||||
|
||||
|
||||
const TargetManagement::TargetAreaAssignment &left = m_sourceModel->m_vecData.at(source_left.row());
|
||||
const TargetManagement::TargetAreaAssignment &right = m_sourceModel->m_vecData.at(source_right.row());
|
||||
switch (source_left.column())
|
||||
{
|
||||
case AssignmentParticipantModel::Columns::Id:
|
||||
return left.id() < right.id();
|
||||
case AssignmentParticipantModel::Columns::AssignmentName:
|
||||
return left.name() < right.name();
|
||||
case AssignmentParticipantModel::Columns::TargetPartipantId:
|
||||
return left.targetParticipantId() < right.targetParticipantId();
|
||||
case AssignmentParticipantModel::Columns::TargetPartipantEquipmentNumber:
|
||||
{
|
||||
const int eqNoLeft = m_sourceModel->m_participantHandler->getParticipantIdToEquipmentNumber(left.targetParticipantId());
|
||||
const int eqNoRight = m_sourceModel->m_participantHandler->getParticipantIdToEquipmentNumber(right.targetParticipantId());
|
||||
return eqNoLeft < eqNoRight;
|
||||
}
|
||||
case AssignmentParticipantModel::Columns::AreaId:
|
||||
return left.areaId() < right.areaId();
|
||||
|
||||
case AssignmentParticipantModel::Columns::Participant:
|
||||
case AssignmentParticipantModel::Columns::AreaName:
|
||||
// QString compare
|
||||
return LtsUtils::lessThan(source_left.data(), source_right.data());
|
||||
}
|
||||
return BaseClass::lessThan(source_left, source_right);
|
||||
}
|
||||
|
||||
|
||||
} // namespace TargetManagement
|
||||
Executable
+160
@@ -0,0 +1,160 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* AssignmentParticipantModel
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Norbert Thoden, NLE, 2020-06-29
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "tgt_participant_handler.h"
|
||||
#include <TargetManagement/tgt_dtc.h>
|
||||
#include <TargetManagement/logger.h>
|
||||
|
||||
#include <LtsWidgets/lts_abstract_table_model.h>
|
||||
#include <LtsWidgets/lts_column_filter_proxy_model.h>
|
||||
#include <LtsSession/lts_session.h>
|
||||
|
||||
namespace TargetManagement
|
||||
{
|
||||
|
||||
// Forward:
|
||||
class ParticipantHandler;
|
||||
|
||||
bool isEqual(const ShootbackConfiguration &c1, const ShootbackConfiguration &c2);
|
||||
bool isDefault(const ShootbackConfiguration &c);
|
||||
bool isEqual(const TargetAreaAssignment &a1, const TargetAreaAssignment &a2, bool ignoringAreaIdAndParticipantId = false);
|
||||
|
||||
// --------------------------------------------------------
|
||||
// AssignmentParticipantModel
|
||||
// --------------------------------------------------------
|
||||
class AssignmentParticipantModel final : public LtsWidgets::LtsAbstractTableModel<TargetManagement::TargetAreaAssignment>
|
||||
{
|
||||
Q_OBJECT
|
||||
using BaseClass = LtsWidgets::LtsAbstractTableModel<TargetManagement::TargetAreaAssignment>;
|
||||
|
||||
public:
|
||||
enum Columns
|
||||
{
|
||||
Id,
|
||||
AssignmentName,
|
||||
IsActive,
|
||||
|
||||
// associated target:
|
||||
TargetId,
|
||||
TargetName,
|
||||
// (associated participant):
|
||||
TargetPartipantId,
|
||||
TargetPartipantEquipmentNumber,
|
||||
Participant,
|
||||
|
||||
// associated area
|
||||
AreaId,
|
||||
AreaName,
|
||||
|
||||
// configuration
|
||||
Interval_1,
|
||||
Flash_1,
|
||||
Effect_1,
|
||||
Interval_2,
|
||||
Flash_2,
|
||||
Effect_2
|
||||
|
||||
};
|
||||
|
||||
explicit AssignmentParticipantModel(QObject *parent = nullptr);
|
||||
|
||||
bool initModel(const std::shared_ptr<Interface::Dtc> &tgtDtc,
|
||||
const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc,
|
||||
const std::shared_ptr<ParticipantManagement::ForeignGuiComboboxInterface> &ppmGuiCbxIfc,
|
||||
LtsSession::LtsSession *session);
|
||||
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const override final;
|
||||
QVariant data(const QModelIndex &, int) const override;
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
|
||||
const QHash <int, QString> &getParticipantHierarchies() const { return m_participantHandler->getParticipantHierarchies(); }
|
||||
const QHash <int, QPixmap> &getParticipantDecorations() const { return m_participantHandler->getParticipantDecorations(); }
|
||||
QSet<int> getAssociatedParticipantIds() const;
|
||||
QSet<int> getAssociatedParticipantIdsForArea(int areaId) const;
|
||||
QSet<int> getAssociatedAreasIdsForParticipantId(int participantId) const;
|
||||
|
||||
int findRowForAreaTargetParticipantId(int areaId, int targetParticipantId);
|
||||
|
||||
const QVector<TargetAreaAssignment> &getData() const { return m_vecData; }
|
||||
|
||||
void addGapFillerForArea(int areaId);
|
||||
void addGapFillerForTargetParticipantId(int targetParticipantId);
|
||||
|
||||
Q_SIGNALS:
|
||||
void signalParticipantNamesChanged();
|
||||
void signalEditableItemChanged();
|
||||
|
||||
private Q_SLOTS:
|
||||
void onTargetAreaAssignmentChanged(const TargetManagement::TargetAreaAssignment &data,
|
||||
DataModification modType);
|
||||
void updateColumnFilter();
|
||||
|
||||
private:
|
||||
QString effectToString(const TargetManagement::Effect &effect) const;
|
||||
|
||||
friend class AssignmentParticipantProxyModel;
|
||||
std::shared_ptr<TargetManagement::Interface::Dtc> m_tgt_dtc;
|
||||
ParticipantHandler *m_participantHandler{nullptr};
|
||||
LtsSession::LtsSession *m_session{nullptr};
|
||||
|
||||
QIcon m_yes{QLatin1String("icon:yes.svg")};
|
||||
QIcon m_no{QLatin1String("icon:no.svg")};
|
||||
|
||||
// column filter
|
||||
QSet<int> m_usedIsActive; // Assigned
|
||||
QSet<int> m_usedAreaIds;
|
||||
QSet<QString> m_usedAreas;
|
||||
|
||||
QSet<int> m_usedTargetIds;
|
||||
QSet<QString> m_usedTargets;
|
||||
|
||||
QSet<int> m_usedTargetParticipantIds;
|
||||
QSet<int> m_usedParticipantEqNo;
|
||||
QSet<QString> m_usedParticipants;
|
||||
// continue with all configuration data???
|
||||
|
||||
|
||||
LOGGER_T m_logger;
|
||||
};
|
||||
|
||||
|
||||
|
||||
// --------------------------------------------------------
|
||||
// AssignmentParticipantProxyModel
|
||||
// --------------------------------------------------------
|
||||
class AssignmentParticipantProxyModel : public LtsWidgets::LtsColumnFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
using BaseClass = LtsWidgets::LtsColumnFilterProxyModel;
|
||||
|
||||
public:
|
||||
using LtsWidgets::LtsColumnFilterProxyModel::LtsColumnFilterProxyModel;
|
||||
void setSourceModel(QAbstractItemModel *sourceModel) override;
|
||||
|
||||
int getFilterToAreaId() const { return m_areaId; }
|
||||
void filterToAreaId(int areaId = -1);
|
||||
int getFilterToTargetParticpantId() const { return m_targetParticipantId; }
|
||||
void filterToTargetParticpantId(int targetParticpantId = -1);
|
||||
|
||||
protected:
|
||||
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override final;
|
||||
bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override;
|
||||
|
||||
protected:
|
||||
AssignmentParticipantModel *m_sourceModel{nullptr};
|
||||
|
||||
int m_areaId{-1};
|
||||
int m_targetParticipantId{-1};
|
||||
};
|
||||
|
||||
|
||||
} //namespace TargetManagement
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Target Configuration
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Norbert Thoden, NLE, 2020-07-ß8
|
||||
*/
|
||||
|
||||
#include "tgt_common.h"
|
||||
|
||||
#include <QColor>
|
||||
|
||||
|
||||
namespace TargetManagement
|
||||
{
|
||||
|
||||
QColor getWarningBackgroundRole() { return QColor(240, 94, 35); } // QColor(240, 94, 35) -> orange
|
||||
|
||||
QColor getNoParticipantColor() { return QColor(240, 94, 35); } // QColor(240, 94, 35) -> orange
|
||||
|
||||
QColor getAssignedButNoConfigurationColor() { return QColor(255, 127, 127); } // QColor(255, 127, 127); -> lightRed
|
||||
|
||||
} // namespace TargetManagement
|
||||
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Target Configuration
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Norbert Thoden, NLE, 2020-07-ß8
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// forward:
|
||||
class QColor;
|
||||
|
||||
namespace TargetManagement
|
||||
{
|
||||
|
||||
// missing configuration
|
||||
QColor getWarningBackgroundRole();
|
||||
|
||||
// no participant -> orange
|
||||
QColor getNoParticipantColor();
|
||||
|
||||
// assigned, but no behaviour configuration -> lightRed
|
||||
QColor getAssignedButNoConfigurationColor();
|
||||
|
||||
|
||||
|
||||
} // namespace TargetManagement
|
||||
Executable
+240
@@ -0,0 +1,240 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Handler for ParticipantData
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Norbert Thoden, NLE, 2020-06-29
|
||||
*/
|
||||
|
||||
#include "tgt_participant_handler.h"
|
||||
#include <ParticipantManagement/ppm_translation.h>
|
||||
|
||||
#include <SituationMap/Symbology/symbol_result.h>
|
||||
#include <SituationMap/Symbology/symbol_dictionary.h>
|
||||
|
||||
#include <QApplication> // pixelMetric
|
||||
|
||||
namespace TargetManagement
|
||||
{
|
||||
|
||||
//---------------------------------
|
||||
// ParticipantHandler
|
||||
//---------------------------------
|
||||
ParticipantHandler::ParticipantHandler(QObject *parent)
|
||||
: BaseClass(parent)
|
||||
, m_logger(getLogger("ParticipantHandler"))
|
||||
{}
|
||||
|
||||
|
||||
bool ParticipantHandler::init(const std::shared_ptr<Interface::Dtc> &tgt_dtc,
|
||||
const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc,
|
||||
const std::shared_ptr<ParticipantManagement::ForeignGuiComboboxInterface> &ppmGuiCbxIfc)
|
||||
{
|
||||
m_tgt_dtc = tgt_dtc;
|
||||
m_ppm_dtc = ppmDtc;
|
||||
m_ppmGuiCbxIfc = ppmGuiCbxIfc;
|
||||
|
||||
// init
|
||||
if (m_tgt_dtc)
|
||||
{
|
||||
connect(m_tgt_dtc.get(), &TargetManagement::Interface::Dtc::shootbackTargetChanged,
|
||||
this, &ParticipantHandler::onShootbackTargetChanged);
|
||||
|
||||
auto cb = [this](const TargetManagement::ShootbackTarget & d) { onShootbackTargetChanged(d, DataModification::eAdded); };
|
||||
m_tgt_dtc->shootbackTargets(cb);
|
||||
}
|
||||
|
||||
if (m_ppm_dtc)
|
||||
{
|
||||
{
|
||||
connect(m_ppm_dtc.get(), &ParticipantManagement::Interface::Dtc::typeChanged,
|
||||
this, &ParticipantHandler::onTypeChanged);
|
||||
|
||||
auto cb = [this](const ParticipantManagement::Type & d) { onTypeChanged(d, DataModification::eAdded); };
|
||||
m_ppm_dtc->types(cb);
|
||||
}
|
||||
{
|
||||
connect(m_ppm_dtc.get(), &ParticipantManagement::Interface::Dtc::participantChanged,
|
||||
this, &ParticipantHandler::onParticipantChanged);
|
||||
auto cb = [this](const ParticipantManagement::Participant & d) { onParticipantChanged(d, DataModification::eAdded); };
|
||||
m_ppm_dtc->participants(cb);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int ParticipantHandler::getParticipantIdToTargetId(int participantId) const
|
||||
{
|
||||
return m_participantIdToTargetId.value(participantId, -1);
|
||||
}
|
||||
|
||||
QString ParticipantHandler::getParticipantHierarchie(int participantId) const
|
||||
{
|
||||
return m_participantHierarchies.value(participantId, tr("No participant name available"));
|
||||
}
|
||||
|
||||
QString ParticipantHandler::target_wmsTypeClassToString(const ParticipantManagement::WmsTypeClass &wmsTypeClass)
|
||||
{
|
||||
switch (wmsTypeClass.underlying())
|
||||
{
|
||||
case ParticipantManagement::WmsTypeClass_def::TargetHuman:
|
||||
return QStringLiteral("Human");
|
||||
case ParticipantManagement::WmsTypeClass_def::TargetVehicle:
|
||||
return QStringLiteral("Vehicle");
|
||||
break;
|
||||
default:
|
||||
{
|
||||
// empty
|
||||
}
|
||||
} //switch
|
||||
return QStringLiteral("-");
|
||||
}
|
||||
|
||||
void ParticipantHandler::onShootbackTargetChanged(const TargetManagement::ShootbackTarget &data, const DataModification modType)
|
||||
{
|
||||
INFO_LOG(m_logger) << "onShootbackTargetChanged: " << data << ", " << modType;
|
||||
|
||||
switch (modType)
|
||||
{
|
||||
case DataModification::eRemoved:
|
||||
m_participantIdToTargetId.remove(data.targetParticipantId());
|
||||
break;
|
||||
case DataModification::eModified:
|
||||
case DataModification::eAdded:
|
||||
m_participantIdToTargetId.insert(data.targetParticipantId(), data.id());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ParticipantHandler::onTypeChanged(const ParticipantManagement::Type &data,
|
||||
const DataModification modType)
|
||||
{
|
||||
INFO_LOG(m_logger) << "onTypeChanged:" << data << ", " << modType;
|
||||
|
||||
switch (modType)
|
||||
{
|
||||
case DataModification::eRemoved:
|
||||
m_typeToTypeClass.remove(data.id());
|
||||
break;
|
||||
case DataModification::eModified:
|
||||
case DataModification::eAdded:
|
||||
m_typeToTypeClass.insert(data.id(), data.typeClass());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ParticipantHandler::onParticipantChanged(const ParticipantManagement::Participant &data,
|
||||
DataModification modType)
|
||||
{
|
||||
TRACE_LOG(m_logger) << "onParticipantChanged: " << data << ", " << modType;
|
||||
|
||||
if (data.isDeleted())
|
||||
modType = DataModification::eRemoved;
|
||||
|
||||
const int dataId = data.id();
|
||||
switch (modType)
|
||||
{
|
||||
case DataModification::eRemoved:
|
||||
m_participantHierarchies.remove(dataId);
|
||||
m_participantIdToEq.remove(dataId);
|
||||
m_participantIdToWmsTypeClass.remove(dataId);
|
||||
break;
|
||||
case DataModification::eModified:
|
||||
case DataModification::eAdded:
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "DataModification::eAdded Participant"
|
||||
<< " Id=" << dataId
|
||||
<< " TypeId=" << data.typeId()
|
||||
<< " eqId=" << (data.equipmentNumber().is_set() ? data.equipmentNumber().get() : -1)
|
||||
<< " " << data.name();
|
||||
|
||||
const int typeId = data.typeId();
|
||||
const ParticipantManagement::Type &type = m_ppm_dtc->type(typeId);
|
||||
if (type.id() != typeId)
|
||||
return;
|
||||
const int equipmentTypeId = type.equipmentTypeId();
|
||||
const ParticipantManagement::EquipmentType &eqType = m_ppm_dtc->equipmentType(equipmentTypeId);
|
||||
if (eqType.id() != equipmentTypeId)
|
||||
return;
|
||||
|
||||
m_participantIdToWmsTypeClass.insert(dataId, eqType.wmsTypeClass());
|
||||
bool bIsTarget{false};
|
||||
switch (eqType.wmsTypeClass().underlying())
|
||||
{
|
||||
case ParticipantManagement::WmsTypeClass::None:
|
||||
case ParticipantManagement::WmsTypeClass::Building:
|
||||
case ParticipantManagement::WmsTypeClass::Vehicle:
|
||||
case ParticipantManagement::WmsTypeClass::Human:
|
||||
case ParticipantManagement::WmsTypeClass::Airborne:
|
||||
case ParticipantManagement::WmsTypeClass::VehicleMarker:
|
||||
bIsTarget = false;
|
||||
break;
|
||||
case ParticipantManagement::WmsTypeClass::TargetVehicle:
|
||||
case ParticipantManagement::WmsTypeClass::TargetHuman:
|
||||
bIsTarget = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
} // switch
|
||||
|
||||
if (!bIsTarget)
|
||||
return;
|
||||
|
||||
// m_participantIdToEq :
|
||||
int eqId = -1;
|
||||
if (data.equipmentNumber().is_set())
|
||||
eqId = data.equipmentNumber().get();
|
||||
if (eqId >= 0)
|
||||
m_participantIdToEq[dataId] = eqId;
|
||||
else
|
||||
m_participantIdToEq.remove(dataId);
|
||||
// : m_participantIdToEq
|
||||
|
||||
// hierarchy...
|
||||
const QString hierarchy = m_ppm_dtc->hierarchyFromParticipant(dataId);
|
||||
if (data.equipmentNumber().is_set())
|
||||
m_participantHierarchies.insert(dataId, hierarchy + QString(QStringLiteral(" (%1)")).arg(data.equipmentNumber().get()));
|
||||
else
|
||||
m_participantHierarchies.insert(dataId, hierarchy);
|
||||
if (m_ppmGuiCbxIfc)
|
||||
{
|
||||
// afterwards, render sidc:
|
||||
AdvancedSymbology::SymbolDictionary &dictionary =
|
||||
AdvancedSymbology::SymbolDictionary::dictionary(AdvancedSymbology::SymbologyType::APP6D);
|
||||
|
||||
if (!m_participantDecorations.contains(dataId))
|
||||
{
|
||||
// for very first view, use simple squares of partyColor:
|
||||
const auto party = m_ppm_dtc->party(data.partyId());
|
||||
const QRgb col = QRgb(party.color());
|
||||
m_participantDecorations.insert(dataId, m_ppmGuiCbxIfc->pixmapFromParty(col));
|
||||
|
||||
AdvancedSymbology::SymbolDataToRender symDataToRender(QString::fromStdString(data.symbol()));
|
||||
symDataToRender.fillColor = m_ppm_dtc->party(data.partyId()).color();
|
||||
symDataToRender.fillColorReplace = true;
|
||||
|
||||
AdvancedSymbology::SymbolResultWatcher *srw =
|
||||
new AdvancedSymbology::SymbolResultWatcher(this);
|
||||
connect(srw, &AdvancedSymbology::SymbolResultWatcher::resultReady, this, [this, dataId, srw]()
|
||||
{
|
||||
if (srw->symbolResult())
|
||||
{
|
||||
m_participantDecorations[dataId] = QPixmap::fromImage(srw->symbolResult()->symbolImage().image());
|
||||
emit signalParticipantChanged(dataId);
|
||||
// update();
|
||||
}
|
||||
});
|
||||
srw->setSymbolResult(dictionary.fetchSymbol(symDataToRender));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
emit signalParticipantNamesChanged();
|
||||
emit signalParticipantChanged(dataId);
|
||||
// emit dataChanged(index(0, rowCount() -1), index(0, columnCount() - 1));
|
||||
}
|
||||
|
||||
} // namespace TargetManagement
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Handler for ParticipantData
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Norbert Thoden, NLE, 2020-06-29
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <TargetManagement/logger.h>
|
||||
|
||||
// Get targets
|
||||
#include <TargetManagement/tgt_dtc.h>
|
||||
|
||||
// Get Participants
|
||||
#include <ParticipantManagement/ppm_dtc.h>
|
||||
#include <Plugins/ParticipantManagement/ppm_gui_combobox_plugin_interface.h>
|
||||
|
||||
#include <LtsWidgets/lts_abstract_table_model.h>
|
||||
#include <LtsWidgets/lts_column_filter_proxy_model.h>
|
||||
#include <LtsSession/lts_session.h>
|
||||
|
||||
namespace TargetManagement
|
||||
{
|
||||
|
||||
// --------------------------------------------------------
|
||||
// ParticipantHandler
|
||||
// --------------------------------------------------------
|
||||
class ParticipantHandler final : public QObject // public LtsWidgets::LtsAbstractTableModel<class T>
|
||||
{
|
||||
Q_OBJECT
|
||||
// using BaseClass = LtsWidgets::LtsAbstractTableModel<T>;
|
||||
using BaseClass = QObject;
|
||||
|
||||
public:
|
||||
explicit ParticipantHandler(QObject *parent = nullptr);
|
||||
|
||||
bool init(const std::shared_ptr<TargetManagement::Interface::Dtc> &tgt_dtc,
|
||||
const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc,
|
||||
const std::shared_ptr<ParticipantManagement::ForeignGuiComboboxInterface> &ppmGuiCbxIfc);
|
||||
|
||||
int getParticipantIdToTargetId(int participantId) const;
|
||||
|
||||
const QHash <int, QString> &getParticipantHierarchies() const { return m_participantHierarchies; }
|
||||
QString getParticipantHierarchie(int participantId) const;
|
||||
|
||||
const QHash <int, QPixmap> &getParticipantDecorations() const { return m_participantDecorations; }
|
||||
QPixmap getParticipantDecoration(int participantId) const { return m_participantDecorations.value(participantId); }
|
||||
|
||||
QHash <int, int> getParticipantIdToEquipmentNumber() const { return m_participantIdToEq; }
|
||||
int getParticipantIdToEquipmentNumber(int participantId) const { return m_participantIdToEq.value(participantId, -1); }
|
||||
|
||||
ParticipantManagement::WmsTypeClass getParticipantIdToWmsTypeClass(int participantId) const
|
||||
{ return m_participantIdToWmsTypeClass.value(participantId, ParticipantManagement::WmsTypeClass_def::None); }
|
||||
|
||||
static QString target_wmsTypeClassToString(const ParticipantManagement::WmsTypeClass &wmsTypeClass);
|
||||
|
||||
Q_SIGNALS:
|
||||
void signalParticipantNamesChanged();
|
||||
void signalParticipantChanged(int participantId);
|
||||
|
||||
private Q_SLOTS:
|
||||
void onShootbackTargetChanged(const TargetManagement::ShootbackTarget &data,
|
||||
const DataModification modType);
|
||||
void onTypeChanged(const ParticipantManagement::Type &data,
|
||||
const DataModification modType);
|
||||
void onParticipantChanged(const ParticipantManagement::Participant &data,
|
||||
DataModification modType);
|
||||
|
||||
|
||||
private:
|
||||
std::shared_ptr<TargetManagement::Interface::Dtc> m_tgt_dtc;
|
||||
std::shared_ptr<ParticipantManagement::Interface::Dtc> m_ppm_dtc;
|
||||
std::shared_ptr<ParticipantManagement::ForeignGuiComboboxInterface> m_ppmGuiCbxIfc;
|
||||
|
||||
QHash <int, int > m_participantIdToTargetId; // key = (target)participantId, value = id of target
|
||||
QHash <int, QString> m_participantHierarchies; // key = participantId, value = HierarchyString
|
||||
QHash <int, QPixmap> m_participantDecorations;
|
||||
QHash <int, int > m_participantIdToEq; // key = participantId, value = EquipmentNumber
|
||||
QHash <int, ParticipantManagement::TypeClass> m_typeToTypeClass; // key = ParticipantType, value = TypeClass
|
||||
QHash <int, ParticipantManagement::WmsTypeClass> m_participantIdToWmsTypeClass; // key = participantId, value = WmsTypeClass
|
||||
|
||||
QIcon m_yes{QLatin1String("icon:yes.svg")};
|
||||
QIcon m_no{QLatin1String("icon:no.svg")};
|
||||
|
||||
LOGGER_T m_logger;
|
||||
};
|
||||
|
||||
} //namespace TargetManagement
|
||||
Executable
+199
@@ -0,0 +1,199 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* TargetManagement - Target Edit Dialog
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Norbert Thoden, NLE, 2020-05-29
|
||||
*/
|
||||
|
||||
#include "tgt_shootback_target_edit.h"
|
||||
#include "tgt_target_part_model.h"
|
||||
#include "ui_tgt_shootback_target_edit.h"
|
||||
|
||||
#include <LtsUtilsSettings/settings.h>
|
||||
|
||||
#include <QBuffer>
|
||||
|
||||
namespace TargetManagement
|
||||
{
|
||||
|
||||
ShootbackTargetEdit::ShootbackTargetEdit(QWidget *parent)
|
||||
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
|
||||
, m_requestHelper(new LtsUtils::RequestHelper(this))
|
||||
, m_ui(new Ui::ShootbackTargetEdit)
|
||||
, m_logger(getLogger("ShootbackTargetEdit"))
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ShootbackTargetEdit::~ShootbackTargetEdit()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ShootbackTargetEdit::retranslate()
|
||||
{
|
||||
translate(m_ui, m_target, tr("ShootbackTarget"));
|
||||
}
|
||||
|
||||
bool ShootbackTargetEdit::init(const std::shared_ptr<TargetManagement::Interface::Dtc> &dtc,
|
||||
const std::shared_ptr<TargetManagement::Interface::Ftc> &ftc,
|
||||
TargetParticipantModel *targetParticipantModel,
|
||||
const TargetManagement::ShootbackTarget &target)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "ShootbackTargetEdit::init()";
|
||||
|
||||
if (!dtc || !ftc)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "ShootbackTargetEdit::init() Invalid shared_ptr!";
|
||||
return false;
|
||||
}
|
||||
|
||||
m_dtc = dtc;
|
||||
m_ftc = ftc;
|
||||
m_targetParticipantModel = targetParticipantModel;
|
||||
setData(target);
|
||||
|
||||
initCmbParticipants();
|
||||
connect(m_targetParticipantModel, &TargetParticipantModel::signalParticipantNamesChanged,
|
||||
this, &ShootbackTargetEdit::initCmbParticipants);
|
||||
|
||||
setOnlineHelpFilename(QStringLiteral("Situation-Targets"));
|
||||
// if (m_target.id() <= 0)
|
||||
// slotChangesMade();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ShootbackTargetEdit::initCmbParticipants()
|
||||
{
|
||||
m_ui->cmbParticipants->clear();
|
||||
|
||||
if (!m_targetParticipantModel)
|
||||
return;
|
||||
|
||||
QSignalBlocker sb(m_ui->cmbParticipants); // pause tooltip update
|
||||
|
||||
m_ui->cmbParticipants->addItem(QStringLiteral("-"), 0); // to remove association
|
||||
|
||||
const auto hierarchies(m_targetParticipantModel->getParticipantHierarchies());
|
||||
const auto decorations(m_targetParticipantModel->getParticipantDecorations());
|
||||
for (auto it = hierarchies.begin(); it != hierarchies.end(); ++it)
|
||||
{
|
||||
const int participantId = it.key();
|
||||
const QString hierarchy(it.value());
|
||||
|
||||
if (!m_targetParticipantModel->getAssociatedParticipantIds().contains(participantId) || m_target.targetParticipantId() == participantId)
|
||||
{
|
||||
const QPixmap &pm = decorations.value(participantId);
|
||||
|
||||
m_ui->cmbParticipants->addItem(QIcon(pm), hierarchy, participantId);
|
||||
|
||||
// Tooltip:
|
||||
int idx = m_ui->cmbParticipants->findData(participantId);
|
||||
QString tooltip(QStringLiteral("<html>"));
|
||||
// without a temporary file:
|
||||
QByteArray baData;
|
||||
QBuffer buffer(&baData);
|
||||
pm.save(&buffer, "PNG", 100);
|
||||
tooltip.append(QStringLiteral("<center><img src='data:image/png;base64,%1'></center>").arg(QString::fromLatin1(baData.toBase64()))); // how can i center the image?
|
||||
|
||||
#ifndef LTS_DEBUG
|
||||
if (QGuiApplication::keyboardModifiers().testFlag(Qt::KeyboardModifier::ShiftModifier))
|
||||
#endif
|
||||
tooltip.append(QStringLiteral("<center>id=%1</center>").arg(participantId));
|
||||
|
||||
tooltip.append(QStringLiteral("</html>"));
|
||||
m_ui->cmbParticipants->setItemData(idx, tooltip, Qt::ToolTipRole);
|
||||
}
|
||||
}
|
||||
|
||||
int newIdx = m_ui->cmbParticipants->findData(m_target.targetParticipantId());
|
||||
if (newIdx >= 0)
|
||||
m_ui->cmbParticipants->setCurrentIndex(newIdx);
|
||||
m_ui->cmbParticipants->model()->sort(0);
|
||||
|
||||
m_ui->cmbParticipants->setIconSize(QSize(50, 50));
|
||||
connect(m_ui->cmbParticipants, QOverload<int>::of(&LtsWidgets::LtsComboBox::currentIndexChanged),
|
||||
this, &ShootbackTargetEdit::onCmbParticipantsChanged, Qt::UniqueConnection);
|
||||
onCmbParticipantsChanged();
|
||||
}
|
||||
|
||||
//slots
|
||||
void ShootbackTargetEdit::onCmbParticipantsChanged()
|
||||
{
|
||||
const auto decorations(m_targetParticipantModel->getParticipantDecorations());
|
||||
int participantId = m_ui->cmbParticipants->currentData().toInt();
|
||||
const auto it = decorations.find(participantId);
|
||||
if (it != decorations.constEnd())
|
||||
{
|
||||
const QPixmap &pm = decorations.value(it.key());
|
||||
{
|
||||
QString tooltip(QStringLiteral("<html>"));
|
||||
QByteArray data;
|
||||
QBuffer buffer(&data);
|
||||
// XML-Symbol with scale = 4 will produce huge images. Limit the size:
|
||||
pm.save(&buffer, "PNG", 100);
|
||||
|
||||
tooltip += QStringLiteral("<center>");
|
||||
tooltip += QStringLiteral("<img src='data:image/png;base64,%1'>").arg(QString::fromLatin1(data.toBase64()));
|
||||
tooltip += QStringLiteral("</center>");
|
||||
|
||||
#ifndef LTS_DEBUG
|
||||
if (QGuiApplication::keyboardModifiers().testFlag(Qt::KeyboardModifier::ShiftModifier))
|
||||
#endif
|
||||
tooltip.append(QStringLiteral("<center>id=%1</center>").arg(participantId));
|
||||
|
||||
tooltip += QStringLiteral("</html>");
|
||||
m_ui->cmbParticipants->setToolTip(tooltip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ShootbackTargetEdit::apply()
|
||||
{
|
||||
m_target.name(m_ui->leName->text().toStdString());
|
||||
|
||||
m_target.activateLaserDesignation(m_ui->cb_activateLaserDetection->isChecked());
|
||||
m_target.activateLights(m_ui->cb_activateLights->isChecked());
|
||||
m_target.activatePopupAutomatic(m_ui->cb_activatePopupAutomatic->isChecked());
|
||||
m_target.permanentInstalledTarget(m_ui->cb_permanentInstalledTarget->isChecked());
|
||||
m_target.hitsToKill(m_ui->sp_hitsToKill->value());
|
||||
|
||||
// selected participant:
|
||||
int32_t participantId = m_ui->cmbParticipants->currentData().toInt();
|
||||
m_target.targetParticipantId(participantId);
|
||||
|
||||
m_requestHelper->addRequest([this]()
|
||||
{
|
||||
return m_ftc->shootbackTargetModifyRequest(m_target, this);
|
||||
});
|
||||
|
||||
return m_requestHelper->startRequests();
|
||||
}
|
||||
|
||||
|
||||
//private
|
||||
|
||||
void ShootbackTargetEdit::setData(const ShootbackTarget &target)
|
||||
{
|
||||
m_target = target;
|
||||
|
||||
m_ui->leName->setText(QString::fromStdString(m_target.name()));
|
||||
|
||||
m_ui->cb_activateLaserDetection->setChecked(m_target.activateLaserDesignation());
|
||||
m_ui->cb_activateLights->setChecked(m_target.activateLights());
|
||||
m_ui->cb_activatePopupAutomatic->setChecked(m_target.activatePopupAutomatic());
|
||||
m_ui->cb_permanentInstalledTarget->setChecked(m_target.permanentInstalledTarget());
|
||||
m_ui->sp_hitsToKill->setValue(m_target.hitsToKill());
|
||||
|
||||
// update combo box:
|
||||
int newIdx = m_ui->cmbParticipants->findData(m_target.targetParticipantId());
|
||||
if (newIdx >= 0)
|
||||
m_ui->cmbParticipants->setCurrentIndex(newIdx);
|
||||
}
|
||||
|
||||
}
|
||||
Executable
+66
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* TargetManagement - Target Edit Dialog
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Norbert Thoden, NLE, 2020-05-29
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LtsWidgets/lts_dialog.h>
|
||||
|
||||
#include <Services/TargetManagement/tgt_dtc.h>
|
||||
#include <Services/TargetManagement/tgt_ftc.h>
|
||||
|
||||
#include <TargetManagement/logger.h>
|
||||
#include <LtsUtilsGuiDds/request_helper.h>
|
||||
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class ShootbackTargetEdit;
|
||||
}
|
||||
|
||||
namespace TargetManagement
|
||||
{
|
||||
class TargetParticipantModel;
|
||||
|
||||
class ShootbackTargetEdit : public LtsWidgets::LtsDialog,
|
||||
protected TargetManagement::Interface::Ftc::ShootbackTargetModifyReplyHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ShootbackTargetEdit(QWidget *parent = nullptr);
|
||||
~ShootbackTargetEdit();
|
||||
|
||||
bool init(const std::shared_ptr<TargetManagement::Interface::Dtc> &dtc,
|
||||
const std::shared_ptr<TargetManagement::Interface::Ftc> &ftc,
|
||||
TargetParticipantModel *targetParticipantModel,
|
||||
const ShootbackTarget &target = ShootbackTarget());
|
||||
|
||||
//virtual functions from TargetManagement::Interface::Ftc::..
|
||||
void onShootbackTargetModifyReply(const Core::FunctionReplyObject &replyObject) override { m_requestHelper->requestReply(replyObject); }
|
||||
|
||||
private Q_SLOTS:
|
||||
void initCmbParticipants();
|
||||
void onCmbParticipantsChanged();
|
||||
|
||||
private:
|
||||
void setData(const ShootbackTarget &target);
|
||||
bool apply() override;
|
||||
void retranslate() override;
|
||||
|
||||
ShootbackTarget m_target;
|
||||
TargetParticipantModel *m_targetParticipantModel{nullptr};
|
||||
|
||||
std::shared_ptr<TargetManagement::Interface::Dtc> m_dtc;
|
||||
std::shared_ptr<TargetManagement::Interface::Ftc> m_ftc;
|
||||
LtsUtils::RequestHelper *m_requestHelper{nullptr};
|
||||
Ui::ShootbackTargetEdit *m_ui{nullptr};
|
||||
LOGGER_T m_logger;
|
||||
};
|
||||
|
||||
} //namespace TargetManagement
|
||||
Executable
+188
@@ -0,0 +1,188 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ShootbackTargetEdit</class>
|
||||
<widget class="QWidget" name="ShootbackTargetEdit">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>963</width>
|
||||
<height>318</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_6">
|
||||
<item row="0" column="0">
|
||||
<layout class="QGridLayout" name="gridLayout_5">
|
||||
<item row="0" column="0">
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="0" column="0">
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="lbl_name">
|
||||
<property name="text">
|
||||
<string>Name:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="leName"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_assoParticipant">
|
||||
<property name="text">
|
||||
<string>Participant:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="LtsWidgets::LtsComboBox" name="cmbParticipants"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="Line" name="line_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="cb_activateLaserDetection">
|
||||
<property name="text">
|
||||
<string>Activate laser detection</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="cb_permanentInstalledTarget">
|
||||
<property name="text">
|
||||
<string>Permanent installed target</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="cb_activateLights">
|
||||
<property name="text">
|
||||
<string>activate lights</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="lb_silhouette">
|
||||
<property name="text">
|
||||
<string>Silhouette:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="cmb_silhouette"/>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="QLabel" name="lb_silhouetteImage">
|
||||
<property name="text">
|
||||
<string>Silhouette-placeholder</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="lb_hitsToKill">
|
||||
<property name="text">
|
||||
<string>Hits to kill:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="sp_hitsToKill"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="lb_curState">
|
||||
<property name="text">
|
||||
<string>Current State:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="lb_curState_2">
|
||||
<property name="text">
|
||||
<string>value</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="cb_activatePopupAutomatic">
|
||||
<property name="text">
|
||||
<string>Activate popup automatic</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="lb_curState_3">
|
||||
<property name="text">
|
||||
<string>Set state:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QRadioButton" name="rb_stateUp">
|
||||
<property name="text">
|
||||
<string>Up</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QRadioButton" name="rb_StateDown">
|
||||
<property name="text">
|
||||
<string>Down</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>LtsWidgets::LtsComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>LtsWidgets/lts_combo_box.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>leName</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
Executable
+692
@@ -0,0 +1,692 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Target-Area-Assignment
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Norbert Thoden, NLE, 2020-06-29
|
||||
*/
|
||||
|
||||
#include "tgt_target_area_assignment_dialog.h"
|
||||
#include "ui_tgt_target_area_assignment_dialog.h"
|
||||
#include "tgt_target_area_assignment_edit.h"
|
||||
#include "tgt_telegrams.h"
|
||||
#include <LtsSession/lts_session_data.h>
|
||||
#include <FileManagement/flm_translation.h>
|
||||
|
||||
#include <PluginInterfaces/gui_plugin_interface.h>
|
||||
#include <Plugins/TargetManagement/tgt_data_plugin_interface.h>
|
||||
#include <Plugins/FileManagement/flm_explorer_gui_plugin_interface.h>
|
||||
#include <Plugins/ParticipantManagement/ppm_data_plugin_interface.h>
|
||||
#include <Plugins/ParticipantManagement/ppm_gui_combobox_plugin_interface.h>
|
||||
#include <Plugins/SituationMapPlugin/situation_map_gui_plugin_interface.h>
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
namespace TargetManagement
|
||||
{
|
||||
|
||||
AssignmentDialog::AssignmentDialog(const QString &menuGroup, LtsSession::LtsSession *session, QWidget *parent)
|
||||
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
|
||||
, m_session(session)
|
||||
, m_ui(new Ui::TargetAreaAssignmentsDialog)
|
||||
, m_menuGroup(menuGroup)
|
||||
, m_requestHelper(new LtsUtils::RequestHelper(this))
|
||||
, m_logger(getLogger("AssignmentDialog"))
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
setOnlineHelpFilename(QStringLiteral("Situation-Assign/Configure_Targets"));
|
||||
}
|
||||
|
||||
AssignmentDialog::~AssignmentDialog()
|
||||
{
|
||||
clearSelectionOfMapObjects();
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
bool AssignmentDialog::init(MODE mode, int idAccordingToMode)
|
||||
{
|
||||
m_mode = mode;
|
||||
|
||||
if (!m_session)
|
||||
return false;
|
||||
|
||||
if (!m_session->getDtc<TargetManagement::DataInterface>(m_dtc))
|
||||
return false;
|
||||
if (!m_session->getFtc<TargetManagement::DataInterface>(m_ftc))
|
||||
return false;
|
||||
if (!m_session->getDtc<ParticipantManagement::DataInterface>(m_ppmDtc))
|
||||
return false;
|
||||
if (!m_session->getForeignGuiInterface<ParticipantManagement::ForeignGuiComboboxInterface>(m_ppmGuiCbxIfc))
|
||||
return false;
|
||||
if (!m_session->getForeignGuiInterface<FileManagement::ForeignGuiInterface>(m_flmGui))
|
||||
return false;
|
||||
if (!m_session->getForeignGuiInterface<SituationMap::ForeignGuiInterface>(m_sitMapGuiIfc))
|
||||
return false;
|
||||
|
||||
// initialize model:
|
||||
INFO_LOG(m_logger) << "AssignmentDialog::init";
|
||||
m_assignmentParticipantModel = new AssignmentParticipantModel(this);
|
||||
m_assignmentParticipantModel->initModel(m_dtc, m_ppmDtc, m_ppmGuiCbxIfc, m_session);
|
||||
|
||||
// proxyModel:
|
||||
m_assignmentParticipantProxyModel = new AssignmentParticipantProxyModel(this);
|
||||
m_assignmentParticipantProxyModel->setSourceModel(m_assignmentParticipantModel);
|
||||
m_assignmentParticipantProxyModel->setDynamicSortFilter(false);
|
||||
|
||||
// set view: (LtsDataView)
|
||||
m_ui->widget->setModel(m_assignmentParticipantProxyModel);
|
||||
|
||||
// to allow remove off some rows at once. Anoying in all other cases -> stay at singleSelection
|
||||
// m_ui->widget->setSelectionMode(QAbstractItemView::SelectionMode::MultiSelection);
|
||||
|
||||
// connects for gui
|
||||
connect(m_ui->widget, &LtsDataView::LtsDataView::signalSelectionChanged,
|
||||
this, &AssignmentDialog::onSelectionChanged);
|
||||
connect(m_ui->widget, &LtsDataView::LtsDataView::signalDoubleClicked,
|
||||
this, &AssignmentDialog::onEditAssignment);
|
||||
connect(this, &AssignmentDialog::escapePressed, this,
|
||||
&AssignmentDialog::onEscapePressed, Qt::UniqueConnection);
|
||||
|
||||
// Create Add-Button
|
||||
m_buttonBox->connectButton(LtsWidgets::DialogButton::Add, this, &AssignmentDialog::onNewAssignment);
|
||||
|
||||
// Create Remove-Button
|
||||
m_buttonBox->connectButton(LtsWidgets::DialogButton::Remove, this, &AssignmentDialog::onRemoveAssignment);
|
||||
|
||||
// Create Modify-Button
|
||||
m_buttonBox->connectButton(LtsWidgets::DialogButton::Edit, this, &AssignmentDialog::onEditAssignment);
|
||||
|
||||
// connect signals of TableView/CustomView:
|
||||
connect(m_ui->widget, &LtsDataView::LtsDataView::clicked, this, &AssignmentDialog::onTableViewClicked);
|
||||
// it´s possible to evaluate signalEntered, but seems to be overkill here:
|
||||
// connect(m_ui->widget, &LtsDataView::LtsDataView::signalEntered, this, &AssignmentDialog::onObjectEntered);
|
||||
|
||||
|
||||
#ifndef LTS_DEBUG
|
||||
m_ui->widget->hideColumn(AssignmentParticipantModel::Columns::Id);
|
||||
m_ui->widget->hideColumn(AssignmentParticipantModel::Columns::TargetPartipantId);
|
||||
#endif
|
||||
|
||||
// connect signals of model:
|
||||
connect(m_assignmentParticipantModel, &AssignmentParticipantModel::signalEditableItemChanged,
|
||||
this, [this]()
|
||||
{
|
||||
slotChangesMade();
|
||||
// most likely the checkBox 'active' has changed. BackgroundRole has to be updated:
|
||||
m_assignmentParticipantModel->update();
|
||||
});
|
||||
|
||||
|
||||
// Save/Load from Library Button
|
||||
m_buttonBox->connectLibraryButton(this,
|
||||
&AssignmentDialog::onImportButtonClicked,
|
||||
&AssignmentDialog::onExportButtonClicked);
|
||||
if (!m_flmGui)
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Library, false);
|
||||
|
||||
|
||||
// 'Map' Button(s)
|
||||
m_buttonBox->connectButton(LtsWidgets::DialogButton::CenterMap, this, &AssignmentDialog::onMapCenterClicked);
|
||||
m_buttonBox->connectButton(LtsWidgets::DialogButton::ZoomMapTo, this, &AssignmentDialog::onMapZoomToClicked);
|
||||
|
||||
if (!m_sitMapGuiIfc)
|
||||
{
|
||||
m_buttonBox->setButtonVisible(LtsWidgets::DialogButton::CenterMap, false);
|
||||
m_buttonBox->setButtonVisible(LtsWidgets::DialogButton::ZoomMapTo, false);
|
||||
}
|
||||
|
||||
|
||||
// according mode: set filter; showHide columns; fill gap etc.
|
||||
setMode(mode, idAccordingToMode);
|
||||
|
||||
// call eneDisa / onSelectionChanged once:
|
||||
onSelectionChanged();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AssignmentDialog::setMode(AssignmentDialog::MODE mode, int idAccordingToMode)
|
||||
{
|
||||
if (!m_assignmentParticipantProxyModel)
|
||||
return false;
|
||||
|
||||
// filter:
|
||||
bool hideTargetColumns = false;
|
||||
bool hideAreaColumns = false;
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case MODE::ALL:
|
||||
m_assignmentParticipantProxyModel->filterToAreaId();
|
||||
m_assignmentParticipantProxyModel->filterToTargetParticpantId();
|
||||
break;
|
||||
case MODE::FILTERED_TO_SINGLE_AREA:
|
||||
m_assignmentParticipantProxyModel->filterToAreaId(idAccordingToMode);
|
||||
hideAreaColumns = true;
|
||||
break;
|
||||
case MODE::FILTERED_TO_SINGLE_TARGET_PARTICPANT:
|
||||
m_assignmentParticipantProxyModel->filterToTargetParticpantId(idAccordingToMode); // idAccordingToMode == targetParticipantId
|
||||
hideTargetColumns = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// targetColumns:
|
||||
m_ui->widget->setColumnHidden(AssignmentParticipantModel::Columns::TargetId, hideTargetColumns);
|
||||
m_ui->widget->setColumnHidden(AssignmentParticipantModel::Columns::TargetName, hideTargetColumns);
|
||||
m_ui->widget->setColumnHidden(AssignmentParticipantModel::Columns::TargetPartipantId, hideTargetColumns);
|
||||
m_ui->widget->setColumnHidden(AssignmentParticipantModel::Columns::TargetPartipantEquipmentNumber, hideTargetColumns);
|
||||
// m_ui->widget->setColumnHidden(AssignmentParticipantModel::Columns::Participant, hideTargetColumns);
|
||||
|
||||
// areaColumns:
|
||||
m_ui->widget->setColumnHidden(AssignmentParticipantModel::Columns::AreaId, hideAreaColumns);
|
||||
m_ui->widget->setColumnHidden(AssignmentParticipantModel::Columns::AreaName, hideAreaColumns);
|
||||
|
||||
|
||||
// fill gaps (add missing entries in the model to show their checkboxes):
|
||||
if (mode == MODE::FILTERED_TO_SINGLE_AREA)
|
||||
m_assignmentParticipantModel->addGapFillerForArea(idAccordingToMode);
|
||||
else if (mode == MODE::FILTERED_TO_SINGLE_TARGET_PARTICPANT)
|
||||
m_assignmentParticipantModel->addGapFillerForTargetParticipantId(idAccordingToMode);
|
||||
|
||||
// visible
|
||||
m_buttonBox->setButtonVisible(LtsWidgets::DialogButton::Library, (mode == MODE::ALL));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AssignmentDialog::retranslate()
|
||||
{
|
||||
if (m_assignmentParticipantProxyModel)
|
||||
{
|
||||
const int areadId = m_assignmentParticipantProxyModel->getFilterToAreaId();
|
||||
if (areadId > 0)
|
||||
{
|
||||
translate(m_ui,
|
||||
QString::fromStdString(m_dtc->shootbackArea(areadId).name()),
|
||||
false,
|
||||
tr("Targets assigned to"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
QString name;
|
||||
const int targetParticipantId = m_assignmentParticipantProxyModel->getFilterToTargetParticpantId();
|
||||
if (targetParticipantId > 0)
|
||||
{
|
||||
const QMap<qint32, TargetManagement::ShootbackTarget> &shootbackTargets =
|
||||
m_dtc->shootbackTargets();
|
||||
for (const TargetManagement::ShootbackTarget &target : qAsConst(shootbackTargets))
|
||||
{
|
||||
if (target.targetParticipantId() == targetParticipantId)
|
||||
{
|
||||
name = QString::fromStdString(target.name());
|
||||
break;
|
||||
}
|
||||
} // for
|
||||
|
||||
translate(m_ui,
|
||||
name,
|
||||
false,
|
||||
tr("Areas assigned to"));
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
// translate(m_ui, tr("Target-Area-Assignments"));
|
||||
translate(m_ui, tr("Shootback Overview"));
|
||||
}
|
||||
|
||||
void AssignmentDialog::keyPressEvent(QKeyEvent *event)
|
||||
{
|
||||
if (event->key() == Qt::Key_Escape)
|
||||
emit escapePressed();
|
||||
return BaseClass::keyPressEvent(event);
|
||||
}
|
||||
|
||||
void AssignmentDialog::onNewAssignment()
|
||||
{
|
||||
INFO_LOG(m_logger) << "onNew";
|
||||
|
||||
AssignmentEditDialog *dialog = new AssignmentEditDialog(this);
|
||||
|
||||
if (!dialog->init(m_dtc, m_ftc, m_assignmentParticipantModel))
|
||||
{
|
||||
ERROR_LOG(m_logger) << QLatin1String("Can't initialize AssignmentEditDialog!");
|
||||
delete dialog;
|
||||
return;
|
||||
}
|
||||
|
||||
connect(dialog, &AssignmentEditDialog::updateItem, this, &AssignmentDialog::onUpdateItem);
|
||||
|
||||
addDialog(dialog, m_menuGroup, QStringLiteral("Add Assignment"), LtsWidgets::LayoutArea::eDialogTab, true, true);
|
||||
}
|
||||
|
||||
void AssignmentDialog::onRemoveAssignment()
|
||||
{
|
||||
const QModelIndexList &selectedRows = m_ui->widget->selectedRows();
|
||||
for (const auto &mi : selectedRows)
|
||||
{
|
||||
Core::RemoveElementRequest req;
|
||||
req.id(m_assignmentParticipantModel->getRowData(mi.row()).id());
|
||||
m_requestHelper->addRequest([req, this]()
|
||||
{
|
||||
return m_ftc->targetAreaAssignmentRemoveRequest(req, this);
|
||||
});
|
||||
}
|
||||
m_requestHelper->startRequests();
|
||||
}
|
||||
|
||||
void AssignmentDialog::onEditAssignment()
|
||||
{
|
||||
QModelIndexList selectedRows = m_ui->widget->selectedRows();
|
||||
if (selectedRows.isEmpty())
|
||||
return;
|
||||
const QModelIndex curIdx = selectedRows.first();
|
||||
if (!curIdx.isValid())
|
||||
return;
|
||||
|
||||
AssignmentEditDialog *dialog = new AssignmentEditDialog(this);
|
||||
|
||||
const TargetAreaAssignment &assignment = m_assignmentParticipantModel->getRowData(curIdx.row());
|
||||
|
||||
DEBUG_LOG(m_logger) << " onEditTargetArea, row = " << curIdx.row() << ", assignment.id() = " << assignment.id();
|
||||
if (!dialog->init(m_dtc, m_ftc, m_assignmentParticipantModel, assignment))
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << QLatin1String("Can't initialize ShootbackTarget!");
|
||||
delete dialog;
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_mode != MODE::ALL)
|
||||
dialog->lockTargetParticipantAndArea(); // edit a certain assignment, changing target and/or areas is not allowed
|
||||
|
||||
connect(dialog, &AssignmentEditDialog::updateItem, this, &AssignmentDialog::onUpdateItem);
|
||||
|
||||
addDialog(dialog, m_menuGroup, QStringLiteral("Edit Target"), LtsWidgets::LayoutArea::eDialogTab, true, true);
|
||||
}
|
||||
|
||||
void AssignmentDialog::onUpdateItem(const TargetAreaAssignment &assignment)
|
||||
{
|
||||
INFO_LOG(m_logger) << LOGFUNCTION << " got item to update, item=" << assignment;
|
||||
|
||||
if (assignment.id()>0)
|
||||
{
|
||||
//
|
||||
// assignment.id>0 -> already persistent
|
||||
//
|
||||
QModelIndex mi = m_assignmentParticipantModel->findIndexForId(assignment.id());
|
||||
int row = mi.row();
|
||||
INFO_LOG(m_logger) << LOGFUNCTION << " got item to update, row=" << row;
|
||||
if (row < 0)
|
||||
{
|
||||
abort();
|
||||
// m_assignmentParticipantModel->insertRow(assignment);
|
||||
// INFO_LOG(m_logger) << LOGFUNCTION << " CHANGED CHANGED CHANGED CHANGED CHANGED";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_assignmentParticipantModel->getRowData(row) != assignment)
|
||||
{
|
||||
m_assignmentParticipantModel->setRowData(row, assignment);
|
||||
INFO_LOG(m_logger) << LOGFUNCTION << " CHANGED CHANGED CHANGED CHANGED CHANGED, row = " << row;
|
||||
slotChangesMade();
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
//
|
||||
// assignment.id<0 -> new
|
||||
//
|
||||
int row = m_assignmentParticipantModel->findRowForAreaTargetParticipantId(assignment.areaId(), assignment.targetParticipantId());
|
||||
INFO_LOG(m_logger) << LOGFUNCTION << " got item to update, row=" << row;
|
||||
if (row < 0)
|
||||
{
|
||||
m_assignmentParticipantModel->insertRow(assignment);
|
||||
INFO_LOG(m_logger) << LOGFUNCTION << " CHANGED CHANGED CHANGED CHANGED CHANGED";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_assignmentParticipantModel->getRowData(row) != assignment)
|
||||
{
|
||||
m_assignmentParticipantModel->setRowData(row, assignment);
|
||||
INFO_LOG(m_logger) << LOGFUNCTION << " CHANGED CHANGED CHANGED CHANGED CHANGED, row = " << row;
|
||||
slotChangesMade();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QByteArray AssignmentDialog::toJson() const
|
||||
{
|
||||
QJsonObject obj;
|
||||
|
||||
// operatorId just for convenience:
|
||||
const int operatorId = LtsSessionData::LtsSessionData::getInstance()->getOperatorId();
|
||||
obj[QStringLiteral("OperatorId")] = operatorId;
|
||||
obj[QStringLiteral("XmlType")] = FileManagement::toString(FileManagement::XmlType::TGTShootbackAssignment); // ToDo
|
||||
|
||||
{
|
||||
const QVector<TargetManagement::TargetAreaAssignment>& modelData = m_assignmentParticipantModel->getData();
|
||||
QJsonArray jArray;
|
||||
for (const TargetManagement::TargetAreaAssignment &taa : modelData)
|
||||
{
|
||||
TargetAreaAssignmentData taad;
|
||||
taad.id = taa.id();
|
||||
taad.name = QString::fromStdString(taa.name());
|
||||
|
||||
taad.areaId = taa.areaId();
|
||||
taad.targetParticipantId = taa.targetParticipantId();
|
||||
|
||||
taad.isActive = taa.isActive();
|
||||
|
||||
// TargetAreaConfigurationData
|
||||
taad.configuration.interval1 = taa.configuration().interval1();
|
||||
taad.configuration.flash1 = taa.configuration().flash1();
|
||||
taad.configuration.effect1 = taa.configuration().effect1();
|
||||
taad.configuration.interval2 = taa.configuration().interval2();
|
||||
taad.configuration.flash2 = taa.configuration().flash2();
|
||||
taad.configuration.effect2 = taa.configuration().effect2();
|
||||
|
||||
|
||||
jArray.append(taad.toJson());
|
||||
}
|
||||
obj[QStringLiteral("TargetAreaAssignment")] = jArray;
|
||||
}
|
||||
QJsonDocument doc(obj);
|
||||
|
||||
DEBUG_LOG(m_logger) << " json = " << doc.toJson();
|
||||
|
||||
return doc.toJson(QJsonDocument::Compact);
|
||||
}
|
||||
|
||||
QVector<TargetManagement::TargetAreaAssignment> AssignmentDialog::fromJson(const QByteArray &content)
|
||||
{
|
||||
const QJsonDocument doc(QJsonDocument::fromJson(content));
|
||||
const QJsonObject obj(doc.object());
|
||||
|
||||
// operatorId just for convenience:
|
||||
const int operatorId = obj[QStringLiteral("operatorId")].toInt();
|
||||
Q_UNUSED(operatorId);
|
||||
|
||||
const QJsonArray &jArray = obj[QStringLiteral("TargetAreaAssignment")].toArray();
|
||||
QVector<TargetManagement::TargetAreaAssignment> vecData;
|
||||
vecData.reserve(jArray.size());
|
||||
for (const auto &item : jArray)
|
||||
{
|
||||
const TargetAreaAssignmentData &taad = TargetAreaAssignmentData::fromJson(item.toObject());
|
||||
TargetManagement::TargetAreaAssignment taa;
|
||||
taa.id(taad.id);
|
||||
taa.name(taad.name.toStdString());
|
||||
|
||||
taa.areaId(taad.areaId);
|
||||
taa.targetParticipantId(taad.targetParticipantId);
|
||||
|
||||
taa.isActive(taad.isActive);
|
||||
|
||||
// TargetAreaConfigurationData
|
||||
taa.configuration().interval1(taad.configuration.interval1);
|
||||
taa.configuration().flash1(taad.configuration.flash1);
|
||||
taa.configuration().effect1(taad.configuration.effect1);
|
||||
taa.configuration().interval2(taad.configuration.interval2);
|
||||
taa.configuration().flash2(taad.configuration.flash2);
|
||||
taa.configuration().effect2(taad.configuration.effect2);
|
||||
|
||||
vecData.push_back(std::move(taa));
|
||||
}
|
||||
return vecData;
|
||||
}
|
||||
|
||||
bool AssignmentDialog::apply()
|
||||
{
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << " APPLY";
|
||||
|
||||
const QVector<TargetAreaAssignment> &assignments = m_assignmentParticipantModel->getData();
|
||||
for (const TargetAreaAssignment &updateCandidate : qAsConst(assignments))
|
||||
{
|
||||
const int assignmentId = updateCandidate.id();
|
||||
const TargetAreaAssignment &curAssignment = m_dtc->targetAreaAssignment(assignmentId);
|
||||
|
||||
if (updateCandidate.isActive() && isDefault(updateCandidate.configuration()))
|
||||
{
|
||||
// apply not allowed
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << " APPLY NOT ALLOWED - Invalid configuration provided for at least one active assignment";
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << " APPLY NOT ALLOWED - Invalid configuration provided for at least one active assignment";
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << " updateCandidate " << updateCandidate;
|
||||
|
||||
QMessageBox::warning(this, tr("No configuration"),
|
||||
tr("Invalid configuration provided for at least one active assignment.")
|
||||
);
|
||||
|
||||
// maybe the selection covers the invalid row marked red (backgroundRole)
|
||||
m_ui->widget->clearSelection();
|
||||
return false;
|
||||
}
|
||||
|
||||
// gapFiller -> call isEqual with ignoringAreaIdAndParticipantId==true
|
||||
bool isGapFiller = (assignmentId <= 0);
|
||||
if (!isEqual(curAssignment, updateCandidate, isGapFiller))
|
||||
{
|
||||
INFO_LOG(m_logger) << LOGFUNCTION << " add request for: assignmentId:" << assignmentId
|
||||
<< " name: " << QString::fromStdString(updateCandidate.name());
|
||||
m_requestHelper->addRequest([this, updateCandidate]()
|
||||
{
|
||||
return m_ftc->targetAreaAssignmentModifyRequest(updateCandidate, this);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (m_requestHelper->hasRequests())
|
||||
m_requestHelper->startRequests();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AssignmentDialog::onEscapePressed()
|
||||
{
|
||||
m_ui->widget->clearSelection();
|
||||
}
|
||||
|
||||
void AssignmentDialog::onExportButtonClicked()
|
||||
{
|
||||
QByteArray byteArray = toJson();
|
||||
int fileId = m_flmGui->saveFileContent(this, FileManagement::FileType::Xml, m_session->exerciseId(), byteArray);
|
||||
if (fileId > 0)
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << "Saved file with id = " << fileId;
|
||||
else
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << "Could not save file in library ";
|
||||
}
|
||||
|
||||
void AssignmentDialog::onImportButtonClicked()
|
||||
{
|
||||
INFO_LOG(m_logger) << LOGFUNCTION << "--- onImportButtonClicked() ";
|
||||
|
||||
QHash<LtsWidgets::Button, QString> buttonTexts;
|
||||
buttonTexts.insert(LtsWidgets::Button::Ok, tr("Overwrite"));
|
||||
buttonTexts.insert(LtsWidgets::Button::Cancel, tr("Cancel"));
|
||||
|
||||
LtsWidgets::LtsMessageDialogNew *dlg = new LtsWidgets::LtsMessageDialogNew(this,
|
||||
tr("Overwrite existing data?"),
|
||||
tr("Load from Library"),
|
||||
LtsWidgets::Behaviour::Popup,
|
||||
LtsWidgets::Button::Ok | LtsWidgets::Button::Cancel,
|
||||
buttonTexts);
|
||||
connect(dlg, &LtsWidgets::LtsMessageDialogNew::ok,
|
||||
this, &AssignmentDialog::onImport);
|
||||
}
|
||||
|
||||
void AssignmentDialog::onImport()
|
||||
{
|
||||
QByteArray content;
|
||||
int fileId = m_flmGui->loadFileContent(this, content, {FileManagement::FileType::Xml},
|
||||
m_session->exerciseId(),
|
||||
FileManagement::toString(FileManagement::XmlType::TGTShootbackAssignment));
|
||||
if (fileId > 0)
|
||||
{
|
||||
if (!m_flmGui->isXmlType(content, FileManagement::toString(FileManagement::XmlType::TGTShootbackAssignment)))
|
||||
{
|
||||
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
|
||||
{
|
||||
// update svc via clear and (re-)insert:
|
||||
// 1) clear svc:
|
||||
const QVector<TargetAreaAssignment> &curData = m_assignmentParticipantModel->getData();
|
||||
for (auto item : curData)
|
||||
{
|
||||
Core::RemoveElementRequest req(item.id());
|
||||
m_requestHelper->addRequest([this, req]()
|
||||
{
|
||||
return m_ftc->targetAreaAssignmentRemoveRequest(req, this);
|
||||
});
|
||||
}
|
||||
|
||||
// 2) re-insert:
|
||||
const QVector<TargetManagement::TargetAreaAssignment> vecDataCandidate(fromJson(content));
|
||||
for (TargetAreaAssignment assignment : vecDataCandidate)
|
||||
{
|
||||
assignment.id(0); // force create
|
||||
m_requestHelper->addRequest([this, assignment]()
|
||||
{
|
||||
return m_ftc->targetAreaAssignmentModifyRequest(assignment, this);
|
||||
});
|
||||
}
|
||||
|
||||
// clear view *before* performing the requests:
|
||||
m_assignmentParticipantModel->clear();
|
||||
|
||||
m_requestHelper->startRequests();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AssignmentDialog::onMapCenterClicked()
|
||||
{
|
||||
if (!m_sitMapGuiIfc)
|
||||
return;
|
||||
QModelIndexList selectedRows = m_ui->widget->selectedRows();
|
||||
if (selectedRows.isEmpty())
|
||||
return;
|
||||
const QModelIndex curIdx = selectedRows.first();
|
||||
if (!curIdx.isValid())
|
||||
return;
|
||||
|
||||
if (m_mode == MODE::FILTERED_TO_SINGLE_TARGET_PARTICPANT)
|
||||
{
|
||||
const int areaId = m_assignmentParticipantModel->getRowData(curIdx.row()).areaId();
|
||||
if (areaId<=0)
|
||||
return;
|
||||
m_sitMapGuiIfc->centerMapToMapObject(SituationMap::MapObjectType::MOT_ShootbackArea, areaId);
|
||||
} else {
|
||||
const int pId = m_assignmentParticipantModel->getRowData(curIdx.row()).targetParticipantId();
|
||||
if (pId<=0)
|
||||
return;
|
||||
m_sitMapGuiIfc->centerMapToMapObject(SituationMap::MapObjectType::MOT_Participant, pId);
|
||||
}
|
||||
}
|
||||
|
||||
void AssignmentDialog::onMapZoomToClicked()
|
||||
{
|
||||
QModelIndexList selectedRows = m_ui->widget->selectedRows();
|
||||
if (selectedRows.isEmpty())
|
||||
return;
|
||||
QModelIndex index = selectedRows.first();
|
||||
if (!index.isValid())
|
||||
return;
|
||||
|
||||
if (!m_assignmentParticipantModel || !m_sitMapGuiIfc)
|
||||
return;
|
||||
|
||||
const TargetAreaAssignment &assignment = m_assignmentParticipantModel->getRowData(index.row());
|
||||
const int areaId = assignment.areaId();
|
||||
const int pId = assignment.targetParticipantId();
|
||||
|
||||
if ((areaId<=0) || (pId<=0))
|
||||
return;
|
||||
|
||||
m_sitMapGuiIfc->zoomMapTo({ {SituationMap::MapObjectType::MOT_Participant, pId}, {SituationMap::MapObjectType::MOT_ShootbackArea, areaId} });
|
||||
}
|
||||
|
||||
void AssignmentDialog::onObjectEntered(const QModelIndex &index)
|
||||
{
|
||||
if (!m_sitMapGuiIfc)
|
||||
return;
|
||||
if (!index.isValid())
|
||||
{
|
||||
m_sitMapGuiIfc->removeObjectIndicator();
|
||||
return;
|
||||
}
|
||||
const TargetAreaAssignment &assignment = m_assignmentParticipantModel->getRowData(index.row());
|
||||
const int areaId = assignment.areaId();
|
||||
const int pId = assignment.targetParticipantId();
|
||||
|
||||
if ((areaId<=0) || (pId<=0))
|
||||
return;
|
||||
|
||||
if (m_mode == MODE::FILTERED_TO_SINGLE_TARGET_PARTICPANT)
|
||||
{
|
||||
// Assigned Area:
|
||||
m_sitMapGuiIfc->objectIndicatorToMapObject(SituationMap::MapObjectType::MOT_ShootbackArea, areaId, true);
|
||||
// Target/Participant
|
||||
m_sitMapGuiIfc->setMapObjectSelected(SituationMap::MapObjectType::MOT_Participant, {pId}, true);
|
||||
} else {
|
||||
// Target/Participant
|
||||
m_sitMapGuiIfc->objectIndicatorToMapObject(SituationMap::MapObjectType::MOT_Participant, pId, true);
|
||||
// Assigned Area:
|
||||
m_sitMapGuiIfc->setMapObjectSelected(SituationMap::MapObjectType::MOT_ShootbackArea, {areaId}, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void AssignmentDialog::onTableViewClicked(const QModelIndex &index)
|
||||
{
|
||||
if (!index.isValid())
|
||||
return;
|
||||
|
||||
if (QGuiApplication::keyboardModifiers().testFlag(Qt::KeyboardModifier::ShiftModifier))
|
||||
onMapCenterClicked();
|
||||
}
|
||||
|
||||
void AssignmentDialog::clearSelectionOfMapObjects()
|
||||
{
|
||||
if (!m_sitMapGuiIfc)
|
||||
return;
|
||||
// remove MapObjectIndicator:
|
||||
m_sitMapGuiIfc->removeObjectIndicator();
|
||||
}
|
||||
|
||||
void AssignmentDialog::onSelectionChanged()
|
||||
{
|
||||
QModelIndexList selectedRows = m_ui->widget->selectedRows();
|
||||
const int cntSelectedRows = selectedRows.size();
|
||||
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Remove, cntSelectedRows >= 1);
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Edit, cntSelectedRows == 1);
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::CenterMap, cntSelectedRows == 1);
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::ZoomMapTo, cntSelectedRows == 1);
|
||||
|
||||
m_buttonBox->setButtonVisible(LtsWidgets::DialogButton::Add, m_mode == MODE::ALL);
|
||||
m_buttonBox->setButtonVisible(LtsWidgets::DialogButton::Remove, m_mode == MODE::ALL);
|
||||
|
||||
if (selectedRows.isEmpty())
|
||||
onObjectEntered({}); // use invalid Idx to removeObjectIndicator
|
||||
else
|
||||
onObjectEntered(selectedRows.first());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
} // namespace TargetManagement
|
||||
Executable
+112
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Target-Area-Assignment
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Norbert Thoden, NLE, 2020-06-29
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LtsWidgets/lts_dialog.h>
|
||||
#include <TargetManagement/tgt_dtc.h>
|
||||
#include <TargetManagement/tgt_ftc.h>
|
||||
#include <ParticipantManagement/ppm_dtc.h>
|
||||
#include <LtsUtilsGuiDds/request_helper.h>
|
||||
#include <TargetManagement/logger.h>
|
||||
#include <Plugins/TargetManagement/Gui/ShootbackTargetConfiguration/tgt_assignment_part_model.h>
|
||||
#include <Plugins/FileManagement/flm_explorer_gui_plugin_interface.h>
|
||||
#include <Plugins/SituationMapPlugin/situation_map_gui_plugin_interface.h>
|
||||
|
||||
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class TargetAreaAssignmentsDialog;
|
||||
}
|
||||
|
||||
namespace TargetManagement
|
||||
{
|
||||
|
||||
class AssignmentDialog final : public LtsWidgets::LtsDialog
|
||||
, protected TargetManagement::Interface::Ftc::TargetAreaAssignmentModifyReplyHandler
|
||||
, protected TargetManagement::Interface::Ftc::TargetAreaAssignmentRemoveReplyHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
using BaseClass = LtsWidgets::LtsDialog;
|
||||
|
||||
enum class MODE
|
||||
{
|
||||
ALL,
|
||||
FILTERED_TO_SINGLE_AREA,
|
||||
FILTERED_TO_SINGLE_TARGET_PARTICPANT
|
||||
};
|
||||
|
||||
|
||||
explicit AssignmentDialog(const QString &menuGroup, LtsSession::LtsSession *session, QWidget *parent = nullptr);
|
||||
~AssignmentDialog();
|
||||
|
||||
bool init(MODE mode = MODE::ALL, int idAccordingToMode = -1);
|
||||
|
||||
Q_SIGNALS:
|
||||
void escapePressed();
|
||||
|
||||
protected:
|
||||
bool setMode(MODE mode, int idAccordingToMode = -1);
|
||||
void retranslate() override;
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent *event) override final;
|
||||
void onTargetAreaAssignmentModifyReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
|
||||
void onTargetAreaAssignmentRemoveReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
|
||||
|
||||
QByteArray toJson() const;
|
||||
QVector<TargetAreaAssignment> fromJson(const QByteArray &content);
|
||||
|
||||
private Q_SLOTS:
|
||||
bool apply() override;
|
||||
|
||||
void onEscapePressed();
|
||||
void onSelectionChanged();
|
||||
void onNewAssignment();
|
||||
void onRemoveAssignment();
|
||||
void onEditAssignment();
|
||||
|
||||
void onUpdateItem(const TargetAreaAssignment &assignment);
|
||||
|
||||
void onExportButtonClicked();
|
||||
void onImportButtonClicked();
|
||||
void onImport();
|
||||
|
||||
void onMapCenterClicked();
|
||||
void onMapZoomToClicked();
|
||||
|
||||
void onObjectEntered(const QModelIndex &index);
|
||||
void onTableViewClicked(const QModelIndex &index);
|
||||
|
||||
void clearSelectionOfMapObjects();
|
||||
|
||||
private:
|
||||
MODE m_mode{MODE::ALL};
|
||||
AssignmentParticipantModel *m_assignmentParticipantModel{nullptr};
|
||||
AssignmentParticipantProxyModel *m_assignmentParticipantProxyModel{nullptr};
|
||||
|
||||
|
||||
std::shared_ptr<TargetManagement::Interface::Dtc> m_dtc;
|
||||
std::shared_ptr<TargetManagement::Interface::Ftc> m_ftc;
|
||||
std::shared_ptr<ParticipantManagement::Interface::Dtc> m_ppmDtc;
|
||||
std::shared_ptr<ParticipantManagement::ForeignGuiComboboxInterface> m_ppmGuiCbxIfc;
|
||||
std::shared_ptr<FileManagement::ForeignGuiInterface> m_flmGui;
|
||||
std::shared_ptr<SituationMap::ForeignGuiInterface> m_sitMapGuiIfc;
|
||||
|
||||
LtsSession::LtsSession *m_session{nullptr};
|
||||
Ui::TargetAreaAssignmentsDialog *m_ui{nullptr};
|
||||
QString m_menuGroup;
|
||||
LtsUtils::RequestHelper *m_requestHelper{nullptr};
|
||||
LOGGER_T m_logger;
|
||||
};
|
||||
|
||||
} // namespace TargetManagement
|
||||
Executable
+45
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TargetAreaAssignmentsDialog</class>
|
||||
<widget class="QWidget" name="TargetAreaAssignmentsDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>455</width>
|
||||
<height>341</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">AlarmView</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="LtsDataView::LtsDataView" name="widget" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>250</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</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>
|
||||
Executable
+294
@@ -0,0 +1,294 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* TargetManagement - Target Edit Dialog
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Norbert Thoden, NLE, 2020-05-29
|
||||
*/
|
||||
|
||||
#include "tgt_target_area_assignment_edit.h"
|
||||
#include "tgt_assignment_part_model.h"
|
||||
#include "ui_tgt_target_area_assignment_edit.h"
|
||||
|
||||
//#include <TargetManagement/ppm_translation.h>
|
||||
|
||||
#include <LtsUtilsSettings/settings.h>
|
||||
|
||||
#include <QBuffer>
|
||||
|
||||
namespace TargetManagement
|
||||
{
|
||||
|
||||
AssignmentEditDialog::AssignmentEditDialog(QWidget *parent)
|
||||
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
|
||||
, m_requestHelper(new LtsUtils::RequestHelper(this))
|
||||
, m_ui(new Ui::AssignmentEdit)
|
||||
, m_logger(getLogger("AssignmentEditDialog"))
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
AssignmentEditDialog::~AssignmentEditDialog()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void AssignmentEditDialog::retranslate()
|
||||
{
|
||||
translate(m_ui, m_assignment, tr("ShootbackAreaAssignment"));
|
||||
}
|
||||
|
||||
bool AssignmentEditDialog::init(const std::shared_ptr<TargetManagement::Interface::Dtc> &dtc,
|
||||
const std::shared_ptr<TargetManagement::Interface::Ftc> &ftc,
|
||||
AssignmentParticipantModel *assignmentParticipantModel,
|
||||
const TargetManagement::TargetAreaAssignment &assignment)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "AssignmentEditDialog::init(), assignment=" << assignment;
|
||||
|
||||
if (!dtc || !ftc)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "AssignmentEditDialog::init() Invalid shared_ptr!";
|
||||
return false;
|
||||
}
|
||||
|
||||
m_dtc = dtc;
|
||||
m_ftc = ftc;
|
||||
m_assignmentParticipantModel = assignmentParticipantModel;
|
||||
|
||||
initCmbParticipants();
|
||||
connect(m_assignmentParticipantModel, &AssignmentParticipantModel::signalParticipantNamesChanged,
|
||||
this, &AssignmentEditDialog::initCmbParticipants);
|
||||
|
||||
initCmbAreas();
|
||||
|
||||
// configuration
|
||||
initCmbPreWarningEffect();
|
||||
initCmbTimeToEffectEffect();
|
||||
|
||||
//HACK as close is not allowed directly
|
||||
// connect(m_buttonBox->getButton(LtsWidgets::DialogButton::Close), &QPushButton::clicked, this, &ParticipantEditItem::close);
|
||||
connect(m_buttonBox->getButton(LtsWidgets::DialogButton::Apply), &QPushButton::clicked, this, &AssignmentEditDialog::readyToClose);
|
||||
|
||||
|
||||
// comboBoxes are filled, set data now
|
||||
setData(assignment);
|
||||
|
||||
setOnlineHelpFilename(QStringLiteral("Situation-Targets"));
|
||||
|
||||
// if (m_assignment.id() <= 0)
|
||||
// slotChangesMade();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AssignmentEditDialog::lockTargetParticipantAndArea()
|
||||
{
|
||||
m_ui->cmbParticipants->setEnabled(false);
|
||||
m_ui->cmbAreas->setEnabled(false);
|
||||
}
|
||||
|
||||
void AssignmentEditDialog::initCmbParticipants()
|
||||
{
|
||||
m_ui->cmbParticipants->clear();
|
||||
|
||||
if (!m_assignmentParticipantModel)
|
||||
return;
|
||||
|
||||
QSignalBlocker sb(m_ui->cmbParticipants); // pause tooltip update
|
||||
|
||||
m_ui->cmbParticipants->addItem(QStringLiteral("-"), 0); // to remove association
|
||||
|
||||
const auto hierarchies(m_assignmentParticipantModel->getParticipantHierarchies());
|
||||
const auto decorations(m_assignmentParticipantModel->getParticipantDecorations());
|
||||
for (auto it = hierarchies.begin(); it != hierarchies.end(); ++it)
|
||||
{
|
||||
const int participantId = it.key();
|
||||
const QString hierarchy(it.value());
|
||||
|
||||
// for Editing it´s neseccary to have all items in the comboBox:
|
||||
// if (!m_assignmentParticipantModel->getAssociatedParticipantIds().contains(participantId) || m_assignment.targetParticipantId() == participantId)
|
||||
{
|
||||
const QPixmap &pm = decorations.value(participantId);
|
||||
|
||||
m_ui->cmbParticipants->addItem(QIcon(pm), hierarchy, participantId);
|
||||
|
||||
// Tooltip:
|
||||
int idx = m_ui->cmbParticipants->findData(participantId);
|
||||
QString tooltip(QStringLiteral("<html>"));
|
||||
// without a temporary file:
|
||||
QByteArray baData;
|
||||
QBuffer buffer(&baData);
|
||||
pm.save(&buffer, "PNG", 100);
|
||||
tooltip.append(QStringLiteral("<center><img src='data:image/png;base64,%1'></center>").arg(QString::fromLatin1(baData.toBase64()))); // how can i center the image?
|
||||
|
||||
#ifndef LTS_DEBUG
|
||||
if (QGuiApplication::keyboardModifiers().testFlag(Qt::KeyboardModifier::ShiftModifier))
|
||||
#endif
|
||||
tooltip.append(QStringLiteral("<center>id=%1</center>").arg(participantId));
|
||||
|
||||
tooltip.append(QStringLiteral("</html>"));
|
||||
m_ui->cmbParticipants->setItemData(idx, tooltip, Qt::ToolTipRole);
|
||||
}
|
||||
}
|
||||
|
||||
int newIdx = m_ui->cmbParticipants->findData(m_assignment.targetParticipantId());
|
||||
if (newIdx >= 0)
|
||||
m_ui->cmbParticipants->setCurrentIndex(newIdx);
|
||||
m_ui->cmbParticipants->model()->sort(0);
|
||||
|
||||
m_ui->cmbParticipants->setIconSize(QSize(50, 50));
|
||||
connect(m_ui->cmbParticipants, QOverload<int>::of(&LtsWidgets::LtsComboBox::currentIndexChanged),
|
||||
this, &AssignmentEditDialog::onCmbParticipantsChanged, Qt::UniqueConnection);
|
||||
onCmbParticipantsChanged();
|
||||
}
|
||||
|
||||
void AssignmentEditDialog::fillCmbEffect(QComboBox *cmb)
|
||||
{
|
||||
if (!cmb)
|
||||
return;
|
||||
cmb->addItem(tr("Near Miss"), TargetManagement::Effect_def::NearMiss);
|
||||
cmb->addItem(tr("Mobility Kill"), TargetManagement::Effect_def::MobilityKill);
|
||||
cmb->addItem(tr("WeaponK ill"), TargetManagement::Effect_def::WeaponKill);
|
||||
cmb->setCurrentIndex(0);
|
||||
}
|
||||
|
||||
void AssignmentEditDialog::initCmbPreWarningEffect()
|
||||
{
|
||||
QComboBox *cmb = m_ui->cmb_preWarningEffect;
|
||||
fillCmbEffect(cmb);
|
||||
|
||||
int newIdx = cmb->findData(m_assignment.configuration().effect1().underlying());
|
||||
if (newIdx >= 0)
|
||||
cmb->setCurrentIndex(newIdx);
|
||||
}
|
||||
|
||||
void AssignmentEditDialog::initCmbTimeToEffectEffect()
|
||||
{
|
||||
QComboBox *cmb = m_ui->cmb_timeToEffectEffect;
|
||||
fillCmbEffect(cmb);
|
||||
|
||||
int newIdx = cmb->findData(m_assignment.configuration().effect2().underlying());
|
||||
if (newIdx >= 0)
|
||||
cmb->setCurrentIndex(newIdx);
|
||||
}
|
||||
|
||||
|
||||
void AssignmentEditDialog::initCmbAreas()
|
||||
{
|
||||
m_ui->cmbAreas->clear();
|
||||
|
||||
auto cb = [this](const TargetManagement::ShootbackArea & area)
|
||||
{
|
||||
m_ui->cmbAreas->addItem(QString::fromStdString(area.name()), area.id());
|
||||
};
|
||||
m_dtc->shootbackAreas(cb);
|
||||
}
|
||||
|
||||
//slots
|
||||
void AssignmentEditDialog::onCmbParticipantsChanged()
|
||||
{
|
||||
const auto decorations(m_assignmentParticipantModel->getParticipantDecorations());
|
||||
int participantId = m_ui->cmbParticipants->currentData().toInt();
|
||||
const auto it = decorations.find(participantId);
|
||||
if (it != decorations.constEnd())
|
||||
{
|
||||
const QPixmap &pm = decorations.value(it.key());
|
||||
{
|
||||
QString tooltip(QStringLiteral("<html>"));
|
||||
QByteArray data;
|
||||
QBuffer buffer(&data);
|
||||
// XML-Symbol with scale = 4 will produce huge images. Limit the size:
|
||||
pm.save(&buffer, "PNG", 100);
|
||||
|
||||
tooltip += QStringLiteral("<center>");
|
||||
tooltip += QStringLiteral("<img src='data:image/png;base64,%1'>").arg(QString::fromLatin1(data.toBase64()));
|
||||
tooltip += QStringLiteral("</center>");
|
||||
|
||||
#ifndef LTS_DEBUG
|
||||
if (QGuiApplication::keyboardModifiers().testFlag(Qt::KeyboardModifier::ShiftModifier))
|
||||
#endif
|
||||
tooltip.append(QStringLiteral("<center>id=%1</center>").arg(participantId));
|
||||
|
||||
tooltip += QStringLiteral("</html>");
|
||||
m_ui->cmbParticipants->setToolTip(tooltip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool AssignmentEditDialog::apply()
|
||||
{
|
||||
// name:
|
||||
m_assignment.name(m_ui->leName->text().toStdString());
|
||||
|
||||
// selected participant:
|
||||
int32_t participantId = m_ui->cmbParticipants->currentData().toInt();
|
||||
m_assignment.targetParticipantId(participantId);
|
||||
|
||||
// selected area:
|
||||
m_assignment.areaId(m_ui->cmbAreas->currentData().toInt());
|
||||
|
||||
// configuration:
|
||||
{
|
||||
ShootbackConfiguration &configRef = m_assignment.configuration();
|
||||
configRef.interval1(m_ui->sb_preWarningInterval->value());
|
||||
configRef.effect1( static_cast<Effect::inner_enum>(m_ui->cmb_preWarningEffect->currentData().toInt()) );
|
||||
configRef.flash1(m_ui->cb_flashAfterExpiration_1->isChecked());
|
||||
|
||||
configRef.interval2(m_ui->sb_timeToEffectInterval->value());
|
||||
configRef.effect2( static_cast<Effect::inner_enum>(m_ui->cmb_timeToEffectEffect->currentData().toInt()) );
|
||||
configRef.flash2(m_ui->cb_flashAfterExpiration_2->isChecked());
|
||||
}
|
||||
|
||||
emit updateItem(m_assignment);
|
||||
|
||||
emit readyToClose();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//private
|
||||
|
||||
void AssignmentEditDialog::setData(const TargetAreaAssignment &assignment)
|
||||
{
|
||||
m_assignment = assignment;
|
||||
|
||||
m_ui->leName->setText(QString::fromStdString(assignment.name()));
|
||||
|
||||
// update combo box:
|
||||
{
|
||||
int newIdx = m_ui->cmbParticipants->findData(m_assignment.targetParticipantId());
|
||||
if (newIdx >= 0)
|
||||
m_ui->cmbParticipants->setCurrentIndex(newIdx);
|
||||
}
|
||||
|
||||
// update combo box:
|
||||
{
|
||||
int newIdx = m_ui->cmbAreas->findData(m_assignment.areaId());
|
||||
if (newIdx >= 0)
|
||||
m_ui->cmbAreas->setCurrentIndex(newIdx);
|
||||
}
|
||||
|
||||
// Shootback-/Behaviour-configuration
|
||||
const ShootbackConfiguration &config = assignment.configuration();
|
||||
{
|
||||
m_ui->sb_preWarningInterval->setValue(config.interval1());
|
||||
m_ui->cb_flashAfterExpiration_1->setChecked(config.flash1());
|
||||
int newIdx = m_ui->cmb_preWarningEffect->findData(config.effect1().underlying());
|
||||
if (newIdx >= 0)
|
||||
m_ui->cmb_preWarningEffect->setCurrentIndex(newIdx);
|
||||
}
|
||||
|
||||
{
|
||||
m_ui->sb_timeToEffectInterval->setValue(config.interval2());
|
||||
m_ui->cb_flashAfterExpiration_2->setChecked(config.flash1());
|
||||
int newIdx = m_ui->cmb_timeToEffectEffect->findData(config.effect2().underlying());
|
||||
if (newIdx >= 0)
|
||||
m_ui->cmb_timeToEffectEffect->setCurrentIndex(newIdx);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Executable
+79
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* TargetManagement - Target Edit Dialog
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Norbert Thoden, NLE, 2020-05-29
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LtsWidgets/lts_dialog.h>
|
||||
|
||||
#include <Services/TargetManagement/tgt_dtc.h>
|
||||
#include <Services/TargetManagement/tgt_ftc.h>
|
||||
|
||||
#include <TargetManagement/logger.h>
|
||||
#include <LtsUtilsGuiDds/request_helper.h>
|
||||
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class AssignmentEdit;
|
||||
}
|
||||
|
||||
namespace TargetManagement
|
||||
{
|
||||
class AssignmentParticipantModel;
|
||||
|
||||
class AssignmentEditDialog : public LtsWidgets::LtsDialog,
|
||||
protected TargetManagement::Interface::Ftc::TargetAreaAssignmentModifyReplyHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AssignmentEditDialog(QWidget *parent = nullptr);
|
||||
~AssignmentEditDialog();
|
||||
|
||||
bool init(const std::shared_ptr<TargetManagement::Interface::Dtc> &dtc,
|
||||
const std::shared_ptr<TargetManagement::Interface::Ftc> &ftc,
|
||||
AssignmentParticipantModel *assignmentParticipantModel,
|
||||
const TargetAreaAssignment &assignment = TargetAreaAssignment());
|
||||
|
||||
void lockTargetParticipantAndArea();
|
||||
|
||||
//virtual functions from TargetManagement::Interface::Ftc::..
|
||||
void onTargetAreaAssignmentModifyReply(const Core::FunctionReplyObject &replyObject) override { m_requestHelper->requestReply(replyObject); }
|
||||
|
||||
Q_SIGNALS:
|
||||
void readyToClose();
|
||||
// void addItem(const QModelIndex &parent, const ParticipantData &newData);
|
||||
void updateItem(const TargetAreaAssignment &assignment);
|
||||
|
||||
public Q_SLOTS:
|
||||
void initCmbParticipants();
|
||||
void initCmbPreWarningEffect();
|
||||
void initCmbTimeToEffectEffect();
|
||||
void initCmbAreas();
|
||||
|
||||
private Q_SLOTS:
|
||||
void onCmbParticipantsChanged();
|
||||
|
||||
private:
|
||||
void fillCmbEffect(QComboBox *cmb);
|
||||
void setData(const TargetAreaAssignment &assignment);
|
||||
bool apply() override;
|
||||
void retranslate() override;
|
||||
|
||||
TargetAreaAssignment m_assignment;
|
||||
AssignmentParticipantModel *m_assignmentParticipantModel{nullptr};
|
||||
|
||||
std::shared_ptr<TargetManagement::Interface::Dtc> m_dtc;
|
||||
std::shared_ptr<TargetManagement::Interface::Ftc> m_ftc;
|
||||
LtsUtils::RequestHelper *m_requestHelper{nullptr};
|
||||
Ui::AssignmentEdit *m_ui{nullptr};
|
||||
LOGGER_T m_logger;
|
||||
};
|
||||
|
||||
} //namespace TargetManagement
|
||||
Executable
+152
@@ -0,0 +1,152 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AssignmentEdit</class>
|
||||
<widget class="QWidget" name="AssignmentEdit">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>963</width>
|
||||
<height>318</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="label_assoArea">
|
||||
<property name="text">
|
||||
<string>Area</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label_assoParticipant">
|
||||
<property name="text">
|
||||
<string>Target/Participant:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLineEdit" name="leName"/>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="lbl_name">
|
||||
<property name="text">
|
||||
<string>Name:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="LtsWidgets::LtsComboBox" name="cmbAreas"/>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="LtsWidgets::LtsComboBox" name="cmbParticipants"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>221</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="3" rowspan="3">
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4" rowspan="3">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="lb_preWarningInterval">
|
||||
<property name="text">
|
||||
<string>Pre-Warning Interval [sec]:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="sb_preWarningInterval"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="cb_flashAfterExpiration_1">
|
||||
<property name="text">
|
||||
<string>Flash after expiration</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="lb_preWarningEffect">
|
||||
<property name="text">
|
||||
<string>Pre-Warning Effekt:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="cmb_preWarningEffect"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="lb_timeToEffectInterval">
|
||||
<property name="text">
|
||||
<string>Time-To-Effect Interval [sec]:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QSpinBox" name="sb_timeToEffectInterval"/>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QCheckBox" name="cb_flashAfterExpiration_2">
|
||||
<property name="text">
|
||||
<string>Flash after expiration</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="lb_timeToEffectEffect">
|
||||
<property name="text">
|
||||
<string>Time-to-Effect Effect:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QComboBox" name="cmb_timeToEffectEffect"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="5">
|
||||
<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>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>LtsWidgets::LtsComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>LtsWidgets/lts_combo_box.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>leName</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
+188
@@ -0,0 +1,188 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Gui Plugin for TargetManagement
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Norbert Thoden, NLE, 2020-05-29
|
||||
*/
|
||||
|
||||
#include "tgt_target_gui_plugin.h"
|
||||
#include "tgt_target_part_dialog.h"
|
||||
#include "tgt_target_area_assignment_dialog.h"
|
||||
#include "tgt_area_dialog.h"
|
||||
|
||||
#include <LtsSession/lts_session.h>
|
||||
#include <LtsWidgets/lts_base_layout_widget.h>
|
||||
|
||||
//#include <Services/ParticipantManagement/ppm_operator_rights.h>
|
||||
|
||||
|
||||
namespace TargetManagement
|
||||
{
|
||||
|
||||
const char s_targetAreaAssignmentIdentifier[] = "tgtAssignments";
|
||||
|
||||
|
||||
std::shared_ptr<GuiPluginBase::Interface> GuiPlugin::createGuiInterface(LtsSession::LtsSession *session)
|
||||
{
|
||||
return std::make_shared<InterfaceImpl>(session);
|
||||
}
|
||||
|
||||
|
||||
InterfaceImpl::InterfaceImpl(LtsSession::LtsSession *session)
|
||||
: GuiPluginBase::Interface(session, getLogger("Plugins.Gui.Tgt.Target"))
|
||||
{}
|
||||
|
||||
|
||||
bool InterfaceImpl::fetchInterfaces()
|
||||
{
|
||||
if (!m_session->getDtc<TargetManagement::DataInterface>(m_dtc))
|
||||
return false;
|
||||
if (!m_session->getFtc<TargetManagement::DataInterface>(m_ftc))
|
||||
return false;
|
||||
|
||||
if (!m_session->getDtc<ParticipantManagement::DataInterface>(m_ppmDtc))
|
||||
return false;
|
||||
|
||||
if (!m_session->getForeignGuiInterface<ParticipantManagement::ForeignGuiComboboxInterface>(m_ppmGuiCbxIfc))
|
||||
return false;
|
||||
|
||||
if (!m_session->getForeignGuiInterface<FileManagement::ForeignGuiInterface>(m_flmGui))
|
||||
return false;
|
||||
|
||||
if (!m_session->getForeignGuiInterface<SituationMap::ForeignGuiInterface>(m_sitMapGuiIfc))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void InterfaceImpl::clearInterfaces()
|
||||
{
|
||||
m_dtc = nullptr;
|
||||
m_ftc = nullptr;
|
||||
}
|
||||
|
||||
QString InterfaceImpl::menuGroup() const
|
||||
{
|
||||
return tr("Participants / Targets");
|
||||
}
|
||||
|
||||
|
||||
QVector<LtsWidgets::PluginData> InterfaceImpl::getActions()
|
||||
{
|
||||
QVector<LtsWidgets::PluginData> ret;
|
||||
|
||||
LtsWidgets::PluginData plData;
|
||||
plData.menuGroup = menuGroup();
|
||||
|
||||
//
|
||||
// "TargetBaseConfiguration"
|
||||
//
|
||||
plData.menuText = tr("Assign/Configure Targets"); // BaseConfiguration like ActivateLaserDesignation...
|
||||
plData.identifier = QLatin1String("tgtTargetBaseConfiguration");
|
||||
plData.menuIcon = QIcon(QLatin1String("icon:target.svg"));
|
||||
// plData.operatorRight = OperatorRights::PartyEdit::PartiesShow;
|
||||
plData.exercisePart = LtsWidgets::ExercisePart::ePlanning;
|
||||
plData.createWidgetFunc = [this](QWidget * parent)
|
||||
{
|
||||
return onShowTargetBaseConfiguration(parent);
|
||||
};
|
||||
ret.append(plData);
|
||||
|
||||
|
||||
if (m_session->app() == LtsAppDescriptor::App::Shootback)
|
||||
{
|
||||
|
||||
//
|
||||
// "ShootbackApp"
|
||||
//
|
||||
plData.menuText = tr("Configure Shootback");
|
||||
plData.identifier = QLatin1String("tgtAssignConfigureTarget");
|
||||
plData.menuIcon = QIcon(QLatin1String("icon:party_edit.svg"));
|
||||
// plData.operatorRight = OperatorRights::PartyEdit::PartiesShow;
|
||||
plData.exercisePart = LtsWidgets::ExercisePart::ePlanning;
|
||||
plData.createWidgetFunc = [this](QWidget * parent)
|
||||
{
|
||||
return onShowTargets(parent);
|
||||
};
|
||||
ret.append(plData);
|
||||
|
||||
plData.menuText = tr("Shootback Overview"); //areaId
|
||||
plData.identifier = QLatin1String(s_targetAreaAssignmentIdentifier);
|
||||
plData.menuIcon = QIcon(QLatin1String("icon:party_edit.svg"));
|
||||
// plData.operatorRight = OperatorRights::PartyEdit::PartiesShow;
|
||||
plData.exercisePart = LtsWidgets::ExercisePart::ePlanning;
|
||||
plData.createWidgetFunc = [this](QWidget * parent)
|
||||
{
|
||||
return onShowTargetAreaAssignment(parent);
|
||||
};
|
||||
|
||||
ret.append(plData);
|
||||
|
||||
plData.menuText = tr("Configure Areas");
|
||||
plData.identifier = QLatin1String("tgtAreas");
|
||||
plData.menuIcon = QIcon(QLatin1String("icon:party_edit.svg"));
|
||||
// plData.operatorRight = OperatorRights::PartyEdit::PartiesShow;
|
||||
plData.exercisePart = LtsWidgets::ExercisePart::ePlanning;
|
||||
plData.createWidgetFunc = [this](QWidget * parent)
|
||||
{
|
||||
return onShowAreas(parent);
|
||||
};
|
||||
ret.append(plData);
|
||||
|
||||
} // if (m_session->app() == LtsAppDescriptor::App::Shootback)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
LtsWidgets::LtsDialog *InterfaceImpl::onShowTargetBaseConfiguration(QWidget *parent)
|
||||
{
|
||||
TargetPartDialog *dlg = new TargetPartDialog(menuGroup(), m_session, parent);
|
||||
if (!dlg->init(TargetPartDialog::MODE::TARGET_BASE_CONFIGURATION))
|
||||
{
|
||||
dlg->deleteLater();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const QString identifier(QStringLiteral("tgtTargetBaseConfigurationXX"));
|
||||
if (!m_session->addWidget(dlg, menuGroup(), identifier, LtsWidgets::LayoutArea::eDialogTab))
|
||||
dlg->deleteLater();
|
||||
|
||||
return dlg;
|
||||
}
|
||||
|
||||
LtsWidgets::LtsDialog *InterfaceImpl::onShowTargets(QWidget *parent)
|
||||
{
|
||||
TargetPartDialog *dlg = new TargetPartDialog(menuGroup(), m_session, parent);
|
||||
if (!dlg->init(TargetPartDialog::MODE::TARGET_OVERVIEW))
|
||||
{
|
||||
dlg->deleteLater();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const QString identifier(QStringLiteral("tgtAssignConfigureTargetXX"));
|
||||
if (!m_session->addWidget(dlg, menuGroup(), identifier, LtsWidgets::LayoutArea::eDialogTab))
|
||||
dlg->deleteLater();
|
||||
|
||||
return dlg;
|
||||
}
|
||||
|
||||
LtsWidgets::LtsDialog *InterfaceImpl::onShowTargetAreaAssignment(QWidget *parent)
|
||||
{
|
||||
// init with parameter
|
||||
m_targetAreaAssignmentDialog = LtsWidgets::initDialog(new AssignmentDialog(menuGroup(), m_session, parent));
|
||||
return m_targetAreaAssignmentDialog;
|
||||
}
|
||||
|
||||
LtsWidgets::LtsDialog *InterfaceImpl::onShowAreas(QWidget *parent)
|
||||
{
|
||||
// init without parameter
|
||||
return LtsWidgets::initDialog(new AreaDialog(menuGroup(), m_session, parent));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace TargetManagement
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Gui Plugin for TargetManagement
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Norbert Thoden, NLE, 2020-05-29
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <TargetManagement/logger.h>
|
||||
#include <TargetManagement/tgt_dtc.h>
|
||||
#include <TargetManagement/tgt_ftc.h>
|
||||
|
||||
#include <PluginInterfaces/gui_plugin_interface.h>
|
||||
#include <Plugins/TargetManagement/tgt_data_plugin_interface.h>
|
||||
#include <Plugins/TargetManagement/tgt_target_gui_plugin_interface.h>
|
||||
#include <Plugins/FileManagement/flm_explorer_gui_plugin_interface.h>
|
||||
#include <Plugins/ParticipantManagement/ppm_data_plugin_interface.h>
|
||||
#include <Plugins/ParticipantManagement/ppm_gui_combobox_plugin_interface.h>
|
||||
#include <Plugins/SituationMapPlugin/situation_map_gui_plugin_interface.h>
|
||||
|
||||
namespace TargetManagement
|
||||
{
|
||||
// forward:
|
||||
class AssignmentDialog;
|
||||
|
||||
|
||||
class GuiPlugin final : public QObject, public GuiPluginBase::Plugin
|
||||
{
|
||||
Q_PLUGIN_METADATA(IID "gui:3:tgt.shootbacktarget")
|
||||
Q_INTERFACES(GuiPluginBase::Plugin)
|
||||
|
||||
Q_OBJECT
|
||||
public:
|
||||
GuiPlugin() = default;
|
||||
~GuiPlugin() = default;
|
||||
|
||||
QString pluginName() override { return QStringLiteral("TargetManagement.GuiPlugin.ShootbackTarget"); }
|
||||
std::shared_ptr<GuiPluginBase::Interface> createGuiInterface(LtsSession::LtsSession *session) override;
|
||||
bool availableInPartition(IDL::PartitionType partition) const override
|
||||
{
|
||||
return (partition == IDL::PartitionType::Global ||
|
||||
partition == IDL::PartitionType::Exercise);
|
||||
}
|
||||
};
|
||||
|
||||
class InterfaceImpl final : public QObject, public GuiPluginBase::Interface
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit InterfaceImpl(LtsSession::LtsSession *session);
|
||||
|
||||
bool fetchInterfaces() override;
|
||||
void clearInterfaces() override;
|
||||
QString menuGroup() const override;
|
||||
QVector<LtsWidgets::PluginData> getActions() override;
|
||||
bool availableInPartition(IDL::PartitionType partition) const override
|
||||
{
|
||||
return partition == IDL::PartitionType::Global ||
|
||||
partition == IDL::PartitionType::Exercise;
|
||||
}
|
||||
|
||||
private:
|
||||
LtsWidgets::LtsDialog *onShowTargetBaseConfiguration(QWidget *parent);
|
||||
LtsWidgets::LtsDialog *onShowTargets(QWidget *parent);
|
||||
LtsWidgets::LtsDialog *onShowTargetAreaAssignment(QWidget *parent);
|
||||
LtsWidgets::LtsDialog *onShowAreas(QWidget *parent);
|
||||
|
||||
QPointer<AssignmentDialog> m_targetAreaAssignmentDialog;
|
||||
|
||||
|
||||
std::shared_ptr<TargetManagement::Interface::Dtc> m_dtc;
|
||||
std::shared_ptr<TargetManagement::Interface::Ftc> m_ftc;
|
||||
std::shared_ptr<ParticipantManagement::Interface::Dtc> m_ppmDtc;
|
||||
std::shared_ptr<ParticipantManagement::ForeignGuiComboboxInterface> m_ppmGuiCbxIfc;
|
||||
std::shared_ptr<FileManagement::ForeignGuiInterface> m_flmGui;
|
||||
std::shared_ptr<SituationMap::ForeignGuiInterface> m_sitMapGuiIfc;
|
||||
};
|
||||
|
||||
|
||||
} // namespace TargetManagement
|
||||
+557
@@ -0,0 +1,557 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Target Configuration
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Norbert Thoden, NLE, 2020-06-29
|
||||
*/
|
||||
|
||||
#include "tgt_target_part_dialog.h"
|
||||
#include "ui_tgt_target_part_dialog.h"
|
||||
#include "tgt_shootback_target_edit.h"
|
||||
#include "tgt_telegrams.h"
|
||||
#include <LtsSession/lts_session_data.h>
|
||||
#include <FileManagement/flm_translation.h>
|
||||
|
||||
#include <PluginInterfaces/gui_plugin_interface.h>
|
||||
#include <Plugins/TargetManagement/tgt_data_plugin_interface.h>
|
||||
#include <Plugins/FileManagement/flm_explorer_gui_plugin_interface.h>
|
||||
#include <Plugins/ParticipantManagement/ppm_data_plugin_interface.h>
|
||||
#include <Plugins/ParticipantManagement/ppm_gui_combobox_plugin_interface.h>
|
||||
#include <Plugins/SituationMapPlugin/situation_map_gui_plugin_interface.h>
|
||||
|
||||
#include "tgt_target_area_assignment_dialog.h"
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
namespace TargetManagement
|
||||
{
|
||||
|
||||
TargetPartDialog::TargetPartDialog(const QString &menuGroup, LtsSession::LtsSession *session, QWidget *parent)
|
||||
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
|
||||
, m_session(session)
|
||||
, m_ui(new Ui::TargetPartDialog)
|
||||
, m_menuGroup(menuGroup)
|
||||
, m_requestHelper(new LtsUtils::RequestHelper(this))
|
||||
, m_logger(getLogger("TargetPartDialog"))
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
setOnlineHelpFilename(QStringLiteral("Situation-Assign/Configure_Targets"));
|
||||
}
|
||||
|
||||
TargetPartDialog::~TargetPartDialog()
|
||||
{
|
||||
clearSelectionOfMapObjects();
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
bool TargetPartDialog::init(TargetManagement::TargetPartDialog::MODE mode)
|
||||
{
|
||||
if (!m_session)
|
||||
return false;
|
||||
|
||||
if (!m_session->getDtc<TargetManagement::DataInterface>(m_dtc))
|
||||
return false;
|
||||
if (!m_session->getFtc<TargetManagement::DataInterface>(m_ftc))
|
||||
return false;
|
||||
if (!m_session->getDtc<ParticipantManagement::DataInterface>(m_ppmDtc))
|
||||
return false;
|
||||
if (!m_session->getForeignGuiInterface<ParticipantManagement::ForeignGuiComboboxInterface>(m_ppmGuiCbxIfc))
|
||||
return false;
|
||||
if (!m_session->getForeignGuiInterface<FileManagement::ForeignGuiInterface>(m_flmGui))
|
||||
return false;
|
||||
if (!m_session->getForeignGuiInterface<SituationMap::ForeignGuiInterface>(m_sitMapGuiIfc))
|
||||
return false;
|
||||
|
||||
// initialize model:
|
||||
INFO_LOG(m_logger) << "TargetPartDialog::init";
|
||||
m_targetParticipantModel = new TargetParticipantModel(this);
|
||||
m_targetParticipantModel->initModel(m_dtc, m_ppmDtc, m_ppmGuiCbxIfc, m_session);
|
||||
|
||||
// proxyModel:
|
||||
auto proxyModel = new TargetParticipantProxyModel(this);
|
||||
proxyModel->setSourceModel(m_targetParticipantModel);
|
||||
proxyModel->setDynamicSortFilter(false);
|
||||
|
||||
// set view: (LtsDataView)
|
||||
m_ui->widget->setModel(m_targetParticipantModel);
|
||||
|
||||
// to allow remove off some rows at once. Anoying in all other cases -> stay at singleSelection
|
||||
// m_ui->widget->setSelectionMode(QAbstractItemView::SelectionMode::MultiSelection);
|
||||
|
||||
m_assignAreaBtn = m_buttonBox->getButton(LtsWidgets::DialogButton::Import);
|
||||
m_buttonBox->connectButton(LtsWidgets::DialogButton::Import, this, &TargetPartDialog::onAssignAreaClicked);
|
||||
|
||||
// connects for gui
|
||||
connect(m_ui->widget, &LtsDataView::LtsDataView::signalSelectionChanged,
|
||||
this, &TargetPartDialog::onSelectionChanged);
|
||||
connect(m_ui->widget, &LtsDataView::LtsDataView::signalDoubleClicked,
|
||||
this, &TargetPartDialog::onEditTargetPart);
|
||||
connect(this, &TargetPartDialog::escapePressed, this,
|
||||
&TargetPartDialog::onEscapePressed, Qt::UniqueConnection);
|
||||
|
||||
// Create Add-Button
|
||||
m_buttonBox->setButtonVisible(LtsWidgets::DialogButton::Add, true);
|
||||
m_buttonBox->connectButton(LtsWidgets::DialogButton::Add, this, &TargetPartDialog::onNewTargetPart);
|
||||
|
||||
// Create Remove-Button
|
||||
m_buttonBox->connectButton(LtsWidgets::DialogButton::Remove, this, &TargetPartDialog::onRemoveTargetPart);
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Remove, false);
|
||||
|
||||
// Create Modify-Button
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Edit, false);
|
||||
m_buttonBox->connectButton(LtsWidgets::DialogButton::Edit, this, &TargetPartDialog::onEditTargetPart);
|
||||
|
||||
// connect signals of TableView/CustomView:
|
||||
connect(m_ui->widget, &LtsDataView::LtsDataView::clicked, this, &TargetPartDialog::onTableViewClicked);
|
||||
// it´s possible to evaluate signalEntered, but seems to be overkill here:
|
||||
// connect(m_ui->widget, &LtsDataView::LtsDataView::signalEntered, this, &TargetPartDialog::onObjectEntered);
|
||||
|
||||
|
||||
#ifndef LTS_DEBUG
|
||||
m_ui->widget->hideColumn(TargetParticipantModel::Columns::Id);
|
||||
m_ui->widget->hideColumn(TargetParticipantModel::Columns::TargetPartipantId);
|
||||
#endif
|
||||
|
||||
// Save/Load from Library Button
|
||||
m_buttonBox->connectLibraryButton(this,
|
||||
&TargetPartDialog::onImportButtonClicked,
|
||||
&TargetPartDialog::onExportButtonClicked);
|
||||
if (!m_flmGui)
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Library, false);
|
||||
|
||||
// 'Map' Button(s)
|
||||
m_buttonBox->connectButton(LtsWidgets::DialogButton::CenterMap, this, &TargetPartDialog::onMapCenterClicked);
|
||||
m_buttonBox->connectButton(LtsWidgets::DialogButton::ZoomMapTo, this, &TargetPartDialog::onMapZoomToClicked);
|
||||
|
||||
// call eneDisa / onSelectionChanged once:
|
||||
onSelectionChanged();
|
||||
|
||||
setMode(mode);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TargetPartDialog::keyPressEvent(QKeyEvent *event)
|
||||
{
|
||||
if (event->key() == Qt::Key_Escape)
|
||||
emit escapePressed();
|
||||
return BaseClass::keyPressEvent(event);
|
||||
}
|
||||
|
||||
|
||||
void TargetPartDialog::setMode(TargetPartDialog::MODE mode)
|
||||
{
|
||||
m_mode = mode;
|
||||
switch (m_mode)
|
||||
{
|
||||
case MODE::TARGET_BASE_CONFIGURATION:
|
||||
m_assignAreaBtn->setVisible(false);
|
||||
break;
|
||||
|
||||
case MODE::TARGET_OVERVIEW:
|
||||
m_assignAreaBtn->setVisible(true);
|
||||
m_ui->widget->hideColumn(TargetParticipantModel::Columns::TargetPartipantId);
|
||||
|
||||
m_ui->widget->hideColumn(TargetParticipantModel::Columns::ActivateLaserDesignation);
|
||||
m_ui->widget->hideColumn(TargetParticipantModel::Columns::ActivateLights);
|
||||
m_ui->widget->hideColumn(TargetParticipantModel::Columns::ActivatePopupAutomatic);
|
||||
m_ui->widget->hideColumn(TargetParticipantModel::Columns::HitsToKill);
|
||||
m_ui->widget->hideColumn(TargetParticipantModel::Columns::PermanentInstalledTarget);
|
||||
m_ui->widget->hideColumn(TargetParticipantModel::Columns::VisibleParticipants);
|
||||
break;
|
||||
} // switch
|
||||
|
||||
m_buttonBox->setButtonVisible(LtsWidgets::DialogButton::Add, (m_mode == MODE::TARGET_BASE_CONFIGURATION));
|
||||
m_buttonBox->setButtonVisible(LtsWidgets::DialogButton::Edit, (m_mode == MODE::TARGET_BASE_CONFIGURATION));
|
||||
m_buttonBox->setButtonVisible(LtsWidgets::DialogButton::Remove, (m_mode == MODE::TARGET_BASE_CONFIGURATION));
|
||||
|
||||
m_buttonBox->setButtonVisible(LtsWidgets::DialogButton::Library, (m_mode == MODE::TARGET_BASE_CONFIGURATION));
|
||||
|
||||
m_buttonBox->setButtonVisible(LtsWidgets::DialogButton::CenterMap, m_sitMapGuiIfc && (m_mode == MODE::TARGET_BASE_CONFIGURATION));
|
||||
m_buttonBox->setButtonVisible(LtsWidgets::DialogButton::ZoomMapTo, m_sitMapGuiIfc && (m_mode == MODE::TARGET_BASE_CONFIGURATION));
|
||||
|
||||
}
|
||||
|
||||
void TargetPartDialog::retranslate()
|
||||
{
|
||||
switch (m_mode)
|
||||
{
|
||||
case MODE::TARGET_BASE_CONFIGURATION:
|
||||
translate(m_ui, tr("Assign/Configure Targets"));
|
||||
m_assignAreaBtn->setText(tr("Assign Area"));
|
||||
break;
|
||||
case MODE::TARGET_OVERVIEW:
|
||||
translate(m_ui, tr("Configure Shootback"));
|
||||
m_assignAreaBtn->setText(tr("Assign Area"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void TargetPartDialog::onNewTargetPart()
|
||||
{
|
||||
INFO_LOG(m_logger) << "onNewTargetPart";
|
||||
|
||||
ShootbackTargetEdit *dialog = new ShootbackTargetEdit(this);
|
||||
|
||||
if (!dialog->init(m_dtc, m_ftc, m_targetParticipantModel))
|
||||
{
|
||||
ERROR_LOG(m_logger) << QLatin1String("Can't initialize shootbackTargetEdit!");
|
||||
delete dialog;
|
||||
return;
|
||||
}
|
||||
addDialog(dialog, m_menuGroup, QStringLiteral("Add Target"), LtsWidgets::LayoutArea::eDialogTab, true, true);
|
||||
}
|
||||
|
||||
void TargetPartDialog::onRemoveTargetPart()
|
||||
{
|
||||
const QModelIndexList &selectedRows = m_ui->widget->selectedRows();
|
||||
for (const auto &mi : selectedRows)
|
||||
{
|
||||
Core::RemoveElementRequest req;
|
||||
req.id(m_targetParticipantModel->getRowData(mi.row()).id());
|
||||
m_requestHelper->addRequest([req, this]()
|
||||
{
|
||||
return m_ftc->shootbackTargetRemoveRequest(req, this);
|
||||
});
|
||||
}
|
||||
m_requestHelper->startRequests();
|
||||
}
|
||||
|
||||
void TargetPartDialog::onEditTargetPart()
|
||||
{
|
||||
if (m_mode == MODE::TARGET_OVERVIEW)
|
||||
return;
|
||||
|
||||
QModelIndexList selectedRows = m_ui->widget->selectedRows();
|
||||
if (selectedRows.isEmpty())
|
||||
return;
|
||||
const QModelIndex curIdx = selectedRows.first();
|
||||
if (!curIdx.isValid())
|
||||
return;
|
||||
INFO_LOG(m_logger) << " onEditTargetPart";
|
||||
|
||||
ShootbackTargetEdit *dialog = new ShootbackTargetEdit(this);
|
||||
|
||||
const TargetManagement::ShootbackTarget &tgt = m_targetParticipantModel->getRowData(curIdx.row());
|
||||
|
||||
if (!dialog->init(m_dtc, m_ftc, m_targetParticipantModel, tgt))
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << QLatin1String("Can't initialize shootbackTargetEdit!");
|
||||
delete dialog;
|
||||
return;
|
||||
}
|
||||
addDialog(dialog, m_menuGroup, QStringLiteral("Edit Target"), LtsWidgets::LayoutArea::eDialogTab, true, true);
|
||||
}
|
||||
|
||||
|
||||
QByteArray TargetPartDialog::toJson() const
|
||||
{
|
||||
QJsonObject obj;
|
||||
|
||||
// operatorId just for convenience:
|
||||
const int operatorId = LtsSessionData::LtsSessionData::getInstance()->getOperatorId();
|
||||
obj[QStringLiteral("OperatorId")] = operatorId;
|
||||
obj[QStringLiteral("XmlType")] = FileManagement::toString(FileManagement::XmlType::TGTShootbackTargetBaseConfiguration);
|
||||
|
||||
{
|
||||
const QVector<TargetManagement::ShootbackTarget> &modelData = m_targetParticipantModel->getData();
|
||||
QJsonArray jArray;
|
||||
for (const TargetManagement::ShootbackTarget &sbt : modelData)
|
||||
{
|
||||
ShootbackTargetData sbtd;
|
||||
sbtd.id = sbt.id();
|
||||
sbtd.name = QString::fromStdString(sbt.name());
|
||||
|
||||
sbtd.targetParticipantEquipmentNumber = -1;
|
||||
if (m_ppmDtc)
|
||||
{
|
||||
const ParticipantManagement::Participant &participant = m_ppmDtc->participant(sbt.targetParticipantId());
|
||||
if (participant.id() == sbt.targetParticipantId() &&
|
||||
participant.equipmentNumber().is_set())
|
||||
sbtd.targetParticipantEquipmentNumber = participant.equipmentNumber().get();
|
||||
}
|
||||
|
||||
sbtd.activateLaserDesignation = sbt.activateLaserDesignation();
|
||||
sbtd.activateLights = sbt.activateLights();
|
||||
sbtd.activatePopupAutomatic = sbt.activatePopupAutomatic();
|
||||
sbtd.hitsToKill = sbt.hitsToKill();
|
||||
sbtd.permanentInstalledTarget = sbt.permanentInstalledTarget();
|
||||
// volatile data: position, visibleParticipants -> do not save -> skip
|
||||
jArray.append(sbtd.toJson());
|
||||
}
|
||||
obj[QStringLiteral("ShootbackTargets")] = jArray;
|
||||
}
|
||||
QJsonDocument doc(obj);
|
||||
|
||||
DEBUG_LOG(m_logger) << " json = " << doc.toJson();
|
||||
|
||||
return doc.toJson(QJsonDocument::Compact);
|
||||
}
|
||||
|
||||
QVector<TargetManagement::ShootbackTarget> TargetPartDialog::fromJson(const QByteArray &content)
|
||||
{
|
||||
const QJsonDocument doc(QJsonDocument::fromJson(content));
|
||||
const QJsonObject obj(doc.object());
|
||||
|
||||
// operatorId just for convenience:
|
||||
const int operatorId = obj[QStringLiteral("operatorId")].toInt();
|
||||
Q_UNUSED(operatorId);
|
||||
|
||||
const QJsonArray &jArray = obj[QStringLiteral("ShootbackTargets")].toArray();
|
||||
QVector<TargetManagement::ShootbackTarget> vecData;
|
||||
vecData.reserve(jArray.size());
|
||||
for (const auto &item : jArray)
|
||||
{
|
||||
const ShootbackTargetData &sbtd = ShootbackTargetData::fromJson(item.toObject());
|
||||
TargetManagement::ShootbackTarget sbt;
|
||||
sbt.id(sbtd.id);
|
||||
sbt.name(sbtd.name.toStdString());
|
||||
|
||||
if (m_ppmDtc)
|
||||
sbt.targetParticipantId(m_ppmDtc->participantIdByEquipmentNumber(sbtd.targetParticipantEquipmentNumber));
|
||||
|
||||
sbt.activateLaserDesignation(sbtd.activateLaserDesignation);
|
||||
sbt.activateLights(sbtd.activateLights);
|
||||
sbt.activatePopupAutomatic(sbtd.activatePopupAutomatic);
|
||||
sbt.hitsToKill(sbtd.hitsToKill);
|
||||
sbt.permanentInstalledTarget(sbtd.permanentInstalledTarget);
|
||||
vecData.push_back(std::move(sbt));
|
||||
}
|
||||
return vecData;
|
||||
}
|
||||
|
||||
void TargetPartDialog::onEscapePressed()
|
||||
{
|
||||
m_ui->widget->clearSelection();
|
||||
}
|
||||
|
||||
void TargetPartDialog::onExportButtonClicked()
|
||||
{
|
||||
QByteArray byteArray = toJson();
|
||||
int fileId = m_flmGui->saveFileContent(this, FileManagement::FileType::Xml, m_session->exerciseId(), byteArray);
|
||||
if (fileId > 0)
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << "Saved file with id = " << fileId;
|
||||
else
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << "Could not save file in library ";
|
||||
}
|
||||
|
||||
void TargetPartDialog::onImportButtonClicked()
|
||||
{
|
||||
QHash<LtsWidgets::Button, QString> buttonTexts;
|
||||
buttonTexts.insert(LtsWidgets::Button::Ok, tr("Overwrite"));
|
||||
buttonTexts.insert(LtsWidgets::Button::Cancel, tr("Cancel"));
|
||||
|
||||
LtsWidgets::LtsMessageDialogNew *dlg = new LtsWidgets::LtsMessageDialogNew(this,
|
||||
tr("Overwrite existing data?"),
|
||||
tr("Load from Library"),
|
||||
LtsWidgets::Behaviour::Popup,
|
||||
LtsWidgets::Button::Ok | LtsWidgets::Button::Cancel,
|
||||
buttonTexts);
|
||||
connect(dlg, &LtsWidgets::LtsMessageDialogNew::ok,
|
||||
this, &TargetPartDialog::onImport);
|
||||
}
|
||||
|
||||
void TargetPartDialog::onImport()
|
||||
{
|
||||
INFO_LOG(m_logger) << LOGFUNCTION << "--- onImportButtonClicked() ";
|
||||
|
||||
QByteArray content;
|
||||
int fileId = m_flmGui->loadFileContent(this, content, {FileManagement::FileType::Xml},
|
||||
m_session->exerciseId(),
|
||||
FileManagement::toString(FileManagement::XmlType::TGTShootbackTargetBaseConfiguration));
|
||||
if (fileId > 0)
|
||||
{
|
||||
if (!m_flmGui->isXmlType(content, FileManagement::toString(FileManagement::XmlType::TGTShootbackTargetBaseConfiguration)))
|
||||
{
|
||||
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
|
||||
{
|
||||
// update svc via clear and (re-)insert:
|
||||
// 1) clear svc:
|
||||
const QVector<ShootbackTarget> &curData = m_targetParticipantModel->getData();
|
||||
for (auto item : curData)
|
||||
{
|
||||
Core::RemoveElementRequest req(item.id());
|
||||
m_requestHelper->addRequest([this, req]()
|
||||
{
|
||||
return m_ftc->shootbackTargetRemoveRequest(req, this);
|
||||
});
|
||||
}
|
||||
|
||||
// 2) re-insert:
|
||||
const QVector<TargetManagement::ShootbackTarget> vecDataCandidate(fromJson(content));
|
||||
for (ShootbackTarget shootbackTargetCandidate : vecDataCandidate)
|
||||
{
|
||||
shootbackTargetCandidate.id(0); // force create
|
||||
m_requestHelper->addRequest([this, shootbackTargetCandidate]()
|
||||
{
|
||||
return m_ftc->shootbackTargetModifyRequest(shootbackTargetCandidate, this);
|
||||
});
|
||||
}
|
||||
|
||||
// clear view *before* performing the requests:
|
||||
m_targetParticipantModel->clear();
|
||||
|
||||
m_requestHelper->startRequests();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TargetPartDialog::onAssignAreaClicked()
|
||||
{
|
||||
QModelIndexList selectedRows = m_ui->widget->selectedRows();
|
||||
if (selectedRows.isEmpty())
|
||||
return;
|
||||
const QModelIndex curIdx = selectedRows.first();
|
||||
if (!curIdx.isValid())
|
||||
return;
|
||||
|
||||
const int targetParticipantId = m_targetParticipantModel->getRowData(curIdx.row()).targetParticipantId();
|
||||
|
||||
// instead of emit a signal, create the according dialog frome here directly
|
||||
//emit assignAreasRequested(targetParticipantId);
|
||||
|
||||
auto dlg = new AssignmentDialog(menuGroup(), m_session, this->parentWidget());
|
||||
if (!dlg->init(AssignmentDialog::MODE::FILTERED_TO_SINGLE_TARGET_PARTICPANT, targetParticipantId))
|
||||
{
|
||||
dlg->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_session->addWidget(dlg, menuGroup(), QStringLiteral("ConfigureAreasToTargetParticipantId_%1").arg(targetParticipantId), LtsWidgets::LayoutArea::eDialogTab))
|
||||
dlg->deleteLater();
|
||||
}
|
||||
|
||||
|
||||
void TargetPartDialog::onMapCenterClicked()
|
||||
{
|
||||
if (!m_sitMapGuiIfc)
|
||||
return;
|
||||
QModelIndexList selectedRows = m_ui->widget->selectedRows();
|
||||
if (selectedRows.isEmpty())
|
||||
return;
|
||||
const QModelIndex curIdx = selectedRows.first();
|
||||
if (!curIdx.isValid())
|
||||
return;
|
||||
|
||||
const int pId = m_targetParticipantModel->getRowData(curIdx.row()).targetParticipantId();
|
||||
m_sitMapGuiIfc->centerMapToMapObject(SituationMap::MapObjectType::MOT_Participant, pId);
|
||||
}
|
||||
|
||||
void TargetPartDialog::onMapZoomToClicked()
|
||||
{
|
||||
QModelIndexList selectedRows = m_ui->widget->selectedRows();
|
||||
if (selectedRows.isEmpty())
|
||||
return;
|
||||
QModelIndex index = selectedRows.first();
|
||||
if (!index.isValid())
|
||||
return;
|
||||
|
||||
if (!m_targetParticipantModel || !m_sitMapGuiIfc)
|
||||
return;
|
||||
|
||||
int pId = m_targetParticipantModel->getRowData(index.row()).targetParticipantId();
|
||||
if (pId<=0)
|
||||
return;
|
||||
|
||||
// Assigned Areas:
|
||||
QVector<int> assignedAreas;
|
||||
auto cb = [pId, &assignedAreas](const TargetManagement::TargetAreaAssignment &assignment)
|
||||
{
|
||||
if (assignment.targetParticipantId() == pId)
|
||||
assignedAreas.push_back(assignment.areaId());
|
||||
};
|
||||
m_dtc->targetAreaAssignments(cb);
|
||||
|
||||
{
|
||||
QVector<QPair<SituationMap::MapObjectType, int>> entities;
|
||||
entities.reserve(assignedAreas.size()+1);
|
||||
entities.push_back({SituationMap::MapObjectType::MOT_Participant, pId});
|
||||
|
||||
for (auto item : assignedAreas)
|
||||
entities.push_back({SituationMap::MapObjectType::MOT_ShootbackArea, item});
|
||||
|
||||
m_sitMapGuiIfc->zoomMapTo(entities);
|
||||
}
|
||||
}
|
||||
|
||||
void TargetPartDialog::onObjectEntered(const QModelIndex &index)
|
||||
{
|
||||
if (!m_sitMapGuiIfc)
|
||||
return;
|
||||
if (!index.isValid())
|
||||
{
|
||||
m_sitMapGuiIfc->removeObjectIndicator();
|
||||
return;
|
||||
}
|
||||
int pId = m_targetParticipantModel->getRowData(index.row()).targetParticipantId();
|
||||
if (pId>0)
|
||||
{
|
||||
// Target/Participant
|
||||
m_sitMapGuiIfc->objectIndicatorToMapObject(SituationMap::MapObjectType::MOT_Participant, pId, true);
|
||||
|
||||
// Assigned Areas:
|
||||
QVector<int> assignedAreas;
|
||||
auto cb = [pId, &assignedAreas](const TargetManagement::TargetAreaAssignment &assignment)
|
||||
{
|
||||
if (assignment.targetParticipantId() == pId)
|
||||
assignedAreas.push_back(assignment.areaId());
|
||||
};
|
||||
m_dtc->targetAreaAssignments(cb);
|
||||
m_sitMapGuiIfc->setMapObjectSelected(SituationMap::MapObjectType::MOT_ShootbackArea, assignedAreas, true);
|
||||
}
|
||||
else
|
||||
m_sitMapGuiIfc->removeObjectIndicator();
|
||||
}
|
||||
|
||||
void TargetPartDialog::onTableViewClicked(const QModelIndex &index)
|
||||
{
|
||||
if (!index.isValid())
|
||||
return;
|
||||
|
||||
if (QGuiApplication::keyboardModifiers().testFlag(Qt::KeyboardModifier::ShiftModifier))
|
||||
onMapCenterClicked();
|
||||
}
|
||||
|
||||
void TargetPartDialog::clearSelectionOfMapObjects()
|
||||
{
|
||||
if (!m_sitMapGuiIfc)
|
||||
return;
|
||||
// remove MapObjectIndicator:
|
||||
m_sitMapGuiIfc->removeObjectIndicator();
|
||||
}
|
||||
|
||||
void TargetPartDialog::onSelectionChanged()
|
||||
{
|
||||
QModelIndexList selectedRows = m_ui->widget->selectedRows();
|
||||
const int cntSelectedRows = selectedRows.size();
|
||||
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Remove, cntSelectedRows == 1);
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Edit, cntSelectedRows == 1);
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::CenterMap, cntSelectedRows == 1);
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::ZoomMapTo, cntSelectedRows == 1);
|
||||
m_assignAreaBtn->setEnabled(cntSelectedRows == 1); // LtsWidgets::DialogButton::Library
|
||||
|
||||
if (selectedRows.isEmpty())
|
||||
onObjectEntered({}); // use invalid Idx to removeObjectIndicator
|
||||
else
|
||||
onObjectEntered(selectedRows.first());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
} // namespace TargetManagement
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Target Configuration
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Norbert Thoden, NLE, 2020-06-29
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LtsWidgets/lts_dialog.h>
|
||||
#include <TargetManagement/tgt_dtc.h>
|
||||
#include <TargetManagement/tgt_ftc.h>
|
||||
#include <ParticipantManagement/ppm_dtc.h>
|
||||
#include <LtsUtilsGuiDds/request_helper.h>
|
||||
#include <TargetManagement/logger.h>
|
||||
#include <Plugins/TargetManagement/Gui/ShootbackTargetConfiguration/tgt_target_part_model.h>
|
||||
#include <Plugins/FileManagement/flm_explorer_gui_plugin_interface.h>
|
||||
#include <Plugins/SituationMapPlugin/situation_map_gui_plugin_interface.h>
|
||||
|
||||
class QPushButton;
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class TargetPartDialog;
|
||||
}
|
||||
|
||||
namespace TargetManagement
|
||||
{
|
||||
|
||||
class TargetPartDialog final : public LtsWidgets::LtsDialog
|
||||
, protected TargetManagement::Interface::Ftc::ShootbackTargetModifyReplyHandler
|
||||
, protected TargetManagement::Interface::Ftc::ShootbackTargetRemoveReplyHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
using BaseClass = LtsWidgets::LtsDialog;
|
||||
|
||||
enum class MODE
|
||||
{
|
||||
TARGET_BASE_CONFIGURATION,
|
||||
TARGET_OVERVIEW
|
||||
};
|
||||
|
||||
explicit TargetPartDialog(const QString &menuGroup, LtsSession::LtsSession *session, QWidget *parent = nullptr);
|
||||
~TargetPartDialog();
|
||||
|
||||
bool init(MODE mode);
|
||||
|
||||
void retranslate() override;
|
||||
|
||||
Q_SIGNALS:
|
||||
void assignAreasRequested(int targetParticpantId);
|
||||
void escapePressed();
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent *event) override final;
|
||||
void onShootbackTargetModifyReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
|
||||
void onShootbackTargetRemoveReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
|
||||
|
||||
void setMode(MODE mode = MODE::TARGET_BASE_CONFIGURATION);
|
||||
|
||||
QByteArray toJson() const;
|
||||
QVector<ShootbackTarget> fromJson(const QByteArray &content);
|
||||
|
||||
private Q_SLOTS:
|
||||
void onEscapePressed();
|
||||
void onSelectionChanged();
|
||||
void onNewTargetPart();
|
||||
void onRemoveTargetPart();
|
||||
void onEditTargetPart();
|
||||
|
||||
void onExportButtonClicked();
|
||||
void onImportButtonClicked();
|
||||
void onImport();
|
||||
|
||||
void onAssignAreaClicked();
|
||||
|
||||
void onMapCenterClicked();
|
||||
void onMapZoomToClicked();
|
||||
|
||||
void onObjectEntered(const QModelIndex &index);
|
||||
void onTableViewClicked(const QModelIndex &index);
|
||||
|
||||
void clearSelectionOfMapObjects();
|
||||
|
||||
private:
|
||||
QPushButton *m_assignAreaBtn{nullptr};
|
||||
TargetParticipantModel *m_targetParticipantModel{nullptr};
|
||||
|
||||
MODE m_mode{MODE::TARGET_BASE_CONFIGURATION};
|
||||
std::shared_ptr<TargetManagement::Interface::Dtc> m_dtc;
|
||||
std::shared_ptr<TargetManagement::Interface::Ftc> m_ftc;
|
||||
std::shared_ptr<ParticipantManagement::Interface::Dtc> m_ppmDtc;
|
||||
std::shared_ptr<ParticipantManagement::ForeignGuiComboboxInterface> m_ppmGuiCbxIfc;
|
||||
std::shared_ptr<FileManagement::ForeignGuiInterface> m_flmGui;
|
||||
std::shared_ptr<SituationMap::ForeignGuiInterface> m_sitMapGuiIfc;
|
||||
|
||||
LtsSession::LtsSession *m_session{nullptr};
|
||||
Ui::TargetPartDialog *m_ui{nullptr};
|
||||
QString m_menuGroup;
|
||||
LtsUtils::RequestHelper *m_requestHelper{nullptr};
|
||||
LOGGER_T m_logger;
|
||||
};
|
||||
|
||||
} // namespace TargetManagement
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TargetPartDialog</class>
|
||||
<widget class="QWidget" name="TargetPartDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>455</width>
|
||||
<height>341</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">AlarmView</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="LtsDataView::LtsDataView" name="widget" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>250</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</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>
|
||||
+388
@@ -0,0 +1,388 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* TargetParticipantModel
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Norbert Thoden, NLE, 2020-06-29
|
||||
*/
|
||||
|
||||
#include "tgt_target_part_model.h"
|
||||
#include "tgt_common.h"
|
||||
|
||||
#include <LtsUtilsCore/variant_operators.h>
|
||||
#include <LtsCoordTrans/lts_coord_trans.h>
|
||||
#include <ParticipantManagement/ppm_translation.h>
|
||||
|
||||
#include <QApplication> // pixelMetric
|
||||
#include <QBuffer>
|
||||
|
||||
namespace TargetManagement
|
||||
{
|
||||
|
||||
QString toString(const std::vector< int32_t > &ids)
|
||||
{
|
||||
QString ret;
|
||||
for (auto id : ids)
|
||||
ret.append(QString::number(id));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------
|
||||
// TargetParticipantModel
|
||||
//---------------------------------
|
||||
TargetParticipantModel::TargetParticipantModel(QObject *parent)
|
||||
: BaseClass(
|
||||
{
|
||||
tr("Id"),
|
||||
tr("Target Name"),
|
||||
// associated participant:
|
||||
tr("Participant Id"),
|
||||
tr("Equipmentnumber"),
|
||||
tr("Type"), // Equipmenttype
|
||||
tr("Participant"),
|
||||
|
||||
// main/base config
|
||||
tr("Position"),
|
||||
tr("ActivateLaserDesignation"),
|
||||
tr("ActivateLights"),
|
||||
tr("ActivatePopupAutomatic"),
|
||||
tr("HitsToKill"),
|
||||
tr("PermanentInstalledTarget"),
|
||||
tr("VisibleParticipants")
|
||||
|
||||
},
|
||||
parent)
|
||||
, m_logger(getLogger("TargetParticipantModel"))
|
||||
{}
|
||||
|
||||
|
||||
bool TargetParticipantModel::initModel(const std::shared_ptr<TargetManagement::Interface::Dtc> &tgtDtc,
|
||||
const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc,
|
||||
const std::shared_ptr<ParticipantManagement::ForeignGuiComboboxInterface> &ppmGuiCbxIfc,
|
||||
LtsSession::LtsSession *session)
|
||||
{
|
||||
m_tgt_dtc = tgtDtc;
|
||||
m_session = session;
|
||||
|
||||
delete m_participantHandler;
|
||||
m_participantHandler = new ParticipantHandler(this);
|
||||
|
||||
m_participantHandler->init(m_tgt_dtc, ppmDtc, ppmGuiCbxIfc);
|
||||
|
||||
connect(m_participantHandler, &ParticipantHandler::signalParticipantNamesChanged,
|
||||
this, &TargetParticipantModel::signalParticipantNamesChanged);
|
||||
connect(m_participantHandler, &ParticipantHandler::signalParticipantChanged,
|
||||
this, &TargetParticipantModel::update);
|
||||
|
||||
|
||||
// insert Model
|
||||
const QMap<qint32, TargetManagement::ShootbackTarget> targetParticipants = m_tgt_dtc->shootbackTargets();
|
||||
INFO_LOG(m_logger) << "initModel - #TargetParticipantModel: " << targetParticipants.size();
|
||||
|
||||
connect(m_tgt_dtc.get(), &Interface::Dtc::shootbackTargetChanged,
|
||||
this, &TargetParticipantModel::onShootbackTargetChanged);
|
||||
|
||||
{
|
||||
auto cb = [this](const TargetManagement::ShootbackTarget & d) { onShootbackTargetChanged(d, DataModification::eAdded); };
|
||||
m_tgt_dtc->shootbackTargets(cb);
|
||||
}
|
||||
|
||||
// updateColumnFilter
|
||||
connect(this, &TargetParticipantModel::rowsInserted, this, &TargetParticipantModel::updateColumnFilter);
|
||||
connect(this, &TargetParticipantModel::rowsRemoved, this, &TargetParticipantModel::updateColumnFilter);
|
||||
connect(this, &TargetParticipantModel::modelReset, this, &TargetParticipantModel::updateColumnFilter);
|
||||
// in case of changing value like hitsToKill:
|
||||
connect(this, &TargetParticipantModel::dataChanged, this, &TargetParticipantModel::updateColumnFilter);
|
||||
updateColumnFilter();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariant TargetParticipantModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (role == LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole &&
|
||||
orientation == Qt::Horizontal)
|
||||
{
|
||||
// a few Set<int> ==>
|
||||
const auto processBoolean = [this](const QSet<int> &usedXYCont) -> QVariant
|
||||
{
|
||||
LtsWidgets::ComboboxFilterContent cfc;
|
||||
cfc.data.reserve(usedXYCont.size());
|
||||
LtsWidgets::ComboboxFilterData cfd;
|
||||
|
||||
for (int value : usedXYCont)
|
||||
{
|
||||
cfd.data = value;
|
||||
cfd.text = value ? tr("Yes") : tr("No");
|
||||
cfd.icon = value ? m_yes : m_no;
|
||||
cfc.data.push_back(cfd);
|
||||
}
|
||||
cfc.sortItems = true;
|
||||
return cfc.toVariant();
|
||||
};
|
||||
|
||||
// a few Set<int> ==>
|
||||
const auto processInt = [](const QSet<int> &usedXYCont) -> QVariant
|
||||
{
|
||||
LtsWidgets::ComboboxFilterContent cfc;
|
||||
cfc.data.reserve(usedXYCont.size());
|
||||
LtsWidgets::ComboboxFilterData cfd;
|
||||
|
||||
for (int value : usedXYCont)
|
||||
{
|
||||
cfd.data = value;
|
||||
cfd.text = QString::number(value);
|
||||
cfc.data.push_back(cfd);
|
||||
}
|
||||
cfc.sortItems = true;
|
||||
return cfc.toVariant();
|
||||
};
|
||||
|
||||
if (section == ActivateLaserDesignation)
|
||||
return processBoolean(m_usedActiveLaserDesignations);
|
||||
else if (section == ActivateLights)
|
||||
return processBoolean(m_usedActivateLights);
|
||||
else if (section == ActivatePopupAutomatic)
|
||||
return processBoolean(m_usedActivatePopupAutomatic);
|
||||
else if (section == HitsToKill)
|
||||
return processInt(m_usedHitsToKill);
|
||||
else if (section == PermanentInstalledTarget)
|
||||
return processBoolean(m_usedPermanetTargetInstalled);
|
||||
}
|
||||
return BaseClass::headerData(section, orientation, role);
|
||||
}
|
||||
|
||||
QVariant TargetParticipantModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
INFO_LOG(m_logger) << LOGFUNCTION << " role=" << role
|
||||
<< " index = " << index.column();
|
||||
|
||||
if (!indexIsValid(index))
|
||||
return QVariant();
|
||||
if (role != Qt::DisplayRole &&
|
||||
role != Qt::DecorationRole &&
|
||||
role != Qt::BackgroundRole &&
|
||||
role != Qt::ToolTipRole &&
|
||||
role != LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole)
|
||||
return QVariant();
|
||||
|
||||
const TargetManagement::ShootbackTarget &shootbackTarget = m_vecData.at(index.row());
|
||||
|
||||
if (role == Qt::DecorationRole)
|
||||
{
|
||||
if (index.column() == Participant)
|
||||
{
|
||||
static const int pmSize = QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize);
|
||||
const QPixmap &pm = m_participantHandler->getParticipantDecoration(shootbackTarget.targetParticipantId());
|
||||
if (!pm.isNull())
|
||||
return pm.scaled(pmSize, pmSize);
|
||||
}
|
||||
else if ((index.column() == ActivateLaserDesignation))
|
||||
return shootbackTarget.activateLaserDesignation() ? m_yes : m_no;
|
||||
else if ((index.column() == ActivateLights))
|
||||
return shootbackTarget.activateLights() ? m_yes : m_no;
|
||||
else if ((index.column() == ActivatePopupAutomatic))
|
||||
return shootbackTarget.activatePopupAutomatic() ? m_yes : m_no;
|
||||
else if ((index.column() == PermanentInstalledTarget))
|
||||
return shootbackTarget.permanentInstalledTarget() ? m_yes : m_no;
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
else if (role == Qt::BackgroundRole)
|
||||
{
|
||||
if ((index.column() == TargetPartipantId) && (shootbackTarget.targetParticipantId() <= 0))
|
||||
return getWarningBackgroundRole(); // orange
|
||||
if (index.column() == TargetPartipantEquipmentNumber)
|
||||
{
|
||||
const int eqNo = m_participantHandler->getParticipantIdToEquipmentNumber(shootbackTarget.targetParticipantId());
|
||||
if (eqNo <= 0)
|
||||
return getWarningBackgroundRole(); // orange
|
||||
}
|
||||
}
|
||||
else if (role == Qt::ToolTipRole)
|
||||
{
|
||||
if (index.column() == Participant)
|
||||
{
|
||||
QString tooltip(QStringLiteral("<html>"));
|
||||
|
||||
const QPixmap &img = m_participantHandler->getParticipantDecoration(shootbackTarget.targetParticipantId());
|
||||
if (!img.isNull())
|
||||
{
|
||||
// without a temporary file:
|
||||
QByteArray data;
|
||||
QBuffer buffer(&data);
|
||||
img.save(&buffer, "PNG", 100);
|
||||
tooltip.append(QStringLiteral("<center><img src='data:image/png;base64,%1'></center>").arg(QString::fromLatin1(data.toBase64())));
|
||||
|
||||
QString hdr = this->headerData(ShootbackTargetName, Qt::Horizontal, Qt::DisplayRole).toString();
|
||||
tooltip.append(QStringLiteral("<p>%1: %2</p>").arg(hdr, QString::fromStdString(shootbackTarget.name())));
|
||||
|
||||
hdr = this->headerData(Participant, Qt::Horizontal, Qt::DisplayRole).toString();
|
||||
const QString &val = m_participantHandler->getParticipantHierarchie(shootbackTarget.targetParticipantId());
|
||||
tooltip.append(QStringLiteral("<p>%1: %2</p>").arg(hdr, val));
|
||||
|
||||
tooltip.append(QStringLiteral("</html>"));
|
||||
return tooltip;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (role == LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole)
|
||||
{
|
||||
// following static_cast<int> are important!!!
|
||||
if (index.column() == ActivateLaserDesignation)
|
||||
return static_cast<int>(shootbackTarget.activateLaserDesignation());
|
||||
if (index.column() == ActivateLights)
|
||||
return static_cast<int>(shootbackTarget.activateLights());
|
||||
if (index.column() == ActivatePopupAutomatic)
|
||||
return static_cast<int>(shootbackTarget.activatePopupAutomatic());
|
||||
if (index.column() == HitsToKill)
|
||||
return shootbackTarget.hitsToKill();
|
||||
}
|
||||
|
||||
switch (index.column())
|
||||
{
|
||||
case Id:
|
||||
return shootbackTarget.id();
|
||||
|
||||
|
||||
// associated participant:
|
||||
|
||||
case ShootbackTargetName:
|
||||
return QString::fromStdString(shootbackTarget.name());
|
||||
|
||||
case TargetPartipantId:
|
||||
return shootbackTarget.targetParticipantId();
|
||||
case TargetPartipantEquipmentNumber:
|
||||
{
|
||||
const int eqNo = m_participantHandler->getParticipantIdToEquipmentNumber(shootbackTarget.targetParticipantId());
|
||||
if (eqNo <= 0)
|
||||
return QStringLiteral("-");
|
||||
return eqNo;
|
||||
}
|
||||
case TargetPartipantEquipmentType:
|
||||
{
|
||||
const auto type = m_participantHandler->getParticipantIdToWmsTypeClass(shootbackTarget.targetParticipantId());
|
||||
return ParticipantHandler::target_wmsTypeClassToString(type);
|
||||
}
|
||||
case Participant:
|
||||
return m_participantHandler->getParticipantHierarchie(shootbackTarget.targetParticipantId());
|
||||
// main/base config
|
||||
case Position:
|
||||
{
|
||||
const Core::GeoPosition2D &pos = shootbackTarget.position();
|
||||
return LtsCoordTrans::mgrsFromGeographic(pos.lon(), pos.lat());
|
||||
}
|
||||
case ActivateLaserDesignation:
|
||||
return shootbackTarget.activateLaserDesignation() ? tr("Yes") : tr("No");
|
||||
case ActivateLights:
|
||||
return shootbackTarget.activateLights() ? tr("Yes") : tr("No");
|
||||
case ActivatePopupAutomatic:
|
||||
return shootbackTarget.activatePopupAutomatic() ? tr("Yes") : tr("No");
|
||||
case HitsToKill:
|
||||
return shootbackTarget.hitsToKill();
|
||||
case PermanentInstalledTarget:
|
||||
return shootbackTarget.permanentInstalledTarget() ? tr("Yes") : tr("No");
|
||||
case VisibleParticipants:
|
||||
return TargetManagement::toString(shootbackTarget.visibleParticipants());
|
||||
} // switch
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QSet<int> TargetParticipantModel::getAssociatedParticipantIds() const
|
||||
{
|
||||
QSet<int> ret;
|
||||
ret.reserve(m_vecData.size());
|
||||
for (const TargetManagement::ShootbackTarget &data : m_vecData)
|
||||
ret += data.targetParticipantId();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void TargetParticipantModel::onShootbackTargetChanged(const TargetManagement::ShootbackTarget &data,
|
||||
const DataModification modType)
|
||||
{
|
||||
BaseClass::onDataChanged(data, modType);
|
||||
emit signalParticipantNamesChanged();
|
||||
}
|
||||
|
||||
void TargetParticipantModel::updateColumnFilter()
|
||||
{
|
||||
m_usedActiveLaserDesignations.clear();
|
||||
m_usedActivateLights.clear();
|
||||
m_usedActivatePopupAutomatic.clear();
|
||||
m_usedHitsToKill.clear();
|
||||
m_usedPermanetTargetInstalled.clear();
|
||||
|
||||
for (const ShootbackTarget &item : qAsConst(m_vecData))
|
||||
{
|
||||
m_usedActiveLaserDesignations.insert(item.activateLaserDesignation());
|
||||
m_usedActivateLights.insert(item.activateLights());
|
||||
m_usedActivatePopupAutomatic.insert(item.activatePopupAutomatic());
|
||||
m_usedHitsToKill.insert(item.hitsToKill());
|
||||
m_usedPermanetTargetInstalled.insert(item.permanentInstalledTarget());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------
|
||||
// TargetParticipantProxyModel
|
||||
// --------------------------------------------------------
|
||||
void TargetParticipantProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
|
||||
{
|
||||
m_sourceModel = qobject_cast<TargetParticipantModel *>(sourceModel);
|
||||
BaseClass::setSourceModel(sourceModel);
|
||||
}
|
||||
|
||||
bool TargetParticipantProxyModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
|
||||
{
|
||||
if (!m_sourceModel || !m_sourceModel->m_participantHandler ||
|
||||
source_left.column() != source_right.column() ||
|
||||
source_left.row() < 0 || source_left.row() >= m_sourceModel->m_vecData.size() ||
|
||||
source_right.row() < 0 || source_right.row() >= m_sourceModel->m_vecData.size()
|
||||
)
|
||||
return BaseClass::lessThan(source_left, source_right);
|
||||
|
||||
|
||||
const TargetManagement::ShootbackTarget &left = m_sourceModel->m_vecData.at(source_left.row());
|
||||
const TargetManagement::ShootbackTarget &right = m_sourceModel->m_vecData.at(source_right.row());
|
||||
switch (source_left.column())
|
||||
{
|
||||
case TargetParticipantModel::Columns::Id:
|
||||
return left.id() < right.id();
|
||||
case TargetParticipantModel::Columns::ShootbackTargetName:
|
||||
return left.name() < right.name();
|
||||
case TargetParticipantModel::Columns::TargetPartipantId:
|
||||
return left.targetParticipantId() < right.targetParticipantId();
|
||||
case TargetParticipantModel::Columns::TargetPartipantEquipmentNumber:
|
||||
{
|
||||
const int eqNoLeft = m_sourceModel->m_participantHandler->getParticipantIdToEquipmentNumber(left.targetParticipantId());
|
||||
const int eqNoRight = m_sourceModel->m_participantHandler->getParticipantIdToEquipmentNumber(left.targetParticipantId());
|
||||
return eqNoLeft < eqNoRight;
|
||||
}
|
||||
|
||||
// case TargetParticipantModel::Columns::Position:
|
||||
|
||||
case TargetParticipantModel::Columns::ActivateLaserDesignation:
|
||||
return left.activateLaserDesignation() < right.activateLaserDesignation();
|
||||
case TargetParticipantModel::Columns::ActivateLights:
|
||||
return left.activateLights() < right.activateLights();
|
||||
case TargetParticipantModel::Columns::ActivatePopupAutomatic:
|
||||
return left.activatePopupAutomatic() < right.activatePopupAutomatic();
|
||||
case TargetParticipantModel::Columns::HitsToKill:
|
||||
return left.hitsToKill() < right.hitsToKill();
|
||||
case TargetParticipantModel::Columns::PermanentInstalledTarget:
|
||||
return left.permanentInstalledTarget() < right.permanentInstalledTarget();
|
||||
case TargetParticipantModel::Columns::VisibleParticipants:
|
||||
return toString(left.visibleParticipants()) < toString(right.visibleParticipants());
|
||||
|
||||
case TargetParticipantModel::Columns::Participant:
|
||||
// QString compare
|
||||
return LtsUtils::lessThan(source_left.data(), source_right.data());
|
||||
}
|
||||
return BaseClass::lessThan(source_left, source_right);
|
||||
}
|
||||
|
||||
|
||||
} // namespace TargetManagement
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* TargetParticipantModel
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Norbert Thoden, NLE, 2020-06-29
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "tgt_participant_handler.h"
|
||||
#include <TargetManagement/tgt_dtc.h>
|
||||
#include <TargetManagement/logger.h>
|
||||
|
||||
#include <LtsWidgets/lts_abstract_table_model.h>
|
||||
#include <LtsWidgets/lts_column_filter_proxy_model.h>
|
||||
#include <LtsSession/lts_session.h>
|
||||
|
||||
namespace TargetManagement
|
||||
{
|
||||
|
||||
// Forward:
|
||||
class ParticipantHandler;
|
||||
|
||||
// --------------------------------------------------------
|
||||
// TargetParticipantModel
|
||||
// --------------------------------------------------------
|
||||
class TargetParticipantModel final : public LtsWidgets::LtsAbstractTableModel<TargetManagement::ShootbackTarget>
|
||||
{
|
||||
Q_OBJECT
|
||||
using BaseClass = LtsWidgets::LtsAbstractTableModel<TargetManagement::ShootbackTarget>;
|
||||
|
||||
public:
|
||||
enum Columns
|
||||
{
|
||||
Id,
|
||||
|
||||
// linked participant:
|
||||
ShootbackTargetName,
|
||||
TargetPartipantId,
|
||||
TargetPartipantEquipmentNumber,
|
||||
TargetPartipantEquipmentType,
|
||||
Participant,
|
||||
|
||||
// main/base config
|
||||
Position,
|
||||
ActivateLaserDesignation,
|
||||
ActivateLights,
|
||||
ActivatePopupAutomatic,
|
||||
HitsToKill,
|
||||
PermanentInstalledTarget,
|
||||
VisibleParticipants,
|
||||
};
|
||||
|
||||
explicit TargetParticipantModel(QObject *parent = nullptr);
|
||||
|
||||
bool initModel(const std::shared_ptr<Interface::Dtc> &tgtDtc,
|
||||
const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc,
|
||||
const std::shared_ptr<ParticipantManagement::ForeignGuiComboboxInterface> &ppmGuiCbxIfc,
|
||||
LtsSession::LtsSession *session);
|
||||
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const override final;
|
||||
QVariant data(const QModelIndex &, int) const override;
|
||||
|
||||
const QHash <int, QString> &getParticipantHierarchies() const { return m_participantHandler->getParticipantHierarchies(); }
|
||||
const QHash <int, QPixmap> &getParticipantDecorations() const { return m_participantHandler->getParticipantDecorations(); }
|
||||
QSet<int> getAssociatedParticipantIds() const;
|
||||
|
||||
const QVector<ShootbackTarget> &getData() const { return m_vecData; }
|
||||
|
||||
Q_SIGNALS:
|
||||
void signalParticipantNamesChanged();
|
||||
|
||||
private Q_SLOTS:
|
||||
void onShootbackTargetChanged(const TargetManagement::ShootbackTarget &data,
|
||||
const DataModification modType);
|
||||
void updateColumnFilter();
|
||||
|
||||
private:
|
||||
friend class TargetParticipantProxyModel;
|
||||
std::shared_ptr<TargetManagement::Interface::Dtc> m_tgt_dtc;
|
||||
ParticipantHandler *m_participantHandler{nullptr};
|
||||
LtsSession::LtsSession *m_session{nullptr};
|
||||
|
||||
QIcon m_yes{QLatin1String("icon:yes.svg")};
|
||||
QIcon m_no{QLatin1String("icon:no.svg")};
|
||||
|
||||
// column filter
|
||||
QSet<int> m_usedActiveLaserDesignations;
|
||||
QSet<int> m_usedActivateLights;
|
||||
QSet<int> m_usedActivatePopupAutomatic;
|
||||
QSet<int> m_usedHitsToKill;
|
||||
QSet<int> m_usedPermanetTargetInstalled;
|
||||
|
||||
LOGGER_T m_logger;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------
|
||||
// TargetParticipantProxyModel
|
||||
// --------------------------------------------------------
|
||||
class TargetParticipantProxyModel : public LtsWidgets::LtsColumnFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
using BaseClass = LtsWidgets::LtsColumnFilterProxyModel;
|
||||
|
||||
public:
|
||||
using LtsWidgets::LtsColumnFilterProxyModel::LtsColumnFilterProxyModel;
|
||||
void setSourceModel(QAbstractItemModel *sourceModel) override;
|
||||
|
||||
protected:
|
||||
bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override;
|
||||
|
||||
protected:
|
||||
TargetParticipantModel *m_sourceModel{nullptr};
|
||||
};
|
||||
|
||||
} //namespace TargetManagement
|
||||
+266
@@ -0,0 +1,266 @@
|
||||
/**
|
||||
* Telegrams toJSON
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Norbert Thoden, NLE, 2020-06-29
|
||||
*/
|
||||
|
||||
#include "tgt_telegrams.h"
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
|
||||
namespace TargetManagement
|
||||
{
|
||||
//
|
||||
// Helpers
|
||||
//
|
||||
JsonException::JsonException(const QJsonObject &obj, const QString &key)
|
||||
: m_obj(obj)
|
||||
, m_key(key)
|
||||
, m_what("Could not find key '" + key.toUtf8() + "' in json ('" + QJsonDocument(obj).toJson(QJsonDocument::Compact) + "')")
|
||||
{}
|
||||
|
||||
template <typename E>
|
||||
QJsonValue enumToJson(E e)
|
||||
{
|
||||
static_assert(std::is_enum<E>::value, "Only useable with enumerations");
|
||||
return static_cast<int>(e);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool get(const QJsonObject &obj, const QString &key, T &val, bool bOptional = false)
|
||||
{
|
||||
if (bOptional)
|
||||
{
|
||||
try
|
||||
{
|
||||
val = T::fromJson(obj[key].toObject());
|
||||
}
|
||||
catch (const JsonException &e)
|
||||
{
|
||||
Q_UNUSED(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
val = T::fromJson(obj[key].toObject());
|
||||
return true;
|
||||
}
|
||||
|
||||
// POD getter
|
||||
template <>
|
||||
bool get(const QJsonObject &obj, const QString &key, bool &val, bool bOptional)
|
||||
{
|
||||
const auto jVal = obj[key];
|
||||
if (!jVal.isBool())
|
||||
{
|
||||
if (bOptional)
|
||||
return false;
|
||||
throw JsonException(obj, key);
|
||||
}
|
||||
val = jVal.toBool();
|
||||
return true;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool get(const QJsonObject &obj, const QString &key, int &val, bool bOptional)
|
||||
{
|
||||
const auto jVal = obj[key];
|
||||
if (!jVal.isDouble()) // ToDo: Check
|
||||
{
|
||||
if (bOptional)
|
||||
return false;
|
||||
throw JsonException(obj, key);
|
||||
}
|
||||
val = jVal.toInt();
|
||||
return true;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool get(const QJsonObject &obj, const QString &key, double &val, bool bOptional)
|
||||
{
|
||||
const auto jVal = obj[key];
|
||||
if (!jVal.isDouble())
|
||||
{
|
||||
if (bOptional)
|
||||
return false;
|
||||
throw JsonException(obj, key);
|
||||
}
|
||||
val = jVal.toDouble();
|
||||
return true;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool get(const QJsonObject &obj, const QString &key, QString &val, bool bOptional)
|
||||
{
|
||||
const auto jVal = obj[key];
|
||||
if (!jVal.isString())
|
||||
{
|
||||
if (bOptional)
|
||||
return false;
|
||||
throw JsonException(obj, key);
|
||||
}
|
||||
val = jVal.toString();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// enum getter
|
||||
//
|
||||
// Effect
|
||||
template <>
|
||||
bool get(const QJsonObject &obj, const QString &key, Effect &val, bool bOptional)
|
||||
{
|
||||
int iVal;
|
||||
get(obj, key, iVal, bOptional);
|
||||
switch (static_cast<Effect_def::type>(iVal))
|
||||
{
|
||||
case Effect_def::NearMiss:
|
||||
case Effect_def::MobilityKill:
|
||||
case Effect_def::WeaponKill:
|
||||
val = Effect( static_cast<Effect_def::type>(iVal) );
|
||||
return true;
|
||||
}
|
||||
throw JsonException(obj, key);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Structs
|
||||
//
|
||||
// ------------------------------------------------------------------
|
||||
//
|
||||
// GeoPosition2D
|
||||
//
|
||||
QJsonObject GeoPosition2D::toJson() const
|
||||
{
|
||||
return QJsonObject({{QStringLiteral("lat"), lat},
|
||||
{QStringLiteral("lon"), lon},
|
||||
});
|
||||
}
|
||||
|
||||
GeoPosition2D GeoPosition2D::fromJson(const QJsonObject &obj)
|
||||
{
|
||||
GeoPosition2D ret;
|
||||
get(obj, QStringLiteral("lat"), ret.lat);
|
||||
get(obj, QStringLiteral("lon"), ret.lon);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// ShootbackTargetData
|
||||
//
|
||||
QJsonObject ShootbackTargetData::toJson() const
|
||||
{
|
||||
return QJsonObject({{QStringLiteral("id"), id},
|
||||
{QStringLiteral("targetDataId"), targetDataId},
|
||||
{QStringLiteral("name"), name},
|
||||
{QStringLiteral("targetParticipantEquipmentNumber"), targetParticipantEquipmentNumber},
|
||||
{QStringLiteral("activateLaserDesignation"), activateLaserDesignation},
|
||||
{QStringLiteral("activateLights"), activateLights},
|
||||
{QStringLiteral("activatePopupAutomatic"), activatePopupAutomatic},
|
||||
{QStringLiteral("hitsToKill"), hitsToKill},
|
||||
{QStringLiteral("permanentInstalledTarget"), permanentInstalledTarget},
|
||||
});
|
||||
}
|
||||
|
||||
ShootbackTargetData ShootbackTargetData::fromJson(const QJsonObject &obj)
|
||||
{
|
||||
ShootbackTargetData ret;
|
||||
get(obj, QStringLiteral("id"), ret.id);
|
||||
get(obj, QStringLiteral("targetDataId"), ret.targetDataId);
|
||||
get(obj, QStringLiteral("name"), ret.name);
|
||||
get(obj, QStringLiteral("targetParticipantEquipmentNumber"), ret.targetParticipantEquipmentNumber);
|
||||
get(obj, QStringLiteral("activateLaserDesignation"), ret.activateLaserDesignation);
|
||||
get(obj, QStringLiteral("activateLights"), ret.activateLights);
|
||||
get(obj, QStringLiteral("activatePopupAutomatic"), ret.activatePopupAutomatic);
|
||||
get(obj, QStringLiteral("hitsToKill"), ret.hitsToKill);
|
||||
get(obj, QStringLiteral("permanentInstalledTarget"), ret.permanentInstalledTarget);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// ShootbackAreaData
|
||||
//
|
||||
QJsonObject ShootbackAreaData::toJson() const
|
||||
{
|
||||
return QJsonObject({{QStringLiteral("id"), id},
|
||||
{QStringLiteral("name"), name},
|
||||
{QStringLiteral("position"), position.toJson()},
|
||||
{QStringLiteral("width"), width},
|
||||
{QStringLiteral("height"), height},
|
||||
});
|
||||
}
|
||||
|
||||
ShootbackAreaData ShootbackAreaData::fromJson(const QJsonObject &obj)
|
||||
{
|
||||
ShootbackAreaData ret;
|
||||
get(obj, QStringLiteral("id"), ret.id);
|
||||
get(obj, QStringLiteral("name"), ret.name);
|
||||
get(obj, QStringLiteral("position"), ret.position);
|
||||
get(obj, QStringLiteral("width"), ret.width);
|
||||
get(obj, QStringLiteral("height"), ret.height);
|
||||
return ret;
|
||||
}
|
||||
|
||||
//
|
||||
// ShootbackConfigurationData
|
||||
//
|
||||
QJsonObject ShootbackConfigurationData::toJson() const
|
||||
{
|
||||
return QJsonObject({{QStringLiteral("interval1"), interval1},
|
||||
{QStringLiteral("flash1"), flash1},
|
||||
{QStringLiteral("effect1"), enumToJson(effect1.underlying())},
|
||||
{QStringLiteral("interval2"), interval2},
|
||||
{QStringLiteral("flash2"), flash2},
|
||||
{QStringLiteral("effect2"), enumToJson(effect2.underlying())},
|
||||
});
|
||||
}
|
||||
|
||||
ShootbackConfigurationData ShootbackConfigurationData::fromJson(const QJsonObject &obj)
|
||||
{
|
||||
ShootbackConfigurationData ret;
|
||||
get(obj, QStringLiteral("interval1"), ret.interval1);
|
||||
get(obj, QStringLiteral("flash1"), ret.flash1);
|
||||
get(obj, QStringLiteral("effect1"), ret.effect1);
|
||||
get(obj, QStringLiteral("interval2"), ret.interval2);
|
||||
get(obj, QStringLiteral("flash2"), ret.flash2);
|
||||
get(obj, QStringLiteral("effect2"), ret.effect2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// TargetAreaAssignmentData
|
||||
//
|
||||
QJsonObject TargetAreaAssignmentData::toJson() const
|
||||
{
|
||||
return QJsonObject({{QStringLiteral("id"), id},
|
||||
{QStringLiteral("name"), name},
|
||||
{QStringLiteral("areaId"), areaId},
|
||||
{QStringLiteral("targetParticipantId"), targetParticipantId},
|
||||
{QStringLiteral("configuration"), configuration.toJson()},
|
||||
{QStringLiteral("isActive"), isActive},
|
||||
});
|
||||
}
|
||||
|
||||
TargetAreaAssignmentData TargetAreaAssignmentData::fromJson(const QJsonObject &obj)
|
||||
{
|
||||
TargetAreaAssignmentData ret;
|
||||
get(obj, QStringLiteral("id"), ret.id);
|
||||
get(obj, QStringLiteral("name"), ret.name);
|
||||
|
||||
get(obj, QStringLiteral("areaId"), ret.areaId);
|
||||
get(obj, QStringLiteral("targetParticipantId"), ret.targetParticipantId);
|
||||
get(obj, QStringLiteral("configuration"), ret.configuration);
|
||||
get(obj, QStringLiteral("isActive"), ret.isActive);
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace TargetManagement
|
||||
+173
@@ -0,0 +1,173 @@
|
||||
/**
|
||||
* Telegrams toJSON
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Norbert Thoden, NLE, 2020-06-29
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <exception>
|
||||
#include <QJsonObject>
|
||||
#include <QString>
|
||||
|
||||
#include <Services/TargetManagement/tgt_dtc.h>
|
||||
|
||||
|
||||
|
||||
namespace TargetManagement
|
||||
{
|
||||
|
||||
class JsonException final : public std::exception
|
||||
{
|
||||
public:
|
||||
JsonException(const QJsonObject &obj, const QString &key);
|
||||
const char *what() const noexcept override { return m_what.data(); }
|
||||
private:
|
||||
QJsonObject m_obj;
|
||||
QString m_key;
|
||||
QByteArray m_what;
|
||||
};
|
||||
template <typename T>
|
||||
struct Constraints;
|
||||
|
||||
|
||||
//
|
||||
// Enumerations
|
||||
//
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Structs
|
||||
//
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
struct Target
|
||||
{
|
||||
virtual ~Target() = default;
|
||||
virtual QJsonObject toJson() const = 0;
|
||||
virtual QString type() const = 0;
|
||||
};
|
||||
|
||||
struct GeoPosition2D
|
||||
{
|
||||
GeoPosition2D() = default;
|
||||
explicit GeoPosition2D(const Core::GeoPosition2D pos)
|
||||
: lat(pos.lat()), lon(pos.lon()) {}
|
||||
|
||||
double lat = 0; // in degree, WGS-84
|
||||
double lon = 0; // in degree, WGS-84
|
||||
|
||||
static GeoPosition2D fromJson(const QJsonObject &obj);
|
||||
QJsonObject toJson() const;
|
||||
|
||||
// Core::GeoPosition2D toCoreGeoPosition2D() const { return {lon, lat}; }
|
||||
|
||||
};
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
template <typename T>
|
||||
struct TargetBaseTmpl : Target
|
||||
{
|
||||
QString type() const override final { return Constraints<T>::type(); }
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
struct ShootbackTargetData final : public TargetBaseTmpl<ShootbackTargetData>
|
||||
{
|
||||
// use simple members and not generated dds struct to be independent
|
||||
|
||||
int32_t id{-1};
|
||||
int32_t targetDataId{-1};
|
||||
QString name;
|
||||
int32_t targetParticipantEquipmentNumber{-1};
|
||||
bool activateLaserDesignation{false};
|
||||
bool permanentInstalledTarget{false};
|
||||
bool activateLights{false};
|
||||
int32_t hitsToKill{-1};
|
||||
bool activatePopupAutomatic{false};
|
||||
|
||||
// conversion functions
|
||||
QJsonObject toJson() const override;
|
||||
static ShootbackTargetData fromJson(const QJsonObject &obj);
|
||||
};
|
||||
template <> struct Constraints<ShootbackTargetData>
|
||||
{
|
||||
static QString type() { return QStringLiteral("ShootbackTargetData"); }
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
struct ShootbackAreaData final : public TargetBaseTmpl<ShootbackAreaData>
|
||||
{
|
||||
// use simple members and not generated dds struct to be independent
|
||||
|
||||
int32_t id{-1};
|
||||
QString name;
|
||||
|
||||
GeoPosition2D position;
|
||||
double width{.0};
|
||||
double height{.0};
|
||||
|
||||
// conversion functions
|
||||
QJsonObject toJson() const override;
|
||||
static ShootbackAreaData fromJson(const QJsonObject &obj);
|
||||
};
|
||||
template <> struct Constraints<ShootbackAreaData>
|
||||
{
|
||||
static QString type() { return QStringLiteral("ShootbackAreaData"); }
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
struct ShootbackConfigurationData final : public TargetBaseTmpl<ShootbackConfigurationData>
|
||||
{
|
||||
// use simple members and not generated dds struct to be independent
|
||||
|
||||
int interval1{-1};
|
||||
bool flash1{false};
|
||||
TargetManagement::Effect effect1{TargetManagement::Effect_def::NearMiss};
|
||||
|
||||
int interval2{-1};
|
||||
bool flash2{false};
|
||||
TargetManagement::Effect effect2{TargetManagement::Effect_def::NearMiss};
|
||||
|
||||
// conversion functions
|
||||
QJsonObject toJson() const override;
|
||||
static ShootbackConfigurationData fromJson(const QJsonObject &obj);
|
||||
};
|
||||
template <> struct Constraints<ShootbackConfigurationData>
|
||||
{
|
||||
static QString type() { return QStringLiteral("ShootbackConfigurationData"); }
|
||||
};
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
struct TargetAreaAssignmentData final : public TargetBaseTmpl<TargetAreaAssignmentData>
|
||||
{
|
||||
// use simple members and not generated dds struct to be independent
|
||||
|
||||
int32_t id{-1};
|
||||
QString name;
|
||||
|
||||
int areaId;
|
||||
int targetParticipantId;
|
||||
|
||||
ShootbackConfigurationData configuration;
|
||||
|
||||
bool isActive{false};
|
||||
|
||||
// conversion functions
|
||||
QJsonObject toJson() const override;
|
||||
static TargetAreaAssignmentData fromJson(const QJsonObject &obj);
|
||||
};
|
||||
template <> struct Constraints<TargetAreaAssignmentData>
|
||||
{
|
||||
static QString type() { return QStringLiteral("TargetAreaAssignmentData"); }
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* HMI Plugin for AreaEffectSimulation (Interface for access from other Plugins)
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Christian Ehrlicher, SLSE, 2016-02-29
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <PluginInterfaces/data_plugin_interface.h>
|
||||
#include <TargetManagement//tgt_dtc.h>
|
||||
#include <TargetManagement/tgt_ftc.h>
|
||||
|
||||
namespace TargetManagement
|
||||
{
|
||||
/**
|
||||
* @brief The DataInterface class provides the Topics Clients only for the GUI Plugins
|
||||
*/
|
||||
class DataInterface : public DataPluginBase::Interface
|
||||
{
|
||||
public:
|
||||
using DataPluginBase::Interface::Interface;
|
||||
|
||||
virtual std::shared_ptr<TargetManagement::Interface::Dtc> getDtc() = 0;
|
||||
virtual std::shared_ptr<TargetManagement::Interface::Ftc> getFtc() = 0;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* HMI Plugin for ParticipantManagement (Interface for access from other Plugins)
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Christian Ehrlicher, SLSE, 2016-02-29
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ParticipantManagement
|
||||
{
|
||||
|
||||
class ForeignPartyGuiInterface
|
||||
{
|
||||
public:
|
||||
ForeignPartyGuiInterface() = default;
|
||||
virtual ~ForeignPartyGuiInterface() = default;
|
||||
};
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user