Files
qt5-legatus-legacy/Lts/Plugins/ParticipantManagement/Gui/ParticipantEdit/participant_organisation.cpp
T
2026-08-13 18:33:10 +02:00

466 lines
17 KiB
C++
Executable File

/**
* @RDE_HEADER@
* GUI Plugin for ParticipantManagement - Participant Organisation
* $Id$
* $HeadURL$
* $Author$
* Created by Patric Karwat, SLSE, 2016-10-17
*/
#include "participant_organisation.h"
#include "ui_participant_organisation.h"
#include "participant_unit_namer.h"
#include <Plugins/ParticipantManagement/Gui/ParticipantTemplates/participant_template_chooser_model.h>
#include <Plugins/ParticipantManagement/ppm_mime_datas.h>
#include <QMenu>
#include <QPainter>
#include <QRect>
#include <QMouseEvent>
#include <LtsWidgets/lts_message_dialog.h>
#include <LtsUtilsCore/dds_vector.h>
namespace ParticipantManagement
{
int ParticipantOrganisationDialog::s_preselectedParty = -1;
ParticipantOrganisationDialog::ParticipantOrganisationDialog(LtsSession::LtsSession *session,
bool asSupportService,
QWidget *parent)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::CloseOnly)
, m_asSupportService(asSupportService)
, m_poolModel(nullptr)
, m_proxyModel(nullptr)
, m_partyModel(nullptr)
, m_attachedModel(nullptr)
, m_detachedModel(nullptr)
, m_cooperateModel(nullptr)
, m_delegate(nullptr)
, m_dtc(nullptr)
, m_ftc(nullptr)
, m_ppmGuiCbxIfc(nullptr)
, m_session(session)
, m_requestHelper(new LtsUtils::RequestHelper(this))
, m_ui(new Ui::ParticipantOrganisation)
, m_logger(getLogger("ParticipantOrganisation"))
{
m_ui->setupUi(this);
m_ui->splitter->setStretchFactor(0, 1);
m_ui->splitter->setStretchFactor(1, 1);
m_ui->splitter->setStretchFactor(2, 2);
connect(m_ui->tvParty, &QTreeView::customContextMenuRequested,
this, &ParticipantOrganisationDialog::showContextMenu);
connect(m_ui->tvAttached, &QTreeView::customContextMenuRequested,
this, &ParticipantOrganisationDialog::showContextMenu);
connect(m_ui->tvDetached, &QTreeView::customContextMenuRequested,
this, &ParticipantOrganisationDialog::showContextMenu);
connect(m_ui->tvCooperate, &QTreeView::customContextMenuRequested,
this, &ParticipantOrganisationDialog::showContextMenu);
if (m_asSupportService)
setOnlineHelpFilename(QStringLiteral("Situation-Organise_Support_Participants"));
else
setOnlineHelpFilename(QStringLiteral("Situation-Organise_Participants"));
}
//----------------------------------------------------------------------------
ParticipantOrganisationDialog::~ParticipantOrganisationDialog()
{
delete m_ui;
}
void ParticipantOrganisationDialog::retranslate()
{
QString name;
if (m_asSupportService)
name = tr("Organise Support Participants");
else
name = tr("Organise Participants");
translate(m_ui, name);
}
void ParticipantOrganisationDialog::lock()
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " START";
m_ui->cbParty->setEnabled(true); // true !!
// avoid BaseClass::lock to be called. PartyEdit stays enabled
m_ui->tvParty->setEnabled(false);
m_ui->tvAttached->setEnabled(false);
m_ui->tvCooperate->setEnabled(false);
m_ui->tvDetached->setEnabled(false);
DEBUG_LOG(m_logger) << LOGFUNCTION << " END";
}
void ParticipantOrganisationDialog::unlock()
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " START";
m_ui->cbParty->setEnabled(true);
m_ui->tvParty->setEnabled(true);
m_ui->tvAttached->setEnabled(true);
m_ui->tvCooperate->setEnabled(true);
m_ui->tvDetached->setEnabled(true);
DEBUG_LOG(m_logger) << LOGFUNCTION << " END";
}
bool ParticipantOrganisationDialog::init(const std::shared_ptr<ParticipantManagement::Interface::Dtc> &dtc,
const std::shared_ptr<ParticipantManagement::Interface::Ftc> &ftc,
const std::shared_ptr<ForeignGuiTemplatesInterface> &ppmGuiTemplateIfc,
const std::shared_ptr<ForeignGuiComboboxInterface> &ppmGuiCbxIfc,
const std::shared_ptr<AdvancedSymbology::ForeignDataInterface> &asbIfc)
{
if (!dtc || !ftc || !ppmGuiCbxIfc)
return false;
m_dtc = dtc;
m_ftc = ftc;
m_ppmGuiTemplateIfc = ppmGuiTemplateIfc;
m_ppmGuiCbxIfc = ppmGuiCbxIfc;
//templateModel
m_ppmGuiTemplateIfc->getTemplateModel(m_ui->tvTemplate, m_asSupportService);
m_ui->tvTemplate->hideColumn(ParticipantTemplateChooserModel::ColTypeClass);
m_ui->tvTemplate->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
//poolModel
m_poolModel = new ParticipantPoolModel(this, m_session, m_dtc, m_asSupportService);
m_ui->tvPool->setModel(m_poolModel);
m_ui->tvPool->hideColumn(ParticipantPoolModel::ColTypeClass);
m_ui->tvPool->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
connect(m_poolModel, &ParticipantPoolModel::startUnitNamer, this, &ParticipantOrganisationDialog::onStartTemplateUnitNamer);
connect(m_poolModel, &ParticipantPoolModel::modifyParticipantData, this, &ParticipantOrganisationDialog::onPoolParticipantsChanged);
m_delegate = new DeleteDelegate(this);
connect(m_delegate, &DeleteDelegate::removePoolParty, this, &ParticipantOrganisationDialog::onRemovePoolParty);
m_ui->tvPool->setItemDelegateForColumn(ParticipantPoolModel::ColRemove, m_delegate);
if (m_asSupportService)
{
m_ui->lblParty->hide();
m_ui->cbParty->hide();
m_ui->tvParty->hide();
m_ui->tvAttached->hide();
m_ui->tvDetached->hide();
m_ui->tvCooperate->hide();
}
else
{
connect(m_ui->cbParty,
static_cast<void (LtsWidgets::LtsComboBox::*)(int)>(&LtsWidgets::LtsComboBox::currentIndexChanged),
this,
&ParticipantOrganisationDialog::onPartyChanged);
//PartyModels
m_partyModel = new ParticipantOrgaModel(ParticipantOrgaModel::PartyOrganisationType::Party,
m_dtc,
asbIfc,
this);
ParticipantOrgaProxyModel *partyProxy = new ParticipantOrgaProxyModel(this);
partyProxy->setSourceModel(m_partyModel);
m_ui->tvParty->setModel(partyProxy);
m_attachedModel = new ParticipantOrgaModel(ParticipantOrgaModel::PartyOrganisationType::Attached,
m_dtc,
asbIfc,
this);
ParticipantOrgaProxyModel *attachProxy = new ParticipantOrgaProxyModel(this);
attachProxy->setSourceModel(m_attachedModel);
m_ui->tvAttached->setModel(attachProxy);
m_detachedModel = new ParticipantOrgaModel(ParticipantOrgaModel::PartyOrganisationType::Detached,
m_dtc,
asbIfc,
this);
ParticipantOrgaProxyModel *detachProxy = new ParticipantOrgaProxyModel(this);
detachProxy->setSourceModel(m_detachedModel);
m_ui->tvDetached->setModel(detachProxy);
m_cooperateModel = new ParticipantOrgaModel(ParticipantOrgaModel::PartyOrganisationType::Cooperate,
m_dtc,
asbIfc,
this);
ParticipantOrgaProxyModel *cooperateProxy = new ParticipantOrgaProxyModel(this);
cooperateProxy->setSourceModel(m_cooperateModel);
m_ui->tvCooperate->setModel(cooperateProxy);
connect(m_partyModel, &ParticipantOrgaModel::participantDataChanged,
this, &ParticipantOrganisationDialog::onPartyParticipantsChanged);
connect(m_attachedModel, &ParticipantOrgaModel::participantDataChanged,
this, &ParticipantOrganisationDialog::onAttachedParticipantsChanged);
connect(m_detachedModel, &ParticipantOrgaModel::participantDataChanged,
this, &ParticipantOrganisationDialog::onDetachedParticipantsChanged);
connect(m_cooperateModel, &ParticipantOrgaModel::participantDataChanged,
this, &ParticipantOrganisationDialog::onCooperateParticipantsChanged);
}
m_ppmGuiCbxIfc->fillPartyComboBox(m_ui->cbParty);
const int idx = m_ui->cbParty->findData(s_preselectedParty);
if (idx >= 0)
m_ui->cbParty->setCurrentIndex(idx);
onPartyChanged();
return true;
}
void ParticipantOrganisationDialog::onModifyParticipantDataReply(const Core::FunctionReplyObject &replyObject)
{
m_requestHelper->requestReply(replyObject);
}
//private
QModelIndex ParticipantOrganisationDialog::selectedIndexView() const
{
QItemSelectionModel *selectionModel = m_ui->tvParty->selectionModel();
QModelIndexList indexL = selectionModel->selectedRows(0);
if (indexL.size() == 0)
return QModelIndex();
return m_proxyModel->mapToSource(indexL.at(0));
}
bool ParticipantOrganisationDialog::saveParticipantData(const ModifyParticipantDataRequest &request)
{
return m_requestHelper->startSingleRequest([this, request]()
{
return m_ftc->modifyParticipantDataRequest(request, this);
});
}
void ParticipantOrganisationDialog::onPoolParticipantsChanged(const QVector<ParticipantData> &participants,
const QString &originatorMimeType)
{
if (participants.isEmpty())
return;
ModifyParticipantDataRequest req;
req.data(LtsUtils::convert<std::vector<ParticipantData>>(participants));
// move from attached/coperate to pool -> update ParticipantOrganisation
if (originatorMimeType == ParticipantPartyAttached)
{
ParticipantOrganisation orga;
orga.participantId(participants.first().id());
orga.currentPartyId(0); // moved to pool
orga.isAttached(false);
orga.isCooperate(false);
req.participantOrganisation(orga);
}
saveParticipantData(req);
}
void ParticipantOrganisationDialog::onPartyParticipantsChanged(int addedParticipantId)
{
// move from pool/detached -> party was done
const int curPartyId = m_ui->cbParty->currentData().toInt();
const QVector<int> rootParticipantIds = m_partyModel->rootParticipantIds();
if (rootParticipantIds.isEmpty())
return;
bool bMovedFromPool = rootParticipantIds.contains(addedParticipantId);
ModifyParticipantDataRequest req;
if (!bMovedFromPool)
{
// search participantOrga with originPartyId = curPartyId, currentPartyId = 0,
// isAttached/isCooperate = false, participantId = addedParticipantId
// and remove it
ParticipantOrganisation orga;
orga.participantId(addedParticipantId);
orga.originPartyId(curPartyId);
orga.currentPartyId(curPartyId); // moved to currentParty
req.participantOrganisation(orga);
}
const QVector<ParticipantData> participantData = m_partyModel->participantData(curPartyId);
req.data(LtsUtils::convert<std::vector<ParticipantData>>(participantData));
saveParticipantData(req);
}
void ParticipantOrganisationDialog::onAttachedParticipantsChanged(int addedParticipantId)
{
// a move from pool -> attached was done
const int curPartyId = m_ui->cbParty->currentData().toInt();
// we need to create a new ParticipantOrganisation entry since addedParticipantId was attached to curParty
ModifyParticipantDataRequest req;
ParticipantOrganisation orga;
orga.participantId(addedParticipantId);
orga.currentPartyId(curPartyId); // moved from pool to curParty
orga.isAttached(true);
orga.isCooperate(false);
req.participantOrganisation(orga);
const QVector<ParticipantData> attachedtData = m_attachedModel->participantData(curPartyId); // moved from Pool
req.data(LtsUtils::convert<std::vector<ParticipantData>>(attachedtData));
saveParticipantData(req);
}
void ParticipantOrganisationDialog::onDetachedParticipantsChanged(int addedParticipantId)
{
// a move from party -> detached was done
const int curPartyId = m_ui->cbParty->currentData().toInt();
// we need to create a new ParticipantOrganisation entry since addedParticipantId was detached from curParty
ModifyParticipantDataRequest req;
ParticipantOrganisation orga;
orga.participantId(addedParticipantId);
orga.originPartyId(curPartyId);
orga.currentPartyId(0); // moved from currentParty to pool
req.participantOrganisation(orga);
const QVector<ParticipantData> participantData = m_partyModel->participantData(curPartyId);
const QVector<ParticipantData> detachedtData = m_detachedModel->participantData(0); // moved to Pool
req.data(LtsUtils::convert<std::vector<ParticipantData>>(participantData + detachedtData));
saveParticipantData(req);
}
void ParticipantOrganisationDialog::onCooperateParticipantsChanged(int addedParticipantId)
{
// a move from pool -> attached was done
const int curPartyId = m_ui->cbParty->currentData().toInt();
// we need to create a new ParticipantOrganisation entry since addedParticipantId was attached to curParty
ModifyParticipantDataRequest req;
ParticipantOrganisation orga;
orga.participantId(addedParticipantId);
orga.currentPartyId(curPartyId); // moved from pool to curParty
orga.isAttached(false);
orga.isCooperate(true);
req.participantOrganisation(orga);
const QVector<ParticipantData> attachedtData = m_cooperateModel->participantData(curPartyId); // moved from Pool
req.data(LtsUtils::convert<std::vector<ParticipantData>>(attachedtData));
saveParticipantData(req);
}
//slots
void ParticipantOrganisationDialog::onStartTemplateUnitNamer(int templateId)
{
const TemplateParticipant tempPart = m_dtc->templateParticipant(templateId);
//as a framelessdlg it will delete itself
ParticipantUnitNamer *namer = new ParticipantUnitNamer(QString::fromStdString(tempPart.designator()), QString::fromStdString(tempPart.tacticalIdentifier()), this);
connect(namer, &ParticipantUnitNamer::newUnitNames, this, [this, templateId](const QString & designator, const QString & tactIdentifer)
{
m_poolModel->addNewTemplateToPool(templateId, designator, tactIdentifer);
});
namer->show();
}
void ParticipantOrganisationDialog::onPartyChanged()
{
const int curPartyId = m_ui->cbParty->currentData().toInt();
s_preselectedParty = curPartyId;
DEBUG_LOG(m_logger) << LOGFUNCTION << " START, curPartyId" << curPartyId
<< ", m_asSupportService=" << m_asSupportService;
// if(!m_asSupportService)
// {
// m_ui->cbParty->setEnabled(false); // will be re-enabled with reply (::onLockDataChanged)
// tryLockTopicNew(QStringLiteral("LockParty"), curPartyId);
// }
for (auto tv : {m_ui->tvParty, m_ui->tvDetached, m_ui->tvAttached, m_ui->tvCooperate})
{
auto model = qobject_cast<ParticipantOrgaProxyModel *>(tv->model());
if (!model) // e.g. in O/C mode
continue;
model->onReinitModel(curPartyId);
const int colCount = tv->model()->columnCount(QModelIndex());
tv->expandAll();
for (int i = 0; i < colCount; ++i)
tv->resizeColumnToContents(i);
tv->header()->resizeSection(0, tv->columnWidth(0) + tv->iconSize().width() + 10);
}
//reinit PoolModel if no save on party
m_poolModel->onReinitModel();
}
void ParticipantOrganisationDialog::onRemovePoolParty()
{
const int curIdx = m_ui->tvPool->currentIndex().row();
if (m_poolModel->canRemoveRow(curIdx))
m_poolModel->removeRow(curIdx);
else
LtsWidgets::LtsMessageDialog::showMessage(this, tr("Can not remove unit - is a detached subunit"), tr("Can not remove unit"));
}
void ParticipantOrganisationDialog::showContextMenu(const QPoint &position)
{
QTreeView *tv = qobject_cast<QTreeView *>(sender());
if (!tv)
return;
const QModelIndex idx = tv->currentIndex();
if (!idx.isValid())
return;
if (tv->model()->rowCount(idx) == 0)
return;
QMenu menu;
if (tv->isExpanded(idx))
{
QAction *collapseAction = new QAction(tr("Collapse"), &menu);
connect(collapseAction, &QAction::triggered, this, [tv, idx]() { tv->collapse(idx);});
menu.addAction(collapseAction);
}
else
{
QAction *expandAction = new QAction(tr("Expand"), &menu);
connect(expandAction, &QAction::triggered, this, [tv, idx]() { tv->expand(idx);});
menu.addAction(expandAction);
}
menu.exec(tv->viewport()->mapToGlobal(position));
}
//delegate for pool Entries
DeleteDelegate::DeleteDelegate(QObject *parent)
: QItemDelegate(parent)
{
}
void DeleteDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if (index.column() == ParticipantManagement::ParticipantPoolModel::ColRemove)
{
painter->drawImage(option.rect.topLeft(), QImage(QLatin1String("icon:trash-alt.svg")).scaled(option.rect.height(), option.rect.height(),
Qt::KeepAspectRatio, Qt::SmoothTransformation));
}
else
QItemDelegate::paint(painter, option, index);
}
bool DeleteDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
{
if (event->type() != QEvent::MouseButtonRelease)
return QItemDelegate::editorEvent(event, model, option, index);
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
QRect imageRect = option.rect;
imageRect.setWidth(imageRect.height());
if (mouseEvent && mouseEvent->button() == Qt::MouseButton::LeftButton &&
imageRect.intersects(QRect(mouseEvent->pos(), mouseEvent->pos())))
{
emit removePoolParty();
return true;
}
else
return QItemDelegate::editorEvent(event, model, option, index);
}
} //namespace ParticipantManagement