##// END OF EJS Templates
Adds the ability to force an acquisition pending for an operation (1)...
Adds the ability to force an acquisition pending for an operation (1) Creates struct that contains operation properties: - its weight - the flag to force acquisition waiting

File last commit:

r1194:73d5f3ef941a
r1249:b9a47ff1b9cc
Show More
CatalogueEventsModel.cpp
442 lines | 13.8 KiB | text/x-c | CppLexer
/ gui / src / Catalogue / CatalogueEventsModel.cpp
#include "Catalogue/CatalogueEventsModel.h"
#include <Common/DateUtils.h>
#include <Common/MimeTypesDef.h>
#include <DBEvent.h>
#include <DBEventProduct.h>
#include <DBTag.h>
#include <Data/SqpRange.h>
#include <SqpApplication.h>
#include <Time/TimeController.h>
#include <list>
#include <unordered_map>
#include <QHash>
#include <QMimeData>
Q_LOGGING_CATEGORY(LOG_CatalogueEventsModel, "CatalogueEventsModel")
const auto EVENT_ITEM_TYPE = 1;
const auto EVENT_PRODUCT_ITEM_TYPE = 2;
struct CatalogueEventsModel::CatalogueEventsModelPrivate {
QVector<std::shared_ptr<DBEvent> > m_Events;
std::unordered_map<DBEvent *, QVector<std::shared_ptr<DBEventProduct> > > m_EventProducts;
std::unordered_set<std::shared_ptr<DBEvent> > m_EventsWithChanges;
QStringList columnNames()
{
return QStringList{tr("Event"), tr("TStart"), tr("TEnd"),
tr("Tags"), tr("Product"), tr("")};
}
QVariant sortData(int col, const std::shared_ptr<DBEvent> &event) const
{
if (col == (int)CatalogueEventsModel::Column::Validation) {
return m_EventsWithChanges.find(event) != m_EventsWithChanges.cend() ? true
: QVariant();
}
return eventData(col, event);
}
QVariant eventData(int col, const std::shared_ptr<DBEvent> &event) const
{
switch (static_cast<Column>(col)) {
case CatalogueEventsModel::Column::Name:
return event->getName();
case CatalogueEventsModel::Column::TStart:
return nbEventProducts(event) > 0 ? DateUtils::dateTime(event->getTStart())
: QVariant{};
case CatalogueEventsModel::Column::TEnd:
return nbEventProducts(event) > 0 ? DateUtils::dateTime(event->getTEnd())
: QVariant{};
case CatalogueEventsModel::Column::Product:
return QString::number(nbEventProducts(event)) + " product(s)";
case CatalogueEventsModel::Column::Tags: {
QString tagList;
auto tags = event->getTags();
for (auto tag : tags) {
tagList += tag.getName();
tagList += ' ';
}
return tagList;
}
case CatalogueEventsModel::Column::Validation:
return QVariant();
default:
break;
}
Q_ASSERT(false);
return QStringLiteral("Unknown Data");
}
void parseEventProduct(const std::shared_ptr<DBEvent> &event)
{
for (auto product : event->getEventProducts()) {
m_EventProducts[event.get()].append(std::make_shared<DBEventProduct>(product));
}
}
int nbEventProducts(const std::shared_ptr<DBEvent> &event) const
{
auto eventProductsIt = m_EventProducts.find(event.get());
if (eventProductsIt != m_EventProducts.cend()) {
return m_EventProducts.at(event.get()).count();
}
else {
return 0;
}
}
QVariant eventProductData(int col, const std::shared_ptr<DBEventProduct> &eventProduct) const
{
switch (static_cast<Column>(col)) {
case CatalogueEventsModel::Column::Name:
return eventProduct->getProductId();
case CatalogueEventsModel::Column::TStart:
return DateUtils::dateTime(eventProduct->getTStart());
case CatalogueEventsModel::Column::TEnd:
return DateUtils::dateTime(eventProduct->getTEnd());
case CatalogueEventsModel::Column::Product:
return eventProduct->getProductId();
case CatalogueEventsModel::Column::Tags:
return QString();
case CatalogueEventsModel::Column::Validation:
return QVariant();
default:
break;
}
Q_ASSERT(false);
return QStringLiteral("Unknown Data");
}
};
CatalogueEventsModel::CatalogueEventsModel(QObject *parent)
: QAbstractItemModel(parent), impl{spimpl::make_unique_impl<CatalogueEventsModelPrivate>()}
{
}
void CatalogueEventsModel::setEvents(const QVector<std::shared_ptr<DBEvent> > &events)
{
beginResetModel();
impl->m_Events = events;
impl->m_EventProducts.clear();
impl->m_EventsWithChanges.clear();
for (auto event : events) {
impl->parseEventProduct(event);
}
endResetModel();
}
std::shared_ptr<DBEvent> CatalogueEventsModel::getEvent(const QModelIndex &index) const
{
if (itemTypeOf(index) == CatalogueEventsModel::ItemType::Event) {
return impl->m_Events.value(index.row());
}
else {
return nullptr;
}
}
std::shared_ptr<DBEvent> CatalogueEventsModel::getParentEvent(const QModelIndex &index) const
{
if (itemTypeOf(index) == CatalogueEventsModel::ItemType::EventProduct) {
return getEvent(index.parent());
}
else {
return nullptr;
}
}
std::shared_ptr<DBEventProduct>
CatalogueEventsModel::getEventProduct(const QModelIndex &index) const
{
if (itemTypeOf(index) == CatalogueEventsModel::ItemType::EventProduct) {
auto event = static_cast<DBEvent *>(index.internalPointer());
return impl->m_EventProducts.at(event).value(index.row());
}
else {
return nullptr;
}
}
void CatalogueEventsModel::addEvent(const std::shared_ptr<DBEvent> &event)
{
beginInsertRows(QModelIndex(), impl->m_Events.count() - 1, impl->m_Events.count() - 1);
impl->m_Events.append(event);
impl->parseEventProduct(event);
endInsertRows();
}
void CatalogueEventsModel::removeEvent(const std::shared_ptr<DBEvent> &event)
{
auto index = impl->m_Events.indexOf(event);
if (index >= 0) {
beginRemoveRows(QModelIndex(), index, index);
impl->m_Events.removeAt(index);
impl->m_EventProducts.erase(event.get());
impl->m_EventsWithChanges.erase(event);
endRemoveRows();
}
}
QVector<std::shared_ptr<DBEvent> > CatalogueEventsModel::events() const
{
return impl->m_Events;
}
void CatalogueEventsModel::refreshEvent(const std::shared_ptr<DBEvent> &event)
{
auto eventIndex = indexOf(event);
if (eventIndex.isValid()) {
// Refreshes the event line
auto colCount = columnCount();
emit dataChanged(eventIndex, index(eventIndex.row(), colCount));
// Also refreshes its children event products
auto childCount = rowCount(eventIndex);
emit dataChanged(index(0, 0, eventIndex), index(childCount, colCount, eventIndex));
}
else {
qCWarning(LOG_CatalogueEventsModel()) << "refreshEvent: event not found.";
}
}
QModelIndex CatalogueEventsModel::indexOf(const std::shared_ptr<DBEvent> &event) const
{
auto row = impl->m_Events.indexOf(event);
if (row >= 0) {
return index(row, 0);
}
return QModelIndex();
}
void CatalogueEventsModel::setEventHasChanges(const std::shared_ptr<DBEvent> &event,
bool hasChanges)
{
if (hasChanges) {
impl->m_EventsWithChanges.insert(event);
}
else {
impl->m_EventsWithChanges.erase(event);
}
}
bool CatalogueEventsModel::eventsHasChanges(const std::shared_ptr<DBEvent> &event) const
{
return impl->m_EventsWithChanges.find(event) != impl->m_EventsWithChanges.cend();
}
QModelIndex CatalogueEventsModel::index(int row, int column, const QModelIndex &parent) const
{
if (!hasIndex(row, column, parent)) {
return QModelIndex();
}
switch (itemTypeOf(parent)) {
case CatalogueEventsModel::ItemType::Root:
return createIndex(row, column);
case CatalogueEventsModel::ItemType::Event: {
auto event = getEvent(parent);
return createIndex(row, column, event.get());
}
case CatalogueEventsModel::ItemType::EventProduct:
break;
default:
break;
}
return QModelIndex();
}
QModelIndex CatalogueEventsModel::parent(const QModelIndex &index) const
{
switch (itemTypeOf(index)) {
case CatalogueEventsModel::ItemType::EventProduct: {
auto parentEvent = static_cast<DBEvent *>(index.internalPointer());
auto it
= std::find_if(impl->m_Events.cbegin(), impl->m_Events.cend(),
[parentEvent](auto event) { return event.get() == parentEvent; });
if (it != impl->m_Events.cend()) {
return createIndex(it - impl->m_Events.cbegin(), 0);
}
else {
return QModelIndex();
}
}
case CatalogueEventsModel::ItemType::Root:
break;
case CatalogueEventsModel::ItemType::Event:
break;
default:
break;
}
return QModelIndex();
}
int CatalogueEventsModel::rowCount(const QModelIndex &parent) const
{
if (parent.column() > 0) {
return 0;
}
switch (itemTypeOf(parent)) {
case CatalogueEventsModel::ItemType::Root:
return impl->m_Events.count();
case CatalogueEventsModel::ItemType::Event: {
auto event = getEvent(parent);
return impl->m_EventProducts[event.get()].count();
}
case CatalogueEventsModel::ItemType::EventProduct:
break;
default:
break;
}
return 0;
}
int CatalogueEventsModel::columnCount(const QModelIndex &parent) const
{
return static_cast<int>(CatalogueEventsModel::Column::NbColumn);
}
Qt::ItemFlags CatalogueEventsModel::flags(const QModelIndex &index) const
{
return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
}
QVariant CatalogueEventsModel::data(const QModelIndex &index, int role) const
{
if (index.isValid()) {
auto type = itemTypeOf(index);
if (type == CatalogueEventsModel::ItemType::Event) {
auto event = getEvent(index);
switch (role) {
case Qt::DisplayRole:
return impl->eventData(index.column(), event);
break;
}
}
else if (type == CatalogueEventsModel::ItemType::EventProduct) {
auto product = getEventProduct(index);
switch (role) {
case Qt::DisplayRole:
return impl->eventProductData(index.column(), product);
break;
}
}
}
return QVariant{};
}
QVariant CatalogueEventsModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
return impl->columnNames().value(section);
}
return QVariant();
}
void CatalogueEventsModel::sort(int column, Qt::SortOrder order)
{
std::sort(impl->m_Events.begin(), impl->m_Events.end(),
[this, column, order](auto e1, auto e2) {
auto data1 = impl->sortData(column, e1);
auto data2 = impl->sortData(column, e2);
auto result = data1.toString() < data2.toString();
return order == Qt::AscendingOrder ? result : !result;
});
emit dataChanged(QModelIndex(), QModelIndex());
emit modelSorted();
}
Qt::DropActions CatalogueEventsModel::supportedDragActions() const
{
return Qt::CopyAction | Qt::MoveAction;
}
QStringList CatalogueEventsModel::mimeTypes() const
{
return {MIME_TYPE_EVENT_LIST, MIME_TYPE_TIME_RANGE};
}
QMimeData *CatalogueEventsModel::mimeData(const QModelIndexList &indexes) const
{
auto mimeData = new QMimeData;
bool isFirst = true;
QVector<std::shared_ptr<DBEvent> > eventList;
QVector<std::shared_ptr<DBEventProduct> > eventProductList;
SqpRange firstTimeRange;
for (const auto &index : indexes) {
if (index.column() == 0) { // only the first column
auto type = itemTypeOf(index);
if (type == ItemType::Event) {
auto event = getEvent(index);
eventList << event;
if (isFirst) {
isFirst = false;
firstTimeRange.m_TStart = event->getTStart();
firstTimeRange.m_TEnd = event->getTEnd();
}
}
else if (type == ItemType::EventProduct) {
auto product = getEventProduct(index);
eventProductList << product;
if (isFirst) {
isFirst = false;
firstTimeRange.m_TStart = product->getTStart();
firstTimeRange.m_TEnd = product->getTEnd();
}
}
}
}
auto eventsEncodedData
= QByteArray{}; // sqpApp->catalogueController().->mimeDataForEvents(eventList); //TODO
mimeData->setData(MIME_TYPE_EVENT_LIST, eventsEncodedData);
if (eventList.count() + eventProductList.count() == 1) {
// No time range MIME data if multiple events are dragged
auto timeEncodedData = TimeController::mimeDataForTimeRange(firstTimeRange);
mimeData->setData(MIME_TYPE_TIME_RANGE, timeEncodedData);
}
return mimeData;
}
CatalogueEventsModel::ItemType CatalogueEventsModel::itemTypeOf(const QModelIndex &index) const
{
if (!index.isValid()) {
return ItemType::Root;
}
else if (index.internalPointer() == nullptr) {
return ItemType::Event;
}
else {
return ItemType::EventProduct;
}
}