/** * @RDE_HEADER@ * TargetParticipantModel * $Id$ * $HeadURL$ * $Author$ * Created by Norbert Thoden, NLE, 2020-06-29 */ #include "tgt_target_part_model.h" #include "tgt_common.h" #include #include #include #include // pixelMetric #include namespace TargetManagement { QString toString(const std::vector< int32_t > &ids) { QString ret; for (auto id : ids) ret.append(QString::number(id)); return ret; } //--------------------------------- // TargetParticipantModel //--------------------------------- TargetParticipantModel::TargetParticipantModel(QObject *parent) : BaseClass( { tr("Id"), tr("Target Name"), // associated participant: tr("Participant Id"), tr("Equipmentnumber"), tr("Type"), // Equipmenttype tr("Participant"), // main/base config tr("Position"), tr("ActivateLaserDesignation"), tr("ActivateLights"), tr("ActivatePopupAutomatic"), tr("HitsToKill"), tr("PermanentInstalledTarget"), tr("VisibleParticipants") }, parent) , m_logger(getLogger("TargetParticipantModel")) {} bool TargetParticipantModel::initModel(const std::shared_ptr &tgtDtc, const std::shared_ptr &ppmDtc, const std::shared_ptr &ppmGuiCbxIfc, LtsSession::LtsSession *session) { m_tgt_dtc = tgtDtc; m_session = session; delete m_participantHandler; m_participantHandler = new ParticipantHandler(this); m_participantHandler->init(m_tgt_dtc, ppmDtc, ppmGuiCbxIfc); connect(m_participantHandler, &ParticipantHandler::signalParticipantNamesChanged, this, &TargetParticipantModel::signalParticipantNamesChanged); connect(m_participantHandler, &ParticipantHandler::signalParticipantChanged, this, &TargetParticipantModel::update); // insert Model const QMap targetParticipants = m_tgt_dtc->shootbackTargets(); INFO_LOG(m_logger) << "initModel - #TargetParticipantModel: " << targetParticipants.size(); connect(m_tgt_dtc.get(), &Interface::Dtc::shootbackTargetChanged, this, &TargetParticipantModel::onShootbackTargetChanged); { auto cb = [this](const TargetManagement::ShootbackTarget & d) { onShootbackTargetChanged(d, DataModification::eAdded); }; m_tgt_dtc->shootbackTargets(cb); } // updateColumnFilter connect(this, &TargetParticipantModel::rowsInserted, this, &TargetParticipantModel::updateColumnFilter); connect(this, &TargetParticipantModel::rowsRemoved, this, &TargetParticipantModel::updateColumnFilter); connect(this, &TargetParticipantModel::modelReset, this, &TargetParticipantModel::updateColumnFilter); // in case of changing value like hitsToKill: connect(this, &TargetParticipantModel::dataChanged, this, &TargetParticipantModel::updateColumnFilter); updateColumnFilter(); return true; } QVariant TargetParticipantModel::headerData(int section, Qt::Orientation orientation, int role) const { if (role == LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole && orientation == Qt::Horizontal) { // a few Set ==> const auto processBoolean = [this](const QSet &usedXYCont) -> QVariant { LtsWidgets::ComboboxFilterContent cfc; cfc.data.reserve(usedXYCont.size()); LtsWidgets::ComboboxFilterData cfd; for (int value : usedXYCont) { cfd.data = value; cfd.text = value ? tr("Yes") : tr("No"); cfd.icon = value ? m_yes : m_no; cfc.data.push_back(cfd); } cfc.sortItems = true; return cfc.toVariant(); }; // a few Set ==> const auto processInt = [](const QSet &usedXYCont) -> QVariant { LtsWidgets::ComboboxFilterContent cfc; cfc.data.reserve(usedXYCont.size()); LtsWidgets::ComboboxFilterData cfd; for (int value : usedXYCont) { cfd.data = value; cfd.text = QString::number(value); cfc.data.push_back(cfd); } cfc.sortItems = true; return cfc.toVariant(); }; if (section == ActivateLaserDesignation) return processBoolean(m_usedActiveLaserDesignations); else if (section == ActivateLights) return processBoolean(m_usedActivateLights); else if (section == ActivatePopupAutomatic) return processBoolean(m_usedActivatePopupAutomatic); else if (section == HitsToKill) return processInt(m_usedHitsToKill); else if (section == PermanentInstalledTarget) return processBoolean(m_usedPermanetTargetInstalled); } return BaseClass::headerData(section, orientation, role); } QVariant TargetParticipantModel::data(const QModelIndex &index, int role) const { INFO_LOG(m_logger) << LOGFUNCTION << " role=" << role << " index = " << index.column(); if (!indexIsValid(index)) return QVariant(); if (role != Qt::DisplayRole && role != Qt::DecorationRole && role != Qt::BackgroundRole && role != Qt::ToolTipRole && role != LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole) return QVariant(); const TargetManagement::ShootbackTarget &shootbackTarget = m_vecData.at(index.row()); if (role == Qt::DecorationRole) { if (index.column() == Participant) { static const int pmSize = QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize); const QPixmap &pm = m_participantHandler->getParticipantDecoration(shootbackTarget.targetParticipantId()); if (!pm.isNull()) return pm.scaled(pmSize, pmSize); } else if ((index.column() == ActivateLaserDesignation)) return shootbackTarget.activateLaserDesignation() ? m_yes : m_no; else if ((index.column() == ActivateLights)) return shootbackTarget.activateLights() ? m_yes : m_no; else if ((index.column() == ActivatePopupAutomatic)) return shootbackTarget.activatePopupAutomatic() ? m_yes : m_no; else if ((index.column() == PermanentInstalledTarget)) return shootbackTarget.permanentInstalledTarget() ? m_yes : m_no; return QVariant(); } else if (role == Qt::BackgroundRole) { if ((index.column() == TargetPartipantId) && (shootbackTarget.targetParticipantId() <= 0)) return getWarningBackgroundRole(); // orange if (index.column() == TargetPartipantEquipmentNumber) { const int eqNo = m_participantHandler->getParticipantIdToEquipmentNumber(shootbackTarget.targetParticipantId()); if (eqNo <= 0) return getWarningBackgroundRole(); // orange } } else if (role == Qt::ToolTipRole) { if (index.column() == Participant) { QString tooltip(QStringLiteral("")); const QPixmap &img = m_participantHandler->getParticipantDecoration(shootbackTarget.targetParticipantId()); if (!img.isNull()) { // without a temporary file: QByteArray data; QBuffer buffer(&data); img.save(&buffer, "PNG", 100); tooltip.append(QStringLiteral("
").arg(QString::fromLatin1(data.toBase64()))); QString hdr = this->headerData(ShootbackTargetName, Qt::Horizontal, Qt::DisplayRole).toString(); tooltip.append(QStringLiteral("

%1: %2

").arg(hdr, QString::fromStdString(shootbackTarget.name()))); hdr = this->headerData(Participant, Qt::Horizontal, Qt::DisplayRole).toString(); const QString &val = m_participantHandler->getParticipantHierarchie(shootbackTarget.targetParticipantId()); tooltip.append(QStringLiteral("

%1: %2

").arg(hdr, val)); tooltip.append(QStringLiteral("")); return tooltip; } } } else if (role == LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole) { // following static_cast are important!!! if (index.column() == ActivateLaserDesignation) return static_cast(shootbackTarget.activateLaserDesignation()); if (index.column() == ActivateLights) return static_cast(shootbackTarget.activateLights()); if (index.column() == ActivatePopupAutomatic) return static_cast(shootbackTarget.activatePopupAutomatic()); if (index.column() == HitsToKill) return shootbackTarget.hitsToKill(); } switch (index.column()) { case Id: return shootbackTarget.id(); // associated participant: case ShootbackTargetName: return QString::fromStdString(shootbackTarget.name()); case TargetPartipantId: return shootbackTarget.targetParticipantId(); case TargetPartipantEquipmentNumber: { const int eqNo = m_participantHandler->getParticipantIdToEquipmentNumber(shootbackTarget.targetParticipantId()); if (eqNo <= 0) return QStringLiteral("-"); return eqNo; } case TargetPartipantEquipmentType: { const auto type = m_participantHandler->getParticipantIdToWmsTypeClass(shootbackTarget.targetParticipantId()); return ParticipantHandler::target_wmsTypeClassToString(type); } case Participant: return m_participantHandler->getParticipantHierarchie(shootbackTarget.targetParticipantId()); // main/base config case Position: { const Core::GeoPosition2D &pos = shootbackTarget.position(); return LtsCoordTrans::mgrsFromGeographic(pos.lon(), pos.lat()); } case ActivateLaserDesignation: return shootbackTarget.activateLaserDesignation() ? tr("Yes") : tr("No"); case ActivateLights: return shootbackTarget.activateLights() ? tr("Yes") : tr("No"); case ActivatePopupAutomatic: return shootbackTarget.activatePopupAutomatic() ? tr("Yes") : tr("No"); case HitsToKill: return shootbackTarget.hitsToKill(); case PermanentInstalledTarget: return shootbackTarget.permanentInstalledTarget() ? tr("Yes") : tr("No"); case VisibleParticipants: return TargetManagement::toString(shootbackTarget.visibleParticipants()); } // switch return QVariant(); } QSet TargetParticipantModel::getAssociatedParticipantIds() const { QSet ret; ret.reserve(m_vecData.size()); for (const TargetManagement::ShootbackTarget &data : m_vecData) ret += data.targetParticipantId(); return ret; } void TargetParticipantModel::onShootbackTargetChanged(const TargetManagement::ShootbackTarget &data, const DataModification modType) { BaseClass::onDataChanged(data, modType); emit signalParticipantNamesChanged(); } void TargetParticipantModel::updateColumnFilter() { m_usedActiveLaserDesignations.clear(); m_usedActivateLights.clear(); m_usedActivatePopupAutomatic.clear(); m_usedHitsToKill.clear(); m_usedPermanetTargetInstalled.clear(); for (const ShootbackTarget &item : qAsConst(m_vecData)) { m_usedActiveLaserDesignations.insert(item.activateLaserDesignation()); m_usedActivateLights.insert(item.activateLights()); m_usedActivatePopupAutomatic.insert(item.activatePopupAutomatic()); m_usedHitsToKill.insert(item.hitsToKill()); m_usedPermanetTargetInstalled.insert(item.permanentInstalledTarget()); } } // -------------------------------------------------------- // TargetParticipantProxyModel // -------------------------------------------------------- void TargetParticipantProxyModel::setSourceModel(QAbstractItemModel *sourceModel) { m_sourceModel = qobject_cast(sourceModel); BaseClass::setSourceModel(sourceModel); } bool TargetParticipantProxyModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const { if (!m_sourceModel || !m_sourceModel->m_participantHandler || source_left.column() != source_right.column() || source_left.row() < 0 || source_left.row() >= m_sourceModel->m_vecData.size() || source_right.row() < 0 || source_right.row() >= m_sourceModel->m_vecData.size() ) return BaseClass::lessThan(source_left, source_right); const TargetManagement::ShootbackTarget &left = m_sourceModel->m_vecData.at(source_left.row()); const TargetManagement::ShootbackTarget &right = m_sourceModel->m_vecData.at(source_right.row()); switch (source_left.column()) { case TargetParticipantModel::Columns::Id: return left.id() < right.id(); case TargetParticipantModel::Columns::ShootbackTargetName: return left.name() < right.name(); case TargetParticipantModel::Columns::TargetPartipantId: return left.targetParticipantId() < right.targetParticipantId(); case TargetParticipantModel::Columns::TargetPartipantEquipmentNumber: { const int eqNoLeft = m_sourceModel->m_participantHandler->getParticipantIdToEquipmentNumber(left.targetParticipantId()); const int eqNoRight = m_sourceModel->m_participantHandler->getParticipantIdToEquipmentNumber(left.targetParticipantId()); return eqNoLeft < eqNoRight; } // case TargetParticipantModel::Columns::Position: case TargetParticipantModel::Columns::ActivateLaserDesignation: return left.activateLaserDesignation() < right.activateLaserDesignation(); case TargetParticipantModel::Columns::ActivateLights: return left.activateLights() < right.activateLights(); case TargetParticipantModel::Columns::ActivatePopupAutomatic: return left.activatePopupAutomatic() < right.activatePopupAutomatic(); case TargetParticipantModel::Columns::HitsToKill: return left.hitsToKill() < right.hitsToKill(); case TargetParticipantModel::Columns::PermanentInstalledTarget: return left.permanentInstalledTarget() < right.permanentInstalledTarget(); case TargetParticipantModel::Columns::VisibleParticipants: return toString(left.visibleParticipants()) < toString(right.visibleParticipants()); case TargetParticipantModel::Columns::Participant: // QString compare return LtsUtils::lessThan(source_left.data(), source_right.data()); } return BaseClass::lessThan(source_left, source_right); } } // namespace TargetManagement