1276 lines
47 KiB
C++
Executable File
1276 lines
47 KiB
C++
Executable File
/**
|
|
* @RDE_HEADER@
|
|
* ExerciseManangement - Exercise Edit Dialog
|
|
* $Id$
|
|
* $HeadURL$
|
|
* $Author$
|
|
* Created by Christian Ehrlicher, SLSE, 2016-02-29
|
|
*/
|
|
|
|
|
|
#include "exm_edit_dialog.h"
|
|
#include "ui_exm_edit_dialog.h"
|
|
#include "exm_edit_phase_dialog.h"
|
|
#include "exm_phase_model.h"
|
|
#include "exm_operator_model.h"
|
|
#include "exm_dialog_model.h" // for GetExerciseImageRequester
|
|
#include "exm_edit_party_dialog.h"
|
|
|
|
#include <LtsWidgets/lts_message_dialog.h>
|
|
#include <LtsUtilsCore/dds_vector.h>
|
|
#include <LtsUtilsCore/dds_vector_to_pixmap.h>
|
|
#include <LtsUtilsSettings/settings.h>
|
|
#include <LtsSession/lts_session_data.h>
|
|
#include <PluginInterfaces/gui_plugin_interface.h>
|
|
#include <Plugins/ExerciseManagement/exm_data_plugin_interface.h>
|
|
#include <Services/FileManagement/flm_ftc.h>
|
|
#include <ExerciseManagement/exm_operator_rights.h>
|
|
|
|
#include <QFile>
|
|
#include <QFileDialog>
|
|
#include <QJsonArray>
|
|
#include <QJsonDocument>
|
|
#include <QMenu>
|
|
|
|
|
|
namespace ExerciseManagement
|
|
{
|
|
// --------------------------------------------------------
|
|
// ExerciseManangementEditDialog
|
|
// --------------------------------------------------------
|
|
ExerciseManagementEditDialog::ExerciseManagementEditDialog(QWidget *parent)
|
|
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
|
|
, m_ui(new Ui::ExerciseManagementEditDialog)
|
|
, m_currentState(ExerciseState::Unknown)
|
|
, m_menuGroup()
|
|
, m_requestHelper(new LtsUtils::RequestHelper(this))
|
|
, m_logger(getLogger("ExerciseManangementEditDialog"))
|
|
{
|
|
m_ui->setupUi(this);
|
|
|
|
// TODO: replace with ui requirements (but after the constraints concept is done - I think they would perfectly fit together)
|
|
connect(m_ui->imageEditor, &LtsWidgets::LtsImageEditor::signalClicked,
|
|
this, &ExerciseManagementEditDialog::slotChangeImage);
|
|
|
|
m_ui->dvOperators->setContextMenuPolicy(Qt::CustomContextMenu);
|
|
connect(m_ui->dvOperators, &LtsDataView::LtsDataView::customContextMenuRequested, this, &ExerciseManagementEditDialog::onContextMenuRequested);
|
|
|
|
// Symbol Filltype derzeit von ESRI nicht unterstützt
|
|
m_ui->lbSymbolFilltype->setVisible(false);
|
|
m_ui->cbSymbolFilltype->setVisible(false);
|
|
|
|
for(int tz = 'Y'; tz <= 'Z'; ++tz)
|
|
m_ui->cbTimeZone->addItem(QString(QChar(tz)), tz);
|
|
for(int tz = 'A'; tz <= 'F'; ++tz)
|
|
m_ui->cbTimeZone->addItem(QString(QChar(tz)), tz);
|
|
|
|
const bool hasLinkedExercises = LtsUtils::ProjectSettings::isFunctionEnabled(QStringLiteral("Exercises"),
|
|
QStringLiteral("CanBeLinked"));
|
|
const bool hasHlaInterface = LtsUtils::ProjectSettings::isFunctionEnabled(QStringLiteral("Exercises"),
|
|
QStringLiteral("HasHlaInterface"));
|
|
m_ui->cbLinkedExercise->setVisible(hasLinkedExercises);
|
|
m_ui->lblLinkedExercise->setVisible(hasLinkedExercises);
|
|
m_ui->cbStartHlaInterface->setVisible(hasHlaInterface);
|
|
}
|
|
|
|
|
|
ExerciseManagementEditDialog::~ExerciseManagementEditDialog()
|
|
{
|
|
delete m_ui;
|
|
}
|
|
|
|
|
|
void ExerciseManagementEditDialog::retranslate()
|
|
{
|
|
// sample: m_ui->retranslateUi(this);
|
|
translate(m_ui, m_dtc->exercise(m_exerciseId), tr("Exercise"));
|
|
// Content in those comboboxes are not translated - no need to refill them
|
|
|
|
m_uiRequirements->clear();
|
|
m_uiRequirements->addRequirement( { m_ui->lblName, [this]() { return (!m_ui->leName->text().isEmpty()); } } );
|
|
m_uiRequirements->addRequirement( { m_ui->lblStart, [this]() { return (!m_ui->dtBegin->isEmpty()); } } );
|
|
m_uiRequirements->addRequirement( { m_ui->lblEnd, [this]() { return (!m_ui->dtEnd->isEmpty() && (m_ui->dtEnd->msecsSinceEpoch() > m_ui->dtBegin->msecsSinceEpoch())); }, tr("The end time must be bigger than the start time") });
|
|
|
|
m_ui->btbDvOperators->setText(LtsWidgets::DialogButton::Edit, tr("Edit Visible Parties"));
|
|
m_buttonBox->setText(LtsWidgets::DialogButton::Export, tr("Save to library"));
|
|
m_buttonBox->setText(LtsWidgets::DialogButton::Import, tr("Load from library"));
|
|
m_buttonBox->setText(LtsWidgets::DialogButton::Load, tr("Create Folders"));
|
|
}
|
|
|
|
|
|
bool ExerciseManagementEditDialog::init(LtsSession::LtsSessionDataDds *session,
|
|
const QString &menuGroup,
|
|
const int exerciseId)
|
|
{
|
|
m_session = session;
|
|
m_menuGroup = menuGroup;
|
|
m_exerciseId = exerciseId;
|
|
|
|
if (!m_session->getDtc<ExerciseManagement::DataInterface>(m_dtc))
|
|
return false;
|
|
if (!m_session->getFtc<ExerciseManagement::DataInterface>(m_ftc))
|
|
return false;
|
|
if (!m_session->getDtc<ProjectDataManagement::DataInterface>(m_pdmDtc)) // TODO: not obli
|
|
return false;
|
|
if (!m_session->getDtc<AssetManagement::DataInterface>(m_asmDtc)) // TODO: not obli
|
|
return false;
|
|
if (!m_session->getDtc<OperatorManagement::DataInterface>(m_opmDtc))
|
|
return false;
|
|
if (!m_session->getDtc<FileManagement::DataInterface>(m_flmDtc))
|
|
return false;
|
|
if (!m_session->getFtc<FileManagement::DataInterface>(m_flmFtc))
|
|
return false;
|
|
|
|
ExerciseManagement::Exercise data = m_dtc->exercise(exerciseId);
|
|
m_currentState = data.state();
|
|
m_ui->dtBegin->setRetrieveCurrentTimeCallback([this]() { return m_session->partitionTime(); });
|
|
m_ui->dtEnd->setRetrieveCurrentTimeCallback([this]() { return m_session->partitionTime(); });
|
|
|
|
m_phaseModel = new ExercisePhaseModel(this);
|
|
m_phaseModel->initModel(m_exerciseId, m_dtc);
|
|
m_phaseProxyModel = new ExercisePhaseProxyModel(this);
|
|
m_phaseProxyModel->setSourceModel(m_phaseModel);
|
|
|
|
m_operatorModel = new ExerciseOperatorModel(m_session, m_exerciseId, this);
|
|
connect(m_operatorModel, &ExerciseOperatorModel::dataChanged, this, &ExerciseManagementEditDialog::slotChangesMade);
|
|
|
|
// set data from dds
|
|
if (data.id() > 0)
|
|
{
|
|
m_ui->leName->setText(QString::fromStdString(data.name()));
|
|
m_ui->dtBegin->setTimezone(data.defaultTimeZone());
|
|
m_ui->dtBegin->setMsecsSinceEpoch(data.beginTime());
|
|
m_ui->dtEnd->setTimezone(data.defaultTimeZone());
|
|
m_ui->dtEnd->setMsecsSinceEpoch(data.endTime());
|
|
|
|
m_ui->pteDescription->setPlainText(QString::fromStdString(data.description()));
|
|
m_ui->pteForces->setPlainText(QString::fromStdString(data.forces()));
|
|
m_ui->cbTimeZone->setCurrentIndex(m_ui->cbTimeZone->findData(data.defaultTimeZone()));
|
|
m_ui->cbStartHlaInterface->setChecked(data.hasHlaInterface());
|
|
}
|
|
else
|
|
{
|
|
m_ui->cbTimeZone->setCurrentIndex(m_ui->cbTimeZone->findData('Z'));
|
|
m_ui->dtBegin->setMsecsSinceEpoch(m_session->partitionTime());
|
|
m_ui->dtEnd->setMsecsSinceEpoch(m_session->partitionTime() + 1000 * 60 * 60 * 24); // 1day
|
|
|
|
}
|
|
|
|
|
|
// stuff for exercise phases
|
|
m_ui->dvPhases->setModel(m_phaseProxyModel);
|
|
m_ui->dvPhases->hideColumn(ExercisePhaseModel::Description); // do not show the description
|
|
m_ui->dvPhases->hideColumn(ExercisePhaseModel::ExerciseId); // do not show the ExerciseId
|
|
m_ui->dvPhases->seamless();
|
|
m_ui->btbDvPhases->connectButton(LtsWidgets::DialogButton::Add, this, &ExerciseManagementEditDialog::onAddExercisePhase);
|
|
m_ui->btbDvPhases->connectButton(LtsWidgets::DialogButton::Edit, this, &ExerciseManagementEditDialog::onEditExercisePhase);
|
|
m_ui->btbDvPhases->connectButton(LtsWidgets::DialogButton::Remove, this, &ExerciseManagementEditDialog::onRemoveExercisePhase);
|
|
|
|
m_ui->dvOperators->setModel(m_operatorModel);
|
|
m_ui->dvOperators->seamless();
|
|
|
|
m_ui->btbDvOperators->connectButton(LtsWidgets::DialogButton::Edit, this, &ExerciseManagementEditDialog::onEditVisibleParties);
|
|
connect(m_ui->dvOperators, &LtsDataView::LtsDataView::signalDoubleClicked, this, &ExerciseManagementEditDialog::onEditVisibleParties);
|
|
|
|
|
|
m_ui->btbDvOperators->getButton(LtsWidgets::DialogButton::Ok)->setVisible(false);
|
|
m_ui->btbDvOperators->getButton(LtsWidgets::DialogButton::Close)->setVisible(false);
|
|
|
|
connect(m_operatorModel, &ExerciseOperatorModel::dataChanged,
|
|
this, &ExerciseManagementEditDialog::enaDisaOperatorsButtons);
|
|
connect(m_ui->dvOperators, &LtsDataView::LtsDataView::signalSelectionChanged,
|
|
this, &ExerciseManagementEditDialog::enaDisaOperatorsButtons);
|
|
enaDisaOperatorsButtons();
|
|
|
|
// workaround (mw)
|
|
m_ui->btbDvPhases->getButton(LtsWidgets::DialogButton::Ok)->setVisible(false);
|
|
m_ui->btbDvPhases->getButton(LtsWidgets::DialogButton::Apply)->setVisible(false);
|
|
m_ui->btbDvPhases->getButton(LtsWidgets::DialogButton::Close)->setVisible(false);
|
|
m_ui->btbDvPhases->getButton(LtsWidgets::DialogButton::Help)->setVisible(false);
|
|
|
|
|
|
LtsUtils::ProjectSettings *ps = LtsUtils::ProjectSettings::getInstance();
|
|
const bool enableEditPhases = ps->value(QStringLiteral("exm"),
|
|
QStringLiteral("enableEditPhases")).toBool();
|
|
if (!enableEditPhases)
|
|
{
|
|
m_ui->lblPhases->hide();
|
|
m_ui->dvPhases->hide();
|
|
m_ui->btbDvPhases->getButton(LtsWidgets::DialogButton::Add)->setVisible(false);
|
|
m_ui->btbDvPhases->getButton(LtsWidgets::DialogButton::Edit)->setVisible(false);
|
|
m_ui->btbDvPhases->getButton(LtsWidgets::DialogButton::Remove)->setVisible(false);
|
|
m_ui->btbDvPhases->getButton(LtsWidgets::DialogButton::Close)->setVisible(false);
|
|
|
|
m_ui->lblActivePhase->hide();
|
|
m_ui->cbActivePhase->hide();
|
|
}
|
|
|
|
connect(m_ui->dvPhases, &LtsDataView::LtsDataView::signalDoubleClicked,
|
|
this, &ExerciseManagementEditDialog::onEditExercisePhase);
|
|
connect(m_ui->dvPhases, &LtsDataView::LtsDataView::signalSelectionChanged,
|
|
this, &ExerciseManagementEditDialog::enaDisaPhaseButtons);
|
|
connect(m_ui->cbTimeZone, &QComboBox::currentTextChanged,
|
|
this, &ExerciseManagementEditDialog::onTimeZoneChanged);
|
|
|
|
enaDisaPhaseButtons();
|
|
|
|
// save and load description
|
|
m_buttonBox->connectButton(LtsWidgets::DialogButton::Export, this, &ExerciseManagementEditDialog::onExport);
|
|
m_buttonBox->connectButton(LtsWidgets::DialogButton::Import, this, &ExerciseManagementEditDialog::onImport);
|
|
|
|
m_buttonBox->connectButton(LtsWidgets::DialogButton::Load, this, &ExerciseManagementEditDialog::onCreateFolders);
|
|
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Load, false);
|
|
|
|
if (!session->getForeignGuiInterface<FileManagement::ForeignGuiInterface>(m_flmGui))
|
|
{
|
|
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Import, false);
|
|
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Export, false);
|
|
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Load, false);
|
|
}
|
|
|
|
// combobox fill
|
|
fillAllCbx();
|
|
|
|
// state cbx
|
|
m_ui->cbState->setEnabled(m_ui->cbState->count() > 1);
|
|
|
|
// active phase cbx
|
|
connect(m_dtc.get(), &Interface::Dtc::exercisePhaseChanged, this, &ExerciseManagementEditDialog::onExercisePhaseChanged);
|
|
m_ui->cbActivePhase->setCurrentIndex(m_ui->cbActivePhase->findData(QVariant(data.activePhaseId())));
|
|
|
|
// radio group cbx
|
|
connect(m_dtc.get(), &Interface::Dtc::exerciseChanged, this, &ExerciseManagementEditDialog::onExerciseChanged);
|
|
m_initialRadioGroupId.clear();
|
|
if (data.radioGroupId().is_set())
|
|
{
|
|
int curIdx = m_ui->cbRadioGroup->findData(QVariant(data.radioGroupId().get()));
|
|
if (curIdx < 0)
|
|
curIdx = 0; // 'No Radio Group'
|
|
else
|
|
m_initialRadioGroupId = data.radioGroupId().get();
|
|
m_ui->cbRadioGroup->setCurrentIndex(curIdx);
|
|
}
|
|
m_ui->cbVisibleInWarehouse->setChecked(data.sendToWMS());
|
|
m_ui->cbLinkedExercise->setCurrentIndex(m_ui->cbLinkedExercise->findData(data.linkedExerciseId()));
|
|
|
|
// training area cbx
|
|
if (data.trainingAreaId() > 0)
|
|
{
|
|
int idx = m_ui->cbTrainingArea->findData(QVariant(data.trainingAreaId()));
|
|
m_ui->cbTrainingArea->setCurrentIndex(idx);
|
|
}
|
|
|
|
if (m_exerciseId < 1) // new exercise
|
|
{
|
|
// no state, state is always 'created'
|
|
m_ui->lblState->hide();
|
|
m_ui->cbState->hide();
|
|
|
|
// no forces text
|
|
//m_ui->lblForces->hide();
|
|
//m_ui->pteForces->hide();
|
|
|
|
// no desc
|
|
//m_ui->lblDesc->hide();
|
|
//m_ui->pteDescription->hide();
|
|
|
|
// no active phase yet, as the exercise has to exist first
|
|
m_ui->cbActivePhase->hide();
|
|
m_ui->lblActivePhase->hide();
|
|
|
|
// no phases yet, as the exercise has to exist first
|
|
m_ui->dvPhases->hide();
|
|
m_ui->lblPhases->hide();
|
|
m_ui->btbDvPhases->hide();
|
|
|
|
// styling
|
|
m_ui->line->hide();
|
|
// m_ui->line_2->hide();
|
|
|
|
QString projectLogoFilename(QStringLiteral(":project/login_logo.png"));
|
|
if (!QFile(projectLogoFilename).exists())
|
|
projectLogoFilename = QStringLiteral(":/project/logo.png");
|
|
|
|
m_ui->imageEditor->setPixmap(QPixmap(projectLogoFilename)); // new exercise's default logo
|
|
m_pictureChanged = true;
|
|
}
|
|
|
|
if (m_exerciseId < 0)
|
|
setOnlineHelpFilename(QStringLiteral("Administrator-Add_Exercise"));
|
|
else
|
|
setOnlineHelpFilename(QStringLiteral("Administrator-Edit_Exercise"));
|
|
|
|
enaDisa();
|
|
|
|
// request exercise image to put it into the image editor
|
|
requestImage();
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
void ExerciseManagementEditDialog::requestImage()
|
|
{
|
|
GetExerciseImageRequester *requester = GetExerciseImageRequester::createGetExerciseImageRequester();
|
|
|
|
connect(requester, &GetExerciseImageRequester::signalDone,
|
|
this, [this, requester]()
|
|
{
|
|
onGetExerciseImageReply(requester->reply());
|
|
});
|
|
|
|
m_ftc->enableGetExerciseImage();
|
|
m_ftc->getExerciseImageRequest(GetExerciseImageRequest(m_exerciseId, m_ui->imageEditor->height(), m_ui->imageEditor->width(), false), requester);
|
|
}
|
|
|
|
|
|
void ExerciseManagementEditDialog::onGetExerciseImageReply(const GetExerciseImageReply &reply)
|
|
{
|
|
if (reply.errorString().empty())
|
|
{
|
|
m_ui->imageEditor->setPixmap(LtsUtils::getPixmap(reply.imageData()));
|
|
return;
|
|
}
|
|
|
|
QString msg(QString::fromStdString(reply.errorString()));
|
|
for (const std::string &arg : qAsConst(reply.errorParams()))
|
|
msg = msg.arg(QString::fromStdString(arg));
|
|
|
|
ERROR_LOG(m_logger) << "loading exercise image failed: " << msg;
|
|
//new LtsWidgets::LtsMessageDialogNew(this, tr("Couldn't get exercise image due to an server error"));
|
|
|
|
// set project logo as exc img
|
|
QString projectLogoFilename(QStringLiteral(":project/login_logo.png"));
|
|
if (!QFile(projectLogoFilename).exists())
|
|
projectLogoFilename = QStringLiteral(":/project/logo.png");
|
|
|
|
m_ui->imageEditor->setPixmap(QPixmap(projectLogoFilename));
|
|
}
|
|
|
|
void ExerciseManagementEditDialog::onTimeZoneChanged()
|
|
{
|
|
QChar tz = m_ui->cbTimeZone->currentData().toChar();
|
|
|
|
m_ui->dtBegin->setTimezone(tz.toLatin1());
|
|
m_ui->dtEnd->setTimezone(tz.toLatin1());
|
|
}
|
|
|
|
bool ExerciseManagementEditDialog::hasVisibleParties(const std::vector<OperatorManagement::PartiesByExercise> vpbe) const
|
|
{
|
|
for (const auto &pbe : vpbe)
|
|
{
|
|
if (pbe.exerciseId() != m_exerciseId)
|
|
continue;
|
|
|
|
return pbe.visibleParties().is_set(); //has_value not support on windows yet so we need depricated is_set
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void ExerciseManagementEditDialog::enaDisaOperatorsButtons()
|
|
{
|
|
const QModelIndex idx = m_ui->dvOperators->currentIndex();
|
|
if (!idx.isValid())
|
|
{
|
|
m_ui->btbDvOperators->setButtonEnabled(LtsWidgets::DialogButton::Edit, false);
|
|
return;
|
|
}
|
|
const QPair<bool, OperatorManagement::User> row = m_operatorModel->getRowData(idx.row());
|
|
bool visibleParties = hasVisibleParties(row.second.visiblePartiesByExercise());
|
|
bool isChecked = row.first;
|
|
|
|
if (LtsSessionData::LtsSessionData::getInstance()->hasOperatorRight(OperatorRights::ExerciseOperatorEdit))
|
|
m_ui->btbDvOperators->setButtonEnabled(LtsWidgets::DialogButton::Edit, (visibleParties && isChecked));
|
|
else
|
|
m_ui->btbDvOperators->setButtonEnabled(LtsWidgets::DialogButton::Edit, false);
|
|
}
|
|
|
|
void ExerciseManagementEditDialog::enaDisaPhaseButtons()
|
|
{
|
|
QModelIndexList selectedRows = m_ui->dvPhases->selectedRows();
|
|
const int cntSelectedRows = selectedRows.size();
|
|
|
|
if (LtsSessionData::LtsSessionData::getInstance()->hasOperatorRight(OperatorRights::ExercisePhaseEdit))
|
|
{
|
|
m_ui->btbDvPhases->setButtonEnabled(LtsWidgets::DialogButton::Edit, cntSelectedRows == 1);
|
|
m_ui->btbDvPhases->setButtonEnabled(LtsWidgets::DialogButton::Remove, cntSelectedRows == 1);
|
|
}
|
|
else
|
|
{
|
|
m_ui->btbDvPhases->setButtonEnabled(LtsWidgets::DialogButton::Add, false);
|
|
m_ui->btbDvPhases->setButtonEnabled(LtsWidgets::DialogButton::Edit, false);
|
|
m_ui->btbDvPhases->setButtonEnabled(LtsWidgets::DialogButton::Remove, false);
|
|
}
|
|
}
|
|
|
|
void ExerciseManagementEditDialog::onAddExercisePhase()
|
|
{
|
|
ExerciseManagementPhaseEditDialog *dialog = new ExerciseManagementPhaseEditDialog(this);
|
|
dialog->init(m_session, m_exerciseId, -1 /* new exercise phase */);
|
|
|
|
addDialog(dialog, m_menuGroup, QLatin1String("NewExercisePhase"), LtsWidgets::LayoutArea::eDialogTab);
|
|
}
|
|
|
|
void ExerciseManagementEditDialog::onRemoveExercisePhase()
|
|
{
|
|
const int phId = m_phaseModel->getRowData(m_ui->dvPhases->currentIndex().row()).id();
|
|
const int folderId = m_flmDtc->getPhaseFolderId(m_exerciseId, 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 ExerciseManagementEditDialog::onEditVisibleParties()
|
|
{
|
|
if (m_exerciseId == -1) // new exercise
|
|
return;
|
|
|
|
const QModelIndex idx = m_ui->dvOperators->currentIndex();
|
|
const QPair<bool, OperatorManagement::User> row = m_operatorModel->getRowData(idx.row());
|
|
const int operatorId = row.second.id();
|
|
bool isChecked = row.first;
|
|
bool visibleParties = hasVisibleParties(row.second.visiblePartiesByExercise());
|
|
|
|
if (operatorId <= 0 || isChecked == false || !visibleParties) // only checked entries with parties (operator_exercise) editable
|
|
return;
|
|
DEBUG_LOG(m_logger) << "current Operator Id: " << operatorId;
|
|
|
|
|
|
ExerciseEditPartyDialog *dialog = new ExerciseEditPartyDialog(operatorId, m_exerciseId, m_menuGroup, this);
|
|
|
|
if (!dialog->init(m_session))
|
|
return;
|
|
|
|
const QString identifier = QLatin1String("EditParties") + QString::number(operatorId) + QString::number(m_exerciseId);
|
|
addDialog(dialog, m_menuGroup, identifier, LtsWidgets::LayoutArea::eDialogTab);
|
|
}
|
|
|
|
void ExerciseManagementEditDialog::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_exerciseId, exPhase.id());
|
|
const QString identifier = QLatin1String("EditExercisePhase") + QString::number(exPhase.id());
|
|
|
|
addDialog(dialog, m_menuGroup, identifier, LtsWidgets::LayoutArea::eDialogTab);
|
|
}
|
|
|
|
void ExerciseManagementEditDialog::onExport()
|
|
{
|
|
DEBUG_LOG(m_logger) << "onExport";
|
|
|
|
const QByteArray byteArray = exerciseToJson();
|
|
DEBUG_LOG(m_logger) << "Exporting: " << byteArray;
|
|
|
|
int fileId = m_flmGui->saveFileContent(this, FileManagement::FileType::Xml, 0, byteArray);
|
|
if (fileId > 0)
|
|
DEBUG_LOG(m_logger) << "Saved file with id = " << fileId;
|
|
else
|
|
ERROR_LOG(m_logger) << "Could not save file in library ";
|
|
}
|
|
|
|
void ExerciseManagementEditDialog::onImport()
|
|
{
|
|
DEBUG_LOG(m_logger) << "onImport";
|
|
|
|
QByteArray content;
|
|
int fileId = m_flmGui->loadFileContent(this, content, {FileManagement::FileType::Xml}, 0, JsonKeys::XMLTYPEVALUE());
|
|
if (fileId > 0)
|
|
{
|
|
if (!m_flmGui->isXmlType(content, JsonKeys::XMLTYPEVALUE()))
|
|
{
|
|
QHash<LtsWidgets::Button, QString> texts({{LtsWidgets::Button::Yes, tr("Ok")}});
|
|
LtsWidgets::LtsMessageDialog::showMessage(this,
|
|
tr("Invalid xml file content"),
|
|
windowTitle(),
|
|
LtsWidgets::Behaviour::Modal,
|
|
LtsWidgets::Button::Yes,
|
|
texts);
|
|
}
|
|
else
|
|
{
|
|
ExerciseModifyRequest req = jsonToExercise(content);
|
|
DEBUG_LOG(m_logger) << "Importing: " << req;
|
|
|
|
m_ui->pteForces->setPlainText(QString::fromStdString(req.forces()));
|
|
m_ui->pteDescription->setPlainText(QString::fromStdString(req.description()));
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
void ExerciseManagementEditDialog::slotChangeImage()
|
|
{
|
|
if (!m_ui->imageEditor->pixmap().isNull())
|
|
{
|
|
if (LtsWidgets::LtsMessageDialog::showMessage(this, tr("Yes - overwrite image.<br>"
|
|
"Cancel - do not overwrite image.<br>"),
|
|
tr("Do you really want to overwrite the current image?"),
|
|
LtsWidgets::Behaviour::Modal,
|
|
LtsWidgets::Button::Yes | LtsWidgets::Button::Cancel) != LtsWidgets::Button::Yes)
|
|
return; // do nothing if not ack by user
|
|
}
|
|
|
|
const QStringList filter ({
|
|
tr("Images (*.jpg *.jpeg *.png)")
|
|
});
|
|
QString fileName = QFileDialog::getOpenFileName(this,
|
|
tr("Select new image for this exercise"),
|
|
QString(), // last wd
|
|
filter.join(QStringLiteral(";;")));
|
|
|
|
if (fileName.isEmpty())
|
|
return;
|
|
|
|
QPixmap pixmap;
|
|
if (!pixmap.load(fileName))
|
|
{
|
|
LtsWidgets::LtsMessageDialog::showMessage(this, tr("Cannot load image '%1'").arg(fileName));
|
|
return;
|
|
}
|
|
|
|
QSize newImgSize(200, 200);
|
|
QRect requestedRect(QPoint(0, 0), newImgSize);
|
|
QRect pictureRect(QPoint(0, 0), pixmap.size());
|
|
|
|
if (pictureRect.contains(requestedRect)) // only shrink, don't grow (which would make the image unnecessarily bigger)
|
|
pixmap = pixmap.scaled(200, 200, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
|
|
|
m_ui->imageEditor->setPixmap(pixmap);
|
|
|
|
m_pictureChanged = true; // TODO: let this be automatically managed by
|
|
slotChangesMade(); // !
|
|
}
|
|
|
|
void ExerciseManagementEditDialog::imageModifyError()
|
|
{
|
|
if (m_exerciseId > 0)
|
|
m_ui->imageEditor->setPixmap(QPixmap());
|
|
|
|
// request exercise image to put it into the image editor / revert
|
|
requestImage();
|
|
}
|
|
|
|
void ExerciseManagementEditDialog::onExerciseChanged(const ExerciseManagement::Exercise &data, DataModification modType)
|
|
{
|
|
Q_UNUSED(modType)
|
|
if (data.id() == m_exerciseId)
|
|
{
|
|
const bool wasModified = hasUnsavedChanges();
|
|
m_currentState = data.state();
|
|
enaDisa();
|
|
fillStateCbx();
|
|
m_ui->cbVisibleInWarehouse->setChecked(data.sendToWMS());
|
|
m_ui->cbLinkedExercise->setCurrentIndex(m_ui->cbLinkedExercise->findData(data.linkedExerciseId()));
|
|
if (!wasModified)
|
|
__unchange__();
|
|
}
|
|
else
|
|
fillRadioGroupCbx();
|
|
}
|
|
|
|
void ExerciseManagementEditDialog::onExercisePhaseChanged(const ExerciseManagement::ExercisePhase &data, DataModification modType)
|
|
{
|
|
Q_UNUSED(modType)
|
|
if (data.exerciseId() == m_exerciseId)
|
|
fillActivePhaseCbx();
|
|
}
|
|
|
|
void ExerciseManagementEditDialog::enaDisa()
|
|
{
|
|
const bool wmsChecked = m_ui->cbVisibleInWarehouse->isChecked();
|
|
const bool exerciseIsRunning = (m_currentState == ExerciseManagement::ExerciseState::Started ||
|
|
m_currentState == ExerciseManagement::ExerciseState::Paused);
|
|
const bool exerciseIsFinished = (m_currentState == ExerciseManagement::ExerciseState::Stopped ||
|
|
m_currentState == ExerciseManagement::ExerciseState::Terminated);
|
|
bool radioGroupAssignable = !exerciseIsFinished;
|
|
if (radioGroupAssignable && exerciseIsRunning)
|
|
radioGroupAssignable = m_initialRadioGroupId.isNull(); // when running, only assignable when not yet assigned
|
|
if (radioGroupAssignable)
|
|
radioGroupAssignable = (m_ui->cbRadioGroup->count() > 1);
|
|
|
|
m_ui->cbVisibleInWarehouse->setEnabled(!exerciseIsRunning || !wmsChecked);
|
|
m_ui->cbLinkedExercise->setEnabled(!exerciseIsRunning && m_exerciseId > 0);
|
|
m_ui->cbRadioGroup->setEnabled(radioGroupAssignable);
|
|
m_ui->cbTrainingArea->setEnabled(!exerciseIsRunning && !exerciseIsFinished);
|
|
if (getExerciseFolder() <= 0)
|
|
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Load, true);
|
|
else
|
|
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Load, false);
|
|
}
|
|
|
|
|
|
void ExerciseManagementEditDialog::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);
|
|
m_ui->cbState->addItem(tr("Terminated"), ExerciseState::Terminated);
|
|
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 ExerciseManagementEditDialog::fillTrainingAreaCbx()
|
|
{
|
|
// training areas
|
|
int curIdxTa = m_ui->cbTrainingArea->currentIndex();
|
|
m_ui->cbTrainingArea->clear();
|
|
auto cb = [this](const AssetManagement::TrainingArea &ta)
|
|
{
|
|
m_ui->cbTrainingArea->addItem(QString::fromStdString(ta.name()), QVariant(ta.id()));
|
|
};
|
|
m_asmDtc->trainingAreas(cb);
|
|
m_ui->cbTrainingArea->model()->sort(0);
|
|
|
|
if (curIdxTa >= 0)
|
|
m_ui->cbTrainingArea->setCurrentIndex(curIdxTa);
|
|
}
|
|
|
|
void ExerciseManagementEditDialog::fillActivePhaseCbx()
|
|
{
|
|
// active phase
|
|
int curIdxActPh = m_ui->cbActivePhase->currentIndex();
|
|
m_ui->cbActivePhase->clear();
|
|
auto cb = [this](const ExerciseManagement::ExercisePhase &phase)
|
|
{
|
|
if (m_exerciseId == 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 ExerciseManagementEditDialog::fillRadioGroupCbx()
|
|
{
|
|
// radio group
|
|
const bool wasModified = hasUnsavedChanges();
|
|
int curRadioGroupId = m_ui->cbRadioGroup->currentData().toInt();
|
|
m_ui->cbRadioGroup->clear();
|
|
|
|
// const entry for no radio
|
|
m_ui->cbRadioGroup->addItem(tr("No Radio Group"), QVariant(0));
|
|
|
|
// filter already used radio groups
|
|
const QMap <qint32, ExerciseManagement::Exercise> mapEx = m_dtc->exercises();
|
|
QMap <qint32, ProjectDataManagement::RadioGroup> mapRadioGrp = m_pdmDtc->radioGroups();
|
|
for (auto it = mapEx.begin(); it != mapEx.end(); ++it)
|
|
if (it.value().id() != m_exerciseId)
|
|
if (it.value().radioGroupId().is_set())
|
|
mapRadioGrp.remove(it.value().radioGroupId().get());
|
|
|
|
// add available groups except base group
|
|
for (auto it = mapRadioGrp.begin(); it != mapRadioGrp.end(); ++it)
|
|
{
|
|
const auto &radioGroup = it.value();
|
|
if (!radioGroup.base_group())
|
|
m_ui->cbRadioGroup->addItem(m_pdmDtc->trRadioGroupName(radioGroup.id()), radioGroup.id());
|
|
}
|
|
|
|
m_ui->cbTrainingArea->model()->sort(0);
|
|
m_ui->cbRadioGroup->setEnabled(m_ui->cbRadioGroup->count() > 1);
|
|
|
|
if (curRadioGroupId >= 0)
|
|
{
|
|
int newIdx = m_ui->cbRadioGroup->findData(curRadioGroupId);
|
|
if (newIdx >= 0)
|
|
{
|
|
m_ui->cbRadioGroup->setCurrentIndex(newIdx);
|
|
if (!wasModified)
|
|
__unchange__();
|
|
}
|
|
}
|
|
}
|
|
|
|
void ExerciseManagementEditDialog::fillLinkedExercisesCbx()
|
|
{
|
|
int curId = m_ui->cbLinkedExercise->currentData().toInt();
|
|
m_ui->cbLinkedExercise->clear();
|
|
auto cb = [this](const Exercise &ex)
|
|
{
|
|
if (ex.state() != ExerciseManagement::ExerciseState::Created && ex.linkedExerciseId() != m_exerciseId)
|
|
return;
|
|
if (ex.id() == m_exerciseId)
|
|
return;
|
|
m_ui->cbLinkedExercise->addItem(QString::fromStdString(ex.name()), ex.id());
|
|
};
|
|
m_dtc->exercises(cb);
|
|
m_ui->cbLinkedExercise->addItem(tr("---"), 0);
|
|
|
|
if (curId < 0)
|
|
curId = 0;
|
|
m_ui->cbLinkedExercise->setCurrentIndex(m_ui->cbLinkedExercise->findData(curId));
|
|
}
|
|
|
|
|
|
void ExerciseManagementEditDialog::fillAllCbx()
|
|
{
|
|
fillStateCbx();
|
|
fillTrainingAreaCbx();
|
|
fillActivePhaseCbx();
|
|
fillRadioGroupCbx();
|
|
fillLinkedExercisesCbx();
|
|
}
|
|
|
|
template<class T>
|
|
bool ExerciseManagementEditDialog::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;
|
|
}
|
|
|
|
bool ExerciseManagementEditDialog::apply() // TODO: clean me up !
|
|
{
|
|
bool retVal = true;
|
|
|
|
bool isAlreadyUnchangeable = unchangeable();
|
|
__unchange__();
|
|
if (!isAlreadyUnchangeable)
|
|
setUnchangeable(true);
|
|
|
|
if (m_exerciseId > 0) // edit existing exercise
|
|
{
|
|
ExerciseState state = static_cast<ExerciseState::type>(m_ui->cbState->currentData().toInt());
|
|
ExerciseManagement::Exercise data = m_dtc->exercise(m_exerciseId);
|
|
if (state == ExerciseState_def::Stopped && data.state() != ExerciseState_def::Stopped)
|
|
{
|
|
if (LtsWidgets::LtsMessageDialog::showMessage(this, QString(),
|
|
tr("Are you sure you want to stop the exercise?"),
|
|
LtsWidgets::Behaviour::Modal,
|
|
LtsWidgets::Button::Yes | LtsWidgets::Button::No) != LtsWidgets::Button::Yes)
|
|
|
|
retVal = false;
|
|
|
|
}
|
|
else if (state == ExerciseState_def::Terminated && data.state() != ExerciseState_def::Terminated)
|
|
{
|
|
if (LtsWidgets::LtsMessageDialog::showMessage(this, QString(),
|
|
tr("Are you sure you want to terminate the exercise?"),
|
|
LtsWidgets::Behaviour::Modal,
|
|
LtsWidgets::Button::Yes | LtsWidgets::Button::No) != LtsWidgets::Button::Yes)
|
|
|
|
retVal = false;
|
|
}
|
|
|
|
if (retVal)
|
|
{
|
|
ExerciseModifyRequest request;
|
|
// Update Data of Existing Exercise
|
|
request.id(m_exerciseId);
|
|
request.beginTime(m_ui->dtBegin->msecsSinceEpoch());
|
|
request.endTime(m_ui->dtEnd->msecsSinceEpoch());
|
|
request.name(m_ui->leName->text().toStdString());
|
|
request.sendToWMS(m_ui->cbVisibleInWarehouse->isChecked());
|
|
request.linkedExerciseId(m_ui->cbLinkedExercise->currentData().toInt());
|
|
request.trainingAreaId(m_ui->cbTrainingArea->currentData().toInt());
|
|
int radioGroup = m_ui->cbRadioGroup->currentData().toInt();
|
|
if (radioGroup != 0)
|
|
{
|
|
m_initialRadioGroupId = radioGroup;
|
|
request.radioGroupId(radioGroup);
|
|
}
|
|
// TODO: add symbolFillType (PDM)
|
|
request.symbolFillTypeId(0);
|
|
request.activePhaseId(m_ui->cbActivePhase->currentData().toInt());
|
|
request.defaultTimeZone(m_ui->cbTimeZone->currentData().toChar().toLatin1());
|
|
request.forces(m_ui->pteForces->toPlainText().toStdString());
|
|
request.description(m_ui->pteDescription->toPlainText().toStdString());
|
|
request.hasHlaInterface(m_ui->cbStartHlaInterface->isChecked());
|
|
request.newState(static_cast<ExerciseState::type>(m_ui->cbState->currentData().toInt()));
|
|
request.operatorId(LtsSessionData::LtsSessionData::getInstance()->getOperatorId());
|
|
request.workstationId(LtsSessionData::LtsSessionData::getInstance()->getWorkstationId());
|
|
|
|
//ExerciseManagement::Exercise data = m_dtc->exercise(m_exerciseId);
|
|
if (data.startTime() > 0)
|
|
request.startTime(data.startTime());
|
|
if (data.stopTime() > 0)
|
|
request.stopTime(data.stopTime());
|
|
|
|
if (!m_requestHelper->startSingleRequest([this, request]()
|
|
{
|
|
m_ftc->enableExerciseModify();
|
|
return m_ftc->exerciseModifyRequest(request, this);
|
|
}))
|
|
retVal = false;
|
|
|
|
if (m_pictureChanged)
|
|
{
|
|
ExerciseImageModifyRequest exImgRequest(m_exerciseId, LtsUtils::fromPixmap(getPixmap()));
|
|
m_requestHelper->startSingleRequest([this, exImgRequest]()
|
|
{
|
|
m_ftc->enableExerciseImageModify();
|
|
return m_ftc->exerciseImageModifyRequest(exImgRequest, this);
|
|
});
|
|
}
|
|
|
|
sendModifiedOperators(m_exerciseId);
|
|
}
|
|
|
|
// do nothing on failure - rh's message is enough
|
|
//return m_requestHelper->startRequests(); // return success or failure
|
|
|
|
// TODO: check if something has changed (constraints manager / ui requirements should also check for changes)
|
|
}
|
|
else // add new exercise
|
|
{
|
|
ExerciseCreateRequest request;
|
|
request.beginTime(m_ui->dtBegin->msecsSinceEpoch());
|
|
request.endTime(m_ui->dtEnd->msecsSinceEpoch());
|
|
request.name(m_ui->leName->text().toStdString());
|
|
request.sendToWMS(m_ui->cbVisibleInWarehouse->isChecked());
|
|
request.linkedExerciseId(m_ui->cbLinkedExercise->currentData().toInt());
|
|
request.trainingAreaId(m_ui->cbTrainingArea->currentData().toInt());
|
|
int radioGroup = m_ui->cbRadioGroup->currentData().toInt();
|
|
if (radioGroup != 0)
|
|
request.radioGroupId(radioGroup);
|
|
|
|
// TODO: symbolFillType (PDM)
|
|
request.symbolFillTypeId(0);
|
|
request.defaultTimeZone(m_ui->cbTimeZone->currentData().toChar().toLatin1());
|
|
request.forces(m_ui->pteForces->toPlainText().toStdString());
|
|
request.description(m_ui->pteDescription->toPlainText().toStdString());
|
|
request.hasHlaInterface(m_ui->cbStartHlaInterface->isChecked());
|
|
|
|
// Add New Exercise
|
|
if (!m_requestHelper->startSingleRequest([this, request]()
|
|
{
|
|
m_ftc->enableExerciseCreate();
|
|
return m_ftc->exerciseCreateRequest(request, this);
|
|
}))
|
|
retVal = false;
|
|
|
|
int newExId = m_requestHelper->getRepliedId();
|
|
|
|
DEBUG_LOG(m_logger) << "Created new exercise with id " << newExId;
|
|
|
|
if (newExId > 0)
|
|
{
|
|
ExerciseImageModifyRequest exImgRequest(newExId,
|
|
LtsUtils::fromPixmap(getPixmap()));
|
|
if (!m_requestHelper->startSingleRequest([this, exImgRequest]()
|
|
{
|
|
m_ftc->enableExerciseImageModify();
|
|
return m_ftc->exerciseImageModifyRequest(exImgRequest, this);
|
|
})) // not a critical error - don't return false!
|
|
{
|
|
WARNING_LOG(m_logger) << "Unable to set default exercise picture";
|
|
LtsWidgets::LtsMessageDialog::showMessage(this, tr("Unable to set default exercise picture"));
|
|
}
|
|
|
|
// now we've the new exerciseId -> we can update the operators
|
|
sendModifiedOperators(newExId);
|
|
|
|
// create Folders
|
|
if (!createFolders(newExId))
|
|
{
|
|
WARNING_LOG(m_logger) << "Unable to create exercise folders in document library.";
|
|
LtsWidgets::LtsMessageDialog::showMessage(this, tr("Unable to create exercise folders in document library."));
|
|
}
|
|
|
|
}
|
|
else
|
|
retVal = false;
|
|
|
|
// TODO: check if something has changed (constraints manager / ui requirements should also check for changes)
|
|
}
|
|
|
|
if (!isAlreadyUnchangeable)
|
|
setUnchangeable(false);
|
|
|
|
return retVal;
|
|
}
|
|
|
|
|
|
const QPixmap ExerciseManagementEditDialog::getPixmap() const
|
|
{
|
|
return QPixmap(m_ui->imageEditor->pixmap());
|
|
}
|
|
|
|
|
|
void ExerciseManagementEditDialog::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();
|
|
|
|
DEBUG_LOG(m_logger) << "Adding request: " << req;
|
|
m_requestHelper->addRequest([this, req, opmFtc]()
|
|
{
|
|
DEBUG_LOG(m_logger) << "Executing request: " << req;
|
|
return opmFtc->operatorCreateModifyRequest(req, this);
|
|
});
|
|
|
|
}
|
|
|
|
m_requestHelper->startRequests();
|
|
}
|
|
|
|
bool ExerciseManagementEditDialog::createFolders(int newExId)
|
|
{
|
|
// exercise folder
|
|
QString folderName = m_flmDtc->getExerciseFolderName(newExId);
|
|
int folderId = createFolder(FileManagement::MainFolder::ExerciseDocuments, folderName);
|
|
|
|
if (folderId <= 0)
|
|
return false;
|
|
|
|
DEBUG_LOG(m_logger) << "Exercise Folder created with id = " << folderId;
|
|
|
|
// Documents sub-folder
|
|
folderName = QStringLiteral("Documents") ;
|
|
int subFolderId = createFolder(folderId, folderName);
|
|
|
|
if (subFolderId <= 0)
|
|
return false;
|
|
|
|
DEBUG_LOG(m_logger) << "Sub Folder Documents created with id = " << subFolderId;
|
|
|
|
// Under Documents: TODO: english names Errors...
|
|
QStringList folderNames;
|
|
folderNames << QStringLiteral("Fault documentation Evaluation") << QStringLiteral("Fault documentation Evaluation EXCON");
|
|
folderNames << QStringLiteral("Incidents") << QStringLiteral("Instructions");
|
|
|
|
bool ok = createExerciseFolders(subFolderId, folderNames);
|
|
DEBUG_LOG(m_logger) << "Created sub-folders Documents: " << ok;
|
|
|
|
// Phase documents
|
|
LtsUtils::ProjectSettings *ps = LtsUtils::ProjectSettings::getInstance();
|
|
const bool enableEditPhases = ps->value(QStringLiteral("exm"),
|
|
QStringLiteral("enableEditPhases")).toBool();
|
|
if (enableEditPhases)
|
|
{
|
|
// Phase Documents folder (needs to be created separate because we need the id of new created folder)
|
|
folderName = QStringLiteral("Phase Documents");
|
|
int folderPhaseDocsId = createFolder(subFolderId, folderName);
|
|
DEBUG_LOG(m_logger) << "Phase Documents Folder created with id = " << folderPhaseDocsId;
|
|
|
|
// active phase folder
|
|
if (folderPhaseDocsId > 0)
|
|
{
|
|
int phId = m_dtc->exercise(newExId).activePhaseId();
|
|
const QString &phaseName = m_flmDtc->getPhaseFolderName(phId);
|
|
int folderPhaseId = createFolder(folderPhaseDocsId, phaseName);
|
|
DEBUG_LOG(m_logger) << "Phase Folder created with id = " << folderPhaseId;
|
|
}
|
|
}
|
|
|
|
// Markers
|
|
folderName = QStringLiteral("Markers");
|
|
subFolderId = createFolder(folderId, folderName);
|
|
DEBUG_LOG(m_logger) << "Markers Folder created with id = " << subFolderId;
|
|
|
|
FileManagement::PathCreateRequest req;
|
|
req.parentId(folderId);
|
|
req.path({"Planning", "TNE Lists"});
|
|
req.isEditable(false);
|
|
req.isHidden(false);
|
|
req.operatorId(LtsSessionData::LtsSessionData::getInstance()->getOperatorId());
|
|
|
|
bool success = m_flmFtc->pathCreateRequest(req);
|
|
if (!success)
|
|
ERROR_LOG(m_logger) << "Planning/TNE Lists could not be created";
|
|
|
|
// Tactical Plans
|
|
req.path({"Tactical Plans", "BDA"});
|
|
success = m_flmFtc->pathCreateRequest(req);
|
|
if (!success)
|
|
ERROR_LOG(m_logger) << "Tactical Plans/BDA could not be created";
|
|
|
|
req.path({"Tactical Plans", "HQ Data"});
|
|
success = m_flmFtc->pathCreateRequest(req);
|
|
|
|
if (!success)
|
|
ERROR_LOG(m_logger) << "Tactical Plans/HQ Data could not be created";
|
|
|
|
// Reports, Snapshots
|
|
folderNames.clear();
|
|
folderNames << QStringLiteral("Reports") << QStringLiteral("Snapshots");
|
|
ok = createExerciseFolders(folderId, folderNames);
|
|
DEBUG_LOG(m_logger) << "Created last exercise documents: " << ok;
|
|
|
|
return true;
|
|
}
|
|
|
|
int ExerciseManagementEditDialog::createFolder(int parentFolderId, const QString &folderName, bool isHidden)
|
|
{
|
|
FileManagement::Folder parentFolder = m_flmDtc->folder(parentFolderId);
|
|
const std::vector<int32_t> &parentPath = parentFolder.path();
|
|
|
|
FileManagement::FolderModifyRequest req;
|
|
req.name(folderName.toStdString());
|
|
req.path(parentPath);
|
|
req.isEditable(false);
|
|
req.isHidden(isHidden);
|
|
req.parentId(parentFolderId);
|
|
req.operatorId(LtsSessionData::LtsSessionData::getInstance()->getOperatorId());
|
|
|
|
m_requestHelper->startSingleRequest([this, req]()
|
|
{
|
|
return m_flmFtc->folderModifyRequest(req, this);
|
|
});
|
|
|
|
DEBUG_LOG(m_logger) << "Created folder id = " << m_requestHelper->getRepliedId();
|
|
|
|
return m_requestHelper->getRepliedId();
|
|
}
|
|
|
|
bool ExerciseManagementEditDialog::createExerciseFolders(int parentFolderId, const QStringList &folderNames)
|
|
{
|
|
FileManagement::Folder parentFolder = m_flmDtc->folder(parentFolderId);
|
|
const std::vector<int32_t> &parentPath = parentFolder.path();
|
|
|
|
FileManagement::FolderModifyRequest req;
|
|
req.path(parentPath);
|
|
req.isEditable(false);
|
|
req.isHidden(false);
|
|
req.parentId(parentFolderId);
|
|
req.operatorId(LtsSessionData::LtsSessionData::getInstance()->getOperatorId());
|
|
|
|
for ( const QString &folderName : folderNames )
|
|
{
|
|
req.name(folderName.toStdString());
|
|
|
|
m_requestHelper->addRequest([this, req]()
|
|
{
|
|
return m_flmFtc->folderModifyRequest(req, this);
|
|
});
|
|
}
|
|
|
|
return m_requestHelper->startRequests();
|
|
}
|
|
|
|
|
|
void ExerciseManagementEditDialog::onContextMenuRequested(const QPoint &position)
|
|
{
|
|
QMenu menu(m_ui->dvOperators);
|
|
menu.addAction(tr("Select All"), this, &ExerciseManagementEditDialog::onSelectAllUsers);
|
|
menu.addAction(tr("Unselect All"), this, &ExerciseManagementEditDialog::onUnselectAllUsers);
|
|
menu.exec(m_ui->dvOperators->mapToGlobal(position));
|
|
}
|
|
|
|
void ExerciseManagementEditDialog::onSelectAllUsers()
|
|
{
|
|
m_operatorModel->selectAll();
|
|
m_operatorModel->update();
|
|
}
|
|
|
|
void ExerciseManagementEditDialog::onUnselectAllUsers()
|
|
{
|
|
m_operatorModel->unselectAll();
|
|
m_operatorModel->update();
|
|
}
|
|
|
|
ExerciseModifyRequest ExerciseManagementEditDialog::setRequestContent() const
|
|
{
|
|
ExerciseModifyRequest req;
|
|
|
|
req.forces(m_ui->pteForces->toPlainText().toStdString());
|
|
req.description(m_ui->pteDescription->toPlainText().toStdString());
|
|
|
|
const ExerciseModifyRequest out = req;
|
|
return out;
|
|
}
|
|
|
|
QByteArray ExerciseManagementEditDialog::exerciseToJson() const
|
|
{
|
|
const ExerciseModifyRequest req = setRequestContent();
|
|
|
|
QJsonObject obj;
|
|
long long startExercise = m_ui->dtBegin->msecsSinceEpoch();
|
|
|
|
obj[JsonKeys::XMLTYPE()] = JsonKeys::XMLTYPEVALUE();
|
|
|
|
obj[JsonKeys::FORCES()] = QString::fromStdString(req.forces());
|
|
obj[JsonKeys::DESCRIPTION()] = QString::fromStdString(req.description());
|
|
|
|
QJsonArray phases;
|
|
for(int row = 0; row < m_phaseModel->rowCount(); ++row)
|
|
{
|
|
QJsonObject phase;
|
|
phase.insert(JsonKeys::PID(), m_phaseModel->getRowData(row).id());
|
|
phase.insert(JsonKeys::PNAME(), QString::fromStdString(m_phaseModel->getRowData(row).name()));
|
|
phase.insert(JsonKeys::PISDELETED(), m_phaseModel->getRowData(row).isDeleted());
|
|
phase.insert(JsonKeys::PISUSED(), m_phaseModel->getRowData(row).isUsed());
|
|
long long beginTime = m_phaseModel->getRowData(row).beginTime() - startExercise;
|
|
long long endTime = m_phaseModel->getRowData(row).endTime() - startExercise;
|
|
phase.insert(JsonKeys::PBEGINTIME(), beginTime);
|
|
phase.insert(JsonKeys::PENDTIME(), endTime);
|
|
phase.insert(JsonKeys::PDESCRIPTION(), QString::fromStdString(m_phaseModel->getRowData(row).description()));
|
|
phase.insert(JsonKeys::PEXERCISEID(), m_phaseModel->getRowData(row).exerciseId());
|
|
phases.append(phase);
|
|
}
|
|
obj[JsonKeys::PHASES()] = phases;
|
|
|
|
QJsonArray operatorIds;
|
|
const QVector<int> checkedIds = m_operatorModel->getCheckedIds();
|
|
for(const int id : checkedIds)
|
|
operatorIds += id;
|
|
obj[JsonKeys::OPERATORS()] = operatorIds;
|
|
|
|
QJsonDocument doc(obj);
|
|
return doc.toJson(QJsonDocument::Compact);
|
|
}
|
|
|
|
ExerciseModifyRequest ExerciseManagementEditDialog::jsonToExercise(const QByteArray &content) const
|
|
{
|
|
ExerciseModifyRequest result;
|
|
|
|
// already checked that content is not empty, is parseable and it contains a proper XmlType (EXMExerciseDescription)
|
|
const QJsonDocument doc(QJsonDocument::fromJson(content));
|
|
const QJsonObject obj(doc.object());
|
|
|
|
result.forces(obj[JsonKeys::FORCES()].toString().toStdString());
|
|
result.description(obj[JsonKeys::DESCRIPTION()].toString().toStdString());
|
|
|
|
// ----- Phases -----
|
|
QJsonArray phasesArray = obj[JsonKeys::PHASES()].toArray();
|
|
QVector<ExerciseManagement::ExercisePhase> phases;
|
|
|
|
for (auto it = phasesArray.constBegin(); it != phasesArray.constEnd(); ++it)
|
|
{
|
|
QJsonObject phaseObj = (*it).toObject();
|
|
ExerciseManagement::ExercisePhase phase;
|
|
phase.id(phaseObj[JsonKeys::PID()].toInt());
|
|
phase.name(phaseObj[JsonKeys::PNAME()].toString().toStdString());
|
|
phase.isDeleted(phaseObj[JsonKeys::PISDELETED()].toBool());
|
|
phase.isUsed(phaseObj[JsonKeys::PISUSED()].toBool());
|
|
phase.description(phaseObj[JsonKeys::PDESCRIPTION()].toString().toStdString());
|
|
// Relative to the exercise start time
|
|
phase.beginTime(phaseObj[JsonKeys::PBEGINTIME()].toInt() + m_ui->dtBegin->msecsSinceEpoch());
|
|
phase.endTime(phaseObj[JsonKeys::PENDTIME()].toInt() + m_ui->dtBegin->msecsSinceEpoch());
|
|
phase.exerciseId(phaseObj[JsonKeys::PEXERCISEID()].toInt());
|
|
phases.append(phase);
|
|
}
|
|
m_phaseModel->setData(phases);
|
|
if ( phases.size()> 0)
|
|
{
|
|
m_ui->dvPhases->show();
|
|
m_ui->lblPhases->show();
|
|
m_ui->btbDvPhases->show();
|
|
}
|
|
|
|
// ----- Operators -----
|
|
const QJsonArray operatorArray = obj[JsonKeys::OPERATORS()].toArray();
|
|
QVector<int> selectedIds;
|
|
selectedIds.reserve(operatorArray.size());
|
|
for (const auto &ele : operatorArray)
|
|
selectedIds.append(ele.toInt());
|
|
m_operatorModel->setChecked(selectedIds);
|
|
|
|
return result;
|
|
}
|
|
|
|
void ExerciseManagementEditDialog::onCreateFolders()
|
|
{
|
|
DEBUG_LOG(m_logger) << "onCreateFolders";
|
|
if (m_exerciseId > 0 && getExerciseFolder() <= 0 )
|
|
{
|
|
bool ok = createFolders(m_exerciseId);
|
|
if (!ok)
|
|
{
|
|
WARNING_LOG(m_logger) << "Could not create exercise folders";
|
|
LtsWidgets::LtsMessageDialog::showMessage(this, tr("Could not create exercise folders"));
|
|
}
|
|
else
|
|
{
|
|
LtsWidgets::LtsMessageDialog::showMessage(this, tr("Exercise folders successfully created"));
|
|
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Load, false);
|
|
}
|
|
}
|
|
}
|
|
|
|
int ExerciseManagementEditDialog::getExerciseFolder()
|
|
{
|
|
if (m_exerciseId <= 0)
|
|
return 0;
|
|
|
|
const int folderId = m_flmDtc->getExerciseFolderId(m_exerciseId);
|
|
DEBUG_LOG(m_logger) << "getExerciseFolder: folderId = " << folderId;
|
|
return folderId;
|
|
}
|
|
|
|
} // namespace ExerciseManagement
|