17 #include <QAbstractTextDocumentLayout> 
   18 #include <QHeaderView> 
   21 #include <QToolButton> 
   22 #include <QFileDialog> 
   23 #include <QPlainTextDocumentLayout> 
   24 #include <QSortFilterProxyModel> 
   25 #include <QActionGroup> 
   38 #include "qgsnative.h" 
   50 #include <QDragEnterEvent> 
   55   , mModel( browserModel )
 
   59   layout()->setContentsMargins( 0, 0, 0, 0 );
 
   60   qgis::down_cast< QVBoxLayout * >( layout() )->setSpacing( 0 );
 
   62   mBrowserView = 
new QgsDockBrowserTreeView( 
this );
 
   63   mLayoutBrowser->addWidget( mBrowserView );
 
   65   mWidgetFilter->hide();
 
   66   mLeFilter->setPlaceholderText( tr( 
"Type here to filter visible items…" ) );
 
   69   QMenu *menu = 
new QMenu( 
this );
 
   70   menu->setSeparatorsCollapsible( 
false );
 
   71   mBtnFilterOptions->setMenu( menu );
 
   72   QAction *action = 
new QAction( tr( 
"Case Sensitive" ), menu );
 
   73   action->setData( 
"case" );
 
   74   action->setCheckable( 
true );
 
   75   action->setChecked( 
false );
 
   76   connect( action, &QAction::toggled, 
this, &QgsBrowserWidget::setCaseSensitive );
 
   77   menu->addAction( action );
 
   78   QActionGroup *group = 
new QActionGroup( menu );
 
   79   action = 
new QAction( tr( 
"Filter Pattern Syntax" ), group );
 
   80   action->setSeparator( 
true );
 
   81   menu->addAction( action );
 
   82   action = 
new QAction( tr( 
"Normal" ), group );
 
   84   action->setCheckable( 
true );
 
   85   action->setChecked( 
true );
 
   86   menu->addAction( action );
 
   87   action = 
new QAction( tr( 
"Wildcard(s)" ), group );
 
   89   action->setCheckable( 
true );
 
   90   menu->addAction( action );
 
   91   action = 
new QAction( tr( 
"Regular Expression" ), group );
 
   93   action->setCheckable( 
true );
 
   94   menu->addAction( action );
 
   96   mBrowserView->setExpandsOnDoubleClick( 
false );
 
   99   connect( mActionAddLayers, &QAction::triggered, 
this, &QgsBrowserWidget::addSelectedLayers );
 
  100   connect( mActionCollapse, &QAction::triggered, mBrowserView, &QgsDockBrowserTreeView::collapseAll );
 
  101   connect( mActionShowFilter, &QAction::triggered, 
this, &QgsBrowserWidget::showFilterWidget );
 
  102   connect( mActionPropertiesWidget, &QAction::triggered, 
this, &QgsBrowserWidget::propertiesWidgetToggled );
 
  103   connect( mLeFilter, &QgsFilterLineEdit::returnPressed, 
this, &QgsBrowserWidget::setFilter );
 
  105   connect( mLeFilter, &QgsFilterLineEdit::textChanged, 
this, &QgsBrowserWidget::setFilter );
 
  106   connect( group, &QActionGroup::triggered, 
this, &QgsBrowserWidget::setFilterSyntax );
 
  107   connect( mBrowserView, &QgsDockBrowserTreeView::customContextMenuRequested, 
this, &QgsBrowserWidget::showContextMenu );
 
  108   connect( mBrowserView, &QgsDockBrowserTreeView::doubleClicked, 
this, &QgsBrowserWidget::itemDoubleClicked );
 
  109   connect( mSplitter, &QSplitter::splitterMoved, 
this, &QgsBrowserWidget::splitterMoved );
 
  128     mBrowserView->setSettingsSection( objectName().toLower() ); 
 
  129     mBrowserView->setBrowserModel( mModel );
 
  130     mBrowserView->setModel( mProxyModel );
 
  131     mBrowserView->setSortingEnabled( 
true );
 
  132     mBrowserView->sortByColumn( 0, Qt::AscendingOrder );
 
  134     mBrowserView->setTextElideMode( Qt::ElideNone );
 
  135     mBrowserView->header()->setSectionResizeMode( 0, QHeaderView::ResizeToContents );
 
  136     mBrowserView->header()->setStretchLastSection( 
false );
 
  139     connect( mBrowserView->selectionModel(), &QItemSelectionModel::selectionChanged,
 
  140              this, &QgsBrowserWidget::selectionChanged );
 
  148     mActionPropertiesWidget->setChecked( settings.
value( settingsSection() + 
"/propertiesWidgetEnabled", 
false ).toBool() );
 
  149     mPropertiesWidget->setVisible( 
false ); 
 
  151     mSplitter->restoreState( settings.
value( QStringLiteral( 
"%1/splitterState" ).arg( settingsSection() ) ).toByteArray() );
 
  154   QWidget::showEvent( e );
 
  157 void QgsBrowserWidget::itemDoubleClicked( 
const QModelIndex &index )
 
  168     if ( provider->handleDoubleClick( item, context ) )
 
  176     if ( mBrowserView->isExpanded( index ) )
 
  177       mBrowserView->collapse( index );
 
  179       mBrowserView->expand( index );
 
  183 void QgsBrowserWidget::onOptionsChanged()
 
  185   std::function< void( 
const QModelIndex &index ) > updateItem;
 
  186   updateItem = [
this, &updateItem]( 
const QModelIndex & index )
 
  190       dirItem->reevaluateMonitoring();
 
  193     const int rowCount = mModel->
rowCount( index );
 
  194     for ( 
int i = 0; i < rowCount; ++i )
 
  196       const QModelIndex child = mModel->
index( i, 0, index );
 
  201   for ( 
int i = 0; i < mModel->
rowCount(); ++i )
 
  203     updateItem( mModel->
index( i, 0 ) );
 
  207 void QgsBrowserWidget::showContextMenu( QPoint pt )
 
  209   QModelIndex index = mProxyModel->mapToSource( mBrowserView->indexAt( pt ) );
 
  214   const QModelIndexList selection = mBrowserView->selectionModel()->selectedIndexes();
 
  215   QList< QgsDataItem * > selectedItems;
 
  216   selectedItems.reserve( selection.size() );
 
  217   for ( 
const QModelIndex &selectedIndex : selection )
 
  221       selectedItems << selectedItem;
 
  224   QMenu *menu = 
new QMenu( 
this );
 
  226   const QList<QMenu *> menus = item->
menus( menu );
 
  227   QList<QAction *> actions = item->
actions( menu );
 
  229   if ( !menus.isEmpty() )
 
  231     for ( QMenu *mn : menus )
 
  237   if ( !actions.isEmpty() )
 
  239     if ( !menu->actions().isEmpty() )
 
  240       menu->addSeparator();
 
  242     menu->addActions( actions );
 
  250     return a->precedenceWhenPopulatingMenus() < b->precedenceWhenPopulatingMenus();
 
  254     provider->populateContextMenu( item, menu, selectedItems, context );
 
  257   if ( menu->actions().isEmpty() )
 
  263   menu->popup( mBrowserView->mapToGlobal( pt ) );
 
  279   mDisabledDataItemsKeys = filter;
 
  289   refreshModel( QModelIndex() );
 
  292 void QgsBrowserWidget::refreshModel( 
const QModelIndex &index )
 
  294   if ( mModel && mProxyModel )
 
  311     for ( 
int i = 0; i < mModel->
rowCount( index ); i++ )
 
  313       QModelIndex idx = mModel->
index( i, 0, index );
 
  314       QModelIndex proxyIdx = mProxyModel->mapFromSource( idx );
 
  334 void QgsBrowserWidget::addLayer( 
QgsLayerItem *layerItem )
 
  342 void QgsBrowserWidget::addSelectedLayers()
 
  344   QApplication::setOverrideCursor( Qt::WaitCursor );
 
  347   QModelIndexList list = mBrowserView->selectionModel()->selectedIndexes();
 
  348   std::sort( list.begin(), list.end() );
 
  351   const auto constList = list;
 
  352   for ( 
const QModelIndex &index : constList )
 
  357       QgsProjectItem *projectItem = qobject_cast<QgsProjectItem *>( item );
 
  359         emit 
openFile( projectItem->
path(), QStringLiteral( 
"project" ) );
 
  361       QApplication::restoreOverrideCursor();
 
  367   for ( 
int i = list.size() - 1; i >= 0; i-- )
 
  372       QgsLayerItem *layerItem = qobject_cast<QgsLayerItem *>( item );
 
  374         addLayer( layerItem );
 
  378   QApplication::restoreOverrideCursor();
 
  381 void QgsBrowserWidget::hideItem()
 
  383   QModelIndex index = mProxyModel->mapToSource( mBrowserView->currentIndex() );
 
  394 void QgsBrowserWidget::showProperties()
 
  396   QModelIndex index = mProxyModel->mapToSource( mBrowserView->currentIndex() );
 
  403     QgsBrowserPropertiesDialog *dialog = 
new QgsBrowserPropertiesDialog( settingsSection(), 
this );
 
  404     dialog->setAttribute( Qt::WA_DeleteOnClose );
 
  405     dialog->setItem( item, createContext() );
 
  410 void QgsBrowserWidget::showFilterWidget( 
bool visible )
 
  412   mWidgetFilter->setVisible( visible );
 
  415     mLeFilter->setText( QString() );
 
  420     mLeFilter->setFocus();
 
  424 void QgsBrowserWidget::setFilter()
 
  426   QString filter = mLeFilter->text();
 
  437 void QgsBrowserWidget::setFilterSyntax( QAction *action )
 
  439   if ( !action || ! mProxyModel )
 
  445 void QgsBrowserWidget::setCaseSensitive( 
bool caseSensitive )
 
  452 int QgsBrowserWidget::selectedItemsCount()
 
  454   QItemSelectionModel *selectionModel = mBrowserView->selectionModel();
 
  455   if ( selectionModel )
 
  457     return selectionModel->selectedIndexes().size();
 
  469 void QgsBrowserWidget::selectionChanged( 
const QItemSelection &selected, 
const QItemSelection &deselected )
 
  472   Q_UNUSED( deselected )
 
  473   if ( mActionPropertiesWidget->isChecked() )
 
  475     setPropertiesWidget();
 
  479 void QgsBrowserWidget::clearPropertiesWidget()
 
  481   while ( mPropertiesLayout->count() > 0 )
 
  483     delete mPropertiesLayout->itemAt( 0 )->widget();
 
  485   mPropertiesWidget->setVisible( 
false );
 
  488 void QgsBrowserWidget::setPropertiesWidget()
 
  490   clearPropertiesWidget();
 
  491   QItemSelectionModel *selectionModel = mBrowserView->selectionModel();
 
  492   if ( selectionModel )
 
  494     QModelIndexList indexes = selectionModel->selectedIndexes();
 
  495     if ( indexes.size() == 1 )
 
  497       QModelIndex index = mProxyModel->mapToSource( indexes.value( 0 ) );
 
  500       QgsBrowserPropertiesWidget *propertiesWidget = QgsBrowserPropertiesWidget::createWidget( item, context, mPropertiesWidget );
 
  501       if ( propertiesWidget )
 
  503         propertiesWidget->setCondensedMode( 
true );
 
  504         mPropertiesLayout->addWidget( propertiesWidget );
 
  508   mPropertiesWidget->setVisible( mPropertiesLayout->count() > 0 );
 
  511 void QgsBrowserWidget::enablePropertiesWidget( 
bool enable )
 
  513   mActionPropertiesWidget->setChecked( enable );
 
  514   propertiesWidgetToggled( enable );
 
  517 void QgsBrowserWidget::propertiesWidgetToggled( 
bool enabled )
 
  519   if ( enabled && selectedItemsCount() == 1 )
 
  521     setPropertiesWidget();
 
  525     clearPropertiesWidget();
 
  529   settings.
setValue( settingsSection() + 
"/propertiesWidgetEnabled", enabled );
 
  534   if ( index.isValid() )
 
  536     QModelIndex proxyIndex = mProxyModel->mapFromSource( index );
 
  537     mBrowserView->expand( proxyIndex );
 
  538     mBrowserView->setCurrentIndex( proxyIndex );
 
  542 void QgsBrowserWidget::splitterMoved()
 
  545   settings.
setValue( QStringLiteral( 
"%1/splitterState" ).arg( settingsSection() ), mSplitter->saveState() );