/** * @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 #include #include #include #include #include #include #include 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 &dtc, const std::shared_ptr &ftc, const std::shared_ptr &ppmGuiTemplateIfc, const std::shared_ptr &ppmGuiCbxIfc, const std::shared_ptr &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(&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 &participants, const QString &originatorMimeType) { if (participants.isEmpty()) return; ModifyParticipantDataRequest req; req.data(LtsUtils::convert>(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 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 = m_partyModel->participantData(curPartyId); req.data(LtsUtils::convert>(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 attachedtData = m_attachedModel->participantData(curPartyId); // moved from Pool req.data(LtsUtils::convert>(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 = m_partyModel->participantData(curPartyId); const QVector detachedtData = m_detachedModel->participantData(0); // moved to Pool req.data(LtsUtils::convert>(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 attachedtData = m_cooperateModel->participantData(curPartyId); // moved from Pool req.data(LtsUtils::convert>(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(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(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(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