/** * @RDE_HEADER@ * Radio TreeModel * $Id$ * $HeadURL$ * $Author$ */ #include "avm_available_streams_model.h" #include #include #include #include #include #include namespace { bool isMountingPointOfInterest(const InfrastructureManagement::StructureElement &se, bool isAudio) { if (se.structureElementTypeId() != InfrastructureManagement::StructureElementType::MountingPoint) return false; // Cameras are relevant for both, audio and video // The problem for audio here is that we cannot know yet whether later // there will be a camera mounted that is capable of audio. if (se.mountingPointTypeId() == InfrastructureManagement::MountingPointType::IndoorCamera || se.mountingPointTypeId() == InfrastructureManagement::MountingPointType::OutdoorCamera) return true; if (isAudio && se.mountingPointTypeId() == InfrastructureManagement::MountingPointType::AnnouncementUnit) return true; return false; } } // anonymous namespace namespace AudioVideoManagement { const QString AvailableStreamsModel::s_MimeType = QStringLiteral("AvailStreamsModel/DragDrop"); struct sorter { bool operator()(const StreamModelData &i, const StreamModelData &j) { QCollator col; col.setNumericMode(true); return col.compare(j.name, i.name) > 0 ; } } sortStuff; AvailableStreamsModel::AvailableStreamsModel(const std::shared_ptr &avmDtc, const std::shared_ptr &ismDtc, LtsSession::LtsSession *session, StreamNameMapping *streamNameMapping, QObject *parent, bool isAudio) : NGLTreeModel(parent, new NGLTreeItem(QVariant(), QIcon()), {tr("Available Streams")}) , m_isAudio(isAudio) , m_avmDtc(avmDtc) , m_ismDtc(ismDtc) , m_session(session) , m_streamNameMapping(streamNameMapping) , m_logger(getLogger("AvailableStreamsModel")) { Q_ASSERT(ismDtc); Q_ASSERT(streamNameMapping); qRegisterMetaTypeStreamOperators("StreamModelData"); qRegisterMetaType("StreamModelData"); setMimeType(s_MimeType); connect(m_ismDtc.get(), &InfrastructureManagement::Interface::Dtc::mainStructureElementChanged, this, [ this]() { initModel(); }); connect(m_streamNameMapping, &StreamNameMapping::changed, this, [ this]() { initModel(); }); if (!m_isAudio) { connect(m_avmDtc.get(), &AudioVideoManagement::Interface::Dtc::videoTeamChanged, this, [ this]() { initModel(); }); } initModel(); } QVariant AvailableStreamsModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) return QVariant(); NGLTreeItem *item = privateData(index); if (!item->data().canConvert()) return QVariant(); const StreamModelData availStream = item->data().value(); switch (role) { case Qt::DisplayRole: { switch (index.column()) { case 0 : return availStream.name; default: return QStringLiteral("??"); } break; } case Qt::DecorationRole: { switch (index.column()) { case 0: { static const QIcon folder(QStringLiteral("icon:evaluation_folder.svg")); static const QIcon camera(QStringLiteral("icon:camera_control.svg")); return availStream.isGroup ? folder : camera; } default: break; } break; } default: break; } // switch return NGLTreeModel::data(index, role); } Qt::ItemFlags AvailableStreamsModel::flags(const QModelIndex &index) const { Qt::ItemFlags defaultFlags = NGLTreeModel::flags(index); NGLTreeItem *item = privateData(index); if (item == m_rootItem) return defaultFlags; return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | defaultFlags; } QMimeData *AvailableStreamsModel::mimeData(const QModelIndexList &indexes) const { // Use display role (textual name of stream) for identification when dropping mimeData QMimeData *pData = NGLTreeModel::mimeData(indexes); pData->setText(data(indexes[0]).toString()); return pData; } bool AvailableStreamsModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) { INFO_LOG(m_logger) << "dropMimeData: action = " << action << ", row = " << row << ", parent: valid = " << parent.isValid(); if (action == Qt::IgnoreAction) return true; if (!data->hasFormat(s_MimeType)) return false; if ((action != Qt::MoveAction) && (action != Qt::CopyAction)) return false; return NGLTreeModel::dropMimeData(data, action, row, column, parent); } void AvailableStreamsModel::initModel() { beginResetModel(); INFO_LOG(m_logger) << "initModel"; // build tree // Ignore NOT installed streams m_rootItem->removeAllChildren(); // group to bundle streams StreamModelData availStream; availStream.id = 0; availStream.name = tr("New group"); availStream.parentId = -1; availStream.isGroup = true; QVariant data; data.setValue(availStream); m_rootItem->appendChild(new NGLTreeItem(data, QIcon())); std::vector toAddIndoor; std::vector toAddOutdoor; std::vector toAddMvs; const auto &mountedAssets = m_ismDtc->mountingPointAssets(); const auto &buildings = m_ismDtc->mainStructureElements(); for (const auto &building : buildings) { for (const auto &mountingPoint : building.elements()) { if (!isMountingPointOfInterest(mountingPoint, m_isAudio)) continue; //check for mounted bool isMounted = false; for (const auto &mountedAsset : mountedAssets) { if (mountedAsset.structureElementId() == mountingPoint.id()) { isMounted = true; break; } } if (!isMounted) continue; StreamModelData item; item.name = m_streamNameMapping->displayName(mountingPoint.id()); item.mountingPointId = mountingPoint.id(); item.isGroup = false; // What about id and parentId? if (mountingPoint.mountingPointTypeId() == InfrastructureManagement::MountingPointType::IndoorCamera) toAddIndoor.push_back(item); else toAddOutdoor.push_back(item); // m_rootItem->appendChild(new NGLTreeItem(data, QIcon())); } } //add MVS in video list if (!m_isAudio) { const auto &mvsStreams = m_avmDtc->videoTeams(); for (const auto &videoTeam : mvsStreams) { if (videoTeam.exerciseId() != m_session->exerciseId()) continue; DEBUG_LOG(m_logger) << "add new videoteam" << videoTeam; StreamModelData item; item.name = QString::fromStdString(videoTeam.streamName().c_str()); item.mountingPointId = -1 * videoTeam.id(); // negative id for mvs item.isGroup = false; // data.setValue(item); toAddMvs.push_back(item); //m_rootItem->appendChild(new NGLTreeItem(data, QIcon())); } } //sort // using object as comp std::sort(toAddOutdoor.begin(), toAddOutdoor.end(), sortStuff); for (const auto &item : toAddOutdoor) { data.setValue(item); m_rootItem->appendChild(new NGLTreeItem(data, QIcon())); } std::sort(toAddIndoor.begin(), toAddIndoor.end(), sortStuff); for (const auto &item : toAddIndoor) { data.setValue(item); m_rootItem->appendChild(new NGLTreeItem(data, QIcon())); } std::sort(toAddMvs.begin(), toAddMvs.end(), sortStuff); for (const auto &item : toAddMvs) { data.setValue(item); m_rootItem->appendChild(new NGLTreeItem(data, QIcon())); } endResetModel(); } StreamModelData StreamModelData::createFromServiceItem(const AvMenuEntry &entry, StreamNameMapping *streamNameMapping, const QMap &videoTeamList) { StreamModelData data; data.id = entry.id(); data.parentId = entry.parentId(); data.isGroup = entry.isGroup(); if (entry.isGroup()) data.name = QString::fromStdString(entry.name().get()); else { if (entry.mountingPointId().is_set() && (entry.mountingPointId().get() > 0)) { data.mountingPointId = entry.mountingPointId().get(); data.name = streamNameMapping->displayName(entry.mountingPointId().get()); } else { data.mountingPointId = entry.mountingPointId().get(); data.name = QString::fromStdString(videoTeamList.value(entry.mountingPointId().get() * -1).streamName()); } } return data; } } // Namespace AudioVideoManagement