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