Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
+390
@@ -0,0 +1,390 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* The ExerciseAssignmentDialog shows how many assets are needed for a specific schedule, needed elsewhere,
|
||||
* totally possessed, free, and missing
|
||||
* $Id: ism_exercise_assignment_dialog.cpp 57783 2022-08-03 11:07:05Z ojog_i $
|
||||
* $HeadURL: svn://192.168.133.21/TDS/branches/product/features/22_09_resmgmt2.0/Lts/Plugins/InfrastructureManagement/Gui/AudioVideoConfig/ExerciseAssignment/ism_exercise_assignment_dialog.cpp $
|
||||
* $Author: ojog_i $
|
||||
* Created by Hannes Baeuerle, SLSE, 2017-06-29
|
||||
* Refreshed by Mike Wille, SLTE, 2022-09-26
|
||||
*/
|
||||
|
||||
#include "ism_exercise_assignment_dialog.h"
|
||||
#include "ui_ism_exercise_assignment_dialog.h"
|
||||
#include "ism_exercise_assignment_dialog_requesters.h"
|
||||
#include "ism_exercise_assignment_dialog_proxy_model.h"
|
||||
|
||||
#include <LtsUtilsCore/json_object.h>
|
||||
#include <ExerciseManagement/exm_data_plugin_interface.h>
|
||||
#include <InfrastructureManagement/ism_data_plugin_interface.h>
|
||||
#include <LtsSession/lts_session.h>
|
||||
#include <LtsPrinting/printing.h>
|
||||
#include <LtsWidgets/lts_overlay_loading.h>
|
||||
#include <LtsUtilsSettings/settings.h>
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
|
||||
using namespace LtsUtils;
|
||||
using namespace LtsWidgets;
|
||||
|
||||
|
||||
namespace InfrastructureManagement
|
||||
{
|
||||
ExerciseAssignmentDialog::ExerciseAssignmentDialog(LtsSession::LtsSession *session, QWidget *parent) noexcept(false)
|
||||
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
|
||||
, m_session(session)
|
||||
, m_ui(new Ui::ExerciseAssignmentDialog)
|
||||
, m_model(nullptr)
|
||||
, m_modelAssignedFilter(new ExerciseAssignmentDialogModelFilterProxy(this))
|
||||
, m_modelUnassignedFilter(new ExerciseAssignmentDialogModelFilterProxy(this))
|
||||
, m_logger(getLogger("ExerciseAssignmentDialog"))
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
m_buttonBox->connectButton(LtsWidgets::DialogButton::Print, this, &ExerciseAssignmentDialog::onPrint);
|
||||
setOnlineHelpFilename(QStringLiteral("Ressourcen-Exercise_Assignment"));
|
||||
|
||||
std::shared_ptr<ExerciseManagement::Interface::Dtc> exmDtc;
|
||||
|
||||
if (!m_session->getDtc<DataInterface>(m_dtc) ||
|
||||
!m_session->getFtc<DataInterface>(m_ftc) ||
|
||||
!m_session->getDtc<ExerciseManagement::DataInterface>(exmDtc))
|
||||
throw std::exception();
|
||||
|
||||
if (!m_ftc->enableMainStructureElementModify())
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Could not enable FT MainStructureElementModify of ISM";
|
||||
throw std::exception();
|
||||
}
|
||||
|
||||
if (!exmDtc->enableExercise())
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Could not enable DT Exercise of EXM";
|
||||
throw std::exception();
|
||||
}
|
||||
|
||||
// Add all available exercises to comboBox (do not add deleted or terminated exercises)
|
||||
exmDtc->exercises([this](const ExerciseManagement::Exercise &data)
|
||||
{
|
||||
if (data.isDeleted())
|
||||
return;
|
||||
|
||||
switch(data.state().underlying())
|
||||
{
|
||||
case ExerciseManagement::ExerciseState_def::Created:
|
||||
case ExerciseManagement::ExerciseState_def::Started:
|
||||
case ExerciseManagement::ExerciseState_def::Paused:
|
||||
case ExerciseManagement::ExerciseState_def::Stopped:
|
||||
{
|
||||
m_exercises.insert(data.id(), data);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
for (const auto &exercise : qAsConst(m_exercises))
|
||||
m_ui->cbExercises->addItem(QString::fromStdString(exercise.name()), exercise.id());
|
||||
|
||||
|
||||
if (m_ui->cbExercises->count() == 0)
|
||||
{
|
||||
setEnabled(false);
|
||||
setUnchangeable();
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Print)->setEnabled(false);
|
||||
return;
|
||||
}
|
||||
else
|
||||
m_ui->label->setVisible(false);
|
||||
|
||||
m_model = new ExerciseAssignmentDialogModel(m_exercises, this);
|
||||
|
||||
// set initial exercise filter to the assigned exercises so that only buildings for exercise x are visible
|
||||
auto exerciseChangedFn = [this](int index = -1)
|
||||
{
|
||||
Q_UNUSED(index);
|
||||
|
||||
m_modelAssignedFilter->setExerciseId(m_ui->cbExercises->currentData().toInt());
|
||||
//m_ui->assignedExercises->expandAll();
|
||||
};
|
||||
|
||||
connect(m_ui->cbExercises, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||
this, exerciseChangedFn);
|
||||
exerciseChangedFn();
|
||||
|
||||
// NOT live, otherwise:
|
||||
connect(m_dtc.get(), &Interface::Dtc::mainStructureElementChanged,
|
||||
this, &ExerciseAssignmentDialog::onMainStructureElementChanged);
|
||||
|
||||
auto cb = [this](const InfrastructureManagement::MainStructureElement &mse)
|
||||
{
|
||||
onMainStructureElementChanged(mse, DataModification::eAdded);
|
||||
};
|
||||
m_dtc->mainStructureElements(cb);
|
||||
|
||||
m_modelUnassignedFilter->setSourceModel(m_model);
|
||||
m_ui->availableExercises->setModel(m_modelUnassignedFilter);
|
||||
m_ui->availableExercises->setSortingEnabled(true);
|
||||
m_ui->availableExercises->sortByColumn(0, Qt::SortOrder::AscendingOrder);
|
||||
m_ui->availableExercises->setDragEnabled(true);
|
||||
m_ui->availableExercises->viewport()->setAcceptDrops(true);
|
||||
// m_ui->availableExercises->setDropIndicatorShown(true);
|
||||
m_ui->availableExercises->setDragDropMode(QAbstractItemView::DragDrop);
|
||||
m_ui->availableExercises->setDefaultDropAction(Qt::DropAction::MoveAction);
|
||||
|
||||
m_modelAssignedFilter->setSourceModel(m_model);
|
||||
m_ui->assignedExercises->setModel(m_modelAssignedFilter);
|
||||
m_ui->assignedExercises->setSortingEnabled(true);
|
||||
m_ui->assignedExercises->sortByColumn(0, Qt::SortOrder::AscendingOrder);
|
||||
m_ui->assignedExercises->setDragEnabled(true);
|
||||
m_ui->assignedExercises->viewport()->setAcceptDrops(true);
|
||||
// m_ui->assignedExercises->setDropIndicatorShown(true);
|
||||
m_ui->assignedExercises->setDragDropMode(QAbstractItemView::DragDrop);
|
||||
m_ui->assignedExercises->setDefaultDropAction(Qt::DropAction::MoveAction);
|
||||
|
||||
connect(m_modelAssignedFilter, &ExerciseAssignmentDialogModelFilterProxy::doRefilter,
|
||||
this, &ExerciseAssignmentDialog::onUnassignedNeedsUpdate);
|
||||
connect(m_modelUnassignedFilter, &ExerciseAssignmentDialogModelFilterProxy::doRefilter,
|
||||
this, &ExerciseAssignmentDialog::onAssignedNeedsUpdate);
|
||||
}
|
||||
|
||||
|
||||
ExerciseAssignmentDialog::~ExerciseAssignmentDialog()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
void ExerciseAssignmentDialog::onUnassignedNeedsUpdate(const QSet<QModelIndex> &setToExpand)
|
||||
{
|
||||
m_modelUnassignedFilter->invalidate();
|
||||
for(auto indexToExpand : setToExpand)
|
||||
m_ui->assignedExercises->expand(m_modelAssignedFilter->mapFromSource(indexToExpand));
|
||||
slotChangesMade();
|
||||
}
|
||||
|
||||
void ExerciseAssignmentDialog::onAssignedNeedsUpdate(const QSet<QModelIndex> &setToExpand)
|
||||
{
|
||||
m_modelAssignedFilter->invalidate();
|
||||
for(auto indexToExpand : setToExpand)
|
||||
m_ui->availableExercises->expand(m_modelUnassignedFilter->mapFromSource(indexToExpand));
|
||||
slotChangesMade();
|
||||
}
|
||||
|
||||
|
||||
void ExerciseAssignmentDialog::retranslate()
|
||||
{
|
||||
translate(m_ui, tr("Exercise Assignment"));
|
||||
}
|
||||
|
||||
|
||||
void ExerciseAssignmentDialog::onMainStructureElementChanged(const InfrastructureManagement::MainStructureElement &mse, DataModification modType)
|
||||
{
|
||||
auto seti = mse.structureElementTypeId();
|
||||
if (seti != StructureElementType::Building &&
|
||||
seti != StructureElementType::Announcement)
|
||||
return;
|
||||
|
||||
// read exercise id and add to assigned exercises
|
||||
QString displayName(m_dtc->getBuildingDisplayName(mse.id()));
|
||||
if (displayName.isEmpty())
|
||||
displayName = QString::fromStdString(mse.name());
|
||||
|
||||
int exerciseId;
|
||||
try
|
||||
{
|
||||
exerciseId = JsonObject::fromJson(mse.properties()).value<JsonArray>(QStringLiteral("available_in_exercise")).at<int>(0); // get exercise id from properties json
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
exerciseId = 0;
|
||||
}
|
||||
if (!m_exercises.contains(exerciseId)) // if building is part of a deleted / terminated exercise, just add it to the unassigned buildings model
|
||||
exerciseId = 0;
|
||||
|
||||
if (modType == DataModification::eModified)
|
||||
m_model->updateMse(mse.id(), mse.groupId(), displayName, exerciseId);
|
||||
else if (modType == DataModification::eAdded)
|
||||
m_model->addMse(mse.id(), mse.groupId(), displayName, exerciseId);
|
||||
else
|
||||
m_model->removeMse(mse.id());
|
||||
}
|
||||
|
||||
bool ExerciseAssignmentDialog::apply()
|
||||
{
|
||||
// XXX: HACK we don't know if user pressed ok or apply - apply() has to emidiately return, but the operation is async... so mimic ok/apply later, based on what was clicked
|
||||
bool wasOkay = (sender() == static_cast<QObject *>(m_buttonBox->getButton(LtsWidgets::DialogButton::Ok)));
|
||||
|
||||
LtsOverlayLoading *lol = new LtsOverlayLoading;
|
||||
setOverlay(lol);
|
||||
|
||||
MSEModifyRequestCollector *collector = new MSEModifyRequestCollector(m_ftc, this);
|
||||
|
||||
{
|
||||
QPushButton *pbCancel = new QPushButton;
|
||||
pbCancel->setText(tr("Cancel"));
|
||||
connect(pbCancel, &QPushButton::clicked,
|
||||
this, [pbCancel, collector, lol]()
|
||||
{
|
||||
collector->cancel();
|
||||
lol->setText(tr("Canceling ..."));
|
||||
pbCancel->setEnabled(false);
|
||||
});
|
||||
|
||||
qobject_cast<QVBoxLayout *>(lol->layout())->addWidget(pbCancel, 0, Qt::AlignmentFlag::AlignCenter);
|
||||
}
|
||||
|
||||
const QVector<RequestInfos> &requestInfos = m_model->getRequestInfos();
|
||||
for (const RequestInfos &ri : qAsConst(requestInfos))
|
||||
{
|
||||
MainStructureElementModifyRequest request;
|
||||
MainStructureElement &mse = request;
|
||||
mse = m_dtc->mainStructureElement(ri.mseId);
|
||||
|
||||
QJsonObject root;
|
||||
try
|
||||
{
|
||||
root = JsonObject::fromJson(mse.properties()).object();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "can't parse json for mseId " << ri.mseId << " and excId " << ri.exerciseId << " - using new json";
|
||||
Q_ASSERT(false);
|
||||
}
|
||||
|
||||
if (LtsUtils::ProjectSettings::getInstance()->value(QStringLiteral("ism"), QStringLiteral("enableSetRecordingDialog")).toBool())
|
||||
setRecording(mse,ri.exerciseId != 0);
|
||||
|
||||
if (ri.exerciseId != 0)
|
||||
root[QStringLiteral("available_in_exercise")] = QJsonArray({{ri.exerciseId}});
|
||||
else
|
||||
root.remove(QStringLiteral("available_in_exercise"));
|
||||
|
||||
mse.properties(QString::fromUtf8(QJsonDocument(root).toJson()).toStdString());
|
||||
|
||||
collector->addRequest(ri, request);
|
||||
}
|
||||
|
||||
int initialCount = collector->count();
|
||||
const QString leText(QStringLiteral("%1<br />%3 / %2").arg(tr("Assigning building(s) to exercise(s)")).arg(initialCount));
|
||||
lol->setText(leText.arg(0));
|
||||
|
||||
|
||||
connect(collector, &MSEModifyRequestCollector::requestComplete,
|
||||
this, [collector, lol, leText, initialCount]()
|
||||
{
|
||||
lol->setText(leText.arg(initialCount - collector->count()));
|
||||
});
|
||||
|
||||
connect(collector, &MSEModifyRequestCollector::finished,
|
||||
this, [this, collector, wasOkay, lol](bool canceled)
|
||||
{
|
||||
unsetOverlay();
|
||||
lol->deleteLater();
|
||||
collector->deleteLater();
|
||||
|
||||
int failedCount = collector->failedCount();
|
||||
if (failedCount > 0)
|
||||
{
|
||||
new LtsWidgets::LtsMessageDialogNew(this, tr("Error: %1 building(s) could not be assigned!").arg(failedCount));
|
||||
return;
|
||||
}
|
||||
|
||||
if (canceled)
|
||||
return;
|
||||
|
||||
__unchange__(); // 'apply' behaviour
|
||||
|
||||
if (!wasOkay) // 'ok' behaviour
|
||||
return;
|
||||
|
||||
closeRequest(); // we 'unchanged', so it will close directly
|
||||
});
|
||||
|
||||
collector->go();
|
||||
|
||||
return false; // our request is async, say false, show a blocking dialog and do ok-/apply-button stuff later
|
||||
}
|
||||
/*!
|
||||
* \brief ExerciseAssignmentDialog::setRecoding
|
||||
* The property of an element with type indoorcamera or outdoorcamera can be updated
|
||||
* \param mse
|
||||
* \param state
|
||||
*/
|
||||
void ExerciseAssignmentDialog::setRecording(MainStructureElement &mse, bool state)
|
||||
{
|
||||
for(auto &el : mse.elements())
|
||||
{
|
||||
if(el.mountingPointTypeId() != MountingPointType::IndoorCamera &&
|
||||
el.mountingPointTypeId() != MountingPointType::OutdoorCamera)
|
||||
continue;
|
||||
|
||||
QJsonDocument propsDoc = QJsonDocument::fromJson(QByteArray::fromStdString(el.properties()));
|
||||
QJsonObject propsObj;
|
||||
if (propsDoc.isObject()) // if the given properties are no valid JSON object, the properties will be made from scratch
|
||||
propsObj = propsDoc.object();
|
||||
propsObj.insert(QLatin1String("record"), state);
|
||||
el.properties(QJsonDocument(propsObj).toJson(QJsonDocument::Compact).toStdString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ExerciseAssignmentDialog::onPrint()
|
||||
{
|
||||
QTreeView tv;
|
||||
tv.setModel(m_model);
|
||||
tv.expandAll();
|
||||
|
||||
LtsPrinting::printView(m_session, this, &tv);
|
||||
}
|
||||
|
||||
} // namespace InfrastructureManagement
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* The AssetListDialog shows how many assets are needed for a specific schedule, needed elsewhere,
|
||||
* totally possessed, free, and missing
|
||||
* $Id: ism_exercise_assignment_dialog.h 45935 2019-03-08 08:36:11Z ehrlicher $
|
||||
* $HeadURL: svn://192.168.133.21/TDS/branches/product/features/22_09_resmgmt2.0/Lts/Plugins/InfrastructureManagement/Gui/AudioVideoConfig/ExerciseAssignment/ism_exercise_assignment_dialog.h $
|
||||
* $Author: ehrlicher $
|
||||
* Created by Hannes Baeuerle, SLSE, 2017-06-29
|
||||
* Refreshed by Mike Wille, SLTE, 2022-09-26
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ExerciseManagement/exm_dtc.h>
|
||||
#include <InfrastructureManagement/ism_dtc.h>
|
||||
#include <InfrastructureManagement/ism_ftc.h>
|
||||
#include <InfrastructureManagement/logger.h>
|
||||
#include <LtsWidgets/lts_dialog.h>
|
||||
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class ExerciseAssignmentDialog;
|
||||
}
|
||||
namespace LtsSession
|
||||
{
|
||||
class LtsSession;
|
||||
}
|
||||
|
||||
|
||||
namespace InfrastructureManagement
|
||||
{
|
||||
class ExerciseAssignmentDialogModel;
|
||||
class ExerciseAssignmentDialogModelFilterProxy;
|
||||
|
||||
|
||||
class ExerciseAssignmentDialog
|
||||
: public LtsWidgets::LtsDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ExerciseAssignmentDialog(LtsSession::LtsSession *session, QWidget *parent = nullptr) noexcept(false);
|
||||
~ExerciseAssignmentDialog();
|
||||
|
||||
private slots:
|
||||
void onUnassignedNeedsUpdate(const QSet<QModelIndex> &setToExpand);
|
||||
void onAssignedNeedsUpdate(const QSet<QModelIndex> &setToExpand);
|
||||
|
||||
void onPrint();
|
||||
|
||||
private:
|
||||
void onMainStructureElementChanged(const InfrastructureManagement::MainStructureElement &mse, DataModification modType);
|
||||
void retranslate() override;
|
||||
bool apply() override;
|
||||
void setRecording(MainStructureElement &mse, bool state);
|
||||
private:
|
||||
LtsSession::LtsSession *m_session;
|
||||
Ui::ExerciseAssignmentDialog *m_ui;
|
||||
std::shared_ptr<Interface::Dtc> m_dtc;
|
||||
std::shared_ptr<Interface::Ftc> m_ftc;
|
||||
|
||||
ExerciseAssignmentDialogModel *m_model;
|
||||
ExerciseAssignmentDialogModelFilterProxy *m_modelAssignedFilter;
|
||||
ExerciseAssignmentDialogModelFilterProxy *m_modelUnassignedFilter;
|
||||
|
||||
QMap<qint32, ExerciseManagement::Exercise> m_exercises;
|
||||
LOGGER_T m_logger;
|
||||
};
|
||||
} // namespace InfrastructureManagement
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ExerciseAssignmentDialog</class>
|
||||
<widget class="QWidget" name="ExerciseAssignmentDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>953</width>
|
||||
<height>681</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p><span style=" color:#aa0000;">WARNING: There are no exercises available. You can't assign buildings.</span></p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<layout class="QGridLayout" name="gridLayout"/>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="lbExercises">
|
||||
<property name="text">
|
||||
<string>Assign to exercise:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="cbExercises">
|
||||
<property name="currentText">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="const" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QTreeView" name="availableExercises">
|
||||
<property name="acceptDrops">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="dragEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="dragDropMode">
|
||||
<enum>QAbstractItemView::DragDrop</enum>
|
||||
</property>
|
||||
<property name="defaultDropAction">
|
||||
<enum>Qt::CopyAction</enum>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QTreeView" name="assignedExercises">
|
||||
<property name="acceptDrops">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="dragEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="dragDropMode">
|
||||
<enum>QAbstractItemView::DragDrop</enum>
|
||||
</property>
|
||||
<property name="defaultDropAction">
|
||||
<enum>Qt::CopyAction</enum>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
+353
@@ -0,0 +1,353 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* $Id: $
|
||||
* $HeadURL: $
|
||||
* $Author: $
|
||||
*
|
||||
* Created by Mike Wille, SLTE, 2022-09-27
|
||||
*/
|
||||
|
||||
#include "ism_exercise_assignment_dialog_model.h"
|
||||
|
||||
#include <QFont>
|
||||
#include <QGuiApplication>
|
||||
#include <InfrastructureManagement/ism_translation.h>
|
||||
#ifdef LTS_DEBUG
|
||||
#include <QTimer> // ftc delay
|
||||
#endif
|
||||
|
||||
|
||||
namespace InfrastructureManagement
|
||||
{
|
||||
ExerciseAssignmentDialogModel::ExerciseAssignmentDialogModel(const QMap<qint32, ExerciseManagement::Exercise> &exercises, QObject *parent) noexcept(false)
|
||||
: QAbstractItemModel(parent)
|
||||
, m_rootItem(new TreeItem(0, 0, tr("InvisibleRootItem"), -1))
|
||||
, m_exercises(exercises)
|
||||
, m_logger(getLogger("ExerciseAssignmentDialogModel"))
|
||||
{
|
||||
for (int it = BuildingGroup_def::UnknownGroup;
|
||||
it <= BuildingGroup_def::Salchau; // WARNING: Change this, when enum changes!
|
||||
++it)
|
||||
{
|
||||
m_rootItem->appendChild(new TreeItem(0, it, toString(static_cast<BuildingGroup_def::type>(it)), -1, m_rootItem));
|
||||
}
|
||||
}
|
||||
|
||||
ExerciseAssignmentDialogModel::~ExerciseAssignmentDialogModel()
|
||||
{
|
||||
delete m_rootItem;
|
||||
}
|
||||
|
||||
void ExerciseAssignmentDialogModel::addMse(int mseId, int sectionId, const QString &displayName, int exerciseId)
|
||||
{
|
||||
const QList<TreeItem*> &childItems = m_rootItem->childItems();
|
||||
for (auto sectionItem : qAsConst(childItems))
|
||||
{
|
||||
if (sectionItem->sectionId() == sectionId)
|
||||
{
|
||||
beginInsertRows(index(sectionItem), sectionItem->childCount(), sectionItem->childCount());
|
||||
sectionItem->appendChild(new TreeItem(mseId, sectionId, displayName, exerciseId, sectionItem));
|
||||
endInsertRows();
|
||||
return;
|
||||
}
|
||||
}
|
||||
ERROR_LOG(m_logger) << "Did not find section with enum value " << sectionId;
|
||||
return;
|
||||
}
|
||||
|
||||
void ExerciseAssignmentDialogModel::updateMse(int mseId, int sectionId, const QString &displayName, int exerciseId)
|
||||
{
|
||||
// Todo: Change of display name or moving to another section not yet implemented
|
||||
Q_UNUSED(sectionId);
|
||||
Q_UNUSED(displayName);
|
||||
|
||||
QModelIndex mi = findItemByMseId(mseId);
|
||||
TreeItem* item = treeItem(mi);
|
||||
if (!item)
|
||||
return;
|
||||
|
||||
if (exerciseId != item->originalExerciseId())
|
||||
{
|
||||
item->setOriginalExerciseId(exerciseId);
|
||||
emit dataChanged(mi, mi);
|
||||
}
|
||||
}
|
||||
|
||||
void ExerciseAssignmentDialogModel::removeMse(int mseId)
|
||||
{
|
||||
QModelIndex mi = findItemByMseId(mseId);
|
||||
TreeItem* item = treeItem(mi);
|
||||
if (!item)
|
||||
return;
|
||||
|
||||
TreeItem* parent = item->parentItem();
|
||||
if (!parent)
|
||||
return;
|
||||
|
||||
beginRemoveRows(index(parent),item->childNumber(),item->childNumber());
|
||||
parent->removeChild(item->childNumber());
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
Qt::DropActions ExerciseAssignmentDialogModel::supportedDropActions() const
|
||||
{
|
||||
return Qt::MoveAction;
|
||||
}
|
||||
|
||||
QVariant ExerciseAssignmentDialogModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid() ||
|
||||
(role != Qt::DisplayRole
|
||||
&& role != Qt::FontRole)
|
||||
)
|
||||
return {};
|
||||
|
||||
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
|
||||
if (!item)
|
||||
return {};
|
||||
|
||||
if (role == Qt::FontRole)
|
||||
{
|
||||
if (item->originalExerciseId() == item->exerciseId())
|
||||
return {};
|
||||
QFont f;
|
||||
f.setBold(true);
|
||||
return f;
|
||||
}
|
||||
|
||||
if (role == Qt::DisplayRole)
|
||||
{
|
||||
if (index.column() == 0)
|
||||
return item->displayName();
|
||||
if (index.column() == 1)
|
||||
{
|
||||
const int exerciseId = item->exerciseId();
|
||||
if (exerciseId < 0)
|
||||
return {};
|
||||
if (exerciseId == 0)
|
||||
return QStringLiteral("-");
|
||||
return QString::fromStdString(m_exercises.value(exerciseId).name());
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
QVariant ExerciseAssignmentDialogModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (orientation != Qt::Orientation::Horizontal || role != Qt::DisplayRole)
|
||||
return QAbstractItemModel::headerData(section, orientation, role);
|
||||
if (section == 0)
|
||||
return tr("Building");
|
||||
if (section == 1)
|
||||
return tr("Assigned Exercises");
|
||||
return {};
|
||||
}
|
||||
|
||||
QModelIndex ExerciseAssignmentDialogModel::index(int row, int column, const QModelIndex &parent) const
|
||||
{
|
||||
if (!hasIndex(row, column, parent))
|
||||
return {};
|
||||
|
||||
TreeItem *parentItem;
|
||||
|
||||
if (!parent.isValid())
|
||||
parentItem = m_rootItem;
|
||||
else
|
||||
parentItem = static_cast<TreeItem*>(parent.internalPointer());
|
||||
|
||||
TreeItem *childItem = parentItem->child(row);
|
||||
if (childItem)
|
||||
return createIndex(row, column, childItem);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
QModelIndex ExerciseAssignmentDialogModel::parent(const QModelIndex &mi) const
|
||||
{
|
||||
if (!mi.isValid())
|
||||
return {};
|
||||
|
||||
TreeItem *childItem = static_cast<TreeItem*>(mi.internalPointer());
|
||||
TreeItem *parentItem = childItem->parentItem();
|
||||
|
||||
return index(parentItem);
|
||||
}
|
||||
|
||||
QModelIndex ExerciseAssignmentDialogModel::index(TreeItem *item) const
|
||||
{
|
||||
if (item == m_rootItem || !item)
|
||||
return {};
|
||||
return createIndex(item->childNumber(),0,item);
|
||||
}
|
||||
|
||||
|
||||
int ExerciseAssignmentDialogModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
TreeItem *parentItem;
|
||||
|
||||
if (!parent.isValid())
|
||||
parentItem = m_rootItem;
|
||||
else
|
||||
parentItem = treeItem(parent);
|
||||
|
||||
return parentItem->childCount();
|
||||
}
|
||||
|
||||
QSet<int> ExerciseAssignmentDialogModel::childMses(const QModelIndex &mi, int exerciseId) const
|
||||
{
|
||||
QSet<int> mses;
|
||||
const QList<TreeItem*> &childItems = treeItem(mi)->childItems();
|
||||
for(auto myChild : qAsConst(childItems))
|
||||
{
|
||||
if (myChild->exerciseId() == exerciseId)
|
||||
mses << myChild->mseId();
|
||||
}
|
||||
return mses;
|
||||
}
|
||||
|
||||
|
||||
TreeItem *ExerciseAssignmentDialogModel::treeItem(const QModelIndex &index) const
|
||||
{
|
||||
return static_cast<TreeItem*>(index.internalPointer());
|
||||
}
|
||||
|
||||
QModelIndex ExerciseAssignmentDialogModel::findItemByMseId(int mseId) const
|
||||
{
|
||||
// This only works as long as first level is section and second level is Building!
|
||||
// Otherwise we need to go into recursion!
|
||||
const QList<TreeItem*> &childItems = m_rootItem->childItems();
|
||||
for (auto sectionItem : qAsConst(childItems))
|
||||
{
|
||||
const QList<TreeItem*> §ionChildItems= sectionItem->childItems();
|
||||
for (auto mseItem : qAsConst(sectionChildItems))
|
||||
{
|
||||
if (mseItem->mseId() == mseId)
|
||||
return index(mseItem);
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void ExerciseAssignmentDialogModel::setExerciseId(const QModelIndex &mi, int exerciseId)
|
||||
{
|
||||
TreeItem *ti = treeItem(mi);
|
||||
if (!ti)
|
||||
return;
|
||||
ti->setExerciseId(exerciseId);
|
||||
emit dataChanged(mi, mi, {Qt::DisplayRole, Qt::FontRole});
|
||||
}
|
||||
|
||||
|
||||
QVector<RequestInfos> ExerciseAssignmentDialogModel::getRequestInfos(bool all) const
|
||||
{
|
||||
QVector<RequestInfos> requestInfos;
|
||||
m_rootItem->getAllUnderlyingRequestInfos(requestInfos, all);
|
||||
return requestInfos;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
TreeItem::TreeItem(int mseId, int sectionId, const QString &displayName, int exerciseId, TreeItem *parentItem)
|
||||
: m_mseId(mseId)
|
||||
, m_sectionId(sectionId)
|
||||
, m_displayName(displayName)
|
||||
, m_exerciseId(exerciseId)
|
||||
, m_originalExerciseId(exerciseId)
|
||||
, m_parentItem(parentItem)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
TreeItem::~TreeItem()
|
||||
{
|
||||
qDeleteAll(m_childItems);
|
||||
}
|
||||
|
||||
void TreeItem::appendChild(TreeItem *child)
|
||||
{
|
||||
m_childItems.append(child);
|
||||
}
|
||||
|
||||
TreeItem *TreeItem::child(int row)
|
||||
{
|
||||
if (row < 0 || row >= m_childItems.size())
|
||||
return nullptr;
|
||||
return m_childItems.at(row);
|
||||
}
|
||||
|
||||
int TreeItem::childNumber() const
|
||||
{
|
||||
if (m_parentItem)
|
||||
return m_parentItem->childItems().indexOf(const_cast<TreeItem*>(this));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int TreeItem::childCount() const
|
||||
{
|
||||
return m_childItems.count();
|
||||
}
|
||||
|
||||
void TreeItem::removeChild(int id)
|
||||
{
|
||||
delete(m_childItems.value(id));
|
||||
m_childItems.removeAt(id);
|
||||
}
|
||||
|
||||
void TreeItem::getAllUnderlyingRequestInfos(QVector<RequestInfos> &requestInfos, bool all) const
|
||||
{
|
||||
const QList<TreeItem*> &childItemsRef = childItems();
|
||||
for (auto myChild : qAsConst(childItemsRef))
|
||||
{
|
||||
if (all || (myChild->exerciseId() != myChild->originalExerciseId()))
|
||||
requestInfos.append({myChild->mseId(), myChild->exerciseId()});
|
||||
myChild->getAllUnderlyingRequestInfos(requestInfos, all);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace InfrastructureManagement
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* $Id: $
|
||||
* $HeadURL: $
|
||||
* $Author: $
|
||||
*
|
||||
* Created by Mike Wille, SLTE, 2022-09-27
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <InfrastructureManagement/logger.h>
|
||||
#include <ExerciseManagement/exm.hpp>
|
||||
#include <QAbstractItemModel>
|
||||
#include <QSet>
|
||||
|
||||
namespace InfrastructureManagement
|
||||
{
|
||||
|
||||
/// RequestInfos
|
||||
struct RequestInfos
|
||||
{
|
||||
int mseId;
|
||||
int exerciseId;
|
||||
};
|
||||
|
||||
// class ExerciseAssignmentDialogModel;
|
||||
class TreeItem
|
||||
{
|
||||
public:
|
||||
explicit TreeItem(int mseId, int sectionId, const QString &displayName, int exerciseId, TreeItem *parentItem = nullptr);
|
||||
~TreeItem();
|
||||
|
||||
void appendChild(TreeItem *child);
|
||||
void removeChild(int id);
|
||||
|
||||
TreeItem* child(int row);
|
||||
int childNumber() const;
|
||||
int childCount() const;
|
||||
const QList<TreeItem*> childItems() const { return m_childItems; }
|
||||
|
||||
int sectionId() const { return m_sectionId; }
|
||||
int mseId() const { return m_mseId; }
|
||||
QString displayName() const { return m_displayName; }
|
||||
|
||||
void setExerciseId(int exerciseId) { m_exerciseId = exerciseId; }
|
||||
int exerciseId() const { return m_exerciseId; }
|
||||
|
||||
void setOriginalExerciseId(int exerciseId) { m_originalExerciseId = exerciseId; }
|
||||
int originalExerciseId() const { return m_originalExerciseId; }
|
||||
|
||||
TreeItem* parentItem() { return m_parentItem; }
|
||||
|
||||
void getAllUnderlyingRequestInfos(QVector<RequestInfos> &requestInfos, bool all = false) const;
|
||||
|
||||
private:
|
||||
int m_mseId;
|
||||
int m_sectionId;
|
||||
QString m_displayName;
|
||||
int m_exerciseId;
|
||||
int m_originalExerciseId;
|
||||
QList<TreeItem*> m_childItems;
|
||||
TreeItem* m_parentItem;
|
||||
};
|
||||
|
||||
/// ExerciseAssignmentDialogModel
|
||||
class ExerciseAssignmentDialogModel : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ExerciseAssignmentDialogModel(const QMap<qint32, ExerciseManagement::Exercise> &exercises, QObject *parent = nullptr) noexcept(false);
|
||||
~ExerciseAssignmentDialogModel();
|
||||
|
||||
void addMse(int mseId, int sectionId, const QString &displayName, int exerciseId);
|
||||
void updateMse(int mseId, int sectionId, const QString &displayName, int exerciseId);
|
||||
void removeMse(int mseId);
|
||||
|
||||
QModelIndex findItemByMseId(int mseId) const;
|
||||
|
||||
void setExerciseId(const QModelIndex &mi, int exerciseId);
|
||||
int exerciseId(const QModelIndex &mi) const { return treeItem(mi) ? treeItem(mi)->exerciseId() : -1; }
|
||||
|
||||
int mseId(const QModelIndex &mi) const { return treeItem(mi) ? treeItem(mi)->mseId() : 0; }
|
||||
|
||||
QVector<RequestInfos> getRequestInfos(bool all = false) const;
|
||||
QSet<int> childMses(const QModelIndex &mi, int exerciseId) const;
|
||||
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
|
||||
|
||||
protected:
|
||||
int rowCount(const QModelIndex &parent = {}) const override;
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
QModelIndex index(int row, int column, const QModelIndex &parent) const override;
|
||||
QModelIndex parent(const QModelIndex &index) const override;
|
||||
int columnCount(const QModelIndex &) const override { return 2; }
|
||||
Qt::DropActions supportedDropActions() const override;
|
||||
|
||||
private:
|
||||
|
||||
TreeItem* treeItem(const QModelIndex &index) const;
|
||||
QModelIndex index(TreeItem *item) const;
|
||||
|
||||
TreeItem* m_rootItem;
|
||||
QMap<qint32, ExerciseManagement::Exercise> m_exercises;
|
||||
LOGGER_T m_logger;
|
||||
};
|
||||
|
||||
} // namespace InfrastructureManagement
|
||||
+183
@@ -0,0 +1,183 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* $Id: $
|
||||
* $HeadURL: $
|
||||
* $Author: $
|
||||
*
|
||||
* Created by Mike Wille, SLTE, 2022-09-27
|
||||
*/
|
||||
|
||||
#include "ism_exercise_assignment_dialog_proxy_model.h"
|
||||
#include "ism_exercise_assignment_dialog_model.h"
|
||||
|
||||
#include <QMimeData>
|
||||
|
||||
|
||||
namespace InfrastructureManagement
|
||||
{
|
||||
void ExerciseAssignmentDialogModelFilterProxy::setSourceModel(QAbstractItemModel *sourceModel)
|
||||
{
|
||||
m_sourceModel = qobject_cast<ExerciseAssignmentDialogModel *>(sourceModel);
|
||||
Q_ASSERT(m_sourceModel != nullptr);
|
||||
QSortFilterProxyModel::setSourceModel(sourceModel);
|
||||
}
|
||||
|
||||
void ExerciseAssignmentDialogModelFilterProxy::setExerciseId(int exerciseId)
|
||||
{
|
||||
m_exerciseId = exerciseId;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
|
||||
bool ExerciseAssignmentDialogModelFilterProxy::filterAcceptsRow(const int sourceRow, const QModelIndex &sourceParent) const
|
||||
{
|
||||
const QModelIndex sourceIndex = sourceModel()->index(sourceRow, 0, sourceParent);
|
||||
|
||||
if (!sourceIndex.isValid())
|
||||
return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent);
|
||||
|
||||
// Parents are true automatically...
|
||||
if (m_sourceModel->mseId(sourceIndex) == 0)
|
||||
return false;
|
||||
|
||||
return (m_sourceModel->exerciseId(sourceIndex) == m_exerciseId);
|
||||
}
|
||||
|
||||
|
||||
bool ExerciseAssignmentDialogModelFilterProxy::lessThan(const QModelIndex &left, const QModelIndex &right) const
|
||||
{
|
||||
return QString::localeAwareCompare(sourceModel()->data(left).toString(), sourceModel()->data(right).toString()) < 0;
|
||||
}
|
||||
|
||||
QVariant ExerciseAssignmentDialogModelFilterProxy::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (section == 0 && orientation == Qt::Orientation::Horizontal && role == Qt::DisplayRole)
|
||||
return m_exerciseId > 0 ? tr("Assigned Buildings") : tr("Unassigned Buildings");
|
||||
return m_sourceModel->headerData(section, orientation, role);
|
||||
}
|
||||
|
||||
QMimeData *ExerciseAssignmentDialogModelFilterProxy::mimeData(const QModelIndexList &indexes) const
|
||||
{
|
||||
QJsonObject root;
|
||||
QJsonArray mseIds;
|
||||
|
||||
for(const QModelIndex mi : indexes)
|
||||
{
|
||||
QModelIndex miSource = mapToSource(mi);
|
||||
int mseId = m_sourceModel->mseId(miSource);
|
||||
if (mseId <= 0)
|
||||
{
|
||||
const QSet<int> childMses = m_sourceModel->childMses(miSource, m_exerciseId);
|
||||
for (int mse : qAsConst(childMses))
|
||||
mseIds << mse;
|
||||
}
|
||||
else
|
||||
mseIds << mseId;
|
||||
}
|
||||
|
||||
root[QStringLiteral("eams")] = mseIds;
|
||||
root[QStringLiteral("oldExerciseId")] = m_exerciseId;
|
||||
|
||||
QMimeData *mimeData = new QMimeData;
|
||||
mimeData->setData(QStringLiteral("rheinmetall/exercise-assignment"), QJsonDocument(root).toJson());
|
||||
return mimeData;
|
||||
}
|
||||
|
||||
Qt::ItemFlags ExerciseAssignmentDialogModelFilterProxy::flags(const QModelIndex &index) const
|
||||
{
|
||||
Qt::ItemFlags f = Qt::ItemIsDropEnabled | QAbstractItemModel::flags(index);
|
||||
|
||||
if (index.isValid())
|
||||
f |= Qt::ItemIsDragEnabled;
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
bool ExerciseAssignmentDialogModelFilterProxy::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
|
||||
{
|
||||
if (!canDropMimeData(data, action, row, column, parent))
|
||||
return false;
|
||||
|
||||
const JsonObject root(JsonObject::fromJson(data->data(QStringLiteral("rheinmetall/exercise-assignment"))));
|
||||
const JsonArray eams(root.value<JsonArray>(QStringLiteral("eams")));
|
||||
QSet<QModelIndex> setToExpand;
|
||||
|
||||
const QVector<int> &eamsVec = eams.toVector<int>();
|
||||
for (int mseId : qAsConst(eamsVec))
|
||||
{
|
||||
QModelIndex sourceMi = m_sourceModel->findItemByMseId(mseId);
|
||||
setToExpand.insert(sourceMi.parent());
|
||||
if (sourceMi.isValid())
|
||||
m_sourceModel->setExerciseId(sourceMi, m_exerciseId);
|
||||
}
|
||||
// Don't know why we have to do this, as always "dataChanged()" is emitted...
|
||||
invalidateFilter();
|
||||
emit doRefilter(setToExpand);
|
||||
return true;
|
||||
}
|
||||
|
||||
Qt::DropActions ExerciseAssignmentDialogModelFilterProxy::supportedDropActions() const
|
||||
{
|
||||
return Qt::MoveAction;
|
||||
}
|
||||
|
||||
bool ExerciseAssignmentDialogModelFilterProxy::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(row)
|
||||
Q_UNUSED(column)
|
||||
Q_UNUSED(parent)
|
||||
|
||||
if (action != supportedDropActions())
|
||||
return false;
|
||||
|
||||
const JsonObject root(JsonObject::fromJson(data->data(QStringLiteral("rheinmetall/exercise-assignment"))));
|
||||
int oldExerciseId = root.value<int>(QStringLiteral("oldExerciseId"));
|
||||
return oldExerciseId != m_exerciseId;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace InfrastructureManagement
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* $Id: $
|
||||
* $HeadURL: $
|
||||
* $Author: $
|
||||
*
|
||||
* Created by Mike Wille, SLTE, 2022-09-27
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <InfrastructureManagement/logger.h>
|
||||
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <LtsUtilsCore/json_object.h>
|
||||
|
||||
using namespace LtsUtils;
|
||||
|
||||
namespace InfrastructureManagement
|
||||
{
|
||||
class ExerciseAssignmentDialogModel;
|
||||
|
||||
|
||||
/// ExerciseAssignmentDialogModelFilterProxy
|
||||
class ExerciseAssignmentDialogModelFilterProxy : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ExerciseAssignmentDialogModelFilterProxy(QObject *parent)
|
||||
: QSortFilterProxyModel(parent)
|
||||
, m_exerciseId(0)
|
||||
, m_logger(getLogger("ExerciseAssignmentDialogModelFilterProxy"))
|
||||
{
|
||||
setRecursiveFilteringEnabled(true);
|
||||
}
|
||||
|
||||
void setSourceModel(QAbstractItemModel *sourceModel) override;
|
||||
void setExerciseId(int exerciseId);
|
||||
|
||||
signals:
|
||||
void doRefilter(const QSet<QModelIndex> &setToExpand);
|
||||
|
||||
protected:
|
||||
bool filterAcceptsRow(const int sourceRow, const QModelIndex &sourceParent) const override;
|
||||
bool lessThan(const QModelIndex &left, const QModelIndex &rioght) const override;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
int columnCount(const QModelIndex &) const override { return 1; }
|
||||
|
||||
QMimeData* mimeData(const QModelIndexList &_indexes) const override;
|
||||
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
|
||||
Qt::DropActions supportedDropActions() const override;
|
||||
bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const override;
|
||||
QStringList mimeTypes() const override
|
||||
{
|
||||
return { QStringLiteral("rheinmetall/exercise-assignment") };
|
||||
}
|
||||
|
||||
|
||||
|
||||
class ExerciseAssignmentMime
|
||||
{
|
||||
public:
|
||||
ExerciseAssignmentMime(const JsonObject &root) noexcept(false) // drop
|
||||
: m_mseId(root.value<int>(QStringLiteral("mseId")))
|
||||
{}
|
||||
|
||||
ExerciseAssignmentMime(int mseId) noexcept(false) // drag
|
||||
: m_mseId(mseId)
|
||||
{}
|
||||
|
||||
QJsonObject toJson() const
|
||||
{
|
||||
return { { QStringLiteral("mseId"), m_mseId } };
|
||||
}
|
||||
int mseId() const { return m_mseId; }
|
||||
|
||||
private:
|
||||
int m_mseId;
|
||||
};
|
||||
|
||||
private:
|
||||
int m_exerciseId;
|
||||
ExerciseAssignmentDialogModel *m_sourceModel;
|
||||
LOGGER_T m_logger;
|
||||
};
|
||||
} // namespace InfrastructureManagement
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* $Id: $
|
||||
* $HeadURL: $
|
||||
* $Author: $
|
||||
*
|
||||
* Created by Mike Wille, SLTE, 2022-09-27
|
||||
*/
|
||||
|
||||
#include "ism_exercise_assignment_dialog_requesters.h"
|
||||
#include "ism_exercise_assignment_dialog_model.h"
|
||||
|
||||
#include <QFont>
|
||||
#include <QGuiApplication>
|
||||
#include <QMimeData>
|
||||
#ifdef LTS_DEBUG
|
||||
#include <QTimer> // ftc delay
|
||||
#endif
|
||||
|
||||
|
||||
namespace InfrastructureManagement
|
||||
{
|
||||
/// MSEModifyRequestCollector
|
||||
void MSEModifyRequestCollector::next()
|
||||
{
|
||||
if (m_requests.isEmpty())
|
||||
{
|
||||
emit finished(m_canceled);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
MSEModifyRequester *requester = new MSEModifyRequester;
|
||||
|
||||
const QPair<RequestInfos, MainStructureElementModifyRequest> request(m_requests.takeFirst());
|
||||
|
||||
connect(requester, &MSEModifyRequester::finished,
|
||||
this, [this](const QString &msg)
|
||||
{
|
||||
bool failed = (!msg.isEmpty());
|
||||
|
||||
if (failed)
|
||||
{
|
||||
m_failedCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ri.model->unchange(ri.rowId);
|
||||
}
|
||||
|
||||
emit requestComplete(failed);
|
||||
|
||||
if (m_canceled)
|
||||
m_requests.clear();
|
||||
|
||||
next();
|
||||
});
|
||||
|
||||
|
||||
auto go = [this, request, requester]()
|
||||
{
|
||||
m_ftc->mainStructureElementModifyRequest(request.second, requester);
|
||||
};
|
||||
|
||||
#ifdef LTS_DEBUG
|
||||
if (QGuiApplication::keyboardModifiers().testFlag(Qt::KeyboardModifier::ControlModifier))
|
||||
{
|
||||
QTimer::singleShot(3000, this, go);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
go();
|
||||
}
|
||||
|
||||
} // namespace InfrastructureManagement
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* $Id: $
|
||||
* $HeadURL: $
|
||||
* $Author: $
|
||||
*
|
||||
* Created by Mike Wille, SLTE, 2022-09-27
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ism_exercise_assignment_dialog_model.h"
|
||||
|
||||
#include <InfrastructureManagement/ism_ftc.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QVector>
|
||||
#include <QPair>
|
||||
|
||||
|
||||
namespace InfrastructureManagement
|
||||
{
|
||||
/// MSEModifyRequester
|
||||
class MSEModifyRequester : public QObject,
|
||||
public Interface::Ftc::MainStructureElementModifyReplyHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MSEModifyRequester()
|
||||
: QObject() // do NOT parent!
|
||||
{}
|
||||
|
||||
void onMainStructureElementModifyReply(const Core::FunctionReplyObject &reply) override
|
||||
{
|
||||
if (reply.error())
|
||||
emit finished(reply.translated());
|
||||
else
|
||||
emit finished({});
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
signals:
|
||||
void finished(const QString &msg);
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// MSEModifyRequestCollector
|
||||
class MSEModifyRequestCollector : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MSEModifyRequestCollector(std::shared_ptr<Interface::Ftc> &ftc, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_ftc(ftc)
|
||||
{}
|
||||
|
||||
void addRequest(const RequestInfos &requestInfos, const MainStructureElementModifyRequest &request)
|
||||
{
|
||||
m_requests += QPair<RequestInfos, MainStructureElementModifyRequest>(requestInfos, request);
|
||||
}
|
||||
|
||||
void cancel()
|
||||
{
|
||||
m_canceled = true;
|
||||
}
|
||||
|
||||
void go()
|
||||
{
|
||||
next();
|
||||
}
|
||||
|
||||
int count() const
|
||||
{
|
||||
return m_requests.count();
|
||||
}
|
||||
|
||||
int failedCount() const
|
||||
{
|
||||
return m_failedCount;
|
||||
}
|
||||
|
||||
private slots:
|
||||
void next();
|
||||
|
||||
signals:
|
||||
void finished(bool canceled);
|
||||
void requestComplete(bool failed);
|
||||
|
||||
private:
|
||||
QVector<QPair<RequestInfos, MainStructureElementModifyRequest> > m_requests;
|
||||
std::shared_ptr<Interface::Ftc> m_ftc;
|
||||
bool m_canceled = false;
|
||||
int m_failedCount = 0;
|
||||
};
|
||||
} // namespace InfrastructureManagement
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
Reference in new issue
Block a user