1 // Copyright (C) 2007-2023 CEA/DEN, EDF R&D, OPEN CASCADE
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 // File : SUIT_DataBrowser.cxx
21 // Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
23 #include "SUIT_DataBrowser.h"
24 #include "SUIT_TreeModel.h"
25 #include <QtxTreeView.h>
30 \class SUIT_DataBrowser
31 \brief Object browser customization.
36 \param parent parent widget
38 SUIT_DataBrowser::SUIT_DataBrowser( QWidget* parent )
39 : OB_Browser( parent )
46 \param root root data object
47 \param parent parent widget
49 SUIT_DataBrowser::SUIT_DataBrowser( SUIT_DataObject* root, QWidget* parent )
50 : OB_Browser( parent )
58 SUIT_DataBrowser::~SUIT_DataBrowser()
63 \brief Get popup menu client type.
64 \return popup client type
66 QString SUIT_DataBrowser::popupClientType() const
68 return "ObjectBrowser";
72 \brief Get root object.
75 SUIT_DataObject* SUIT_DataBrowser::root() const
77 SUIT_ProxyModel* m = qobject_cast<SUIT_ProxyModel*>( model() );
78 return m ? m->root() : 0;
82 \brief Set root object.
83 \param r new root object
85 void SUIT_DataBrowser::setRoot( SUIT_DataObject* r )
87 SUIT_ProxyModel* m = qobject_cast<SUIT_ProxyModel*>( model() );
93 \brief Get 'auto-update tree' flag value.
94 \return 'auto-update tree' flag value
95 \sa setAutoUpdate(), updateTree()
97 bool SUIT_DataBrowser::autoUpdate() const
99 SUIT_ProxyModel* m = qobject_cast<SUIT_ProxyModel*>( model() );
100 return m ? m->autoUpdate() : false;
104 \brief Set 'auto-update tree' flag value.
106 If this flag is set to \c true (by default), the object browser is updated
107 automatically when data tree is changed.
109 \param on 'auto-update tree' flag value
110 \sa autoUpdate(), updateTree()
112 void SUIT_DataBrowser::setAutoUpdate( const bool on )
114 SUIT_ProxyModel* m = qobject_cast<SUIT_ProxyModel*>( model() );
116 m->setAutoUpdate( on );
120 \brief Get 'updateModified' flag value.
121 \return 'updateModified' flag value
123 bool SUIT_DataBrowser::updateModified() const
125 SUIT_ProxyModel* m = qobject_cast<SUIT_ProxyModel*>( model() );
126 return m ? m->updateModified() : false;
130 \brief Set 'updateModified' flag value.
131 \param on 'updateModified' flag value
133 void SUIT_DataBrowser::setUpdateModified( const bool on )
135 SUIT_ProxyModel* m = qobject_cast<SUIT_ProxyModel*>( model() );
137 m->setUpdateModified( on );
141 \brief Update object browser starting from the object \obj;
142 open all branches automatically if \a autoOpen is \c true.
143 \param obj starting object for updating
144 \param autoOpen if \c true automatically open branches
146 void SUIT_DataBrowser::updateTree( SUIT_DataObject* obj, const bool /*autoOpen*/ )
148 SUIT_ProxyModel* m = qobject_cast<SUIT_ProxyModel*>( model() );
150 m->updateTree( obj );
153 if (myAutoSizeFirstColumn)
154 adjustFirstColumnWidth();
155 if (myAutoSizeColumns)
156 adjustColumnsWidth();
162 \brief Get current key accelerator by id.
163 \return current key accelerator
164 \sa setShortcutKey(), requestUpdate(), requestRename()
166 int SUIT_DataBrowser::shortcutKey(const int id) const
168 return myShortcutMap.value(id)->key()[0];
172 \brief Assign the key accelerator for the shortcut.
174 \param id id of the shortcut
175 \param key new key accelerator
176 \sa shortcutKey(), requestUpdate(), requestRename()
178 void SUIT_DataBrowser::setShortcutKey( const int id, const int key )
180 ShortcutMap::iterator it = myShortcutMap.find( id );
181 if( it != myShortcutMap.end() )
186 \brief Get list of selected data objects.
187 \return list of the currently selected data objects
189 DataObjectList SUIT_DataBrowser::getSelected() const
197 \brief Get list of selected data objects.
199 \param lst list to be filled with the currently selected data objects
201 void SUIT_DataBrowser::getSelected( DataObjectList& lst ) const
205 SUIT_ProxyModel* m = qobject_cast<SUIT_ProxyModel*>( model() );
208 QModelIndexList sel = selectedIndexes();
211 foreach( idx, sel ) {
212 SUIT_DataObject* obj = m->object( idx );
220 \brief Set selected object.
221 \param obj data object to set selected
222 \param append if \c true, the object is added to the current selection;
223 otherwise the previous selection is first cleared
225 void SUIT_DataBrowser::setSelected( const SUIT_DataObject* obj, const bool append )
227 SUIT_ProxyModel* m = qobject_cast<SUIT_ProxyModel*>( model() );
230 QModelIndex index = m->index( obj );
231 if ( index.isValid() )
232 select( index, true, append );
237 \brief function to sort QModelIndexList with qSort
239 bool modelIndexLessThan(const QModelIndex& lhs, const QModelIndex& rhs)
241 QModelIndex lhs_parent=lhs.parent();
242 QModelIndex rhs_parent=rhs.parent();
243 if(lhs_parent < rhs_parent)return true;
244 if(lhs_parent == rhs_parent) return lhs < rhs;
249 \brief Set list of selected data objects.
250 \param lst list of the data object to set selected
251 \param append if \c true, the objects are added to the current selection;
252 otherwise the previous selection is first cleared
254 void SUIT_DataBrowser::setSelected( const DataObjectList& lst, const bool append )
256 SUIT_ProxyModel* m = qobject_cast<SUIT_ProxyModel*>( model() );
259 QModelIndexList indexes;
260 SUIT_DataObject* obj;
262 foreach( obj, lst ) {
263 QModelIndex index = m->index( obj );
264 if ( index.isValid() )
265 indexes.append( index );
267 qSort(indexes.begin(), indexes.end(), modelIndexLessThan);
269 select( indexes, true, append ); // if !indexes.isEmpty() ???
274 \brief Make the view item for specified data object is visible.
275 \param obj data object
277 void SUIT_DataBrowser::ensureVisible( SUIT_DataObject* obj )
284 ensureVisible( lst );
288 \brief Make the view items for specified data objects is visible.
289 \param lst data object list
291 void SUIT_DataBrowser::ensureVisible( const DataObjectList& lst )
293 QtxTreeView* tv = treeView();
294 SUIT_AbstractModel* treeModel = dynamic_cast<SUIT_AbstractModel*>( model() );
295 if ( !tv || !treeModel )
298 for ( DataObjectList::const_iterator it = lst.begin(); it != lst.end(); ++it )
300 QModelIndex idx = treeModel->index( *it );
307 \brief Add custom actions to the popup menu.
308 \param menu popup menu
310 void SUIT_DataBrowser::contextMenuPopup( QMenu* menu )
312 createPopupMenu( menu );
316 \brief Set 'auto-size first column' flag value.
318 If this flag is set to \c true (by default), the first column width is resized
321 \param on 'auto-size first column' flag value
322 \sa setAutoSizeColumns()
324 void SUIT_DataBrowser::setAutoSizeFirstColumn( const bool on )
326 myAutoSizeFirstColumn = on;
330 \brief Set 'auto-size columns' flag value.
332 If this flag is set to \c true (by default is false), columns width except
333 the first column is resized to its contents.
335 \param on 'auto-size columns' flag value
336 \sa setAutoSizeFirstColumn()
338 void SUIT_DataBrowser::setAutoSizeColumns( const bool on )
340 myAutoSizeColumns = on;
344 \brief Process context menu request event.
345 \param e context menu event
347 void SUIT_DataBrowser::contextMenuEvent( QContextMenuEvent* e )
349 contextMenuRequest( e );
353 \brief Set 'resize on expand item' flag value.
355 If this flag is set to \c true (by default is false), after
356 expanding an item columns will be resized to its contents.
358 \param on 'resize on expand item' flag value
360 void SUIT_DataBrowser::setResizeOnExpandItem( const bool on )
362 myResizeOnExpandItem = on;
366 \brief Initialize object browser.
367 \param root root data object
369 void SUIT_DataBrowser::init( SUIT_DataObject* root )
371 SUIT_ProxyModel* m = new SUIT_ProxyModel( root, this );
372 connect( m, SIGNAL( modelUpdated() ), this, SLOT( onModelUpdated() ) );
375 setItemDelegate( qobject_cast<SUIT_ProxyModel*>( model() )->delegate() );
376 connect( treeView(), SIGNAL( sortingEnabled( bool ) ),
377 model(), SLOT( setSortingEnabled( bool ) ) );
378 connect( treeView(), SIGNAL( clicked( const QModelIndex& ) ),
379 this, SLOT( onClicked( const QModelIndex& ) ) );
380 connect( treeView(), SIGNAL( doubleClicked( const QModelIndex& ) ),
381 this, SLOT( onDblClicked( const QModelIndex& ) ) );
382 connect( treeView(), SIGNAL( expanded( const QModelIndex& ) ),
383 this, SLOT( onExpanded( const QModelIndex& ) ) );
384 connect( this , SIGNAL( requestRename() ),
385 this , SLOT ( onStartEditing() ));
387 myShortcutMap.insert(UpdateShortcut , new QShortcut( Qt::Key_F5, this, SIGNAL( requestUpdate() ), SIGNAL( requestUpdate() ) ) );
388 myShortcutMap.insert(RenameShortcut , new QShortcut( Qt::Key_F2, this, SIGNAL( requestRename() ), SIGNAL( requestRename() ) ) );
390 myAutoSizeFirstColumn = true;
391 myAutoSizeColumns = false;
392 myResizeOnExpandItem = false;
396 \fn void SUIT_DataBrowser::requestUpdate();
397 \brief The signal is emitted when the key accelerator
398 assigned for the update operation is pressed by the user.
400 By default, \c [F5] key is assigned for the update operation.
401 The key accelerator can be changed with the setShortcutKey() method.
403 \sa shortcutKey(), setShortcutKey()
407 \fn void SUIT_DataBrowser::clicked( SUIT_DataObject* o );
408 \brief This signal is emitted when a mouse button is clicked.
410 The data object the mouse was clicked on is specified by \a o.
411 The signal is only emitted when the object is valid.
413 \param o data object which is clicked
417 \fn void SUIT_DataBrowser::doubleClicked( SUIT_DataObject* o );
418 \brief This signal is emitted when a mouse button is double-clicked.
420 The data object the mouse was double-clicked on is specified by \a o.
421 The signal is only emitted when the object is valid.
423 \param o data object which is double-clicked
427 \brief Update internal modification time just after data model update
429 void SUIT_DataBrowser::onModelUpdated()
435 \brief Called when item is clicked in the tree view
438 Emits signal clicked( SUIT_DataObject* );
440 void SUIT_DataBrowser::onClicked( const QModelIndex& index )
442 SUIT_ProxyModel* m = qobject_cast<SUIT_ProxyModel*>( model() );
445 SUIT_DataObject* obj = m->object( index );
447 emit( clicked( obj ) );
448 m->emitClicked(obj, index);
454 \brief Called when item is double-clicked in the tree view
457 Emits signal doubleClicked( SUIT_DataObject* );
459 void SUIT_DataBrowser::onDblClicked( const QModelIndex& index )
461 SUIT_ProxyModel* m = qobject_cast<SUIT_ProxyModel*>( model() );
464 SUIT_DataObject* obj = m->object( index );
465 if ( obj ) emit( doubleClicked( obj ) );
470 \brief Called when item specified by index is expanded.
473 void SUIT_DataBrowser::onExpanded( const QModelIndex& /*index*/ )
475 if (myResizeOnExpandItem) {
476 adjustFirstColumnWidth();
477 adjustColumnsWidth();
482 \brief Make editable selected item in place.
485 void SUIT_DataBrowser::onStartEditing() {
486 DataObjectList sel = getSelected();
487 SUIT_ProxyModel* m = qobject_cast<SUIT_ProxyModel*>( model() );
488 if(treeView() && m && sel.count() == 1){
489 treeView()->edit(m->index( sel.first(), SUIT_DataObject::NameId ));