Salome HOME
57d868a19f18ad277be9623711f6067442c50fef
[modules/hydro.git] / src / HYDROGUI / HYDROGUI_DataBrowser.cxx
1 // Copyright (C) 2014-2015  EDF-R&D
2 // This library is free software; you can redistribute it and/or
3 // modify it under the terms of the GNU Lesser General Public
4 // License as published by the Free Software Foundation; either
5 // version 2.1 of the License, or (at your option) any later version.
6 //
7 // This library is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10 // Lesser General Public License for more details.
11 //
12 // You should have received a copy of the GNU Lesser General Public
13 // License along with this library; if not, write to the Free Software
14 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
15 //
16 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
17 //
18
19 #include "HYDROGUI_DataBrowser.h"
20 #include "HYDROGUI_Module.h"
21 #include "HYDROGUI_DataObject.h"
22
23 #include <LightApp_Application.h>
24 #include <LightApp_OBSelector.h>
25 #include <LightApp_SelectionMgr.h>
26 #include <QHeaderView>
27 #include <QtxSearchTool.h>
28 #include <QtxTreeView.h>
29 #include <SUIT_DataObject.h>
30 #include <SUIT_ResourceMgr.h>
31 #include <SUIT_SelectionMgr.h>
32 #include <SUIT_DataObjectIterator.h>
33         
34 #define VISIBILITY_COLUMN_WIDTH 25
35
36
37 #include <SUIT_Selector.h>
38 #include <SUIT_DataOwner.h>
39
40 #include <QObject>
41 #include <QShortcut>
42 #include <QMenu>
43
44 class SUIT_DataBrowser;
45 class LightApp_DataObject;
46
47
48 #include "LightApp_DataOwner.h"
49 #include "LightApp_DataObject.h"
50 #include "LightApp_Application.h"
51 #include <SUIT_DataBrowser.h>
52 #include <SUIT_Session.h>
53 #include <SUIT_DataObjectIterator.h>
54 #include <QTime>
55 #include <time.h>
56
57
58 // The selector is redefined in order to correct the selection in the browser.
59 // The main modification is to call fillEntries without the selector modified
60 // time compare. The modified time is result of the clock() method.
61 // On Linux, the method clock() returns the same values with some delay. So, it is possible,
62 // that time has the same value, but the browser has already other objects.
63 // So, the obsole entries can be in the saved entries by the filled method.
64 // May be it will be improved in the latest version of GUI_SRC.
65 // This redefinition is done for tag V7_3_0 of GUI_SRC.
66 class HYDROGUI_OBSelector : public LightApp_OBSelector
67 {
68 public:
69   HYDROGUI_OBSelector( SUIT_DataBrowser*, SUIT_SelectionMgr* );
70   virtual ~HYDROGUI_OBSelector();
71
72 protected:
73   virtual void       getSelection( SUIT_DataOwnerPtrList& ) const;
74   virtual void       setSelection( const SUIT_DataOwnerPtrList& );
75
76 private:
77   void               fillEntries( QMap<QString, LightApp_DataObject*>& );
78
79 private:
80   SUIT_DataOwnerPtrList               mySelectedList;
81   QMap<QString, LightApp_DataObject*> myEntries;
82 };
83
84 HYDROGUI_OBSelector::HYDROGUI_OBSelector( SUIT_DataBrowser* ob, SUIT_SelectionMgr* mgr )
85 : LightApp_OBSelector( ob, mgr )
86 {
87 }
88
89 /*!
90   \brief Destructor.
91 */
92 HYDROGUI_OBSelector::~HYDROGUI_OBSelector()
93 {
94 }
95
96 /*!
97   \brief Get list of currently selected objects.
98   \param theList list to be filled with the selected objects owners
99   \ This method is necessary to fill the cach containter mySelectedList
100   \ It is the same as in LightApp_OBSelector
101 */
102 void HYDROGUI_OBSelector::getSelection( SUIT_DataOwnerPtrList& theList ) const
103 {
104   SUIT_DataBrowser* aBrowser = browser();
105
106   if ( mySelectedList.count() == 0 ) {
107     SUIT_Session* session = SUIT_Session::session();
108     SUIT_Application* sapp = session ? session->activeApplication() : 0;
109     LightApp_Application* app = dynamic_cast<LightApp_Application*>( sapp );
110     if( !app || !aBrowser )
111       return;
112
113     DataObjectList objlist;
114     aBrowser->getSelected( objlist );
115     HYDROGUI_OBSelector* that = (HYDROGUI_OBSelector*)this;
116     QListIterator<SUIT_DataObject*> it( objlist );
117     while ( it.hasNext() ) {
118       LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>( it.next() );
119       if ( obj && app->checkDataObject( obj) ) {
120 #ifndef DISABLE_SALOMEOBJECT
121         Handle(SALOME_InteractiveObject) aSObj = new SALOME_InteractiveObject
122           ( obj->entry().toLatin1().constData(),
123             obj->componentDataType().toLatin1().constData(),
124             obj->name().toLatin1().constData() );
125         LightApp_DataOwner* owner = new LightApp_DataOwner( aSObj  );
126 #else
127         LightApp_DataOwner* owner = new LightApp_DataOwner( obj->entry() );
128 #endif
129         that->mySelectedList.append( SUIT_DataOwnerPtr( owner ) );
130       }
131     }
132   }
133   theList = mySelectedList;
134 }
135
136 /*!
137   \brief Set selection.
138   \param theList list of the object owners to be set selected
139   \ It is the same as in LightApp_OBSelector. The difference is in the row with
140   \ the modification time check.
141 */
142 void HYDROGUI_OBSelector::setSelection( const SUIT_DataOwnerPtrList& theList )
143 {
144   SUIT_DataBrowser* aBrowser = browser();
145   if ( !aBrowser )
146     return;
147
148   // this is the difference to LightApp_OBSelector. For this, this class is redefined
149   //if( myEntries.count() == 0 || myModifiedTime < aBrowser->getModifiedTime() )
150   {
151     fillEntries( myEntries );
152   }
153
154   DataObjectList objList;
155   for ( SUIT_DataOwnerPtrList::const_iterator it = theList.begin(); 
156         it != theList.end(); ++it ) {
157     const LightApp_DataOwner* owner = dynamic_cast<const LightApp_DataOwner*>( (*it).operator->() );
158
159     if ( owner && myEntries.contains( owner->entry() ) )
160       objList.append( myEntries[owner->entry()] );
161   }
162
163   aBrowser->setSelected( objList );
164   mySelectedList.clear();
165 }
166
167 /*!
168   \brief Fill map of the data objects currently shown in the Object Browser.
169   \param entries map to be filled
170   \ It is the same as in LightApp_OBSelector
171 */
172 void HYDROGUI_OBSelector::fillEntries( QMap<QString, LightApp_DataObject*>& entries )
173 {
174   entries.clear();
175
176   SUIT_DataBrowser* aBrowser = browser();
177   if ( !aBrowser )
178     return;
179
180   for ( SUIT_DataObjectIterator it( aBrowser->root(),
181                                     SUIT_DataObjectIterator::DepthLeft ); it.current(); ++it ) {
182     LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>( it.current() );
183     if ( obj )
184       entries.insert( obj->entry(), obj );
185   }
186
187   setModified();
188 }
189
190
191 HYDROGUI_DataBrowser::HYDROGUI_DataBrowser( HYDROGUI_Module* theModule, SUIT_DataObject* theRoot, QWidget* theParent )
192 : SUIT_DataBrowser( theRoot, theParent ), myModule( theModule )
193 {
194   SUIT_ResourceMgr* resMgr = theModule->getApp()->resourceMgr();
195
196   if ( ( !theRoot ) && theModule )
197   {
198     // Initialize the root with the module data model
199     setRoot( new CAM_ModuleObject( theModule->dataModel(), NULL ) );
200   }
201
202   setSortMenuEnabled( true );
203   setAutoUpdate( true );
204   setUpdateModified( true );
205
206   if ( resMgr->hasValue( "ObjectBrowser", "auto_hide_search_tool" ) )
207     searchTool()->enableAutoHide( resMgr->booleanValue( "ObjectBrowser", "auto_hide_search_tool" ) );
208
209   setWindowTitle( tr( "OBJECT_BROWSER" ) );
210   connect( this, SIGNAL( requestUpdate() ), theModule->getApp(), SLOT( onRefresh() ) );
211
212   QString EntryCol = QObject::tr( "ENTRY_COLUMN" );
213   QString RefObjCol = tr( "REF_OBJECT_COLUMN" );
214   QString AltitudeCol = tr( "ALTITUDE_COLUMN" );
215
216   SUIT_AbstractModel* treeModel = dynamic_cast<SUIT_AbstractModel*>( model() );
217   //RKV: treeModel->setSearcher( theModule->getApp() );
218   treeModel->setSearcher( this ); //RKV
219   treeModel->registerColumn( 0, EntryCol, LightApp_DataObject::EntryId );
220   treeModel->setAppropriate( EntryCol, Qtx::Toggled );
221   treeModel->registerColumn( 0, RefObjCol, HYDROGUI_DataObject::RefObjectId );
222   treeModel->setAppropriate( RefObjCol, Qtx::Toggled );
223   treeModel->registerColumn( 0, AltitudeCol, HYDROGUI_DataObject::AltitudeObjId );
224   treeModel->setAppropriate( AltitudeCol, Qtx::Toggled );
225
226   // Mantis issue 0020136: Drag&Drop in OB
227   SUIT_ProxyModel* proxyModel = dynamic_cast<SUIT_ProxyModel*>(treeModel);
228   if ( proxyModel ) {
229     connect( proxyModel, 
230       SIGNAL( dropped( const QList<SUIT_DataObject*>&, SUIT_DataObject*, int, Qt::DropAction ) ),
231       SIGNAL( dropped( const QList<SUIT_DataObject*>&, SUIT_DataObject*, int, Qt::DropAction ) ) );
232
233     //// Connect signal emitted after editing for updating after objects renaming
234     SUIT_TreeModel* aMiniModel = dynamic_cast<SUIT_TreeModel*>( proxyModel->sourceModel() );
235     if ( aMiniModel )
236     {
237       connect( aMiniModel, SIGNAL( dataChanged( const QModelIndex &, const QModelIndex & ) ), 
238         SIGNAL( dataChanged() ) );
239     }
240
241     // Do updating also in the module's main object browser.
242     if ( theModule )
243     {
244       SUIT_DataBrowser* aModulBrowser = theModule->getApp()->objectBrowser();
245       if ( aModulBrowser )
246       {
247         SUIT_ProxyModel* aPModel = dynamic_cast<SUIT_ProxyModel*>(aModulBrowser->model());
248         if ( aPModel )
249         {
250           SUIT_TreeModel* aModel = dynamic_cast<SUIT_TreeModel*>(aPModel->sourceModel());
251           //connect( proxyModel, SIGNAL( dataChanged( const QModelIndex &, const QModelIndex & ) ), 
252           //  aPModel, SIGNAL( dataChanged( const QModelIndex &, const QModelIndex & ) ) );
253           //connect( proxyModel, SIGNAL( dataChanged( const QModelIndex &, const QModelIndex & ) ), 
254           //  aModel, SIGNAL( dataChanged( const QModelIndex &, const QModelIndex & ) ) );
255           connect( proxyModel, SIGNAL( modelUpdated() ), aModel, SIGNAL( modelUpdated() ) );
256         }
257       }
258     }
259   }
260
261   // temporary commented
262   /*
263   OB_ListView* ob_list = dynamic_cast<OB_ListView*>( const_cast<QListView*>( listView() ) );
264   if( ob_list )
265     ob_list->setColumnMaxWidth( 0, theModule->getApp()->desktop()->width()/4 );
266
267   setFilter( new LightApp_OBFilter( theModule->getApp()->selectionMgr() ) );
268   */
269
270   // Create OBSelector
271   new HYDROGUI_OBSelector( this, theModule->getApp()->selectionMgr() );
272
273   treeView()->header()->setResizeMode(SUIT_DataObject::VisibilityId, QHeaderView::Fixed);
274   treeView()->header()->moveSection(SUIT_DataObject::NameId,SUIT_DataObject::VisibilityId);
275   treeView()->setColumnWidth(SUIT_DataObject::VisibilityId, VISIBILITY_COLUMN_WIDTH);
276   treeView()->hideColumn( SUIT_DataObject::VisibilityId );
277   treeView()->hideColumn( LightApp_DataObject::EntryId );
278   connectPopupRequest( theModule->getApp(), SLOT( onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ) ) );
279 }
280
281 HYDROGUI_DataBrowser::~HYDROGUI_DataBrowser()
282 {
283 }
284
285 SUIT_DataObject* HYDROGUI_DataBrowser::findObject( const QString& theEntry ) const
286 {
287   LightApp_DataObject* aCurObj;
288   for ( SUIT_DataObjectIterator it( root(), SUIT_DataObjectIterator::DepthLeft ); it.current(); ++it ) {
289     aCurObj = dynamic_cast<LightApp_DataObject*>( it.current() );
290     if ( aCurObj && aCurObj->entry() == theEntry )
291       return aCurObj;
292   }
293   return NULL;
294 }
295
296 /*!
297   \brief Switch read only mode for the Object Browser.
298   \param theIsReadOnly if true - read only mode will be turned on
299 */
300 void HYDROGUI_DataBrowser::setReadOnly( const bool theIsReadOnly )
301 {
302   //TODO: to be reimplemented
303
304   // Enable/disable edit triggers
305   foreach ( QTreeView* aView, findChildren<QTreeView*>() ) {
306     aView->setDragEnabled ( !theIsReadOnly );
307     aView->setEditTriggers ( theIsReadOnly ?
308                              QAbstractItemView::NoEditTriggers :
309                              QAbstractItemView::DoubleClicked );
310   }
311
312   // Enable/disable rename shortcut
313   QList<QShortcut*> aShortcuts = findChildren<QShortcut*>();
314   QShortcut* aShortcut;
315   foreach( aShortcut, aShortcuts ) {
316     if ( aShortcut->key() == QKeySequence( shortcutKey( RenameShortcut ) ) ) {
317       aShortcut->setEnabled( !theIsReadOnly );
318     }
319   }
320 }
321
322 void HYDROGUI_DataBrowser::createPopupMenu( QMenu* theMenu )
323 {
324   theMenu->clear();
325   DataObjectList aSelection = getSelected();
326   bool isOnlyZones = aSelection.size() > 0;
327   foreach( SUIT_DataObject* anObj, aSelection )
328   {
329     HYDROGUI_DataObject* aHydroObj = dynamic_cast<HYDROGUI_DataObject*>( anObj );
330     if( aHydroObj )
331     {
332       Handle(HYDROData_Entity) aModelObj = aHydroObj->modelObject();
333       if( !aModelObj.IsNull() )
334       {
335         isOnlyZones = aModelObj->GetKind()==KIND_ZONE;
336         if( !isOnlyZones )
337           break;
338       }
339       else
340       {
341         isOnlyZones = false;
342         break;
343       }
344     }
345     else
346     {
347       isOnlyZones = false;
348       break;
349     }
350   }
351
352   if( isOnlyZones )
353     theMenu->addAction( tr( "ZONE_TO_NEW_REGION" ), this, SIGNAL( newRegion() ) );
354 }