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::enablePropertiesWidget );
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 );
117 settings.
setValue( settingsSection() +
"/propertiesWidgetEnabled", mPropertiesWidgetEnabled );
119 settings.
setValue( settingsSection() +
"/propertiesWidgetHeight", mPropertiesWidgetHeight );
134 mBrowserView->setSettingsSection( objectName().toLower() );
135 mBrowserView->setBrowserModel( mModel );
136 mBrowserView->setModel( mProxyModel );
137 mBrowserView->setSortingEnabled(
true );
138 mBrowserView->sortByColumn( 0, Qt::AscendingOrder );
140 mBrowserView->setTextElideMode( Qt::ElideNone );
141 mBrowserView->header()->setSectionResizeMode( 0, QHeaderView::ResizeToContents );
142 mBrowserView->header()->setStretchLastSection(
false );
145 connect( mBrowserView->selectionModel(), &QItemSelectionModel::selectionChanged,
146 this, &QgsBrowserWidget::selectionChanged );
155 mPropertiesWidgetEnabled = settings.
value( settingsSection() +
"/propertiesWidgetEnabled",
false ).toBool();
156 mActionPropertiesWidget->setChecked( mPropertiesWidgetEnabled );
157 mPropertiesWidget->setVisible(
false );
159 mPropertiesWidgetHeight = settings.
value( settingsSection() +
"/propertiesWidgetHeight" ).toFloat();
160 QList<int> sizes = mSplitter->sizes();
161 int total = sizes.value( 0 ) + sizes.value( 1 );
162 int height =
static_cast<int>( total * mPropertiesWidgetHeight );
164 sizes << total - height << height;
165 mSplitter->setSizes( sizes );
168 QWidget::showEvent( e );
171 void QgsBrowserWidget::itemDoubleClicked(
const QModelIndex &index )
182 if ( provider->handleDoubleClick( item, context ) )
190 if ( mBrowserView->isExpanded( index ) )
191 mBrowserView->collapse( index );
193 mBrowserView->expand( index );
197 void QgsBrowserWidget::onOptionsChanged()
199 std::function< void(
const QModelIndex &index ) > updateItem;
200 updateItem = [
this, &updateItem](
const QModelIndex & index )
204 dirItem->reevaluateMonitoring();
207 const int rowCount = mModel->
rowCount( index );
208 for (
int i = 0; i < rowCount; ++i )
210 const QModelIndex child = mModel->
index( i, 0, index );
215 for (
int i = 0; i < mModel->
rowCount(); ++i )
217 updateItem( mModel->
index( i, 0 ) );
221 void QgsBrowserWidget::showContextMenu( QPoint pt )
223 QModelIndex index = mProxyModel->mapToSource( mBrowserView->indexAt( pt ) );
228 const QModelIndexList selection = mBrowserView->selectionModel()->selectedIndexes();
229 QList< QgsDataItem * > selectedItems;
230 selectedItems.reserve( selection.size() );
231 for (
const QModelIndex &selectedIndex : selection )
235 selectedItems << selectedItem;
238 QMenu *menu =
new QMenu(
this );
240 const QList<QMenu *> menus = item->
menus( menu );
241 QList<QAction *> actions = item->
actions( menu );
243 if ( !menus.isEmpty() )
245 for ( QMenu *mn : menus )
251 if ( !actions.isEmpty() )
253 if ( !menu->actions().isEmpty() )
254 menu->addSeparator();
256 menu->addActions( actions );
264 return a->precedenceWhenPopulatingMenus() < b->precedenceWhenPopulatingMenus();
268 provider->populateContextMenu( item, menu, selectedItems, context );
271 if ( menu->actions().isEmpty() )
277 menu->popup( mBrowserView->mapToGlobal( pt ) );
293 mDisabledDataItemsKeys = filter;
303 refreshModel( QModelIndex() );
306 void QgsBrowserWidget::refreshModel(
const QModelIndex &index )
308 if ( mModel && mProxyModel )
325 for (
int i = 0; i < mModel->
rowCount( index ); i++ )
327 QModelIndex idx = mModel->
index( i, 0, index );
328 QModelIndex proxyIdx = mProxyModel->mapFromSource( idx );
348 void QgsBrowserWidget::addLayer(
QgsLayerItem *layerItem )
356 void QgsBrowserWidget::addSelectedLayers()
358 QApplication::setOverrideCursor( Qt::WaitCursor );
361 QModelIndexList list = mBrowserView->selectionModel()->selectedIndexes();
362 std::sort( list.begin(), list.end() );
365 const auto constList = list;
366 for (
const QModelIndex &index : constList )
371 QgsProjectItem *projectItem = qobject_cast<QgsProjectItem *>( item );
373 emit
openFile( projectItem->
path(), QStringLiteral(
"project" ) );
375 QApplication::restoreOverrideCursor();
381 for (
int i = list.size() - 1; i >= 0; i-- )
386 QgsLayerItem *layerItem = qobject_cast<QgsLayerItem *>( item );
388 addLayer( layerItem );
392 QApplication::restoreOverrideCursor();
395 void QgsBrowserWidget::hideItem()
397 QModelIndex index = mProxyModel->mapToSource( mBrowserView->currentIndex() );
408 void QgsBrowserWidget::showProperties()
410 QModelIndex index = mProxyModel->mapToSource( mBrowserView->currentIndex() );
417 QgsBrowserPropertiesDialog *dialog =
new QgsBrowserPropertiesDialog( settingsSection(),
this );
418 dialog->setAttribute( Qt::WA_DeleteOnClose );
419 dialog->setItem( item, createContext() );
424 void QgsBrowserWidget::showFilterWidget(
bool visible )
426 mWidgetFilter->setVisible( visible );
429 mLeFilter->setText( QString() );
434 mLeFilter->setFocus();
438 void QgsBrowserWidget::setFilter()
440 QString filter = mLeFilter->text();
451 void QgsBrowserWidget::setFilterSyntax( QAction *action )
453 if ( !action || ! mProxyModel )
459 void QgsBrowserWidget::setCaseSensitive(
bool caseSensitive )
466 int QgsBrowserWidget::selectedItemsCount()
468 QItemSelectionModel *selectionModel = mBrowserView->selectionModel();
469 if ( selectionModel )
471 return selectionModel->selectedIndexes().size();
483 void QgsBrowserWidget::selectionChanged(
const QItemSelection &selected,
const QItemSelection &deselected )
486 Q_UNUSED( deselected )
487 if ( mPropertiesWidgetEnabled )
489 setPropertiesWidget();
493 void QgsBrowserWidget::clearPropertiesWidget()
495 while ( mPropertiesLayout->count() > 0 )
497 delete mPropertiesLayout->itemAt( 0 )->widget();
499 mPropertiesWidget->setVisible(
false );
502 void QgsBrowserWidget::setPropertiesWidget()
504 clearPropertiesWidget();
505 QItemSelectionModel *selectionModel = mBrowserView->selectionModel();
506 if ( selectionModel )
508 QModelIndexList indexes = selectionModel->selectedIndexes();
509 if ( indexes.size() == 1 )
511 QModelIndex index = mProxyModel->mapToSource( indexes.value( 0 ) );
514 QgsBrowserPropertiesWidget *propertiesWidget = QgsBrowserPropertiesWidget::createWidget( item, context, mPropertiesWidget );
515 if ( propertiesWidget )
517 propertiesWidget->setCondensedMode(
true );
518 mPropertiesLayout->addWidget( propertiesWidget );
522 mPropertiesWidget->setVisible( mPropertiesLayout->count() > 0 );
525 void QgsBrowserWidget::enablePropertiesWidget(
bool enable )
527 mPropertiesWidgetEnabled = enable;
528 if ( enable && selectedItemsCount() == 1 )
530 setPropertiesWidget();
534 clearPropertiesWidget();
540 if ( index.isValid() )
542 QModelIndex proxyIndex = mProxyModel->mapFromSource( index );
543 mBrowserView->expand( proxyIndex );
544 mBrowserView->setCurrentIndex( proxyIndex );
548 void QgsBrowserWidget::splitterMoved()
550 QList<int> sizes = mSplitter->sizes();
551 float total = sizes.value( 0 ) + sizes.value( 1 );
552 mPropertiesWidgetHeight = total > 0 ? sizes.value( 1 ) / total : 0;
@ Fertile
Can create children. Even items without this capability may have children, but cannot create them,...
@ Fast
CreateChildren() is fast enough to be run in main thread when refreshing items, most root items (wms,...
@ Layer
Represents a map layer.
@ Project
Represents a QGIS project.
@ Directory
Represents a file directory.
A model for showing available data sources and other items in a structured tree.
void setMessageBar(QgsMessageBar *bar)
Sets message bar that will be passed in QgsDataItemGuiContext to data items.
void connectionsChanged(const QString &providerKey)
Emitted when connections for the specified providerKey have changed in the browser.
QgsDataItem * dataItem(const QModelIndex &idx) const
Returns the data item at the specified index, or nullptr if no item exists at the index.
void hidePath(QgsDataItem *item)
Hide the given path in the browser model.
void refresh(const QString &path)
Refresh item specified by path.
int rowCount(const QModelIndex &parent=QModelIndex()) const override
void initialize()
Delayed initialization, needed because the provider registry must be already populated.
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
bool initialized() const
Returns true if the model has been initialized.
A QSortFilterProxyModel subclass for filtering and sorting browser model items.
FilterSyntax
Filter syntax options.
@ RegularExpression
Regular expression filtering.
@ Wildcards
Wildcard filtering.
@ Normal
Standard string filtering.
void setHiddenDataItemProviderKeyFilter(const QStringList &hiddenItemsFilter)
Sets a filter to hide data items based on QgsDataItem::providerKey() associated with the item.
void setFilterString(const QString &filter)
Sets the filter string to use when filtering items in the model.
QgsDataItem * dataItem(const QModelIndex &index) const
Returns the data item at the specified proxy index, or nullptr if no item exists at the index.
void setFilterCaseSensitivity(Qt::CaseSensitivity sensitivity)
Sets whether item filtering should be case sensitive.
void setFilterSyntax(FilterSyntax syntax)
Sets the filter syntax.
void setBrowserModel(QgsBrowserModel *model)
Sets the underlying browser model.
Encapsulates the context in which a QgsDataItem is shown within the application GUI.
void setMessageBar(QgsMessageBar *bar)
Sets the associated message bar.
QList< QgsDataItemGuiProvider * > providers() const
Returns the list of available providers.
Abstract base class for providers which affect how QgsDataItem items behave within the application GU...
Base class for all items in the model.
virtual QList< QMenu * > menus(QWidget *parent)
Returns the list of menus available for this item.
virtual bool handleDoubleClick()
Called when a user double clicks on the item.
Qgis::BrowserItemType type() const
virtual QList< QAction * > actions(QWidget *parent)
Returns the list of actions available for this item.
virtual Qgis::BrowserItemCapabilities capabilities2() const
Returns the capabilities for the data item.
virtual void depopulate()
Remove children recursively and set as not populated. This is used when refreshing collapsed items.
A directory: contains subdirectories and layers.
void cleared()
Emitted when the widget is cleared.
void optionsChanged()
This signal is emitted whenever the application options have been changed.
static QgsGui * instance()
Returns a pointer to the singleton instance.
static QgsDataItemGuiProviderRegistry * dataItemGuiProviderRegistry()
Returns the global data item GUI provider registry, used for tracking providers which affect the brow...
Item that represents a layer that can be opened with one of the providers.
QgsMimeDataUtils::UriList mimeUris() const override
Returns mime URIs for the data item, most data providers will only return a single URI but some data ...
A bar for displaying non-blocking messages to the user.
Data item that can be used to represent QGIS projects.
This class is a composition of two QSettings instances:
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
#define QgsDebugMsgLevel(str, level)