##// END OF EJS Templates
Some WIP refactoring, trying to remove TimeController object...
Some WIP refactoring, trying to remove TimeController object SciQLOP core should be usable OOTB without creating controllers objects. Time range should be given on variable creation not taken from a global object. Signed-off-by: Alexis Jeandet <alexis.jeandet@member.fsf.org>

File last commit:

r1315:b20dcec1c57b
r1345:ce477e992869
Show More
CatalogueEventsModel.cpp
484 lines | 15.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;
Move event in catalogue with Drag&Drop
r1308 QVector<std::shared_ptr<DBCatalogue> > m_SourceCatalogue;
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) {
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 bug time precision with catalogue
r1315 return nbEventProducts(event) > 0
? DateUtils::dateTime(event->getTStart())
.toString(DATETIME_FORMAT_ONE_LINE)
: QVariant{};
"Apply" and "cancel" buttons on an event
r1162 case CatalogueEventsModel::Column::TEnd:
Fix bug time precision with catalogue
r1315 return nbEventProducts(event) > 0
? DateUtils::dateTime(event->getTEnd())
.toString(DATETIME_FORMAT_ONE_LINE)
: QVariant{};
Product field now display products event list instead of only its size
r1310 case CatalogueEventsModel::Column::Product: {
auto eventProducts = event->getEventProducts();
QStringList eventProductList;
for (auto evtProduct : eventProducts) {
eventProductList << evtProduct.getProductId();
}
return eventProductList.join(";");
}
"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:
Fix bug time precision with catalogue
r1315 return DateUtils::dateTime(eventProduct->getTStart())
.toString(DATETIME_FORMAT_ONE_LINE);
"Apply" and "cancel" buttons on an event
r1162 case CatalogueEventsModel::Column::TEnd:
Fix bug time precision with catalogue
r1315 return DateUtils::dateTime(eventProduct->getTEnd())
.toString(DATETIME_FORMAT_ONE_LINE);
"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 {
}
Move event in catalogue with Drag&Drop
r1308 void CatalogueEventsModel::setSourceCatalogues(
const QVector<std::shared_ptr<DBCatalogue> > &catalogues)
{
impl->m_SourceCatalogue = catalogues;
}
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
{
Move event in catalogue with Drag&Drop
r1308 return Qt::CopyAction | Qt::MoveAction;
Change the event model to a treeview model + update the last version of CatalogueAPI
r1149 }
QStringList CatalogueEventsModel::mimeTypes() const
{
Move event in catalogue with Drag&Drop
r1308 return {MIME_TYPE_EVENT_LIST, MIME_TYPE_SOURCE_CATALOGUE_LIST, MIME_TYPE_TIME_RANGE};
Change the event model to a treeview model + update the last version of CatalogueAPI
r1149 }
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);
Move event in catalogue with Drag&Drop
r1308
auto sourceCataloguesEncodedData
= sqpApp->catalogueController().mimeDataForCatalogues(impl->m_SourceCatalogue);
mimeData->setData(MIME_TYPE_SOURCE_CATALOGUE_LIST, sourceCataloguesEncodedData);
Drop of events on a catalogue
r1230 }
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;
}
}