1 // Copyright (C) 2007-2015 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // File : OB_Browser.cxx
24 // Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
26 #include "OB_Browser.h"
28 //#include "OB_Filter.h"
29 //#include "OB_ListItem.h"
30 //#include "OB_ListView.h"
32 #include <QtxTreeView.h>
33 #include <QtxSearchTool.h>
34 //#include <SUIT_DataObjectIterator.h>
38 #include <QItemSelection>
40 #include <QVBoxLayout>
41 #include <QAbstractItemModel>
42 #include <QAbstractItemDelegate>
43 #include <QHeaderView>
49 \class OB_Browser::ToolTip
50 Tool tip for OB_Browser.
53 //TODO: ToolTip commented - to be removed or revised
55 class OB_Browser::ToolTip : public QToolTip
58 ToolTip( OB_Browser* b, QWidget* p = 0 );
61 void maybeTip( const QPoint& );
64 OB_Browser* myBrowser;
71 OB_Browser::ToolTip::ToolTip( OB_Browser* b, QWidget* p )
81 OB_Browser::ToolTip::~ToolTip()
86 It is called when there is a possibility that a tool tip
87 should be shown and must decide whether there is a tool tip for the point
88 in the widget that this QToolTip object relates to.
89 \param pos - point co-ordinates
92 void OB_Browser::ToolTip::maybeTip( const QPoint& pos )
94 if ( !parentWidget() || !myBrowser || !myBrowser->isShowToolTips() )
97 QListView* lv = myBrowser->listView();
99 QListViewItem* item = lv->itemAt( pos );
100 SUIT_DataObject* obj = myBrowser->dataObject( item );
104 QString aText = obj->toolTip();
106 if ( aText.isEmpty() )
109 QRect aRect = lv->itemRect( item );
118 \brief Object browser widget which can be used to handle tree-like data model.
120 The class OB_Browser implements public API of an object browser widget
121 that can be used to display arbitrary application data in a hierarchical form.
122 It is based on Qt4 model/view architecture.
124 Object browser can be used with conjuction of any custom item model inherited
125 from QAbstractItemModel class (see Qt 4 reference manual).
127 The class provides a functionality get/modify selection, drag-n-drop of the
133 \param parent paren widget
134 \param model data model
136 OB_Browser::OB_Browser( QWidget* parent, QAbstractItemModel* model )
141 myView = new QtxTreeView( this ); // create tree view
142 myView->setRootIsDecorated( true ); // show root item
143 myView->setSelectionMode( QAbstractItemView::ExtendedSelection ); // enable extended selection mode
144 myView->setAllColumnsShowFocus( true ); // focus is shown in all columns
146 // enable drag-n-drop support
147 myView->setDragDropMode( QAbstractItemView::DragDrop ); // enable both drag and drop operations
148 myView->setDropIndicatorShown( true ); // show drag indicator on dragging
150 // set-up search tool
151 mySearchTool = new QtxSearchTool( this, myView ); // create search tool
152 mySearchTool->setFrameStyle( QFrame::NoFrame | QFrame::Plain ); // do not show frame
153 mySearchTool->setActivators( QtxSearchTool::StandardKey | QtxSearchTool::SlashKey ); // set activation mode
154 mySearchTool->setSearcher( new QtxTreeViewSearcher( myView ) ); // assign searcher (for tree view)
157 QVBoxLayout* main = new QVBoxLayout( this );
158 main->addWidget( myView );
159 main->addWidget( mySearchTool );
160 main->setMargin( 0 );
161 main->setSpacing( 3 );
163 // TODO: decide what to do with tooltip
164 //myShowToolTips = true;
165 //myTooltip = new ToolTip( this, myView->viewport() );
167 // TODO: drag-n-drop works differently - SUIT_TreeModel to be updated
168 // and QTreeView needs some setup
169 //connect( myView, SIGNAL( dropped( QPtrList<QListViewItem>, QListViewItem*, int ) ),
170 // this, SLOT( onDropped( QPtrList<QListViewItem>, QListViewItem*, int ) ) );
173 connect( myView, SIGNAL( selectionChanged() ),
174 this, SIGNAL( selectionChanged() ) );
180 OB_Browser::~OB_Browser()
187 \brief Get data model.
191 QAbstractItemModel* OB_Browser::model() const
193 return myView->model();
197 \brief Set data model.
198 \param model data model
201 void OB_Browser::setModel( QAbstractItemModel* model )
203 myView->setModel( model );
209 \brief Get current item delegate (items renderer).
210 \return currently used item delegate
211 \sa setItemDelegate()
213 QAbstractItemDelegate* OB_Browser::itemDelegate() const
215 return myView->itemDelegate();
219 \brief Set item delegate (items renderer).
220 \param d custom item delegate
223 void OB_Browser::setItemDelegate( QAbstractItemDelegate* d )
225 myView->setItemDelegate( d );
229 \brief Check if controls for expanding and collapsing top-level items are shown.
230 \return \c true if top-level items are decorated
231 \sa setRootIsDecorated()
233 bool OB_Browser::rootIsDecorated() const
235 return myView->rootIsDecorated();
239 \brief Show/hide controls for expanding and collapsing top-level items.
240 \param decor if \c true, top-level items are decorated
241 \sa rootIsDecorated()
243 void OB_Browser::setRootIsDecorated( const bool decor )
245 if ( decor != rootIsDecorated() )
246 myView->setRootIsDecorated( decor );
250 \brief Check if "Sorting" popup menu command for the header is enabled.
251 \return \c true if "Sorting" menu command is enabled
252 \sa setSortMenuEnabled()
254 bool OB_Browser::sortMenuEnabled() const
256 return myView->sortMenuEnabled();
260 \brief Enable/disable "Sorting" popup menu command for the header.
261 \param enableSortMenu if \c true, enable "Sorting" menu command
262 \sa sortMenuEnabled()
264 void OB_Browser::setSortMenuEnabled( const bool enabled )
266 if ( enabled != sortMenuEnabled() )
267 myView->setSortMenuEnabled( enabled );
271 \brief Get search tool widget.
272 \return search tool widget
273 \sa isSearchToolEnabled(), setSearchToolEnabled()
275 QtxSearchTool* OB_Browser::searchTool() const
281 \brief Check if search tool is enabled.
282 \return \c true if search tool is enabled
283 \sa setSearchToolEnabled(), searchTool()
285 bool OB_Browser::isSearchToolEnabled() const
287 return mySearchTool->isEnabled();
291 \brief Enable/disable search tool.
292 \param enable pass \c true to enable search tool
293 \sa isSearchToolEnabled(), searchTool()
295 void OB_Browser::setSearchToolEnabled( const bool enable )
297 if ( mySearchTool->isEnabled() == enable )
300 mySearchTool->setEnabled( enable );
301 if ( !mySearchTool->isEnabled() )
302 mySearchTool->hide();
306 \brief Get number of levels which should be automatically expanded
307 when updating the data tree.
308 \return number of levels to be auto-opened on tree updating
309 \sa setAutoOpenLevel()
311 int OB_Browser::autoOpenLevel() const
313 return myAutoOpenLevel;
317 \brief Set number of levels which should be automatically expanded
318 when updating the data tree.
319 \param levels number of levels to be auto-opened on tree updating
322 void OB_Browser::setAutoOpenLevel( const int levels )
324 if ( myAutoOpenLevel != levels )
325 myAutoOpenLevel = levels;
329 \brief Expand all branches to the specified number of levels.
331 If \a levels value is negative, then autoOpenLevel() value is used instead.
333 \param levels number of levels to be expanded
336 void OB_Browser::openLevels( const int levels )
338 myView->expandLevels( levels < 0 ? autoOpenLevel() : levels );
342 \return state "are tooltips shown"
345 bool OB_Browser::isShowToolTips()
347 return myShowToolTips;
351 Sets new value of state "are tooltips shown"
352 \param theDisplay - new value
355 void OB_Browser::setShowToolTips( const bool theDisplay )
357 myShowToolTips = theDisplay;
362 \brief Get number of selected items.
363 \return number of selected items
365 int OB_Browser::numberOfSelected() const
367 // we take selection by rows
368 return myView->selectionModel() ? myView->selectionModel()->selectedRows().count() : 0;
372 \brief Get all selected items.
373 \return unsorted list of selected indexes with no duplicates
375 QModelIndexList OB_Browser::selectedIndexes() const
377 // we take selection by rows
378 return myView->selectionModel() ? myView->selectionModel()->selectedRows() : QModelIndexList();
382 \brief Get selection containing information about selected ranges.
383 \return QItemSelection instance
385 const QItemSelection OB_Browser::selection() const
387 static QItemSelection emptySel;
388 QItemSelection sel = emptySel;
389 if ( myView->selectionModel() )
390 sel = myView->selectionModel()->selection();
395 \brief Select/deselect specified model index.
396 \param index model index to be selected/deselected
397 \param on if \c true, the index will be selected, otherwise - deselected
398 \param keepSelection if \c true (default) the previous selection is kept,
399 otherwise it is first cleared
401 void OB_Browser::select( const QModelIndex& index, const bool on, const bool keepSelection )
403 if ( myView->selectionModel() ) {
404 QItemSelectionModel::SelectionFlags f = on ? QItemSelectionModel::Select : QItemSelectionModel::Deselect;
405 f = f | QItemSelectionModel::Rows;
406 if ( !keepSelection )
407 f = f | QItemSelectionModel::Clear;
409 myView->selectionModel()->select( index, f );
414 \brief Select/deselect specified model indices.
415 \param indexes model indices to be selected/deselected
416 \param on if \c true, the indices will be selected, otherwise - deselected
417 \param keepSelection if \c true (default) the previous selection is kept,
418 otherwise it is first cleared
420 void OB_Browser::select( const QModelIndexList& indexes, const bool on, const bool keepSelection )
422 bool blocked = myView->signalsBlocked();
423 myView->blockSignals( true );
427 if ( !indexes.isEmpty() ) {
428 QItemSelection mysel;
429 // select by range if indexes are contiguous
430 QModelIndex first=indexes.at(0);
431 QModelIndex last=first;
432 if (indexes.size() > 1) {
433 for (int i = 1; i < indexes.size(); ++i)
436 if(idx.parent().row()==last.parent().row() && idx.parent().column()==last.parent().column() &&
437 idx.row()==last.row()+1 && idx.column()==last.column())
439 // index is contiguous to last: extend the range
444 // index idx is not contiguous: create a new range
445 mysel.select(first,last);
451 mysel.select(first,last);
453 if ( myView->selectionModel() ) {
454 QItemSelectionModel::SelectionFlags f = on ? QItemSelectionModel::Select : QItemSelectionModel::Deselect;
455 f = f | QItemSelectionModel::Rows;
456 if ( !keepSelection )
457 f = f | QItemSelectionModel::Clear;
458 myView->selectionModel()->select( mysel, f );
461 else if ( !keepSelection )
463 myView->clearSelection();
466 myView->blockSignals( blocked );
467 emit( selectionChanged() );
471 \brief Check if specified model index is expanded or collapsed.
472 \param index model index
473 \return \c true if model index is expanded
476 bool OB_Browser::isOpen( const QModelIndex& index ) const
478 return index.isValid() && model() && model()->hasChildren( index ) && myView->isExpanded( index );
482 \brief Expand/collapse the specified model index.
483 \param index model index
484 \param open if \c true, the index will be expanded, otherwse - collapsed
487 void OB_Browser::setOpen( const QModelIndex& index, const bool open )
489 myView->setExpanded( index, open ); // hasChildren() ???
493 \brief Adjust first column width to its contents.
495 void OB_Browser::adjustWidth()
497 myView->resizeColumnToEncloseContents( 0 );
501 \brief Adjust first column width to its contents.
503 void OB_Browser::adjustFirstColumnWidth()
505 myView->resizeColumnToEncloseContents( 0 );
509 \brief Adjust all columns width to its contents except the first column.
511 void OB_Browser::adjustColumnsWidth()
513 for ( int aCol = 1; aCol < myView->header()->count(); aCol++ ) {
514 if ( myView->columnWidth( aCol ) > 0 )
515 myView->resizeColumnToEncloseContents( aCol );
520 \return SUIT object correspondint to item at position 'pos'
521 \param pos - position
523 /* TODO: removed - QTreeView::indexAt() should be used
524 SUIT_DataObject* OB_Browser::dataObjectAt( const QPoint& pos ) const
526 SUIT_DataObject* obj = 0;
528 QListView* lv = listView();
530 obj = dataObject( lv->itemAt( pos ) );
536 \return filter of list view
539 OB_Filter* OB_Browser::filter() const
541 return myView->filter();
545 Changes filter of list view
546 \param f - new filter
549 void OB_Browser::setFilter( OB_Filter* f )
551 myView->setFilter( f );
555 Sets global width mode
556 \param mode - new width mode
559 void OB_Browser::setWidthMode( QListView::WidthMode mode )
561 for ( int i = 0, n = myView->columns(); i < n; i++ )
562 if( mode!=QListView::Maximum || myView->columnWidth( i )>0 )
563 myView->setColumnWidthMode( i, mode );
568 \param obj - start object
569 \param autoOpen - to open automatically branches of autoOpenLevel()
573 void OB_Browser::updateTree( SUIT_DataObject* obj, const bool autoOpen )
575 // QTime t1 = QTime::currentTime();
577 if ( !obj && !(obj = getRootObject()) )
580 DataObjectKey curKey;
581 DataObjectMap selObjs, openObjs;
582 DataObjectKeyMap selKeys, openKeys;
584 int selNum = numberOfSelected();
586 SUIT_DataObject* curObj = storeState( selObjs, openObjs, selKeys, openKeys, curKey );
590 restoreState( selObjs, openObjs, curObj, selKeys, openKeys, curKey );
597 if ( selNum != numberOfSelected() )
598 emit selectionChanged();
600 // QTime t2 = QTime::currentTime();
601 // qDebug( QString( "update tree time = %1 msecs" ).arg( t1.msecsTo( t2 ) ) );
605 Replaces part of tree starting at object 'src' by tree starting at object 'trg'
608 void OB_Browser::replaceTree( SUIT_DataObject* src, SUIT_DataObject* trg )
610 if ( !src || !trg || src == trg || src->root() != getRootObject() )
613 DataObjectKey curKey;
614 DataObjectMap selObjs, openObjs;
615 DataObjectKeyMap selKeys, openKeys;
617 int selNum = numberOfSelected();
619 SUIT_DataObject* curObj = storeState( selObjs, openObjs, selKeys, openKeys, curKey );
621 SUIT_DataObject* parent = src->parent();
622 int pos = parent ? parent->childPos( src ) : -1;
626 removeConnections( src );
627 if ( isAutoDeleteObjects() )
630 if ( parent && pos != -1 )
631 parent->insertChild( trg, pos );
633 trg->setParent( parent );
636 createConnections( trg );
638 restoreState( selObjs, openObjs, curObj, selKeys, openKeys, curKey );
642 if ( selNum != numberOfSelected() )
643 emit selectionChanged();
647 Adjusts width by item
651 void OB_Browser::adjustWidth( QListViewItem* item )
655 item->widthChanged( 0 );
656 if ( item->isOpen() )
657 adjustWidth( item->firstChild() );
658 item = item->nextSibling();
664 \remove all items referencing current (through data objects)
667 void OB_Browser::removeReferences( QListViewItem* item )
672 SUIT_DataObject* obj = dataObject( item );
673 obj->disconnect( this, SLOT( onDestroyed( SUIT_DataObject* ) ) );
674 myItems.remove( obj );
676 QListViewItem* i = item->firstChild();
679 removeReferences( i );
680 i = i->nextSibling();
685 Connects all children to SLOT onDestroyed
687 /* TODO: move to SUIT_TreeModel
688 void OB_Browser::createConnections( SUIT_DataObject* obj )
693 DataObjectList childList;
694 obj->children( childList, true );
696 childList.prepend( obj );
698 for ( DataObjectListIterator it( childList ); it.current(); ++it )
699 it.current()->connect( this, SLOT( onDestroyed( SUIT_DataObject* ) ) );
703 Disconnects all children from SLOT onDestroyed
705 /* TODO: move to SUIT_TreeModel
706 void OB_Browser::removeConnections( SUIT_DataObject* obj )
711 DataObjectList childList;
712 obj->children( childList, true );
714 childList.prepend( obj );
716 for ( DataObjectListIterator it( childList ); it.current(); ++it )
717 it.current()->disconnect( this, SLOT( onDestroyed( SUIT_DataObject* ) ) );
721 Stores states (opened, selected) of current tree items
723 \param selObjs, selKeys - maps of selected objects
724 \param openObjs, openKeys - maps of opened objects
725 \param curKey - map of current objects
727 /* TODO: to be revised
728 SUIT_DataObject* OB_Browser::storeState( DataObjectMap& selObjs, DataObjectMap& openObjs,
729 DataObjectKeyMap& selKeys, DataObjectKeyMap& openKeys,
730 DataObjectKey& curKey ) const
732 QListView* lv = listView();
736 SUIT_DataObject* curObj = dataObject( lv->currentItem() );
738 curKey = objectKey( curObj );
740 for ( QListViewItemIterator it( lv ); it.current(); ++it )
742 SUIT_DataObject* obj = dataObject( it.current() );
746 selObjs.insert( obj, lv->isSelected( it.current() ) );
747 openObjs.insert( obj, lv->isOpen( it.current() ) );
748 if ( lv->isSelected( it.current() ) )
749 selKeys.insert( objectKey( obj ), 0 );
750 if ( lv->isOpen( it.current() ) )
751 openKeys.insert( objectKey( obj ), 0 );
758 Restores states (opened, selected) of current tree items
759 \param selObjs, selKeys - maps of selected objects
760 \param openObjs, openKeys - maps of opened objects
761 \param curKey - map of current objects
763 /* TODO: to be revised
764 void OB_Browser::restoreState( const DataObjectMap& selObjs, const DataObjectMap& openObjs,
765 const SUIT_DataObject* curObj, const DataObjectKeyMap& selKeys,
766 const DataObjectKeyMap& openKeys, const DataObjectKey& curKey )
768 QListView* lv = listView();
772 bool block = lv->signalsBlocked();
773 lv->blockSignals( true );
775 QListViewItem* curItem = 0;
776 for ( QListViewItemIterator it( lv ); it.current(); ++it )
778 QListViewItem* item = it.current();
779 SUIT_DataObject* obj = dataObject( item );
784 DataObjectKey key = objectKey( obj );
786 if ( selObjs.contains( obj ) )
788 if ( selObjs[obj] && !lv->isSelected( item ) )
789 lv->setSelected( item, true );
791 else if ( !key.isNull() && selKeys.contains( key ) && !lv->isSelected( item ) )
792 lv->setSelected( item, true );
794 if ( openObjs.contains( obj ) )
796 bool parentOpen = true;
797 if( item && item->parent() )
798 parentOpen = item->parent()->isOpen();
800 if ( openObjs[obj] && parentOpen )
801 lv->setOpen( item, true );
803 else if ( !key.isNull() && openKeys.contains( key ) )
805 bool parentOpen = true;
806 if( item && item->parent() )
807 parentOpen = item->parent()->isOpen();
810 lv->setOpen( item, true );
813 if ( !curItem && ( curObj == obj || ( !curKey.isNull() && curKey == key )) )
818 lv->setCurrentItem( curItem );
820 lv->blockSignals( block );
824 Creates object key by tree item
826 /* TODO: move to SUIT_TreeModel
827 OB_Browser::DataObjectKey OB_Browser::objectKey( QListViewItem* i ) const
829 return objectKey( dataObject( i ) );
833 Creates object key by SUIT object
835 /* TODO: move to SUIT_TreeModel
836 OB_Browser::DataObjectKey OB_Browser::objectKey( SUIT_DataObject* obj ) const
841 return DataObjectKey( obj->key() );
846 \brief Get tree view widget.
847 \return tree view widget of the object browser
849 QtxTreeView* OB_Browser::treeView() const
855 \brief Process context menu request event.
856 \param e context menu event
858 void OB_Browser::contextMenuEvent( QContextMenuEvent* e )
860 QMenu* popup = new QMenu();
862 createPopupMenu( popup );
864 Qtx::simplifySeparators( popup );
866 if ( !popup->actions().isEmpty() )
867 popup->exec( e->globalPos() );
872 \brief Get the time of the latest updating.
873 \return latest updating time
875 unsigned long OB_Browser::getModifiedTime() const
877 return myModifiedTime;
881 \brief Update the time of the latest updating.
883 void OB_Browser::setModified()
885 myModifiedTime = clock();
889 \brief Called when "Expand all" popup menu command is activated.
891 Expands all selected items recursively.
893 void OB_Browser::onExpandAll()
895 QModelIndexList indexes = selectedIndexes();
897 disconnect( treeView(), SIGNAL( expanded( const QModelIndex& ) ),
898 this, SLOT( onExpanded( const QModelIndex& ) ) );
900 foreach ( index, indexes ) {
901 myView->expandAll( index );
903 connect( treeView(), SIGNAL( expanded( const QModelIndex& ) ),
904 this, SLOT( onExpanded( const QModelIndex& ) ) );
905 emit(onExpanded( index));
909 \brief Called when "Collapse all" popup menu command is activated.
911 Collapse all selected items recursively.
913 void OB_Browser::onCollapseAll()
915 QModelIndexList indexes = selectedIndexes();
918 foreach ( index, indexes ) {
919 myView->collapseAll( index );
924 SLOT: called if SUIT object is destroyed
926 /* TODO: moved to SUIT_TreeModel
927 void OB_Browser::onDestroyed( SUIT_DataObject* obj )
933 SLOT: called on finish of drag-n-drop operation
934 \param items - dragged items
935 \param item - destination (item on that they were dropped)
936 \param action - QDropEvent::Action
938 // TODO: drag-n-drop works differently - SUIT_TreeModel to be updated
939 // and QTreeView needs some setup
941 void OB_Browser::onDropped( QPtrList<QListViewItem> items, QListViewItem* item, int action )
943 SUIT_DataObject* obj = dataObject( item );
948 for ( QPtrListIterator<QListViewItem> it( items ); it.current(); ++it )
950 SUIT_DataObject* o = dataObject( it.current() );
955 if ( !lst.isEmpty() )
956 emit dropped( lst, obj, action );
960 Updates texts of items
962 /* TODO: to be removed
963 void OB_Browser::updateText()
965 if ( myColumnIds.isEmpty() )
968 QListView* lv = listView();
972 for ( QListViewItemIterator it( lv ); it.current(); ++it )
974 SUIT_DataObject* obj = dataObject( it.current() );
978 for( QMap<int, int>::iterator itr = myColumnIds.begin(); itr != myColumnIds.end(); ++itr )
979 it.current()->setText( itr.data(), obj->text( itr.key() ) );
984 \return true if item must be updated
985 \param item - item to be checked
987 /* TODO: to be revised
988 bool OB_Browser::needToUpdateTexts( QListViewItem* item ) const
990 SUIT_DataObject* obj = dataObject( item );
994 for( QMap<int, int>::const_iterator it = myColumnIds.begin(); it != myColumnIds.end(); ++it )
995 if( item->text( it.data() ) != obj->text( it.key() ) )
1001 Updates texts of item
1002 \param item - item to be updated
1004 /* TODO: to be revised
1005 void OB_Browser::updateText( QListViewItem* item )
1007 SUIT_DataObject* obj = dataObject( item );
1011 for( QMap<int, int>::iterator it = myColumnIds.begin(); it != myColumnIds.end(); ++it )
1012 item->setText( it.data(), obj->text( it.key() ) );
1017 \brief Add custom actions to the popup menu.
1018 \param menu popup menu
1020 void OB_Browser::createPopupMenu( QMenu* menu )
1022 menu->addSeparator();
1024 QModelIndexList indexes = selectedIndexes();
1026 bool closed = false, opened = false;
1028 for ( QModelIndexList::Iterator it = indexes.begin();
1029 it != indexes.end() && !closed; ++it ) {
1030 closed = hasCollased( *it );
1033 for ( QModelIndexList::Iterator it = indexes.begin();
1034 it != indexes.end() && !opened; ++it ) {
1035 opened = hasExpanded( *it );
1039 menu->addAction( tr( "MEN_EXPAND_ALL" ), this, SLOT( onExpandAll() ) );
1041 menu->addAction( tr( "MEN_COLLAPSE_ALL" ), this, SLOT( onCollapseAll() ) );
1043 if ( isSearchToolEnabled() ) {
1044 menu->addSeparator();
1045 menu->addAction( tr( "MEN_FIND" ), searchTool(), SLOT( find() ), QKeySequence(Qt::CTRL + Qt::Key_F) );
1046 menu->addSeparator();
1051 Expands item with all it's children
1053 /* TODO: to be revised
1054 void OB_Browser::expand( QListViewItem* item )
1059 item->setOpen( true );
1060 for ( QListViewItem* child = item->firstChild(); child; child = child->nextSibling() )
1065 \brief Check if model index is collapsed or has collapsed children.
1066 \return \c true if item or one of its children is collapsed
1068 bool OB_Browser::hasCollased( const QModelIndex& index ) const
1070 bool result = false;
1072 if ( index.isValid() && model() ) {
1073 bool hasChildren = model()->hasChildren( index );
1074 result = hasChildren && !myView->isExpanded( index );
1075 if ( !result && hasChildren ) {
1076 int rows = model()->rowCount( index );
1077 for ( int i = 0; i < rows && !result; i ++ ) {
1078 QModelIndex child = model()->index( i, 0, index );
1079 result = hasCollased( child );
1087 \brief Check if model index is expanded or has expanded children.
1088 \return \c true if item or one of its children is expanded
1090 bool OB_Browser::hasExpanded( const QModelIndex& index ) const
1092 bool result = false;
1094 if ( index.isValid() && model() ) {
1095 bool hasChildren = model()->hasChildren( index );
1096 result = hasChildren && myView->isExpanded( index );
1097 if ( !result && hasChildren ) {
1098 int rows = model()->rowCount( index );
1099 for ( int i = 0; i < rows && !result; i ++ ) {
1100 QModelIndex child = model()->index( i, 0, index );
1101 result = hasExpanded( child );
1110 \param obj - SUIT object to be removed
1111 \param autoUpd - auto tree updating
1113 /* TODO: moved to SUIT_TreeModel
1114 void OB_Browser::removeObject( SUIT_DataObject* obj, const bool autoUpd )
1119 // Removing list view items from <myItems> recursively for all children.
1120 // Otherwise, "delete item" line will destroy all item's children,
1121 // and <myItems> will contain invalid pointers (see ~QListViewItem() description in Qt docs)
1122 DataObjectList childList;
1123 obj->children( childList, true );
1124 for ( DataObjectListIterator it( childList ); it.current(); ++it )
1126 it.current()->disconnect( this, SLOT( onDestroyed( SUIT_DataObject* ) ) );
1127 myItems.remove( it.current() );
1130 QListViewItem* item = listViewItem( obj );
1132 obj->disconnect( this, SLOT( onDestroyed( SUIT_DataObject* ) ) );
1133 myItems.remove( obj );
1135 if ( obj == myRoot )
1137 // remove all child list view items
1145 if ( isAutoUpdate() )
1147 SUIT_DataObject* pObj = item && item->parent() ? dataObject( item->parent() ) : 0;
1148 updateTree( pObj, false );
1155 Opens branches from 1 to autoOpenLevel()
1158 /* TODO: to be revised
1159 void OB_Browser::autoOpenBranches()
1169 /* TODO: to be revised
1170 void OB_Browser::openBranch( QListViewItem* item, const int level )
1177 item->setOpen( true );
1178 openBranch( item->firstChild(), level - 1 );
1179 item = item->nextSibling();
1184 SLOT: called on double click on item, emits signal
1186 /* TODO: to be revised
1187 void OB_Browser::onDoubleClicked( QListViewItem* item )
1190 emit doubleClicked( dataObject( item ) );
1195 \fn void OB_Browser::selectionChanged();
1196 \brief Emitted when selection is changed in the Object Browser.
1199 QByteArray OB_Browser::getOpenStates( int theColumn ) const
1202 QDataStream aStream( &aData, QIODevice::WriteOnly );
1203 MapOfOpenStates aMap;
1204 const_cast<OB_Browser*>( this )->openStates( true, aMap, QModelIndex(), theColumn );
1205 MapOfOpenStates::const_iterator anIt = aMap.begin(), aLast = aMap.end();
1206 for( ; anIt!=aLast; anIt++ )
1208 QString anEntry = anIt.key();
1209 qint32 anOpenAttr = anIt.value() ? 1 : 0;
1210 aStream << anEntry << anOpenAttr;
1215 void OB_Browser::setOpenStates( const QByteArray& theData, int theColumn )
1217 QByteArray* aData = const_cast<QByteArray*>( &theData );
1218 QDataStream aStream( aData, QIODevice::ReadOnly );
1219 MapOfOpenStates aMap;
1220 while( !aStream.atEnd() )
1224 aStream >> anEntry >> anOpenAttr;
1225 bool isOpen = anOpenAttr!=0;
1226 aMap[anEntry] = isOpen;
1228 openStates( false, aMap, QModelIndex(), theColumn );
1231 void OB_Browser::openStates( bool isGet, MapOfOpenStates& theMap, const QModelIndex& theIndex, int theColumn )
1233 if( theIndex.isValid() )
1235 QString anEntry = theIndex.sibling( theIndex.row(), theColumn ).data().toString();
1239 isOpen = treeView()->isExpanded( theIndex );
1240 theMap[anEntry] = isOpen;
1244 isOpen = theMap.contains( anEntry ) ? theMap[anEntry] : false;
1245 treeView()->setExpanded( theIndex, isOpen );
1249 const QAbstractItemModel* aModel = model();
1251 int n = aModel->rowCount( theIndex );
1252 for( int i=0; i<n; i++ )
1254 QModelIndex aChild = aModel->index( i, 0, theIndex );
1255 openStates( isGet, theMap, aChild, theColumn );