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