Moved support classes into own private header

This commit is contained in:
Alessandro Pasotti 2017-06-01 17:28:42 +02:00
parent 7082649778
commit d62d444ea7
6 changed files with 747 additions and 940 deletions

View File

@ -9,157 +9,11 @@
class QgsBrowserPropertiesWrapLabel : QTextEdit
{
%Docstring
Hack to show wrapped text without spaces
.. versionadded:: 2.10
%End
%TypeHeaderCode
#include "qgsbrowserdockwidget.h"
%End
public:
QgsBrowserPropertiesWrapLabel( const QString &text, QWidget *parent = 0 );
%Docstring
Constructor for QgsBrowserPropertiesWrapLabel
\param text label text
\param parent parent widget
%End
};
class QgsBrowserPropertiesWidget : QWidget
{
%Docstring
The QgsBrowserPropertiesWidget base class
.. versionadded:: 2.10
%End
%TypeHeaderCode
#include "qgsbrowserdockwidget.h"
%End
public:
explicit QgsBrowserPropertiesWidget( QWidget *parent = 0 );
%Docstring
Constructor for QgsBrowserPropertiesWidget
\param parent parent widget
%End
static QgsBrowserPropertiesWidget *createWidget( QgsDataItem *item, QWidget *parent = 0 ) /Factory/;
%Docstring
Factory method to create a new browser widget
:rtype: QgsBrowserPropertiesWidget
%End
virtual void setItem( QgsDataItem *item );
%Docstring
Stub
%End
virtual void setWidget( QWidget *widget );
%Docstring
Set content widget, usually item paramWidget. Takes ownership.
%End
virtual void setCondensedMode( bool condensedMode );
%Docstring
Sets whether the properties widget should display in condensed mode, ie, for display in a dock
widget rather than it's own separate dialog.
\param condensedMode set to true to enable condensed mode
.. versionadded:: 2.10
%End
};
class QgsBrowserLayerProperties : QgsBrowserPropertiesWidget
{
%Docstring
The QgsBrowserLayerProperties class
.. versionadded:: 2.10
%End
%TypeHeaderCode
#include "qgsbrowserdockwidget.h"
%End
public:
explicit QgsBrowserLayerProperties( QWidget *parent = 0 );
%Docstring
Constructor for QgsBrowserLayerProperties
\param parent parent widget
%End
virtual void setItem( QgsDataItem *item );
%Docstring
Set item
%End
virtual void setCondensedMode( bool condensedMode );
%Docstring
Sets whether the properties widget should display in condensed mode, ie, for display in a dock
widget rather than it's own separate dialog.
\param condensedMode set to true to enable condensed mode
.. versionadded:: 2.10
%End
};
class QgsBrowserDirectoryProperties : QgsBrowserPropertiesWidget
{
%Docstring
The QgsBrowserDirectoryProperties class
.. versionadded:: 2.10
%End
%TypeHeaderCode
#include "qgsbrowserdockwidget.h"
%End
public:
explicit QgsBrowserDirectoryProperties( QWidget *parent = 0 );
%Docstring
Constructor for QgsBrowserDirectoryProperties
\param parent parent widget
%End
virtual void setItem( QgsDataItem *item );
%Docstring
Create widget from the given item and add it
%End
};
class QgsBrowserPropertiesDialog : QDialog
{
%Docstring
The QgsBrowserPropertiesDialog class
.. versionadded:: 2.10
%End
%TypeHeaderCode
#include "qgsbrowserdockwidget.h"
%End
public:
QgsBrowserPropertiesDialog( const QString &settingsSection, QWidget *parent = 0 );
%Docstring
Constructor for QgsBrowserPropertiesDialog
\param settingsSection prefix for settings (from the object name)
\param parent parent widget
%End
~QgsBrowserPropertiesDialog();
void setItem( QgsDataItem *item );
%Docstring
Create dialog from the given item and add it
%End
};
class QgsBrowserDockWidget : QgsDockWidget
{
%Docstring
The QgsBrowserDockWidget class
.. versionadded:: 2.10
.. versionadded:: 3.0
%End
%TypeHeaderCode
@ -167,7 +21,7 @@ class QgsBrowserDockWidget : QgsDockWidget
%End
public:
explicit QgsBrowserDockWidget( const QString &name, QWidget *parent = 0 );
explicit QgsBrowserDockWidget( const QString &name, QWidget *parent /TransferThis/ = 0 );
%Docstring
Constructor for QgsBrowserDockWidget
\param name name of the widget
@ -232,7 +86,6 @@ Apply filter to the model
Update project home directory
%End
void addSelectedLayers();
%Docstring
Add selected layers to the project
@ -270,155 +123,15 @@ Emitted when drop uri list needs to be handled
%End
protected:
void refreshModel( const QModelIndex &index );
%Docstring
Refresh the model
%End
virtual void showEvent( QShowEvent *event );
%Docstring
Show event override
%End
void addLayer( QgsLayerItem *layerItem );
%Docstring
Add a layer
%End
void clearPropertiesWidget();
%Docstring
Clear the properties widget
%End
void setPropertiesWidget();
%Docstring
Set the properties widget
%End
int selectedItemsCount();
%Docstring
Count selected items
:rtype: int
%End
QString settingsSection();
%Docstring
Settings prefix (the object name)
:rtype: str
%End
};
class QgsDockBrowserTreeView : QgsBrowserTreeView
{
%Docstring
Utility class for correct drag&drop handling.
We want to allow user to drag layers to qgis window. At the same time we do not
accept drops of the items on our view - but if we ignore the drag enter action
then qgis application consumes the drag events and it is possible to drop the
items on the tree view although the drop is actually managed by qgis app.
.. versionadded:: 2.10
%End
%TypeHeaderCode
#include "qgsbrowserdockwidget.h"
%End
public:
explicit QgsDockBrowserTreeView( QWidget *parent );
%Docstring
Constructor for QgsDockBrowserTreeView
\param parent parent widget
%End
virtual void dragEnterEvent( QDragEnterEvent *e );
%Docstring
Overrides drag enter event
%End
virtual void dragMoveEvent( QDragMoveEvent *e );
%Docstring
Overrides drag move event
%End
virtual void dropEvent( QDropEvent *e );
%Docstring
Overrides drag stop event
%End
};
class QgsBrowserTreeFilterProxyModel : QSortFilterProxyModel
{
%Docstring
Utility class for filtering browser items
.. versionadded:: 2.10
%End
%TypeHeaderCode
#include "qgsbrowserdockwidget.h"
%End
public:
explicit QgsBrowserTreeFilterProxyModel( QObject *parent );
%Docstring
Constructor for QgsBrowserTreeFilterProxyModel
@param parent parent widget
%End
void setBrowserModel( QgsBrowserModel *model );
%Docstring
Set the browser model
%End
void setFilterSyntax( const QString &syntax );
%Docstring
Set the filter syntax
%End
void setFilter( const QString &filter );
%Docstring
Set the filter
%End
void setCaseSensitive( bool caseSensitive );
%Docstring
Set case sensitivity
%End
void updateFilter();
%Docstring
Update filter
%End
protected:
bool filterAcceptsString( const QString &value ) const;
%Docstring
Filter accepts string
:rtype: bool
%End
virtual bool filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const;
%Docstring
It would be better to apply the filer only to expanded (visible) items, but using mapFromSource() + view here was causing strange errors
:rtype: bool
%End
bool filterAcceptsAncestor( const QModelIndex &sourceIndex ) const;
%Docstring
Returns true if at least one ancestor is accepted by filter
:rtype: bool
%End
bool filterAcceptsDescendant( const QModelIndex &sourceIndex ) const;
%Docstring
Returns true if at least one descendant s accepted by filter
:rtype: bool
%End
bool filterAcceptsItem( const QModelIndex &sourceIndex ) const;
%Docstring
Filter accepts item name
:rtype: bool
%End
};
/************************************************************************
* This file has been generated automatically from *

View File

@ -174,6 +174,7 @@ SET(QGIS_GUI_SRCS
qgsblendmodecombobox.cpp
qgsbrowsertreeview.cpp
qgsbrowserdockwidget.cpp
qgsbrowserdockwidget_p.cpp
qgsbusyindicatordialog.cpp
qgscharacterselectordialog.cpp
qgscheckablecombobox.cpp
@ -363,6 +364,7 @@ SET(QGIS_GUI_MOC_HDRS
qgsdial.h
qgsdialog.h
qgsdockwidget.h
qgsbrowserdockwidget_p.h
qgsbrowserdockwidget.h
qgsencodingfiledialog.h
qgserrordialog.h
@ -651,6 +653,7 @@ SET(QGIS_GUI_HDRS
qgstablewidgetitem.h
qgsuserinputdockwidget.h
qgsbrowserdockwidget.h
qgsbrowserdockwidget_p.h
qgsvertexmarker.h
qgsfiledownloader.h

View File

@ -13,6 +13,7 @@
* *
***************************************************************************/
#include "qgsbrowserdockwidget.h"
#include "qgsbrowserdockwidget_p.h"
#include <QAbstractTextDocumentLayout>
#include <QHeaderView>
@ -37,228 +38,6 @@
#include <QDragEnterEvent>
QgsBrowserPropertiesWrapLabel::QgsBrowserPropertiesWrapLabel( const QString &text, QWidget *parent )
: QTextEdit( text, parent )
{
setReadOnly( true );
setFrameStyle( QFrame::NoFrame );
setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum );
QPalette pal = palette();
pal.setColor( QPalette::Base, Qt::transparent );
setPalette( pal );
setLineWrapMode( QTextEdit::WidgetWidth );
setWordWrapMode( QTextOption::WrapAnywhere );
connect( qobject_cast<QAbstractTextDocumentLayout *>( document()->documentLayout() ), &QAbstractTextDocumentLayout::documentSizeChanged,
this, &QgsBrowserPropertiesWrapLabel::adjustHeight );
setMaximumHeight( 20 );
}
void QgsBrowserPropertiesWrapLabel::adjustHeight( QSizeF size )
{
int height = size.height() + 2 * frameWidth();
setMinimumHeight( height );
setMaximumHeight( height );
}
QgsBrowserPropertiesWidget::QgsBrowserPropertiesWidget( QWidget *parent )
: QWidget( parent )
{
}
void QgsBrowserPropertiesWidget::setWidget( QWidget *paramWidget )
{
QVBoxLayout *layout = new QVBoxLayout( this );
paramWidget->setParent( this );
layout->addWidget( paramWidget );
}
QgsBrowserPropertiesWidget *QgsBrowserPropertiesWidget::createWidget( QgsDataItem *item, QWidget *parent )
{
QgsBrowserPropertiesWidget *propertiesWidget = nullptr;
// In general, we would like to show all items' paramWidget, but top level items like
// WMS etc. have currently too large widgets which do not fit well to browser properties widget
if ( item->type() == QgsDataItem::Directory )
{
propertiesWidget = new QgsBrowserDirectoryProperties( parent );
propertiesWidget->setItem( item );
}
else if ( item->type() == QgsDataItem::Layer )
{
// prefer item's widget over standard layer widget
QWidget *paramWidget = item->paramWidget();
if ( paramWidget )
{
propertiesWidget = new QgsBrowserPropertiesWidget( parent );
propertiesWidget->setWidget( paramWidget );
}
else
{
propertiesWidget = new QgsBrowserLayerProperties( parent );
propertiesWidget->setItem( item );
}
}
return propertiesWidget;
}
QgsBrowserLayerProperties::QgsBrowserLayerProperties( QWidget *parent )
: QgsBrowserPropertiesWidget( parent )
{
setupUi( this );
mUriLabel = new QgsBrowserPropertiesWrapLabel( QString(), this );
mHeaderGridLayout->addItem( new QWidgetItem( mUriLabel ), 1, 1 );
}
void QgsBrowserLayerProperties::setItem( QgsDataItem *item )
{
QgsLayerItem *layerItem = qobject_cast<QgsLayerItem *>( item );
if ( !layerItem )
return;
mNoticeLabel->clear();
QgsMapLayer::LayerType type = layerItem->mapLayerType();
QString layerMetadata = tr( "Error" );
QgsCoordinateReferenceSystem layerCrs;
// temporarily override /Projections/defaultBehavior to avoid dialog prompt
QgsSettings settings;
QString defaultProjectionOption = settings.value( QStringLiteral( "Projections/defaultBehavior" ), "prompt" ).toString();
if ( settings.value( QStringLiteral( "Projections/defaultBehavior" ), "prompt" ).toString() == QLatin1String( "prompt" ) )
{
settings.setValue( QStringLiteral( "Projections/defaultBehavior" ), "useProject" );
}
// find root item
// we need to create a temporary layer to get metadata
// we could use a provider but the metadata is not as complete and "pretty" and this is easier
QgsDebugMsg( QString( "creating temporary layer using path %1" ).arg( layerItem->path() ) );
if ( type == QgsMapLayer::RasterLayer )
{
QgsDebugMsg( "creating raster layer" );
// should copy code from addLayer() to split uri ?
QgsRasterLayer *layer = new QgsRasterLayer( layerItem->uri(), layerItem->uri(), layerItem->providerKey() );
if ( layer )
{
if ( layer->isValid() )
{
layerCrs = layer->crs();
layerMetadata = layer->htmlMetadata();
}
delete layer;
}
}
else if ( type == QgsMapLayer::VectorLayer )
{
QgsDebugMsg( "creating vector layer" );
QgsVectorLayer *layer = new QgsVectorLayer( layerItem->uri(), layerItem->name(), layerItem->providerKey() );
if ( layer )
{
if ( layer->isValid() )
{
layerCrs = layer->crs();
layerMetadata = layer->htmlMetadata();
}
delete layer;
}
}
else if ( type == QgsMapLayer::PluginLayer )
{
// TODO: support display of properties for plugin layers
return;
}
// restore /Projections/defaultBehavior
if ( defaultProjectionOption == QLatin1String( "prompt" ) )
{
settings.setValue( QStringLiteral( "Projections/defaultBehavior" ), defaultProjectionOption );
}
mNameLabel->setText( layerItem->name() );
mUriLabel->setText( layerItem->uri() );
mProviderLabel->setText( layerItem->providerKey() );
QString myStyle = QgsApplication::reportStyleSheet();
mMetadataTextBrowser->document()->setDefaultStyleSheet( myStyle );
mMetadataTextBrowser->setHtml( layerMetadata );
// report if layer was set to to project crs without prompt (may give a false positive)
if ( defaultProjectionOption == QLatin1String( "prompt" ) )
{
QgsCoordinateReferenceSystem defaultCrs =
QgsProject::instance()->crs();
if ( layerCrs == defaultCrs )
mNoticeLabel->setText( "NOTICE: Layer srs set from project (" + defaultCrs.authid() + ')' );
}
if ( mNoticeLabel->text().isEmpty() )
{
mNoticeLabel->hide();
}
}
void QgsBrowserLayerProperties::setCondensedMode( bool condensedMode )
{
if ( condensedMode )
{
mUriLabel->setLineWrapMode( QTextEdit::NoWrap );
mUriLabel->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
mUriLabel->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
}
else
{
mUriLabel->setLineWrapMode( QTextEdit::WidgetWidth );
mUriLabel->setHorizontalScrollBarPolicy( Qt::ScrollBarAsNeeded );
mUriLabel->setVerticalScrollBarPolicy( Qt::ScrollBarAsNeeded );
}
}
QgsBrowserDirectoryProperties::QgsBrowserDirectoryProperties( QWidget *parent )
: QgsBrowserPropertiesWidget( parent )
, mDirectoryWidget( nullptr )
{
setupUi( this );
mPathLabel = new QgsBrowserPropertiesWrapLabel( QString(), mHeaderWidget );
mHeaderGridLayout->addItem( new QWidgetItem( mPathLabel ), 0, 1 );
}
void QgsBrowserDirectoryProperties::setItem( QgsDataItem *item )
{
QgsDirectoryItem *directoryItem = qobject_cast<QgsDirectoryItem *>( item );
if ( !item )
return;
mPathLabel->setText( directoryItem->dirPath() );
mDirectoryWidget = new QgsDirectoryParamWidget( directoryItem->dirPath(), this );
mLayout->addWidget( mDirectoryWidget );
}
QgsBrowserPropertiesDialog::QgsBrowserPropertiesDialog( const QString &settingsSection, QWidget *parent )
: QDialog( parent )
, mPropertiesWidget( nullptr )
, mSettingsSection( settingsSection )
{
setupUi( this );
QgsSettings settings;
restoreGeometry( settings.value( mSettingsSection + "/propertiesDialog/geometry" ).toByteArray() );
}
QgsBrowserPropertiesDialog::~QgsBrowserPropertiesDialog()
{
QgsSettings settings;
settings.setValue( mSettingsSection + "/propertiesDialog/geometry", saveGeometry() );
}
void QgsBrowserPropertiesDialog::setItem( QgsDataItem *item )
{
if ( !item )
return;
mPropertiesWidget = QgsBrowserPropertiesWidget::createWidget( item, this );
mLayout->addWidget( mPropertiesWidget );
setWindowTitle( item->type() == QgsDataItem::Layer ? tr( "Layer Properties" ) : tr( "Directory Properties" ) );
}
QgsBrowserDockWidget::QgsBrowserDockWidget( const QString &name, QWidget *parent )
: QgsDockWidget( parent )
, mModel( nullptr )
@ -743,218 +522,3 @@ void QgsBrowserDockWidget::splitterMoved()
float total = sizes.value( 0 ) + sizes.value( 1 );
mPropertiesWidgetHeight = total > 0 ? sizes.value( 1 ) / total : 0;
}
//
// QgsDockBrowserTreeView
//
QgsDockBrowserTreeView::QgsDockBrowserTreeView( QWidget *parent ) : QgsBrowserTreeView( parent )
{
setDragDropMode( QTreeView::DragDrop ); // sets also acceptDrops + dragEnabled
setSelectionMode( QAbstractItemView::ExtendedSelection );
setContextMenuPolicy( Qt::CustomContextMenu );
setHeaderHidden( true );
setDropIndicatorShown( true );
}
void QgsDockBrowserTreeView::dragEnterEvent( QDragEnterEvent *e )
{
// if this mime data come from layer tree, the proposed action will be MoveAction
// but for browser we really need CopyAction
if ( e->mimeData()->hasFormat( QStringLiteral( "application/qgis.layertreemodeldata" ) ) &&
e->mimeData()->hasFormat( QStringLiteral( "application/x-vnd.qgis.qgis.uri" ) ) )
e->setDropAction( Qt::CopyAction );
// accept drag enter so that our widget will not get ignored
// and drag events will not get passed to QgisApp
e->accept();
}
void QgsDockBrowserTreeView::dragMoveEvent( QDragMoveEvent *e )
{
// do not accept drops above/below items
/*if ( dropIndicatorPosition() != QAbstractItemView::OnItem )
{
QgsDebugMsg("drag not on item");
e->ignore();
return;
}*/
// if this mime data come from layer tree, the proposed action will be MoveAction
// but for browser we really need CopyAction
if ( e->mimeData()->hasFormat( QStringLiteral( "application/qgis.layertreemodeldata" ) ) &&
e->mimeData()->hasFormat( QStringLiteral( "application/x-vnd.qgis.qgis.uri" ) ) )
e->setDropAction( Qt::CopyAction );
QTreeView::dragMoveEvent( e );
if ( !e->mimeData()->hasFormat( QStringLiteral( "application/x-vnd.qgis.qgis.uri" ) ) )
{
e->ignore();
return;
}
}
void QgsDockBrowserTreeView::dropEvent( QDropEvent *e )
{
// if this mime data come from layer tree, the proposed action will be MoveAction
// but for browser we really need CopyAction
if ( e->mimeData()->hasFormat( QStringLiteral( "application/qgis.layertreemodeldata" ) ) &&
e->mimeData()->hasFormat( QStringLiteral( "application/x-vnd.qgis.qgis.uri" ) ) )
e->setDropAction( Qt::CopyAction );
QTreeView::dropEvent( e );
}
//
// QgsBrowserTreeFilterProxyModel
//
QgsBrowserTreeFilterProxyModel::QgsBrowserTreeFilterProxyModel( QObject *parent )
: QSortFilterProxyModel( parent )
, mModel( nullptr )
, mPatternSyntax( QStringLiteral( "normal" ) )
, mCaseSensitivity( Qt::CaseInsensitive )
{
setDynamicSortFilter( true );
}
void QgsBrowserTreeFilterProxyModel::setBrowserModel( QgsBrowserModel *model )
{
mModel = model;
setSourceModel( model );
}
void QgsBrowserTreeFilterProxyModel::setFilterSyntax( const QString &syntax )
{
QgsDebugMsg( QString( "syntax = %1" ).arg( syntax ) );
if ( mPatternSyntax == syntax )
return;
mPatternSyntax = syntax;
updateFilter();
}
void QgsBrowserTreeFilterProxyModel::setFilter( const QString &filter )
{
QgsDebugMsg( QString( "filter = %1" ).arg( mFilter ) );
if ( mFilter == filter )
return;
mFilter = filter;
updateFilter();
}
void QgsBrowserTreeFilterProxyModel::setCaseSensitive( bool caseSensitive )
{
mCaseSensitivity = caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
updateFilter();
}
void QgsBrowserTreeFilterProxyModel::updateFilter()
{
QgsDebugMsg( QString( "filter = %1 syntax = %2" ).arg( mFilter, mPatternSyntax ) );
mREList.clear();
if ( mPatternSyntax == QLatin1String( "normal" ) )
{
Q_FOREACH ( const QString &f, mFilter.split( '|' ) )
{
QRegExp rx( QString( "*%1*" ).arg( f.trimmed() ) );
rx.setPatternSyntax( QRegExp::Wildcard );
rx.setCaseSensitivity( mCaseSensitivity );
mREList.append( rx );
}
}
else if ( mPatternSyntax == QLatin1String( "wildcard" ) )
{
Q_FOREACH ( const QString &f, mFilter.split( '|' ) )
{
QRegExp rx( f.trimmed() );
rx.setPatternSyntax( QRegExp::Wildcard );
rx.setCaseSensitivity( mCaseSensitivity );
mREList.append( rx );
}
}
else
{
QRegExp rx( mFilter.trimmed() );
rx.setPatternSyntax( QRegExp::RegExp );
rx.setCaseSensitivity( mCaseSensitivity );
mREList.append( rx );
}
invalidateFilter();
}
bool QgsBrowserTreeFilterProxyModel::filterAcceptsString( const QString &value ) const
{
if ( mPatternSyntax == QLatin1String( "normal" ) || mPatternSyntax == QLatin1String( "wildcard" ) )
{
Q_FOREACH ( const QRegExp &rx, mREList )
{
QgsDebugMsg( QString( "value: [%1] rx: [%2] match: %3" ).arg( value, rx.pattern() ).arg( rx.exactMatch( value ) ) );
if ( rx.exactMatch( value ) )
return true;
}
}
else
{
Q_FOREACH ( const QRegExp &rx, mREList )
{
QgsDebugMsg( QString( "value: [%1] rx: [%2] match: %3" ).arg( value, rx.pattern() ).arg( rx.indexIn( value ) ) );
if ( rx.indexIn( value ) != -1 )
return true;
}
}
return false;
}
bool QgsBrowserTreeFilterProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const
{
if ( mFilter.isEmpty() || !mModel )
return true;
QModelIndex sourceIndex = mModel->index( sourceRow, 0, sourceParent );
return filterAcceptsItem( sourceIndex ) || filterAcceptsAncestor( sourceIndex ) || filterAcceptsDescendant( sourceIndex );
}
bool QgsBrowserTreeFilterProxyModel::filterAcceptsAncestor( const QModelIndex &sourceIndex ) const
{
if ( !mModel )
return true;
QModelIndex sourceParentIndex = mModel->parent( sourceIndex );
if ( !sourceParentIndex.isValid() )
return false;
if ( filterAcceptsItem( sourceParentIndex ) )
return true;
return filterAcceptsAncestor( sourceParentIndex );
}
bool QgsBrowserTreeFilterProxyModel::filterAcceptsDescendant( const QModelIndex &sourceIndex ) const
{
if ( !mModel )
return true;
for ( int i = 0; i < mModel->rowCount( sourceIndex ); i++ )
{
QgsDebugMsg( QString( "i = %1" ).arg( i ) );
QModelIndex sourceChildIndex = mModel->index( i, 0, sourceIndex );
if ( filterAcceptsItem( sourceChildIndex ) )
return true;
if ( filterAcceptsDescendant( sourceChildIndex ) )
return true;
}
return false;
}
bool QgsBrowserTreeFilterProxyModel::filterAcceptsItem( const QModelIndex &sourceIndex ) const
{
if ( !mModel )
return true;
//accept item if either displayed text or comment role matches string
QString comment = mModel->data( sourceIndex, QgsBrowserModel::CommentRole ).toString();
return ( filterAcceptsString( mModel->data( sourceIndex, Qt::DisplayRole ).toString() )
|| ( !comment.isEmpty() && filterAcceptsString( comment ) ) );
}

View File

@ -23,6 +23,7 @@
#include "qgsdataitem.h"
#include "qgsbrowsertreeview.h"
#include "qgsdockwidget.h"
#include "qgsbrowserdockwidget_p.h"
#include "qgis_gui.h"
#include <QSortFilterProxyModel>
@ -33,139 +34,10 @@ class QgsLayerItem;
class QgsDataItem;
class QgsBrowserTreeFilterProxyModel;
/**
* \ingroup gui
* Hack to show wrapped text without spaces
* \since QGIS 2.10
*/
class GUI_EXPORT QgsBrowserPropertiesWrapLabel : public QTextEdit
{
Q_OBJECT
public:
/**
* Constructor for QgsBrowserPropertiesWrapLabel
* \param text label text
* \param parent parent widget
*/
QgsBrowserPropertiesWrapLabel( const QString &text, QWidget *parent = nullptr );
private slots:
void adjustHeight( QSizeF size );
};
/**
* \ingroup gui
* The QgsBrowserPropertiesWidget base class
* \since QGIS 2.10
*/
class GUI_EXPORT QgsBrowserPropertiesWidget : public QWidget
{
Q_OBJECT
public:
/**
* Constructor for QgsBrowserPropertiesWidget
* \param parent parent widget
*/
explicit QgsBrowserPropertiesWidget( QWidget *parent = nullptr );
//! Factory method to create a new browser widget
static QgsBrowserPropertiesWidget *createWidget( QgsDataItem *item, QWidget *parent = nullptr ) SIP_FACTORY;
//! Stub
virtual void setItem( QgsDataItem *item ) { Q_UNUSED( item ) }
//! Set content widget, usually item paramWidget. Takes ownership.
virtual void setWidget( QWidget *widget );
/** Sets whether the properties widget should display in condensed mode, ie, for display in a dock
* widget rather than it's own separate dialog.
* \param condensedMode set to true to enable condensed mode
* \since QGIS 2.10
*/
virtual void setCondensedMode( bool condensedMode ) { Q_UNUSED( condensedMode ); }
};
/**
* \ingroup gui
* The QgsBrowserLayerProperties class
* \since QGIS 2.10
*/
class GUI_EXPORT QgsBrowserLayerProperties : public QgsBrowserPropertiesWidget, private Ui::QgsBrowserLayerPropertiesBase
{
Q_OBJECT
public:
/**
* Constructor for QgsBrowserLayerProperties
* \param parent parent widget
*/
explicit QgsBrowserLayerProperties( QWidget *parent = nullptr );
//! Set item
void setItem( QgsDataItem *item ) override;
/** Sets whether the properties widget should display in condensed mode, ie, for display in a dock
* widget rather than it's own separate dialog.
* \param condensedMode set to true to enable condensed mode
* \since QGIS 2.10
*/
virtual void setCondensedMode( bool condensedMode ) override;
private:
QgsBrowserPropertiesWrapLabel *mUriLabel = nullptr;
};
/**
* \ingroup gui
* The QgsBrowserDirectoryProperties class
* \since QGIS 2.10
*/
class GUI_EXPORT QgsBrowserDirectoryProperties : public QgsBrowserPropertiesWidget, private Ui::QgsBrowserDirectoryPropertiesBase
{
Q_OBJECT
public:
/**
* Constructor for QgsBrowserDirectoryProperties
* \param parent parent widget
*/
explicit QgsBrowserDirectoryProperties( QWidget *parent = nullptr );
//! Create widget from the given item and add it
void setItem( QgsDataItem *item ) override;
private:
QgsDirectoryParamWidget *mDirectoryWidget = nullptr;
QgsBrowserPropertiesWrapLabel *mPathLabel = nullptr;
};
/**
* \ingroup gui
* The QgsBrowserPropertiesDialog class
* \since QGIS 2.10
*/
class GUI_EXPORT QgsBrowserPropertiesDialog : public QDialog, private Ui::QgsBrowserPropertiesDialogBase
{
Q_OBJECT
public:
/**
* Constructor for QgsBrowserPropertiesDialog
* \param settingsSection prefix for settings (from the object name)
* \param parent parent widget
*/
QgsBrowserPropertiesDialog( const QString &settingsSection, QWidget *parent = nullptr );
~QgsBrowserPropertiesDialog();
//! Create dialog from the given item and add it
void setItem( QgsDataItem *item );
private:
QgsBrowserPropertiesWidget *mPropertiesWidget = nullptr;
QString mSettingsSection;
};
/**
* \ingroup gui
* The QgsBrowserDockWidget class
* \since QGIS 2.10
* \since QGIS 3.0
*/
class GUI_EXPORT QgsBrowserDockWidget : public QgsDockWidget, private Ui::QgsBrowserDockWidgetBase
{
@ -177,7 +49,7 @@ class GUI_EXPORT QgsBrowserDockWidget : public QgsDockWidget, private Ui::QgsBro
* \param name name of the widget
* \param parent parent widget
*/
explicit QgsBrowserDockWidget( const QString &name, QWidget *parent = nullptr );
explicit QgsBrowserDockWidget( const QString &name, QWidget *parent SIP_TRANSFERTHIS = nullptr );
~QgsBrowserDockWidget();
//! Add directory to favorites
void addFavoriteDirectory( const QString &favDir );
@ -211,7 +83,6 @@ class GUI_EXPORT QgsBrowserDockWidget : public QgsDockWidget, private Ui::QgsBro
//! Update project home directory
void updateProjectHome();
//! Add selected layers to the project
void addSelectedLayers();
//! Show the layer properties
@ -233,10 +104,12 @@ class GUI_EXPORT QgsBrowserDockWidget : public QgsDockWidget, private Ui::QgsBro
void handleDropUriList( const QgsMimeDataUtils::UriList & );
protected:
//! Refresh the model
void refreshModel( const QModelIndex &index );
//! Show event override
void showEvent( QShowEvent *event ) override;
private:
//! Refresh the model
void refreshModel( const QModelIndex &index );
//! Add a layer
void addLayer( QgsLayerItem *layerItem );
//! Clear the properties widget
@ -257,88 +130,8 @@ class GUI_EXPORT QgsBrowserDockWidget : public QgsDockWidget, private Ui::QgsBro
// height fraction
float mPropertiesWidgetHeight;
private:
};
/**
* \ingroup gui
* Utility class for correct drag&drop handling.
*
* We want to allow user to drag layers to qgis window. At the same time we do not
* accept drops of the items on our view - but if we ignore the drag enter action
* then qgis application consumes the drag events and it is possible to drop the
* items on the tree view although the drop is actually managed by qgis app.
* \since QGIS 2.10
*/
class GUI_EXPORT QgsDockBrowserTreeView : public QgsBrowserTreeView
{
Q_OBJECT
public:
/**
* Constructor for QgsDockBrowserTreeView
* \param parent parent widget
*/
explicit QgsDockBrowserTreeView( QWidget *parent );
//! Overrides drag enter event
void dragEnterEvent( QDragEnterEvent *e ) override;
//! Overrides drag move event
void dragMoveEvent( QDragMoveEvent *e ) override;
//! Overrides drag stop event
void dropEvent( QDropEvent *e ) override;
};
/**
* \ingroup gui
* Utility class for filtering browser items
* \since QGIS 2.10
*/
class GUI_EXPORT QgsBrowserTreeFilterProxyModel : public QSortFilterProxyModel
{
Q_OBJECT
public:
/**
* Constructor for QgsBrowserTreeFilterProxyModel
* @param parent parent widget
*/
explicit QgsBrowserTreeFilterProxyModel( QObject *parent );
//! Set the browser model
void setBrowserModel( QgsBrowserModel *model );
//! Set the filter syntax
void setFilterSyntax( const QString &syntax );
//! Set the filter
void setFilter( const QString &filter );
//! Set case sensitivity
void setCaseSensitive( bool caseSensitive );
//! Update filter
void updateFilter();
protected:
QgsBrowserModel *mModel = nullptr;
QString mFilter; //filter string provided
QVector<QRegExp> mREList; //list of filters, separated by "|"
QString mPatternSyntax;
Qt::CaseSensitivity mCaseSensitivity;
//! Filter accepts string
bool filterAcceptsString( const QString &value ) const;
//! It would be better to apply the filer only to expanded (visible) items, but using mapFromSource() + view here was causing strange errors
bool filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const override;
//! Returns true if at least one ancestor is accepted by filter
bool filterAcceptsAncestor( const QModelIndex &sourceIndex ) const;
//! Returns true if at least one descendant s accepted by filter
bool filterAcceptsDescendant( const QModelIndex &sourceIndex ) const;
//! Filter accepts item name
bool filterAcceptsItem( const QModelIndex &sourceIndex ) const;
};
#endif // QGSBROWSERDOCKWIDGET_H

View File

@ -0,0 +1,483 @@
/***************************************************************************
qgsbrowserdockwidget_p.cpp
Private classes for QgsBrowserDockWidget
---------------------
begin : May 2017
copyright : (C) 2017 by Alessandro Pasotti
real work done by : (C) 2011 by Martin Dobias
email : a dot pasotti at itopen dot it
---------------------
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsbrowserdockwidget_p.h"
#include <QAbstractTextDocumentLayout>
#include <QHeaderView>
#include <QTreeView>
#include <QMenu>
#include <QToolButton>
#include <QFileDialog>
#include <QPlainTextDocumentLayout>
#include <QSortFilterProxyModel>
#include "qgsbrowsermodel.h"
#include "qgsbrowsertreeview.h"
#include "qgslogger.h"
#include "qgsrasterlayer.h"
#include "qgsvectorlayer.h"
#include "qgsproject.h"
#include "qgssettings.h"
#include <QDragEnterEvent>
/// @cond PRIVATE
QgsBrowserPropertiesWrapLabel::QgsBrowserPropertiesWrapLabel( const QString &text, QWidget *parent )
: QTextEdit( text, parent )
{
setReadOnly( true );
setFrameStyle( QFrame::NoFrame );
setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum );
QPalette pal = palette();
pal.setColor( QPalette::Base, Qt::transparent );
setPalette( pal );
setLineWrapMode( QTextEdit::WidgetWidth );
setWordWrapMode( QTextOption::WrapAnywhere );
connect( qobject_cast<QAbstractTextDocumentLayout *>( document()->documentLayout() ), &QAbstractTextDocumentLayout::documentSizeChanged,
this, &QgsBrowserPropertiesWrapLabel::adjustHeight );
setMaximumHeight( 20 );
}
void QgsBrowserPropertiesWrapLabel::adjustHeight( QSizeF size )
{
int height = size.height() + 2 * frameWidth();
setMinimumHeight( height );
setMaximumHeight( height );
}
QgsBrowserPropertiesWidget::QgsBrowserPropertiesWidget( QWidget *parent )
: QWidget( parent )
{
}
void QgsBrowserPropertiesWidget::setWidget( QWidget *paramWidget )
{
QVBoxLayout *layout = new QVBoxLayout( this );
paramWidget->setParent( this );
layout->addWidget( paramWidget );
}
QgsBrowserPropertiesWidget *QgsBrowserPropertiesWidget::createWidget( QgsDataItem *item, QWidget *parent )
{
QgsBrowserPropertiesWidget *propertiesWidget = nullptr;
// In general, we would like to show all items' paramWidget, but top level items like
// WMS etc. have currently too large widgets which do not fit well to browser properties widget
if ( item->type() == QgsDataItem::Directory )
{
propertiesWidget = new QgsBrowserDirectoryProperties( parent );
propertiesWidget->setItem( item );
}
else if ( item->type() == QgsDataItem::Layer )
{
// prefer item's widget over standard layer widget
QWidget *paramWidget = item->paramWidget();
if ( paramWidget )
{
propertiesWidget = new QgsBrowserPropertiesWidget( parent );
propertiesWidget->setWidget( paramWidget );
}
else
{
propertiesWidget = new QgsBrowserLayerProperties( parent );
propertiesWidget->setItem( item );
}
}
return propertiesWidget;
}
QgsBrowserLayerProperties::QgsBrowserLayerProperties( QWidget *parent )
: QgsBrowserPropertiesWidget( parent )
{
setupUi( this );
mUriLabel = new QgsBrowserPropertiesWrapLabel( QString(), this );
mHeaderGridLayout->addItem( new QWidgetItem( mUriLabel ), 1, 1 );
}
void QgsBrowserLayerProperties::setItem( QgsDataItem *item )
{
QgsLayerItem *layerItem = qobject_cast<QgsLayerItem *>( item );
if ( !layerItem )
return;
mNoticeLabel->clear();
QgsMapLayer::LayerType type = layerItem->mapLayerType();
QString layerMetadata = tr( "Error" );
QgsCoordinateReferenceSystem layerCrs;
// temporarily override /Projections/defaultBehavior to avoid dialog prompt
QgsSettings settings;
QString defaultProjectionOption = settings.value( QStringLiteral( "Projections/defaultBehavior" ), "prompt" ).toString();
if ( settings.value( QStringLiteral( "Projections/defaultBehavior" ), "prompt" ).toString() == QLatin1String( "prompt" ) )
{
settings.setValue( QStringLiteral( "Projections/defaultBehavior" ), "useProject" );
}
// find root item
// we need to create a temporary layer to get metadata
// we could use a provider but the metadata is not as complete and "pretty" and this is easier
QgsDebugMsg( QString( "creating temporary layer using path %1" ).arg( layerItem->path() ) );
if ( type == QgsMapLayer::RasterLayer )
{
QgsDebugMsg( "creating raster layer" );
// should copy code from addLayer() to split uri ?
QgsRasterLayer *layer = new QgsRasterLayer( layerItem->uri(), layerItem->uri(), layerItem->providerKey() );
if ( layer )
{
if ( layer->isValid() )
{
layerCrs = layer->crs();
layerMetadata = layer->htmlMetadata();
}
delete layer;
}
}
else if ( type == QgsMapLayer::VectorLayer )
{
QgsDebugMsg( "creating vector layer" );
QgsVectorLayer *layer = new QgsVectorLayer( layerItem->uri(), layerItem->name(), layerItem->providerKey() );
if ( layer )
{
if ( layer->isValid() )
{
layerCrs = layer->crs();
layerMetadata = layer->htmlMetadata();
}
delete layer;
}
}
else if ( type == QgsMapLayer::PluginLayer )
{
// TODO: support display of properties for plugin layers
return;
}
// restore /Projections/defaultBehavior
if ( defaultProjectionOption == QLatin1String( "prompt" ) )
{
settings.setValue( QStringLiteral( "Projections/defaultBehavior" ), defaultProjectionOption );
}
mNameLabel->setText( layerItem->name() );
mUriLabel->setText( layerItem->uri() );
mProviderLabel->setText( layerItem->providerKey() );
QString myStyle = QgsApplication::reportStyleSheet();
mMetadataTextBrowser->document()->setDefaultStyleSheet( myStyle );
mMetadataTextBrowser->setHtml( layerMetadata );
// report if layer was set to to project crs without prompt (may give a false positive)
if ( defaultProjectionOption == QLatin1String( "prompt" ) )
{
QgsCoordinateReferenceSystem defaultCrs =
QgsProject::instance()->crs();
if ( layerCrs == defaultCrs )
mNoticeLabel->setText( "NOTICE: Layer srs set from project (" + defaultCrs.authid() + ')' );
}
if ( mNoticeLabel->text().isEmpty() )
{
mNoticeLabel->hide();
}
}
void QgsBrowserLayerProperties::setCondensedMode( bool condensedMode )
{
if ( condensedMode )
{
mUriLabel->setLineWrapMode( QTextEdit::NoWrap );
mUriLabel->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
mUriLabel->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
}
else
{
mUriLabel->setLineWrapMode( QTextEdit::WidgetWidth );
mUriLabel->setHorizontalScrollBarPolicy( Qt::ScrollBarAsNeeded );
mUriLabel->setVerticalScrollBarPolicy( Qt::ScrollBarAsNeeded );
}
}
QgsBrowserDirectoryProperties::QgsBrowserDirectoryProperties( QWidget *parent )
: QgsBrowserPropertiesWidget( parent )
, mDirectoryWidget( nullptr )
{
setupUi( this );
mPathLabel = new QgsBrowserPropertiesWrapLabel( QString(), mHeaderWidget );
mHeaderGridLayout->addItem( new QWidgetItem( mPathLabel ), 0, 1 );
}
void QgsBrowserDirectoryProperties::setItem( QgsDataItem *item )
{
QgsDirectoryItem *directoryItem = qobject_cast<QgsDirectoryItem *>( item );
if ( !item )
return;
mPathLabel->setText( directoryItem->dirPath() );
mDirectoryWidget = new QgsDirectoryParamWidget( directoryItem->dirPath(), this );
mLayout->addWidget( mDirectoryWidget );
}
QgsBrowserPropertiesDialog::QgsBrowserPropertiesDialog( const QString &settingsSection, QWidget *parent )
: QDialog( parent )
, mPropertiesWidget( nullptr )
, mSettingsSection( settingsSection )
{
setupUi( this );
QgsSettings settings;
restoreGeometry( settings.value( mSettingsSection + "/propertiesDialog/geometry" ).toByteArray() );
}
QgsBrowserPropertiesDialog::~QgsBrowserPropertiesDialog()
{
QgsSettings settings;
settings.setValue( mSettingsSection + "/propertiesDialog/geometry", saveGeometry() );
}
void QgsBrowserPropertiesDialog::setItem( QgsDataItem *item )
{
if ( !item )
return;
mPropertiesWidget = QgsBrowserPropertiesWidget::createWidget( item, this );
mLayout->addWidget( mPropertiesWidget );
setWindowTitle( item->type() == QgsDataItem::Layer ? tr( "Layer Properties" ) : tr( "Directory Properties" ) );
}
//
// QgsDockBrowserTreeView
//
QgsDockBrowserTreeView::QgsDockBrowserTreeView( QWidget *parent ) : QgsBrowserTreeView( parent )
{
setDragDropMode( QTreeView::DragDrop ); // sets also acceptDrops + dragEnabled
setSelectionMode( QAbstractItemView::ExtendedSelection );
setContextMenuPolicy( Qt::CustomContextMenu );
setHeaderHidden( true );
setDropIndicatorShown( true );
}
void QgsDockBrowserTreeView::dragEnterEvent( QDragEnterEvent *e )
{
// if this mime data come from layer tree, the proposed action will be MoveAction
// but for browser we really need CopyAction
if ( e->mimeData()->hasFormat( QStringLiteral( "application/qgis.layertreemodeldata" ) ) &&
e->mimeData()->hasFormat( QStringLiteral( "application/x-vnd.qgis.qgis.uri" ) ) )
e->setDropAction( Qt::CopyAction );
// accept drag enter so that our widget will not get ignored
// and drag events will not get passed to QgisApp
e->accept();
}
void QgsDockBrowserTreeView::dragMoveEvent( QDragMoveEvent *e )
{
// do not accept drops above/below items
/*if ( dropIndicatorPosition() != QAbstractItemView::OnItem )
{
QgsDebugMsg("drag not on item");
e->ignore();
return;
}*/
// if this mime data come from layer tree, the proposed action will be MoveAction
// but for browser we really need CopyAction
if ( e->mimeData()->hasFormat( QStringLiteral( "application/qgis.layertreemodeldata" ) ) &&
e->mimeData()->hasFormat( QStringLiteral( "application/x-vnd.qgis.qgis.uri" ) ) )
e->setDropAction( Qt::CopyAction );
QTreeView::dragMoveEvent( e );
if ( !e->mimeData()->hasFormat( QStringLiteral( "application/x-vnd.qgis.qgis.uri" ) ) )
{
e->ignore();
return;
}
}
void QgsDockBrowserTreeView::dropEvent( QDropEvent *e )
{
// if this mime data come from layer tree, the proposed action will be MoveAction
// but for browser we really need CopyAction
if ( e->mimeData()->hasFormat( QStringLiteral( "application/qgis.layertreemodeldata" ) ) &&
e->mimeData()->hasFormat( QStringLiteral( "application/x-vnd.qgis.qgis.uri" ) ) )
e->setDropAction( Qt::CopyAction );
QTreeView::dropEvent( e );
}
//
// QgsBrowserTreeFilterProxyModel
//
QgsBrowserTreeFilterProxyModel::QgsBrowserTreeFilterProxyModel( QObject *parent )
: QSortFilterProxyModel( parent )
, mModel( nullptr )
, mPatternSyntax( QStringLiteral( "normal" ) )
, mCaseSensitivity( Qt::CaseInsensitive )
{
setDynamicSortFilter( true );
}
void QgsBrowserTreeFilterProxyModel::setBrowserModel( QgsBrowserModel *model )
{
mModel = model;
setSourceModel( model );
}
void QgsBrowserTreeFilterProxyModel::setFilterSyntax( const QString &syntax )
{
QgsDebugMsg( QString( "syntax = %1" ).arg( syntax ) );
if ( mPatternSyntax == syntax )
return;
mPatternSyntax = syntax;
updateFilter();
}
void QgsBrowserTreeFilterProxyModel::setFilter( const QString &filter )
{
QgsDebugMsg( QString( "filter = %1" ).arg( mFilter ) );
if ( mFilter == filter )
return;
mFilter = filter;
updateFilter();
}
void QgsBrowserTreeFilterProxyModel::setCaseSensitive( bool caseSensitive )
{
mCaseSensitivity = caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
updateFilter();
}
void QgsBrowserTreeFilterProxyModel::updateFilter()
{
QgsDebugMsg( QString( "filter = %1 syntax = %2" ).arg( mFilter, mPatternSyntax ) );
mREList.clear();
if ( mPatternSyntax == QLatin1String( "normal" ) )
{
Q_FOREACH ( const QString &f, mFilter.split( '|' ) )
{
QRegExp rx( QString( "*%1*" ).arg( f.trimmed() ) );
rx.setPatternSyntax( QRegExp::Wildcard );
rx.setCaseSensitivity( mCaseSensitivity );
mREList.append( rx );
}
}
else if ( mPatternSyntax == QLatin1String( "wildcard" ) )
{
Q_FOREACH ( const QString &f, mFilter.split( '|' ) )
{
QRegExp rx( f.trimmed() );
rx.setPatternSyntax( QRegExp::Wildcard );
rx.setCaseSensitivity( mCaseSensitivity );
mREList.append( rx );
}
}
else
{
QRegExp rx( mFilter.trimmed() );
rx.setPatternSyntax( QRegExp::RegExp );
rx.setCaseSensitivity( mCaseSensitivity );
mREList.append( rx );
}
invalidateFilter();
}
bool QgsBrowserTreeFilterProxyModel::filterAcceptsString( const QString &value ) const
{
if ( mPatternSyntax == QLatin1String( "normal" ) || mPatternSyntax == QLatin1String( "wildcard" ) )
{
Q_FOREACH ( const QRegExp &rx, mREList )
{
QgsDebugMsg( QString( "value: [%1] rx: [%2] match: %3" ).arg( value, rx.pattern() ).arg( rx.exactMatch( value ) ) );
if ( rx.exactMatch( value ) )
return true;
}
}
else
{
Q_FOREACH ( const QRegExp &rx, mREList )
{
QgsDebugMsg( QString( "value: [%1] rx: [%2] match: %3" ).arg( value, rx.pattern() ).arg( rx.indexIn( value ) ) );
if ( rx.indexIn( value ) != -1 )
return true;
}
}
return false;
}
bool QgsBrowserTreeFilterProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const
{
if ( mFilter.isEmpty() || !mModel )
return true;
QModelIndex sourceIndex = mModel->index( sourceRow, 0, sourceParent );
return filterAcceptsItem( sourceIndex ) || filterAcceptsAncestor( sourceIndex ) || filterAcceptsDescendant( sourceIndex );
}
bool QgsBrowserTreeFilterProxyModel::filterAcceptsAncestor( const QModelIndex &sourceIndex ) const
{
if ( !mModel )
return true;
QModelIndex sourceParentIndex = mModel->parent( sourceIndex );
if ( !sourceParentIndex.isValid() )
return false;
if ( filterAcceptsItem( sourceParentIndex ) )
return true;
return filterAcceptsAncestor( sourceParentIndex );
}
bool QgsBrowserTreeFilterProxyModel::filterAcceptsDescendant( const QModelIndex &sourceIndex ) const
{
if ( !mModel )
return true;
for ( int i = 0; i < mModel->rowCount( sourceIndex ); i++ )
{
QgsDebugMsg( QString( "i = %1" ).arg( i ) );
QModelIndex sourceChildIndex = mModel->index( i, 0, sourceIndex );
if ( filterAcceptsItem( sourceChildIndex ) )
return true;
if ( filterAcceptsDescendant( sourceChildIndex ) )
return true;
}
return false;
}
bool QgsBrowserTreeFilterProxyModel::filterAcceptsItem( const QModelIndex &sourceIndex ) const
{
if ( !mModel )
return true;
//accept item if either displayed text or comment role matches string
QString comment = mModel->data( sourceIndex, QgsBrowserModel::CommentRole ).toString();
return ( filterAcceptsString( mModel->data( sourceIndex, Qt::DisplayRole ).toString() )
|| ( !comment.isEmpty() && filterAcceptsString( comment ) ) );
}
///@endcond

View File

@ -0,0 +1,251 @@
/***************************************************************************
qgsbrowserdockwidget_p.h
Private classes for QgsBrowserDockWidget
---------------------
begin : May 2017
copyright : (C) 2017 by Alessandro Pasotti
real work done by : (C) 2011 by Martin Dobias
email : a dot pasotti at itopen dot it
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSBROWSERDOCKWIDGET_P_H
#define QGSBROWSERDOCKWIDGET_P_H
/// @cond PRIVATE
//
// W A R N I N G
// -------------
//
// This file is not part of the QGIS API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
#include <ui_qgsbrowserdockwidgetbase.h>
#include <ui_qgsbrowserlayerpropertiesbase.h>
#include <ui_qgsbrowserdirectorypropertiesbase.h>
#include <ui_qgsbrowserpropertiesdialogbase.h>
#include "qgsdataitem.h"
#include "qgsbrowsertreeview.h"
#include "qgsdockwidget.h"
#include <QSortFilterProxyModel>
class QgsBrowserModel;
class QModelIndex;
class QgsDockBrowserTreeView;
class QgsLayerItem;
class QgsDataItem;
class QgsBrowserTreeFilterProxyModel;
/**
* Hack to show wrapped text without spaces
*/
class QgsBrowserPropertiesWrapLabel : public QTextEdit
{
Q_OBJECT
public:
/**
* Constructor for QgsBrowserPropertiesWrapLabel
* \param text label text
* \param parent parent widget
*/
QgsBrowserPropertiesWrapLabel( const QString &text, QWidget *parent = nullptr );
private slots:
void adjustHeight( QSizeF size );
};
/**
* The QgsBrowserPropertiesWidget base class
*/
class QgsBrowserPropertiesWidget : public QWidget
{
Q_OBJECT
public:
/**
* Constructor for QgsBrowserPropertiesWidget
* \param parent parent widget
*/
explicit QgsBrowserPropertiesWidget( QWidget *parent = nullptr );
//! Factory method to create a new browser properties widget
static QgsBrowserPropertiesWidget *createWidget( QgsDataItem *item, QWidget *parent = nullptr );
//! Stub
virtual void setItem( QgsDataItem *item ) { Q_UNUSED( item ) }
//! Set content widget, usually item paramWidget. Takes ownership.
virtual void setWidget( QWidget *widget );
/** Sets whether the properties widget should display in condensed mode, ie, for display in a dock
* widget rather than it's own separate dialog.
* \param condensedMode set to true to enable condensed mode
* \since QGIS 2.10
*/
virtual void setCondensedMode( bool condensedMode ) { Q_UNUSED( condensedMode ); }
};
/**
* The QgsBrowserLayerProperties class
*/
class QgsBrowserLayerProperties : public QgsBrowserPropertiesWidget, private Ui::QgsBrowserLayerPropertiesBase
{
Q_OBJECT
public:
/**
* Constructor for QgsBrowserLayerProperties
* \param parent parent widget
*/
explicit QgsBrowserLayerProperties( QWidget *parent = nullptr );
//! Set item
void setItem( QgsDataItem *item ) override;
/** Sets whether the properties widget should display in condensed mode, ie, for display in a dock
* widget rather than it's own separate dialog.
* \param condensedMode set to true to enable condensed mode
* \since QGIS 2.10
*/
virtual void setCondensedMode( bool condensedMode ) override;
private:
QgsBrowserPropertiesWrapLabel *mUriLabel = nullptr;
};
/**
* The QgsBrowserDirectoryProperties class
*/
class QgsBrowserDirectoryProperties : public QgsBrowserPropertiesWidget, private Ui::QgsBrowserDirectoryPropertiesBase
{
Q_OBJECT
public:
/**
* Constructor for QgsBrowserDirectoryProperties
* \param parent parent widget
*/
explicit QgsBrowserDirectoryProperties( QWidget *parent = nullptr );
//! Create widget from the given item and add it
void setItem( QgsDataItem *item ) override;
private:
QgsDirectoryParamWidget *mDirectoryWidget = nullptr;
QgsBrowserPropertiesWrapLabel *mPathLabel = nullptr;
};
/**
* The QgsBrowserPropertiesDialog class
*/
class QgsBrowserPropertiesDialog : public QDialog, private Ui::QgsBrowserPropertiesDialogBase
{
Q_OBJECT
public:
/**
* Constructor for QgsBrowserPropertiesDialog
* \param settingsSection prefix for settings (from the object name)
* \param parent parent widget
*/
QgsBrowserPropertiesDialog( const QString &settingsSection, QWidget *parent = nullptr );
~QgsBrowserPropertiesDialog();
//! Create dialog from the given item and add it
void setItem( QgsDataItem *item );
private:
QgsBrowserPropertiesWidget *mPropertiesWidget = nullptr;
QString mSettingsSection;
};
/**
* Utility class for correct drag&drop handling.
*
* We want to allow user to drag layers to qgis window. At the same time we do not
* accept drops of the items on our view - but if we ignore the drag enter action
* then qgis application consumes the drag events and it is possible to drop the
* items on the tree view although the drop is actually managed by qgis app.
*/
class QgsDockBrowserTreeView : public QgsBrowserTreeView
{
Q_OBJECT
public:
/**
* Constructor for QgsDockBrowserTreeView
* \param parent parent widget
*/
explicit QgsDockBrowserTreeView( QWidget *parent );
//! Overrides drag enter event
void dragEnterEvent( QDragEnterEvent *e ) override;
//! Overrides drag move event
void dragMoveEvent( QDragMoveEvent *e ) override;
//! Overrides drag stop event
void dropEvent( QDropEvent *e ) override;
};
/**
* Utility class for filtering browser items
*/
class QgsBrowserTreeFilterProxyModel : public QSortFilterProxyModel
{
Q_OBJECT
public:
/**
* Constructor for QgsBrowserTreeFilterProxyModel
* @param parent parent widget
*/
explicit QgsBrowserTreeFilterProxyModel( QObject *parent );
//! Set the browser model
void setBrowserModel( QgsBrowserModel *model );
//! Set the filter syntax
void setFilterSyntax( const QString &syntax );
//! Set the filter
void setFilter( const QString &filter );
//! Set case sensitivity
void setCaseSensitive( bool caseSensitive );
//! Update filter
void updateFilter();
protected:
QgsBrowserModel *mModel = nullptr;
QString mFilter; //filter string provided
QVector<QRegExp> mREList; //list of filters, separated by "|"
QString mPatternSyntax;
Qt::CaseSensitivity mCaseSensitivity;
//! Filter accepts string
bool filterAcceptsString( const QString &value ) const;
//! It would be better to apply the filer only to expanded (visible) items, but using mapFromSource() + view here was causing strange errors
bool filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const override;
//! Returns true if at least one ancestor is accepted by filter
bool filterAcceptsAncestor( const QModelIndex &sourceIndex ) const;
//! Returns true if at least one descendant s accepted by filter
bool filterAcceptsDescendant( const QModelIndex &sourceIndex ) const;
//! Filter accepts item name
bool filterAcceptsItem( const QModelIndex &sourceIndex ) const;
};
/// @endcond
#endif // QGSBROWSERDOCKWIDGET_P_H