// -*- C++ -*- // // This file is part of the Coriolis Software. // Copyright (c) UPMC/LIP6 2015-2016, All Rights Reserved // // +-----------------------------------------------------------------+ // | H U R R I C A N E | // | V L S I B a c k e n d D a t a - B a s e | // | | // | Author : Jean-Paul CHAPUT | // | E-mail : Jean-Paul.Chaput@lip6.fr | // | =============================================================== | // | C++ Module : "./HierarchyWidget.cpp" | // +-----------------------------------------------------------------+ #include #include #include #include #include #include #include #include #include #include #include "hurricane/Commons.h" #include "hurricane/Warning.h" #include "hurricane/Net.h" #include "hurricane/viewer/Graphics.h" #include "hurricane/viewer/HierarchyModel.h" #include "hurricane/viewer/HierarchyWidget.h" namespace Hurricane { // ------------------------------------------------------------------- // Class : "HierarchyWidget". HierarchyWidget::HierarchyWidget ( QWidget* parent ) : QWidget (parent) , _cellWidget (NULL) , _cell (NULL) , _baseModel (new HierarchyModel(this)) , _view (new QTreeView(this)) , _filterPatternLineEdit(new QLineEdit(this)) , _rowHeight (20) { setAttribute( Qt::WA_DeleteOnClose ); setAttribute( Qt::WA_QuitOnClose, false ); setContextMenuPolicy( Qt::ActionsContextMenu ); _rowHeight = QFontMetrics( Graphics::getFixedFont() ).height() + 4; //_view->setShowGrid ( false ); _view->setAlternatingRowColors( true ); _view->setSelectionBehavior ( QAbstractItemView::SelectRows ); _view->setSelectionMode ( QAbstractItemView::SingleSelection ); _view->setSortingEnabled ( true ); _view->setModel ( _baseModel ); //_view->resizeColumnToContents ( 1 ); QHeaderView* horizontalHeader = _view->header(); horizontalHeader->setDefaultAlignment ( Qt::AlignHCenter ); horizontalHeader->setMinimumSectionSize( (Graphics::isHighDpi()) ? 600 : 300 ); #if QT_VERSION < QT_VERSION_CHECK(5,0,0) horizontalHeader->setResizeMode ( 0, QHeaderView::Interactive ); horizontalHeader->setResizeMode ( 1, QHeaderView::Interactive ); // #else // horizontalHeader->setSectionResizeMode ( 0, QHeaderView::Interactive ); // horizontalHeader->setSectionResizeMode ( 1, QHeaderView::Interactive ); #endif horizontalHeader->setStretchLastSection( true ); QLabel* filterPatternLabel = new QLabel(tr("&Filter pattern:"), this); filterPatternLabel->setBuddy( _filterPatternLineEdit ); QGridLayout* gLayout = new QGridLayout(); gLayout->addWidget( _view , 1, 0, 1, 2 ); gLayout->addWidget( filterPatternLabel , 2, 0 ); gLayout->addWidget(_filterPatternLineEdit, 2, 1); setLayout( gLayout ); connect ( _view, SIGNAL(collapsed (const QModelIndex&)) , this , SLOT (collapseHook(const QModelIndex& )) ); connect ( _filterPatternLineEdit , SIGNAL(returnPressed ()) , this , SLOT (textFilterChanged()) ); connect ( _view->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&,const QItemSelection&)) , this , SLOT (followSelected (const QItemSelection&,const QItemSelection&)) ); TreeKeyFilter* filter = new TreeKeyFilter( this ); _view->installEventFilter( filter ); resize(300, 300); } void HierarchyWidget::setCell ( Cell* cell ) { if (_cell == cell) return; _cell = cell; _view->setVisible( false ); _view->selectionModel()->clear(); _baseModel->setCell( cell ); string windowTitle = "Hierarchy" + getString(cell); setWindowTitle( tr(windowTitle.c_str()) ); _view->selectionModel()->select( _baseModel->index(0,0,_view->rootIndex()) , QItemSelectionModel::Select|QItemSelectionModel::Rows ); _view->resizeColumnToContents( 0 ); _view->setVisible( true ); } bool HierarchyWidget::isRSelected ( const QModelIndex& index ) const { HierarchyInfos* infos = const_cast(_baseModel->infosFromIndex(index)); for ( size_t row=0 ; row < infos->getInstances().size() ; ++row ) { QModelIndex childIndex = _baseModel->index( row, 0, index ); if (_view->selectionModel()->isSelected(childIndex)) return true; if (not infos->isCollapsed() and isRSelected(childIndex)) return true; } return false; } void HierarchyWidget::rexpand ( Path path ) { if (path.isEmpty()) return; QModelIndex index = _baseModel->index( 0, 0, QModelIndex() ); do { Instance* head = path.getHeadInstance(); path = path.getTailPath(); _view->expand( index ); HierarchyInfos* parentInfos = const_cast( _baseModel->infosFromIndex(index) ); HierarchyInfos* childInfos = NULL; for ( HierarchyInfos* child : parentInfos->getInstances() ) { if (child->getInstance() == head) { childInfos = child; break; } } if (not childInfos) { cerr << Warning("HierarchyWidget::rexpand(): discrepency between Path and Hierarchy.") << endl; return; } index = _baseModel->index( childInfos->getRowInParent(), 0, index ); } while (not path.isEmpty()); _view->selectionModel()->clear(); _view->selectionModel()->select( index, QItemSelectionModel::Select|QItemSelectionModel::Rows ); _view->setCurrentIndex( index ); } void HierarchyWidget::rexpand ( const QModelIndex& index ) { HierarchyInfos* infos = const_cast(_baseModel->infosFromIndex(index)); if (infos) { if (not infos->isCollapsed()) { _view->expand( index ); for ( HierarchyInfos* child : infos->getInstances() ) { rexpand( _baseModel->index( child->getRowInParent(), 0, index ) ); } } } } void HierarchyWidget::collapseHook ( const QModelIndex& index ) { if (isRSelected(index)) { _view->selectionModel()->clear(); _view->selectionModel()->select( index, QItemSelectionModel::Select|QItemSelectionModel::Rows ); } HierarchyInfos* infos = const_cast(_baseModel->infosFromIndex(index)); infos->collapse(); } void HierarchyWidget::textFilterChanged () { QModelIndexList selecteds = _view->selectionModel()->selectedIndexes(); if (not selecteds.isEmpty()) { QModelIndex index = selecteds[0]; HierarchyInfos* infos = const_cast(_baseModel->infosFromIndex(index)); infos->setFilterPattern( _filterPatternLineEdit->text() ); _view->reset(); rexpand( _view->rootIndex() ); _view->selectionModel()->select( index, QItemSelectionModel::Select|QItemSelectionModel::Rows ); _view->setCurrentIndex( index ); } } void HierarchyWidget::followSelected ( const QItemSelection& selecteds, const QItemSelection& deselecteds ) { if (selecteds.indexes().isEmpty()) { //cerr << Warning("HierarchyWidget::followSelected(): Selection should never be empty.") << endl; return; } QModelIndex index = selecteds.indexes()[0]; HierarchyInfos* infos = const_cast(_baseModel->infosFromIndex(index)); _filterPatternLineEdit->setText( infos->getFilterPattern() ); } void HierarchyWidget::goTo ( int delta ) { if (delta == 0) return; //QModelIndex newIndex = _baseModel->index( _view->currentIndex().row()+delta, 0, QModelIndex() ); //if (newIndex.isValid()) // _view->selectRow( newIndex.row() ); } // ------------------------------------------------------------------- // Class : "TreeKeyFilter". TreeKeyFilter::TreeKeyFilter ( QObject* parent ) : QObject(parent) { } bool TreeKeyFilter::eventFilter ( QObject* object, QEvent* event ) { if (event->type() == QEvent::KeyPress) { HierarchyWidget* owner = qobject_cast( parent() ); if (not owner) return false; QKeyEvent* keyEvent = static_cast(event); if (keyEvent->key() == Qt::Key_Return) { QModelIndexList selecteds = owner->_view->selectionModel()->selectedIndexes(); if (not selecteds.isEmpty()) { QModelIndex index = selecteds[0]; HierarchyInfos* infos = const_cast(owner->_baseModel->infosFromIndex(index)); if (infos) { if (owner->getCellWidget()) { owner->getCellWidget()->setCell( infos->getMasterCell(), infos->getPath() ); } } } } } return QObject::eventFilter( object, event ); } } // Hurricane namespace.