##// END OF EJS Templates
Merge pull request 397 from SciQLop-fork develop...
Merge pull request 397 from SciQLop-fork develop Develop

File last commit:

r1245:f0b824bb0975
r1248:63746919da62 merge
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
r1149 #include "Catalogue/CatalogueEventsModel.h"
Drop of events on a catalogue
r1230 #include <Catalogue/CatalogueController.h>
Change the event model to a treeview model + update the last version of CatalogueAPI
r1149 #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
r1162 Q_LOGGING_CATEGORY(LOG_CatalogueEventsModel, "CatalogueEventsModel")
Change the event model to a treeview model + update the last version of CatalogueAPI
r1149 const auto EVENT_ITEM_TYPE = 1;
const auto EVENT_PRODUCT_ITEM_TYPE = 2;
Edition of event products via the inspector
r1150 struct CatalogueEventsModel::CatalogueEventsModelPrivate {
Change the event model to a treeview model + update the last version of CatalogueAPI
r1149 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
r1162 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
r1237 auto hasChanges = sqpApp->catalogueController().eventHasChanges(event);
return hasChanges ? true : QVariant();
"Apply" and "cancel" buttons on an event
r1162 }
return eventData(col, event);
Change the event model to a treeview model + update the last version of CatalogueAPI
r1149 }
QVariant eventData(int col, const std::shared_ptr<DBEvent> &event) const
{
switch (static_cast<Column>(col)) {
"Apply" and "cancel" buttons on an event
r1162 case CatalogueEventsModel::Column::Name:
Change the event model to a treeview model + update the last version of CatalogueAPI
r1149 return event->getName();
"Apply" and "cancel" buttons on an event
r1162 case CatalogueEventsModel::Column::TStart:
Fix display of tstart & tend when an event has no event products
r1161 return nbEventProducts(event) > 0 ? DateUtils::dateTime(event->getTStart())
: QVariant{};
"Apply" and "cancel" buttons on an event
r1162 case CatalogueEventsModel::Column::TEnd:
Fix display of tstart & tend when an event has no event products
r1161 return nbEventProducts(event) > 0 ? DateUtils::dateTime(event->getTEnd())
: QVariant{};
"Apply" and "cancel" buttons on an event
r1162 case CatalogueEventsModel::Column::Product:
Fix display of tstart & tend when an event has no event products
r1161 return QString::number(nbEventProducts(event)) + " product(s)";
"Apply" and "cancel" buttons on an event
r1162 case CatalogueEventsModel::Column::Tags: {
Change the event model to a treeview model + update the last version of CatalogueAPI
r1149 QString tagList;
auto tags = event->getTags();
for (auto tag : tags) {
tagList += tag.getName();
tagList += ' ';
}
return tagList;
}
"Apply" and "cancel" buttons on an event
r1162 case CatalogueEventsModel::Column::Validation:
return QVariant();
Change the event model to a treeview model + update the last version of CatalogueAPI
r1149 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
r1161 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
r1149 QVariant eventProductData(int col, const std::shared_ptr<DBEventProduct> &eventProduct) const
{
switch (static_cast<Column>(col)) {
"Apply" and "cancel" buttons on an event
r1162 case CatalogueEventsModel::Column::Name:
Change the event model to a treeview model + update the last version of CatalogueAPI
r1149 return eventProduct->getProductId();
"Apply" and "cancel" buttons on an event
r1162 case CatalogueEventsModel::Column::TStart:
Change the event model to a treeview model + update the last version of CatalogueAPI
r1149 return DateUtils::dateTime(eventProduct->getTStart());
"Apply" and "cancel" buttons on an event
r1162 case CatalogueEventsModel::Column::TEnd:
Change the event model to a treeview model + update the last version of CatalogueAPI
r1149 return DateUtils::dateTime(eventProduct->getTEnd());
"Apply" and "cancel" buttons on an event
r1162 case CatalogueEventsModel::Column::Product:
Change the event model to a treeview model + update the last version of CatalogueAPI
r1149 return eventProduct->getProductId();
"Apply" and "cancel" buttons on an event
r1162 case CatalogueEventsModel::Column::Tags:
Change the event model to a treeview model + update the last version of CatalogueAPI
r1149 return QString();
"Apply" and "cancel" buttons on an event
r1162 case CatalogueEventsModel::Column::Validation:
return QVariant();
Change the event model to a treeview model + update the last version of CatalogueAPI
r1149 default:
break;
}
Q_ASSERT(false);
return QStringLiteral("Unknown Data");
}
Fix sorting with event products
r1233
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
r1149 };
CatalogueEventsModel::CatalogueEventsModel(QObject *parent)
Edition of event products via the inspector
r1150 : QAbstractItemModel(parent), impl{spimpl::make_unique_impl<CatalogueEventsModelPrivate>()}
Change the event model to a treeview model + update the last version of CatalogueAPI
r1149 {
}
void CatalogueEventsModel::setEvents(const QVector<std::shared_ptr<DBEvent> > &events)
{
beginResetModel();
impl->m_Events = events;
Edition of event products via the inspector
r1150 impl->m_EventProducts.clear();
Change the event model to a treeview model + update the last version of CatalogueAPI
r1149 for (auto event : events) {
impl->parseEventProduct(event);
}
endResetModel();
}
Edition of event products via the inspector
r1150 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
r1149 {
Edition of event products via the inspector
r1150 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
r1149 }
void CatalogueEventsModel::addEvent(const std::shared_ptr<DBEvent> &event)
{
Fix sorting with event products
r1233 beginInsertRows(QModelIndex(), impl->m_Events.count(), impl->m_Events.count());
Change the event model to a treeview model + update the last version of CatalogueAPI
r1149 impl->m_Events.append(event);
impl->parseEventProduct(event);
endInsertRows();
Fix sorting with event products
r1233
// 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
r1149 }
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
r1162 QVector<std::shared_ptr<DBEvent> > CatalogueEventsModel::events() const
{
return impl->m_Events;
}
fix refresh of events after a discard
r1245 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
r1149 {
"Apply" and "cancel" buttons on an event
r1162 auto eventIndex = indexOf(event);
if (eventIndex.isValid()) {
fix refresh of events after a discard
r1245 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
r1162 // Refreshes the event line
Edition of event products via the inspector
r1150 auto colCount = columnCount();
"Apply" and "cancel" buttons on an event
r1162 emit dataChanged(eventIndex, index(eventIndex.row(), colCount));
Edition of event products via the inspector
r1150
"Apply" and "cancel" buttons on an event
r1162 // Also refreshes its children event products
Fix sorting with event products
r1233 impl->refreshChildrenOfIndex(this, eventIndex);
Change the event model to a treeview model + update the last version of CatalogueAPI
r1149 }
"Apply" and "cancel" buttons on an event
r1162 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
r1149 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
r1150 switch (itemTypeOf(parent)) {
case CatalogueEventsModel::ItemType::Root:
Change the event model to a treeview model + update the last version of CatalogueAPI
r1149 return createIndex(row, column);
Edition of event products via the inspector
r1150 case CatalogueEventsModel::ItemType::Event: {
auto event = getEvent(parent);
Change the event model to a treeview model + update the last version of CatalogueAPI
r1149 return createIndex(row, column, event.get());
}
Edition of event products via the inspector
r1150 case CatalogueEventsModel::ItemType::EventProduct:
Change the event model to a treeview model + update the last version of CatalogueAPI
r1149 break;
default:
break;
}
return QModelIndex();
}
QModelIndex CatalogueEventsModel::parent(const QModelIndex &index) const
{
Edition of event products via the inspector
r1150 switch (itemTypeOf(index)) {
case CatalogueEventsModel::ItemType::EventProduct: {
Change the event model to a treeview model + update the last version of CatalogueAPI
r1149 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
r1150 case CatalogueEventsModel::ItemType::Root:
Change the event model to a treeview model + update the last version of CatalogueAPI
r1149 break;
Edition of event products via the inspector
r1150 case CatalogueEventsModel::ItemType::Event:
Change the event model to a treeview model + update the last version of CatalogueAPI
r1149 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
r1150 switch (itemTypeOf(parent)) {
case CatalogueEventsModel::ItemType::Root:
Change the event model to a treeview model + update the last version of CatalogueAPI
r1149 return impl->m_Events.count();
Edition of event products via the inspector
r1150 case CatalogueEventsModel::ItemType::Event: {
auto event = getEvent(parent);
Change the event model to a treeview model + update the last version of CatalogueAPI
r1149 return impl->m_EventProducts[event.get()].count();
}
Edition of event products via the inspector
r1150 case CatalogueEventsModel::ItemType::EventProduct:
Change the event model to a treeview model + update the last version of CatalogueAPI
r1149 break;
default:
break;
}
return 0;
}
int CatalogueEventsModel::columnCount(const QModelIndex &parent) const
{
"Apply" and "cancel" buttons on an event
r1162 return static_cast<int>(CatalogueEventsModel::Column::NbColumn);
Change the event model to a treeview model + update the last version of CatalogueAPI
r1149 }
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
r1150 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
r1149 switch (role) {
case Qt::DisplayRole:
return impl->eventData(index.column(), event);
break;
}
}
Edition of event products via the inspector
r1150 else if (type == CatalogueEventsModel::ItemType::EventProduct) {
auto product = getEventProduct(index);
Change the event model to a treeview model + update the last version of CatalogueAPI
r1149 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
r1233 beginResetModel();
Change the event model to a treeview model + update the last version of CatalogueAPI
r1149 std::sort(impl->m_Events.begin(), impl->m_Events.end(),
[this, column, order](auto e1, auto e2) {
"Apply" and "cancel" buttons on an event
r1162 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
r1149
auto result = data1.toString() < data2.toString();
return order == Qt::AscendingOrder ? result : !result;
});
Fix sorting with event products
r1233 endResetModel();
"Apply" and "cancel" buttons on an event
r1162 emit modelSorted();
Change the event model to a treeview model + update the last version of CatalogueAPI
r1149 }
Qt::DropActions CatalogueEventsModel::supportedDragActions() const
{
Drop of events on a catalogue
r1230 return Qt::CopyAction;
Change the event model to a treeview model + update the last version of CatalogueAPI
r1149 }
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
r1151 bool isFirst = true;
Change the event model to a treeview model + update the last version of CatalogueAPI
r1149 QVector<std::shared_ptr<DBEvent> > eventList;
Fix drag&drop on time widget with event products
r1151 QVector<std::shared_ptr<DBEventProduct> > eventProductList;
Change the event model to a treeview model + update the last version of CatalogueAPI
r1149
SqpRange firstTimeRange;
for (const auto &index : indexes) {
if (index.column() == 0) { // only the first column
Fix drag&drop on time widget with event products
r1151 auto type = itemTypeOf(index);
if (type == ItemType::Event) {
auto event = getEvent(index);
eventList << event;
if (isFirst) {
isFirst = false;
Displays TStart & TEnd for events
r1152 firstTimeRange.m_TStart = event->getTStart();
firstTimeRange.m_TEnd = event->getTEnd();
Fix drag&drop on time widget with event products
r1151 }
}
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
r1149 }
}
Drop of events on a catalogue
r1230 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
r1149
Fix drag&drop on time widget with event products
r1151 if (eventList.count() + eventProductList.count() == 1) {
Change the event model to a treeview model + update the last version of CatalogueAPI
r1149 // 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
r1150
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;
}
}