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