##// END OF EJS Templates
Implements validation of variable's data (1)...
Implements validation of variable's data (1) Creates helper used to validate data, depending on the server set at compile time

File last commit:

r1162:73d5f3ef941a
r1198:077a4fb03e91
Show More
CatalogueEventsModel.cpp
442 lines | 13.8 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"
#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;
"Apply" and "cancel" buttons on an event
r1162 std::unordered_set<std::shared_ptr<DBEvent> > m_EventsWithChanges;
Change the event model to a treeview model + update the last version of CatalogueAPI
r1149
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) {
return m_EventsWithChanges.find(event) != m_EventsWithChanges.cend() ? true
: QVariant();
}
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");
}
};
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();
"Apply" and "cancel" buttons on an event
r1162 impl->m_EventsWithChanges.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)
{
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());
"Apply" and "cancel" buttons on an event
r1162 impl->m_EventsWithChanges.erase(event);
Change the event model to a treeview model + update the last version of CatalogueAPI
r1149 endRemoveRows();
}
}
"Apply" and "cancel" buttons on an event
r1162 QVector<std::shared_ptr<DBEvent> > CatalogueEventsModel::events() const
{
return impl->m_Events;
}
Change the event model to a treeview model + update the last version of CatalogueAPI
r1149 void CatalogueEventsModel::refreshEvent(const std::shared_ptr<DBEvent> &event)
{
"Apply" and "cancel" buttons on an event
r1162 auto eventIndex = indexOf(event);
if (eventIndex.isValid()) {
// 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
Edition of event products via the inspector
r1150 auto childCount = rowCount(eventIndex);
emit dataChanged(index(0, 0, eventIndex), index(childCount, colCount, 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();
}
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();
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)
{
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;
});
emit dataChanged(QModelIndex(), QModelIndex());
"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
{
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;
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 }
}
auto eventsEncodedData
= QByteArray{}; // sqpApp->catalogueController().->mimeDataForEvents(eventList); //TODO
mimeData->setData(MIME_TYPE_EVENT_LIST, eventsEncodedData);
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;
}
}