Salome HOME
69cc9c616c58b32feda738a6194f444cfacd5a26
[modules/shaper.git] / src / XGUI / XGUI_ObjectsBrowser.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
2
3 #include "XGUI_ObjectsBrowser.h"
4 #include "XGUI_DocumentDataModel.h"
5 #include "XGUI_Tools.h"
6
7 #include <ModelAPI_Data.h>
8 #include <ModelAPI_Session.h>
9 #include <ModelAPI_Document.h>
10 #include <ModelAPI_Object.h>
11
12 #include <QLayout>
13 #include <QLabel>
14 #include <QLineEdit>
15 #include <QPixmap>
16 #include <QEvent>
17 #include <QMouseEvent>
18 #include <QAction>
19
20 XGUI_DataTree::XGUI_DataTree(QWidget* theParent)
21     : QTreeView(theParent)
22 {
23   setHeaderHidden(true);
24   setModel(new XGUI_DocumentDataModel(this));
25   setEditTriggers(QAbstractItemView::NoEditTriggers);
26   setSelectionBehavior(QAbstractItemView::SelectRows);
27   setSelectionMode(QAbstractItemView::ExtendedSelection);
28
29   connect(selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
30           this, SLOT(onSelectionChanged(const QItemSelection&, const QItemSelection&)));
31 }
32
33 XGUI_DataTree::~XGUI_DataTree()
34 {
35 }
36
37 XGUI_DocumentDataModel* XGUI_DataTree::dataModel() const
38 {
39   return static_cast<XGUI_DocumentDataModel*>(model());
40 }
41
42 void XGUI_DataTree::onSelectionChanged(const QItemSelection& theSelected,
43                                        const QItemSelection& theDeselected)
44 {
45   mySelectedData.clear();
46   QModelIndexList aIndexes = selectionModel()->selectedIndexes();
47   XGUI_DocumentDataModel* aModel = dataModel();
48   QModelIndexList::const_iterator aIt;
49   for (aIt = aIndexes.constBegin(); aIt != aIndexes.constEnd(); ++aIt) {
50     ObjectPtr aObject = aModel->object(*aIt);
51     if (aObject)
52       mySelectedData.append(aObject);
53   }
54   emit selectionChanged();
55 }
56
57 void XGUI_DataTree::mouseDoubleClickEvent(QMouseEvent* theEvent)
58 {
59   if (theEvent->button() == Qt::LeftButton) {
60     QModelIndex aIndex = currentIndex();
61     XGUI_DocumentDataModel* aModel = dataModel();
62     ObjectPtr aObject = aModel->object(aIndex);
63     ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObject);
64     if (aPart) {
65       aPart->activate();
66     }
67   } else
68     QTreeView::mouseDoubleClickEvent(theEvent);
69 }
70
71 void XGUI_DataTree::contextMenuEvent(QContextMenuEvent* theEvent)
72 {
73   emit contextMenuRequested(theEvent);
74 }
75
76 void XGUI_DataTree::commitData(QWidget* theEditor)
77 {
78   QLineEdit* aEditor = dynamic_cast<QLineEdit*>(theEditor);
79   if (aEditor) {
80     QString aRes = aEditor->text();
81     ObjectPtr aFeature = mySelectedData.first();
82     SessionPtr aMgr = ModelAPI_Session::get();
83     aMgr->startOperation();
84     aFeature->data()->setName(qPrintable(aRes));
85     aMgr->finishOperation();
86   }
87 }
88
89 void XGUI_DataTree::clear() 
90 {
91   mySelectedData.clear();
92   XGUI_DocumentDataModel* aModel = dataModel();
93   aModel->clear();
94   reset();
95 }
96
97 //********************************************************************
98 //********************************************************************
99 //********************************************************************
100 XGUI_ObjectsBrowser::XGUI_ObjectsBrowser(QWidget* theParent)
101     : QWidget(theParent)
102 {
103   QVBoxLayout* aLayout = new QVBoxLayout(this);
104   aLayout->setContentsMargins(0, 0, 0, 0);
105   aLayout->setSpacing(0);
106
107   QFrame* aLabelWgt = new QFrame(this);
108   aLabelWgt->setAutoFillBackground(true);
109   QPalette aPalet = aLabelWgt->palette();
110   aPalet.setColor(QPalette::Window, Qt::white);
111   aLabelWgt->setPalette(aPalet);
112
113   aLayout->addWidget(aLabelWgt);
114   QHBoxLayout* aLabelLay = new QHBoxLayout(aLabelWgt);
115   aLabelLay->setContentsMargins(0, 0, 0, 0);
116   aLabelLay->setSpacing(0);
117
118   QLabel* aLbl = new QLabel(aLabelWgt);
119   aLbl->setPixmap(QPixmap(":pictures/assembly.png"));
120   aLbl->setMargin(2);
121
122   aLbl->setAutoFillBackground(true);
123
124   aLabelLay->addWidget(aLbl);
125
126   SessionPtr aMgr = ModelAPI_Session::get();
127   DocumentPtr aDoc = aMgr->moduleDocument();
128   // TODO: Find a name of the root document
129
130   myActiveDocLbl = new QLineEdit(tr("Part set"), aLabelWgt);
131   myActiveDocLbl->setReadOnly(true);
132   myActiveDocLbl->setFrame(false);
133   //myActiveDocLbl->setMargin(2);
134   myActiveDocLbl->setContextMenuPolicy(Qt::CustomContextMenu);
135
136   myActiveDocLbl->installEventFilter(this);
137
138   aLabelLay->addWidget(myActiveDocLbl);
139   aLabelLay->setStretch(1, 1);
140
141   myTreeView = new XGUI_DataTree(this);
142   aLayout->addWidget(myTreeView);
143
144   myDocModel = myTreeView->dataModel();
145
146   aLabelWgt->setFrameShape(myTreeView->frameShape());
147   aLabelWgt->setFrameShadow(myTreeView->frameShadow());
148
149   connect(myTreeView, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
150   connect(myTreeView, SIGNAL(activePartChanged(ObjectPtr)), this,
151           SLOT(onActivePartChanged(ObjectPtr)));
152   connect(myTreeView, SIGNAL(activePartChanged(ObjectPtr)), this,
153           SIGNAL(activePartChanged(ObjectPtr)));
154
155   connect(myActiveDocLbl, SIGNAL(customContextMenuRequested(const QPoint&)), this,
156           SLOT(onLabelContextMenuRequested(const QPoint&)));
157   connect(myTreeView, SIGNAL(contextMenuRequested(QContextMenuEvent*)), this,
158           SLOT(onContextMenuRequested(QContextMenuEvent*)));
159
160   onActivePartChanged(ObjectPtr());
161
162   // Create internal actions
163   QAction* aAction = new QAction(QIcon(":pictures/rename_edit.png"), tr("Rename"), this);
164   aAction->setData("RENAME_CMD");
165   connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onEditItem()));
166   addAction(aAction);
167 }
168
169 //***************************************************
170 XGUI_ObjectsBrowser::~XGUI_ObjectsBrowser()
171 {
172 }
173
174 //***************************************************
175 void XGUI_ObjectsBrowser::onActivePartChanged(ObjectPtr thePart)
176 {
177   QPalette aPalet = myActiveDocLbl->palette();
178   if (thePart) {
179     aPalet.setColor(QPalette::Text, Qt::black);
180   } else {
181     aPalet.setColor(QPalette::Text, QColor(0, 72, 140));
182   }
183   myActiveDocLbl->setPalette(aPalet);
184 }
185
186 //***************************************************
187 bool XGUI_ObjectsBrowser::eventFilter(QObject* obj, QEvent* theEvent)
188 {
189   if (obj == myActiveDocLbl) {
190     if (myActiveDocLbl->isReadOnly()) {
191       if (theEvent->type() == QEvent::MouseButtonDblClick) {
192         if (myDocModel->activePartIndex().isValid()) {
193           myTreeView->setExpanded(myDocModel->activePartIndex(), false);
194         }
195         myDocModel->deactivatePart();
196         onActivePartChanged(ObjectPtr());
197         emit activePartChanged(ObjectPtr());
198       }
199     } else {
200       // End of editing by mouse click
201       if (theEvent->type() == QEvent::MouseButtonRelease) {
202         QMouseEvent* aEvent = (QMouseEvent*) theEvent;
203         QPoint aPnt = mapFromGlobal(aEvent->globalPos());
204         if (childAt(aPnt) != myActiveDocLbl) {
205           closeDocNameEditing(true);
206         }
207       } else if (theEvent->type() == QEvent::KeyRelease) {
208         QKeyEvent* aEvent = (QKeyEvent*) theEvent;
209         switch (aEvent->key()) {
210           case Qt::Key_Return:
211           case Qt::Key_Enter:  // Accept current input
212             closeDocNameEditing(true);
213             break;
214           case Qt::Key_Escape:  // Cancel the input
215             closeDocNameEditing(false);
216             break;
217         }
218       }
219     }
220   }
221   return QWidget::eventFilter(obj, theEvent);
222 }
223
224 //***************************************************
225 void XGUI_ObjectsBrowser::closeDocNameEditing(bool toSave)
226 {
227   myActiveDocLbl->deselect();
228   myActiveDocLbl->clearFocus();
229   myActiveDocLbl->releaseMouse();
230   myActiveDocLbl->setReadOnly(true);
231   if (toSave) {
232     // TODO: Save the name of root document
233     SessionPtr aMgr = ModelAPI_Session::get();
234     DocumentPtr aDoc = aMgr->moduleDocument();
235   } else {
236     myActiveDocLbl->setText(myActiveDocLbl->property("OldText").toString());
237   }
238 }
239
240 //***************************************************
241 void XGUI_ObjectsBrowser::activatePart(const ResultPartPtr& thePart)
242 {
243   if (thePart) {
244     QModelIndex aIndex = myDocModel->partIndex(thePart);
245
246     if ((myDocModel->activePartIndex() != aIndex) && myDocModel->activePartIndex().isValid()) {
247       myTreeView->setExpanded(myDocModel->activePartIndex(), false);
248     }
249     bool isChanged = myDocModel->activatedIndex(aIndex);
250     if (isChanged) {
251       if (myDocModel->activePartIndex().isValid()) {
252         myTreeView->setExpanded(aIndex.parent(), true);
253         myTreeView->setExpanded(aIndex, true);
254         onActivePartChanged(myDocModel->object(aIndex));
255       } else {
256         onActivePartChanged(ObjectPtr());
257       }
258     }
259   } else {
260     QModelIndex aIndex = myDocModel->activePartIndex();
261     if (aIndex.isValid()) {
262       myDocModel->activatedIndex(aIndex);
263       myTreeView->setExpanded(aIndex, false);
264       onActivePartChanged(ObjectPtr());
265     }
266   }
267 }
268
269 //***************************************************
270 void XGUI_ObjectsBrowser::onContextMenuRequested(QContextMenuEvent* theEvent)
271 {
272   myObjectsList = myTreeView->selectedObjects();
273   bool toEnable = myObjectsList.size() == 1;
274   foreach(QAction* aCmd, actions())
275   {
276     aCmd->setEnabled(toEnable);
277   }
278   emit contextMenuRequested(theEvent);
279 }
280
281 //***************************************************
282 void XGUI_ObjectsBrowser::onLabelContextMenuRequested(const QPoint& thePnt)
283 {
284   myObjectsList.clear();
285   //Empty feature pointer means that selected root document
286   myObjectsList.append(ObjectPtr());
287
288   foreach(QAction* aCmd, actions())
289   {
290     aCmd->setEnabled(true);
291   }
292   QContextMenuEvent aEvent(QContextMenuEvent::Mouse, thePnt, myActiveDocLbl->mapToGlobal(thePnt));
293   emit contextMenuRequested(&aEvent);
294 }
295
296 //***************************************************
297 void XGUI_ObjectsBrowser::onEditItem()
298 {
299   if (myObjectsList.size() > 0) {
300     ObjectPtr aFeature = myObjectsList.first();
301     if (aFeature) {  // Selection happens in TreeView
302       // Find index which corresponds the feature
303       QModelIndex aIndex;
304       foreach(QModelIndex aIdx, selectedIndexes())
305       {
306         ObjectPtr aFea = dataModel()->object(aIdx);
307         if (dataModel()->object(aIdx)->isSame(aFeature)) {
308           aIndex = aIdx;
309           break;
310         }
311       }
312       if (aIndex.isValid()) {
313         myTreeView->setCurrentIndex(aIndex);
314         myTreeView->edit(aIndex);
315       }
316     } else {  //Selection happens in Upper label
317       myActiveDocLbl->setReadOnly(false);
318       myActiveDocLbl->setFocus();
319       myActiveDocLbl->selectAll();
320       myActiveDocLbl->grabMouse();
321       myActiveDocLbl->setProperty("OldText", myActiveDocLbl->text());
322     }
323   }
324 }
325
326 //***************************************************
327 void XGUI_ObjectsBrowser::onSelectionChanged()
328 {
329   myObjectsList = myTreeView->selectedObjects();
330   emit selectionChanged();
331 }
332
333 //***************************************************
334 void XGUI_ObjectsBrowser::rebuildDataTree()
335 {
336   myDocModel->rebuildDataTree();
337   update();
338 }
339
340 //***************************************************
341 void XGUI_ObjectsBrowser::setObjectsSelected(const QObjectPtrList& theObjects)
342 {
343   QList<QModelIndex> theIndexes;
344   QItemSelectionModel* aSelectModel = myTreeView->selectionModel();
345   aSelectModel->clear();
346
347   foreach(ObjectPtr aFeature, theObjects)
348   {
349     QModelIndex aIndex = myDocModel->objectIndex(aFeature);
350     if (aIndex.isValid()) {
351       aSelectModel->select(aIndex, QItemSelectionModel::Select);
352     }
353   }
354 }
355
356 //***************************************************
357 void XGUI_ObjectsBrowser::processEvent(const std::shared_ptr<Events_Message>& theMessage)
358
359   myDocModel->processEvent(theMessage); 
360 }
361
362
363 //***************************************************
364 void XGUI_ObjectsBrowser::clearContent()  
365
366   myObjectsList.clear();
367   myTreeView->clear(); 
368 }