Skip to content
Permalink
Browse files

Allow showing additional items in QgsMapLayerComboBox

These may represent additional layers such as layers which
are not included in the map layer registry, or paths to
layers which have not yet been loaded into QGIS.
  • Loading branch information
nyalldawson committed Nov 16, 2016
1 parent ec49341 commit 9ee7873572237fbb54cc677503686af3349ed414
@@ -20,6 +20,7 @@ class QgsMapLayerModel : QAbstractItemModel
LayerIdRole, /*!< Stores the map layer ID */
LayerRole, /*!< Stores pointer to the map layer itself */
IsEmptyRole, //!< True if index corresponds to the empty (not set) value
IsAdditionalRole, //!< True if index corresponds to an additional (non map layer) item
};

/**
@@ -68,6 +69,22 @@ class QgsMapLayerModel : QAbstractItemModel
*/
bool showCrs() const;

/**
* Sets a list of additional (non map layer) items to include at the end of the model.
* These may represent additional layers such as layers which are not included in the map
* layer registry, or paths to layers which have not yet been loaded into QGIS.
* @see additionalItems()
* @note added in QGIS 3.0
*/
void setAdditionalItems( const QStringList& items );

/**
* Return the list of additional (non map layer) items included at the end of the model.
* @see setAdditionalItems()
* @note added in QGIS 3.0
*/
QStringList additionalItems() const;

/**
* @brief layersChecked returns the list of layers which are checked (or unchecked)
*/
@@ -56,6 +56,22 @@ class QgsMapLayerComboBox : QComboBox
*/
bool showCrs() const;

/**
* Sets a list of additional (non map layer) items to include at the end of the combobox.
* These may represent additional layers such as layers which are not included in the map
* layer registry, or paths to layers which have not yet been loaded into QGIS.
* @see additionalItems()
* @note added in QGIS 3.0
*/
void setAdditionalItems( const QStringList& items );

/**
* Return the list of additional (non map layer) items included at the end of the combo box.
* @see setAdditionalItems()
* @note added in QGIS 3.0
*/
QStringList additionalItems() const;

/** Returns the current layer selected in the combo box.
* @see layer
*/
@@ -108,8 +108,37 @@ QModelIndex QgsMapLayerModel::indexFromLayer( QgsMapLayer *layer ) const
return index( r, 0 );
}

void QgsMapLayerModel::setAdditionalItems( const QStringList& items )
{
if ( items == mAdditionalItems )
return;

int offset = 0;
if ( mAllowEmpty )
offset++;

offset += mLayers.count();

//remove existing
if ( !mAdditionalItems.isEmpty() )
{
beginRemoveRows( QModelIndex(), offset, offset + mAdditionalItems.count() - 1 );
mAdditionalItems.clear();
endRemoveRows();
}

//add new
beginInsertRows( QModelIndex(), offset, offset + items.count() - 1 );
mAdditionalItems = items;
endInsertRows();
}

void QgsMapLayerModel::removeLayers( const QStringList& layerIds )
{
int offset = 0;
if ( mAllowEmpty )
offset++;

Q_FOREACH ( const QString& layerId, layerIds )
{
QModelIndex startIndex = index( 0, 0 );
@@ -119,7 +148,7 @@ void QgsMapLayerModel::removeLayers( const QStringList& layerIds )
QModelIndex index = list[0];
beginRemoveRows( QModelIndex(), index.row(), index.row() );
mLayersChecked.remove( layerId );
mLayers.removeAt( index.row() );
mLayers.removeAt( index.row() - offset );
endRemoveRows();
}
}
@@ -171,7 +200,7 @@ int QgsMapLayerModel::rowCount( const QModelIndex &parent ) const
if ( parent.isValid() )
return 0;

return ( mAllowEmpty ? 1 : 0 ) + mLayers.length();
return ( mAllowEmpty ? 1 : 0 ) + mLayers.length() + mAdditionalItems.count();
}

int QgsMapLayerModel::columnCount( const QModelIndex &parent ) const
@@ -183,16 +212,20 @@ int QgsMapLayerModel::columnCount( const QModelIndex &parent ) const

QVariant QgsMapLayerModel::data( const QModelIndex &index, int role ) const
{
bool isEmpty = index.row() == 0 && mAllowEmpty;

if ( !index.isValid() )
return QVariant();

bool isEmpty = index.row() == 0 && mAllowEmpty;
int additionalIndex = index.row() - ( mAllowEmpty ? 1 : 0 ) - mLayers.count();

if ( role == Qt::DisplayRole )
{
if ( index.row() == 0 && mAllowEmpty )
return QVariant();

if ( additionalIndex >= 0 )
return mAdditionalItems.at( additionalIndex );

QgsMapLayer* layer = static_cast<QgsMapLayer*>( index.internalPointer() );
if ( !layer )
return QVariant();
@@ -209,7 +242,7 @@ QVariant QgsMapLayerModel::data( const QModelIndex &index, int role ) const

if ( role == LayerIdRole )
{
if ( isEmpty )
if ( isEmpty || additionalIndex >= 0 )
return QVariant();

QgsMapLayer* layer = static_cast<QgsMapLayer*>( index.internalPointer() );
@@ -218,7 +251,7 @@ QVariant QgsMapLayerModel::data( const QModelIndex &index, int role ) const

if ( role == LayerRole )
{
if ( isEmpty )
if ( isEmpty || additionalIndex >= 0 )
return QVariant();

return QVariant::fromValue<QgsMapLayer*>( static_cast<QgsMapLayer*>( index.internalPointer() ) );
@@ -227,9 +260,12 @@ QVariant QgsMapLayerModel::data( const QModelIndex &index, int role ) const
if ( role == IsEmptyRole )
return isEmpty;

if ( role == IsAdditionalRole )
return additionalIndex >= 0;

if ( role == Qt::CheckStateRole && mItemCheckable )
{
if ( isEmpty )
if ( isEmpty || additionalIndex >= 0 )
return QVariant();

QgsMapLayer* layer = static_cast<QgsMapLayer*>( index.internalPointer() );
@@ -238,7 +274,7 @@ QVariant QgsMapLayerModel::data( const QModelIndex &index, int role ) const

if ( role == Qt::DecorationRole )
{
if ( isEmpty )
if ( isEmpty || additionalIndex >= 0 )
return QVariant();

QgsMapLayer* layer = static_cast<QgsMapLayer*>( index.internalPointer() );
@@ -315,9 +351,10 @@ Qt::ItemFlags QgsMapLayerModel::flags( const QModelIndex &index ) const
}

bool isEmpty = index.row() == 0 && mAllowEmpty;
int additionalIndex = index.row() - ( mAllowEmpty ? 1 : 0 ) - mLayers.count();

Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
if ( mItemCheckable && !isEmpty )
if ( mItemCheckable && !isEmpty && additionalIndex < 0 )
{
flags |= Qt::ItemIsUserCheckable;
}
@@ -328,8 +365,9 @@ Qt::ItemFlags QgsMapLayerModel::flags( const QModelIndex &index ) const
bool QgsMapLayerModel::setData( const QModelIndex &index, const QVariant &value, int role )
{
bool isEmpty = index.row() == 0 && mAllowEmpty;
int additionalIndex = index.row() - ( mAllowEmpty ? 1 : 0 ) - mLayers.count();

if ( role == Qt::CheckStateRole && !isEmpty )
if ( role == Qt::CheckStateRole && !isEmpty && additionalIndex < 0 )
{
QgsMapLayer* layer = static_cast<QgsMapLayer*>( index.internalPointer() );
mLayersChecked[layer->id()] = ( Qt::CheckState )value.toInt();
@@ -36,6 +36,7 @@ class CORE_EXPORT QgsMapLayerModel : public QAbstractItemModel
Q_PROPERTY( bool allowEmptyLayer READ allowEmptyLayer WRITE setAllowEmptyLayer )
Q_PROPERTY( bool showCrs READ showCrs WRITE setShowCrs )
Q_PROPERTY( bool itemsCheckable READ itemsCheckable WRITE setItemsCheckable )
Q_PROPERTY( QStringList additionalItems READ additionalItems WRITE setAdditionalItems )

public:

@@ -45,6 +46,7 @@ class CORE_EXPORT QgsMapLayerModel : public QAbstractItemModel
LayerIdRole = Qt::UserRole + 1, //!< Stores the map layer ID
LayerRole, //!< Stores pointer to the map layer itself
IsEmptyRole, //!< True if index corresponds to the empty (not set) value
IsAdditionalRole, //!< True if index corresponds to an additional (non map layer) item
};

/**
@@ -107,6 +109,22 @@ class CORE_EXPORT QgsMapLayerModel : public QAbstractItemModel
*/
QModelIndex indexFromLayer( QgsMapLayer* layer ) const;

/**
* Sets a list of additional (non map layer) items to include at the end of the model.
* These may represent additional layers such as layers which are not included in the map
* layer registry, or paths to layers which have not yet been loaded into QGIS.
* @see additionalItems()
* @note added in QGIS 3.0
*/
void setAdditionalItems( const QStringList& items );

/**
* Return the list of additional (non map layer) items included at the end of the model.
* @see setAdditionalItems()
* @note added in QGIS 3.0
*/
QStringList additionalItems() const { return mAdditionalItems; }

protected slots:
void removeLayers( const QStringList& layerIds );
void addLayers( const QList<QgsMapLayer*>& layers );
@@ -138,6 +156,7 @@ class CORE_EXPORT QgsMapLayerModel : public QAbstractItemModel

bool mAllowEmpty;
bool mShowCrs;
QStringList mAdditionalItems;
};

#endif // QGSMAPLAYERMODEL_H
@@ -78,7 +78,8 @@ bool QgsMapLayerProxyModel::filterAcceptsRow( int source_row, const QModelIndex

QModelIndex index = sourceModel()->index( source_row, 0, source_parent );

if ( sourceModel()->data( index, QgsMapLayerModel::IsEmptyRole ).toBool() )
if ( sourceModel()->data( index, QgsMapLayerModel::IsEmptyRole ).toBool()
|| sourceModel()->data( index, QgsMapLayerModel::IsAdditionalRole ).toBool() )
return true;

QgsMapLayer* layer = static_cast<QgsMapLayer*>( index.internalPointer() );
@@ -133,6 +134,15 @@ bool QgsMapLayerProxyModel::lessThan( const QModelIndex &left, const QModelIndex
else if ( sourceModel()->data( right, QgsMapLayerModel::IsEmptyRole ).toBool() )
return false;

// additional rows are always last
bool leftAdditional = sourceModel()->data( left, QgsMapLayerModel::IsAdditionalRole ).toBool();
bool rightAdditional = sourceModel()->data( right, QgsMapLayerModel::IsAdditionalRole ).toBool();

if ( leftAdditional && !rightAdditional )
return false;
else if ( rightAdditional && !leftAdditional )
return true;

// default mode is alphabetical order
QString leftStr = sourceModel()->data( left ).toString();
QString rightStr = sourceModel()->data( right ).toString();
@@ -48,6 +48,16 @@ bool QgsMapLayerComboBox::showCrs() const
return mProxyModel->sourceLayerModel()->showCrs();
}

void QgsMapLayerComboBox::setAdditionalItems( const QStringList& items )
{
mProxyModel->sourceLayerModel()->setAdditionalItems( items );
}

QStringList QgsMapLayerComboBox::additionalItems() const
{
return mProxyModel->sourceLayerModel()->additionalItems();
}

void QgsMapLayerComboBox::setLayer( QgsMapLayer *layer )
{
if ( !layer )
@@ -83,6 +83,22 @@ class GUI_EXPORT QgsMapLayerComboBox : public QComboBox
*/
bool showCrs() const;

/**
* Sets a list of additional (non map layer) items to include at the end of the combobox.
* These may represent additional layers such as layers which are not included in the map
* layer registry, or paths to layers which have not yet been loaded into QGIS.
* @see additionalItems()
* @note added in QGIS 3.0
*/
void setAdditionalItems( const QStringList& items );

/**
* Return the list of additional (non map layer) items included at the end of the combo box.
* @see setAdditionalItems()
* @note added in QGIS 3.0
*/
QStringList additionalItems() const;

/** Returns the current layer selected in the combo box.
* @see layer
*/

0 comments on commit 9ee7873

Please sign in to comment.
You can’t perform that action at this time.