Salome HOME
22888: EDF 10437 GEOM: Dimensions improvements
[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   header()->setResizeMode( 1, QHeaderView::ResizeToContents );
77
78   QStringList rootNames;
79   rootNames << tr("GEOM_DIMENSIONS") << "";
80   myDimensionsItem = new QTreeWidgetItem( this, rootNames );
81   myDimensionsItem->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled );
82   addTopLevelItem( myDimensionsItem );
83
84   // get a free dockable window id
85   myWindowID = 11;
86   while( app->dockWindow( myWindowID ))
87     ++myWindowID;
88   ++myWindowID;
89
90   createActions();
91   setContextMenuPolicy( Qt::CustomContextMenu );
92   connect( this, SIGNAL( customContextMenuRequested(const QPoint&) ),
93            this, SLOT( showContextMenu(const QPoint&) ) );
94
95   connect( myStudy, SIGNAL( objVisibilityChanged( QString, Qtx::VisibilityState ) ), 
96            this, SLOT( updateVisibilityColumn( QString, Qtx::VisibilityState ) ) );
97   connect( app->objectBrowser(), SIGNAL( updated() ), this, SLOT( updateTree() ) );
98   GeometryGUI* aGeomGUI = dynamic_cast<GeometryGUI*>( app->module( "Geometry" ) );
99   connect( aGeomGUI, SIGNAL( DimensionsUpdated( const QString& ) ), this, SLOT( updateBranch( const QString& ) ) );
100   connect( this, SIGNAL( itemClicked( QTreeWidgetItem*, int) ), 
101            this, SLOT( onItemClicked( QTreeWidgetItem*, int ) ) );
102
103 }
104
105 GEOMGUI_TextTreeWdg::~GEOMGUI_TextTreeWdg()
106 {
107   //std::cout<<"~GEOMGUI_TextTreeWdg"<<std::endl;
108 }
109
110 //=================================================================================
111 // function : createActions
112 // purpose  : Create context popup menu actions.
113 //=================================================================================
114 void GEOMGUI_TextTreeWdg::createActions()
115 {
116   QAction* a = new QAction( tr( "MEN_DISPLAY" ), this );
117   a->setIcon( myVisibleIcon );
118   myActions.insert( GEOMOp::OpShow, a );
119   
120   QAction* b = new QAction( tr( "MEN_ERASE" ), this );
121   b->setIcon( myInvisibleIcon );
122   myActions.insert( GEOMOp::OpHide, b );
123 }
124
125 //=================================================================================
126 // function : updateTree
127 // purpose  :
128 //=================================================================================
129 void GEOMGUI_TextTreeWdg::updateTree()
130 {
131   myStudy = dynamic_cast<SalomeApp_Study*>( SUIT_Session::session()->activeApplication()->activeStudy() );
132   _PTR(Study) aDSStudy = myStudy->studyDS();
133   if ( aDSStudy ) {
134     _PTR(SComponent) SC ( aDSStudy->FindComponent( "GEOM" ) );
135     if ( SC ) {
136       _PTR(ChildIterator) anIter ( aDSStudy->NewChildIterator( SC ) );
137       anIter->InitEx( true );
138       QList<QString> objEntries = myObjects.keys();
139       while( anIter->More() ) {
140         _PTR(SObject) valSO ( anIter->Value() );
141         _PTR(SObject) refSO;
142         if ( !valSO->ReferencedObject( refSO ) ) {
143           // update tree of object's dimensions
144           QString anEntry = valSO->GetID().c_str();
145           updateBranch( anEntry );
146           objEntries.removeAll( anEntry );
147         }
148         anIter->Next();
149       }
150       foreach (QString entry, objEntries) {
151         removeBranch( entry, true );
152       }
153     }
154   }
155 }
156   
157 //=================================================================================
158 // function : updateBranch
159 // purpose  :
160 //=================================================================================
161 void GEOMGUI_TextTreeWdg::updateBranch( const QString& theEntry )
162 {
163   myStudy = dynamic_cast<SalomeApp_Study*>( SUIT_Session::session()->activeApplication()->activeStudy() );
164   if ( myStudy ) {
165     _PTR(Study) aStudyDS = myStudy->studyDS();
166     if ( aStudyDS ) {
167       _PTR(SObject) obj( aStudyDS->FindObjectID( theEntry.toStdString() ) );
168       QString aName = obj->GetName().c_str();
169   
170       GEOMGUI_DimensionProperty aProp;
171       aProp.LoadFromAttribute( myStudy, theEntry.toStdString() );
172       int nbProps = aProp.GetNumber();
173
174       QTreeWidgetItem* objectItem = itemFromEntry( theEntry );
175       if ( objectItem ) {
176         removeBranch( theEntry, nbProps > 0 ? false : true );
177       }
178       QStringList itemName;
179       if ( nbProps > 0 ) {
180         itemName << aName << "";
181         if ( !objectItem ) {
182           objectItem = new QTreeWidgetItem( myDimensionsItem, itemName );
183           objectItem->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled );
184           objectItem->setData( 1, Qt::UserRole, theEntry );
185           myDimensionsItem->addChild( objectItem );
186           myObjects.insert( theEntry, objectItem );
187           if ( myDimensionsItem->childCount() == 1 )
188             myDimensionsItem->setExpanded( true );
189         }
190         bool isDisplayed = myDisplayer.IsDisplayed( theEntry );
191         // read dimension records from property
192         for ( int anIt = 0; anIt < aProp.GetNumber(); ++anIt )
193           {
194             QString aName  = aProp.GetName( anIt );
195             bool isVisible = aProp.IsVisible( anIt );
196
197             QTreeWidgetItem* anItem = new QTreeWidgetItem;
198             anItem->setText( 0, aName );
199             //  if ( isDisplayed )
200             anItem->setIcon( 1, isVisible ? myVisibleIcon : myInvisibleIcon );
201             anItem->setData( 0, Qt::UserRole, anIt );
202             anItem->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled );
203             objectItem->addChild( anItem ); 
204           }
205       }
206     }
207   }
208 }
209
210 //=================================================================================
211 // function : removeBranch
212 // purpose  :
213 //=================================================================================
214 void GEOMGUI_TextTreeWdg::removeBranch( const QString& theEntry, bool force )
215 {
216   QTreeWidgetItem* objectItem = itemFromEntry( theEntry );
217   if ( !objectItem )
218     return;
219   qDeleteAll( objectItem->takeChildren() );
220   if ( force ) {
221     myDimensionsItem->removeChild( objectItem );
222     myObjects.remove( theEntry );
223   }
224 }
225
226 //=================================================================================
227 // function : onItemClicked()
228 // purpose  : called when tree item was clicked
229 //=================================================================================
230 void GEOMGUI_TextTreeWdg::onItemClicked( QTreeWidgetItem* theItem, int theColumn )
231 {
232   if( theColumn != 1 || theItem->icon( 1 ).isNull() || theItem->isDisabled() )
233     return;
234   
235   std::string anEntry = entryFromItem( theItem->parent() ).toStdString();
236   int aDimIndex = idFromItem( theItem );
237   GEOMGUI_DimensionProperty aProp;
238   aProp.LoadFromAttribute( myStudy, anEntry );
239   if ( aProp.IsVisible( aDimIndex ) ) {
240     aProp.SetVisible( aDimIndex, false );
241     theItem->setIcon( 1, myInvisibleIcon );
242   } else {
243     aProp.SetVisible( aDimIndex, true );
244     theItem->setIcon( 1, myVisibleIcon );
245   }
246   aProp.SaveToAttribute( myStudy, anEntry );
247   redisplay( anEntry.c_str() );
248 }
249
250 //=================================================================================
251 // function : idFromItem
252 // purpose  :
253 //=================================================================================
254 int GEOMGUI_TextTreeWdg::idFromItem( QTreeWidgetItem* theItem )
255 {
256   if ( !theItem )
257     return -1;
258
259   bool isIdOK = false;
260   const int anId = theItem->data( 0, Qt::UserRole ).toInt( &isIdOK );
261
262   return isIdOK ? anId : -1;
263 }
264
265 //=================================================================================
266 // function : entryFromItem
267 // purpose  :
268 //=================================================================================
269 QString GEOMGUI_TextTreeWdg::entryFromItem( QTreeWidgetItem* theShapeItem )
270 {
271   if ( !theShapeItem )
272     return "";
273
274   return theShapeItem->data( 1, Qt::UserRole ).toString();
275 }
276
277 //=================================================================================
278 // function : itemFromEntry
279 // purpose  :
280 //=================================================================================
281 QTreeWidgetItem* GEOMGUI_TextTreeWdg::itemFromEntry( QString theEntry )
282 {
283   if ( theEntry.isEmpty() )
284     return 0;
285
286   return myObjects.value( theEntry, 0 );
287 }
288
289 //=================================================================================
290 // function : updateVisibilityColumn
291 // purpose  : Update icons of dimension items.
292 //=================================================================================
293 void GEOMGUI_TextTreeWdg::updateVisibilityColumn( QString theEntry, Qtx::VisibilityState theState )
294 {
295   QTreeWidgetItem* anItem = itemFromEntry( theEntry );
296   if ( !anItem )
297     return;
298   anItem->setDisabled( theState != Qtx::ShownState );
299   QTreeWidgetItem* aChildItem;
300   GEOMGUI_DimensionProperty aProp;
301   for ( int i=0; i < anItem->childCount(); i++ ) {
302     aChildItem = anItem->child( i );
303     if ( theState == Qtx::ShownState ) {
304       aProp.LoadFromAttribute( myStudy, theEntry.toStdString() );
305       if ( aProp.GetNumber() == 0 )
306         continue;
307       aChildItem->setIcon( 1, aProp.IsVisible( idFromItem( aChildItem ) ) ? myVisibleIcon : myInvisibleIcon );
308       aChildItem->setDisabled( false );
309     } else {
310       aChildItem->setIcon( 1, QIcon() );
311       aChildItem->setDisabled( true );
312     }
313   }
314 }
315
316 //=================================================================================
317 // function : showContextMenu
318 // purpose  : 
319 //=================================================================================
320 void GEOMGUI_TextTreeWdg::showContextMenu( const QPoint& pos )
321 {
322   if ( selectedItems().isEmpty() )
323     return;
324   QMenu aMenu;
325   aMenu.addAction( myActions[GEOMOp::OpShow] );
326   aMenu.addAction( myActions[GEOMOp::OpHide] );
327   if ( selectedItems().count() == 1 ) {
328     QTreeWidgetItem* anItem = selectedItems().first();
329     QString anEntry = entryFromItem( anItem->parent() );
330     if ( !anEntry.isEmpty() ) {
331       GEOMGUI_DimensionProperty aProp;
332       aProp.LoadFromAttribute( myStudy, anEntry.toStdString() );
333       if ( aProp.GetNumber() == 0 )
334         return;
335       aMenu.clear();
336       if ( aProp.IsVisible( idFromItem( anItem ) ) )
337         aMenu.addAction( myActions[GEOMOp::OpHide] );
338       else
339         aMenu.addAction( myActions[GEOMOp::OpShow] );
340     }
341   }
342   QAction* selPopupItem = aMenu.exec( viewport()->mapToGlobal(pos) );
343   if ( selPopupItem == myActions[GEOMOp::OpShow] )
344     setVisibility( true );
345   else if ( selPopupItem == myActions[GEOMOp::OpHide] )
346     setVisibility( false );
347 }
348
349 //=================================================================================
350 // function : setVisibility
351 // purpose  : 
352 //=================================================================================
353 void GEOMGUI_TextTreeWdg::setVisibility( bool theVisibility )
354 {
355   if ( myDimensionsItem->isSelected() ) {
356     // set visibility for all dimensions
357     QTreeWidgetItem* anItem;
358     foreach ( QString entry, myObjects.keys() ) {
359       anItem = itemFromEntry( entry );
360       if ( !anItem->isDisabled() )
361         setShapeDimensionsVisibility( entry, theVisibility );
362     }
363     return;
364   }
365   foreach ( QTreeWidgetItem* item, selectedItems() ) {
366     if ( item->isDisabled() || item->parent()->isSelected() )
367       continue;
368     QString anEntry = entryFromItem( item );
369     if ( !anEntry.isEmpty() ) {
370       // it is a shape item
371       setShapeDimensionsVisibility( anEntry, theVisibility );
372     } else {
373       // it is a dimension item
374       anEntry = entryFromItem( item->parent() );
375       setDimensionVisibility( anEntry, item, theVisibility );
376     }
377   }
378 }
379
380 //=================================================================================
381 // function : setShapeDimensionsVisibility
382 // purpose  : 
383 //=================================================================================
384 void GEOMGUI_TextTreeWdg::setShapeDimensionsVisibility( QString theEntry, bool theVisibility )
385 {
386   QTreeWidgetItem* anItem = itemFromEntry( theEntry );
387   QTreeWidgetItem* aChildItem;
388   for ( int i=0; i < anItem->childCount(); i++ ) {
389     aChildItem = anItem->child( i );
390     setDimensionVisibility( theEntry, aChildItem, theVisibility );
391   }
392   redisplay( theEntry );
393 }
394
395 //=================================================================================
396 // function : setDimensionVisibility
397 // purpose  : 
398 //=================================================================================
399 void GEOMGUI_TextTreeWdg::setDimensionVisibility( QString theEntry, QTreeWidgetItem* theDimItem, bool theVisibility )
400 {
401   GEOMGUI_DimensionProperty aProp;
402   aProp.LoadFromAttribute( myStudy, theEntry.toStdString() );
403   int aDimIndex = idFromItem( theDimItem );
404   if ( aProp.GetNumber() == 0  || aProp.IsVisible( aDimIndex ) == theVisibility )
405     return;;
406   aProp.SetVisible( aDimIndex, theVisibility );
407   aProp.SaveToAttribute( myStudy, theEntry.toStdString() );
408
409   theDimItem->setIcon( 1, theVisibility ? myVisibleIcon : myInvisibleIcon );
410   redisplay( theEntry );
411 }
412
413 //=================================================================================
414 // function : redisplay
415 // purpose  : 
416 //=================================================================================
417 void GEOMGUI_TextTreeWdg::redisplay( QString theEntry )
418 {
419   Handle(SALOME_InteractiveObject) io = new SALOME_InteractiveObject( theEntry.toLatin1().constData(), "GEOM", "TEMP_IO" );
420   myDisplayer.Redisplay( io );
421 }