Initial commit

This commit is contained in:
torsten committed 2026-08-13 18:33:10 +02:00
commit b7d90b9afe
16245 files changed
+3396666

No files matched your search

+28
View File
@@ -0,0 +1,28 @@
#
# $Id$
# $HeadURL$
# $Author$
# Created by Christian Ehrlicher, SLSE, 2016-02-29
#
ADD_SUBDIRECTORY(Data)
ADD_SUBDIRECTORY(Gui)
#
# Gui Plugin Interface
#
ADD_INTERFACE_LIBRARY(ExmGuiPluginInterface
${CMAKE_CURRENT_SOURCE_DIR}/exm_gui_plugin_interface.h
${CMAKE_CURRENT_SOURCE_DIR}/..
GuiPluginInterface
)
#
# Data Plugin Interface
#
ADD_INTERFACE_LIBRARY(ExmDataPluginInterface
${CMAKE_CURRENT_SOURCE_DIR}/exm_data_plugin_interface.h
${CMAKE_CURRENT_SOURCE_DIR}/..
DataPluginInterface
svcExmCommon
)
+19
View File
@@ -0,0 +1,19 @@
#
# $Id$
# $HeadURL$
# $Author$
# Created by Mike Wille, SLSE, 2016-09-06
#
#
# Data Plugin
#
NGL_ADD_LIBRARY(WS ExmDataPlugin MODULE exm_data_plugin.cpp exm_data_plugin.h)
NGL_TARGET_LINK_LIBRARIES(ExmDataPlugin
Qt5::Core
ExmDataPluginInterface
svcExmClient
NGLLogger
LtsSessionDataDds
)
NGL_INSTALL_TARGET(ExmDataPlugin)
+37
View File
@@ -0,0 +1,37 @@
/**
* @RDE_HEADER@
* Data Plugin for ExerciseManangement
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#include "exm_data_plugin.h"
#include <DDS/DDSConnector/dds_connector.h>
#include <LtsSession/lts_session_data_dds.h>
namespace ExerciseManagement
{
std::shared_ptr<DataPluginBase::Interface> DataPlugin::createDataInterface(LtsSession::LtsSessionDataDds *session)
{
std::shared_ptr<Interface::Dtc> dtc;
std::shared_ptr<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<ExerciseManagement::Interface::Dtc> &dtc,
const std::shared_ptr<ExerciseManagement::Interface::Ftc> &ftc)
: DataInterface()
, m_dtc(dtc)
, m_ftc(ftc)
{}
} // namespace ExerciseManagement
+54
View File
@@ -0,0 +1,54 @@
/**
* @RDE_HEADER@
* Data Plugin for ExerciseManangement
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#pragma once
#include <PluginInterfaces/data_plugin_interface.h>
#include <Plugins/ExerciseManagement/exm_data_plugin_interface.h>
namespace ExerciseManagement
{
class DataPlugin final : public QObject, public DataPluginBase::Plugin
{
Q_PLUGIN_METADATA(IID "data:3:exm")
Q_INTERFACES(DataPluginBase::Plugin)
Q_OBJECT
public:
DataPlugin() = default;
~DataPlugin() = default;
QString pluginName() const override { return QStringLiteral("ExerciseManagement"); }
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<ExerciseManagement::Interface::Dtc> &dtc,
const std::shared_ptr<ExerciseManagement::Interface::Ftc> &ftc);
std::shared_ptr<ExerciseManagement::Interface::Dtc> getDtc() override { return m_dtc; }
std::shared_ptr<ExerciseManagement::Interface::Ftc> getFtc() override { return m_ftc; }
private:
std::shared_ptr<ExerciseManagement::Interface::Dtc> m_dtc;
std::shared_ptr<ExerciseManagement::Interface::Ftc> m_ftc;
};
} // namespace ExerciseManagement
+8
View File
@@ -0,0 +1,8 @@
#
# $Id$
# $HeadURL$
# $Author$
# Created by Christian Ehrlicher, SLSE, 2016-02-29
#
ADD_SUBDIRECTORY(ExerciseEdit)
ADD_SUBDIRECTORY(ExerciseWatch)
@@ -0,0 +1,82 @@
#
# $Id$
# $HeadURL$
# $Author$
# Created by Christian Ehrlicher, SLSE, 2016-02-29
#
SET(exm_edit_gui_SRCS
exm_edit_gui_plugin.cpp
exm_edit_gui_plugin.h
exm_dialog.cpp
exm_dialog.h
exm_dialog_model.cpp
exm_dialog_model.h
exm_edit_dialog.cpp
exm_edit_dialog.h
exm_edit_phase_dialog.cpp
exm_edit_phase_dialog.h
exm_exercise_purpose.cpp
exm_exercise_purpose.h
exm_phase_edit.cpp
exm_phase_edit.h
exm_phase_model.cpp
exm_phase_model.h
exm_state_edit.cpp
exm_state_edit.h
exm_operator_edit.cpp
exm_operator_edit.h
exm_operator_model.cpp
exm_operator_model.h
exm_edit_party_dialog.cpp
exm_edit_party_dialog.h
exm_edit_visible_parties_model.cpp
exm_edit_visible_parties_model.h
exm_edit_adler_visible_parties_model.cpp
exm_edit_adler_visible_parties_model.h
CustomViews/exm_exercise.cpp
CustomViews/exm_exercise.h
ExerciseChooser/exm_chooser.cpp
ExerciseChooser/exm_chooser.h
)
NGL_WRAP_UI(exm_edit_gui_SRCS
exm_dialog.ui
exm_edit_dialog.ui
exm_edit_phase_dialog.ui
exm_exercise_purpose.ui
exm_operator_edit.ui
exm_phase_edit.ui
exm_state_edit.ui
exm_edit_party_dialog.ui
CustomViews/exm_exercise.ui
ExerciseChooser/exm_chooser.ui
)
NGL_ADD_LIBRARY(WS ExmEditGuiPlugin MODULE ${exm_edit_gui_SRCS})
NGL_TARGET_LINK_LIBRARIES(ExmEditGuiPlugin
ngltools # dtg
NGLLogger
LtsSession
PdmDataPluginInterface
PpmDataPluginInterface
AsmDataPluginInterface
AsmGuiPluginInterface
ExmDataPluginInterface
OpmDataPluginInterface
ExmGuiPluginInterface
FlmDataPluginInterface
Qt5::Widgets
LtsCoordTrans
LtsWidgets
LtsDataView
LtsUtilsGuiDds
LtsUtilsSettings
LtsSessionData
ProjectConfig
LtsUtilsGuiConnectDialog
)
NGL_INSTALL_TARGET(ExmEditGuiPlugin)
@@ -0,0 +1,114 @@
/**
* @RDE_HEADER@
* CustomView for Exercises
* $Id$
* $HeadURL$
* $Author$
* Created by Mike Wille, SLSE, 2016-04-08
*/
#include "exm_exercise.h"
#include "ui_exm_exercise.h"
#include "exm_dialog_model.h"
#include <ngltools/ngltools_dtg.h>
#include <LtsUtilsCore/dds_vector_to_pixmap.h>
#include <QFile>
#include <QDebug>
namespace ExerciseManagement
{
CustomViewExercise::CustomViewExercise(QWidget *parent)
: AbstractDisplayWidget(parent)
, m_ui(new Ui::CustomViewExercise)
{
m_ui->setupUi(this);
m_ui->image->setMenuEnabled(false); // no menu !
m_ui->image->setDrawOuterRect(false);
}
CustomViewExercise::~CustomViewExercise()
{
delete m_ui;
}
QSize CustomViewExercise::imageSize() const
{
return m_ui->image->size();
}
void CustomViewExercise::loadDefaultImage(QPixmap &intoPixmap)
{
QString projectLogoFilename(QStringLiteral(":project/login_logo.png"));
if (!QFile::exists(projectLogoFilename))
projectLogoFilename = QStringLiteral(":/project/logo.png");
intoPixmap = QPixmap(projectLogoFilename);
}
bool CustomViewExercise::init(const QModelIndex &idx)
{
if (!idx.isValid())
return false;
const QString exName = rowData(idx, ExerciseManagement::ExerciseManagementDialogModel::Name).toString();
m_ui->lbExerciseName->setText(exName);
m_ui->lbExerciseName->setToolTip(exName);
QPixmap img;
int exerciseId = rowData(idx, ExerciseManagement::ExerciseManagementDialogModel::Id).toInt();
if (exerciseId == 0)
{
m_ui->lbExerciseName->setWordWrap(true);
m_ui->lbLocation->hide();
m_ui->lbCreationDate->hide();
m_ui->lbDescription->hide();
m_ui->lbStatus->hide();
loadDefaultImage(img);
}
else
{
m_ui->lbLocation->setText(rowData(idx, ExerciseManagement::ExerciseManagementDialogModel::TrainingArea).toString());
m_ui->lbCreationDate->setText(DTG::toString(rowData(idx, ExerciseManagement::ExerciseManagementDialogModel::Created).toDateTime()));
m_ui->lbDescription->setText(rowData(idx, ExerciseManagement::ExerciseManagementDialogModel::Description).toString());
m_ui->lbStatus->setText(rowData(idx, ExerciseManagement::ExerciseManagementDialogModel::Status).toString());
// status label color same as in LtsBaseLayoutWidget
QPalette p = m_ui->lbStatus->palette();
QColor newCol = rowData(idx, ExerciseManagement::ExerciseManagementDialogModel::Status, Qt::TextColorRole).value<QColor>();
p.setColor(m_ui->lbStatus->backgroundRole(), newCol);
p.setColor(m_ui->lbStatus->foregroundRole(), newCol);
m_ui->lbStatus->setPalette(p);
QByteArray imgData = rowData(idx, ExerciseManagement::ExerciseManagementDialogModel::Image).toByteArray();
if (imgData.isEmpty())
loadDefaultImage(img);
else
img = LtsUtils::getPixmap(imgData);
}
if (!img.isNull())
m_ui->image->setPixmap(img);
// IO: set unique object names for Squish
this->setObjectName(QStringLiteral("customViewExercise_")+QString::number(exerciseId));
m_ui->lbExerciseName->setObjectName(QStringLiteral("lbExerciseName_")+QString::number(exerciseId));
m_ui->lbLocation->setObjectName(QStringLiteral("lbLocation_")+QString::number(exerciseId));
m_ui->lbCreationDate->setObjectName(QStringLiteral("lbCreationDate_")+QString::number(exerciseId));
m_ui->lbDescription->setObjectName(QStringLiteral("lbDescription_")+QString::number(exerciseId));
m_ui->lbStatus->setObjectName(QStringLiteral("lbStatus_")+QString::number(exerciseId));
m_ui->image->setObjectName(QStringLiteral("image_")+QString::number(exerciseId));
return true;
}
} // namespace ExerciseManagement
@@ -0,0 +1,35 @@
/**
* @RDE_HEADER@
* CustomView for Exercises
* $Id$
* $HeadURL$
* $Author$
* Created by Mike Wille, SLSE, 2016-04-08
*/
#pragma once
#include <Viewer/LtsDataView/abstract_display_widget.h>
namespace Ui
{
class CustomViewExercise;
}
namespace ExerciseManagement
{
class CustomViewExercise final : public LtsDataView::AbstractDisplayWidget
{
Q_OBJECT
public:
explicit CustomViewExercise(QWidget *parent = nullptr);
~CustomViewExercise();
bool init(const QModelIndex &idx) override;
void loadDefaultImage(QPixmap &intoPixmap);
QSize imageSize() const;
private:
Ui::CustomViewExercise* m_ui;
};
} // namespace ExerciseManagement
@@ -0,0 +1,123 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CustomViewExercise</class>
<widget class="QWidget" name="CustomViewExercise">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>379</width>
<height>174</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string notr="true"/>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="LtsWidgets::LtsImageEditor" name="image">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>128</width>
<height>128</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>128</width>
<height>128</height>
</size>
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="lbExerciseName">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string notr="true">&lt;Exercise Name&gt;</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lbLocation">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="text">
<string notr="true">&lt;Location&gt;</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lbCreationDate">
<property name="text">
<string notr="true">&lt;Creation Date&gt;</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lbStatus">
<property name="text">
<string notr="true">&lt;Status&gt;</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lbDescription">
<property name="text">
<string notr="true">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&amp;lt;Description with wordwrap&amp;gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LtsWidgets::LtsImageEditor</class>
<extends>QWidget</extends>
<header>LtsWidgets/lts_image_editor.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,212 @@
/**
* @RDE_HEADER@
* ExerciseChooser Payload UI
* $Id$
* $HeadURL$
* $Author$
* Created by Mike Wille, SLSE, 2016-08-12
*/
#include "exm_chooser.h"
#include "ui_exm_chooser.h"
#include "exm_dialog_model.h"
#include "CustomViews/exm_exercise.h"
#include <LtsWidgets/lts_global_wait_dialog.h>
#include <LtsSession/lts_session.h>
#include <LtsSession/lts_session_data.h>
#include <Plugins/ExerciseManagement/exm_data_plugin_interface.h>
#include <Plugins/OperatorManagement/opm_data_plugin_interface.h>
#include <Plugins/AssetManagement/asm_data_plugin_interface.h>
#include <Plugins/ProjectDataManagement/pdm_data_plugin_interface.h>
#include <OperatorManagement/opm_operator_rights.h>
#include <LtsUtilsCore/dds_vector.h>
#include <QCloseEvent>
namespace ExerciseManagement
{
ExerciseChooser::ExerciseChooser(QWidget *parent)
: QDialog(parent)
, m_ui(new Ui::ExerciseChooser)
{
LtsWidgets::LtsGlobalWaitDialog::getInstance()->setVisible(false);
m_ui->setupUi(this);
setWindowTitle(tr("Select Exercise"));
setWindowFlags(windowFlags() | /*Qt::WindowStaysOnTopHint | */Qt::FramelessWindowHint); // hints..
m_ui->widget->seamless();
connect(m_ui->widget, &LtsDataView::LtsDataView::selectionChanged,
this, &ExerciseChooser::enaDisa);
connect(m_ui->widget, &LtsDataView::LtsDataView::doubleClicked,
this, &ExerciseChooser::slotExerciseSelected, Qt::QueuedConnection);
connect(m_ui->pbSelect, &QPushButton::clicked,
this, &ExerciseChooser::slotExerciseSelected, Qt::QueuedConnection);
connect(m_ui->pbQuit, &QPushButton::clicked,
this, &ExerciseChooser::signalQuit, Qt::QueuedConnection);
connect(m_ui->pbQuit, &QPushButton::clicked,
this, [this]()
{
//LtsWidgets::LtsGlobalWaitDialog::getInstance()->wait(); // resume plugin manager's loading screen after this ui
LtsWidgets::LtsGlobalWaitDialog::getInstance()->setVisible(true);
m_close = true;
close();
});
//LtsWidgets::LtsGlobalWaitDialog::getInstance()->done(); // interrupt plugin manager's loading screen for this ui
}
ExerciseChooser::~ExerciseChooser()
{
delete m_ui;
}
bool ExerciseChooser::init(LtsSession::LtsSession *session)
{
m_session = session;
std::shared_ptr<ExerciseManagement::Interface::Dtc> dtc;
if (!session->getDtc<ExerciseManagement::DataInterface>(dtc))
return false;
std::shared_ptr<ExerciseManagement::Interface::Ftc> ftc;
if (!session->getFtc<ExerciseManagement::DataInterface>(ftc))
return false;
if (!session->getDtc<OperatorManagement::DataInterface>(m_opmDtc))
return false;
std::shared_ptr<ProjectDataManagement::Interface::Dtc> pdmDtc;
if (!session->getDtc<ProjectDataManagement::DataInterface>(pdmDtc))
return false;
std::shared_ptr<AssetManagement::Interface::Dtc> asmDtc;
if (!session->getDtc<AssetManagement::DataInterface>(asmDtc))
return false;
delete m_model;
delete m_proxyModel;
m_model = new ExerciseManagementDialogModel(this);
m_model->initModel(dtc, ftc, asmDtc, pdmDtc, true, true);
m_proxyModel = new ExerciseManagementProxyModel(this);
m_proxyModel->setAdminExerciseVisible(true);
m_proxyModel->setVisibleExerciseStates({ExerciseState::Created, ExerciseState::Started, ExerciseState::Paused, ExerciseState::Stopped});
m_proxyModel->setSourceModel(m_model);
m_proxyModel->setSortRole(Qt::UserRole);
m_proxyModel->sort(0);
CustomViewExercise *customViewExerciseDummy = new CustomViewExercise();
m_model->setImageSizeConstraints(customViewExerciseDummy->imageSize());
delete customViewExerciseDummy;
connect(m_opmDtc.get(), &OperatorManagement::Interface::Dtc::userChanged,
this, &ExerciseChooser::onUserChanged);
const int opId = LtsSessionData::LtsSessionData::getInstance()->getOperatorId();
onUserChanged(m_opmDtc->user(opId), DataModification::eAdded);
m_ui->widget->selectCustomView();
m_ui->widget->setSelectionMode(QAbstractItemView::SelectionMode::SingleSelection);
m_ui->widget->setModel(m_proxyModel, [this]() { return new CustomViewExercise(this); });
for (int i = 0; i < m_proxyModel->columnCount(); ++i)
m_ui->widget->hideColumn(i);
m_ui->widget->showColumn(ExerciseManagement::ExerciseManagementDialogModel::Name);
return true;
}
void ExerciseChooser::enaDisa()
{
m_ui->pbSelect->setEnabled(m_ui->widget->selectedRows().length() == 1);
}
void ExerciseChooser::reject()
{
LtsWidgets::LtsGlobalWaitDialog::getInstance()->setVisible(true);
if (!m_selected)
emit signalQuit();
QDialog::reject();
}
void ExerciseChooser::closeEvent(QCloseEvent *event) // TODO: override reject() TODO: renew this method
{
if (!m_close)
{
event->ignore();
return;
}
LtsWidgets::LtsGlobalWaitDialog::getInstance()->setVisible(true);
if (!m_selected)
emit signalQuit();
}
void ExerciseChooser::slotExerciseSelected()
{
if (m_selected)
return;
m_selected = true;
const QModelIndex idx = m_ui->widget->currentIndex();
const Exercise ex = m_model->getRowData(idx.row());
if (ex.id() < 0)
return;
setEnabled(false);
//hide();
//QCoreApplication::processEvents();
LtsWidgets::LtsGlobalWaitDialog::getInstance()->setVisible(true);
emit signalSelectExercise(ex.id());
m_close = true;
close();
}
void ExerciseChooser::onUserChanged(const OperatorManagement::User &user, DataModification mod)
{
if (!m_session || !m_proxyModel)
return;
const int opId = LtsSessionData::LtsSessionData::getInstance()->getOperatorId();
if (user.id() != opId)
return;
if (mod == DataModification::eRemoved)
{
m_proxyModel->setVisibleExerciseIds({});
return;
}
const bool hasAdminRights = std::any_of(user.effectiveAcls().begin(), user.effectiveAcls().end(),
[](int val) { return val == OperatorRights::Administrator; });
if (m_session->app() == LtsAppDescriptor::App::OC ||
(hasAdminRights && (m_session->app() == LtsAppDescriptor::App::Situation ||
m_session->app() == LtsAppDescriptor::App::PlanEditor)))
m_proxyModel->setAdminExerciseVisible(true);
else
m_proxyModel->setAdminExerciseVisible(false);
m_proxyModel->setVisibleExerciseIds(LtsUtils::convert<QVector<int>>(user.exerciseIds()));
}
}
@@ -0,0 +1,73 @@
/**
* @RDE_HEADER@
* ExerciseChooser Payload UI
* $Id$
* $HeadURL$
* $Author$
* Created by Mike Wille, SLSE, 2016-08-12
*/
#pragma once
#include <QDialog>
#include <memory>
#include <LtsUtilsCore/data_modification_enum.h>
namespace Ui
{
class ExerciseChooser;
}
namespace LtsSession
{
class LtsSession;
}
namespace OperatorManagement
{
class User;
namespace Interface {
class Dtc;
}
}
namespace ExerciseManagement
{
class ExerciseManagementDialogModel;
class ExerciseManagementProxyModel;
class ExerciseChooser : public QDialog // TODO: move me directly to Gui ?
{
Q_OBJECT
public:
explicit ExerciseChooser(QWidget *parent = nullptr);
bool init(LtsSession::LtsSession *session);
~ExerciseChooser();
void selectExercise(int exerciseId);
protected:
void closeEvent(QCloseEvent *event) override;
private slots:
void slotExerciseSelected();
void enaDisa();
void reject() override;
void onUserChanged(const OperatorManagement::User &user, DataModification mod);
signals:
void signalQuit();
void signalSelectExercise(int exercise);
private:
std::shared_ptr<OperatorManagement::Interface::Dtc> m_opmDtc;
Ui::ExerciseChooser *m_ui{nullptr};
ExerciseManagementDialogModel *m_model{nullptr};
ExerciseManagementProxyModel *m_proxyModel{nullptr};
LtsSession::LtsSession *m_session{nullptr};
bool m_selected{false};
bool m_close{false};
};
} // namespace ExerciseManagement
@@ -0,0 +1,96 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ExerciseChooser</class>
<widget class="QDialog" name="ExerciseChooser">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1300</width>
<height>820</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>RME EXCON - Exercise Chooser</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,0">
<item>
<layout class="QVBoxLayout" name="excLayout" stretch="0,999">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Login to Exercise:</string>
</property>
</widget>
</item>
<item>
<widget class="LtsDataView::LtsDataView" name="widget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>600</width>
<height>300</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="pbQuit">
<property name="text">
<string>Quit</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="pbSelect">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Select</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LtsDataView::LtsDataView</class>
<extends>QWidget</extends>
<header>LtsDataView/lts_data_view.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,185 @@
/**
* @RDE_HEADER@
* ExerciseManangement - Exercise Overview Dialog
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#include "exm_dialog.h"
#include "ui_exm_dialog.h"
#include "exm_dialog_model.h"
#include "exm_edit_dialog.h"
#include "CustomViews/exm_exercise.h"
#include <Plugins/ExerciseManagement/exm_data_plugin_interface.h>
#include <Plugins/AssetManagement/asm_data_plugin_interface.h>
#include <Plugins/ProjectDataManagement/pdm_data_plugin_interface.h>
#include <Services/FileManagement/flm_ftc.h>
#include <LtsSession/lts_session_data.h>
#include <LtsUtilsSettings/settings.h>
namespace ExerciseManagement
{
//---------------------------------
// ExerciseManagementDialog
//---------------------------------
ExerciseManagementDialog::ExerciseManagementDialog(const QString &menuGroup, QWidget *parent)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::CloseOnly)
, m_model(nullptr)
, m_ui(new Ui::ExerciseManagementDialog)
, m_session(nullptr)
, m_ftc(nullptr)
, m_menuGroup(menuGroup)
, m_requestHelper(new LtsUtils::RequestHelper(this))
, m_logger(getLogger("ExerciseManagementDialog"))
{
m_ui->setupUi(this);
setOnlineHelpFilename(QStringLiteral("Administrator-Exercises"));
m_buttonBox->connectButton(LtsWidgets::DialogButton::Add, this, &ExerciseManagementDialog::onAddExercise);
m_buttonBox->connectButton(LtsWidgets::DialogButton::Edit, this, &ExerciseManagementDialog::onEditExercise);
m_buttonBox->connectButton(LtsWidgets::DialogButton::Remove, this, &ExerciseManagementDialog::onRemoveExercise);
connect(m_ui->widget, &LtsDataView::LtsDataView::signalDoubleClicked,
this, &ExerciseManagementDialog::onEditExercise);
}
ExerciseManagementDialog::~ExerciseManagementDialog()
{
delete m_ui;
}
void ExerciseManagementDialog::retranslate()
{
translate(m_ui, tr("Exercises"));
}
void ExerciseManagementDialog::tableColumnOrganiserSetting()
{
//LtsColumnOrganiser
m_ui->widget->setColumnsOrganiserEnabled(identifier(), true);
}
bool ExerciseManagementDialog::init(LtsSession::LtsSessionDataDds *session)
{
m_session = session;
std::shared_ptr<ExerciseManagement::Interface::Dtc> dtc;
std::shared_ptr<AssetManagement::Interface::Dtc> asmDtc;
std::shared_ptr<ProjectDataManagement::Interface::Dtc> pdmDtc;
if (!m_session->getDtc<ExerciseManagement::DataInterface>(dtc))
return false;
if (!m_session->getFtc<ExerciseManagement::DataInterface>(m_ftc))
return false;
if (!m_session->getDtc<ProjectDataManagement::DataInterface>(pdmDtc))
return false;
if (!m_session->getDtc<AssetManagement::DataInterface>(asmDtc))
return false;
if (!m_session->getDtc<FileManagement::DataInterface>(m_flmDtc))
return false;
if (!m_session->getFtc<FileManagement::DataInterface>(m_flmFtc))
return false;
m_flmDtc->enableAll();
m_model = new ExerciseManagementDialogModel(this);
m_model->initModel(dtc, m_ftc, asmDtc, pdmDtc, true);
auto proxy = new ExerciseManagementProxyModel(this);
proxy->setSourceModel(m_model);
proxy->setAdminExerciseVisible(false);
proxy->setVisibleExerciseIds({-1});
m_ui->widget->setModel(proxy, [this]() { return new CustomViewExercise(this); });
m_ui->widget->hideColumn(ExerciseManagementDialogModel::Image);
const bool hasLinkedExercises = LtsUtils::ProjectSettings::isFunctionEnabled(QStringLiteral("Exercises"),
QStringLiteral("CanBeLinked"));
const bool hasHlaInterface = LtsUtils::ProjectSettings::isFunctionEnabled(QStringLiteral("Exercises"),
QStringLiteral("HasHlaInterface"));
m_ui->widget->setColumnHidden(ExerciseManagementDialogModel::LinkedId, !hasLinkedExercises);
m_ui->widget->setColumnHidden(ExerciseManagementDialogModel::HasHlaInterface, !hasHlaInterface);
connect(m_ui->widget, &LtsDataView::LtsDataView::signalSelectionChanged,
this, &ExerciseManagementDialog::enaDisa);
enaDisa();
LtsUtils::ProjectSettings *ps = LtsUtils::ProjectSettings::getInstance();
const bool enableEditPhases = ps->value(QStringLiteral("exm"),
QStringLiteral("enableEditPhases")).toBool();
if (!enableEditPhases)
m_ui->widget->hideColumn(ExerciseManagementDialogModel::ActivePhase);
return true;
}
void ExerciseManagementDialog::enaDisa()
{
QModelIndexList selectedRows = m_ui->widget->selectedRows();
const int cntSelectedRows = selectedRows.size();
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Edit, cntSelectedRows == 1);
const QModelIndex curIdx = m_ui->widget->currentIndex();
const ExerciseManagement::ExerciseState state = m_model->getRowData(curIdx.row()).state();
const bool isRemovable = (state == ExerciseManagement::ExerciseState::Unknown ||
state == ExerciseManagement::ExerciseState::Created ||
state == ExerciseManagement::ExerciseState::Stopped ||
state == ExerciseManagement::ExerciseState::Terminated);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Remove, curIdx.isValid() && isRemovable);
}
void ExerciseManagementDialog::onAddExercise()
{
ExerciseManagementEditDialog *dialog = new ExerciseManagementEditDialog(this);
dialog->init(m_session, m_menuGroup, -1 /* new exercise */);
addDialog(dialog, m_menuGroup, QStringLiteral("NewExercise"));
}
void ExerciseManagementDialog::onRemoveExercise()
{
const QModelIndex curIdx = m_ui->widget->currentIndex();
if (!curIdx.isValid())
return;
const int exId = m_model->getRowData(curIdx.row()).id();
const int folderId = m_flmDtc->getExerciseFolderId(exId);
if (folderId > 0)
{
Core::RemoveElementRequest req(folderId);
m_requestHelper->startSingleRequest([req, this]()
{
return m_flmFtc->folderRemoveRequest(req, this);
});
}
ExerciseManagement::ExerciseRemoveRequest req(exId, false);
m_requestHelper->startSingleRequest([req, this]()
{
m_ftc->enableExerciseRemove();
return m_ftc->exerciseRemoveRequest(req, this);
});
}
void ExerciseManagementDialog::onEditExercise()
{
const QModelIndex idx = m_ui->widget->currentIndex();
const Exercise ex = m_model->getRowData(idx.row());
if (ex.id() <= 0)
return;
DEBUG_LOG(m_logger) << "current EXId: " << ex.id();
ExerciseManagementEditDialog *dialog = new ExerciseManagementEditDialog(this);
dialog->init(m_session, m_menuGroup, ex.id());
const QString identifier = QStringLiteral("EditExercise%1").arg(ex.id());
addDialog(dialog, m_menuGroup, identifier);
}
} // namespace ExerciseManagement
@@ -0,0 +1,67 @@
/**
* @RDE_HEADER@
* ExerciseManangement - Exercise Overview Dialog
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#pragma once
#include <ExerciseManagement/exm_ftc.h>
#include <ExerciseManagement/exm_dtc.h>
#include <ExerciseManagement/logger.h>
#include <LtsWidgets/lts_dialog.h>
#include <LtsUtilsGuiDds/request_helper.h>
#include <LtsSession/lts_session.h>
#include <FileManagement/flm_dtc.h>
#include <FileManagement/flm_ftc.h>
namespace Ui
{
class ExerciseManagementDialog;
}
namespace ExerciseManagement
{
class ExerciseManagementDialogModel;
// --------------------------------------------------------
// ExerciseManagementDialog
// --------------------------------------------------------
class ExerciseManagementDialog : public LtsWidgets::LtsDialog
, protected ExerciseManagement::Interface::Ftc::ExerciseRemoveReplyHandler
, protected FileManagement::Interface::Ftc::FolderRemoveReplyHandler
{
Q_OBJECT
public:
explicit ExerciseManagementDialog(const QString &menuGroup, QWidget *parent = nullptr);
~ExerciseManagementDialog();
bool init(LtsSession::LtsSessionDataDds *session);
private slots:
void enaDisa();
void onAddExercise();
void onEditExercise();
void onRemoveExercise();
private:
void retranslate() override;
void onExerciseRemoveReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
void onFolderRemoveReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
void tableColumnOrganiserSetting() override;
ExerciseManagementDialogModel *m_model;
Ui::ExerciseManagementDialog *m_ui;
LtsSession::LtsSessionDataDds *m_session;
std::shared_ptr<ExerciseManagement::Interface::Ftc> m_ftc;
std::shared_ptr<FileManagement::Interface::Dtc> m_flmDtc;
std::shared_ptr<FileManagement::Interface::Ftc> m_flmFtc;
QString m_menuGroup;
LtsUtils::RequestHelper *m_requestHelper;
LOGGER_T m_logger;
};
}
@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ExerciseManagementDialog</class>
<widget class="QWidget" name="ExerciseManagementDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>600</width>
<height>500</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Exercise Management</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="LtsDataView::LtsDataView" name="widget">
<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>
@@ -0,0 +1,315 @@
/**
* @RDE_HEADER@
* HMI Plugin for ExerciseManangement - Exercise Overview Dialog Model
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#include "exm_dialog_model.h"
#include <LtsUtilsCore/dds_vector.h>
#include <ExerciseManagement/exm_translation.h>
#include <QTimer>
namespace ExerciseManagement
{
//---------------------------------
// ExerciseManagementDialogModel
//---------------------------------
ExerciseManagementDialogModel::ExerciseManagementDialogModel(QObject *parent)
: LtsWidgets::LtsAbstractTableModel<ExerciseManagement::Exercise>({tr("Id"),
tr("Name"),
tr("Training Area"),
tr("Begin"),
tr("End"),
tr("Started"),
tr("Stopped"),
tr("Status"),
tr("Radio Group"),
tr("Active Phase"),
tr("Created"),
tr("Time Zone"),
tr("Forces"),
tr("Description"),
tr("Linked Exercise"),
tr("Transferred"),
tr("HLA"),
tr("Image")},
parent)
, m_exmDtc(nullptr)
, m_asmDtc(nullptr)
, m_pdmDtc(nullptr)
, m_logger(getLogger("ExerciseManagementDialogModel"))
{}
bool ExerciseManagementDialogModel::initModel(const std::shared_ptr<ExerciseManagement::Interface::Dtc> &dtc,
const std::shared_ptr<ExerciseManagement::Interface::Ftc> &ftc,
const std::shared_ptr<AssetManagement::Interface::Dtc> &asmDtc,
const std::shared_ptr<ProjectDataManagement::Interface::Dtc> &pdmDtc,
bool addAdminExercise,
bool preloadExerciseImages)
{
m_exmDtc = dtc;
m_exmFtc = ftc;
m_asmDtc = asmDtc;
m_pdmDtc = pdmDtc;
connect(m_exmDtc.get(), &ExerciseManagement::Interface::Dtc::exerciseChanged,
this, [this, preloadExerciseImages](const ExerciseManagement::Exercise &ex, DataModification mod)
{
onDataChanged(ex, mod);
if (mod != DataModification::eAdded)
return;
if (preloadExerciseImages)
addImagePreload(ex.id());
});
if (addAdminExercise)
{
// insert admin session manually
ExerciseManagement::Exercise adminExercise;
adminExercise.name(tr("Superordinate Config / Administration").toStdString());
adminExercise.id(0);
insertRow(adminExercise);
}
// insert Model
m_exmDtc->exercises([this, preloadExerciseImages](const ExerciseManagement::Exercise &ex)
{
insertRow(ex);
if (preloadExerciseImages)
addImagePreload(ex.id());
});
INFO_LOG(m_logger) << "initModel - #exercises: " << m_vecData.size();
return true;
}
int ExerciseManagementDialogModel::getId(const ExerciseManagement::Exercise &data) const
{
return data.id();
}
void ExerciseManagementDialogModel::addImagePreload(int32_t exId) // one image at a time - only fetch next image if last one already received
{
if (m_exerciseImages.contains(exId)) // don't preload mages that are already loaded
return;
m_preloadImages += exId;
if (m_imagePreloadPending) // only start preloading if not currently preloading one currently
return;
m_imagePreloadPending = true;
preloadNextImage();
}
void ExerciseManagementDialogModel::preloadNextImage()
{
if (m_preloadImages.isEmpty())
return;
m_exmFtc->enableGetExerciseImage();
m_exmFtc->getExerciseImageRequest(GetExerciseImageRequest(m_preloadImages.takeFirst(), m_imageSize.height(), m_imageSize.width(), false),
createGetExerciseImageRequester());
}
GetExerciseImageRequester *ExerciseManagementDialogModel::createGetExerciseImageRequester()
{
auto r = GetExerciseImageRequester::createGetExerciseImageRequester();
connect(r, &GetExerciseImageRequester::signalDone,
this, [this, r]()
{
m_imagePreloadPending = false;
const GetExerciseImageReply &reply(r->reply());
if (reply.errorString().empty())
{
m_exerciseImages.insert(reply.id(), LtsUtils::toQByteArray(reply.imageData()));
// tell the view that it should reload the image
QModelIndex idx(findIndexForId(reply.id(), 0)); // XXX: Florian's Workaround - dataChanged works with column 0, but not with Columns::Image! Works for now! Better than resetting the model.
emit dataChanged(idx, idx, { Qt::DisplayRole });
}
else
{
QString msg(QString::fromStdString(reply.errorString()));
for (const std::string &arg : qAsConst(reply.errorParams()))
msg = msg.arg(QString::fromStdString(arg));
ERROR_LOG(m_logger) << "image preload failed: " << msg;
}
QTimer::singleShot(1, this, &ExerciseManagementDialogModel::preloadNextImage); // schedule requester deletion before asking for the next image (not really necessary but 100 times cleaner)
});
return r;
}
void ExerciseManagementDialogModel::setImageSizeConstraints(const QSize &size)
{
m_imageSize = size;
}
QVariant ExerciseManagementDialogModel::data(const QModelIndex &index, int role) const
{
if ((role != Qt::DisplayRole && role != Qt::UserRole && role != Qt::TextColorRole) || !indexIsValid(index))
return QVariant();
const ExerciseManagement::Exercise &ex = m_vecData.at(index.row());
if (role == Qt::DisplayRole)
{
switch (index.column())
{
case ExerciseManagementDialogModel::Columns::Name:
return QString::fromStdString(ex.name());
case ExerciseManagementDialogModel::Columns::TrainingArea:
{
const AssetManagement::TrainingArea ta = m_asmDtc->trainingArea(ex.trainingAreaId());
return QString::fromStdString(ta.name());
}
case ExerciseManagementDialogModel::Columns::Begin:
return QDateTime::fromMSecsSinceEpoch(ex.beginTime());
case ExerciseManagementDialogModel::Columns::End:
return QDateTime::fromMSecsSinceEpoch(ex.endTime());
case ExerciseManagementDialogModel::Columns::Started:
return QDateTime::fromMSecsSinceEpoch(ex.startTime());
case ExerciseManagementDialogModel::Columns::Stopped:
return QDateTime::fromMSecsSinceEpoch(ex.stopTime());
case ExerciseManagementDialogModel::Columns::Status:
return ExerciseManagement::toString(ex.state());
case ExerciseManagementDialogModel::Columns::RadioGroup:
if (ex.radioGroupId().is_set())
return m_pdmDtc->trRadioGroupName(ex.radioGroupId().get());
return QStringLiteral(" - ");
case ExerciseManagementDialogModel::Columns::ActivePhase:
return QString::fromStdString(m_exmDtc->exercisePhase(ex.activePhaseId()).name());
case ExerciseManagementDialogModel::Columns::Created:
return QDateTime::fromMSecsSinceEpoch(ex.created());
case ExerciseManagementDialogModel::Columns::TimeZone:
return (ex.defaultTimeZone() == 0) ? QStringLiteral("-") : QString(QLatin1Char(ex.defaultTimeZone()));
case ExerciseManagementDialogModel::Columns::Forces:
return QString::fromStdString(ex.forces());
case ExerciseManagementDialogModel::Columns::Description:
return QString::fromStdString(ex.description());
case ExerciseManagementDialogModel::Columns::Image:
return m_exerciseImages.value(ex.id());
case ExerciseManagementDialogModel::Columns::Id:
return ex.id();
case ExerciseManagementDialogModel::Columns::LinkedId:
{
if (ex.linkedExerciseId() == 0)
return QVariant();
const int row = findRowForId(ex.linkedExerciseId());
if (row < 0)
return QStringLiteral("????? - %1").arg(ex.linkedExerciseId());
return QString(QString::fromStdString(m_vecData.at(row).name()) +
QStringLiteral(" (%1)").arg(ex.linkedExerciseId()));
}
case ExerciseManagementDialogModel::Columns::Transferred:
return ex.transferred() ? tr("Yes") : tr("No");
case ExerciseManagementDialogModel::Columns::HasHlaInterface:
return ex.hasHlaInterface() ? tr("Yes") : tr("No");
}
}
else if (role == Qt::UserRole) // sorting order
{
if (ex.id() == 0)
return 0;
switch (ex.state().underlying())
{
case ExerciseState::Unknown: return 6;
case ExerciseState::Created: return 3;
case ExerciseState::Started: return 1;
case ExerciseState::Paused: return 2;
case ExerciseState::Stopped: return 4;
case ExerciseState::Terminated: return 5;
}
return 99;
}
else if (role == Qt::TextColorRole)
{
if (index.column() == ExerciseManagementDialogModel::Columns::Status)
{
switch (ex.state().underlying())
{
case ExerciseState::Unknown: return QColor(Qt::black);
case ExerciseState::Created: return QColor(Qt::cyan);
case ExerciseState::Started: return QColor(Qt::darkGreen);
case ExerciseState::Paused: return QColor(Qt::darkYellow);
case ExerciseState::Stopped: return QColor(Qt::magenta);
case ExerciseState::Terminated: return QColor(Qt::red);
}
}
}
return QVariant();
}
//
// ExerciseManagementProxyModel
//
void ExerciseManagementProxyModel::setAdminExerciseVisible(bool bAdminVisible)
{
if (m_bAdminVisible == bAdminVisible)
return;
m_bAdminVisible = bAdminVisible;
invalidateFilter();
}
void ExerciseManagementProxyModel::setVisibleExerciseIds(const QVector<int> &exIds)
{
if (m_exIds == exIds)
return;
m_exIds = exIds;
invalidateFilter();
}
void ExerciseManagementProxyModel::setVisibleExerciseStates(const QVector<ExerciseState> &visibleStates)
{
if (m_visibleStates == visibleStates)
return;
m_visibleStates = visibleStates;
invalidateFilter();
}
void ExerciseManagementProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
{
m_sourceModel = qobject_cast<ExerciseManagementDialogModel*>(sourceModel);
LtsWidgets::LtsColumnFilterProxyModel::setSourceModel(sourceModel);
}
bool ExerciseManagementProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{
if (!m_sourceModel || source_parent.isValid() || source_row < 0 || source_row >= m_sourceModel->m_vecData.size())
return LtsWidgets::LtsColumnFilterProxyModel::filterAcceptsRow(source_row, source_parent);
const auto &ex = m_sourceModel->m_vecData.at(source_row);
if (ex.id() == 0)
{
if (!m_bAdminVisible)
return false;
return LtsWidgets::LtsColumnFilterProxyModel::filterAcceptsRow(source_row, source_parent);
}
if (!m_exIds.contains(ex.id()) && !m_exIds.contains(-1))
return false;
if (!m_visibleStates.contains(ex.state()) && !m_visibleStates.isEmpty())
return false;
return LtsWidgets::LtsColumnFilterProxyModel::filterAcceptsRow(source_row, source_parent);
}
} // namespace ExerciseManagement
@@ -0,0 +1,155 @@
/**
* @RDE_HEADER@
* ExerciseManangement - Exercise Overview Dialog Model
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#pragma once
#include <ExerciseManagement/logger.h>
#include <LtsWidgets/lts_abstract_table_model.h>
#include <LtsWidgets/lts_column_filter_proxy_model.h>
#include <AssetManagement/asm_dtc.h>
#include <ExerciseManagement/exm_dtc.h>
#include <ExerciseManagement/exm_ftc.h>
#include <ProjectDataManagement/pdm_dtc.h>
namespace ExerciseManagement
{
class AbstractRequester
: public QObject
{
Q_OBJECT
public:
AbstractRequester()
: QObject(nullptr)
{}
signals:
void signalDone();
};
// TODO: autogen!
class GetExerciseImageRequester
: public AbstractRequester
, public ExerciseManagement::Interface::Ftc::GetExerciseImageReplyHandler
{
Q_OBJECT
private:
GetExerciseImageRequester() = default;
public:
static GetExerciseImageRequester *createGetExerciseImageRequester()
{
return new GetExerciseImageRequester;
}
const GetExerciseImageReply &reply() const
{
return m_reply;
}
void onGetExerciseImageReply(const GetExerciseImageReply &reply) override final
{
m_reply = reply;
emit signalDone();
deleteLater();
}
private:
GetExerciseImageReply m_reply;
};
// --------------------------------------------------------
// ExerciseManagementModel
// --------------------------------------------------------
class ExerciseManagementDialogModel final
: public LtsWidgets::LtsAbstractTableModel<ExerciseManagement::Exercise>
{
Q_OBJECT
public:
enum Columns
{
Id,
Name,
TrainingArea,
Begin,
End,
Started,
Stopped,
Status,
RadioGroup,
ActivePhase,
Created,
TimeZone,
Forces,
Description,
LinkedId,
Transferred,
HasHlaInterface,
Image
};
explicit ExerciseManagementDialogModel(QObject *parent = nullptr);
bool initModel(const std::shared_ptr<ExerciseManagement::Interface::Dtc> &dtc,
const std::shared_ptr<ExerciseManagement::Interface::Ftc> &ftc,
const std::shared_ptr<AssetManagement::Interface::Dtc> &asmDtc,
const std::shared_ptr<ProjectDataManagement::Interface::Dtc> &pdmDtc,
bool addAdminExercise = false,
bool preloadExerciseImages = false);
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override final;
void addImagePreload(int32_t exId);
void setImageSizeConstraints(const QSize &size);
protected:
int getId(const ExerciseManagement::Exercise &data) const override final;
private slots:
void preloadNextImage();
private:
GetExerciseImageRequester *createGetExerciseImageRequester();
std::shared_ptr<ExerciseManagement::Interface::Dtc> m_exmDtc;
std::shared_ptr<ExerciseManagement::Interface::Ftc> m_exmFtc;
std::shared_ptr<AssetManagement::Interface::Dtc> m_asmDtc;
std::shared_ptr<ProjectDataManagement::Interface::Dtc> m_pdmDtc;
QVector<int32_t> m_preloadImages;
QMap<int32_t /* exId */, QByteArray /* image */> m_exerciseImages;
bool m_imagePreloadPending { false };
QSize m_imageSize;
LOGGER_T m_logger;
friend class ExerciseManagementProxyModel;
};
class ExerciseManagementProxyModel final : public LtsWidgets::LtsColumnFilterProxyModel
{
Q_OBJECT
public:
using LtsWidgets::LtsColumnFilterProxyModel::LtsColumnFilterProxyModel;
void setAdminExerciseVisible(bool bAdminVisible);
void setVisibleExerciseStates(const QVector<ExerciseState> &visibleStates);
void setVisibleExerciseIds(const QVector<int> &exIds);
void setSourceModel(QAbstractItemModel *sourceModel) override;
protected:
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
private:
ExerciseManagementDialogModel *m_sourceModel = nullptr;
QVector<int> m_exIds;
QVector<ExerciseState> m_visibleStates;
bool m_bAdminVisible = false;
};
}
@@ -0,0 +1,164 @@
/**
* @RDE_HEADER@
* ExerciseManagement - Operator Exercise Edit ADLER Visible Parties Model
* $Id$
* $HeadURL$
* $Author$
* Created by Astrid Mueller, ESZE, 2026-02-25
*/
#include "exm_edit_adler_visible_parties_model.h"
#include <ParticipantManagement/ppm_translation.h>
#include <ParticipantManagement/ppm_dtc.h>
#include <QJsonArray>
#include <QJsonObject>
#include <QJsonDocument>
namespace ExerciseManagement
{
ExerciseEditAdlerVisiblePartiesModel::ExerciseEditAdlerVisiblePartiesModel(int operatorId,
int exerciseId,
QObject *parent)
: LtsWidgets::LtsCheckableTableModel<QPair<bool, ParticipantManagement::Party>>({tr("Id"), tr("Name")}, ColName, parent)
, m_opmDtc(nullptr)
, m_operatorId (operatorId)
, m_exerciseId(exerciseId)
{
}
ExerciseEditAdlerVisiblePartiesModel::~ExerciseEditAdlerVisiblePartiesModel()
{
}
bool ExerciseEditAdlerVisiblePartiesModel::init(LtsSession::LtsSessionDataDds *session)
{
session->getDtc<OperatorManagement::DataInterface>(m_opmDtc);
std::shared_ptr<ParticipantManagement::Interface::Dtc> ppmDtc;
if (!session->getDtc<ParticipantManagement::DataInterface>(ppmDtc))
return false;
connect(ppmDtc.get(), &ParticipantManagement::Interface::Dtc::partyChanged,
this, &ExerciseEditAdlerVisiblePartiesModel::onPartiesChanged, Qt::UniqueConnection);
auto cb = [this](const ParticipantManagement::Party &party)
{
onPartiesChanged(party, DataModification::eAdded);
};
ppmDtc->partys(cb);
return true;
}
QVariant ExerciseEditAdlerVisiblePartiesModel::data(const QModelIndex &index, int role) const
{
if (role != Qt::DisplayRole)
return LtsCheckableTableModel::data(index, role);
if (!indexIsValid(index))
return {};
const ParticipantManagement::Party &party = m_vecData.at(index.row()).second;
switch (index.column())
{
case ColId:
return party.id();
case ColName:
return ParticipantManagement::trPartyName(party.name());
}
return {};
}
void ExerciseEditAdlerVisiblePartiesModel::onPartiesChanged(const ParticipantManagement::Party &data, DataModification mod)
{
switch(mod)
{
case DataModification::eAdded:
{
insertRow(qMakePair(hasAdlerParty(data), data));
break;
}
case DataModification::eRemoved:
{
for (int i = 0; i < m_vecData.size(); ++i)
{
if (m_vecData.at(i).second.id() == data.id())
{
removeRow(i);
return;
}
}
break;
}
case DataModification::eModified:
{
for (int i = 0; i < m_vecData.size(); ++i)
{
if (m_vecData.at(i).second.id() == data.id())
{
m_vecData[i].second = data;
const QModelIndex idx(index(i, ColName, QModelIndex()));
emit dataChanged(idx, idx, {Qt::DisplayRole});
break;
}
}
break;
} // case Modified
} // switch
}
bool ExerciseEditAdlerVisiblePartiesModel::isFiltered(const QPair<bool, ParticipantManagement::Party> &data, DataModification modType) const
{
// pool and support alway checked but hidden for user
if (data.second.id() <= 1 )
return true;
return LtsCheckableTableModel::isFiltered(data, modType);
}
bool ExerciseEditAdlerVisiblePartiesModel::hasAdlerParty(const ParticipantManagement::Party &party) const
{
const auto visiblePartiesByExercise = m_opmDtc->user(m_operatorId).visiblePartiesByExercise();
bool partyVisible = false;
for (const auto &exerciseParties : visiblePartiesByExercise)
{
if (exerciseParties.exerciseId() != m_exerciseId)
continue;
if (!exerciseParties.visibleParties().is_set()) //has_value not support on windows yet so we need depricated is_set
return false;
// if the party is not visible, you can not get this one for ADLER
// must not occur, but is checked,
for (const auto &partyId : exerciseParties.visibleParties().get())
if (partyId == party.id())
partyVisible = true;
if (!partyVisible)
return false;
// get properties
const QJsonObject properties(QJsonDocument::fromJson(QByteArray::fromStdString(exerciseParties.properties())).object());
const QJsonArray arr(properties.value(QStringLiteral("adlerAllowed")).toArray());
for (const auto &partyId : arr)
if (partyId == party.id())
return true;
return false;
}
return false;
}
int ExerciseEditAdlerVisiblePartiesModel::findRowForPartyId(int id) const
{
for (int i = 0; i < m_vecData.size(); ++i)
{
if (m_vecData.at(i).second.id() == id)
return i;
}
return -1;
}
}
@@ -0,0 +1,71 @@
/**
* @RDE_HEADER@
* ExerciseManagement - Operator Exercise Edit ADLER Visible Parties Model
* $Id$
* $HeadURL$
* $Author$
* Created by Astrid Mueller, ESZE, 2026-02-25
*/
#pragma once
#include <Plugins/OperatorManagement/Data/opm_data_plugin.h>
#include <Plugins/ParticipantManagement/Data/ppm_data_plugin.h>
#include <LtsSession/lts_session_data_dds.h>
#include <LtsWidgets/lts_checkable_table_model.h>
#include <QDebug>
#include <QPair>
namespace ExerciseManagement
{
class ExerciseEditAdlerVisiblePartiesModel : public LtsWidgets::LtsCheckableTableModel<QPair<bool, ParticipantManagement::Party>>
{
Q_OBJECT
public:
enum Columns
{
ColId,
ColName
};
explicit ExerciseEditAdlerVisiblePartiesModel(int operatorId = 0,
int exerciseId = 0,
QObject *parent = nullptr);
~ExerciseEditAdlerVisiblePartiesModel();
bool init(LtsSession::LtsSessionDataDds *session);
QVariant data(const QModelIndex &index, int role) const override;
Qt::ItemFlags flags(const QModelIndex &index) const override
{
Qt::ItemFlags flags = QAbstractTableModel::flags(index);
if (m_uncheckedPartyIds.contains(index.row()) && index.column() == ColName)
{
flags &= ~(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
}
else if (index.column() == ColName)
{
flags |= (Qt::ItemIsUserCheckable);
}
return flags;
}
void setUncheckedPartyIds(const QVector<int> uncheckedPartyIds){m_uncheckedPartyIds = uncheckedPartyIds;};
int findRowForPartyId(int id) const;
public slots:
void onPartiesChanged(const ParticipantManagement::Party &data, DataModification mod);
bool isFiltered(const QPair<bool, ParticipantManagement::Party> &data, DataModification modType) const override;
private:
bool hasAdlerParty(const ParticipantManagement::Party &party) const;
std::shared_ptr<OperatorManagement::Interface::Dtc> m_opmDtc;
QVector<int> m_uncheckedPartyIds;
int m_operatorId;
int m_exerciseId;
};
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,166 @@
/**
* @RDE_HEADER@
* ExerciseManangement - Exercise Edit Dialog
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#pragma once
#include <ExerciseManagement/exm_ftc.h>
#include <ExerciseManagement/exm_dtc.h>
#include <ExerciseManagement/logger.h>
#include <LtsWidgets/lts_dialog.h>
#include <LtsUtilsGuiDds/request_helper.h>
#include <LtsSession/lts_session_data_dds.h>
#include <Plugins/OperatorManagement/opm_data_plugin_interface.h>
#include <Plugins/AssetManagement/asm_data_plugin_interface.h>
#include <Plugins/ProjectDataManagement/pdm_data_plugin_interface.h>
#include <Plugins/ParticipantManagement/ppm_data_plugin_interface.h>
#include <Plugins/FileManagement/flm_data_plugin_interface.h>
#include <Plugins/FileManagement/flm_explorer_gui_plugin_interface.h>
#include <FileManagement/flm_translation.h>
namespace Ui
{
class ExerciseManagementEditDialog;
}
namespace ExerciseManagement
{
namespace JsonKeys
{
// general
inline QString XMLTYPE() { return QStringLiteral("XmlType"); }
inline QString XMLTYPEVALUE() { return FileManagement::toString(FileManagement::XmlType::EXMExerciseDescription); }
// Exercise
inline QString PHASES() { return QStringLiteral("phases"); }
inline QString OPERATORS() { return QStringLiteral("operators"); }
inline QString FORCES() { return QStringLiteral("forces"); }
inline QString DESCRIPTION() { return QStringLiteral("description"); }
// ExercisePhase:
inline QString PID() { return QStringLiteral("phaseId"); }
inline QString PNAME() { return QStringLiteral("phaseName"); }
inline QString PISDELETED() { return QStringLiteral("phaseIsDeleted"); }
inline QString PISUSED() { return QStringLiteral("phaseIsUsed"); }
inline QString PBEGINTIME() { return QStringLiteral("phaseBeginTime"); }
inline QString PENDTIME() { return QStringLiteral("phaseEndTime"); }
inline QString PDESCRIPTION() { return QStringLiteral("phaseDescription"); }
inline QString PEXERCISEID() { return QStringLiteral("phaseExerciseId"); }
} // namespace JsonKeys
class ExercisePhaseModel;
class ExercisePhaseProxyModel;
class ExerciseOperatorModel;
// --------------------------------------------------------
// ExerciseManagementEditDialog
// --------------------------------------------------------
class ExerciseManagementEditDialog final : public LtsWidgets::LtsDialog
, protected ExerciseManagement::Interface::Ftc::ExerciseCreateReplyHandler
, protected ExerciseManagement::Interface::Ftc::ExerciseModifyReplyHandler
, protected ExerciseManagement::Interface::Ftc::ExerciseImageModifyReplyHandler
, protected ExerciseManagement::Interface::Ftc::GetExerciseImageReplyHandler
, protected ExerciseManagement::Interface::Ftc::ExercisePhaseRemoveReplyHandler
, protected OperatorManagement::Interface::Ftc::OperatorCreateModifyReplyHandler
, protected FileManagement::Interface::Ftc::FolderModifyReplyHandler
, protected FileManagement::Interface::Ftc::FolderRemoveReplyHandler
{
Q_OBJECT
public:
explicit ExerciseManagementEditDialog(QWidget *parent = nullptr);
bool init(LtsSession::LtsSessionDataDds *session,
const QString &menuGroup,
const int exerciseId);
~ExerciseManagementEditDialog();
protected:
void onExerciseCreateReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
void onExerciseModifyReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
void onExerciseImageModifyReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); imageModifyError(); }
void onGetExerciseImageReply(const GetExerciseImageReply &reply) override final;
void onExercisePhaseRemoveReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
void onOperatorCreateModifyReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
void onFolderModifyReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
void onFolderRemoveReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
private slots:
void slotChangeImage();
void enaDisaOperatorsButtons();
void enaDisaPhaseButtons();
void onAddExercisePhase();
void onEditVisibleParties();
void onEditExercisePhase();
void onRemoveExercisePhase();
void onExport();
void onImport();
void onCreateFolders();
void onExerciseChanged(const Exercise &data, DataModification modType);
void onExercisePhaseChanged(const ExercisePhase &data, DataModification modType);
void onContextMenuRequested(const QPoint &position);
void onSelectAllUsers();
void onUnselectAllUsers();
void onTimeZoneChanged();
signals:
void sendData(const ExerciseManagement::Exercise &data);
private:
void retranslate() override;
bool apply() override final;
void enaDisa();
void fillStateCbx();
void fillTrainingAreaCbx();
void fillActivePhaseCbx();
void fillRadioGroupCbx();
void fillLinkedExercisesCbx();
void fillAllCbx();
void imageModifyError();
void sendModifiedOperators(int thisExerciseId);
int createFolder(int parentFolderId, const QString &folderName, bool isHidden = false);
bool createFolders(int newExId);
bool createExerciseFolders(int parentFolderId, const QStringList &folderNames);
ExerciseModifyRequest setRequestContent() const;
QByteArray exerciseToJson() const;
ExerciseModifyRequest jsonToExercise(const QByteArray &content) const;
void requestImage();
const QPixmap getPixmap() const;
int getExerciseFolder();
Ui::ExerciseManagementEditDialog *m_ui{nullptr};
LtsSession::LtsSessionDataDds *m_session{nullptr};
ExercisePhaseModel *m_phaseModel{nullptr};
ExercisePhaseProxyModel *m_phaseProxyModel{nullptr};
ExerciseOperatorModel *m_operatorModel{nullptr};
bool m_pictureChanged{false};
int m_exerciseId{-1};
QVariant m_initialRadioGroupId;
ExerciseState m_currentState;
std::shared_ptr<Interface::Dtc> m_dtc;
std::shared_ptr<Interface::Ftc> m_ftc;
std::shared_ptr<OperatorManagement::Interface::Dtc> m_opmDtc;
std::shared_ptr<AssetManagement::Interface::Dtc> m_asmDtc;
std::shared_ptr<ProjectDataManagement::Interface::Dtc> m_pdmDtc;
std::shared_ptr<ParticipantManagement::Interface::Dtc> m_ppmDtc;
std::shared_ptr<FileManagement::Interface::Dtc> m_flmDtc;
std::shared_ptr<FileManagement::Interface::Ftc> m_flmFtc;
std::shared_ptr<FileManagement::ForeignGuiInterface> m_flmGui;
QString m_menuGroup;
LtsUtils::RequestHelper *m_requestHelper{nullptr};
LOGGER_T m_logger;
template<class T>
bool removeElement(std::vector<T> &vec, T elem);
bool hasVisibleParties(const std::vector<OperatorManagement::PartiesByExercise> vpbe) const;
};
}
@@ -0,0 +1,317 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ExerciseManagementEditDialog</class>
<widget class="QWidget" name="ExerciseManagementEditDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1258</width>
<height>687</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Translated in Source</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="3" column="0">
<widget class="QLabel" name="lblState">
<property name="text">
<string>State:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="LtsWidgets::LtsComboBox" name="cbLinkedExercise">
<property name="insertPolicy">
<enum>QComboBox::InsertAlphabetically</enum>
</property>
</widget>
</item>
<item row="2" column="5">
<widget class="QComboBox" name="cbTimeZone"/>
</item>
<item row="0" column="6" rowspan="4">
<widget class="LtsWidgets::LtsImageEditor" name="imageEditor">
<property name="minimumSize">
<size>
<width>128</width>
<height>128</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>128</width>
<height>128</height>
</size>
</property>
<property name="toolTip">
<string>Select an Exercise Picture</string>
</property>
</widget>
</item>
<item row="3" column="3">
<widget class="LtsWidgets::LtsComboBox" name="cbActivePhase"/>
</item>
<item row="1" column="1">
<widget class="LtsWidgets::LtsComboBox" name="cbTrainingArea"/>
</item>
<item row="1" column="2">
<widget class="QLabel" name="lblRadioGroup">
<property name="text">
<string>Radio Group:</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="LtsWidgets::LtsComboBox" name="cbRadioGroup"/>
</item>
<item row="2" column="2">
<widget class="QLabel" name="lblEnd">
<property name="text">
<string>End Time:</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="lblName">
<property name="text">
<string>Name:</string>
</property>
</widget>
</item>
<item row="0" column="1" colspan="5">
<widget class="QLineEdit" name="leName"/>
</item>
<item row="4" column="2">
<widget class="QLabel" name="lbSymbolFilltype">
<property name="text">
<string>Symbol Filltype:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="lblTrainingArea">
<property name="text">
<string>Training Area:</string>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="LtsWidgets::LtsDateTimeEdit" name="dtEnd">
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
<property name="editTimezone">
<bool>false</bool>
</property>
</widget>
</item>
<item row="2" column="4">
<widget class="QLabel" name="lbSymbolFilltype_2">
<property name="text">
<string>Time Zone:</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="lblStart">
<property name="text">
<string>Begin Time:</string>
</property>
</widget>
</item>
<item row="5" column="0" colspan="7">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="LtsWidgets::LtsDateTimeEdit" name="dtBegin">
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
<property name="editTimezone">
<bool>false</bool>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="LtsWidgets::LtsComboBox" name="cbState"/>
</item>
<item row="1" column="4" colspan="2">
<widget class="QCheckBox" name="cbVisibleInWarehouse">
<property name="text">
<string>Visible in Warehouse System</string>
</property>
</widget>
</item>
<item row="4" column="3">
<widget class="QComboBox" name="cbSymbolFilltype">
<property name="insertPolicy">
<enum>QComboBox::InsertAlphabetically</enum>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="lblLinkedExercise">
<property name="text">
<string>Linked Exercise:</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QLabel" name="lblActivePhase">
<property name="text">
<string>Active Phase:</string>
</property>
</widget>
</item>
<item row="3" column="4" colspan="2">
<widget class="QCheckBox" name="cbStartHlaInterface">
<property name="text">
<string>Start HLA Interface</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QGridLayout" name="gridLayout_2">
<item row="2" column="0">
<widget class="QLabel" name="lblDesc">
<property name="text">
<string>Description:</string>
</property>
</widget>
</item>
<item row="1" column="2" rowspan="3">
<widget class="QLabel" name="lblPhases">
<property name="text">
<string>Phases:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QPlainTextEdit" name="pteDescription">
<property name="minimumSize">
<size>
<width>0</width>
<height>50</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>120</height>
</size>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPlainTextEdit" name="pteForces">
<property name="minimumSize">
<size>
<width>0</width>
<height>50</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>120</height>
</size>
</property>
</widget>
</item>
<item row="1" column="3" rowspan="3">
<widget class="LtsDataView::LtsDataView" name="dvPhases"/>
</item>
<item row="4" column="2" colspan="2">
<widget class="LtsWidgets::LtsDialogButtonBox" name="btbDvPhases">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="lblForces">
<property name="text">
<string>Forces:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="LtsDataView::LtsDataView" name="dvOperators"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="lblOperators">
<property name="text">
<string>Operators:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="LtsWidgets::LtsDialogButtonBox" name="btbDvOperators"/>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LtsWidgets::LtsDialogButtonBox</class>
<extends>QWidget</extends>
<header>LtsWidgets/lts_dialog_button_box.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>LtsWidgets::LtsImageEditor</class>
<extends>QWidget</extends>
<header>LtsWidgets/lts_image_editor.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>LtsWidgets::LtsComboBox</class>
<extends>QComboBox</extends>
<header>LtsWidgets/lts_combo_box.h</header>
</customwidget>
<customwidget>
<class>LtsWidgets::LtsDateTimeEdit</class>
<extends>QWidget</extends>
<header>LtsWidgets/lts_date_time_edit.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>LtsDataView::LtsDataView</class>
<extends>QWidget</extends>
<header>LtsDataView/lts_data_view.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>leName</tabstop>
<tabstop>cbTrainingArea</tabstop>
<tabstop>cbRadioGroup</tabstop>
<tabstop>cbVisibleInWarehouse</tabstop>
<tabstop>dtBegin</tabstop>
<tabstop>dtEnd</tabstop>
<tabstop>cbTimeZone</tabstop>
<tabstop>cbState</tabstop>
<tabstop>cbActivePhase</tabstop>
<tabstop>cbStartHlaInterface</tabstop>
<tabstop>cbLinkedExercise</tabstop>
<tabstop>cbSymbolFilltype</tabstop>
<tabstop>pteForces</tabstop>
<tabstop>pteDescription</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,346 @@
/**
* @RDE_HEADER@
* GUI Plugin for ExerciseManangement
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#include "exm_edit_gui_plugin.h"
#include "exm_dialog.h"
#include "exm_edit_dialog.h"
#include "exm_exercise_purpose.h"
#include "exm_phase_edit.h"
#include "exm_state_edit.h"
#include "exm_operator_edit.h"
#include "ExerciseChooser/exm_chooser.h"
#include <cstdlib> // for abort
#include <LtsSession/lts_session.h>
#include <LtsSession/lts_session_manager.h>
#include <LtsSession/lts_session_data.h>
#include <LtsWidgets/lts_background_widget.h>
#include <Services/ExerciseManagement/exm_dtc.h>
#include <Services/SituationReplayManagement/srm_dtc.h>
#include <Core/core_dtc.h> // SitRepMgr
#include <LtsCoordTrans/lts_coord_trans.h>
#include <LtsWidgets/lts_wait_dialog.h>
#include <ConnectDialog/connect_dialog_nt.h>
#include <ExerciseManagement/exm_operator_rights.h>
#include <LtsUtilsSettings/settings.h>
#include <QTimer>
#include <QDebug>
namespace ExerciseManagement
{
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.Exm.Edit"))
, m_dtc(nullptr)
, m_asmDtc(nullptr)
, m_mainBackground(nullptr)
{}
QVector<LtsWidgets::PluginData> InterfaceImpl::getActions()
{
QVector<LtsWidgets::PluginData> ret;
if(m_session->partitionType() == IDL::PartitionType::Global)
{
LtsWidgets::PluginData plData;
plData.menuGroup = menuGroup();
plData.menuText = tr("Exercises");
plData.menuIcon = QIcon(QLatin1String("icon:set_exercise_process.svg"));
plData.identifier = QLatin1String("exmExerciseEdit");
plData.operatorRight = OperatorRights::ExercisesEdit;
plData.exercisePart = LtsWidgets::ExercisePart::ePlanning;
plData.createWidgetFunc = [this](QWidget *parent)
{
return onShowExerciseManagementDialog(parent);
};
ret.append(plData);
}
if(m_session->partitionType() == IDL::PartitionType::Exercise)
{
#if !GUEZ_MODE || LTS_DEBUG // in GUEZ ein Übungstatus soll nur in Übergeordnete Übung geändert werden.
LtsWidgets::PluginData plStateEdit;
plStateEdit.menuGroup = menuGroup();
plStateEdit.menuText = tr("Exercise State");
plStateEdit.menuIcon = QIcon(QLatin1String("icon:set_exercise_process.svg"));
plStateEdit.identifier = QLatin1String("exmStateEdit");
plStateEdit.operatorRight = OperatorRights::ExerciseStateEdit;
plStateEdit.exercisePart = LtsWidgets::ExercisePart::eExecution;
plStateEdit.createWidgetFunc = [this](QWidget *parent)
{
return onShowExerciseManagementStateEdit(parent);
};
ret.append(plStateEdit);
#endif
LtsWidgets::PluginData plExercisePurpose;
plExercisePurpose.menuGroup = menuGroup();
plExercisePurpose.menuText = tr("Exercise Purpose");
plExercisePurpose.menuIcon = QIcon(QLatin1String("icon:exercise_purpose.svg"));
plExercisePurpose.identifier = QLatin1String("exmExercisePurpose");
plExercisePurpose.operatorRight = OperatorRights::ExercisePurposeEdit;
plExercisePurpose.exercisePart = LtsWidgets::ExercisePart::ePlanning;
plExercisePurpose.createWidgetFunc = [this](QWidget *parent)
{
return onShowExerciseManagementExercisePurpose(parent);
};
ret.append(plExercisePurpose);
LtsUtils::ProjectSettings *ps = LtsUtils::ProjectSettings::getInstance();
const bool enableEditPhases = ps->value(QStringLiteral("exm"),
QStringLiteral("enableEditPhases")).toBool();
if (enableEditPhases)
{
LtsWidgets::PluginData plPhaseEdit;
plPhaseEdit.menuGroup = menuGroup();
plPhaseEdit.menuText = tr("Exercise Phases");
plPhaseEdit.menuIcon = QIcon(QLatin1String("icon:phase_def.svg"));
plPhaseEdit.identifier = QLatin1String("exmPhaseEdit");
plPhaseEdit.operatorRight = OperatorRights::ExercisePhaseEdit;
plPhaseEdit.exercisePart = LtsWidgets::ExercisePart::ePlanning;
plPhaseEdit.createWidgetFunc = [this](QWidget *parent)
{
return onShowExerciseManagementPhaseEdit(parent);
};
ret.append(plPhaseEdit);
}
LtsWidgets::PluginData plOperatorEdit;
plOperatorEdit.menuGroup = menuGroup();
plOperatorEdit.menuText = tr("Exercise Operators");
plOperatorEdit.menuIcon = QIcon(QLatin1String("icon:operator_rights.svg"));
plOperatorEdit.identifier = QLatin1String("exmOperatorEdit");
plOperatorEdit.operatorRight = OperatorRights::ExerciseOperatorEdit;
plOperatorEdit.createWidgetFunc = [this](QWidget *parent)
{
return onShowExerciseManagementOperatorEdit(parent);
};
ret.append(plOperatorEdit);
}
return ret;
}
bool InterfaceImpl::fetchInterfaces()
{
if (!m_session->getDtc<ExerciseManagement::DataInterface>(m_dtc))
return false;
std::shared_ptr<ProjectDataManagement::Interface::Dtc> pdmDtc;
if (!m_session->getDtc<ProjectDataManagement::DataInterface>(pdmDtc)) // TODO: not obli
return false;
if (!m_session->getDtc<AssetManagement::DataInterface>(m_asmDtc)) // TODO: not obli
return false;
for (const QString &option : getOptions())
DEBUG_LOG(m_logger) << "option: " << option;
return true;
}
void InterfaceImpl::clearInterfaces()
{
m_asmDtc = nullptr;
m_dtc = nullptr;
}
LtsWidgets::LtsDialog *InterfaceImpl::onShowExerciseManagementDialog(QWidget *parent)
{
ExerciseManagementDialog *dialog = new ExerciseManagementDialog(menuGroup(), parent);
dialog->init(m_session);
return dialog;
}
LtsWidgets::LtsDialog *InterfaceImpl::onShowExerciseManagementExercisePurpose(QWidget *parent)
{
ExerciseManagementExercisePurpose *dialog = new ExerciseManagementExercisePurpose(menuGroup(), parent);
dialog->init(m_session);
return dialog;
}
LtsWidgets::LtsDialog *InterfaceImpl::onShowExerciseManagementStateEdit(QWidget *parent)
{
ExerciseManagementStateEdit *dialog = new ExerciseManagementStateEdit(menuGroup(), parent);
dialog->init(m_session);
return dialog;
}
LtsWidgets::LtsDialog *InterfaceImpl::onShowExerciseManagementPhaseEdit(QWidget *parent)
{
ExerciseManagementPhaseEdit *dialog = new ExerciseManagementPhaseEdit(menuGroup(), parent);
dialog->init(m_session);
return dialog;
}
LtsWidgets::LtsDialog *InterfaceImpl::onShowExerciseManagementOperatorEdit(QWidget *parent)
{
ExerciseManagementOperatorEdit *dialog = new ExerciseManagementOperatorEdit(menuGroup(), parent);
dialog->init(m_session);
return dialog;
}
void InterfaceImpl::executePayload(LtsWidgets::LtsBackgroundWidget *mainBackground)
{
connect(this, &InterfaceImpl::signalSuccess,
m_session, &LtsSession::LtsSession::slotExecuteNextPayload, Qt::QueuedConnection);
if (m_session->partitionType() != IDL::PartitionType::Global) // skip payload if already in exercise (or replay)
{
checkNeedRecalcMgrsSquares(m_session->exerciseId());
emit signalSuccess(); // exm payload not needed here
return;
}
m_mainBackground = mainBackground;
m_dtc->enableExercise();
connect(new LtsUtils::ConnectingDialogNT([this](int timeWait) { return m_dtc->waitForHistoricalDataExercise(timeWait); }, tr("Exercise Management"), tr("Global"), mainBackground),
&QObject::destroyed,
this, &InterfaceImpl::executePayloadStep2, Qt::QueuedConnection); // ingores errors
}
void InterfaceImpl::executePayloadStep2()
{
int idPreset = LtsSessionData::LtsSessionData::getInstance()->getPartitionIdPreset();
if (m_session->isLoadedFromSavegame() /* otherwise exercise chooser is shown whenever it was an admin session (as it would be partition type Global ;) */)
idPreset = 0; // so this is a global session BUT was saved with a savegame, so set idPreset to 0 to not show the exc chooser on a savegame, trust me
if (idPreset > -1) // preset is set! skip exc chooser (as the session manager logged it in already)
{
// no direct call to make sure LtsSessionManager::m_sessionMap is properly filled
// to get the same behavior as below (exerciseChooser->show() does not block)
QTimer::singleShot(0,
this,
[this]()
{
slotSelectExercise(LtsSessionData::LtsSessionData::getInstance()->getPartitionIdPreset());
LtsSessionData::LtsSessionData::getInstance()->removePresets();
});
}
else
{
ExerciseChooser *exerciseChooser = new ExerciseChooser(m_mainBackground);
exerciseChooser->init(m_session);
exerciseChooser->setAttribute(Qt::WA_DeleteOnClose);
connect(exerciseChooser, &ExerciseChooser::signalSelectExercise,
this, [this](int partitionId) { slotSelectExercise(partitionId); }, Qt::QueuedConnection);
connect(exerciseChooser, &ExerciseChooser::signalQuit,
m_session, &LtsSession::LtsSession::signalQuit);
// TODO: connect to deleteLater?
if (!LtsSessionData::LtsSessionData::getInstance()->isTablet())
exerciseChooser->setModal(true);
exerciseChooser->show();
}
}
void InterfaceImpl::slotSelectExercise(int partitionId)
{
LtsSession::LtsSessionManager *sessionManager = m_session->getSessionManager();
if (partitionId > 0) // non-admin session
{
//m_session->setBaseLayoutVisiblity(false); // don't show admin session if an exercise/replay is required
LtsSession::DdsConnectionParams connParams(m_session->connParams());
connParams.partitionId = partitionId;
connParams.partitionType = IDL::PartitionType::Exercise;
connParams.exerciseId = partitionId;
sessionManager->createSession(connParams,
true, /* show base layout */
true /* payloads were already triggered - but since the script editor payload has to be in an exercise, payloads must be started */);
ExerciseManagement::Exercise exc = m_dtc->exercise(partitionId);
int excId = exc.id();
if (excId == 0)
{
qWarning() << "Preset Exercise does not exist or db/svc is down!";
Q_ASSERT(false);
return;
}
if (excId != partitionId)
{
qWarning() << "exc => preset mismatch";
Q_ASSERT(false);
return;
}
m_asmDtc->enableTrainingArea();
connect(new LtsUtils::ConnectingDialogNT([this](int timeWait) { return m_asmDtc->waitForHistoricalDataTrainingArea(timeWait); }, tr("Asset Management"), tr("Global"), m_mainBackground),
&QObject::destroyed,
this, [this, exc]()
{
selectExerciseStep2(exc);
}, Qt::QueuedConnection);
}
else
{
// user selected Admin Session as his Exercise => as it was already created, make it visible
//LtsSession::LtsSession *session = sessionManager->getSession(IDL::PartitionType::Global, 0);
if (!m_session)
{
qWarning() << "No Admin Session available - abort."; // TODO: ERROR_LOG(m_logger) <<
abort();
}
m_session->setBaseLayoutVisible(); // show the Admin Session's BaseLayout
emit signalSuccess(); // we are done (exc chosen), tell the session that it can continue executing payloads
}
}
void InterfaceImpl::selectExerciseStep2(const ExerciseManagement::Exercise &exc)
{
checkNeedRecalcMgrsSquares(exc);
m_session->setMarkForDeletion(); // admin session not needed anymore!
emit signalSuccess(); // we are done (exc chosen), tell the session that it can continue executing payloads
}
void InterfaceImpl::checkNeedRecalcMgrsSquares(int exerciseId)
{
if (!LtsCoordTrans::defaultMgrsSquares().isEmpty())
return;
checkNeedRecalcMgrsSquares(m_dtc->exercise(exerciseId));
}
void InterfaceImpl::checkNeedRecalcMgrsSquares(const ExerciseManagement::Exercise &exc)
{
if (!LtsCoordTrans::defaultMgrsSquares().isEmpty())
return;
AssetManagement::TrainingArea ta = m_asmDtc->trainingArea(exc.trainingAreaId());
if (ta.id() != exc.trainingAreaId())
{
qWarning() << "Could not fetch Training Area with id " << exc.trainingAreaId();
abort();
}
LtsCoordTrans::UtmCoordinate bottomLeft = LtsCoordTrans::UtmCoordinate::fromGeographic(ta.bottomLeft().lon(), ta.bottomLeft().lat());
LtsCoordTrans::getMgrsSquares(QRectF(bottomLeft.geographic(0, ta.height()), bottomLeft.geographic(ta.width(), 0)), true, true);
}
} // namespace ExerciseManagement
@@ -0,0 +1,91 @@
/**
* @RDE_HEADER@
* Gui Plugin for ExerciseManangement
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#pragma once
#include <ExerciseManagement/logger.h>
#include <PluginInterfaces/gui_plugin_interface.h>
#include <Common/ProjectConfig/project_defines.h>
#include <Plugins/ExerciseManagement/exm_data_plugin_interface.h>
#include <Plugins/ExerciseManagement/exm_gui_plugin_interface.h>
#include <Plugins/AssetManagement/asm_data_plugin_interface.h>
#include <Plugins/ProjectDataManagement/pdm_data_plugin_interface.h>
#include <Plugins/SituationReplayManagement/srm_data_plugin_interface.h>
namespace ExerciseManagement
{
class GuiPlugin final : public QObject, public GuiPluginBase::Plugin
{
Q_PLUGIN_METADATA(IID "gui:3:exm")
Q_INTERFACES(GuiPluginBase::Plugin)
Q_OBJECT
public:
explicit GuiPlugin() = default;
~GuiPlugin() = default;
QString pluginName() override { return QLatin1String("ExerciseManagementGuiPlugin"); }
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 // TODO: ExerciseChooser to own plugin! Not everyone needs to edit the Exercise !
{
Q_OBJECT
public:
explicit InterfaceImpl(LtsSession::LtsSession *session);
QVector<LtsWidgets::PluginData> getActions() override;
QString menuGroup() const override { return tr("Exercises"); }
// LtsUtils::LtsTranslatableIdentifier menuGroupIdentifier() const override
// { return LtsUtils::LtsTranslatableIdentifier(QStringLiteral("Exercises"), this, "Exercises"); }
bool fetchInterfaces() override;
void clearInterfaces() override;
bool availableInPartition(IDL::PartitionType partition) const override
{
return partition == IDL::PartitionType::Global ||
partition == IDL::PartitionType::Exercise;
}
// be able to show exercise chooser
int executionPriority() const override { return 2; /* after opm settings (1) */ }
void executePayload(LtsWidgets::LtsBackgroundWidget *mainBackground) override;
private:
LtsWidgets::LtsDialog *onShowExerciseManagementDialog(QWidget *parent);
LtsWidgets::LtsDialog *onShowExerciseManagementExercisePurpose(QWidget *parent);
LtsWidgets::LtsDialog *onShowExerciseManagementStateEdit(QWidget *parent);
LtsWidgets::LtsDialog *onShowExerciseManagementPhaseEdit(QWidget *parent);
LtsWidgets::LtsDialog *onShowExerciseManagementOperatorEdit(QWidget *parent);
void selectExerciseStep2(const Exercise &exc);
void checkNeedRecalcMgrsSquares(int exerciseId);
void checkNeedRecalcMgrsSquares(const Exercise &exc);
std::shared_ptr<ExerciseManagement::Interface::Dtc> m_dtc;
std::shared_ptr<AssetManagement::Interface::Dtc> m_asmDtc;
LtsWidgets::LtsBackgroundWidget *m_mainBackground;
signals:
void signalSuccess();
private slots:
void slotSelectExercise(int partitionId);
void executePayloadStep2();
};
} // namespace ExerciseManagement
@@ -0,0 +1,244 @@
/**
* @RDE_HEADER@
* ExerciseManagement - Exercise Edit Party Dialog
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#include "exm_edit_party_dialog.h"
#include "ui_exm_edit_party_dialog.h"
#include <LtsWidgets/lts_frameless_dialog.h>
#include <LtsWidgets/lts_message_dialog.h>
#include <LtsSession/lts_session.h>
#include <Plugins/ParticipantManagement/Data/ppm_data_plugin.h>
#include <Plugins/ExerciseManagement/Data/exm_data_plugin.h>
#include <QListWidget>
#include <QMenu>
#include <QJsonArray>
#include <QJsonObject>
#include <QJsonDocument>
namespace ExerciseManagement
{
ExerciseEditPartyDialog::ExerciseEditPartyDialog(const int operatorId,
const int exerciseId,
const QString &menuGroup,
QWidget *parent)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
, m_operatorId(operatorId)
, m_exerciseId(exerciseId)
, m_visiblePartiesChanged(false)
, m_adlerVisiblePartiesChanged(false)
, m_menuGroup(menuGroup)
, m_visiblePartiesModel(nullptr)
, m_adlerVisiblePartiesModel(nullptr)
, m_opmDtc(nullptr)
, m_opmFtc(nullptr)
, m_ui(new Ui::ExerciseEditPartyDialog)
, m_logger(getLogger("exerciseEditPartyDialog"))
, m_requestHelper(new LtsUtils::RequestHelper(this))
{
setNoTopicLock();
m_ui->setupUi(this);
setOnlineHelpFilename(QStringLiteral("Administrator-Operator-Parties"));
}
bool ExerciseEditPartyDialog::init(LtsSession::LtsSessionDataDds *session)
{
if (!session->getDtc<OperatorManagement::DataInterface>(m_opmDtc))
return false;
if (!session->getFtc<OperatorManagement::DataInterface>(m_opmFtc))
return false;
m_visiblePartiesModel = new ExerciseEditVisiblePartiesModel(m_operatorId, m_exerciseId, this);
if (!m_visiblePartiesModel->init(session))
return false;
m_ui->tvVisibleParties->setModel(m_visiblePartiesModel);
m_ui->tvVisibleParties->resizeColumnsToContent();
m_ui->tvVisibleParties->setSortIndicator(ExerciseEditVisiblePartiesModel::Columns::ColId, Qt::SortOrder::AscendingOrder);
m_ui->tvVisibleParties->setSortingEnabled(false);
m_adlerVisiblePartiesModel = new ExerciseEditAdlerVisiblePartiesModel(m_operatorId, m_exerciseId, this);
if (!m_adlerVisiblePartiesModel->init(session))
return false;
m_ui->tvAdlerVisibleParties->setModel(m_adlerVisiblePartiesModel);
m_ui->tvAdlerVisibleParties->resizeColumnsToContent();
m_ui->tvAdlerVisibleParties->setSortIndicator(ExerciseEditAdlerVisiblePartiesModel::Columns::ColId, Qt::SortOrder::AscendingOrder);
m_ui->tvAdlerVisibleParties->setSortingEnabled(false);
#ifndef LTS_DEBUG
m_ui->tvVisibleParties->hideColumn(ExerciseEditVisiblePartiesModel::Columns::ColId);
m_ui->tvAdlerVisibleParties->hideColumn(ExerciseEditVisiblePartiesModel::Columns::ColId);
#endif
connect(m_ui->tvVisibleParties, &LtsDataView::LtsDataView::doubleClicked, m_visiblePartiesModel, &ExerciseEditVisiblePartiesModel::switchCheckbox);
connect(m_ui->tvAdlerVisibleParties, &LtsDataView::LtsDataView::doubleClicked, this, &ExerciseEditPartyDialog::onDoubleClicked);
connect(m_visiblePartiesModel, &ExerciseEditVisiblePartiesModel::dataChanged, this, [this](const QModelIndex &index) {
m_visiblePartiesChanged = true; slotChangesMade(); onSwitchCheckbox(index);});
connect(m_adlerVisiblePartiesModel, &ExerciseEditAdlerVisiblePartiesModel::dataChanged, this, [this]() {
m_adlerVisiblePartiesChanged = true; slotChangesMade();});
#ifdef LTS_DEBUG
m_ui->tvVisibleParties->setContextMenuPolicy(Qt::CustomContextMenu);
connect(m_ui->tvVisibleParties, &LtsDataView::LtsDataView::customContextMenuRequested, this, &ExerciseEditPartyDialog::onContextMenuRequested);
#endif
setAdlerVisiblePartiesUncheckable();
return true;
}
bool ExerciseEditPartyDialog::operatorUpdateVisiblePartiesByExercise(const OperatorManagement::OperatorUpdateVisiblePartiesByExerciseRequest &req)
{
DEBUG_LOG(m_logger) << LOGFUNCTION;
return m_requestHelper->startSingleRequest([this, req]()
{
return m_opmFtc->operatorUpdateVisiblePartiesByExerciseRequest(req, this);
});
}
ExerciseEditPartyDialog::~ExerciseEditPartyDialog()
{
delete m_ui;
}
void ExerciseEditPartyDialog::retranslate()
{
translate(m_ui, m_opmDtc->user(m_operatorId), tr("EX:%1 Operator ").arg(m_exerciseId));
}
QByteArray ExerciseEditPartyDialog::adlerVisiblePartiesToJson() const
{
QJsonArray adlerVisiblePartiesArray;
QJsonObject adlerVisiblePartiesObject;
// pool and support are in the list (always available);
adlerVisiblePartiesArray.append(0); // pool
adlerVisiblePartiesArray.append(1); // O/C Service;
const QVector<int> &checkedParties = m_adlerVisiblePartiesModel->getCheckedIds();
for (const int id : checkedParties)
adlerVisiblePartiesArray.append(id);
adlerVisiblePartiesObject[QStringLiteral("adlerAllowed")] = adlerVisiblePartiesArray;
QJsonDocument adlerVisiblePartiesDocument(adlerVisiblePartiesObject);
return adlerVisiblePartiesDocument.toJson(QJsonDocument::Compact);
}
void ExerciseEditPartyDialog::setAdlerVisiblePartiesUncheckable()
{
const QVector<int> &uncheckedParties = m_visiblePartiesModel->getUncheckedIds();
QVector<int> rowIds;
for (const int id : uncheckedParties)
{
int rowId = m_adlerVisiblePartiesModel->findRowForPartyId(id);
if (rowId < 0)
continue;
rowIds.append(rowId);
}
m_adlerVisiblePartiesModel->setUncheckedPartyIds(rowIds);
}
//Private Slots
bool ExerciseEditPartyDialog::apply()
{
DEBUG_LOG(m_logger) << LOGFUNCTION;
if (m_operatorId <= 0) // user not exists
return true;
//updateData
OperatorManagement::OperatorUpdateVisiblePartiesByExerciseRequest req;
req.id(m_operatorId);
req.exerciseId(m_exerciseId);
if (!m_visiblePartiesChanged && !m_adlerVisiblePartiesChanged)
return false;
QSet<int> visiblePartyIds = m_visiblePartiesModel->getCheckedIds().toList().toSet();
// check if pool and support are in the list (always available);
visiblePartyIds.insert(0); // pool
visiblePartyIds.insert(1); // O/C Service;
const QVector<int> hiddenPartyIds = m_visiblePartiesModel->getUncheckedIds();
for (const int visible : visiblePartyIds)
DEBUG_LOG(m_logger) << "visible party: " << visible;
for (const int hidden : hiddenPartyIds)
DEBUG_LOG(m_logger) << "hidden party: " << hidden;
req.hiddenParties().set({});
req.visibleParties().set({});
std::copy(hiddenPartyIds.begin(), hiddenPartyIds.end(), std::back_inserter(req.hiddenParties().get()));
std::copy(visiblePartyIds.begin(), visiblePartyIds.end(), std::back_inserter(req.visibleParties().get()));
req.properties(adlerVisiblePartiesToJson().toStdString());
DEBUG_LOG(m_logger) << "----------------- opId: " << req.id() << ", exId:" << req.exerciseId() << ", req.hiddenParties.size:" << hiddenPartyIds.size()
<< "adlerVisibleParties: " << req.properties();
return operatorUpdateVisiblePartiesByExercise(req);
}
void ExerciseEditPartyDialog::onContextMenuRequested(const QPoint &position)
{
QMenu menu(m_ui->tvVisibleParties);
menu.addAction(tr("Select All"), this, &ExerciseEditPartyDialog::onSelectAllParties);
menu.addAction(tr("Unselect All"), this, &ExerciseEditPartyDialog::onUnselectAllParties);
menu.exec(m_ui->tvVisibleParties->mapToGlobal(position));
}
void ExerciseEditPartyDialog::onSelectAllParties()
{
m_visiblePartiesModel->selectAll();
m_visiblePartiesModel->update();
}
void ExerciseEditPartyDialog::onUnselectAllParties()
{
m_visiblePartiesModel->unselectAll();
m_visiblePartiesModel->update();
}
void ExerciseEditPartyDialog::onSwitchCheckbox(const QModelIndex &index)
{
if (!index.isValid())
{
return;
}
DEBUG_LOG(m_logger) << LOGFUNCTION << "index.row():" << index.row();
const QPair<bool, ParticipantManagement::Party> row = m_visiblePartiesModel->getRowData(index.row());
QPair<bool, ParticipantManagement::Party> rowAdler = m_adlerVisiblePartiesModel->getRowData(index.row());
rowAdler.first = row.first;
setAdlerVisiblePartiesUncheckable();
m_adlerVisiblePartiesModel->setRowData(index.row(), rowAdler);
}
void ExerciseEditPartyDialog::onDoubleClicked(const QModelIndex &index)
{
if (!index.isValid())
{
return;
}
DEBUG_LOG(m_logger) << LOGFUNCTION << "index.row():" << index.row();
// if the party is not checked, you can not get this one for ADLER
bool isChecked = m_visiblePartiesModel->getRowData(index.row()).first;
if (!isChecked)
return;
QPair<bool, ParticipantManagement::Party> row = m_adlerVisiblePartiesModel->getRowData(index.row());
row.first = !row.first;
m_adlerVisiblePartiesModel->setRowData(index.row(), row);
}
}
@@ -0,0 +1,81 @@
/**
* @RDE_HEADER@
* ExerciseManangement - Exercise Edit Party Dialog
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#pragma once
#include <OperatorManagement/opm_ftc.h>
#include <OperatorManagement/opm_dtc.h>
#include <ExerciseManagement/logger.h>
#include "exm_edit_visible_parties_model.h"
#include "exm_edit_adler_visible_parties_model.h"
#include <LtsWidgets/lts_dialog.h>
#include <LtsUtilsGuiDds/request_helper.h>
namespace Ui
{
class ExerciseEditPartyDialog;
}
namespace LtsSession {
class LtsSession;
}
namespace ExerciseManagement
{
// --------------------------------------------------------
// OperatorManagementEditPartyDialog
// --------------------------------------------------------
class ExerciseEditPartyDialog : public LtsWidgets::LtsDialog
, protected OperatorManagement::Interface::Ftc::OperatorUpdateVisiblePartiesByExerciseReplyHandler
{
Q_OBJECT
public:
explicit ExerciseEditPartyDialog(const int operatorId,
const int exerciseId,
const QString &menuGroup,
QWidget *parent = nullptr);
~ExerciseEditPartyDialog();
bool init(LtsSession::LtsSessionDataDds *session);
void onOperatorUpdateVisiblePartiesByExerciseReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
private:
void retranslate() override;
bool apply() override final;
QByteArray adlerVisiblePartiesToJson() const;
void setAdlerVisiblePartiesUncheckable();
private slots:
void onContextMenuRequested(const QPoint &position);
void onSelectAllParties();
void onUnselectAllParties();
void onSwitchCheckbox(const QModelIndex &index);
void onDoubleClicked(const QModelIndex &index);
private:
int m_operatorId;
int m_exerciseId;
bool m_visiblePartiesChanged;
bool m_adlerVisiblePartiesChanged;
QString m_menuGroup;
ExerciseEditVisiblePartiesModel *m_visiblePartiesModel;
ExerciseEditAdlerVisiblePartiesModel *m_adlerVisiblePartiesModel;
std::shared_ptr<OperatorManagement::Interface::Dtc> m_opmDtc;
std::shared_ptr<OperatorManagement::Interface::Ftc> m_opmFtc;
Ui::ExerciseEditPartyDialog *m_ui;
LOGGER_T m_logger;
LtsUtils::RequestHelper *m_requestHelper;
bool operatorUpdateVisiblePartiesByExercise(const OperatorManagement::OperatorUpdateVisiblePartiesByExerciseRequest &req);
};
}
@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ExerciseEditPartyDialog</class>
<widget class="QWidget" name="ExerciseEditPartyDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>687</width>
<height>571</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Operator Edit</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<layout class="QVBoxLayout" name="layParties">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="lblVisibleParties">
<property name="text">
<string>Visible Parties:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lblAdlerVisibleParties">
<property name="text">
<string>ADLER Visible Parties:</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="LtsDataView::LtsDataView" name="tvVisibleParties" native="true">
<property name="showColumnCount" stdset="0">
<bool>false</bool>
</property>
<property name="toolButtonsVisible" stdset="0">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="LtsDataView::LtsDataView" name="tvAdlerVisibleParties" native="true">
<property name="showColumnCount" stdset="0">
<bool>false</bool>
</property>
<property name="toolButtonsVisible" stdset="0">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LtsDataView::LtsDataView</class>
<extends>QWidget</extends>
<header>LtsDataView/lts_data_view.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,144 @@
/**
* @RDE_HEADER@
* ExerciseManangement - Exercise Phase Edit Dialog
* $Id$
* $HeadURL$
* $Author$
* Created by Philipp Dassow, SLS1, 2017-04-12
*/
#include "exm_edit_phase_dialog.h"
#include "ui_exm_edit_phase_dialog.h"
#include <Plugins/ExerciseManagement/exm_data_plugin_interface.h>
#include <Plugins/FileManagement/flm_data_plugin_interface.h>
#include <LtsSession/lts_session_data.h>
namespace ExerciseManagement
{
ExerciseManagementPhaseEditDialog::ExerciseManagementPhaseEditDialog(QWidget *parent)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
, m_ui(new Ui::ExerciseManagementPhaseEditDialog)
, m_requestHelper(new LtsUtils::RequestHelper(this))
, m_logger(getLogger("ExerciseManangementPhaseEditDialog"))
{
m_ui->setupUi(this);
m_uiRequirements->addRequirement( { m_ui->lblName, [this]() { return (!m_ui->leName->text().isEmpty()); } } );
m_uiRequirements->addRequirement( { m_ui->lblStart, [this]() { return (!m_ui->dtStart->isEmpty()); } } );
m_uiRequirements->addRequirement( { m_ui->lblEnd, [this]() { return (!m_ui->dtEnd->isEmpty()); } } );
}
ExerciseManagementPhaseEditDialog::~ExerciseManagementPhaseEditDialog()
{
delete m_ui;
}
bool ExerciseManagementPhaseEditDialog::init(LtsSession::LtsSessionDataDds *session,
const int exerciseId,
const int phaseId)
{
m_session = session;
m_exerciseId = exerciseId;
m_exercisePhaseId = phaseId;
if (!m_session->getDtc<ExerciseManagement::DataInterface>(m_dtc))
return false;
if (!m_session->getFtc<ExerciseManagement::DataInterface>(m_ftc))
return false;
if (!m_session->getDtc<FileManagement::DataInterface>(m_flmDtc))
return false;
if (!m_session->getFtc<FileManagement::DataInterface>(m_flmFtc))
return false;
ExerciseManagement::ExercisePhase data = m_dtc->exercisePhase(phaseId);
m_ui->leName->setText(QString::fromUtf8(data.name().c_str()));
m_ui->pteDescription->setPlainText(QString::fromStdString(data.description()));
m_ui->dtStart->setMsecsSinceEpoch(data.beginTime());
m_ui->dtEnd->setMsecsSinceEpoch(data.endTime());
m_ui->dtStart->setRetrieveCurrentTimeCallback([this]() { return m_session->partitionTime(); });
m_ui->dtEnd->setRetrieveCurrentTimeCallback([this]() { return m_session->partitionTime(); });
// new phase for exerciseId
if (m_exercisePhaseId <= 0)
{
m_ui->dtStart->setMsecsSinceEpoch(m_dtc->exercise(exerciseId).beginTime());
m_ui->dtEnd->setMsecsSinceEpoch(m_dtc->exercise(exerciseId).endTime());
}
setOnlineHelpFilename(QStringLiteral("Situation-Exercise_Phases"));
return true;
}
void ExerciseManagementPhaseEditDialog::retranslate()
{
translate(m_ui,
m_dtc->exercisePhase(m_exercisePhaseId),
tr("Phase"));
}
bool ExerciseManagementPhaseEditDialog::apply()
{
if (m_exercisePhaseId > 0)
{
m_requestHelper->addRequest([this]()
{
// Update Data of Existing Phase
std::string name = m_ui->leName->text().toStdString();
std::string description = m_ui->pteDescription->toPlainText().toStdString();
qint64 start = m_ui->dtStart->msecsSinceEpoch();
qint64 end = m_ui->dtEnd->msecsSinceEpoch();
ExercisePhaseModifyRequest req;
req.name(name);
req.description(description);
req.beginTime(start);
req.endTime(end);
req.exerciseId(m_exerciseId);
req.id(m_exercisePhaseId);
m_ftc->enableExercisePhaseModify();
return m_ftc->exercisePhaseModifyRequest(req, this);
});
}
else
{
// Add New Phase
m_requestHelper->startSingleRequest([this]()
{
std::string name = m_ui->leName->text().toStdString();
std::string description = m_ui->pteDescription->toPlainText().toStdString();
qint64 start = m_ui->dtStart->msecsSinceEpoch();
qint64 end = m_ui->dtEnd->msecsSinceEpoch();
m_ftc->enableExercisePhaseCreate();
return m_ftc->exercisePhaseCreateRequest(ExercisePhaseCreateRequest(name, description, start, end, m_exerciseId), this);
});
int phaseId = m_requestHelper->getRepliedId();
if (phaseId > 0)
{
const QString folderName = QStringLiteral("Phase Documents");
int exeFolderId = m_flmDtc->getExerciseFolderId(m_exerciseId);
int folderPhaseDocsId = m_flmDtc->findFolder(exeFolderId, folderName);
FileManagement::FolderModifyRequest req;
req.name(m_flmDtc->getPhaseFolderName(phaseId).toStdString());
req.isEditable(false);
req.isHidden(false);
req.parentId(folderPhaseDocsId);
req.operatorId(LtsSessionData::LtsSessionData::getInstance()->getOperatorId());
m_requestHelper->startSingleRequest([this, req]()
{
return m_flmFtc->folderModifyRequest(req, this);
});
}
// TODO: check if something has changed (constraints manager / ui requirements should also check for changes)
}
// do nothing on failure - rh's message is enough
return m_requestHelper->startRequests(); // return success or failure
}
} // namespace ExerciseManagement
@@ -0,0 +1,66 @@
/**
* @RDE_HEADER@
* ExerciseManangement - Exercise Phase Edit Dialog
* $Id$
* $HeadURL$
* $Author$
* Created by Philipp Dassow, SLS1, 2017-04-12
*/
#pragma once
#include <ExerciseManagement/exm_dtc.h>
#include <ExerciseManagement/exm_ftc.h>
#include <ExerciseManagement/logger.h>
#include <LtsSession/lts_session_data_dds.h>
#include <LtsWidgets/lts_dialog.h>
#include <LtsUtilsGuiDds/request_helper.h>
#include <FileManagement/flm_dtc.h>
#include <FileManagement/flm_ftc.h>
namespace Ui
{
class ExerciseManagementPhaseEditDialog;
}
namespace ExerciseManagement
{
class ExerciseManagementPhaseEditDialog : public LtsWidgets::LtsDialog
, protected ExerciseManagement::Interface::Ftc::ExercisePhaseCreateReplyHandler
, protected ExerciseManagement::Interface::Ftc::ExercisePhaseModifyReplyHandler
, protected FileManagement::Interface::Ftc::FolderModifyReplyHandler
{
Q_OBJECT
public:
explicit ExerciseManagementPhaseEditDialog(QWidget *parent = nullptr);
bool init(LtsSession::LtsSessionDataDds *session,
const int exerciseId,
const int phaseId);
~ExerciseManagementPhaseEditDialog();
void onExercisePhaseCreateReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
void onExercisePhaseModifyReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
void onFolderModifyReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
signals:
void sendData(const ExerciseManagement::ExercisePhase &data);
private:
void retranslate() override;
bool apply() override final;
Ui::ExerciseManagementPhaseEditDialog *m_ui{nullptr};
LtsSession::LtsSessionDataDds *m_session{nullptr};
int m_exercisePhaseId{-1};
int m_exerciseId{-1};
std::shared_ptr<Interface::Dtc> m_dtc;
std::shared_ptr<Interface::Ftc> m_ftc;
std::shared_ptr<FileManagement::Interface::Dtc> m_flmDtc;
std::shared_ptr<FileManagement::Interface::Ftc> m_flmFtc;
LtsUtils::RequestHelper *m_requestHelper{nullptr};
LOGGER_T m_logger;
};
}
@@ -0,0 +1,119 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ExerciseManagementPhaseEditDialog</class>
<widget class="QWidget" name="ExerciseManagementPhaseEditDialog">
<property name="windowTitle">
<string notr="true">Edit Phase</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="3" column="1">
<widget class="LtsWidgets::LtsDateTimeEdit" name="dtEnd"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="lblStart">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Start Time:</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="lblEnd">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>End Time:</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="lblName">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Name:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="lblDescription">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Description:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="LtsWidgets::LtsDateTimeEdit" name="dtStart"/>
</item>
<item row="1" column="1" colspan="2">
<widget class="QPlainTextEdit" name="pteDescription">
<property name="minimumSize">
<size>
<width>0</width>
<height>100</height>
</size>
</property>
</widget>
</item>
<item row="2" column="2">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="1" colspan="2">
<widget class="QLineEdit" name="leName">
<property name="maxLength">
<number>50</number>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LtsWidgets::LtsDateTimeEdit</class>
<extends>QWidget</extends>
<header>LtsWidgets/lts_date_time_edit.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>leName</tabstop>
<tabstop>pteDescription</tabstop>
<tabstop>dtStart</tabstop>
<tabstop>dtEnd</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,154 @@
/**
* @RDE_HEADER@
* ExerciseManagement - Operator Exercise Edit Visible Parties Model
* $Id$
* $HeadURL$
* $Author$
* Created by Philipp Dassow, SLST, 2019-09-18
*/
#include "exm_edit_visible_parties_model.h"
#include <ParticipantManagement/ppm_translation.h>
#include <ParticipantManagement/ppm_dtc.h>
namespace ExerciseManagement
{
ExerciseEditVisiblePartiesModel::ExerciseEditVisiblePartiesModel(int operatorId,
int exerciseId,
QObject *parent)
: LtsWidgets::LtsCheckableTableModel<QPair<bool, ParticipantManagement::Party>>({tr("Id"), tr("Name")}, ColName, parent)
, m_opmDtc(nullptr)
, m_operatorId (operatorId)
, m_exerciseId(exerciseId)
{
}
ExerciseEditVisiblePartiesModel::~ExerciseEditVisiblePartiesModel()
{
}
bool ExerciseEditVisiblePartiesModel::init(LtsSession::LtsSessionDataDds *session)
{
session->getDtc<OperatorManagement::DataInterface>(m_opmDtc);
std::shared_ptr<ParticipantManagement::Interface::Dtc> ppmDtc;
if (!session->getDtc<ParticipantManagement::DataInterface>(ppmDtc))
return false;
connect(ppmDtc.get(), &ParticipantManagement::Interface::Dtc::partyChanged,
this, &ExerciseEditVisiblePartiesModel::onPartiesChanged, Qt::UniqueConnection);
auto cb = [this](const ParticipantManagement::Party &party)
{
onPartiesChanged(party, DataModification::eAdded);
};
ppmDtc->partys(cb);
return true;
}
QVariant ExerciseEditVisiblePartiesModel::data(const QModelIndex &index, int role) const
{
if (role != Qt::DisplayRole)
return LtsCheckableTableModel::data(index, role);
if (!indexIsValid(index))
return {};
const ParticipantManagement::Party &party = m_vecData.at(index.row()).second;
switch (index.column())
{
case ColId:
return party.id();
case ColName:
return ParticipantManagement::trPartyName(party.name());
}
return {};
}
void ExerciseEditVisiblePartiesModel::onPartiesChanged(const ParticipantManagement::Party &data, DataModification mod)
{
switch(mod)
{
case DataModification::eAdded:
{
insertRow(qMakePair(!isPartyHidden(data) && hasParty(data), data));
break;
}
case DataModification::eRemoved:
{
for (int i = 0; i < m_vecData.size(); ++i)
{
if (m_vecData.at(i).second.id() == data.id())
{
removeRow(i);
return;
}
}
break;
}
case DataModification::eModified:
{
for (int i = 0; i < m_vecData.size(); ++i)
{
if (m_vecData.at(i).second.id() == data.id())
{
m_vecData[i].second = data;
const QModelIndex idx(index(i, ColName, QModelIndex()));
emit dataChanged(idx, idx, {Qt::DisplayRole});
break;
}
}
break;
} // case Modified
} // switch
}
bool ExerciseEditVisiblePartiesModel::isFiltered(const QPair<bool, ParticipantManagement::Party> &data, DataModification modType) const
{
// pool and support alway checked but hidden for user
if (data.second.id() <= 1 )
return true;
return LtsCheckableTableModel::isFiltered(data, modType);
}
bool ExerciseEditVisiblePartiesModel::hasParty(const ParticipantManagement::Party &party) const
{
const auto visiblePartiesByExercise = m_opmDtc->user(m_operatorId).visiblePartiesByExercise();
for (const auto &exerciseParties : visiblePartiesByExercise)
{
if (exerciseParties.exerciseId() != m_exerciseId)
continue;
if (!exerciseParties.visibleParties().is_set()) //has_value not support on windows yet so we need depricated is_set
return false;
for (const auto &partyId : exerciseParties.visibleParties().get())
if (partyId == party.id())
return true;
return false;
}
return false;
}
bool ExerciseEditVisiblePartiesModel::isPartyHidden(const ParticipantManagement::Party &party) const
{
const auto visiblePartiesByExercise = m_opmDtc->user(m_operatorId).visiblePartiesByExercise();
for (const auto &exerciseParties : visiblePartiesByExercise)
{
if (exerciseParties.exerciseId() != m_exerciseId)
continue;
if (!exerciseParties.hiddenParties().is_set()) //has_value not support on windows yet so we need depricated is_set
return false;
for (const auto &partyId : exerciseParties.hiddenParties().get())
if (partyId == party.id())
return true;
return false;
}
return false;
}
}
@@ -0,0 +1,55 @@
/**
* @RDE_HEADER@
* ExerciseManagement - Operator Exercise Edit Visible Parties Model
* $Id$
* $HeadURL$
* $Author$
* Created by Philipp Dassow, SLST, 2019-09-18
*/
#pragma once
#include <Plugins/OperatorManagement/Data/opm_data_plugin.h>
#include <Plugins/ParticipantManagement/Data/ppm_data_plugin.h>
#include <LtsSession/lts_session_data_dds.h>
#include <LtsWidgets/lts_checkable_table_model.h>
#include <QPair>
namespace ExerciseManagement
{
class ExerciseEditVisiblePartiesModel : public LtsWidgets::LtsCheckableTableModel<QPair<bool, ParticipantManagement::Party>>
{
Q_OBJECT
public:
enum Columns
{
ColId,
ColName
};
explicit ExerciseEditVisiblePartiesModel(int operatorId = 0,
int exerciseId = 0,
QObject *parent = nullptr);
~ExerciseEditVisiblePartiesModel();
bool init(LtsSession::LtsSessionDataDds *session);
QVariant data(const QModelIndex &index, int role) const override;
public slots:
void onPartiesChanged(const ParticipantManagement::Party &data, DataModification mod);
bool isFiltered(const QPair<bool, ParticipantManagement::Party> &data, DataModification modType) const override;
private:
bool hasParty(const ParticipantManagement::Party &party) const;
bool isPartyHidden(const ParticipantManagement::Party &party) const;
std::shared_ptr<OperatorManagement::Interface::Dtc> m_opmDtc;
int m_operatorId;
int m_exerciseId;
};
}
@@ -0,0 +1,96 @@
/**
* @RDE_HEADER@
* ExerciseManangement - Exercise Purpose Dialog
* $Id: exm_edit_dialog.h 41137 2018-04-20 08:50:55Z schroeder_m $
* $HeadURL: svn://slssvn/TDS/branches/product/devel/trunk/Lts/Plugins/ExerciseManagement/Gui/ExerciseEdit/exm_edit_dialog.h $
* $Author: schroeder_m $
* Created by Malte Schröder, SLSE, 2018-04-21
*/
#include "exm_exercise_purpose.h"
#include "ui_exm_exercise_purpose.h"
#include <Plugins/ExerciseManagement/exm_data_plugin_interface.h>
namespace ExerciseManagement
{
ExerciseManagementExercisePurpose::ExerciseManagementExercisePurpose(const QString &menuGroup, QWidget *parent)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
, m_ui(new Ui::ExerciseManagementExercisePurpose)
, m_dtc(nullptr)
, m_ftc(nullptr)
, m_session(nullptr)
, m_menuGroup(menuGroup)
, m_exercise()
, m_requestHelper(new LtsUtils::RequestHelper(this))
, m_logger(getLogger("ExerciseManagementExercisePurpose"))
{
m_ui->setupUi(this);
m_uiRequirements->addRequirement( { m_ui->lblForces, [this]() { return (!m_ui->pteForces->toPlainText().isEmpty()); } } );
m_uiRequirements->addRequirement( { m_ui->lblDesc, [this]() { return (!m_ui->pteDescription->toPlainText().isEmpty()); } } );
setOnlineHelpFilename(QStringLiteral("Situation-Exercise_Purpose"));
}
ExerciseManagementExercisePurpose::~ExerciseManagementExercisePurpose()
{
delete m_ui;
}
bool ExerciseManagementExercisePurpose::init(LtsSession::LtsSessionDataDds *session)
{
m_session = session;
if (!m_session->getDtc<ExerciseManagement::DataInterface>(m_dtc))
return false;
if (!m_session->getFtc<ExerciseManagement::DataInterface>(m_ftc))
return false;
m_exercise = m_dtc->exercise(m_session->exerciseId());
m_ui->pteForces->setPlainText(QString::fromStdString(m_exercise.forces()));
m_ui->pteDescription->setPlainText(QString::fromStdString(m_exercise.description()));
return true;
}
void ExerciseManagementExercisePurpose::retranslate()
{
translate(m_ui, m_exercise, tr("Exercise Purpose"));
tryLockTopicNew();
}
bool ExerciseManagementExercisePurpose::apply()
{
if (m_exercise.id() > 0)
{
ExerciseModifyRequest request;
// Update Data of Existing Exercise
request.id(m_exercise.id());
request.beginTime(m_exercise.beginTime());
request.endTime(m_exercise.endTime());
request.name(m_exercise.name());
request.sendToWMS(m_exercise.sendToWMS());
request.linkedExerciseId(m_exercise.linkedExerciseId());
request.trainingAreaId(m_exercise.trainingAreaId());
request.radioGroupId(m_exercise.radioGroupId());
request.symbolFillTypeId(m_exercise.symbolFillTypeId());
request.activePhaseId(m_exercise.activePhaseId());
request.defaultTimeZone(m_exercise.defaultTimeZone());
request.forces(m_ui->pteForces->toPlainText().toStdString());
request.description(m_ui->pteDescription->toPlainText().toStdString());
request.newState(m_exercise.state());
if(!m_requestHelper->startSingleRequest(
[this, request]()
{ m_ftc->enableExerciseModify();
return m_ftc->exerciseModifyRequest(request, this);
})
)
return false;
}
return true;
}
}
@@ -0,0 +1,51 @@
/**
* @RDE_HEADER@
* ExerciseManangement - Exercise Purpose Dialog
* $Id: exm_edit_dialog.h 41137 2018-04-20 08:50:55Z schroeder_m $
* $HeadURL: svn://slssvn/TDS/branches/product/devel/trunk/Lts/Plugins/ExerciseManagement/Gui/ExerciseEdit/exm_edit_dialog.h $
* $Author: schroeder_m $
* Created by Malte Schröder, SLSE, 2018-04-21
*/
#pragma once
#include <ExerciseManagement/exm_dtc.h>
#include <ExerciseManagement/exm_ftc.h>
#include <ExerciseManagement/logger.h>
#include <LtsWidgets/lts_dialog.h>
#include <LtsUtilsGuiDds/request_helper.h>
#include <LtsSession/lts_session_data_dds.h>
namespace Ui {
class ExerciseManagementExercisePurpose;
}
namespace ExerciseManagement
{
class ExerciseManagementExercisePurpose : public LtsWidgets::LtsDialog
, protected ExerciseManagement::Interface::Ftc::ExerciseModifyReplyHandler
{
Q_OBJECT
public:
explicit ExerciseManagementExercisePurpose(const QString &menuGroup, QWidget *parent = nullptr);
~ExerciseManagementExercisePurpose();
bool init(LtsSession::LtsSessionDataDds *session);
protected:
void onExerciseModifyReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
private:
void retranslate() override;
bool apply() override final;
Ui::ExerciseManagementExercisePurpose *m_ui;
std::shared_ptr<Interface::Dtc> m_dtc;
std::shared_ptr<Interface::Ftc> m_ftc;
LtsSession::LtsSessionDataDds *m_session;
QString m_menuGroup;
ExerciseManagement::Exercise m_exercise;
LtsUtils::RequestHelper *m_requestHelper;
LOGGER_T m_logger;
};
}
@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ExerciseManagementExercisePurpose</class>
<widget class="QWidget" name="ExerciseManagementExercisePurpose">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>696</width>
<height>326</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="2" column="1">
<widget class="QPlainTextEdit" name="pteDescription">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>50</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="lblForces">
<property name="text">
<string>Forces:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPlainTextEdit" name="pteForces">
<property name="minimumSize">
<size>
<width>0</width>
<height>50</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="lblDesc">
<property name="text">
<string>Description:</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,153 @@
/**
* @RDE_HEADER@
* ExerciseManangement - Operator Edit Dialog
* $Id: exm_edit_dialog.h 41137 2018-04-20 08:50:55Z schroeder_m $
* $HeadURL: svn://slssvn/TDS/branches/product/devel/trunk/Lts/Plugins/ExerciseManagement/Gui/ExerciseEdit/exm_edit_dialog.h $
* $Author: schroeder_m $
* Created by Malte Schröder, SLSE, 2018-04-25
*/
#include "exm_operator_edit.h"
#include "ui_exm_operator_edit.h"
#include <Plugins/ExerciseManagement/exm_data_plugin_interface.h>
#include <QMenu>
namespace ExerciseManagement
{
ExerciseManagementOperatorEdit::ExerciseManagementOperatorEdit(const QString &menuGroup, QWidget *parent)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
, m_ui(new Ui::ExerciseManagementOperatorEdit)
, m_opmDtc(nullptr)
, m_session(nullptr)
, m_operatorModel(nullptr)
, m_menuGroup(menuGroup)
, m_exercise()
, m_requestHelper(new LtsUtils::RequestHelper(this))
, m_logger(getLogger("ExerciseManagementOperatorEdit"))
{
m_ui->setupUi(this);
#ifdef LTS_DEBUG
m_ui->dvOperators->setContextMenuPolicy(Qt::CustomContextMenu);
connect(m_ui->dvOperators, &LtsDataView::LtsDataView::customContextMenuRequested, this, &ExerciseManagementOperatorEdit::onContextMenuRequested);
#endif
setOnlineHelpFilename(QStringLiteral("Situation-Operators"));
}
ExerciseManagementOperatorEdit::~ExerciseManagementOperatorEdit()
{
delete m_ui;
}
bool ExerciseManagementOperatorEdit::init(LtsSession::LtsSessionDataDds *session)
{
m_session = session;
if (!m_session->getDtc<OperatorManagement::DataInterface>(m_opmDtc))
return false;
std::shared_ptr<Interface::Dtc> dtc;
if (!m_session->getDtc<ExerciseManagement::DataInterface>(dtc))
return false;
m_exercise = dtc->exercise(m_session->exerciseId());
m_operatorModel = new ExerciseOperatorModel(m_session, m_exercise.id(), this);
m_ui->dvOperators->setModel(m_operatorModel);
m_ui->dvOperators->seamless();
connect(m_operatorModel, &ExerciseOperatorModel::dataChanged, this, &ExerciseManagementOperatorEdit::slotChangesMade);
return true;
}
void ExerciseManagementOperatorEdit::onContextMenuRequested(const QPoint &position)
{
QMenu menu(m_ui->dvOperators);
menu.addAction(tr("Select All"), this, &ExerciseManagementOperatorEdit::onSelectAllUsers);
menu.addAction(tr("Unselect All"), this, &ExerciseManagementOperatorEdit::onUnselectAllUsers);
menu.exec(m_ui->dvOperators->mapToGlobal(position));
}
void ExerciseManagementOperatorEdit::onSelectAllUsers()
{
m_operatorModel->selectAll();
m_operatorModel->update();
}
void ExerciseManagementOperatorEdit::onUnselectAllUsers()
{
m_operatorModel->unselectAll();
m_operatorModel->update();
}
void ExerciseManagementOperatorEdit::retranslate()
{
translate(m_ui, m_exercise, tr("Exercise Operators"));
}
bool ExerciseManagementOperatorEdit::apply()
{
if (m_exercise.id() > 0)
{
sendModifiedOperators(m_exercise.id());
return true;
}
return false;
}
template<class T>
bool ExerciseManagementOperatorEdit::removeElement(std::vector<T> &vec, T elem)
{
for (auto it = vec.begin(); it != vec.end(); ++it)
{
if (*it == elem)
{
vec.erase(it);
return true;
}
}
return false;
}
void ExerciseManagementOperatorEdit::sendModifiedOperators(int thisExerciseId)
{
std::shared_ptr<OperatorManagement::Interface::Ftc> opmFtc;
if (!m_session->getFtc<OperatorManagement::DataInterface>(opmFtc))
{
ERROR_LOG(m_logger) << "Cannot change add/remove Operators to/from Exercise as the OPM-FTC could not be fetched." ;
return;
}
for (int row = 0; row < m_operatorModel->rowCount(); ++row)
{
const auto rowData = m_operatorModel->getRowData(row);
bool found = false;
OperatorManagement::User user = m_opmDtc->user(rowData.second.id());
for (auto ex : user.exerciseIds())
if (ex == thisExerciseId)
found = true;
if (found == rowData.first) // Nothing changed
continue;
if (rowData.first)
user.exerciseIds().resize(user.exerciseIds().size() + 1, thisExerciseId);
else
removeElement(user.exerciseIds(), thisExerciseId);
OperatorManagement::OperatorCreateModifyRequest req;
req.id(user.id());
req.visibleExercises() = user.exerciseIds();
req.visiblePartiesByExercise() = user.visiblePartiesByExercise();
m_requestHelper->startSingleRequest([this, req, opmFtc]()
{
return opmFtc->operatorCreateModifyRequest(req, this);
});
}
}
}
@@ -0,0 +1,65 @@
/**
* @RDE_HEADER@
* ExerciseManangement - Operator Edit Dialog
* $Id: exm_edit_dialog.h 41137 2018-04-20 08:50:55Z schroeder_m $
* $HeadURL: svn://slssvn/TDS/branches/product/devel/trunk/Lts/Plugins/ExerciseManagement/Gui/ExerciseEdit/exm_edit_dialog.h $
* $Author: schroeder_m $
* Created by Malte Schröder, SLSE, 2018-04-25
*/
#pragma once
#include <ExerciseManagement/exm_ftc.h>
#include <ExerciseManagement/logger.h>
#include <LtsWidgets/lts_dialog.h>
#include <LtsUtilsGuiDds/request_helper.h>
#include <LtsSession/lts_session_data_dds.h>
#include "exm_operator_model.h"
namespace Ui
{
class ExerciseManagementOperatorEdit;
}
namespace ExerciseManagement
{
class ExerciseManagementOperatorEdit : public LtsWidgets::LtsDialog
, protected ExerciseManagement::Interface::Ftc::ExerciseModifyReplyHandler
, protected OperatorManagement::Interface::Ftc::OperatorCreateModifyReplyHandler
{
Q_OBJECT
public:
explicit ExerciseManagementOperatorEdit(const QString &menuGroup, QWidget *parent = nullptr);
~ExerciseManagementOperatorEdit();
bool init(LtsSession::LtsSessionDataDds *session);
protected:
void onExerciseModifyReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
void onOperatorCreateModifyReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
private slots:
void onSelectAllUsers();
void onUnselectAllUsers();
void onContextMenuRequested(const QPoint &position);
private:
void retranslate() override;
bool apply() override final;
void sendModifiedOperators(int thisExerciseId);
Ui::ExerciseManagementOperatorEdit *m_ui;
std::shared_ptr<OperatorManagement::Interface::Dtc> m_opmDtc;
LtsSession::LtsSessionDataDds *m_session;
ExerciseOperatorModel *m_operatorModel;
QString m_menuGroup;
ExerciseManagement::Exercise m_exercise;
LtsUtils::RequestHelper *m_requestHelper;
LOGGER_T m_logger;
template<class T>
bool removeElement(std::vector<T> &vec, T elem);
};
}
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ExerciseManagementOperatorEdit</class>
<widget class="QWidget" name="ExerciseManagementOperatorEdit">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="LtsDataView::LtsDataView" name="dvOperators"/>
</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>
@@ -0,0 +1,153 @@
/**
* @RDE_HEADER@
* OperatorManagement - Group Edit member of model
* $Id$
* $HeadURL$
* $Author$
* Created by Malte Diers, SLSE, 2017-10-10
*/
#include "exm_operator_model.h"
#include <ExerciseManagement/logger.h>
#include <ExerciseManagement/exm_dtc.h>
#include <LtsSession/lts_session_data.h>
#include <ParticipantManagement/ppm_translation.h>
namespace ExerciseManagement
{
static constexpr int s_OrganisatorId = 99;
ExerciseOperatorModel::ExerciseOperatorModel(LtsSession::LtsSessionDataDds *session,
int exerciseId,
QObject *parent)
: LtsWidgets::LtsCheckableTableModel<QPair<bool, OperatorManagement::User>>( {tr("Name"),
tr("Description"),
tr("Visible Parties")}, 0, parent)
, m_opmDtc(nullptr)
, m_ppmDtc(nullptr)
, m_exerciseId(exerciseId)
{
if (!session->getDtc<OperatorManagement::DataInterface>(m_opmDtc))
return;
if (!session->getDtc<ParticipantManagement::DataInterface>(m_ppmDtc))
return;
auto cb = [this](const OperatorManagement::User &user)
{
if (user.id() != s_OrganisatorId)
insertRow(qMakePair(hasMembership(user), user));
};
m_opmDtc->users(cb);
connect(m_opmDtc.get(), &OperatorManagement::Interface::Dtc::userChanged, this,
&ExerciseOperatorModel::onOperatorChanged);
}
QVariant ExerciseOperatorModel::data(const QModelIndex &index, int role) const
{
if (!indexIsValid(index))
return {};
if (role != Qt::DisplayRole)
return LtsCheckableTableModel::data(index, role);
const auto &entry = m_vecData.at(index.row()).second;
std::vector<OperatorManagement::PartiesByExercise> vpbe = entry.visiblePartiesByExercise();
switch (index.column())
{
case Name:
return QString::fromStdString(entry.name());
case Description:
return QString::fromStdString(entry.description());
case VisibleParties:
{
return hasVisibleParties(vpbe);
}
}
return {};
}
QString ExerciseOperatorModel::hasVisibleParties(const std::vector<OperatorManagement::PartiesByExercise> vpbe) const
{
int exerciseId = (m_exerciseId != -1) ? m_exerciseId
: 0 /*new exercise*/;
for (const auto &pbe : vpbe)
{
if (pbe.exerciseId() != exerciseId)
continue;
std::vector<int32_t> hiddenParties = {};
if (pbe.hiddenParties().is_set()) //has_value not support on windows yet so we need depricated is_set
hiddenParties = pbe.hiddenParties().get();
if(pbe.visibleParties().is_set()) //has_value not support on windows yet so we need depricated is_set
{
return visibleParties(pbe.visibleParties().get(),
hiddenParties);
}
}
return {};
}
QString ExerciseOperatorModel::visibleParties(const std::vector<int32_t> &visible,
const std::vector<int32_t> &hidden) const
{
QStringList result;
result.reserve(visible.size());
for (const int partyId : visible)
{
bool isHidden = false;
for (const int hiddenId : hidden)
{
if (hiddenId != partyId)
continue;
isHidden = true;
}
if (!isHidden)
result.append(ParticipantManagement::trPartyName(m_ppmDtc->party(partyId).name()));
}
return result.join(QStringLiteral(", "));
}
void ExerciseOperatorModel::onOperatorChanged(const OperatorManagement::User &data, DataModification mod)
{
switch (mod)
{
case DataModification::eAdded:
{
insertRow(qMakePair(false, data));
break;
}
case DataModification::eRemoved:
{
for (int i = 0; i < m_vecData.size(); ++i)
if (m_vecData[i].second.id() == data.id())
{
removeRow(i);
break;
}
break;
}
case DataModification::eModified:
{
for (int i = 0; i < m_vecData.size(); ++i)
if (m_vecData[i].second.id() == data.id())
{
m_vecData[i].second = data;
break;
}
break;
}
}
}
bool ExerciseOperatorModel::hasMembership(const OperatorManagement::User &user) const
{
for (const auto exerciseId : user.exerciseIds())
if (exerciseId == m_exerciseId)
return true;
return false;
}
}
@@ -0,0 +1,51 @@
/**
* @RDE_HEADER@
* OperatorManagement - Group Edit member of model
* $Id$
* $HeadURL$
* $Author$
* Created by Malte Diers, SLSE, 2017-10-10
*/
#pragma once
#include <Plugins/OperatorManagement/Data/opm_data_plugin.h>
#include <Plugins/ParticipantManagement/Data/ppm_data_plugin.h>
#include <LtsSession/lts_session_data_dds.h>
#include <LtsWidgets/lts_checkable_table_model.h>
namespace ExerciseManagement
{
class ExerciseOperatorModel : public LtsWidgets::LtsCheckableTableModel<QPair<bool, OperatorManagement::User>>
{
Q_OBJECT
public:
enum Columns
{
Name,
Description,
VisibleParties
};
explicit ExerciseOperatorModel(LtsSession::LtsSessionDataDds *session, int exerciseId = 0,
QObject *parent = nullptr);
~ExerciseOperatorModel() = default;
QVariant data(const QModelIndex &index, int role) const override;
public slots:
void onOperatorChanged(const OperatorManagement::User &data, DataModification mod);
private:
QString hasVisibleParties(const std::vector<OperatorManagement::PartiesByExercise> vpbe) const;
QString visibleParties(const std::vector<int32_t> &visible,
const std::vector<int32_t> &hidden) const;
bool hasMembership(const OperatorManagement::User &user) const;
std::shared_ptr<OperatorManagement::Interface::Dtc> m_opmDtc;
std::shared_ptr<ParticipantManagement::Interface::Dtc> m_ppmDtc;
int m_exerciseId;
};
}
@@ -0,0 +1,142 @@
/**
* @RDE_HEADER@
* ExerciseManangement - Phase Edit Dialog
* $Id: exm_edit_dialog.h 41137 2018-04-20 08:50:55Z schroeder_m $
* $HeadURL: svn://slssvn/TDS/branches/product/devel/trunk/Lts/Plugins/ExerciseManagement/Gui/ExerciseEdit/exm_edit_dialog.h $
* $Author: schroeder_m $
* Created by Malte Schröder, SLSE, 2018-04-23
*/
#include "exm_phase_edit.h"
#include "ui_exm_phase_edit.h"
#include "exm_phase_model.h"
#include "exm_edit_phase_dialog.h"
#include <Plugins/ExerciseManagement/exm_data_plugin_interface.h>
namespace ExerciseManagement
{
ExerciseManagementPhaseEdit::ExerciseManagementPhaseEdit(const QString &menuGroup, QWidget *parent)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::CloseOnly)
, m_ui(new Ui::ExerciseManagementPhaseEdit)
, m_dtc(nullptr)
, m_ftc(nullptr)
, m_flmDtc(nullptr)
, m_flmFtc(nullptr)
, m_session(nullptr)
, m_phaseModel(nullptr)
, m_menuGroup(menuGroup)
, m_exercise()
, m_requestHelper(new LtsUtils::RequestHelper(this))
, m_logger(getLogger("ExerciseManagementStateEdit"))
{
m_ui->setupUi(this);
setOnlineHelpFilename(QStringLiteral("Situation-Exercise_Phases"));
}
ExerciseManagementPhaseEdit::~ExerciseManagementPhaseEdit()
{
delete m_ui;
}
bool ExerciseManagementPhaseEdit::init(LtsSession::LtsSessionDataDds *session)
{
m_session = session;
if (!m_session->getDtc<ExerciseManagement::DataInterface>(m_dtc))
return false;
if (!m_session->getFtc<ExerciseManagement::DataInterface>(m_ftc))
return false;
if (!m_session->getDtc<FileManagement::DataInterface>(m_flmDtc))
return false;
if (!m_session->getFtc<FileManagement::DataInterface>(m_flmFtc))
return false;
m_exercise = m_dtc->exercise(m_session->exerciseId());
m_phaseModel = new ExercisePhaseModel(this);
m_phaseModel->initModel(m_exercise.id(), m_dtc);
m_ui->dvPhases->setModel(m_phaseModel);
m_ui->dvPhases->hideColumn(3); // do not show the description
m_ui->dvPhases->hideColumn(4); // do not show the ExerciseId
m_ui->dvPhases->seamless();
m_buttonBox->connectButton(LtsWidgets::DialogButton::Add, this, &ExerciseManagementPhaseEdit::onAddExercisePhase);
m_buttonBox->connectButton(LtsWidgets::DialogButton::Edit, this, &ExerciseManagementPhaseEdit::onEditExercisePhase);
m_buttonBox->connectButton(LtsWidgets::DialogButton::Remove, this, &ExerciseManagementPhaseEdit::onRemoveExercisePhase);
connect(m_ui->dvPhases, &LtsDataView::LtsDataView::signalDoubleClicked,
this, &ExerciseManagementPhaseEdit::onEditExercisePhase);
connect(m_ui->dvPhases, &LtsDataView::LtsDataView::signalSelectionChanged,
this, &ExerciseManagementPhaseEdit::enaDisaPhaseButtons);
enaDisaPhaseButtons();
return true;
}
void ExerciseManagementPhaseEdit::enaDisaPhaseButtons()
{
QModelIndexList selectedRows = m_ui->dvPhases->selectedRows();
const int cntSelectedRows = selectedRows.size();
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Edit, cntSelectedRows == 1);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Remove, cntSelectedRows == 1);
}
void ExerciseManagementPhaseEdit::onAddExercisePhase()
{
ExerciseManagementPhaseEditDialog *dialog = new ExerciseManagementPhaseEditDialog(this);
dialog->init(m_session, m_exercise.id(), -1 /* new exercise phase */);
addDialog(dialog, m_menuGroup, QLatin1String("NewExercisePhase"), LtsWidgets::LayoutArea::eDialogTab);
}
void ExerciseManagementPhaseEdit::onEditExercisePhase()
{
const QModelIndex idx = m_ui->dvPhases->currentIndex();
const ExercisePhase exPhase = m_phaseModel->getRowData(idx.row());
if (exPhase.id() <= 0)
return;
DEBUG_LOG(m_logger) << "current exPhase Id: " << exPhase.id();
ExerciseManagementPhaseEditDialog *dialog = new ExerciseManagementPhaseEditDialog(this);
dialog->init(m_session, m_exercise.id(), exPhase.id());
const QString identifier = QLatin1String("EditExercisePhase") + QString::number(exPhase.id());
addDialog(dialog, m_menuGroup, identifier, LtsWidgets::LayoutArea::eDialogTab);
}
void ExerciseManagementPhaseEdit::onRemoveExercisePhase()
{
const int phId = m_phaseModel->getRowData(m_ui->dvPhases->currentIndex().row()).id();
int exeFolderId = m_flmDtc->getExerciseFolderId(m_exercise.id());
const int folderId = m_flmDtc->getPhaseFolderId(exeFolderId, phId);
if (folderId > 0)
{
Core::RemoveElementRequest req(folderId);
m_requestHelper->startSingleRequest([req, this]()
{
return m_flmFtc->folderRemoveRequest(req, this);
});
}
Core::RemoveElementRequest req(m_phaseModel->getRowData(m_ui->dvPhases->currentIndex().row()).id());
m_requestHelper->startSingleRequest([req, this]()
{
m_ftc->enableExercisePhaseRemove();
return m_ftc->exercisePhaseRemoveRequest(req, this);
});
}
void ExerciseManagementPhaseEdit::retranslate()
{
translate(m_ui, tr("Exercise Phases"));
}
}
@@ -0,0 +1,64 @@
/**
* @RDE_HEADER@
* ExerciseManangement - Phase Edit Dialog
* $Id: exm_edit_dialog.h 41137 2018-04-20 08:50:55Z schroeder_m $
* $HeadURL: svn://slssvn/TDS/branches/product/devel/trunk/Lts/Plugins/ExerciseManagement/Gui/ExerciseEdit/exm_edit_dialog.h $
* $Author: schroeder_m $
* Created by Malte Schröder, SLSE, 2018-04-23
*/
#pragma once
#include <ExerciseManagement/exm_dtc.h>
#include <ExerciseManagement/exm_ftc.h>
#include <ExerciseManagement/logger.h>
#include <LtsWidgets/lts_dialog.h>
#include <LtsUtilsGuiDds/request_helper.h>
#include <LtsSession/lts_session_data_dds.h>
#include <Plugins/FileManagement/flm_data_plugin_interface.h>
namespace Ui {
class ExerciseManagementPhaseEdit;
}
namespace ExerciseManagement
{
class ExercisePhaseModel;
class ExerciseManagementPhaseEdit : public LtsWidgets::LtsDialog
, protected ExerciseManagement::Interface::Ftc::ExercisePhaseRemoveReplyHandler
, protected FileManagement::Interface::Ftc::FolderRemoveReplyHandler
{
Q_OBJECT
public:
explicit ExerciseManagementPhaseEdit(const QString &menuGroup, QWidget *parent = nullptr);
~ExerciseManagementPhaseEdit();
bool init(LtsSession::LtsSessionDataDds *session);
protected:
void onExercisePhaseRemoveReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
void onFolderRemoveReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
private slots:
void onAddExercisePhase();
void onEditExercisePhase();
void onRemoveExercisePhase();
private:
void retranslate() override;
void enaDisaPhaseButtons();
Ui::ExerciseManagementPhaseEdit *m_ui;
std::shared_ptr<Interface::Dtc> m_dtc;
std::shared_ptr<Interface::Ftc> m_ftc;
std::shared_ptr<FileManagement::Interface::Dtc> m_flmDtc;
std::shared_ptr<FileManagement::Interface::Ftc> m_flmFtc;
LtsSession::LtsSessionDataDds *m_session;
ExercisePhaseModel *m_phaseModel;
QString m_menuGroup;
ExerciseManagement::Exercise m_exercise;
LtsUtils::RequestHelper *m_requestHelper;
LOGGER_T m_logger;
};
}
@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ExerciseManagementPhaseEdit</class>
<widget class="QWidget" name="ExerciseManagementPhaseEdit">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>821</width>
<height>546</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1">
<widget class="LtsDataView::LtsDataView" name="dvPhases"/>
</item>
<item row="1" column="0" colspan="2">
<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>
</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>
@@ -0,0 +1,104 @@
/**
* @RDE_HEADER@
* Exercise Phase Overview Model
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2017-04-11
*/
#include "exm_phase_model.h"
namespace ExerciseManagement
{
//---------------------------------
// ExercisePhaseModel
//---------------------------------
ExercisePhaseModel::ExercisePhaseModel(QObject *parent)
: LtsWidgets::LtsAbstractTableModel<ExerciseManagement::ExercisePhase>({tr("Phase"),
tr("Start"),
tr("End"),
tr("Description"),
tr("Exercise-Id")},
parent)
, m_exmDtc(nullptr)
, m_logger(getLogger("ExercisePhaseModel"))
{}
bool ExercisePhaseModel::initModel(int exerciseId, const std::shared_ptr<ExerciseManagement::Interface::Dtc> &dtc)
{
m_exerciseId = exerciseId;
m_exmDtc = dtc;
connect(m_exmDtc.get(), &ExerciseManagement::Interface::Dtc::exercisePhaseChanged,
this, &ExercisePhaseModel::onDataChanged);
// insert Model
m_exmDtc->exercisePhases([this](const ExercisePhase &item) { insertRow(item); });
INFO_LOG(m_logger) << "initModel - #exercise phases: " << m_vecData.size();
return true;
}
QVariant ExercisePhaseModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid() || role != Qt::DisplayRole || index.row() >= m_vecData.size())
return QVariant();
if (role == Qt::DisplayRole)
{
const ExerciseManagement::ExercisePhase &exPhase = m_vecData.at(index.row());
switch (index.column())
{
case Name:
return QString::fromStdString(exPhase.name());
case Start:
return QDateTime::fromMSecsSinceEpoch(exPhase.beginTime());
case End:
return QDateTime::fromMSecsSinceEpoch(exPhase.endTime());
case Description:
return QString::fromStdString(exPhase.description());
case ExerciseId:
return (exPhase.exerciseId());
}
}
return QVariant();
}
//
// ExercisePhaseProxyModel
//
void ExercisePhaseProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
{
m_sourceModel = qobject_cast<ExercisePhaseModel*>(sourceModel);
LtsWidgets::LtsColumnFilterProxyModel::setSourceModel(sourceModel);
}
bool ExercisePhaseProxyModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
{
if (!m_sourceModel ||
source_left.column() != source_right.column() ||
!source_left.isValid() ||
!source_right.isValid())
return LtsWidgets::LtsColumnFilterProxyModel::lessThan(source_left, source_right);
const auto &dataLeft = m_sourceModel->m_vecData.at(source_left.row());
const auto dataRight = m_sourceModel->m_vecData.at(source_right.row());
switch (source_left.column())
{
case ExercisePhaseModel::Start:
return dataLeft.beginTime() < dataRight.beginTime();
case ExercisePhaseModel::End:
return dataLeft.endTime() < dataRight.endTime();
case ExercisePhaseModel::Name:
case ExercisePhaseModel::Description:
case ExercisePhaseModel::ExerciseId:
break;
}
return LtsWidgets::LtsColumnFilterProxyModel::lessThan(source_left, source_right);
}
} // namespace ExerciseManagement
@@ -0,0 +1,72 @@
/**
* @RDE_HEADER@
* ExerciseManangement - Exercise Phase Overview Model
* $Id$
* $HeadURL$
* $Author$
* Created by Philipp Dassow, SLS1, 2017-04-11
*/
#pragma once
#include <LtsWidgets/lts_abstract_table_model.h>
#include <LtsWidgets/lts_column_filter_proxy_model.h>
#include <ExerciseManagement/exm_dtc.h>
#include <ExerciseManagement/logger.h>
namespace ExerciseManagement
{
// --------------------------------------------------------
// Exercise Phase Model
// --------------------------------------------------------
class ExercisePhaseModel final : public LtsWidgets::LtsAbstractTableModel<ExerciseManagement::ExercisePhase>
{
Q_OBJECT
public:
enum Columns
{
Name,
Start,
End,
Description,
ExerciseId
};
explicit ExercisePhaseModel(QObject *parent = nullptr);
bool initModel(int exerciseId, const std::shared_ptr<ExerciseManagement::Interface::Dtc> &dtc);
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override final;
protected:
bool isFiltered(const ExercisePhase &data, DataModification modType) const override
{
if (data.exerciseId() != m_exerciseId)
return true;
return LtsWidgets::LtsAbstractTableModel<ExerciseManagement::ExercisePhase>::isFiltered(data, modType);
}
private:
int m_exerciseId{0};
std::shared_ptr<ExerciseManagement::Interface::Dtc> m_exmDtc;
LOGGER_T m_logger;
friend class ExercisePhaseProxyModel;
};
class ExercisePhaseProxyModel final : public LtsWidgets::LtsColumnFilterProxyModel
{
Q_OBJECT
public:
using LtsWidgets::LtsColumnFilterProxyModel::LtsColumnFilterProxyModel;
void setSourceModel(QAbstractItemModel *sourceModel) override;
protected:
bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override;
private:
ExercisePhaseModel *m_sourceModel = nullptr;
};
}
@@ -0,0 +1,200 @@
/**
* @RDE_HEADER@
* ExerciseManangement - State Edit Dialog
* $Id: exm_edit_dialog.h 41137 2018-04-20 08:50:55Z schroeder_m $
* $HeadURL: svn://slssvn/TDS/branches/product/devel/trunk/Lts/Plugins/ExerciseManagement/Gui/ExerciseEdit/exm_edit_dialog.h $
* $Author: schroeder_m $
* Created by Malte Schröder, SLSE, 2018-04-20
*/
#include "exm_state_edit.h"
#include "ui_exm_state_edit.h"
#include <Plugins/ExerciseManagement/exm_data_plugin_interface.h>
#include <LtsWidgets/lts_message_dialog.h>
#include <LtsUtilsSettings/settings.h>
namespace ExerciseManagement
{
ExerciseManagementStateEdit::ExerciseManagementStateEdit(const QString &menuGroup, QWidget *parent)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
, m_ui(new Ui::ExerciseManagementStateEdit)
, m_dtc(nullptr)
, m_ftc(nullptr)
, m_session(nullptr)
, m_menuGroup(menuGroup)
, m_exercise()
, m_currentState(ExerciseState::Unknown)
, m_requestHelper(new LtsUtils::RequestHelper(this))
, m_logger(getLogger("ExerciseManagementStateEdit"))
{
m_ui->setupUi(this);
m_ui->cbState->setMinimumWidth(150);
m_ui->cbActivePhase->setMinimumWidth(150);
m_uiRequirements->addRequirement( { m_ui->lblState, [this]() { return (m_ui->cbState->currentData().isValid()); } } );
m_uiRequirements->addRequirement( { m_ui->lblActivePhase, [this]() { return (m_ui->cbActivePhase->currentData().isValid()); } } );
LtsUtils::ProjectSettings *ps = LtsUtils::ProjectSettings::getInstance();
const bool enableEditPhases = ps->value(QStringLiteral("exm"),
QStringLiteral("enableEditPhases")).toBool();
m_ui->lblActivePhase->setVisible(enableEditPhases);
m_ui->cbActivePhase->setVisible(enableEditPhases);
setOnlineHelpFilename(QStringLiteral("Situation-Exercise_State"));
}
ExerciseManagementStateEdit::~ExerciseManagementStateEdit()
{
delete m_ui;
}
bool ExerciseManagementStateEdit::init(LtsSession::LtsSessionDataDds *session)
{
m_session = session;
if (!m_session->getDtc<ExerciseManagement::DataInterface>(m_dtc))
return false;
if (!m_session->getFtc<ExerciseManagement::DataInterface>(m_ftc))
return false;
m_exercise = m_dtc->exercise(m_session->exerciseId());
m_currentState = m_exercise.state();
// combobox fill
fillStateCbx();
fillActivePhaseCbx();
// state cbx
m_ui->cbState->setEnabled(m_ui->cbState->count() > 1);
if (m_currentState == ExerciseState::Stopped || m_currentState == ExerciseState::Terminated)
{
m_ui->cbActivePhase->setEnabled(false);
}
// active phase cbx
connect(m_dtc.get(), &Interface::Dtc::exercisePhaseChanged, this, &ExerciseManagementStateEdit::onExercisePhaseChanged);
m_ui->cbActivePhase->setCurrentIndex(m_ui->cbActivePhase->findData(QVariant(m_exercise.activePhaseId())));
return true;
}
void ExerciseManagementStateEdit::fillStateCbx()
{
LtsUtils::ProjectSettings *ps = LtsUtils::ProjectSettings::getInstance();
const bool enableExerciseTerminatedToStopped = ps->value(QStringLiteral("exm"),
QStringLiteral("enableExerciseTerminatedToStopped")).toBool();
// exercise states
m_ui->cbState->clear();
switch (m_currentState.underlying())
{
case ExerciseState::Created:
m_ui->cbState->addItem(tr("Created"), ExerciseState::Created);
m_ui->cbState->addItem(tr("Start"), ExerciseState::Started);
break;
case ExerciseState::Started:
m_ui->cbState->addItem(tr("Started"), ExerciseState::Started);
m_ui->cbState->addItem(tr("Pause"), ExerciseState::Paused);
m_ui->cbState->addItem(tr("Stop"), ExerciseState::Stopped);
break;
case ExerciseState::Paused:
m_ui->cbState->addItem(tr("Paused"), ExerciseState::Paused);
m_ui->cbState->addItem(tr("Resume"), ExerciseState::Started);
m_ui->cbState->addItem(tr("Stop"), ExerciseState::Stopped);
break;
case ExerciseState::Stopped:
m_ui->cbState->addItem(tr("Stopped"), ExerciseState::Stopped);
break;
case ExerciseState::Terminated:
m_ui->cbState->addItem(tr("Terminated"), ExerciseState::Terminated);
if (enableExerciseTerminatedToStopped)
m_ui->cbState->addItem(tr("Stopped"), ExerciseState::Stopped);
break;
case ExerciseState::Unknown:
m_ui->cbState->addItem(tr("Unknown"), ExerciseState::Unknown);
break;
}
}
void ExerciseManagementStateEdit::fillActivePhaseCbx()
{
// active phase
int curIdxActPh = m_ui->cbActivePhase->currentIndex();
m_ui->cbActivePhase->clear();
auto cb = [this](const ExerciseManagement::ExercisePhase &phase)
{
if (m_exercise.id() == phase.exerciseId())
m_ui->cbActivePhase->addItem(QString::fromStdString(phase.name()), QVariant(phase.id()));
};
m_dtc->exercisePhases(cb);
m_ui->cbActivePhase->setEnabled(m_ui->cbActivePhase->count() > 1);
if (curIdxActPh >= 0)
m_ui->cbActivePhase->setCurrentIndex(curIdxActPh);
}
void ExerciseManagementStateEdit::onExercisePhaseChanged(const ExerciseManagement::ExercisePhase &data, DataModification modType)
{
Q_UNUSED(modType)
if (data.exerciseId() == m_exercise.id())
fillActivePhaseCbx();
}
void ExerciseManagementStateEdit::retranslate()
{
translate(m_ui, m_exercise, tr("Exercise State"));
}
bool ExerciseManagementStateEdit::apply()
{
ExerciseState exState = static_cast<ExerciseState::type>(m_ui->cbState->currentData().toInt());
if (exState.underlying() == ExerciseState_def::Stopped &&
LtsWidgets::LtsMessageDialog::showMessage(this,
tr("Are you sure you want to stop the exercise?"),
tr("Stop Exercise"),
LtsWidgets::Behaviour::Modal,
LtsWidgets::Button::Yes | LtsWidgets::Button::No)
== LtsWidgets::Button::No)
{
m_ui->cbState->setCurrentIndex(m_ui->cbState->findData(m_currentState.underlying()));
return true;
}
if (m_exercise.id() > 0)
{
ExerciseModifyRequest request;
// Update Data of Existing Exercise
request.id(m_exercise.id());
request.beginTime(m_exercise.beginTime());
request.endTime(m_exercise.endTime());
request.startTime(m_exercise.startTime());
request.stopTime(m_exercise.stopTime());
request.name(m_exercise.name());
request.sendToWMS(m_exercise.sendToWMS());
request.linkedExerciseId(m_exercise.linkedExerciseId());
request.trainingAreaId(m_exercise.trainingAreaId());
request.radioGroupId(m_exercise.radioGroupId());
request.symbolFillTypeId(m_exercise.symbolFillTypeId());
request.activePhaseId(m_ui->cbActivePhase->currentData().toInt());
request.defaultTimeZone(m_exercise.defaultTimeZone());
request.forces(m_exercise.forces());
request.description(m_exercise.description());
request.newState(static_cast<ExerciseState::type>(m_ui->cbState->currentData().toInt()));
if(!m_requestHelper->startSingleRequest(
[this, request]() {
m_ftc->enableExerciseModify();
return m_ftc->exerciseModifyRequest(request, this); })
)
return false;
}
init(m_session);
return true;
}
}
@@ -0,0 +1,59 @@
/**
* @RDE_HEADER@
* ExerciseManangement - State Edit Dialog
* $Id: exm_edit_dialog.h 41137 2018-04-20 08:50:55Z schroeder_m $
* $HeadURL: svn://slssvn/TDS/branches/product/devel/trunk/Lts/Plugins/ExerciseManagement/Gui/ExerciseEdit/exm_edit_dialog.h $
* $Author: schroeder_m $
* Created by Malte Schröder, SLSE, 2018-04-20
*/
#pragma once
#include <ExerciseManagement/exm_dtc.h>
#include <ExerciseManagement/exm_ftc.h>
#include <ExerciseManagement/logger.h>
#include <LtsWidgets/lts_dialog.h>
#include <LtsUtilsGuiDds/request_helper.h>
#include <LtsSession/lts_session_data_dds.h>
namespace Ui
{
class ExerciseManagementStateEdit;
}
namespace ExerciseManagement
{
class ExerciseManagementStateEdit : public LtsWidgets::LtsDialog
, protected ExerciseManagement::Interface::Ftc::ExerciseModifyReplyHandler
{
Q_OBJECT
public:
explicit ExerciseManagementStateEdit(const QString &menuGroup, QWidget *parent = nullptr);
~ExerciseManagementStateEdit();
bool init(LtsSession::LtsSessionDataDds *session);
protected:
void onExerciseModifyReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
private slots:
void onExercisePhaseChanged(const ExerciseManagement::ExercisePhase &data, DataModification modType);
private:
void retranslate() override;
bool apply() override final;
void fillStateCbx();
void fillActivePhaseCbx();
Ui::ExerciseManagementStateEdit *m_ui;
std::shared_ptr<Interface::Dtc> m_dtc;
std::shared_ptr<Interface::Ftc> m_ftc;
LtsSession::LtsSessionDataDds *m_session;
QString m_menuGroup;
ExerciseManagement::Exercise m_exercise;
ExerciseState m_currentState;
LtsUtils::RequestHelper *m_requestHelper;
LOGGER_T m_logger;
};
}
@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ExerciseManagementStateEdit</class>
<widget class="QWidget" name="ExerciseManagementStateEdit">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>488</width>
<height>221</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<widget class="QLabel" name="lblActivePhase">
<property name="text">
<string>Active Phase:</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="lblState">
<property name="text">
<string>State:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="LtsWidgets::LtsComboBox" name="cbState"/>
</item>
<item row="1" column="1">
<widget class="LtsWidgets::LtsComboBox" name="cbActivePhase"/>
</item>
<item row="2" column="0" colspan="2">
<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>
<item row="0" column="2" rowspan="2">
<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>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,23 @@
#
# $Id$
# $HeadURL$
# $Author$
# Created by Mike Wille, SLSE, 2017-09-29
#
SET(ExmWatch_SRCS
exm_watch_gui_plugin.cpp
exm_watch_gui_plugin.h
)
NGL_ADD_LIBRARY(WS ExmWatchGuiPlugin MODULE ${ExmWatch_SRCS})
NGL_TARGET_LINK_LIBRARIES(ExmWatchGuiPlugin
ngltools
LtsSession
ExmDataPluginInterface
LtsWidgets
)
NGL_INSTALL_TARGET(ExmWatchGuiPlugin)
@@ -0,0 +1,223 @@
/**
* @RDE_HEADER@
* Plugin to watch the currently active Exercise and keep track of the Exc Name, Exc Phase, etc.
* $Id$
* $HeadURL$
* $Author$
* Created by Mike Wille, SLSE, 2017-09-29
*/
#include "exm_watch_gui_plugin.h"
#include <LtsSession/lts_session.h>
#include <LtsWidgets/lts_message_dialog.h>
#include <LtsWidgets/lts_base_layout_widget.h>
#include <ExerciseManagement/exm_translation.h>
#include <ngltools/ngltools_dtg.h>
namespace ExerciseManagement
{
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.Exm.Watch"))
, m_dtc(nullptr)
, m_isDeleted(false)
{}
bool InterfaceImpl::fetchInterfaces()
{
if (!m_session->getDtc<ExerciseManagement::DataInterface>(m_dtc))
return false;
return true;
}
QVector<LtsWidgets::PluginData> InterfaceImpl::getActions()
{
QVector<LtsWidgets::PluginData> ret;
{
LtsWidgets::PluginData plData;
plData.menuGroup = menuGroup();
plData.createInstant = LtsWidgets::CreateInstantType::CreateInstantAndDiscardAction;
plData.directFunc = [this](const LtsWidgets::PluginData &)
{
connect(m_dtc.get(), &ExerciseManagement::Interface::Dtc::exerciseChanged,
this, &InterfaceImpl::slotExerciseChanged);
connect(m_dtc.get(), &ExerciseManagement::Interface::Dtc::exercisePhaseChanged,
this, &InterfaceImpl::slotExercisePhaseChanged);
if (m_session->isInitializationDone())
slotSetExerciseData();
else
connect(m_session, &LtsSession::LtsSession::signalDoneInitializingSession,
this, &InterfaceImpl::slotSetExerciseData); // wait until session is initialized
};
ret.append(plData);
}
return ret;
}
LtsWidgets::ExcState InterfaceImpl::convertState(ExerciseState state)
{
int underlying = state.underlying() - 1;
if (underlying >= 0)
{
int i_state = (1 << static_cast<int>(underlying));
return static_cast<LtsWidgets::ExcState>(i_state);
}
return LtsWidgets::ExcState::eUnknown;
}
void InterfaceImpl::clearInterfaces()
{
m_dtc = nullptr;
}
QColor InterfaceImpl::exerciseStateColor(ExerciseManagement::ExerciseState state)
{
switch(state.underlying())
{
case ExerciseState::Unknown: return Qt::black;
case ExerciseState::Created: return Qt::cyan;
case ExerciseState::Started: return Qt::darkGreen;
case ExerciseState::Paused: return Qt::darkYellow;
case ExerciseState::Stopped: return Qt::magenta;
case ExerciseState::Terminated: return Qt::red;
}
return QColor();
}
void InterfaceImpl::slotExerciseChanged(const ExerciseManagement::Exercise &data, DataModification modType)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, this=" << this << ", exId=" << data.id();
if (m_isDeleted)
return;
if (data.id() != m_session->exerciseId())
return;
switch (modType)
{
case DataModification::eRemoved:
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " eRemoved" << ", this=" << this << ", exId=" << data.id();
m_previouslyRemoved = true;
WARNING_LOG(m_logger) << "Partition has been removed from the DDS bus! Session: " << m_session->toString();
if (m_session->baseLayout())
m_session->baseLayout()->showMessage(tr("Connection to server lost"), tr("Trying to reconnect. You will be notified."), LtsWidgets::LtsNotificationBox::MessageType::Error);
break;
}
case DataModification::eAdded:
{
WARNING_LOG(m_logger) << LOGFUNCTION << ", Partition added to DDS bus! Session: " << m_session->toString();
DEBUG_LOG(m_logger) << LOGFUNCTION << " eAdded, m_previouslyRemoved=" << m_previouslyRemoved << ", this=" << this << ", exId=" << data.id();
if (m_previouslyRemoved)
{
m_previouslyRemoved = false;
if (m_session->baseLayout())
m_session->baseLayout()->showMessage(tr("Successfully reconnected"), tr("Connection to server was successfully reestablished."), LtsWidgets::LtsNotificationBox::MessageType::Success);
}
Q_FALLTHROUGH();
}
case DataModification::eModified:
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " eModified, m_previouslyRemoved=" << m_previouslyRemoved << ", this=" << this << ", exId=" << data.id();
slotSetExerciseData();
break;
}
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END, this=" << this << ", exId=" << data.id();
}
void InterfaceImpl::slotExercisePhaseChanged(const ExerciseManagement::ExercisePhase &data, DataModification modType)
{
Q_UNUSED(modType);
if (m_isDeleted)
return;
if (data.exerciseId() != m_session->exerciseId() ||
data.id() != m_session->exerciseData()->phId)
return;
slotExerciseChanged(m_dtc->exercise(m_session->exerciseId()), DataModification::eModified);
}
QString InterfaceImpl::partitionTypeString() const
{
switch (m_session->partitionType())
{
case IDL::PartitionType::Global: return QStringLiteral("<font color='grey'>%1</font>").arg(tr("Admin"));
case IDL::PartitionType::Exercise: return QStringLiteral("<font color='green'>%1</font>").arg(tr("Live"));
case IDL::PartitionType::Replay: return QStringLiteral("<font color='red'>%1</font>").arg(tr("Replay"));
default: return tr("unknown");
}
}
void InterfaceImpl::slotSetExerciseData()
{
disconnect(m_session, &LtsSession::LtsSession::signalDoneInitializingSession,
this, nullptr);
LtsWidgets::ExerciseData exData;
// 26.06.2023, Norbert Thoden
// Sometimes the ScriptEditorEssentialsView doesn´t have any buttons at the right menue.
// Reason:
// "Partition has been removed from the DDS bus"
// So afterwards slotSetExerciseData has called.
// With a virgin dtc leads to invalid data Exercise.
// So add waitForHistoricalData :-)
// Addtionally:
// Within slotExerciseChanged it´s handled as not m_previouslyRemoved
// and 'break' had skipped the rest of the slot - especially eModified.
// Now: If DDS partiton is newly created, the slot is called,
// eAdded and via Q_FALLTHROUGH eModified is executed also!
// To avoid signalExerciseDataChanged to be emiited multiple times,
// data is checked (operator==())
m_dtc->waitForHistoricalDataExercise(2000);
m_dtc->waitForHistoricalDataExercisePhase(2000);
const ExerciseManagement::Exercise &ex = m_dtc->exercise(m_session->exerciseId());
if (ex.id() != m_session->exerciseId())
FATAL_LOG(m_logger) << LOGFUNCTION << ", requested exId and return exId do not match!!!";
// no assert here to not desturb debugging
const ExerciseManagement::ExercisePhase &ph = m_dtc->exercisePhase(ex.activePhaseId());
exData.exName = QString::fromStdString(ex.name());
exData.exDescription = QString::fromStdString(ex.description());
exData.exStateString = ExerciseManagement::toString(ex.state());
exData.exState = convertState(ex.state());
exData.exStateCol = exerciseStateColor(ex.state());
exData.partitionType = partitionTypeString();
exData.phId = ph.id();
exData.phName = QString::fromStdString(ph.name());
exData.phDescription = QString::fromStdString(ph.description());
m_session->setExerciseData(exData);
DTG::setTimezone(ex.defaultTimeZone(), false);
}
} // namespace ExerciseManagement
@@ -0,0 +1,87 @@
/**
* @RDE_HEADER@
* Plugin to watch the currently active Exercise and keep track of the Exc Name, Exc Phase, etc.
* $Id$
* $HeadURL$
* $Author$
* Created by Mike Wille, SLSE, 2017-09-29
*/
#pragma once
#include <ExerciseManagement/logger.h>
#include <PluginInterfaces/gui_plugin_interface.h>
#include <Common/ProjectConfig/project_defines.h>
#include <Plugins/ExerciseManagement/exm_data_plugin_interface.h>
#include <Plugins/ExerciseManagement/exm_gui_plugin_interface.h>
namespace ExerciseManagement
{
class GuiPlugin final : public QObject, public GuiPluginBase::Plugin
{
Q_PLUGIN_METADATA(IID "gui:3:exm.watch")
Q_INTERFACES(GuiPluginBase::Plugin)
Q_OBJECT
public:
explicit GuiPlugin() = default;
~GuiPlugin() = default;
QString pluginName() override { return QLatin1String("ExerciseManagementWatchGuiPlugin"); }
std::shared_ptr<GuiPluginBase::Interface> createGuiInterface(LtsSession::LtsSession *session) override;
bool availableInPartition(IDL::PartitionType partition) const override
{
return (partition == IDL::PartitionType::Exercise) || (partition == IDL::PartitionType::Replay);
}
};
class InterfaceImpl final : public QObject, public GuiPluginBase::Interface
{
Q_OBJECT
public:
explicit InterfaceImpl(LtsSession::LtsSession *session);
bool fetchInterfaces() override;
void clearInterfaces() override;
QVector<LtsWidgets::PluginData> getActions() override;
bool availableInPartition(IDL::PartitionType partition) const override
{
return (partition == IDL::PartitionType::Exercise) || (partition == IDL::PartitionType::Replay);
}
private:
static LtsWidgets::ExcState convertState(ExerciseState state);
static QColor exerciseStateColor(ExerciseManagement::ExerciseState state);
QString partitionTypeString() const;
std::shared_ptr<ExerciseManagement::Interface::Dtc> m_dtc;
bool m_isDeleted;
bool m_previouslyRemoved { false };
private slots:
void slotExerciseChanged(const ExerciseManagement::Exercise &data, DataModification modType);
void slotExercisePhaseChanged(const ExerciseManagement::ExercisePhase &data, DataModification modType);
void slotSetExerciseData();
};
} // namespace ExerciseManagement
+30
View File
@@ -0,0 +1,30 @@
/**
* @RDE_HEADER@
* HMI Plugin for Exercisemanagemt (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 <ExerciseManagement/exm_dtc.h>
#include <ExerciseManagement/exm_ftc.h>
namespace ExerciseManagement
{
/**
* @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<ExerciseManagement::Interface::Dtc> getDtc() = 0;
virtual std::shared_ptr<ExerciseManagement::Interface::Ftc> getFtc() = 0;
};
} // namespace ExerciseManagement
+21
View File
@@ -0,0 +1,21 @@
/**
* @RDE_HEADER@
* HMI Plugin for Exercisemanagemt (Interface for access from other Plugins)
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#pragma once
namespace ExerciseManagement
{
class ForeignGuiInterface
{
public:
ForeignGuiInterface() = default;
virtual ~ForeignGuiInterface() = default;
};
} // namespace ExerciseManagement