Files
qt5-legatus-legacy/Lts/Plugins/ExerciseManagement/Gui/ExerciseEdit/exm_edit_dialog.cpp
T
2026-08-13 18:33:10 +02:00

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