##// END OF EJS Templates
"Apply" and "cancel" buttons on an event
trabillard -
r1194:73d5f3ef941a
parent child
Show More
@@ -0,0 +1,13
1 #ifndef SCIQLOP_CATALOGUEEXPLORERHELPER_H
2 #define SCIQLOP_CATALOGUEEXPLORERHELPER_H
3
4 #include <QWidget>
5
6 #include <functional>
7
8 struct CatalogueExplorerHelper {
9 static QWidget *buildValidationWidget(QWidget *parent, std::function<void()> save,
10 std::function<void()> discard);
11 };
12
13 #endif // SCIQLOP_CATALOGUEEXPLORERHELPER_H
@@ -0,0 +1,32
1 #include "Catalogue/CatalogueExplorerHelper.h"
2
3 #include <QBoxLayout>
4 #include <QToolButton>
5
6 const auto VALIDATION_BUTTON_ICON_SIZE = 12;
7
8 QWidget *CatalogueExplorerHelper::buildValidationWidget(QWidget *parent, std::function<void()> save,
9 std::function<void()> discard)
10 {
11 auto widget = new QWidget{parent};
12
13 auto layout = new QHBoxLayout{widget};
14 layout->setContentsMargins(0, 0, 0, 0);
15 layout->setSpacing(0);
16
17 auto btnValid = new QToolButton{widget};
18 btnValid->setIcon(QIcon{":/icones/save"});
19 btnValid->setIconSize(QSize{VALIDATION_BUTTON_ICON_SIZE, VALIDATION_BUTTON_ICON_SIZE});
20 btnValid->setAutoRaise(true);
21 QObject::connect(btnValid, &QToolButton::clicked, save);
22 layout->addWidget(btnValid);
23
24 auto btnDiscard = new QToolButton{widget};
25 btnDiscard->setIcon(QIcon{":/icones/discard"});
26 btnDiscard->setIconSize(QSize{VALIDATION_BUTTON_ICON_SIZE, VALIDATION_BUTTON_ICON_SIZE});
27 btnDiscard->setAutoRaise(true);
28 QObject::connect(btnDiscard, &QToolButton::clicked, discard);
29 layout->addWidget(btnDiscard);
30
31 return widget;
32 }
@@ -1,46 +1,68
1 1 #ifndef SCIQLOP_CATALOGUEEVENTSMODEL_H
2 2 #define SCIQLOP_CATALOGUEEVENTSMODEL_H
3 3
4 4 #include <Common/spimpl.h>
5 5 #include <QAbstractItemModel>
6 #include <QLoggingCategory>
7 #include <unordered_set>
6 8
7 9 class DBEvent;
8 10 class DBEventProduct;
9 11
12 Q_DECLARE_LOGGING_CATEGORY(LOG_CatalogueEventsModel)
13
10 14 class CatalogueEventsModel : public QAbstractItemModel {
15 Q_OBJECT
16
17 signals:
18 void modelSorted();
19
11 20 public:
12 21 CatalogueEventsModel(QObject *parent = nullptr);
13 22
23 enum class Column { Name, TStart, TEnd, Tags, Product, Validation, NbColumn };
24
14 25 void setEvents(const QVector<std::shared_ptr<DBEvent> > &events);
15 26 void addEvent(const std::shared_ptr<DBEvent> &event);
16 27 void removeEvent(const std::shared_ptr<DBEvent> &event);
28 QVector<std::shared_ptr<DBEvent> > events() const;
17 29
18 30 enum class ItemType { Root, Event, EventProduct };
19 31 ItemType itemTypeOf(const QModelIndex &index) const;
20 32 std::shared_ptr<DBEvent> getEvent(const QModelIndex &index) const;
21 33 std::shared_ptr<DBEvent> getParentEvent(const QModelIndex &index) const;
22 34 std::shared_ptr<DBEventProduct> getEventProduct(const QModelIndex &index) const;
23 35
36 /// Refresh the data for the specified event
24 37 void refreshEvent(const std::shared_ptr<DBEvent> &event);
25 38
39 /// Returns a QModelIndex which represent the specified event
40 QModelIndex indexOf(const std::shared_ptr<DBEvent> &event) const;
41
42 /// Marks a change flag on the specified event to allow sorting on the validation column
43 void setEventHasChanges(const std::shared_ptr<DBEvent> &event, bool hasChanges);
44
45 /// Returns true if the specified event has unsaved changes
46 bool eventsHasChanges(const std::shared_ptr<DBEvent> &event) const;
47
26 48 // Model
27 49 QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
28 50 QModelIndex parent(const QModelIndex &index) const;
29 51 int rowCount(const QModelIndex &parent = QModelIndex()) const override;
30 52 int columnCount(const QModelIndex &parent = QModelIndex()) const override;
31 53 Qt::ItemFlags flags(const QModelIndex &index) const override;
32 54 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
33 55 QVariant headerData(int section, Qt::Orientation orientation,
34 56 int role = Qt::DisplayRole) const override;
35 57 void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) override;
36 58
37 59 Qt::DropActions supportedDragActions() const override;
38 60 QStringList mimeTypes() const override;
39 61 QMimeData *mimeData(const QModelIndexList &indexes) const override;
40 62
41 63 private:
42 64 class CatalogueEventsModelPrivate;
43 65 spimpl::unique_impl_ptr<CatalogueEventsModelPrivate> impl;
44 66 };
45 67
46 68 #endif // SCIQLOP_CATALOGUEEVENTSMODEL_H
@@ -1,33 +1,36
1 1 #ifndef SCIQLOP_CATALOGUETREEWIDGETITEM_H
2 2 #define SCIQLOP_CATALOGUETREEWIDGETITEM_H
3 3
4 4 #include <Common/spimpl.h>
5 5 #include <QTreeWidgetItem>
6 6
7 7 class DBCatalogue;
8 8
9 9
10 10 class CatalogueTreeWidgetItem : public QTreeWidgetItem {
11 11 public:
12 12 CatalogueTreeWidgetItem(std::shared_ptr<DBCatalogue> catalogue,
13 13 int type = QTreeWidgetItem::Type);
14 14
15 15 QVariant data(int column, int role) const override;
16 16 void setData(int column, int role, const QVariant &value) override;
17 17
18 18 /// Returns the catalogue represented by the item
19 19 std::shared_ptr<DBCatalogue> catalogue() const;
20 20
21 21 /// Displays or hides the save and cancel buttons indicating that the catalogue has unsaved
22 22 /// changes
23 23 void setHasChanges(bool value);
24 24
25 /// Returns true if the widget indicating the event has unsaved changes is displayed
26 bool hasChanges();
27
25 28 /// Refreshes the data displayed by the item from the catalogue
26 29 void refresh();
27 30
28 31 private:
29 32 class CatalogueTreeWidgetItemPrivate;
30 33 spimpl::unique_impl_ptr<CatalogueTreeWidgetItemPrivate> impl;
31 34 };
32 35
33 36 #endif // SCIQLOP_CATALOGUETREEWIDGETITEM_H
@@ -1,137 +1,139
1 1 qxorm_dep = dependency('QxOrm', required : true, fallback:['QxOrm','qxorm_dep'])
2 2 catalogueapi_dep = dependency('CatalogueAPI', required : true, fallback:['CatalogueAPI','CatalogueAPI_dep'])
3 3
4 4 gui_moc_headers = [
5 5 'include/DataSource/DataSourceWidget.h',
6 6 'include/Settings/SqpSettingsDialog.h',
7 7 'include/Settings/SqpSettingsGeneralWidget.h',
8 8 'include/SidePane/SqpSidePane.h',
9 9 'include/SqpApplication.h',
10 10 'include/DragAndDrop/DragDropScroller.h',
11 11 'include/DragAndDrop/DragDropTabSwitcher.h',
12 12 'include/TimeWidget/TimeWidget.h',
13 13 'include/Variable/VariableInspectorWidget.h',
14 14 'include/Variable/RenameVariableDialog.h',
15 15 'include/Visualization/qcustomplot.h',
16 16 'include/Visualization/VisualizationGraphWidget.h',
17 17 'include/Visualization/VisualizationTabWidget.h',
18 18 'include/Visualization/VisualizationWidget.h',
19 19 'include/Visualization/VisualizationZoneWidget.h',
20 20 'include/Visualization/VisualizationDragDropContainer.h',
21 21 'include/Visualization/VisualizationDragWidget.h',
22 22 'include/Visualization/ColorScaleEditor.h',
23 23 'include/Actions/SelectionZoneAction.h',
24 24 'include/Visualization/VisualizationMultiZoneSelectionDialog.h',
25 25 'include/Catalogue/CatalogueExplorer.h',
26 26 'include/Catalogue/CatalogueEventsWidget.h',
27 27 'include/Catalogue/CatalogueSideBarWidget.h',
28 'include/Catalogue/CatalogueInspectorWidget.h'
28 'include/Catalogue/CatalogueInspectorWidget.h',
29 'include/Catalogue/CatalogueEventsModel.h'
29 30 ]
30 31
31 32 gui_ui_files = [
32 33 'ui/DataSource/DataSourceWidget.ui',
33 34 'ui/Settings/SqpSettingsDialog.ui',
34 35 'ui/Settings/SqpSettingsGeneralWidget.ui',
35 36 'ui/SidePane/SqpSidePane.ui',
36 37 'ui/TimeWidget/TimeWidget.ui',
37 38 'ui/Variable/VariableInspectorWidget.ui',
38 39 'ui/Variable/RenameVariableDialog.ui',
39 40 'ui/Variable/VariableMenuHeaderWidget.ui',
40 41 'ui/Visualization/VisualizationGraphWidget.ui',
41 42 'ui/Visualization/VisualizationTabWidget.ui',
42 43 'ui/Visualization/VisualizationWidget.ui',
43 44 'ui/Visualization/VisualizationZoneWidget.ui',
44 45 'ui/Visualization/ColorScaleEditor.ui',
45 46 'ui/Visualization/VisualizationMultiZoneSelectionDialog.ui',
46 47 'ui/Catalogue/CatalogueExplorer.ui',
47 48 'ui/Catalogue/CatalogueEventsWidget.ui',
48 49 'ui/Catalogue/CatalogueSideBarWidget.ui',
49 50 'ui/Catalogue/CatalogueInspectorWidget.ui'
50 51 ]
51 52
52 53 gui_qresources = ['resources/sqpguiresources.qrc']
53 54
54 55 rcc_gen = generator(rcc,
55 56 output : 'qrc_@BASENAME@.cpp',
56 57 arguments : [
57 58 '--output',
58 59 '@OUTPUT@',
59 60 '@INPUT@',
60 61 '@EXTRA_ARGS@'])
61 62
62 63 rcc_files = rcc_gen.process(gui_qresources, extra_args : ['-name', 'sqpguiresources'])
63 64
64 65 gui_moc_files = qt5.preprocess(moc_headers : gui_moc_headers,
65 66 ui_files : gui_ui_files)
66 67
67 68 gui_sources = [
68 69 'src/SqpApplication.cpp',
69 70 'src/DragAndDrop/DragDropGuiController.cpp',
70 71 'src/DragAndDrop/DragDropScroller.cpp',
71 72 'src/DragAndDrop/DragDropTabSwitcher.cpp',
72 73 'src/Common/ColorUtils.cpp',
73 74 'src/Common/VisualizationDef.cpp',
74 75 'src/DataSource/DataSourceTreeWidgetItem.cpp',
75 76 'src/DataSource/DataSourceTreeWidgetHelper.cpp',
76 77 'src/DataSource/DataSourceWidget.cpp',
77 78 'src/DataSource/DataSourceTreeWidget.cpp',
78 79 'src/Settings/SqpSettingsDialog.cpp',
79 80 'src/Settings/SqpSettingsGeneralWidget.cpp',
80 81 'src/SidePane/SqpSidePane.cpp',
81 82 'src/TimeWidget/TimeWidget.cpp',
82 83 'src/Variable/VariableInspectorWidget.cpp',
83 84 'src/Variable/VariableInspectorTableView.cpp',
84 85 'src/Variable/VariableMenuHeaderWidget.cpp',
85 86 'src/Variable/RenameVariableDialog.cpp',
86 87 'src/Visualization/VisualizationGraphHelper.cpp',
87 88 'src/Visualization/VisualizationGraphRenderingDelegate.cpp',
88 89 'src/Visualization/VisualizationGraphWidget.cpp',
89 90 'src/Visualization/VisualizationTabWidget.cpp',
90 91 'src/Visualization/VisualizationWidget.cpp',
91 92 'src/Visualization/VisualizationZoneWidget.cpp',
92 93 'src/Visualization/qcustomplot.cpp',
93 94 'src/Visualization/QCustomPlotSynchronizer.cpp',
94 95 'src/Visualization/operations/FindVariableOperation.cpp',
95 96 'src/Visualization/operations/GenerateVariableMenuOperation.cpp',
96 97 'src/Visualization/operations/MenuBuilder.cpp',
97 98 'src/Visualization/operations/RemoveVariableOperation.cpp',
98 99 'src/Visualization/operations/RescaleAxeOperation.cpp',
99 100 'src/Visualization/VisualizationDragDropContainer.cpp',
100 101 'src/Visualization/VisualizationDragWidget.cpp',
101 102 'src/Visualization/AxisRenderingUtils.cpp',
102 103 'src/Visualization/PlottablesRenderingUtils.cpp',
103 104 'src/Visualization/MacScrollBarStyle.cpp',
104 105 'src/Visualization/VisualizationCursorItem.cpp',
105 106 'src/Visualization/ColorScaleEditor.cpp',
106 107 'src/Visualization/SqpColorScale.cpp',
107 108 'src/Visualization/QCPColorMapIterator.cpp',
108 109 'src/Visualization/VisualizationSelectionZoneItem.cpp',
109 110 'src/Visualization/VisualizationSelectionZoneManager.cpp',
110 111 'src/Actions/SelectionZoneAction.cpp',
111 112 'src/Actions/ActionsGuiController.cpp',
112 113 'src/Visualization/VisualizationActionManager.cpp',
113 114 'src/Visualization/VisualizationMultiZoneSelectionDialog.cpp',
114 115 'src/Catalogue/CatalogueExplorer.cpp',
115 116 'src/Catalogue/CatalogueEventsWidget.cpp',
116 117 'src/Catalogue/CatalogueSideBarWidget.cpp',
117 118 'src/Catalogue/CatalogueInspectorWidget.cpp',
118 119 'src/Catalogue/CatalogueTreeWidgetItem.cpp',
119 'src/Catalogue/CatalogueEventsModel.cpp'
120 'src/Catalogue/CatalogueEventsModel.cpp',
121 'src/Catalogue/CatalogueExplorerHelper.cpp'
120 122 ]
121 123
122 124 gui_inc = include_directories(['include'])
123 125
124 126 sciqlop_gui_lib = library('sciqlopgui',
125 127 gui_sources,
126 128 gui_moc_files,
127 129 rcc_files,
128 130 include_directories : [gui_inc],
129 131 dependencies : [ qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core, catalogueapi_dep],
130 132 install : true
131 133 )
132 134
133 135 sciqlop_gui = declare_dependency(link_with : sciqlop_gui_lib,
134 136 include_directories : gui_inc,
135 137 dependencies : [qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core, catalogueapi_dep])
136 138
137 139
@@ -1,387 +1,442
1 1 #include "Catalogue/CatalogueEventsModel.h"
2 2
3 3 #include <Common/DateUtils.h>
4 4 #include <Common/MimeTypesDef.h>
5 5 #include <DBEvent.h>
6 6 #include <DBEventProduct.h>
7 7 #include <DBTag.h>
8 8 #include <Data/SqpRange.h>
9 9 #include <SqpApplication.h>
10 10 #include <Time/TimeController.h>
11 11
12 12 #include <list>
13 13 #include <unordered_map>
14 14
15 15 #include <QHash>
16 16 #include <QMimeData>
17 17
18 Q_LOGGING_CATEGORY(LOG_CatalogueEventsModel, "CatalogueEventsModel")
19
18 20 const auto EVENT_ITEM_TYPE = 1;
19 21 const auto EVENT_PRODUCT_ITEM_TYPE = 2;
20 22
21 23 struct CatalogueEventsModel::CatalogueEventsModelPrivate {
22 24 QVector<std::shared_ptr<DBEvent> > m_Events;
23 25 std::unordered_map<DBEvent *, QVector<std::shared_ptr<DBEventProduct> > > m_EventProducts;
26 std::unordered_set<std::shared_ptr<DBEvent> > m_EventsWithChanges;
24 27
25 enum class Column { Name, TStart, TEnd, Tags, Product, NbColumn };
26 28 QStringList columnNames()
27 29 {
28 return QStringList{tr("Event"), tr("TStart"), tr("TEnd"), tr("Tags"), tr("Product")};
30 return QStringList{tr("Event"), tr("TStart"), tr("TEnd"),
31 tr("Tags"), tr("Product"), tr("")};
32 }
33
34 QVariant sortData(int col, const std::shared_ptr<DBEvent> &event) const
35 {
36 if (col == (int)CatalogueEventsModel::Column::Validation) {
37 return m_EventsWithChanges.find(event) != m_EventsWithChanges.cend() ? true
38 : QVariant();
39 }
40
41 return eventData(col, event);
29 42 }
30 43
31 44 QVariant eventData(int col, const std::shared_ptr<DBEvent> &event) const
32 45 {
33 46 switch (static_cast<Column>(col)) {
34 case Column::Name:
47 case CatalogueEventsModel::Column::Name:
35 48 return event->getName();
36 case Column::TStart:
49 case CatalogueEventsModel::Column::TStart:
37 50 return nbEventProducts(event) > 0 ? DateUtils::dateTime(event->getTStart())
38 51 : QVariant{};
39 case Column::TEnd:
52 case CatalogueEventsModel::Column::TEnd:
40 53 return nbEventProducts(event) > 0 ? DateUtils::dateTime(event->getTEnd())
41 54 : QVariant{};
42 case Column::Product:
55 case CatalogueEventsModel::Column::Product:
43 56 return QString::number(nbEventProducts(event)) + " product(s)";
44 case Column::Tags: {
57 case CatalogueEventsModel::Column::Tags: {
45 58 QString tagList;
46 59 auto tags = event->getTags();
47 60 for (auto tag : tags) {
48 61 tagList += tag.getName();
49 62 tagList += ' ';
50 63 }
51 64
52 65 return tagList;
53 66 }
67 case CatalogueEventsModel::Column::Validation:
68 return QVariant();
54 69 default:
55 70 break;
56 71 }
57 72
58 73 Q_ASSERT(false);
59 74 return QStringLiteral("Unknown Data");
60 75 }
61 76
62 77 void parseEventProduct(const std::shared_ptr<DBEvent> &event)
63 78 {
64 79 for (auto product : event->getEventProducts()) {
65 80 m_EventProducts[event.get()].append(std::make_shared<DBEventProduct>(product));
66 81 }
67 82 }
68 83
69 84 int nbEventProducts(const std::shared_ptr<DBEvent> &event) const
70 85 {
71 86 auto eventProductsIt = m_EventProducts.find(event.get());
72 87 if (eventProductsIt != m_EventProducts.cend()) {
73 88 return m_EventProducts.at(event.get()).count();
74 89 }
75 90 else {
76 91 return 0;
77 92 }
78 93 }
79 94
80 95 QVariant eventProductData(int col, const std::shared_ptr<DBEventProduct> &eventProduct) const
81 96 {
82 97 switch (static_cast<Column>(col)) {
83 case Column::Name:
98 case CatalogueEventsModel::Column::Name:
84 99 return eventProduct->getProductId();
85 case Column::TStart:
100 case CatalogueEventsModel::Column::TStart:
86 101 return DateUtils::dateTime(eventProduct->getTStart());
87 case Column::TEnd:
102 case CatalogueEventsModel::Column::TEnd:
88 103 return DateUtils::dateTime(eventProduct->getTEnd());
89 case Column::Product:
104 case CatalogueEventsModel::Column::Product:
90 105 return eventProduct->getProductId();
91 case Column::Tags: {
106 case CatalogueEventsModel::Column::Tags:
92 107 return QString();
93 }
108 case CatalogueEventsModel::Column::Validation:
109 return QVariant();
94 110 default:
95 111 break;
96 112 }
97 113
98 114 Q_ASSERT(false);
99 115 return QStringLiteral("Unknown Data");
100 116 }
101 117 };
102 118
103 119 CatalogueEventsModel::CatalogueEventsModel(QObject *parent)
104 120 : QAbstractItemModel(parent), impl{spimpl::make_unique_impl<CatalogueEventsModelPrivate>()}
105 121 {
106 122 }
107 123
108 124 void CatalogueEventsModel::setEvents(const QVector<std::shared_ptr<DBEvent> > &events)
109 125 {
110 126 beginResetModel();
111 127
112 128 impl->m_Events = events;
113 129 impl->m_EventProducts.clear();
130 impl->m_EventsWithChanges.clear();
114 131 for (auto event : events) {
115 132 impl->parseEventProduct(event);
116 133 }
117 134
118 135 endResetModel();
119 136 }
120 137
121 138 std::shared_ptr<DBEvent> CatalogueEventsModel::getEvent(const QModelIndex &index) const
122 139 {
123 140 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::Event) {
124 141 return impl->m_Events.value(index.row());
125 142 }
126 143 else {
127 144 return nullptr;
128 145 }
129 146 }
130 147
131 148 std::shared_ptr<DBEvent> CatalogueEventsModel::getParentEvent(const QModelIndex &index) const
132 149 {
133 150 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::EventProduct) {
134 151 return getEvent(index.parent());
135 152 }
136 153 else {
137 154 return nullptr;
138 155 }
139 156 }
140 157
141 158 std::shared_ptr<DBEventProduct>
142 159 CatalogueEventsModel::getEventProduct(const QModelIndex &index) const
143 160 {
144 161 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::EventProduct) {
145 162 auto event = static_cast<DBEvent *>(index.internalPointer());
146 163 return impl->m_EventProducts.at(event).value(index.row());
147 164 }
148 165 else {
149 166 return nullptr;
150 167 }
151 168 }
152 169
153 170 void CatalogueEventsModel::addEvent(const std::shared_ptr<DBEvent> &event)
154 171 {
155 172 beginInsertRows(QModelIndex(), impl->m_Events.count() - 1, impl->m_Events.count() - 1);
156 173 impl->m_Events.append(event);
157 174 impl->parseEventProduct(event);
158 175 endInsertRows();
159 176 }
160 177
161 178 void CatalogueEventsModel::removeEvent(const std::shared_ptr<DBEvent> &event)
162 179 {
163 180 auto index = impl->m_Events.indexOf(event);
164 181 if (index >= 0) {
165 182 beginRemoveRows(QModelIndex(), index, index);
166 183 impl->m_Events.removeAt(index);
167 184 impl->m_EventProducts.erase(event.get());
185 impl->m_EventsWithChanges.erase(event);
168 186 endRemoveRows();
169 187 }
170 188 }
171 189
190 QVector<std::shared_ptr<DBEvent> > CatalogueEventsModel::events() const
191 {
192 return impl->m_Events;
193 }
194
172 195 void CatalogueEventsModel::refreshEvent(const std::shared_ptr<DBEvent> &event)
173 196 {
174 auto i = impl->m_Events.indexOf(event);
175 if (i >= 0) {
176 auto eventIndex = index(i, 0);
197 auto eventIndex = indexOf(event);
198 if (eventIndex.isValid()) {
199
200 // Refreshes the event line
177 201 auto colCount = columnCount();
178 emit dataChanged(eventIndex, index(i, colCount));
202 emit dataChanged(eventIndex, index(eventIndex.row(), colCount));
179 203
204 // Also refreshes its children event products
180 205 auto childCount = rowCount(eventIndex);
181 206 emit dataChanged(index(0, 0, eventIndex), index(childCount, colCount, eventIndex));
182 207 }
208 else {
209 qCWarning(LOG_CatalogueEventsModel()) << "refreshEvent: event not found.";
210 }
211 }
212
213 QModelIndex CatalogueEventsModel::indexOf(const std::shared_ptr<DBEvent> &event) const
214 {
215 auto row = impl->m_Events.indexOf(event);
216 if (row >= 0) {
217 return index(row, 0);
218 }
219
220 return QModelIndex();
221 }
222
223 void CatalogueEventsModel::setEventHasChanges(const std::shared_ptr<DBEvent> &event,
224 bool hasChanges)
225 {
226 if (hasChanges) {
227 impl->m_EventsWithChanges.insert(event);
228 }
229 else {
230 impl->m_EventsWithChanges.erase(event);
231 }
232 }
233
234 bool CatalogueEventsModel::eventsHasChanges(const std::shared_ptr<DBEvent> &event) const
235 {
236 return impl->m_EventsWithChanges.find(event) != impl->m_EventsWithChanges.cend();
183 237 }
184 238
185 239 QModelIndex CatalogueEventsModel::index(int row, int column, const QModelIndex &parent) const
186 240 {
187 241 if (!hasIndex(row, column, parent)) {
188 242 return QModelIndex();
189 243 }
190 244
191 245 switch (itemTypeOf(parent)) {
192 246 case CatalogueEventsModel::ItemType::Root:
193 247 return createIndex(row, column);
194 248 case CatalogueEventsModel::ItemType::Event: {
195 249 auto event = getEvent(parent);
196 250 return createIndex(row, column, event.get());
197 251 }
198 252 case CatalogueEventsModel::ItemType::EventProduct:
199 253 break;
200 254 default:
201 255 break;
202 256 }
203 257
204 258 return QModelIndex();
205 259 }
206 260
207 261 QModelIndex CatalogueEventsModel::parent(const QModelIndex &index) const
208 262 {
209 263 switch (itemTypeOf(index)) {
210 264 case CatalogueEventsModel::ItemType::EventProduct: {
211 265 auto parentEvent = static_cast<DBEvent *>(index.internalPointer());
212 266 auto it
213 267 = std::find_if(impl->m_Events.cbegin(), impl->m_Events.cend(),
214 268 [parentEvent](auto event) { return event.get() == parentEvent; });
215 269
216 270 if (it != impl->m_Events.cend()) {
217 271 return createIndex(it - impl->m_Events.cbegin(), 0);
218 272 }
219 273 else {
220 274 return QModelIndex();
221 275 }
222 276 }
223 277 case CatalogueEventsModel::ItemType::Root:
224 278 break;
225 279 case CatalogueEventsModel::ItemType::Event:
226 280 break;
227 281 default:
228 282 break;
229 283 }
230 284
231 285 return QModelIndex();
232 286 }
233 287
234 288 int CatalogueEventsModel::rowCount(const QModelIndex &parent) const
235 289 {
236 290 if (parent.column() > 0) {
237 291 return 0;
238 292 }
239 293
240 294 switch (itemTypeOf(parent)) {
241 295 case CatalogueEventsModel::ItemType::Root:
242 296 return impl->m_Events.count();
243 297 case CatalogueEventsModel::ItemType::Event: {
244 298 auto event = getEvent(parent);
245 299 return impl->m_EventProducts[event.get()].count();
246 300 }
247 301 case CatalogueEventsModel::ItemType::EventProduct:
248 302 break;
249 303 default:
250 304 break;
251 305 }
252 306
253 307 return 0;
254 308 }
255 309
256 310 int CatalogueEventsModel::columnCount(const QModelIndex &parent) const
257 311 {
258 return static_cast<int>(CatalogueEventsModelPrivate::Column::NbColumn);
312 return static_cast<int>(CatalogueEventsModel::Column::NbColumn);
259 313 }
260 314
261 315 Qt::ItemFlags CatalogueEventsModel::flags(const QModelIndex &index) const
262 316 {
263 317 return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
264 318 }
265 319
266 320 QVariant CatalogueEventsModel::data(const QModelIndex &index, int role) const
267 321 {
268 322 if (index.isValid()) {
269 323
270 324 auto type = itemTypeOf(index);
271 325 if (type == CatalogueEventsModel::ItemType::Event) {
272 326 auto event = getEvent(index);
273 327 switch (role) {
274 328 case Qt::DisplayRole:
275 329 return impl->eventData(index.column(), event);
276 330 break;
277 331 }
278 332 }
279 333 else if (type == CatalogueEventsModel::ItemType::EventProduct) {
280 334 auto product = getEventProduct(index);
281 335 switch (role) {
282 336 case Qt::DisplayRole:
283 337 return impl->eventProductData(index.column(), product);
284 338 break;
285 339 }
286 340 }
287 341 }
288 342
289 343 return QVariant{};
290 344 }
291 345
292 346 QVariant CatalogueEventsModel::headerData(int section, Qt::Orientation orientation, int role) const
293 347 {
294 348 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
295 349 return impl->columnNames().value(section);
296 350 }
297 351
298 352 return QVariant();
299 353 }
300 354
301 355 void CatalogueEventsModel::sort(int column, Qt::SortOrder order)
302 356 {
303 357 std::sort(impl->m_Events.begin(), impl->m_Events.end(),
304 358 [this, column, order](auto e1, auto e2) {
305 auto data1 = impl->eventData(column, e1);
306 auto data2 = impl->eventData(column, e2);
359 auto data1 = impl->sortData(column, e1);
360 auto data2 = impl->sortData(column, e2);
307 361
308 362 auto result = data1.toString() < data2.toString();
309 363
310 364 return order == Qt::AscendingOrder ? result : !result;
311 365 });
312 366
313 367 emit dataChanged(QModelIndex(), QModelIndex());
368 emit modelSorted();
314 369 }
315 370
316 371 Qt::DropActions CatalogueEventsModel::supportedDragActions() const
317 372 {
318 373 return Qt::CopyAction | Qt::MoveAction;
319 374 }
320 375
321 376 QStringList CatalogueEventsModel::mimeTypes() const
322 377 {
323 378 return {MIME_TYPE_EVENT_LIST, MIME_TYPE_TIME_RANGE};
324 379 }
325 380
326 381 QMimeData *CatalogueEventsModel::mimeData(const QModelIndexList &indexes) const
327 382 {
328 383 auto mimeData = new QMimeData;
329 384
330 385 bool isFirst = true;
331 386
332 387 QVector<std::shared_ptr<DBEvent> > eventList;
333 388 QVector<std::shared_ptr<DBEventProduct> > eventProductList;
334 389
335 390 SqpRange firstTimeRange;
336 391 for (const auto &index : indexes) {
337 392 if (index.column() == 0) { // only the first column
338 393
339 394 auto type = itemTypeOf(index);
340 395 if (type == ItemType::Event) {
341 396 auto event = getEvent(index);
342 397 eventList << event;
343 398
344 399 if (isFirst) {
345 400 isFirst = false;
346 401 firstTimeRange.m_TStart = event->getTStart();
347 402 firstTimeRange.m_TEnd = event->getTEnd();
348 403 }
349 404 }
350 405 else if (type == ItemType::EventProduct) {
351 406 auto product = getEventProduct(index);
352 407 eventProductList << product;
353 408
354 409 if (isFirst) {
355 410 isFirst = false;
356 411 firstTimeRange.m_TStart = product->getTStart();
357 412 firstTimeRange.m_TEnd = product->getTEnd();
358 413 }
359 414 }
360 415 }
361 416 }
362 417
363 418 auto eventsEncodedData
364 419 = QByteArray{}; // sqpApp->catalogueController().->mimeDataForEvents(eventList); //TODO
365 420 mimeData->setData(MIME_TYPE_EVENT_LIST, eventsEncodedData);
366 421
367 422 if (eventList.count() + eventProductList.count() == 1) {
368 423 // No time range MIME data if multiple events are dragged
369 424 auto timeEncodedData = TimeController::mimeDataForTimeRange(firstTimeRange);
370 425 mimeData->setData(MIME_TYPE_TIME_RANGE, timeEncodedData);
371 426 }
372 427
373 428 return mimeData;
374 429 }
375 430
376 431 CatalogueEventsModel::ItemType CatalogueEventsModel::itemTypeOf(const QModelIndex &index) const
377 432 {
378 433 if (!index.isValid()) {
379 434 return ItemType::Root;
380 435 }
381 436 else if (index.internalPointer() == nullptr) {
382 437 return ItemType::Event;
383 438 }
384 439 else {
385 440 return ItemType::EventProduct;
386 441 }
387 442 }
@@ -1,328 +1,360
1 1 #include "Catalogue/CatalogueEventsWidget.h"
2 2 #include "ui_CatalogueEventsWidget.h"
3 3
4 4 #include <Catalogue/CatalogueController.h>
5 5 #include <Catalogue/CatalogueEventsModel.h>
6 #include <Catalogue/CatalogueExplorerHelper.h>
6 7 #include <CatalogueDao.h>
7 8 #include <DBCatalogue.h>
8 9 #include <SqpApplication.h>
9 10 #include <Visualization/VisualizationTabWidget.h>
10 11 #include <Visualization/VisualizationWidget.h>
11 12 #include <Visualization/VisualizationZoneWidget.h>
12 13
13 14 #include <QDialog>
14 15 #include <QDialogButtonBox>
15 16 #include <QListWidget>
16 17
17 18 Q_LOGGING_CATEGORY(LOG_CatalogueEventsWidget, "CatalogueEventsWidget")
18 19
19 /// Format of the dates appearing in the label of a cursor
20 const auto DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd hh:mm:ss");
20 /// Fixed size of the validation column
21 const auto VALIDATION_COLUMN_SIZE = 35;
21 22
22 23 struct CatalogueEventsWidget::CatalogueEventsWidgetPrivate {
23 24
24 25 CatalogueEventsModel *m_Model = nullptr;
25 26 QStringList m_ZonesForTimeMode;
26 27 QString m_ZoneForGraphMode;
27 28
28 29 VisualizationWidget *m_VisualizationWidget = nullptr;
29 30
30 31 void setEvents(const QVector<std::shared_ptr<DBEvent> > &events, QTreeView *treeView)
31 32 {
32 33 treeView->setSortingEnabled(false);
33 34 m_Model->setEvents(events);
34 35 treeView->setSortingEnabled(true);
35 36 }
36 37
37 38 void addEvent(const std::shared_ptr<DBEvent> &event, QTreeView *treeView)
38 39 {
39 40 treeView->setSortingEnabled(false);
40 41 m_Model->addEvent(event);
41 42 treeView->setSortingEnabled(true);
42 43 }
43 44
44 45 void removeEvent(const std::shared_ptr<DBEvent> &event, QTreeView *treeView)
45 46 {
46 47 treeView->setSortingEnabled(false);
47 48 m_Model->removeEvent(event);
48 49 treeView->setSortingEnabled(true);
49 50 }
50 51
51 52 QStringList getAvailableVisualizationZoneList() const
52 53 {
53 54 if (m_VisualizationWidget) {
54 55 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
55 56 return tab->availableZoneWidgets();
56 57 }
57 58 }
58 59
59 60 return QStringList{};
60 61 }
61 62
62 63 QStringList selectZone(QWidget *parent, const QStringList &selectedZones,
63 64 bool allowMultiSelection, const QPoint &location)
64 65 {
65 66 auto availableZones = getAvailableVisualizationZoneList();
66 67 if (availableZones.isEmpty()) {
67 68 return QStringList{};
68 69 }
69 70
70 71 QDialog d(parent, Qt::Tool);
71 72 d.setWindowTitle("Choose a zone");
72 73 auto layout = new QVBoxLayout{&d};
73 74 layout->setContentsMargins(0, 0, 0, 0);
74 75 auto listWidget = new QListWidget{&d};
75 76 layout->addWidget(listWidget);
76 77
77 78 QSet<QListWidgetItem *> checkedItems;
78 79 for (auto zone : availableZones) {
79 80 auto item = new QListWidgetItem{zone};
80 81 item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsUserCheckable);
81 82 if (selectedZones.contains(zone)) {
82 83 item->setCheckState(Qt::Checked);
83 84 checkedItems << item;
84 85 }
85 86 else {
86 87 item->setCheckState(Qt::Unchecked);
87 88 }
88 89
89 90 listWidget->addItem(item);
90 91 }
91 92
92 93 auto buttonBox = new QDialogButtonBox{QDialogButtonBox::Ok, &d};
93 94 layout->addWidget(buttonBox);
94 95
95 96 QObject::connect(buttonBox, &QDialogButtonBox::accepted, &d, &QDialog::accept);
96 97 QObject::connect(buttonBox, &QDialogButtonBox::rejected, &d, &QDialog::reject);
97 98
98 99 QObject::connect(listWidget, &QListWidget::itemChanged,
99 100 [&checkedItems, allowMultiSelection, listWidget](auto item) {
100 101 if (item->checkState() == Qt::Checked) {
101 102 if (!allowMultiSelection) {
102 103 for (auto checkedItem : checkedItems) {
103 104 listWidget->blockSignals(true);
104 105 checkedItem->setCheckState(Qt::Unchecked);
105 106 listWidget->blockSignals(false);
106 107 }
107 108
108 109 checkedItems.clear();
109 110 }
110 111 checkedItems << item;
111 112 }
112 113 else {
113 114 checkedItems.remove(item);
114 115 }
115 116 });
116 117
117 118 QStringList result;
118 119
119 120 d.setMinimumWidth(120);
120 121 d.resize(d.minimumSizeHint());
121 122 d.move(location);
122 123 if (d.exec() == QDialog::Accepted) {
123 124 for (auto item : checkedItems) {
124 125 result += item->text();
125 126 }
126 127 }
127 128 else {
128 129 result = selectedZones;
129 130 }
130 131
131 132 return result;
132 133 }
133 134
134 135 void updateForTimeMode(QTreeView *treeView)
135 136 {
136 137 auto selectedRows = treeView->selectionModel()->selectedRows();
137 138
138 139 if (selectedRows.count() == 1) {
139 140 auto event = m_Model->getEvent(selectedRows.first());
140 141 if (event) {
141 142 if (m_VisualizationWidget) {
142 143 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
143 144
144 145 for (auto zoneName : m_ZonesForTimeMode) {
145 146 if (auto zone = tab->getZoneWithName(zoneName)) {
146 147 SqpRange eventRange;
147 148 eventRange.m_TStart = event->getTStart();
148 149 eventRange.m_TEnd = event->getTEnd();
149 150 zone->setZoneRange(eventRange);
150 151 }
151 152 }
152 153 }
153 154 else {
154 155 qCWarning(LOG_CatalogueEventsWidget())
155 156 << "updateTimeZone: no tab found in the visualization";
156 157 }
157 158 }
158 159 else {
159 160 qCWarning(LOG_CatalogueEventsWidget())
160 161 << "updateTimeZone: visualization widget not found";
161 162 }
162 163 }
163 164 }
164 165 else {
165 166 qCWarning(LOG_CatalogueEventsWidget())
166 167 << "updateTimeZone: not compatible with multiple events selected";
167 168 }
168 169 }
169 170
170 171 void updateForGraphMode(QTreeView *treeView)
171 172 {
172 173 auto selectedRows = treeView->selectionModel()->selectedRows();
173 174
174 175 if (selectedRows.count() == 1) {
175 176 auto event = m_Model->getEvent(selectedRows.first());
176 177 if (m_VisualizationWidget) {
177 178 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
178 179 if (auto zone = tab->getZoneWithName(m_ZoneForGraphMode)) {
179 180 // TODO
180 181 }
181 182 }
182 183 else {
183 184 qCWarning(LOG_CatalogueEventsWidget())
184 185 << "updateGraphMode: no tab found in the visualization";
185 186 }
186 187 }
187 188 else {
188 189 qCWarning(LOG_CatalogueEventsWidget())
189 190 << "updateGraphMode: visualization widget not found";
190 191 }
191 192 }
192 193 else {
193 194 qCWarning(LOG_CatalogueEventsWidget())
194 195 << "updateGraphMode: not compatible with multiple events selected";
195 196 }
196 197 }
197 198 };
198 199
199 200 CatalogueEventsWidget::CatalogueEventsWidget(QWidget *parent)
200 201 : QWidget(parent),
201 202 ui(new Ui::CatalogueEventsWidget),
202 203 impl{spimpl::make_unique_impl<CatalogueEventsWidgetPrivate>()}
203 204 {
204 205 ui->setupUi(this);
205 206
206 207 impl->m_Model = new CatalogueEventsModel{this};
207 208 ui->treeView->setModel(impl->m_Model);
208 209
209 210 ui->treeView->setSortingEnabled(true);
210 211 ui->treeView->setDragDropMode(QAbstractItemView::DragDrop);
211 212 ui->treeView->setDragEnabled(true);
212 213
213 214 connect(ui->btnTime, &QToolButton::clicked, [this](auto checked) {
214 215 if (checked) {
215 216 ui->btnChart->setChecked(false);
216 217 impl->m_ZonesForTimeMode
217 218 = impl->selectZone(this, impl->m_ZonesForTimeMode, true,
218 219 this->mapToGlobal(ui->btnTime->frameGeometry().center()));
219 220
220 221 impl->updateForTimeMode(ui->treeView);
221 222 }
222 223 });
223 224
224 225 connect(ui->btnChart, &QToolButton::clicked, [this](auto checked) {
225 226 if (checked) {
226 227 ui->btnTime->setChecked(false);
227 228 impl->m_ZoneForGraphMode
228 229 = impl->selectZone(this, {impl->m_ZoneForGraphMode}, false,
229 230 this->mapToGlobal(ui->btnChart->frameGeometry().center()))
230 231 .value(0);
231 232
232 233 impl->updateForGraphMode(ui->treeView);
233 234 }
234 235 });
235 236
236 237 auto emitSelection = [this]() {
237 238 QVector<std::shared_ptr<DBEvent> > events;
238 239 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
239 240
240 241 for (auto rowIndex : ui->treeView->selectionModel()->selectedRows()) {
241 242
242 243 auto itemType = impl->m_Model->itemTypeOf(rowIndex);
243 244 if (itemType == CatalogueEventsModel::ItemType::Event) {
244 245 events << impl->m_Model->getEvent(rowIndex);
245 246 }
246 247 else if (itemType == CatalogueEventsModel::ItemType::EventProduct) {
247 248 eventProducts << qMakePair(impl->m_Model->getParentEvent(rowIndex),
248 249 impl->m_Model->getEventProduct(rowIndex));
249 250 }
250 251 }
251 252
252 253 if (!events.isEmpty() && eventProducts.isEmpty()) {
253 254 emit this->eventsSelected(events);
254 255 }
255 256 else if (events.isEmpty() && !eventProducts.isEmpty()) {
256 257 emit this->eventProductsSelected(eventProducts);
257 258 }
258 259 else {
259 260 emit this->selectionCleared();
260 261 }
261 262 };
262 263
263 264 connect(ui->treeView, &QTreeView::clicked, emitSelection);
264 265 connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, emitSelection);
265 266
266 267 connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, [this]() {
267 268 auto isNotMultiSelection = ui->treeView->selectionModel()->selectedRows().count() <= 1;
268 269 ui->btnChart->setEnabled(isNotMultiSelection);
269 270 ui->btnTime->setEnabled(isNotMultiSelection);
270 271
271 272 if (isNotMultiSelection && ui->btnTime->isChecked()) {
272 273 impl->updateForTimeMode(ui->treeView);
273 274 }
274 275 else if (isNotMultiSelection && ui->btnChart->isChecked()) {
275 276 impl->updateForGraphMode(ui->treeView);
276 277 }
277 278 });
278 279
279 280 ui->treeView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
280 ui->treeView->header()->setSectionResizeMode(0, QHeaderView::Stretch);
281 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Name,
282 QHeaderView::Stretch);
283 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Validation,
284 QHeaderView::Fixed);
285 ui->treeView->header()->resizeSection((int)CatalogueEventsModel::Column::Validation,
286 VALIDATION_COLUMN_SIZE);
281 287 ui->treeView->header()->setSortIndicatorShown(true);
288
289 connect(impl->m_Model, &CatalogueEventsModel::modelSorted, [this]() {
290 auto allEvents = impl->m_Model->events();
291 for (auto event : allEvents) {
292 setEventChanges(event, impl->m_Model->eventsHasChanges(event));
293 }
294 });
282 295 }
283 296
284 297 CatalogueEventsWidget::~CatalogueEventsWidget()
285 298 {
286 299 delete ui;
287 300 }
288 301
289 302 void CatalogueEventsWidget::setVisualizationWidget(VisualizationWidget *visualization)
290 303 {
291 304 impl->m_VisualizationWidget = visualization;
292 305 }
293 306
294 307 void CatalogueEventsWidget::setEventChanges(const std::shared_ptr<DBEvent> &event, bool hasChanges)
295 308 {
296 309 impl->m_Model->refreshEvent(event);
310
311 auto eventIndex = impl->m_Model->indexOf(event);
312 auto validationIndex
313 = eventIndex.sibling(eventIndex.row(), (int)CatalogueEventsModel::Column::Validation);
314
315 if (hasChanges) {
316 if (ui->treeView->indexWidget(validationIndex) == nullptr) {
317 auto widget = CatalogueExplorerHelper::buildValidationWidget(
318 ui->treeView, [this, event]() { setEventChanges(event, false); },
319 [this, event]() { setEventChanges(event, false); });
320 ui->treeView->setIndexWidget(validationIndex, widget);
321 }
322 }
323 else {
324 // Note: the widget is destroyed
325 ui->treeView->setIndexWidget(validationIndex, nullptr);
326 }
327
328 impl->m_Model->setEventHasChanges(event, hasChanges);
297 329 }
298 330
299 331 void CatalogueEventsWidget::populateWithCatalogues(
300 332 const QVector<std::shared_ptr<DBCatalogue> > &catalogues)
301 333 {
302 334 QSet<QUuid> eventIds;
303 335 QVector<std::shared_ptr<DBEvent> > events;
304 336
305 337 for (auto catalogue : catalogues) {
306 338 auto catalogueEvents = sqpApp->catalogueController().retrieveEventsFromCatalogue(catalogue);
307 339 for (auto event : catalogueEvents) {
308 340 if (!eventIds.contains(event->getUniqId())) {
309 341 events << event;
310 342 eventIds.insert(event->getUniqId());
311 343 }
312 344 }
313 345 }
314 346
315 347 impl->setEvents(events, ui->treeView);
316 348 }
317 349
318 350 void CatalogueEventsWidget::populateWithAllEvents()
319 351 {
320 352 auto allEvents = sqpApp->catalogueController().retrieveAllEvents();
321 353
322 354 QVector<std::shared_ptr<DBEvent> > events;
323 355 for (auto event : allEvents) {
324 356 events << event;
325 357 }
326 358
327 359 impl->setEvents(events, ui->treeView);
328 360 }
@@ -1,103 +1,87
1 1 #include "Catalogue/CatalogueTreeWidgetItem.h"
2 #include <Catalogue/CatalogueExplorerHelper.h>
2 3
3 4 #include <memory>
4 5
5 6 #include <DBCatalogue.h>
6 #include <QBoxLayout>
7 #include <QToolButton>
8
9 const auto VALIDATION_BUTTON_ICON_SIZE = 12;
10 7
11 8 /// Column in the tree widget where the apply and cancel buttons must appear
12 9 const auto APPLY_CANCEL_BUTTONS_COLUMN = 1;
13 10
14 11 struct CatalogueTreeWidgetItem::CatalogueTreeWidgetItemPrivate {
15 12
16 13 std::shared_ptr<DBCatalogue> m_Catalogue;
17 14
18 15 CatalogueTreeWidgetItemPrivate(std::shared_ptr<DBCatalogue> catalogue) : m_Catalogue(catalogue)
19 16 {
20 17 }
21 18 };
22 19
23 20
24 21 CatalogueTreeWidgetItem::CatalogueTreeWidgetItem(std::shared_ptr<DBCatalogue> catalogue, int type)
25 22 : QTreeWidgetItem(type),
26 23 impl{spimpl::make_unique_impl<CatalogueTreeWidgetItemPrivate>(catalogue)}
27 24 {
28 25 setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable);
29 26 }
30 27
31 28 QVariant CatalogueTreeWidgetItem::data(int column, int role) const
32 29 {
33 30 if (column == 0) {
34 31 switch (role) {
35 32 case Qt::EditRole: // fallthrough
36 33 case Qt::DisplayRole:
37 34 return impl->m_Catalogue->getName();
38 35 default:
39 36 break;
40 37 }
41 38 }
42 39
43 40 return QTreeWidgetItem::data(column, role);
44 41 }
45 42
46 43 void CatalogueTreeWidgetItem::setData(int column, int role, const QVariant &value)
47 44 {
48 45 if (role == Qt::EditRole && column == 0) {
49 46 auto newName = value.toString();
50 47 if (newName != impl->m_Catalogue->getName()) {
51 48 setText(0, newName);
52 49 impl->m_Catalogue->setName(newName);
53 50 setHasChanges(true);
54 51 }
55 52 }
56 53 else {
57 54 QTreeWidgetItem::setData(column, role, value);
58 55 }
59 56 }
60 57
61 58 std::shared_ptr<DBCatalogue> CatalogueTreeWidgetItem::catalogue() const
62 59 {
63 60 return impl->m_Catalogue;
64 61 }
65 62
66 63 void CatalogueTreeWidgetItem::setHasChanges(bool value)
67 64 {
68 65 if (value) {
69 if (treeWidget()->itemWidget(this, APPLY_CANCEL_BUTTONS_COLUMN) == nullptr) {
70 auto widet = new QWidget{treeWidget()};
71
72 auto layout = new QHBoxLayout{widet};
73 layout->setContentsMargins(0, 0, 0, 0);
74 layout->setSpacing(0);
75
76 auto btnValid = new QToolButton{widet};
77 btnValid->setIcon(QIcon{":/icones/save"});
78 btnValid->setIconSize(QSize{VALIDATION_BUTTON_ICON_SIZE, VALIDATION_BUTTON_ICON_SIZE});
79 btnValid->setAutoRaise(true);
80 QObject::connect(btnValid, &QToolButton::clicked, [this]() { setHasChanges(false); });
81 layout->addWidget(btnValid);
82
83 auto btnDiscard = new QToolButton{widet};
84 btnDiscard->setIcon(QIcon{":/icones/discard"});
85 btnDiscard->setIconSize(
86 QSize{VALIDATION_BUTTON_ICON_SIZE, VALIDATION_BUTTON_ICON_SIZE});
87 btnDiscard->setAutoRaise(true);
88 QObject::connect(btnDiscard, &QToolButton::clicked, [this]() { setHasChanges(false); });
89 layout->addWidget(btnDiscard);
90
91 treeWidget()->setItemWidget(this, APPLY_CANCEL_BUTTONS_COLUMN, {widet});
66 if (!hasChanges()) {
67 auto widget = CatalogueExplorerHelper::buildValidationWidget(
68 treeWidget(), [this]() { setHasChanges(false); },
69 [this]() { setHasChanges(false); });
70 treeWidget()->setItemWidget(this, APPLY_CANCEL_BUTTONS_COLUMN, widget);
92 71 }
93 72 }
94 73 else {
95 74 // Note: the widget is destroyed
96 75 treeWidget()->setItemWidget(this, APPLY_CANCEL_BUTTONS_COLUMN, nullptr);
97 76 }
98 77 }
99 78
79 bool CatalogueTreeWidgetItem::hasChanges()
80 {
81 return treeWidget()->itemWidget(this, APPLY_CANCEL_BUTTONS_COLUMN) != nullptr;
82 }
83
100 84 void CatalogueTreeWidgetItem::refresh()
101 85 {
102 86 emitDataChanged();
103 87 }
General Comments 4
Under Review
author

Pull request updated. Auto status change to "Under Review"

Changed commits:
  * 1 added
  * 0 removed

Changed files:
  * M app/src/Main.cpp
  * M core/include/Catalogue/CatalogueController.h
  * M core/src/Catalogue/CatalogueController.cpp
  * M core/src/Plugin/PluginManager.cpp
  * M core/tests/Data/TestDataSeriesUtils.cpp
  * M gui/include/Catalogue/CatalogueEventsModel.h
  * M gui/include/Catalogue/CatalogueEventsWidget.h
  * M gui/include/Catalogue/CatalogueTreeWidgetItem.h
  * M gui/meson.build
  * M gui/src/Catalogue/CatalogueEventsModel.cpp
  * M gui/src/Catalogue/CatalogueEventsWidget.cpp
  * M gui/src/Catalogue/CatalogueExplorer.cpp
  * M gui/src/Catalogue/CatalogueSideBarWidget.cpp
  * M gui/src/Catalogue/CatalogueTreeWidgetItem.cpp
  * M gui/src/Visualization/VisualizationActionManager.cpp
  * M gui/src/Visualization/VisualizationGraphWidget.cpp
  * M gui/src/Visualization/VisualizationSelectionZoneItem.cpp
  * M plugins/amda/tests/TestAmdaResultParser.cpp
  * R cmake/FindCatalogueAPI.cmake
  * R core/include/Common/MimeTypesDef.h
  * R core/include/Data/DataSeriesUtils.h
  * R core/include/Data/OptionalAxis.h
  * R core/include/Data/SpectrogramSeries.h
  * R core/include/Data/Unit.h
  * R core/include/DataSource/DataSourceItemMergeHelper.h
  * R core/include/Variable/VariableCacheStrategyFactory.h
  * R core/include/Variable/VariableSingleThresholdCacheStrategy.h
  * R core/src/Common/MimeTypesDef.cpp
  * R core/src/Data/DataSeriesUtils.cpp
  * R core/src/Data/OptionalAxis.cpp
  * R core/src/Data/SpectrogramSeries.cpp
  * R core/src/DataSource/DataSourceItemMergeHelper.cpp
  * R core/tests-resources/TestDataSeriesUtils/TestThresholds.txt
  * R core/tests/Data/DataSeriesBuilders.cpp
  * R core/tests/Data/DataSeriesBuilders.h
  * R core/tests/Data/DataSeriesTestsUtils.cpp
  * R core/tests/Data/DataSeriesTestsUtils.h
  * R core/tests/Data/TestOptionalAxis.cpp
  * R core/tests/Data/TestScalarSeries.cpp
  * R core/tests/Data/TestSpectrogramSeries.cpp
  * R core/tests/Data/TestVectorSeries.cpp
  * R core/tests/DataSource/DataSourceItemBuilder.cpp
  * R core/tests/DataSource/DataSourceItemBuilder.h
  * R core/tests/DataSource/TestDataSourceItem.cpp
  * R core/tests/Variable/TestVariableSync.cpp
  * R extern/CatalogueAPI.cmake
  * R gui/include/Actions/ActionsGuiController.h
  * R gui/include/Actions/SelectionZoneAction.h
  * R gui/include/Catalogue/CatalogueExplorer.h
  * R gui/include/Catalogue/CatalogueInspectorWidget.h
  * R gui/include/Catalogue/CatalogueSideBarWidget.h
  * R gui/include/Common/VisualizationDef.h
  * R gui/include/DataSource/DataSourceTreeWidget.h
  * R gui/include/DragAndDrop/DragDropGuiController.h
  * R gui/include/DragAndDrop/DragDropScroller.h
  * R gui/include/DragAndDrop/DragDropTabSwitcher.h
  * R gui/include/Variable/VariableInspectorTableView.h
  * R gui/include/Visualization/AxisRenderingUtils.h
  * R gui/include/Visualization/ColorScaleEditor.h
  * R gui/include/Visualization/MacScrollBarStyle.h
  * R gui/include/Visualization/PlottablesRenderingUtils.h
  * R gui/include/Visualization/QCPColorMapIterator.h
  * R gui/include/Visualization/SqpColorScale.h
  * R gui/include/Visualization/VisualizationActionManager.h
  * R gui/include/Visualization/VisualizationCursorItem.h
  * R gui/include/Visualization/VisualizationDragDropContainer.h
  * R gui/include/Visualization/VisualizationDragWidget.h
  * R gui/include/Visualization/VisualizationMultiZoneSelectionDialog.h
  * R gui/include/Visualization/VisualizationSelectionZoneItem.h
  * R gui/include/Visualization/VisualizationSelectionZoneManager.h
  * R gui/resources/icones/add.png
  * R gui/resources/icones/allEvents.png
  * R gui/resources/icones/catalogue.png
  * R gui/resources/icones/chart.png
  * R gui/resources/icones/cursor.png
  * R gui/resources/icones/database.png
  * R gui/resources/icones/discard.png
  * R gui/resources/icones/drag.png
  * R gui/resources/icones/pointer.png
  * R gui/resources/icones/rectangle.png
  * R gui/resources/icones/remove.png
  * R gui/resources/icones/save.png
  * R gui/resources/icones/time.png
  * R gui/resources/icones/trash.png
  * R gui/resources/icones/zoom.png
  * R gui/src/Actions/ActionsGuiController.cpp
  * R gui/src/Actions/SelectionZoneAction.cpp
  * R gui/src/Catalogue/CatalogueInspectorWidget.cpp
  * R gui/src/Common/VisualizationDef.cpp
  * R gui/src/DataSource/DataSourceTreeWidget.cpp
  * R gui/src/DragAndDrop/DragDropGuiController.cpp
  * R gui/src/DragAndDrop/DragDropScroller.cpp
  * R gui/src/DragAndDrop/DragDropTabSwitcher.cpp
  * R gui/src/Variable/VariableInspectorTableView.cpp
  * R gui/src/Visualization/AxisRenderingUtils.cpp
  * R gui/src/Visualization/ColorScaleEditor.cpp
  * R gui/src/Visualization/MacScrollBarStyle.cpp
  * R gui/src/Visualization/PlottablesRenderingUtils.cpp
  * R gui/src/Visualization/QCPColorMapIterator.cpp
  * R gui/src/Visualization/SqpColorScale.cpp
  * R gui/src/Visualization/VisualizationCursorItem.cpp
  * R gui/src/Visualization/VisualizationDragDropContainer.cpp
  * R gui/src/Visualization/VisualizationDragWidget.cpp
  * R gui/src/Visualization/VisualizationMultiZoneSelectionDialog.cpp
  * R gui/src/Visualization/VisualizationSelectionZoneManager.cpp
  * R gui/ui/Catalogue/CatalogueEventsWidget.ui
  * R gui/ui/Catalogue/CatalogueExplorer.ui
  * R gui/ui/Catalogue/CatalogueInspectorWidget.ui
  * R gui/ui/Catalogue/CatalogueSideBarWidget.ui
  * R gui/ui/Visualization/ColorScaleEditor.ui
  * R gui/ui/Visualization/VisualizationMultiZoneSelectionDialog.ui
  * R plugins/amda/include/AmdaResultParserDefs.h
  * R plugins/amda/include/AmdaResultParserHelper.h
  * R plugins/amda/include/AmdaServer.h
  * R plugins/amda/resources/samples/AmdaSampleV3.json
  * R plugins/amda/src/AmdaResultParserDefs.cpp
  * R plugins/amda/src/AmdaResultParserHelper.cpp
  * R plugins/amda/src/AmdaServer.cpp
  * R plugins/amda/tests-resources/TestAmdaResultParser/amdaV2/FileNotFound.txt
  * R plugins/amda/tests-resources/TestAmdaResultParser/amdaV2/NaNValue.txt
  * R plugins/amda/tests-resources/TestAmdaResultParser/amdaV2/NaNX.txt
  * R plugins/amda/tests-resources/TestAmdaResultParser/amdaV2/NoUnit.txt
  * R plugins/amda/tests-resources/TestAmdaResultParser/amdaV2/TooManyValues.txt
  * R plugins/amda/tests-resources/TestAmdaResultParser/amdaV2/ValidScalar1.txt
  * R plugins/amda/tests-resources/TestAmdaResultParser/amdaV2/ValidVector1.txt
  * R plugins/amda/tests-resources/TestAmdaResultParser/amdaV2/WrongDate.txt
  * R plugins/amda/tests-resources/TestAmdaResultParser/amdaV2/WrongUnit.txt
  * R plugins/amda/tests-resources/TestAmdaResultParser/amdaV2/WrongValue.txt
  * R plugins/amda/tests-resources/TestAmdaResultParser/spectro/InvalidSpectrogramWrongBands.txt
  * R plugins/amda/tests-resources/TestAmdaResultParser/spectro/ValidSpectrogram1.txt
  * R plugins/amda/tests-resources/TestAmdaResultParser/spectro/ValidSpectrogram2.txt
  * R plugins/amda/tests-resources/TestAmdaResultParser/spectro/ValidSpectrogram3.txt
  * R plugins/amda/tests-resources/TestAmdaResultParser/spectro/ValidSpectrogramDataHoles.txt
  * R plugins/amda/tests-resources/TestAmdaResultParser/spectro/ValidSpectrogramDataHoles2.txt
  * R plugins/amda/tests-resources/TestAmdaResultParser/spectro/ValidSpectrogramFillValues.txt
  * R plugins/amda/tests-resources/TestAmdaResultParser/spectro/ValidSpectrogramNaNValues.txt
  * R plugins/amda/vera-exclusions/exclusions.txt
  * R plugins/mockplugin/include/MockDefs.h
  * R plugins/mockplugin/src/MockDefs.cpp
  * R subprojects/CatalogueAPI.wrap
  * R subprojects/QxOrm.wrap
  * R .gitignore
  * R CMakeLists.txt
  * R app/src/MainWindow.cpp
  * R app/ui/MainWindow.ui
  * R cmake/sciqlop_applications.cmake
  * R cmake/sciqlop_package_qt.cmake
  * R core/CMakeLists.txt
  * R core/cmake/Findsciqlop-core.cmake
  * R core/include/Common/SortUtils.h
  * R core/include/Data/ArrayData.h
  * R core/include/Data/DataSeries.h
  * R core/include/Data/DataSeriesIterator.h
  * R core/include/Data/IDataSeries.h
  * R core/include/Data/VariableRequest.h
  * R core/include/DataSource/DataSourceController.h
  * R core/include/DataSource/DataSourceItem.h
  * R core/include/DataSource/DataSourceItemAction.h
  * R core/include/Plugin/PluginManager.h
  * R core/include/Time/TimeController.h
  * R core/include/Variable/Variable.h
  * R core/include/Variable/VariableCacheStrategy.h
  * R core/include/Variable/VariableController.h
  * R core/include/Variable/VariableModel.h
  * R core/meson.build
  * R core/src/Data/DataSeriesIterator.cpp
  * R core/src/Data/VectorSeries.cpp
  * R core/src/DataSource/DataSourceController.cpp
  * R core/src/DataSource/DataSourceItem.cpp
  * R core/src/DataSource/DataSourceItemAction.cpp
  * R core/src/Time/TimeController.cpp
  * R core/src/Variable/Variable.cpp
  * R core/src/Variable/VariableAcquisitionWorker.cpp
  * R core/src/Variable/VariableController.cpp
  * R core/src/Variable/VariableModel.cpp
  * R core/tests/Data/TestTwoDimArrayData.cpp
  * R core/tests/Variable/TestVariable.cpp
  * R core/tests/meson.build
  * R gui/CMakeLists.txt
  * R gui/cmake/Findsciqlop-gui.cmake
  * R gui/include/DataSource/DataSourceWidget.h
  * R gui/include/SqpApplication.h
  * R gui/include/TimeWidget/TimeWidget.h
  * R gui/include/Visualization/VisualizationGraphHelper.h
  * R gui/include/Visualization/VisualizationGraphRenderingDelegate.h
  * R gui/include/Visualization/VisualizationGraphWidget.h
  * R gui/include/Visualization/VisualizationTabWidget.h
  * R gui/include/Visualization/VisualizationWidget.h
  * R gui/include/Visualization/VisualizationZoneWidget.h
  * R gui/resources/sqpguiresources.qrc
  * R gui/src/DataSource/DataSourceTreeWidgetItem.cpp
  * R gui/src/DataSource/DataSourceWidget.cpp
  * R gui/src/SqpApplication.cpp
  * R gui/src/TimeWidget/TimeWidget.cpp
  * R gui/src/Variable/VariableInspectorWidget.cpp
  * R gui/src/Visualization/VisualizationGraphHelper.cpp
  * R gui/src/Visualization/VisualizationGraphRenderingDelegate.cpp
  * R gui/src/Visualization/VisualizationTabWidget.cpp
  * R gui/src/Visualization/VisualizationWidget.cpp
  * R gui/src/Visualization/VisualizationZoneWidget.cpp
  * R gui/src/Visualization/operations/GenerateVariableMenuOperation.cpp
  * R gui/src/Visualization/operations/RescaleAxeOperation.cpp
  * R gui/ui/DataSource/DataSourceWidget.ui
  * R gui/ui/TimeWidget/TimeWidget.ui
  * R gui/ui/Variable/VariableInspectorWidget.ui
  * R gui/ui/Visualization/VisualizationTabWidget.ui
  * R gui/ui/Visualization/VisualizationZoneWidget.ui
  * R gui/vera-exclusions/exclusions.txt
  * R meson.build
  * R plugins/amda/CMakeLists.txt
  * R plugins/amda/cmake/Findsciqlop-amda.cmake
  * R plugins/amda/include/AmdaDefs.h
  * R plugins/amda/include/AmdaPlugin.h
  * R plugins/amda/include/AmdaProvider.h
  * R plugins/amda/include/AmdaResultParser.h
  * R plugins/amda/meson.build
  * R plugins/amda/resources/amdaresources.qrc
  * R plugins/amda/src/AmdaDefs.cpp
  * R plugins/amda/src/AmdaPlugin.cpp
  * R plugins/amda/src/AmdaProvider.cpp
  * R plugins/amda/src/AmdaResultParser.cpp
  * R plugins/amda/tests/TestAmdaAcquisition.cpp
  * R plugins/mockplugin/cmake/Findsciqlop-mockplugin.cmake
  * R plugins/mockplugin/include/CosinusProvider.h
  * R plugins/mockplugin/meson.build
  * R plugins/mockplugin/src/CosinusProvider.cpp
  * R plugins/mockplugin/src/MockPlugin.cpp
  * R plugins/mockplugin/tests/TestCosinusAcquisition.cpp
  * R core/src/Variable/VariableCacheStrategy.cpp
  * R core/tests/Data/TestDataSeries.cpp
Approved

Status change > Approved

You need to be logged in to leave comments. Login now