]> SALOME platform Git repositories - modules/shaper.git/blob - src/XGUI/XGUI_ObjectsBrowser.cpp
Salome HOME
Minimization of activate/deactivate calls.
[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     } else {
209       if (theEvent->type() == QEvent::MouseButtonDblClick) {
210         emit headerMouseDblClicked(QModelIndex());
211         return true;
212       }  
213     }
214   }
215   return QWidget::eventFilter(obj, theEvent);
216 }
217
218 //***************************************************
219 void XGUI_ObjectsBrowser::closeDocNameEditing(bool toSave)
220 {
221   myActiveDocLbl->deselect();
222   myActiveDocLbl->clearFocus();
223   myActiveDocLbl->releaseMouse();
224   myActiveDocLbl->setReadOnly(true);
225   if (toSave) {
226     // TODO: Save the name of root document
227     SessionPtr aMgr = ModelAPI_Session::get();
228     DocumentPtr aDoc = aMgr->moduleDocument();
229   } else {
230     myActiveDocLbl->setText(myActiveDocLbl->property("OldText").toString());
231   }
232 }
233
234 //***************************************************
235 void XGUI_ObjectsBrowser::onContextMenuRequested(QContextMenuEvent* theEvent)
236 {
237   QModelIndexList aIndexes;
238   QObjectPtrList aSelectedData = selectedObjects(&aIndexes);
239   bool toEnable = false;
240   if (aSelectedData.size() == 1) {
241     Qt::ItemFlags aFlags = dataModel()->flags(aIndexes.first());
242     toEnable = ((aFlags & Qt::ItemIsEditable) != 0);
243   }
244   foreach(QAction* aCmd, actions()) {
245     aCmd->setEnabled(toEnable);
246   }
247   emit contextMenuRequested(theEvent);
248 }
249
250 //***************************************************
251 void XGUI_ObjectsBrowser::onLabelContextMenuRequested(const QPoint& thePnt)
252 {
253   myTreeView->selectionModel()->clearSelection();
254   //Empty feature pointer means that selected root document
255   foreach(QAction* aCmd, actions()) {
256     aCmd->setEnabled(true);
257   }
258   QContextMenuEvent aEvent(QContextMenuEvent::Mouse, thePnt, myActiveDocLbl->mapToGlobal(thePnt));
259   emit contextMenuRequested(&aEvent);
260 }
261
262 //***************************************************
263 void XGUI_ObjectsBrowser::onEditItem()
264 {
265   QObjectPtrList aSelectedData = selectedObjects();
266   if (aSelectedData.size() > 0) {
267     ObjectPtr aFeature = aSelectedData.first();
268     if (aFeature) {  // Selection happens in TreeView
269       // Find index which corresponds the feature
270       QModelIndex aIndex;
271       foreach(QModelIndex aIdx, selectedIndexes()) {
272         ObjectPtr aFea = dataModel()->object(aIdx);
273         if (dataModel()->object(aIdx)->isSame(aFeature)) {
274           aIndex = aIdx;
275           break;
276         }
277       }
278       if (aIndex.isValid()) {
279         myTreeView->setCurrentIndex(aIndex);
280         myTreeView->edit(aIndex);
281       }
282       return;
283     }
284   }
285   //Selection happens in Upper label
286   myActiveDocLbl->setReadOnly(false);
287   myActiveDocLbl->setFocus();
288   myActiveDocLbl->selectAll();
289   myActiveDocLbl->grabMouse();
290   myActiveDocLbl->setProperty("OldText", myActiveDocLbl->text());
291 }
292
293 //***************************************************
294 void XGUI_ObjectsBrowser::rebuildDataTree()
295 {
296   myDocModel->rebuildDataTree();
297   update();
298 }
299
300 //***************************************************
301 void XGUI_ObjectsBrowser::setObjectsSelected(const QObjectPtrList& theObjects)
302 {
303   QList<QModelIndex> theIndexes;
304   QItemSelectionModel* aSelectModel = myTreeView->selectionModel();
305   aSelectModel->clear();
306
307   foreach(ObjectPtr aFeature, theObjects)
308   {
309     QModelIndex aIndex = myDocModel->objectIndex(aFeature);
310     if (aIndex.isValid()) {
311       aSelectModel->select(aIndex, QItemSelectionModel::Select);
312     }
313   }
314 }
315
316 //***************************************************
317 void XGUI_ObjectsBrowser::clearContent()  
318
319   myTreeView->clear(); 
320 }
321
322 void XGUI_ObjectsBrowser::setDataModel(ModuleBase_IDocumentDataModel* theModel)
323 {
324   myDocModel = theModel;
325   myTreeView->setModel(myDocModel);
326   QItemSelectionModel* aSelMod = myTreeView->selectionModel();
327   connect(aSelMod, SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
328           this, SLOT(onSelectionChanged(const QItemSelection&, const QItemSelection&)));
329 }
330
331 void XGUI_ObjectsBrowser::onSelectionChanged(const QItemSelection& theSelected,
332                                        const QItemSelection& theDeselected)
333 {
334   emit selectionChanged();
335 }
336
337 QObjectPtrList XGUI_ObjectsBrowser::selectedObjects(QModelIndexList* theIndexes) const
338 {
339   QObjectPtrList aList;
340   QModelIndexList aIndexes = selectedIndexes();
341   ModuleBase_IDocumentDataModel* aModel = dataModel();
342   QModelIndexList::const_iterator aIt;
343   for (aIt = aIndexes.constBegin(); aIt != aIndexes.constEnd(); ++aIt) {
344     if ((*aIt).column() == 0) {
345       ObjectPtr aObject = aModel->object(*aIt);
346       if (aObject) {
347         aList.append(aObject);
348         if (theIndexes)
349           theIndexes->append(*aIt);
350       }
351     }
352   }
353   return aList;
354 }