1 // Copyright (C) 2007-2023 CEA, EDF, 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 // The indexes must have the same parent to be selected
437 if(idx.parent()==last.parent() &&
438 idx.row()==last.row()+1 && idx.column()==last.column())
440 // index is contiguous to last: extend the range
445 // index idx is not contiguous: create a new range
446 mysel.select(first,last);
452 mysel.select(first,last);
454 if ( myView->selectionModel() ) {
455 QItemSelectionModel::SelectionFlags f = on ? QItemSelectionModel::Select : QItemSelectionModel::Deselect;
456 f = f | QItemSelectionModel::Rows;
457 if ( !keepSelection )
458 f = f | QItemSelectionModel::Clear;
459 myView->selectionModel()->select( mysel, f );
462 else if ( !keepSelection )
464 myView->clearSelection();
467 myView->blockSignals( blocked );
468 emit( selectionChanged() );
472 \brief Check if specified model index is expanded or collapsed.
473 \param index model index
474 \return \c true if model index is expanded
477 bool OB_Browser::isOpen( const QModelIndex& index ) const
479 return index.isValid() && model() && model()->hasChildren( index ) && myView->isExpanded( index );
483 \brief Expand/collapse the specified model index.
484 \param index model index
485 \param open if \c true, the index will be expanded, otherwse - collapsed
488 void OB_Browser::setOpen( const QModelIndex& index, const bool open )
490 myView->setExpanded( index, open ); // hasChildren() ???
494 \brief Adjust first column width to its contents.
496 void OB_Browser::adjustWidth()
498 myView->resizeColumnToEncloseContents( 0 );
502 \brief Adjust first column width to its contents.
504 void OB_Browser::adjustFirstColumnWidth()
506 myView->resizeColumnToEncloseContents( 0 );
510 \brief Adjust all columns width to its contents except the first column.
512 void OB_Browser::adjustColumnsWidth()
514 for ( int aCol = 1; aCol < myView->header()->count(); aCol++ ) {
515 if ( myView->columnWidth( aCol ) > 0 )
516 myView->resizeColumnToEncloseContents( aCol );
521 \return SUIT object correspondint to item at position 'pos'
522 \param pos - position
524 /* TODO: removed - QTreeView::indexAt() should be used
525 SUIT_DataObject* OB_Browser::dataObjectAt( const QPoint& pos ) const
527 SUIT_DataObject* obj = 0;
529 QListView* lv = listView();
531 obj = dataObject( lv->itemAt( pos ) );
537 \return filter of list view
540 OB_Filter* OB_Browser::filter() const
542 return myView->filter();
546 Changes filter of list view
547 \param f - new filter
550 void OB_Browser::setFilter( OB_Filter* f )
552 myView->setFilter( f );
556 Sets global width mode
557 \param mode - new width mode
560 void OB_Browser::setWidthMode( QListView::WidthMode mode )
562 for ( int i = 0, n = myView->columns(); i < n; i++ )
563 if( mode!=QListView::Maximum || myView->columnWidth( i )>0 )
564 myView->setColumnWidthMode( i, mode );
569 \param obj - start object
570 \param autoOpen - to open automatically branches of autoOpenLevel()
574 void OB_Browser::updateTree( SUIT_DataObject* obj, const bool autoOpen )
576 // QTime t1 = QTime::currentTime();
578 if ( !obj && !(obj = getRootObject()) )
581 DataObjectKey curKey;
582 DataObjectMap selObjs, openObjs;
583 DataObjectKeyMap selKeys, openKeys;
585 int selNum = numberOfSelected();
587 SUIT_DataObject* curObj = storeState( selObjs, openObjs, selKeys, openKeys, curKey );
591 restoreState( selObjs, openObjs, curObj, selKeys, openKeys, curKey );
598 if ( selNum != numberOfSelected() )
599 emit selectionChanged();
601 // QTime t2 = QTime::currentTime();
602 // qDebug( QString( "update tree time = %1 msecs" ).arg( t1.msecsTo( t2 ) ) );
606 Replaces part of tree starting at object 'src' by tree starting at object 'trg'
609 void OB_Browser::replaceTree( SUIT_DataObject* src, SUIT_DataObject* trg )
611 if ( !src || !trg || src == trg || src->root() != getRootObject() )
614 DataObjectKey curKey;
615 DataObjectMap selObjs, openObjs;
616 DataObjectKeyMap selKeys, openKeys;
618 int selNum = numberOfSelected();
620 SUIT_DataObject* curObj = storeState( selObjs, openObjs, selKeys, openKeys, curKey );
622 SUIT_DataObject* parent = src->parent();
623 int pos = parent ? parent->childPos( src ) : -1;
627 removeConnections( src );
628 if ( isAutoDeleteObjects() )
631 if ( parent && pos != -1 )
632 parent->insertChild( trg, pos );
634 trg->setParent( parent );
637 createConnections( trg );
639 restoreState( selObjs, openObjs, curObj, selKeys, openKeys, curKey );
643 if ( selNum != numberOfSelected() )
644 emit selectionChanged();
648 Adjusts width by item
652 void OB_Browser::adjustWidth( QListViewItem* item )
656 item->widthChanged( 0 );
657 if ( item->isOpen() )
658 adjustWidth( item->firstChild() );
659 item = item->nextSibling();
665 \remove all items referencing current (through data objects)
668 void OB_Browser::removeReferences( QListViewItem* item )
673 SUIT_DataObject* obj = dataObject( item );
674 obj->disconnect( this, SLOT( onDestroyed( SUIT_DataObject* ) ) );
675 myItems.remove( obj );
677 QListViewItem* i = item->firstChild();
680 removeReferences( i );
681 i = i->nextSibling();
686 Connects all children to SLOT onDestroyed
688 /* TODO: move to SUIT_TreeModel
689 void OB_Browser::createConnections( SUIT_DataObject* obj )
694 DataObjectList childList;
695 obj->children( childList, true );
697 childList.prepend( obj );
699 for ( DataObjectListIterator it( childList ); it.current(); ++it )
700 it.current()->connect( this, SLOT( onDestroyed( SUIT_DataObject* ) ) );
704 Disconnects all children from SLOT onDestroyed
706 /* TODO: move to SUIT_TreeModel
707 void OB_Browser::removeConnections( SUIT_DataObject* obj )
712 DataObjectList childList;
713 obj->children( childList, true );
715 childList.prepend( obj );
717 for ( DataObjectListIterator it( childList ); it.current(); ++it )
718 it.current()->disconnect( this, SLOT( onDestroyed( SUIT_DataObject* ) ) );
722 Stores states (opened, selected) of current tree items
724 \param selObjs, selKeys - maps of selected objects
725 \param openObjs, openKeys - maps of opened objects
726 \param curKey - map of current objects
728 /* TODO: to be revised
729 SUIT_DataObject* OB_Browser::storeState( DataObjectMap& selObjs, DataObjectMap& openObjs,
730 DataObjectKeyMap& selKeys, DataObjectKeyMap& openKeys,
731 DataObjectKey& curKey ) const
733 QListView* lv = listView();
737 SUIT_DataObject* curObj = dataObject( lv->currentItem() );
739 curKey = objectKey( curObj );
741 for ( QListViewItemIterator it( lv ); it.current(); ++it )
743 SUIT_DataObject* obj = dataObject( it.current() );
747 selObjs.insert( obj, lv->isSelected( it.current() ) );
748 openObjs.insert( obj, lv->isOpen( it.current() ) );
749 if ( lv->isSelected( it.current() ) )
750 selKeys.insert( objectKey( obj ), 0 );
751 if ( lv->isOpen( it.current() ) )
752 openKeys.insert( objectKey( obj ), 0 );
759 Restores states (opened, selected) of current tree items
760 \param selObjs, selKeys - maps of selected objects
761 \param openObjs, openKeys - maps of opened objects
762 \param curKey - map of current objects
764 /* TODO: to be revised
765 void OB_Browser::restoreState( const DataObjectMap& selObjs, const DataObjectMap& openObjs,
766 const SUIT_DataObject* curObj, const DataObjectKeyMap& selKeys,
767 const DataObjectKeyMap& openKeys, const DataObjectKey& curKey )
769 QListView* lv = listView();
773 bool block = lv->signalsBlocked();
774 lv->blockSignals( true );
776 QListViewItem* curItem = 0;
777 for ( QListViewItemIterator it( lv ); it.current(); ++it )
779 QListViewItem* item = it.current();
780 SUIT_DataObject* obj = dataObject( item );
785 DataObjectKey key = objectKey( obj );
787 if ( selObjs.contains( obj ) )
789 if ( selObjs[obj] && !lv->isSelected( item ) )
790 lv->setSelected( item, true );
792 else if ( !key.isNull() && selKeys.contains( key ) && !lv->isSelected( item ) )
793 lv->setSelected( item, true );
795 if ( openObjs.contains( obj ) )
797 bool parentOpen = true;
798 if( item && item->parent() )
799 parentOpen = item->parent()->isOpen();
801 if ( openObjs[obj] && parentOpen )
802 lv->setOpen( item, true );
804 else if ( !key.isNull() && openKeys.contains( key ) )
806 bool parentOpen = true;
807 if( item && item->parent() )
808 parentOpen = item->parent()->isOpen();
811 lv->setOpen( item, true );
814 if ( !curItem && ( curObj == obj || ( !curKey.isNull() && curKey == key )) )
819 lv->setCurrentItem( curItem );
821 lv->blockSignals( block );
825 Creates object key by tree item
827 /* TODO: move to SUIT_TreeModel
828 OB_Browser::DataObjectKey OB_Browser::objectKey( QListViewItem* i ) const
830 return objectKey( dataObject( i ) );
834 Creates object key by SUIT object
836 /* TODO: move to SUIT_TreeModel
837 OB_Browser::DataObjectKey OB_Browser::objectKey( SUIT_DataObject* obj ) const
842 return DataObjectKey( obj->key() );
847 \brief Get tree view widget.
848 \return tree view widget of the object browser
850 QtxTreeView* OB_Browser::treeView() const
856 \brief Process context menu request event.
857 \param e context menu event
859 void OB_Browser::contextMenuEvent( QContextMenuEvent* e )
861 QMenu* popup = new QMenu();
863 createPopupMenu( popup );
865 Qtx::simplifySeparators( popup );
867 if ( !popup->actions().isEmpty() )
868 popup->exec( e->globalPos() );
873 \brief Get the time of the latest updating.
874 \return latest updating time
876 unsigned long OB_Browser::getModifiedTime() const
878 return myModifiedTime;
882 \brief Update the time of the latest updating.
884 void OB_Browser::setModified()
886 myModifiedTime = clock();
890 \brief Called when "Expand all" popup menu command is activated.
892 Expands all selected items recursively.
894 void OB_Browser::onExpandAll()
896 QModelIndexList indexes = selectedIndexes();
898 disconnect( treeView(), SIGNAL( expanded( const QModelIndex& ) ),
899 this, SLOT( onExpanded( const QModelIndex& ) ) );
901 foreach ( index, indexes ) {
902 myView->expandAll( index );
904 connect( treeView(), SIGNAL( expanded( const QModelIndex& ) ),
905 this, SLOT( onExpanded( const QModelIndex& ) ) );
906 emit(onExpanded( index));
910 \brief Called when "Collapse all" popup menu command is activated.
912 Collapse all selected items recursively.
914 void OB_Browser::onCollapseAll()
916 QModelIndexList indexes = selectedIndexes();
919 foreach ( index, indexes ) {
920 myView->collapseAll( index );
925 SLOT: called if SUIT object is destroyed
927 /* TODO: moved to SUIT_TreeModel
928 void OB_Browser::onDestroyed( SUIT_DataObject* obj )
934 SLOT: called on finish of drag-n-drop operation
935 \param items - dragged items
936 \param item - destination (item on that they were dropped)
937 \param action - QDropEvent::Action
939 // TODO: drag-n-drop works differently - SUIT_TreeModel to be updated
940 // and QTreeView needs some setup
942 void OB_Browser::onDropped( QPtrList<QListViewItem> items, QListViewItem* item, int action )
944 SUIT_DataObject* obj = dataObject( item );
949 for ( QPtrListIterator<QListViewItem> it( items ); it.current(); ++it )
951 SUIT_DataObject* o = dataObject( it.current() );
956 if ( !lst.isEmpty() )
957 emit dropped( lst, obj, action );
961 Updates texts of items
963 /* TODO: to be removed
964 void OB_Browser::updateText()
966 if ( myColumnIds.isEmpty() )
969 QListView* lv = listView();
973 for ( QListViewItemIterator it( lv ); it.current(); ++it )
975 SUIT_DataObject* obj = dataObject( it.current() );
979 for( QMap<int, int>::iterator itr = myColumnIds.begin(); itr != myColumnIds.end(); ++itr )
980 it.current()->setText( itr.data(), obj->text( itr.key() ) );
985 \return true if item must be updated
986 \param item - item to be checked
988 /* TODO: to be revised
989 bool OB_Browser::needToUpdateTexts( QListViewItem* item ) const
991 SUIT_DataObject* obj = dataObject( item );
995 for( QMap<int, int>::const_iterator it = myColumnIds.begin(); it != myColumnIds.end(); ++it )
996 if( item->text( it.data() ) != obj->text( it.key() ) )
1002 Updates texts of item
1003 \param item - item to be updated
1005 /* TODO: to be revised
1006 void OB_Browser::updateText( QListViewItem* item )
1008 SUIT_DataObject* obj = dataObject( item );
1012 for( QMap<int, int>::iterator it = myColumnIds.begin(); it != myColumnIds.end(); ++it )
1013 item->setText( it.data(), obj->text( it.key() ) );
1018 \brief Add custom actions to the popup menu.
1019 \param menu popup menu
1021 void OB_Browser::createPopupMenu( QMenu* menu )
1023 menu->addSeparator();
1025 QModelIndexList indexes = selectedIndexes();
1027 bool closed = false, opened = false;
1029 for ( QModelIndexList::Iterator it = indexes.begin();
1030 it != indexes.end() && !closed; ++it ) {
1031 closed = hasCollased( *it );
1034 for ( QModelIndexList::Iterator it = indexes.begin();
1035 it != indexes.end() && !opened; ++it ) {
1036 opened = hasExpanded( *it );
1040 menu->addAction( tr( "MEN_EXPAND_ALL" ), this, SLOT( onExpandAll() ) );
1042 menu->addAction( tr( "MEN_COLLAPSE_ALL" ), this, SLOT( onCollapseAll() ) );
1044 if ( isSearchToolEnabled() ) {
1045 menu->addSeparator();
1046 menu->addAction( tr( "MEN_FIND" ), searchTool(), SLOT( find() ), QKeySequence(Qt::CTRL + Qt::Key_F) );
1047 menu->addSeparator();
1052 Expands item with all it's children
1054 /* TODO: to be revised
1055 void OB_Browser::expand( QListViewItem* item )
1060 item->setOpen( true );
1061 for ( QListViewItem* child = item->firstChild(); child; child = child->nextSibling() )
1066 \brief Check if model index is collapsed or has collapsed children.
1067 \return \c true if item or one of its children is collapsed
1069 bool OB_Browser::hasCollased( const QModelIndex& index ) const
1071 bool result = false;
1073 if ( index.isValid() && model() ) {
1074 bool hasChildren = model()->hasChildren( index );
1075 result = hasChildren && !myView->isExpanded( index );
1076 if ( !result && hasChildren ) {
1077 int rows = model()->rowCount( index );
1078 for ( int i = 0; i < rows && !result; i ++ ) {
1079 QModelIndex child = model()->index( i, 0, index );
1080 result = hasCollased( child );
1088 \brief Check if model index is expanded or has expanded children.
1089 \return \c true if item or one of its children is expanded
1091 bool OB_Browser::hasExpanded( const QModelIndex& index ) const
1093 bool result = false;
1095 if ( index.isValid() && model() ) {
1096 bool hasChildren = model()->hasChildren( index );
1097 result = hasChildren && myView->isExpanded( index );
1098 if ( !result && hasChildren ) {
1099 int rows = model()->rowCount( index );
1100 for ( int i = 0; i < rows && !result; i ++ ) {
1101 QModelIndex child = model()->index( i, 0, index );
1102 result = hasExpanded( child );
1111 \param obj - SUIT object to be removed
1112 \param autoUpd - auto tree updating
1114 /* TODO: moved to SUIT_TreeModel
1115 void OB_Browser::removeObject( SUIT_DataObject* obj, const bool autoUpd )
1120 // Removing list view items from <myItems> recursively for all children.
1121 // Otherwise, "delete item" line will destroy all item's children,
1122 // and <myItems> will contain invalid pointers (see ~QListViewItem() description in Qt docs)
1123 DataObjectList childList;
1124 obj->children( childList, true );
1125 for ( DataObjectListIterator it( childList ); it.current(); ++it )
1127 it.current()->disconnect( this, SLOT( onDestroyed( SUIT_DataObject* ) ) );
1128 myItems.remove( it.current() );
1131 QListViewItem* item = listViewItem( obj );
1133 obj->disconnect( this, SLOT( onDestroyed( SUIT_DataObject* ) ) );
1134 myItems.remove( obj );
1136 if ( obj == myRoot )
1138 // remove all child list view items
1146 if ( isAutoUpdate() )
1148 SUIT_DataObject* pObj = item && item->parent() ? dataObject( item->parent() ) : 0;
1149 updateTree( pObj, false );
1156 Opens branches from 1 to autoOpenLevel()
1159 /* TODO: to be revised
1160 void OB_Browser::autoOpenBranches()
1170 /* TODO: to be revised
1171 void OB_Browser::openBranch( QListViewItem* item, const int level )
1178 item->setOpen( true );
1179 openBranch( item->firstChild(), level - 1 );
1180 item = item->nextSibling();
1185 SLOT: called on double click on item, emits signal
1187 /* TODO: to be revised
1188 void OB_Browser::onDoubleClicked( QListViewItem* item )
1191 emit doubleClicked( dataObject( item ) );
1196 \fn void OB_Browser::selectionChanged();
1197 \brief Emitted when selection is changed in the Object Browser.
1200 QByteArray OB_Browser::getOpenStates( int theColumn ) const
1203 QDataStream aStream( &aData, QIODevice::WriteOnly );
1204 MapOfOpenStates aMap;
1205 const_cast<OB_Browser*>( this )->openStates( true, aMap, QModelIndex(), theColumn );
1206 MapOfOpenStates::const_iterator anIt = aMap.begin(), aLast = aMap.end();
1207 for( ; anIt!=aLast; anIt++ )
1209 QString anEntry = anIt.key();
1210 qint32 anOpenAttr = anIt.value() ? 1 : 0;
1211 aStream << anEntry << anOpenAttr;
1216 void OB_Browser::setOpenStates( const QByteArray& theData, int theColumn )
1218 QByteArray* aData = const_cast<QByteArray*>( &theData );
1219 QDataStream aStream( aData, QIODevice::ReadOnly );
1220 MapOfOpenStates aMap;
1221 while( !aStream.atEnd() )
1225 aStream >> anEntry >> anOpenAttr;
1226 bool isOpen = anOpenAttr!=0;
1227 aMap[anEntry] = isOpen;
1229 openStates( false, aMap, QModelIndex(), theColumn );
1232 void OB_Browser::openStates( bool isGet, MapOfOpenStates& theMap, const QModelIndex& theIndex, int theColumn )
1234 if( theIndex.isValid() )
1236 QString anEntry = theIndex.sibling( theIndex.row(), theColumn ).data().toString();
1240 isOpen = treeView()->isExpanded( theIndex );
1241 theMap[anEntry] = isOpen;
1245 isOpen = theMap.contains( anEntry ) ? theMap[anEntry] : false;
1246 treeView()->setExpanded( theIndex, isOpen );
1250 const QAbstractItemModel* aModel = model();
1252 int n = aModel->rowCount( theIndex );
1253 for( int i=0; i<n; i++ )
1255 QModelIndex aChild = aModel->index( i, 0, theIndex );
1256 openStates( isGet, theMap, aChild, theColumn );