Salome HOME
Merge branch 'V7_dev' into V8_0_0_BR
[modules/geom.git] / src / GEOMGUI / GEOMGUI_TextTreeWdg.cxx
1 // Copyright (C) 2015  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // File      : GEOMGUI_TextTreeWdg.cxx
20 // Author    : Alexander KOVALEV (akl)
21
22 #include "GEOMGUI_TextTreeWdg.h"
23
24 #include "GEOMGUI_DimensionProperty.h"
25 #include "GeometryGUI.h"
26 #include "GeometryGUI_Operations.h"
27 #include <GEOM_Constants.h>
28 #include <GEOMUtils.hxx>
29
30 // GUI includes
31 #include <LightApp_Module.h>
32 #include <SalomeApp_Application.h>
33 #include <SalomeApp_Study.h>
34 #include <SUIT_Desktop.h>
35 #include <SUIT_Session.h>
36 #include <SUIT_ResourceMgr.h>
37 #include <SUIT_DataBrowser.h>
38
39 // Qt includes
40 #include <QAction>
41 #include <QMenu>
42 #include <QString>
43 #include <QLabel>
44 #include <QLineEdit>
45 #include <QTreeWidget>
46 #include <QHeaderView>
47 #include <QGroupBox>
48 #include <QVBoxLayout>
49 #include <QHBoxLayout>
50 #include <QHash>
51
52 GEOMGUI_TextTreeWdg::GEOMGUI_TextTreeWdg( SalomeApp_Application* app )
53   : myDisplayer(NULL)
54 {
55   myStudy = dynamic_cast<SalomeApp_Study*>( app->activeStudy() );
56   myDisplayer = GEOM_Displayer( myStudy );
57
58   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
59   myVisibleIcon = QIcon( resMgr->loadPixmap( "SUIT", tr( "ICON_DATAOBJ_VISIBLE" ) ) );
60   myInvisibleIcon = QIcon( resMgr->loadPixmap( "SUIT", tr( "ICON_DATAOBJ_INVISIBLE" ) ) );
61
62   setWindowTitle( tr( "TEXT_TREE_VIEW_TITLE" ) );
63   setObjectName( "geomTextTreeWdg" );
64
65   setRootIsDecorated( true );
66   setSelectionMode( QAbstractItemView::ExtendedSelection );
67   setAllColumnsShowFocus( true );
68   setUniformRowHeights( true );
69
70   QStringList columnNames;
71   columnNames << tr("TEXT_TREE_VIEW_NAME") << "";
72   QTreeWidgetItem * headerItem = new QTreeWidgetItem( columnNames );
73   headerItem->setIcon( 1, myVisibleIcon );
74   setHeaderItem ( headerItem ); 
75   header()->moveSection( 1, 0 );
76 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
77   header()->setResizeMode( 1, QHeaderView::ResizeToContents );
78 #else
79   header()->setSectionResizeMode( 1, QHeaderView::ResizeToContents );
80 #endif
81   QStringList rootNames;
82   rootNames << tr("GEOM_DIMENSIONS") << "";
83   myDimensionsItem = new QTreeWidgetItem( this, rootNames );
84   myDimensionsItem->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled );
85   addTopLevelItem( myDimensionsItem );
86
87   // get a free dockable window id
88   myWindowID = 11;
89   while( app->dockWindow( myWindowID ))
90     ++myWindowID;
91   ++myWindowID;
92
93   createActions();
94   setContextMenuPolicy( Qt::CustomContextMenu );
95   connect( this, SIGNAL( customContextMenuRequested(const QPoint&) ),
96            this, SLOT( showContextMenu(const QPoint&) ) );
97
98   connect( myStudy, SIGNAL( objVisibilityChanged( QString, Qtx::VisibilityState ) ), 
99            this, SLOT( updateVisibilityColumn( QString, Qtx::VisibilityState ) ) );
100   connect( app->objectBrowser(), SIGNAL( updated() ), this, SLOT( updateTree() ) );
101   GeometryGUI* aGeomGUI = dynamic_cast<GeometryGUI*>( app->module( "Geometry" ) );
102   connect( aGeomGUI, SIGNAL( DimensionsUpdated( const QString& ) ), this, SLOT( updateBranch( const QString& ) ) );
103   connect( this, SIGNAL( itemClicked( QTreeWidgetItem*, int) ), 
104            this, SLOT( onItemClicked( QTreeWidgetItem*, int ) ) );
105
106 }
107
108 GEOMGUI_TextTreeWdg::~GEOMGUI_TextTreeWdg()
109 {
110   //std::cout<<"~GEOMGUI_TextTreeWdg"<<std::endl;
111 }
112
113 //=================================================================================
114 // function : createActions
115 // purpose  : Create context popup menu actions.
116 //=================================================================================
117 void GEOMGUI_TextTreeWdg::createActions()
118 {
119   QAction* a = new QAction( tr( "MEN_DISPLAY" ), this );
120   a->setIcon( myVisibleIcon );
121   myActions.insert( GEOMOp::OpShow, a );
122   
123   QAction* b = new QAction( tr( "MEN_ERASE" ), this );
124   b->setIcon( myInvisibleIcon );
125   myActions.insert( GEOMOp::OpHide, b );
126 }
127
128 //=================================================================================
129 // function : updateTree
130 // purpose  :
131 //=================================================================================
132 void GEOMGUI_TextTreeWdg::updateTree()
133 {
134   myStudy = dynamic_cast<SalomeApp_Study*>( SUIT_Session::session()->activeApplication()->activeStudy() );
135   _PTR(Study) aDSStudy = myStudy->studyDS();
136   if ( aDSStudy ) {
137     _PTR(SComponent) SC ( aDSStudy->FindComponent( "GEOM" ) );
138     if ( SC ) {
139       _PTR(ChildIterator) anIter ( aDSStudy->NewChildIterator( SC ) );
140       anIter->InitEx( true );
141       QList<QString> objEntries = myObjects.keys();
142       while( anIter->More() ) {
143         _PTR(SObject) valSO ( anIter->Value() );
144         _PTR(SObject) refSO;
145         if ( !valSO->ReferencedObject( refSO ) ) {
146           // update tree of object's dimensions
147           QString anEntry = valSO->GetID().c_str();
148           updateBranch( anEntry );
149           objEntries.removeAll( anEntry );
150         }
151         anIter->Next();
152       }
153       foreach (QString entry, objEntries) {
154         removeBranch( entry, true );
155       }
156     }
157   }
158 }
159   
160 //=================================================================================
161 // function : updateBranch
162 // purpose  :
163 //=================================================================================
164 void GEOMGUI_TextTreeWdg::updateBranch( const QString& theEntry )
165 {
166   myStudy = dynamic_cast<SalomeApp_Study*>( SUIT_Session::session()->activeApplication()->activeStudy() );
167   if ( myStudy ) {
168     _PTR(Study) aStudyDS = myStudy->studyDS();
169     if ( aStudyDS ) {
170       _PTR(SObject) obj( aStudyDS->FindObjectID( theEntry.toStdString() ) );
171       QString aName = obj->GetName().c_str();
172   
173       GEOMGUI_DimensionProperty aProp;
174       aProp.LoadFromAttribute( myStudy, theEntry.toStdString() );
175       int nbProps = aProp.GetNumber();
176
177       QTreeWidgetItem* objectItem = itemFromEntry( theEntry );
178       if ( objectItem ) {
179         removeBranch( theEntry, nbProps > 0 ? false : true );
180       }
181       QStringList itemName;
182       if ( nbProps > 0 ) {
183         itemName << aName << "";
184         if ( !objectItem ) {
185           objectItem = new QTreeWidgetItem( myDimensionsItem, itemName );
186           objectItem->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled );
187           objectItem->setData( 1, Qt::UserRole, theEntry );
188           myDimensionsItem->addChild( objectItem );
189           myObjects.insert( theEntry, objectItem );
190           if ( myDimensionsItem->childCount() == 1 )
191             myDimensionsItem->setExpanded( true );
192         }
193         bool isDisplayed = myDisplayer.IsDisplayed( theEntry );
194         // read dimension records from property
195         for ( int anIt = 0; anIt < aProp.GetNumber(); ++anIt )
196           {
197             QString aName  = aProp.GetName( anIt );
198             bool isVisible = aProp.IsVisible( anIt );
199
200             QTreeWidgetItem* anItem = new QTreeWidgetItem;
201             anItem->setText( 0, aName );
202             //  if ( isDisplayed )
203             anItem->setIcon( 1, isVisible ? myVisibleIcon : myInvisibleIcon );
204             anItem->setData( 0, Qt::UserRole, anIt );
205             anItem->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled );
206             objectItem->addChild( anItem ); 
207           }
208       }
209     }
210   }
211 }
212
213 //=================================================================================
214 // function : removeBranch
215 // purpose  :
216 //=================================================================================
217 void GEOMGUI_TextTreeWdg::removeBranch( const QString& theEntry, bool force )
218 {
219   QTreeWidgetItem* objectItem = itemFromEntry( theEntry );
220   if ( !objectItem )
221     return;
222   qDeleteAll( objectItem->takeChildren() );
223   if ( force ) {
224     myDimensionsItem->removeChild( objectItem );
225     myObjects.remove( theEntry );
226   }
227 }
228
229 //=================================================================================
230 // function : onItemClicked()
231 // purpose  : called when tree item was clicked
232 //=================================================================================
233 void GEOMGUI_TextTreeWdg::onItemClicked( QTreeWidgetItem* theItem, int theColumn )
234 {
235   if( theColumn != 1 || theItem->icon( 1 ).isNull() || theItem->isDisabled() )
236     return;
237   
238   std::string anEntry = entryFromItem( theItem->parent() ).toStdString();
239   int aDimIndex = idFromItem( theItem );
240   GEOMGUI_DimensionProperty aProp;
241   aProp.LoadFromAttribute( myStudy, anEntry );
242   if ( aProp.IsVisible( aDimIndex ) ) {
243     aProp.SetVisible( aDimIndex, false );
244     theItem->setIcon( 1, myInvisibleIcon );
245   } else {
246     aProp.SetVisible( aDimIndex, true );
247     theItem->setIcon( 1, myVisibleIcon );
248   }
249   aProp.SaveToAttribute( myStudy, anEntry );
250   redisplay( anEntry.c_str() );
251 }
252
253 //=================================================================================
254 // function : idFromItem
255 // purpose  :
256 //=================================================================================
257 int GEOMGUI_TextTreeWdg::idFromItem( QTreeWidgetItem* theItem )
258 {
259   if ( !theItem )
260     return -1;
261
262   bool isIdOK = false;
263   const int anId = theItem->data( 0, Qt::UserRole ).toInt( &isIdOK );
264
265   return isIdOK ? anId : -1;
266 }
267
268 //=================================================================================
269 // function : entryFromItem
270 // purpose  :
271 //=================================================================================
272 QString GEOMGUI_TextTreeWdg::entryFromItem( QTreeWidgetItem* theShapeItem )
273 {
274   if ( !theShapeItem )
275     return "";
276
277   return theShapeItem->data( 1, Qt::UserRole ).toString();
278 }
279
280 //=================================================================================
281 // function : itemFromEntry
282 // purpose  :
283 //=================================================================================
284 QTreeWidgetItem* GEOMGUI_TextTreeWdg::itemFromEntry( QString theEntry )
285 {
286   if ( theEntry.isEmpty() )
287     return 0;
288
289   return myObjects.value( theEntry, 0 );
290 }
291
292 //=================================================================================
293 // function : updateVisibilityColumn
294 // purpose  : Update icons of dimension items.
295 //=================================================================================
296 void GEOMGUI_TextTreeWdg::updateVisibilityColumn( QString theEntry, Qtx::VisibilityState theState )
297 {
298   QTreeWidgetItem* anItem = itemFromEntry( theEntry );
299   if ( !anItem )
300     return;
301   anItem->setDisabled( theState != Qtx::ShownState );
302   QTreeWidgetItem* aChildItem;
303   GEOMGUI_DimensionProperty aProp;
304   for ( int i=0; i < anItem->childCount(); i++ ) {
305     aChildItem = anItem->child( i );
306     if ( theState == Qtx::ShownState ) {
307       aProp.LoadFromAttribute( myStudy, theEntry.toStdString() );
308       if ( aProp.GetNumber() == 0 )
309         continue;
310       aChildItem->setIcon( 1, aProp.IsVisible( idFromItem( aChildItem ) ) ? myVisibleIcon : myInvisibleIcon );
311       aChildItem->setDisabled( false );
312     } else {
313       aChildItem->setIcon( 1, QIcon() );
314       aChildItem->setDisabled( true );
315     }
316   }
317 }
318
319 //=================================================================================
320 // function : showContextMenu
321 // purpose  : 
322 //=================================================================================
323 void GEOMGUI_TextTreeWdg::showContextMenu( const QPoint& pos )
324 {
325   if ( selectedItems().isEmpty() )
326     return;
327   QMenu aMenu;
328   aMenu.addAction( myActions[GEOMOp::OpShow] );
329   aMenu.addAction( myActions[GEOMOp::OpHide] );
330   if ( selectedItems().count() == 1 ) {
331     QTreeWidgetItem* anItem = selectedItems().first();
332     QString anEntry = entryFromItem( anItem->parent() );
333     if ( !anEntry.isEmpty() ) {
334       GEOMGUI_DimensionProperty aProp;
335       aProp.LoadFromAttribute( myStudy, anEntry.toStdString() );
336       if ( aProp.GetNumber() == 0 )
337         return;
338       aMenu.clear();
339       if ( aProp.IsVisible( idFromItem( anItem ) ) )
340         aMenu.addAction( myActions[GEOMOp::OpHide] );
341       else
342         aMenu.addAction( myActions[GEOMOp::OpShow] );
343     }
344   }
345   QAction* selPopupItem = aMenu.exec( viewport()->mapToGlobal(pos) );
346   if ( selPopupItem == myActions[GEOMOp::OpShow] )
347     setVisibility( true );
348   else if ( selPopupItem == myActions[GEOMOp::OpHide] )
349     setVisibility( false );
350 }
351
352 //=================================================================================
353 // function : setVisibility
354 // purpose  : 
355 //=================================================================================
356 void GEOMGUI_TextTreeWdg::setVisibility( bool theVisibility )
357 {
358   if ( myDimensionsItem->isSelected() ) {
359     // set visibility for all dimensions
360     QTreeWidgetItem* anItem;
361     foreach ( QString entry, myObjects.keys() ) {
362       anItem = itemFromEntry( entry );
363       if ( !anItem->isDisabled() )
364         setShapeDimensionsVisibility( entry, theVisibility );
365     }
366     return;
367   }
368   foreach ( QTreeWidgetItem* item, selectedItems() ) {
369     if ( item->isDisabled() || item->parent()->isSelected() )
370       continue;
371     QString anEntry = entryFromItem( item );
372     if ( !anEntry.isEmpty() ) {
373       // it is a shape item
374       setShapeDimensionsVisibility( anEntry, theVisibility );
375     } else {
376       // it is a dimension item
377       anEntry = entryFromItem( item->parent() );
378       setDimensionVisibility( anEntry, item, theVisibility );
379     }
380   }
381 }
382
383 //=================================================================================
384 // function : setShapeDimensionsVisibility
385 // purpose  : 
386 //=================================================================================
387 void GEOMGUI_TextTreeWdg::setShapeDimensionsVisibility( QString theEntry, bool theVisibility )
388 {
389   QTreeWidgetItem* anItem = itemFromEntry( theEntry );
390   QTreeWidgetItem* aChildItem;
391   for ( int i=0; i < anItem->childCount(); i++ ) {
392     aChildItem = anItem->child( i );
393     setDimensionVisibility( theEntry, aChildItem, theVisibility );
394   }
395   redisplay( theEntry );
396 }
397
398 //=================================================================================
399 // function : setDimensionVisibility
400 // purpose  : 
401 //=================================================================================
402 void GEOMGUI_TextTreeWdg::setDimensionVisibility( QString theEntry, QTreeWidgetItem* theDimItem, bool theVisibility )
403 {
404   GEOMGUI_DimensionProperty aProp;
405   aProp.LoadFromAttribute( myStudy, theEntry.toStdString() );
406   int aDimIndex = idFromItem( theDimItem );
407   if ( aProp.GetNumber() == 0  || aProp.IsVisible( aDimIndex ) == theVisibility )
408     return;;
409   aProp.SetVisible( aDimIndex, theVisibility );
410   aProp.SaveToAttribute( myStudy, theEntry.toStdString() );
411
412   theDimItem->setIcon( 1, theVisibility ? myVisibleIcon : myInvisibleIcon );
413   redisplay( theEntry );
414 }
415
416 //=================================================================================
417 // function : redisplay
418 // purpose  : 
419 //=================================================================================
420 void GEOMGUI_TextTreeWdg::redisplay( QString theEntry )
421 {
422   Handle(SALOME_InteractiveObject) io = new SALOME_InteractiveObject( theEntry.toLatin1().constData(), "GEOM", "TEMP_IO" );
423   myDisplayer.Redisplay( io );
424 }