Line data Source code
1 : // DUNE DAQ modification notice:
2 : // This file has been modified from the original ATLAS dbe source for the DUNE DAQ project.
3 : // Fork baseline commit: dbe-02-12-17 (2022-05-12).
4 : // Renamed since fork: no.
5 :
6 : /// Including QT Headers
7 : #include "dbe/subtreeproxy.hpp"
8 : #include "dbe/tree.hpp"
9 :
10 : #include "dbe/treenode.hpp"
11 : #include "dbe/treeselection.hpp"
12 :
13 : #include <QAction>
14 : #include <QContextMenuEvent>
15 : #include <QMenu>
16 : #include <QMessageBox>
17 :
18 : /// Including DBE
19 : #include "dbe/CustomTreeView.hpp"
20 : #include "dbe/ObjectCreator.hpp"
21 : #include "dbe/ObjectEditor.hpp"
22 : #include "dbe/TreeModelInterface.hpp"
23 : #include "dbe/messenger.hpp"
24 :
25 : //------------------------------------------------------------------------------------------
26 0 : dbe::CustomTreeView::CustomTreeView(QWidget* Parent)
27 : : QTreeView(Parent)
28 0 : , contextMenu(nullptr)
29 : {
30 0 : setDragEnabled(true);
31 0 : setSortingEnabled(true);
32 0 : setExpandsOnDoubleClick(false);
33 0 : CreateActions();
34 0 : setSelectionMode(QAbstractItemView::ExtendedSelection);
35 0 : setUniformRowHeights(true);
36 0 : }
37 : //------------------------------------------------------------------------------------------
38 :
39 : //------------------------------------------------------------------------------------------
40 : void
41 0 : dbe::CustomTreeView::contextMenuEvent(QContextMenuEvent* Event)
42 : {
43 0 : if (contextMenu == nullptr) {
44 0 : contextMenu = new QMenu(this);
45 0 : contextMenu->addAction(editObjectAc);
46 0 : contextMenu->addAction(deleteObjectAc);
47 0 : contextMenu->addAction(createObjectAc);
48 0 : contextMenu->addAction(deleteObjectWidgetAc);
49 0 : contextMenu->addAction(copyObjectAc);
50 0 : contextMenu->addAction(buildTableFromClassAc);
51 0 : contextMenu->addAction(expandAllAc);
52 0 : contextMenu->addAction(collapseAllAc);
53 0 : contextMenu->addAction(refByAc);
54 0 : contextMenu->addAction(refByAcOnlyComp);
55 : }
56 :
57 0 : model_common_interface* modelInterface = dynamic_cast<model_common_interface*>(this->model());
58 0 : QModelIndex index = this->currentIndex();
59 :
60 0 : if (index.isValid()) {
61 0 : if (modelInterface) {
62 :
63 0 : try {
64 0 : tref obj = modelInterface->getobject(index);
65 0 : (contextMenu->actions()).at(0)->setVisible(true);
66 0 : (contextMenu->actions()).at(1)->setVisible(true);
67 0 : (contextMenu->actions()).at(2)->setVisible(true);
68 0 : (contextMenu->actions()).at(3)->setVisible(false);
69 0 : (contextMenu->actions()).at(4)->setVisible(true);
70 0 : (contextMenu->actions()).at(5)->setVisible(false);
71 0 : (contextMenu->actions()).at(6)->setVisible(false);
72 0 : (contextMenu->actions()).at(7)->setVisible(false);
73 0 : (contextMenu->actions()).at(8)->setVisible(true);
74 0 : (contextMenu->actions()).at(9)->setVisible(true);
75 0 : } catch (daq::dbe::cannot_handle_invalid_qmodelindex const& e) {
76 0 : (contextMenu->actions()).at(0)->setVisible(false);
77 0 : (contextMenu->actions()).at(1)->setVisible(false);
78 0 : (contextMenu->actions()).at(2)->setVisible(true);
79 0 : (contextMenu->actions()).at(3)->setVisible(false);
80 0 : (contextMenu->actions()).at(4)->setVisible(false);
81 0 : (contextMenu->actions()).at(5)->setVisible(false);
82 0 : (contextMenu->actions()).at(6)->setVisible(false);
83 0 : (contextMenu->actions()).at(7)->setVisible(false);
84 0 : (contextMenu->actions()).at(8)->setVisible(false);
85 0 : (contextMenu->actions()).at(9)->setVisible(false);
86 0 : }
87 : }
88 :
89 0 : contextMenu->exec(Event->globalPos());
90 : }
91 0 : }
92 : //------------------------------------------------------------------------------------------
93 :
94 : //------------------------------------------------------------------------------------------
95 : void
96 0 : dbe::CustomTreeView::CreateActions()
97 : {
98 :
99 0 : editObjectAc = new QAction(tr("&Edit Object"), this);
100 0 : editObjectAc->setShortcut(tr("Ctrl+E"));
101 0 : editObjectAc->setShortcutContext(Qt::WidgetShortcut);
102 0 : connect(editObjectAc, SIGNAL(triggered()), this, SLOT(slot_edit_object()));
103 0 : addAction(editObjectAc);
104 :
105 0 : deleteObjectAc = new QAction(tr("&Delete Object"), this);
106 0 : deleteObjectAc->setShortcut(tr("Ctrl+D"));
107 0 : deleteObjectAc->setShortcutContext(Qt::WidgetShortcut);
108 0 : connect(deleteObjectAc, SIGNAL(triggered()), this, SLOT(slot_delete_objects()));
109 0 : addAction(deleteObjectAc);
110 :
111 0 : createObjectAc = new QAction(tr("Create &New Object"), this);
112 0 : createObjectAc->setShortcut(tr("Ctrl+N"));
113 0 : createObjectAc->setShortcutContext(Qt::WidgetShortcut);
114 0 : connect(createObjectAc, SIGNAL(triggered()), this, SLOT(slot_create_object()));
115 0 : addAction(createObjectAc);
116 :
117 0 : copyObjectAc = new QAction(tr("&Copy This Object Into A New One"), this);
118 0 : copyObjectAc->setShortcut(tr("Ctrl+Shift+N"));
119 0 : copyObjectAc->setShortcutContext(Qt::WidgetShortcut);
120 0 : connect(copyObjectAc, SIGNAL(triggered()), this, SLOT(slot_copy_object()));
121 0 : addAction(copyObjectAc);
122 :
123 0 : deleteObjectWidgetAc = new QAction(tr("Delete Object &Widget"), this);
124 0 : deleteObjectWidgetAc->setShortcut(tr("Ctrl+W"));
125 0 : deleteObjectWidgetAc->setShortcutContext(Qt::WidgetShortcut);
126 0 : addAction(deleteObjectWidgetAc);
127 :
128 0 : buildTableFromClassAc = new QAction(tr("Build Tab&le From Class"), this);
129 0 : buildTableFromClassAc->setShortcut(tr("Ctrl+L"));
130 0 : buildTableFromClassAc->setShortcutContext(Qt::WidgetShortcut);
131 0 : addAction(buildTableFromClassAc);
132 :
133 0 : expandAllAc = new QAction(tr("Expand &All"), this);
134 0 : expandAllAc->setShortcut(tr("Ctrl+A"));
135 0 : expandAllAc->setShortcutContext(Qt::WidgetShortcut);
136 0 : connect(expandAllAc, SIGNAL(triggered()), this,
137 : SLOT(expandAll())); // QTreeView slot
138 0 : addAction(expandAllAc);
139 :
140 0 : collapseAllAc = new QAction(tr("C&ollapse All"), this);
141 0 : collapseAllAc->setShortcut(tr("Ctrl+Shift+C"));
142 0 : collapseAllAc->setShortcutContext(Qt::WidgetShortcut);
143 0 : connect(collapseAllAc, SIGNAL(triggered()), this,
144 : SLOT(collapseAll())); // QTreeView slot
145 0 : addAction(collapseAllAc);
146 :
147 0 : refByAc = new QAction(tr("&Referenced By (All objects)"), this);
148 0 : refByAc->setShortcut(tr("Ctrl+Y"));
149 0 : refByAc->setShortcutContext(Qt::WidgetShortcut);
150 0 : refByAc->setToolTip("Find all objects which reference the selecetd object");
151 0 : refByAc->setStatusTip(refByAc->toolTip());
152 0 : connect(refByAc, SIGNAL(triggered()), this, SLOT(referencedByAll()));
153 0 : addAction(refByAc);
154 :
155 0 : refByAcOnlyComp = new QAction(tr("Referenced B&y (Only Composite)"), this);
156 0 : refByAcOnlyComp->setShortcut(tr("Ctrl+Shift+Y"));
157 0 : refByAcOnlyComp->setShortcutContext(Qt::WidgetShortcut);
158 0 : refByAcOnlyComp->setToolTip("Find objects (ONLY Composite ones) which reference the selecetd object");
159 0 : refByAcOnlyComp->setStatusTip(refByAcOnlyComp->toolTip());
160 0 : connect(refByAcOnlyComp, SIGNAL(triggered()), this, SLOT(referencedbyOnlycomposite()));
161 0 : addAction(refByAcOnlyComp);
162 0 : }
163 : //------------------------------------------------------------------------------------------
164 :
165 : //------------------------------------------------------------------------------------------
166 : void
167 0 : dbe::CustomTreeView::slot_create_object()
168 : {
169 : // To create an object we only need to extract the information of the class that the
170 : // user had clicked onto.
171 0 : model_common_interface* common_model = dynamic_cast<model_common_interface*>(model());
172 0 : QModelIndex const& treeindex = currentIndex();
173 0 : treenode* cnode = nullptr;
174 :
175 0 : if (common_model && treeindex.isValid()) {
176 0 : dunedaq::conffwk::class_t classinfo = common_model->getclass(treeindex);
177 :
178 0 : if (dynamic_cast<models::treeselection*>(model())) {
179 0 : models::treeselection* selectionmodel = dynamic_cast<models::treeselection*>(model());
180 :
181 0 : if (selectionmodel) {
182 0 : QModelIndex const& srcindex = selectionmodel->mapToSource(treeindex);
183 :
184 0 : if (dbe::models::tree* tree_model = dynamic_cast<dbe::models::tree*>(selectionmodel->sourceModel())) {
185 0 : cnode = tree_model->getnode(srcindex);
186 : }
187 : }
188 0 : } else if (dbe::models::subtree_proxy* subtree_model = dynamic_cast<dbe::models::subtree_proxy*>(model())) {
189 0 : cnode = subtree_model->getnode(treeindex);
190 : }
191 :
192 0 : if (dynamic_cast<RelationshipNode*>(cnode)) {
193 0 : treenode* parent = cnode->GetParent();
194 0 : ObjectNode* NodeObject = dynamic_cast<ObjectNode*>(parent);
195 0 : RelationshipNode* RelationshipTreeNode = dynamic_cast<RelationshipNode*>(cnode);
196 :
197 0 : (new ObjectCreator(NodeObject->GetObject(), RelationshipTreeNode->relation_t()))->show();
198 : } else {
199 0 : (new ObjectCreator(classinfo))->show();
200 : }
201 0 : }
202 0 : }
203 : //------------------------------------------------------------------------------------------
204 :
205 : //------------------------------------------------------------------------------------------
206 : void
207 0 : dbe::CustomTreeView::slot_delete_objects()
208 : {
209 0 : if (this->model() != nullptr) {
210 0 : QModelIndexList qindices = this->selectedIndexes();
211 0 : std::vector<QModelIndex> indices;
212 :
213 0 : for (QModelIndex const& q : qindices) {
214 0 : if (q.isValid() and q.column() == 0) {
215 0 : indices.push_back(q);
216 : }
217 : }
218 :
219 0 : if (models::treeselection* casted_model = dynamic_cast<models::treeselection*>(this->model())) {
220 0 : casted_model->delete_objects(indices.begin(), indices.end());
221 0 : } else if (dbe::models::subtree_proxy* casted_model = dynamic_cast<dbe::models::subtree_proxy*>(this->model())) {
222 0 : casted_model->delete_objects(indices.begin(), indices.end());
223 : } else {
224 0 : WARN("Object Deleting",
225 : "Object deletion failed due to the internal model being in invalid state",
226 0 : "You are advised to restart the application before proceeding any further");
227 : }
228 0 : }
229 0 : }
230 : //------------------------------------------------------------------------------------------
231 :
232 : //------------------------------------------------------------------------------------------
233 : void
234 0 : dbe::CustomTreeView::slot_edit_object()
235 : {
236 0 : if (this->model() != nullptr) {
237 0 : QModelIndexList indices = this->selectedIndexes();
238 :
239 0 : for (QModelIndex const& q : indices) {
240 0 : edit_object(q);
241 : }
242 0 : }
243 0 : }
244 : //------------------------------------------------------------------------------------------
245 :
246 : //------------------------------------------------------------------------------------------
247 : void
248 0 : dbe::CustomTreeView::edit_object(QModelIndex const& index)
249 : {
250 0 : model_common_interface* filtermodel = dynamic_cast<model_common_interface*>(model());
251 :
252 0 : if (!index.isValid()) {
253 : return;
254 : }
255 :
256 0 : if (filtermodel) {
257 0 : try {
258 0 : tref obj = filtermodel->getobject(index);
259 0 : bool WidgetFound = false;
260 0 : QString ObjectEditorName = QString("%1@%2").arg(obj.UID().c_str()).arg(obj.class_name().c_str());
261 :
262 0 : for (QWidget* Editor : QApplication::allWidgets()) {
263 0 : ObjectEditor* Widget = dynamic_cast<ObjectEditor*>(Editor);
264 :
265 0 : if (Widget != nullptr) {
266 0 : if ((Widget->objectName()).compare(ObjectEditorName) == 0) {
267 0 : Widget->raise();
268 0 : Widget->setVisible(true);
269 : WidgetFound = true;
270 : }
271 : }
272 0 : }
273 :
274 0 : if (!WidgetFound) {
275 0 : (new ObjectEditor(obj))->show();
276 : }
277 0 : } catch (daq::dbe::cannot_handle_invalid_qmodelindex const& e) {
278 : // nothing to do , maybe the user just clicked the wrong place
279 0 : }
280 : }
281 : }
282 : //------------------------------------------------------------------------------------------
283 :
284 : //------------------------------------------------------------------------------------------
285 : void
286 0 : dbe::CustomTreeView::slot_copy_object()
287 : {
288 0 : model_common_interface* filtermodel = dynamic_cast<model_common_interface*>(model());
289 0 : QModelIndex i = currentIndex();
290 :
291 0 : if (i.isValid() and filtermodel) {
292 0 : try {
293 0 : (new ObjectCreator(filtermodel->getobject(i)))->show();
294 0 : } catch (daq::dbe::cannot_handle_invalid_qmodelindex const& e) {
295 : // TODO the index can be invalid in this case
296 0 : }
297 : }
298 0 : }
299 : //------------------------------------------------------------------------------------------
300 : void
301 0 : dbe::CustomTreeView::referencedbyOnlycomposite()
302 : {
303 0 : referencedBy(true);
304 0 : }
305 :
306 : void
307 0 : dbe::CustomTreeView::referencedByAll()
308 : {
309 0 : referencedBy(false);
310 0 : }
311 : //------------------------------------------------------------------------------------------
312 : void
313 0 : dbe::CustomTreeView::closeEvent(QCloseEvent* event)
314 : {
315 : // Reset the model when the widget is closed
316 : // If not done, reference to removed objects may create issues
317 0 : models::treeselection* filtermodel = dynamic_cast<models::treeselection*>(model());
318 :
319 0 : setModel(nullptr);
320 :
321 0 : if (filtermodel != nullptr) {
322 0 : filtermodel->ResetQueryObjects();
323 0 : filtermodel->deleteLater();
324 : }
325 :
326 0 : event->accept();
327 0 : }
328 :
329 : //------------------------------------------------------------------------------------------
330 : void
331 0 : dbe::CustomTreeView::referencedBy(bool All)
332 : {
333 0 : model_common_interface* filtermodel = dynamic_cast<model_common_interface*>(model());
334 0 : QModelIndex Index = currentIndex();
335 :
336 0 : if (!Index.isValid()) {
337 0 : return;
338 : }
339 :
340 0 : if (filtermodel) {
341 :
342 0 : try {
343 0 : tref obj = filtermodel->getobject(Index);
344 0 : std::vector<tref> objects;
345 :
346 0 : if (not obj.is_null()) {
347 0 : objects = obj.referenced_by("*", All);
348 : }
349 :
350 0 : if (objects.size() > 0) {
351 0 : dbe::models::tree* Source = dynamic_cast<dbe::models::tree*>(filtermodel->ReturnSourceModel());
352 0 : models::treeselection* Selection = new models::treeselection();
353 0 : Selection->SetFilterType(models::treeselection::ObjectFilterType);
354 0 : Selection->SetQueryObjects(objects);
355 0 : Selection->setFilterRegExp("Dummy");
356 0 : Selection->setSourceModel(Source);
357 :
358 0 : CustomTreeView* tView = new CustomTreeView(0);
359 0 : tView->setModel(Selection);
360 0 : tView->setWindowTitle(QString("Objects referencing '%1'").arg(obj.UID().c_str()));
361 0 : tView->setSortingEnabled(true);
362 0 : tView->setAlternatingRowColors(true);
363 0 : tView->resizeColumnToContents(0);
364 0 : tView->resizeColumnToContents(1);
365 0 : tView->setAttribute(Qt::WA_DeleteOnClose);
366 :
367 0 : connect(tView, SIGNAL(doubleClicked(QModelIndex)), tView, SLOT(slot_edit_object()));
368 :
369 0 : tView->show();
370 : } else {
371 0 : if (All) {
372 0 : WARN("No references of only composite objects have been found for object",
373 : " ",
374 : "with UID:",
375 : obj.UID(),
376 : "of class",
377 0 : obj.class_name());
378 : } else {
379 0 : WARN("No references of objects have been found for object",
380 : " ",
381 : "with UID:",
382 : obj.UID(),
383 : "of class",
384 0 : obj.class_name());
385 : }
386 : }
387 0 : } catch (daq::dbe::cannot_handle_invalid_qmodelindex const& e) {
388 0 : }
389 : }
390 : }
391 : //------------------------------------------------------------------------------------------
392 :
393 : //------------------------------------------------------------------------------------------
394 : void
395 0 : dbe::CustomTreeView::referencedBy(bool All, tref obj)
396 : {
397 0 : model_common_interface* filtermodel = dynamic_cast<model_common_interface*>(model());
398 :
399 0 : if (filtermodel) {
400 0 : std::vector<tref> objects;
401 :
402 0 : if (!obj.is_null()) {
403 0 : objects = obj.referenced_by("*", All);
404 : }
405 :
406 0 : if (objects.size() > 0) {
407 0 : dbe::models::tree* Source = dynamic_cast<dbe::models::tree*>(filtermodel->ReturnSourceModel());
408 0 : models::treeselection* Selection = new models::treeselection();
409 0 : Selection->SetFilterType(models::treeselection::ObjectFilterType);
410 0 : Selection->SetQueryObjects(objects);
411 0 : Selection->setFilterRegExp("Dummy");
412 0 : Selection->setSourceModel(Source);
413 :
414 0 : CustomTreeView* tView = new CustomTreeView(0);
415 0 : tView->setModel(Selection);
416 0 : tView->setSortingEnabled(true);
417 0 : tView->setAlternatingRowColors(true);
418 0 : tView->resizeColumnToContents(0);
419 0 : tView->hideColumn(1);
420 : // tView->resizeColumnToContents(1);
421 0 : tView->setWindowTitle(QString("Objects referencing '%1'").arg(obj.UID().c_str()));
422 0 : tView->setAttribute(Qt::WA_DeleteOnClose);
423 :
424 0 : connect(tView, SIGNAL(doubleClicked(QModelIndex)), tView, SLOT(slot_edit_object()));
425 :
426 0 : tView->show();
427 : } else {
428 0 : if (All) {
429 0 : WARN("No references for object", "Only Composite Objects - Not found", "with UID:", obj.UID());
430 : } else {
431 0 : WARN("No references for object", "All Objects - Not found", "with UID:", obj.UID());
432 : }
433 : }
434 0 : }
435 0 : }
436 : //------------------------------------------------------------------------------------------
|