1
0
Fork 0
OpenLCP/platform/qt/sacn/multiversemodel.cpp

322 lines
8.2 KiB
C++

#include "multiverseitem.h"
#include "multiversemodel.h"
#include "qsacnnode.h"
#include <QMetaEnum>
/**
* @brief MultiverseModel::MultiverseModel
* @param parent
* @param node
*/
MultiverseModel::MultiverseModel(QObject *parent, QSacnNode *node)
: QAbstractItemModel(parent)
, node_(node)
, rootItem_(new MultiverseItem())
{
// create items for the category headers
QMetaEnum categories = QMetaEnum::fromType<Catagory>();
for (int itr = 0; itr < categories.keyCount(); itr++)
{
auto header = new MultiverseItem(rootItem_);
header->setOverrideData(QString(categories.key(itr)));
auto idx = MultiverseModel::index(itr, 0, QModelIndex());
categoryIndexes.insert(static_cast<Catagory>(categories.value(itr)), idx);
}
// connect node changes
connect(node, &QSacnNode::discoveryUpdates,
this, &MultiverseModel::doDiscovery);
connect(node, &QSacnNode::subscribing,
this, [this](QSacnUniverse *universe){
insert_(categoryIndexes.value(Receiver), universe);
});
connect(node, &QSacnNode::unsubscribing,
this, [this](QSacnUniverse *universe){
remove_(categoryIndexes.value(Receiver), universe);
});
connect(node, &QSacnNode::creating,
this, [this](QSacnUniverse *universe){
insert_(categoryIndexes.value(Source), universe);
});
connect(node, &QSacnNode::terminating,
this, [this](QSacnUniverse *universe){
remove_(categoryIndexes.value(Source), universe);
});
}
/**
* @brief MultiverseModel::~MultiverseModel
*/
MultiverseModel::~MultiverseModel()
{
delete rootItem_;
}
/**
* @brief MultiverseModel::getItem
* @param index
* @return
*/
MultiverseItem * MultiverseModel::getItem(const QModelIndex &index) const
{
if (index.isValid())
{
auto item = static_cast<MultiverseItem*>(index.internalPointer());
if (item)
return item;
}
return rootItem_;
}
/**
* @brief MultiverseModel::headerData
* @param section
* @param orientation
* @param role
* @return
*/
QVariant MultiverseModel::headerData(int section, Qt::Orientation orientation,
int role) const
{
if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
switch (static_cast<Column>(section)) {
case Universe:
return tr("Universe");
case Status:
return tr("Status");
case Priority:
return tr("Priority");
case Channels:
return tr("Channels");
case SourceName:
return tr("Source Name");
}
}
return QVariant();
}
/**
* @brief MultiverseModel::index
* @param row
* @param column
* @param parent
* @return
*/
QModelIndex MultiverseModel::index(int row, int column,
const QModelIndex &parent) const
{
if (parent.isValid() && parent.column() != 0)
return QModelIndex();
MultiverseItem *parentItem = getItem(parent);
if (!parentItem)
return QModelIndex();
auto childItem = parentItem->child(row);
if (childItem)
return createIndex(row, column, childItem);
return QModelIndex();
}
/**
* @brief MultiverseModel::parent
* @param index
* @return
*/
QModelIndex MultiverseModel::parent(const QModelIndex &index) const
{
if (!checkIndex(index, CheckIndexOption::IndexIsValid |
CheckIndexOption::DoNotUseParent))
return QModelIndex();
auto childItem = getItem(index);
auto parentItem = childItem ? childItem->parentItem() : nullptr;
if (parentItem == rootItem_ || !parentItem)
return QModelIndex();
return createIndex(parentItem->row(), 0, parentItem);
}
/**
* @brief MultiverseModel::rowCount
* @param parent
* @return
*/
int MultiverseModel::rowCount(const QModelIndex &parent) const
{
auto parentItem = getItem(parent);
return parentItem ? parentItem->childCount() : 0;
}
/**
* @brief MultiverseModel::columnCount
* @param parent
* @return
*/
int MultiverseModel::columnCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return QMetaEnum::fromType<Column>().keyCount();
}
/**
* @brief MultiverseModel::data
* @param index
* @param role
* @return
*/
QVariant MultiverseModel::data(const QModelIndex &index, int role) const
{
if (!checkIndex(index, CheckIndexOption::IndexIsValid))
return QVariant();
return getItem(index)->data(index.column(), role);
}
/**
* @brief MultiverseModel::setData
* @param index
* @param value
* @param role
* @return
*/
bool MultiverseModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (!checkIndex(index, CheckIndexOption::IndexIsValid))
return false;
if (getItem(index)->setData(index.column(), value, role))
{
emit dataChanged(index, index, QVector<int>() << role);
return true;
}
return false;
}
/**
* @brief MultiverseModel::flags
* @param index
* @return
*/
Qt::ItemFlags MultiverseModel::flags(const QModelIndex &index) const
{
if (!checkIndex(index, CheckIndexOption::IndexIsValid))
return Qt::NoItemFlags;
auto item = getItem(index);
if (!item)
return Qt::NoItemFlags;
return item->flags(index.column(), QAbstractItemModel::flags(index));
}
/**
* @brief MultiverseModel::insert
* @param universe
* @param parent
* @return
*/
void MultiverseModel::insert_(const QModelIndex &parent,
QSacnUniverse* universe,
QSacnDiscoveredUniverse *discovery)
{
auto item = getItem(parent);
beginInsertRows(parent, item->childCount(), item->childCount());
auto child = new MultiverseItem(item, universe, discovery);
endInsertRows();
auto index = QPersistentModelIndex(createIndex(item->childCount() - 1, 0,
child));
auto refreshRow = [this] (QPersistentModelIndex index) {
auto begin = index.sibling(index.row(), 0);
auto end = begin.siblingAtColumn(columnCount() - 1);
emit dataChanged(begin, end);
};
connect(universe, &QSacnUniverse::dataChanged,
this, [refreshRow, index](){ refreshRow(index); });
connect(universe, &QSacnUniverse::statusChanged,
this, [refreshRow, index](){ refreshRow(index); });
connect(universe, &QSacnUniverse::sourceListChanged,
this, [this, universe, child, index, refreshRow]() {
// remove the old children
beginRemoveRows(index, 0, child->childCount() - 1);
child->removeChildren();
endRemoveRows();
// add the new children
beginInsertRows(index, 0, universe->sources().size() - 1);
child->createChildren();
endInsertRows();
// refresh row of new child when data arrives
for (int i = 0; i < child->childCount(); i++)
{
auto grandchild = child->child(i);
auto index = QPersistentModelIndex(createIndex(i, 0, grandchild));
auto data = grandchild->data(Column::Universe, Qt::EditRole);
if (data.metaType().id() != qMetaTypeId<QSacnUniverse*>())
return;
auto universe = data.value<QSacnUniverse*>();
connect(universe, &QSacnUniverse::dataChanged,
this, [refreshRow, index](){ refreshRow(index); });
connect(universe, &QSacnUniverse::statusChanged,
this, [refreshRow, index](){ refreshRow(index); });
}
});
}
/**
* @brief MultiverseModel::remove
* @param parent
* @param data
*/
void MultiverseModel::remove_(const QModelIndex &parent,
const QSacnUniverse *universe)
{
auto item = static_cast<MultiverseItem*>(parent.internalPointer());
auto row = item->childRow(Column::Universe, QVariant::fromValue(universe));
if (row < 0)
return;
auto child = item->child(row);
if (!child)
return;
beginRemoveRows(parent, row, row);
item->removeChild(child);
endRemoveRows();
}
void MultiverseModel::doDiscovery()
{
auto parentIndex = categoryIndexes.value(MultiverseModel::Discovery);
auto parent = static_cast<MultiverseItem*>(parentIndex.internalPointer());
beginRemoveRows(parentIndex, 0, parent->childCount() - 1);
parent->removeChildren();
endRemoveRows();
beginInsertRows(parentIndex, 0, node_->discovered.size() - 1);
for (auto& discovery : node_->discovered)
new MultiverseItem(parent, nullptr, discovery.get());
endInsertRows();
}