##// END OF EJS Templates
Fixes the refresh of data that was not working all the time
Fixes the refresh of data that was not working all the time

File last commit:

r1300:f0b824bb0975
r1324:c436df4b66de
Show More
CatalogueEventsModel.cpp
461 lines | 14.7 KiB | text/x-c | CppLexer
/ gui / src / Catalogue / CatalogueEventsModel.cpp
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 #include "Catalogue/CatalogueEventsModel.h"
Drop of events on a catalogue
r1285 #include <Catalogue/CatalogueController.h>
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 #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>
"Apply" and "cancel" buttons on an event
r1194 Q_LOGGING_CATEGORY(LOG_CatalogueEventsModel, "CatalogueEventsModel")
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 const auto EVENT_ITEM_TYPE = 1;
const auto EVENT_PRODUCT_ITEM_TYPE = 2;
Edition of event products via the inspector
r1183 struct CatalogueEventsModel::CatalogueEventsModelPrivate {
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 QVector<std::shared_ptr<DBEvent> > m_Events;
std::unordered_map<DBEvent *, QVector<std::shared_ptr<DBEventProduct> > > m_EventProducts;
QStringList columnNames()
{
"Apply" and "cancel" buttons on an event
r1194 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) {
store events with changes in the catalogue controller
r1292 auto hasChanges = sqpApp->catalogueController().eventHasChanges(event);
return hasChanges ? true : QVariant();
"Apply" and "cancel" buttons on an event
r1194 }
return eventData(col, event);
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 }
QVariant eventData(int col, const std::shared_ptr<DBEvent> &event) const
{
switch (static_cast<Column>(col)) {
"Apply" and "cancel" buttons on an event
r1194 case CatalogueEventsModel::Column::Name:
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 return event->getName();
"Apply" and "cancel" buttons on an event
r1194 case CatalogueEventsModel::Column::TStart:
Fix display of tstart & tend when an event has no event products
r1193 return nbEventProducts(event) > 0 ? DateUtils::dateTime(event->getTStart())
: QVariant{};
"Apply" and "cancel" buttons on an event
r1194 case CatalogueEventsModel::Column::TEnd:
Fix display of tstart & tend when an event has no event products
r1193 return nbEventProducts(event) > 0 ? DateUtils::dateTime(event->getTEnd())
: QVariant{};
"Apply" and "cancel" buttons on an event
r1194 case CatalogueEventsModel::Column::Product:
Fix display of tstart & tend when an event has no event products
r1193 return QString::number(nbEventProducts(event)) + " product(s)";
"Apply" and "cancel" buttons on an event
r1194 case CatalogueEventsModel::Column::Tags: {
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 QString tagList;
auto tags = event->getTags();
for (auto tag : tags) {
tagList += tag.getName();
tagList += ' ';
}
return tagList;
}
"Apply" and "cancel" buttons on an event
r1194 case CatalogueEventsModel::Column::Validation:
return QVariant();
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 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));
}
}
Fix display of tstart & tend when an event has no event products
r1193 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;
}
}
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 QVariant eventProductData(int col, const std::shared_ptr<DBEventProduct> &eventProduct) const
{
switch (static_cast<Column>(col)) {
"Apply" and "cancel" buttons on an event
r1194 case CatalogueEventsModel::Column::Name:
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 return eventProduct->getProductId();
"Apply" and "cancel" buttons on an event
r1194 case CatalogueEventsModel::Column::TStart:
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 return DateUtils::dateTime(eventProduct->getTStart());
"Apply" and "cancel" buttons on an event
r1194 case CatalogueEventsModel::Column::TEnd:
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 return DateUtils::dateTime(eventProduct->getTEnd());
"Apply" and "cancel" buttons on an event
r1194 case CatalogueEventsModel::Column::Product:
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 return eventProduct->getProductId();
"Apply" and "cancel" buttons on an event
r1194 case CatalogueEventsModel::Column::Tags:
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 return QString();
"Apply" and "cancel" buttons on an event
r1194 case CatalogueEventsModel::Column::Validation:
return QVariant();
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 default:
break;
}
Q_ASSERT(false);
return QStringLiteral("Unknown Data");
}
Fix sorting with event products
r1288
void refreshChildrenOfIndex(CatalogueEventsModel *model, const QModelIndex &index) const
{
auto childCount = model->rowCount(index);
auto colCount = model->columnCount();
emit model->dataChanged(model->index(0, 0, index),
model->index(childCount, colCount, index));
}
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 };
CatalogueEventsModel::CatalogueEventsModel(QObject *parent)
Edition of event products via the inspector
r1183 : QAbstractItemModel(parent), impl{spimpl::make_unique_impl<CatalogueEventsModelPrivate>()}
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 {
}
void CatalogueEventsModel::setEvents(const QVector<std::shared_ptr<DBEvent> > &events)
{
beginResetModel();
impl->m_Events = events;
Edition of event products via the inspector
r1183 impl->m_EventProducts.clear();
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 for (auto event : events) {
impl->parseEventProduct(event);
}
endResetModel();
}
Edition of event products via the inspector
r1183 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
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 {
Edition of event products via the inspector
r1183 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;
}
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 }
void CatalogueEventsModel::addEvent(const std::shared_ptr<DBEvent> &event)
{
Fix sorting with event products
r1288 beginInsertRows(QModelIndex(), impl->m_Events.count(), impl->m_Events.count());
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 impl->m_Events.append(event);
impl->parseEventProduct(event);
endInsertRows();
Fix sorting with event products
r1288
// Also refreshes its children event products
auto eventIndex = index(impl->m_Events.count(), 0);
impl->refreshChildrenOfIndex(this, eventIndex);
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 }
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());
endRemoveRows();
}
}
"Apply" and "cancel" buttons on an event
r1194 QVector<std::shared_ptr<DBEvent> > CatalogueEventsModel::events() const
{
return impl->m_Events;
}
fix refresh of events after a discard
r1300 void CatalogueEventsModel::refreshEvent(const std::shared_ptr<DBEvent> &event,
bool refreshEventProducts)
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 {
"Apply" and "cancel" buttons on an event
r1194 auto eventIndex = indexOf(event);
if (eventIndex.isValid()) {
fix refresh of events after a discard
r1300 if (refreshEventProducts) {
// Reparse the associated event products
auto nbEventProducts = impl->nbEventProducts(event);
auto newNbOfEventProducts = event->getEventProducts().size();
if (newNbOfEventProducts < nbEventProducts) {
beginRemoveRows(eventIndex, newNbOfEventProducts, nbEventProducts - 1);
impl->m_EventProducts.erase(event.get());
impl->parseEventProduct(event);
endRemoveRows();
}
else if (newNbOfEventProducts > nbEventProducts) {
beginInsertRows(eventIndex, nbEventProducts, newNbOfEventProducts - 1);
impl->m_EventProducts.erase(event.get());
impl->parseEventProduct(event);
endInsertRows();
}
else { // newNbOfEventProducts == nbEventProducts
impl->m_EventProducts.erase(event.get());
impl->parseEventProduct(event);
}
}
"Apply" and "cancel" buttons on an event
r1194 // Refreshes the event line
Edition of event products via the inspector
r1183 auto colCount = columnCount();
"Apply" and "cancel" buttons on an event
r1194 emit dataChanged(eventIndex, index(eventIndex.row(), colCount));
Edition of event products via the inspector
r1183
"Apply" and "cancel" buttons on an event
r1194 // Also refreshes its children event products
Fix sorting with event products
r1288 impl->refreshChildrenOfIndex(this, eventIndex);
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 }
"Apply" and "cancel" buttons on an event
r1194 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();
}
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 QModelIndex CatalogueEventsModel::index(int row, int column, const QModelIndex &parent) const
{
if (!hasIndex(row, column, parent)) {
return QModelIndex();
}
Edition of event products via the inspector
r1183 switch (itemTypeOf(parent)) {
case CatalogueEventsModel::ItemType::Root:
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 return createIndex(row, column);
Edition of event products via the inspector
r1183 case CatalogueEventsModel::ItemType::Event: {
auto event = getEvent(parent);
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 return createIndex(row, column, event.get());
}
Edition of event products via the inspector
r1183 case CatalogueEventsModel::ItemType::EventProduct:
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 break;
default:
break;
}
return QModelIndex();
}
QModelIndex CatalogueEventsModel::parent(const QModelIndex &index) const
{
Edition of event products via the inspector
r1183 switch (itemTypeOf(index)) {
case CatalogueEventsModel::ItemType::EventProduct: {
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 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();
}
}
Edition of event products via the inspector
r1183 case CatalogueEventsModel::ItemType::Root:
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 break;
Edition of event products via the inspector
r1183 case CatalogueEventsModel::ItemType::Event:
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 break;
default:
break;
}
return QModelIndex();
}
int CatalogueEventsModel::rowCount(const QModelIndex &parent) const
{
if (parent.column() > 0) {
return 0;
}
Edition of event products via the inspector
r1183 switch (itemTypeOf(parent)) {
case CatalogueEventsModel::ItemType::Root:
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 return impl->m_Events.count();
Edition of event products via the inspector
r1183 case CatalogueEventsModel::ItemType::Event: {
auto event = getEvent(parent);
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 return impl->m_EventProducts[event.get()].count();
}
Edition of event products via the inspector
r1183 case CatalogueEventsModel::ItemType::EventProduct:
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 break;
default:
break;
}
return 0;
}
int CatalogueEventsModel::columnCount(const QModelIndex &parent) const
{
"Apply" and "cancel" buttons on an event
r1194 return static_cast<int>(CatalogueEventsModel::Column::NbColumn);
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 }
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()) {
Edition of event products via the inspector
r1183 auto type = itemTypeOf(index);
if (type == CatalogueEventsModel::ItemType::Event) {
auto event = getEvent(index);
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 switch (role) {
case Qt::DisplayRole:
return impl->eventData(index.column(), event);
break;
}
}
Edition of event products via the inspector
r1183 else if (type == CatalogueEventsModel::ItemType::EventProduct) {
auto product = getEventProduct(index);
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 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)
{
Fix sorting with event products
r1288 beginResetModel();
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 std::sort(impl->m_Events.begin(), impl->m_Events.end(),
[this, column, order](auto e1, auto e2) {
"Apply" and "cancel" buttons on an event
r1194 auto data1 = impl->sortData(column, e1);
auto data2 = impl->sortData(column, e2);
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182
auto result = data1.toString() < data2.toString();
return order == Qt::AscendingOrder ? result : !result;
});
Fix sorting with event products
r1288 endResetModel();
"Apply" and "cancel" buttons on an event
r1194 emit modelSorted();
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 }
Qt::DropActions CatalogueEventsModel::supportedDragActions() const
{
Drop of events on a catalogue
r1285 return Qt::CopyAction;
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 }
QStringList CatalogueEventsModel::mimeTypes() const
{
return {MIME_TYPE_EVENT_LIST, MIME_TYPE_TIME_RANGE};
}
QMimeData *CatalogueEventsModel::mimeData(const QModelIndexList &indexes) const
{
auto mimeData = new QMimeData;
Fix drag&drop on time widget with event products
r1184 bool isFirst = true;
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 QVector<std::shared_ptr<DBEvent> > eventList;
Fix drag&drop on time widget with event products
r1184 QVector<std::shared_ptr<DBEventProduct> > eventProductList;
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182
SqpRange firstTimeRange;
for (const auto &index : indexes) {
if (index.column() == 0) { // only the first column
Fix drag&drop on time widget with event products
r1184 auto type = itemTypeOf(index);
if (type == ItemType::Event) {
auto event = getEvent(index);
eventList << event;
if (isFirst) {
isFirst = false;
Displays TStart & TEnd for events
r1185 firstTimeRange.m_TStart = event->getTStart();
firstTimeRange.m_TEnd = event->getTEnd();
Fix drag&drop on time widget with event products
r1184 }
}
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();
}
}
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 }
}
Drop of events on a catalogue
r1285 if (!eventList.isEmpty() && eventProductList.isEmpty()) {
auto eventsEncodedData = sqpApp->catalogueController().mimeDataForEvents(eventList);
mimeData->setData(MIME_TYPE_EVENT_LIST, eventsEncodedData);
}
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182
Fix drag&drop on time widget with event products
r1184 if (eventList.count() + eventProductList.count() == 1) {
Change the event model to a treeview model + update the last version of CatalogueAPI
r1182 // No time range MIME data if multiple events are dragged
auto timeEncodedData = TimeController::mimeDataForTimeRange(firstTimeRange);
mimeData->setData(MIME_TYPE_TIME_RANGE, timeEncodedData);
}
return mimeData;
}
Edition of event products via the inspector
r1183
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;
}
}