Files
qt5-legatus-legacy/Lts/Plugins/AudioVideoManagement/Gui/AVMenuEdit/avm_available_streams_model.cpp
T
2026-08-13 18:33:10 +02:00

324 lines
8.7 KiB
C++
Executable File

/**
* @RDE_HEADER@
* Radio TreeModel
* $Id$
* $HeadURL$
* $Author$
*/
#include "avm_available_streams_model.h"
#include <AudioVideoManagement/stream_name_mapping.h>
#include <InfrastructureManagement/ism.hpp>
#include <nglwidgets/ngltreeitem.h>
#include <QSet>
#include <QMimeData>
#include <QCollator>
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<Interface::Dtc> &avmDtc,
const std::shared_ptr<InfrastructureManagement::Interface::Dtc> &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>("StreamModelData");
qRegisterMetaType<StreamModelData>("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<StreamModelData>())
return QVariant();
const StreamModelData availStream = item->data().value<StreamModelData>();
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<StreamModelData> toAddIndoor;
std::vector<StreamModelData> toAddOutdoor;
std::vector<StreamModelData> 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<int, VideoTeam> &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