121 changes: 18 additions & 103 deletions src/app/composer/qgsatlascompositionwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
#include "qgsatlascompositionwidget.h"
#include "qgsatlascomposition.h"
#include "qgscomposition.h"
#include "qgsfieldmodel.h"
#include "qgsmaplayerregistry.h"
#include "qgsmaplayerproxymodel.h"
#include "qgsexpressionbuilderdialog.h"
#include "qgscomposermap.h"

Expand All @@ -28,28 +30,11 @@ QgsAtlasCompositionWidget::QgsAtlasCompositionWidget( QWidget* parent, QgsCompos
{
setupUi( this );

// populate the layer list
mAtlasCoverageLayerComboBox->clear();
const QMap< QString, QgsMapLayer * >& layers = QgsMapLayerRegistry::instance()->mapLayers();
int idx = 0;
for ( QMap<QString, QgsMapLayer*>::const_iterator it = layers.begin(); it != layers.end(); ++it )
{
// Only consider vector layers
if ( dynamic_cast<QgsVectorLayer*>( it.value() ) )
{
mAtlasCoverageLayerComboBox->insertItem( idx++, it.value()->name(), /* userdata */ qVariantFromValue(( void* )it.value() ) );
}
}
// update sort columns
fillSortColumns();

// Connect to addition / removal of layers
QgsMapLayerRegistry* layerRegistry = QgsMapLayerRegistry::instance();
if ( layerRegistry )
{
connect( layerRegistry, SIGNAL( layerWillBeRemoved( QString ) ), this, SLOT( onLayerRemoved( QString ) ) );
connect( layerRegistry, SIGNAL( layerWasAdded( QgsMapLayer* ) ), this, SLOT( onLayerAdded( QgsMapLayer* ) ) );
}
mAtlasCoverageLayerComboBox->setFilters( QgsMapLayerProxyModel::HasGeometry );
mAtlasSortFeatureKeyComboBox->setLayer( mAtlasCoverageLayerComboBox->currentLayer() );
connect( mAtlasCoverageLayerComboBox, SIGNAL( layerChanged( QgsMapLayer* ) ), mAtlasSortFeatureKeyComboBox, SLOT( setLayer( QgsMapLayer* ) ) );
connect( mAtlasCoverageLayerComboBox, SIGNAL( layerChanged( QgsMapLayer* ) ), this, SLOT( changeCoverageLayer( QgsMapLayer* ) ) );
connect( mAtlasSortFeatureKeyComboBox, SIGNAL( fieldChanged( QString ) ), this, SLOT( changesSortFeatureField( QString ) ) );

// Sort direction
mAtlasSortFeatureDirectionButton->setEnabled( false );
Expand Down Expand Up @@ -82,68 +67,24 @@ void QgsAtlasCompositionWidget::on_mUseAtlasCheckBox_stateChanged( int state )
}
}

void QgsAtlasCompositionWidget::onLayerRemoved( QString layerName )
{
QgsAtlasComposition* atlasMap = &mComposition->atlasComposition();
// update the atlas coverage layer combo box
for ( int i = 0; i < mAtlasCoverageLayerComboBox->count(); ++i )
{
const QgsMapLayer* layer = reinterpret_cast<const QgsMapLayer*>( mAtlasCoverageLayerComboBox->itemData( i ).value<void*>() );
if ( layer->id() == layerName )
{
mAtlasCoverageLayerComboBox->removeItem( i );
break;
}
}
if ( mAtlasCoverageLayerComboBox->count() == 0 )
{
atlasMap->setCoverageLayer( 0 );
}
}

void QgsAtlasCompositionWidget::onLayerAdded( QgsMapLayer* map )
{
QgsAtlasComposition* atlasMap = &mComposition->atlasComposition();
// update the atlas coverage layer combo box
QgsVectorLayer* vectorLayer = dynamic_cast<QgsVectorLayer*>( map );
if ( vectorLayer )
{
mAtlasCoverageLayerComboBox->addItem( map->name(), qVariantFromValue(( void* )map ) );

if ( mAtlasCoverageLayerComboBox->count() == 1 )
{
atlasMap->setCoverageLayer( vectorLayer );
updateAtlasFeatures();
}
}
}

void QgsAtlasCompositionWidget::on_mAtlasCoverageLayerComboBox_currentIndexChanged( int index )
void QgsAtlasCompositionWidget::changeCoverageLayer( QgsMapLayer *layer )
{
QgsAtlasComposition* atlasMap = &mComposition->atlasComposition();
if ( !atlasMap )
{
return;
}
if ( index == -1 )

QgsVectorLayer* vl = dynamic_cast<QgsVectorLayer*>( layer );

if ( !vl )
{
atlasMap->setCoverageLayer( 0 );

// clean up the sorting columns
mAtlasSortFeatureKeyComboBox->clear();
}
else
{
QgsVectorLayer* layer = reinterpret_cast<QgsVectorLayer*>( mAtlasCoverageLayerComboBox->itemData( index ).value<void*>() );

if ( layer )
{
atlasMap->setCoverageLayer( layer );
updateAtlasFeatures();
}

// update sorting columns
fillSortColumns();
atlasMap->setCoverageLayer( vl );
updateAtlasFeatures();
}
}

Expand Down Expand Up @@ -260,18 +201,14 @@ void QgsAtlasCompositionWidget::updateAtlasFeatures()
}
}

void QgsAtlasCompositionWidget::on_mAtlasSortFeatureKeyComboBox_currentIndexChanged( int index )
void QgsAtlasCompositionWidget::changesSortFeatureField( QString fieldName )
{
QgsAtlasComposition* atlasMap = &mComposition->atlasComposition();
if ( !atlasMap )
{
return;
}

if ( index != -1 )
{
atlasMap->setSortKeyAttributeIndex( index );
}
atlasMap->setSortKeyAttributeName( fieldName );
updateAtlasFeatures();
}

Expand Down Expand Up @@ -347,23 +284,6 @@ void QgsAtlasCompositionWidget::on_mAtlasSortFeatureDirectionButton_clicked()
updateAtlasFeatures();
}

void QgsAtlasCompositionWidget::fillSortColumns()
{
QgsAtlasComposition* atlasMap = &mComposition->atlasComposition();
if ( !atlasMap || !atlasMap->coverageLayer() )
{
return;
}

mAtlasSortFeatureKeyComboBox->clear();
// Get fields of the selected coverage layer
const QgsFields& fields = atlasMap->coverageLayer()->pendingFields();
for ( int i = 0; i < fields.count(); ++i )
{
mAtlasSortFeatureKeyComboBox->insertItem( i, fields.at( i ).name() );
}
}

void QgsAtlasCompositionWidget::updateGuiElements()
{
QgsAtlasComposition* atlasMap = &mComposition->atlasComposition();
Expand All @@ -376,17 +296,12 @@ void QgsAtlasCompositionWidget::updateGuiElements()
mUseAtlasCheckBox->setCheckState( Qt::Unchecked );
}

int idx = mAtlasCoverageLayerComboBox->findData( qVariantFromValue(( void* )atlasMap->coverageLayer() ) );
if ( idx != -1 )
{
mAtlasCoverageLayerComboBox->setCurrentIndex( idx );
}

mAtlasCoverageLayerComboBox->setLayer( atlasMap->coverageLayer() );
mAtlasSortFeatureKeyComboBox->setField( atlasMap->sortKeyAttributeName() );
mAtlasFilenamePatternEdit->setText( atlasMap->filenamePattern() );
mAtlasHideCoverageCheckBox->setCheckState( atlasMap->hideCoverage() ? Qt::Checked : Qt::Unchecked );
mAtlasSingleFileCheckBox->setCheckState( atlasMap->singleFile() ? Qt::Checked : Qt::Unchecked );
mAtlasSortFeatureCheckBox->setCheckState( atlasMap->sortFeatures() ? Qt::Checked : Qt::Unchecked );
mAtlasSortFeatureKeyComboBox->setCurrentIndex( atlasMap->sortKeyAttributeIndex() );
mAtlasSortFeatureDirectionButton->setArrowType( atlasMap->sortAscending() ? Qt::UpArrow : Qt::DownArrow );
mAtlasFeatureFilterEdit->setText( atlasMap->featureFilter() );
mAtlasFeatureFilterCheckBox->setCheckState( atlasMap->filterFeatures() ? Qt::Checked : Qt::Unchecked );
Expand Down
9 changes: 2 additions & 7 deletions src/app/composer/qgsatlascompositionwidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,25 +36,20 @@ class QgsAtlasCompositionWidget:

public slots:
void on_mUseAtlasCheckBox_stateChanged( int state );
void on_mAtlasCoverageLayerComboBox_currentIndexChanged( int index );
void changeCoverageLayer( QgsMapLayer* layer );
void on_mAtlasFilenamePatternEdit_textChanged( const QString& text );
void on_mAtlasFilenameExpressionButton_clicked();
void on_mAtlasHideCoverageCheckBox_stateChanged( int state );
void on_mAtlasSingleFileCheckBox_stateChanged( int state );

void on_mAtlasSortFeatureCheckBox_stateChanged( int state );
void on_mAtlasSortFeatureKeyComboBox_currentIndexChanged( int index );
void changesSortFeatureField( QString fieldName );
void on_mAtlasSortFeatureDirectionButton_clicked();
void on_mAtlasFeatureFilterEdit_editingFinished();
void on_mAtlasFeatureFilterButton_clicked();
void on_mAtlasFeatureFilterCheckBox_stateChanged( int state );

// extract fields from the current coverage layer and populate the corresponding combo box
void fillSortColumns();
private slots:
void onLayerRemoved( QString );
void onLayerAdded( QgsMapLayer* );

void updateGuiElements();

void updateAtlasFeatures();
Expand Down
22 changes: 2 additions & 20 deletions src/app/qgisapp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3758,29 +3758,11 @@ void QgisApp::fileSaveAs()

void QgisApp::dxfExport()
{
QgsLegend* mapLegend = legend();
if ( !mapLegend )
{
return;
}

QgsDxfExportDialog d( mapLegend->layers() );
QgsDxfExportDialog d;
if ( d.exec() == QDialog::Accepted )
{
QgsDxfExport dxfExport;

QList<QgsMapLayer*> layerList;
QList<QString> layerIdList = d.layers();
QList<QString>::const_iterator layerIt = layerIdList.constBegin();
for ( ; layerIt != layerIdList.constEnd(); ++layerIt )
{
QgsMapLayer* l = QgsMapLayerRegistry::instance()->mapLayer( *layerIt );
if ( l )
{
layerList.append( l );
}
}

QList<QgsMapLayer*> layerList = d.layers();
dxfExport.addLayers( layerList );
dxfExport.setSymbologyScaleDenominator( d.symbologyScale() );
dxfExport.setSymbologyExport( d.symbologyMode() );
Expand Down
50 changes: 12 additions & 38 deletions src/app/qgsdxfexportdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,41 +17,28 @@

#include "qgsdxfexportdialog.h"
#include "qgsmaplayer.h"
#include "qgsmaplayermodel.h"
#include "qgsmaplayerregistry.h"
#include "qgsvectorlayer.h"
#include "qgis.h"
#include <QFileDialog>
#include <QPushButton>
#include <QSettings>

QgsDxfExportDialog::QgsDxfExportDialog( const QList<QgsMapLayer*>& layerKeys, QWidget* parent, Qt::WindowFlags f ): QDialog( parent, f )
QgsDxfExportDialog::QgsDxfExportDialog( QWidget* parent, Qt::WindowFlags f ): QDialog( parent, f )
{
setupUi( this );

mModel = new QgsMapLayerProxyModel( this );
mModel->sourceLayerModel()->setItemsCheckable( true );
mModel->setFilters( QgsMapLayerProxyModel::HasGeometry );
mLayersListView->setModel( mModel );

connect( mFileLineEdit, SIGNAL( textChanged( const QString& ) ), this, SLOT( setOkEnabled() ) );
connect( this, SIGNAL( accepted() ), this, SLOT( saveSettings() ) );
connect( mSelectAllButton, SIGNAL( clicked() ), this, SLOT( selectAll() ) );
connect( mUnSelectAllButton, SIGNAL( clicked() ), this, SLOT( unSelectAll() ) );

QList<QgsMapLayer*>::const_iterator layerIt = layerKeys.constBegin();
for ( ; layerIt != layerKeys.constEnd(); ++layerIt )
{
QgsMapLayer* layer = *layerIt;
if ( layer )
{
if ( layer->type() == QgsMapLayer::VectorLayer )
{
QgsVectorLayer* vl = dynamic_cast<QgsVectorLayer*>( layer );
if ( !vl->hasGeometryType() )
continue;
QListWidgetItem* layerItem = new QListWidgetItem( layer->name() );
layerItem->setData( Qt::UserRole, layer->id() );
layerItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsUserCheckable );
layerItem->setCheckState( Qt::Checked );
mLayersListWidget->addItem( layerItem );
}
}
}

//last dxf symbology mode
QSettings s;
mSymbologyModeComboBox->setCurrentIndex( s.value( "qgis/lastDxfSymbologyMode", "2" ).toInt() );
Expand All @@ -64,34 +51,21 @@ QgsDxfExportDialog::QgsDxfExportDialog( const QList<QgsMapLayer*>& layerKeys, QW

QgsDxfExportDialog::~QgsDxfExportDialog()
{

}

void QgsDxfExportDialog::selectAll()
{
for ( int r = 0; r < mLayersListWidget->count(); r++ )
mLayersListWidget->item( r )->setCheckState( Qt::Checked );
mModel->sourceLayerModel()->checkAll( Qt::Checked );
}

void QgsDxfExportDialog::unSelectAll()
{
for ( int r = 0; r < mLayersListWidget->count(); r++ )
mLayersListWidget->item( r )->setCheckState( Qt::Unchecked );
mModel->sourceLayerModel()->checkAll( Qt::Unchecked );
}

QList<QString> QgsDxfExportDialog::layers() const
QList<QgsMapLayer*> QgsDxfExportDialog::layers() const
{
QList<QString> layerKeyList;
int nItems = mLayersListWidget->count();
for ( int i = 0; i < nItems; ++i )
{
QListWidgetItem* currentItem = mLayersListWidget->item( i );
if ( currentItem->checkState() == Qt::Checked )
{
layerKeyList.prepend( currentItem->data( Qt::UserRole ).toString() );
}
}
return layerKeyList;
return mModel->sourceLayerModel()->layersChecked();
}

double QgsDxfExportDialog::symbologyScale() const
Expand Down
8 changes: 6 additions & 2 deletions src/app/qgsdxfexportdialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,16 @@

#include "ui_qgsdxfexportdialogbase.h"
#include "qgsdxfexport.h"
#include "qgsmaplayerproxymodel.h"

class QgsDxfExportDialog: public QDialog, private Ui::QgsDxfExportDialogBase
{
Q_OBJECT
public:
QgsDxfExportDialog( const QList<QgsMapLayer*>& layerKeys, QWidget * parent = 0, Qt::WindowFlags f = 0 );
QgsDxfExportDialog( QWidget * parent = 0, Qt::WindowFlags f = 0 );
~QgsDxfExportDialog();

QList<QString> layers() const;
QList<QgsMapLayer *> layers() const;
double symbologyScale() const;
QgsDxfExport::SymbologyExport symbologyMode() const;
QString saveFile() const;
Expand All @@ -43,6 +44,9 @@ class QgsDxfExportDialog: public QDialog, private Ui::QgsDxfExportDialogBase
void on_mFileSelectionButton_clicked();
void setOkEnabled();
void saveSettings();

private:
QgsMapLayerProxyModel* mModel;
};

#endif // QGSDXFEXPORTDIALOG_H
49 changes: 43 additions & 6 deletions src/core/composer/qgsatlascomposition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ void QgsAtlasComposition::setCoverageLayer( QgsVectorLayer* layer )
QgsExpression::setSpecialColumn( "$numfeatures", QVariant(( int )mFeatureIds.size() ) );

// Grab the first feature so that user can use it to test the style in rules.
if( layer )
if ( layer )
{
QgsFeature fet;
layer->getFeatures().nextFeature( fet );
Expand Down Expand Up @@ -155,6 +155,29 @@ void QgsAtlasComposition::setMargin( float margin )
map->setAtlasMargin(( double ) margin );
}

int QgsAtlasComposition::sortKeyAttributeIndex() const
{
if ( !mCoverageLayer )
{
return -1;
}
return mCoverageLayer->fieldNameIndex( mSortKeyAttributeName );
}

void QgsAtlasComposition::setSortKeyAttributeIndex( int idx )
{
if ( mCoverageLayer )
{
const QgsFields fields = mCoverageLayer->pendingFields();
if ( idx >= 0 && idx < fields.count() )
{
mSortKeyAttributeName = fields[idx].name();
return;
}
}
mSortKeyAttributeName = "";
}

//
// Private class only used for the sorting of features
class FieldSorter
Expand Down Expand Up @@ -215,6 +238,7 @@ int QgsAtlasComposition::updateFeatures()
QgsFeature feat;
mFeatureIds.clear();
mFeatureKeys.clear();
int sortIdx = mCoverageLayer->fieldNameIndex( mSortKeyAttributeName );
while ( fit.nextFeature( feat ) )
{
if ( mFilterFeatures && !mFeatureFilter.isEmpty() )
Expand All @@ -233,14 +257,14 @@ int QgsAtlasComposition::updateFeatures()
}
mFeatureIds.push_back( feat.id() );

if ( mSortFeatures )
if ( mSortFeatures && sortIdx != -1 )
{
mFeatureKeys.insert( feat.id(), feat.attributes()[ mSortKeyAttributeIdx ] );
mFeatureKeys.insert( feat.id(), feat.attributes()[ sortIdx ] );
}
}

// sort features, if asked for
if ( mSortFeatures )
if ( mFeatureKeys.count() )
{
FieldSorter sorter( mFeatureKeys, mSortAscending );
qSort( mFeatureIds.begin(), mFeatureIds.end(), sorter );
Expand Down Expand Up @@ -567,7 +591,7 @@ void QgsAtlasComposition::writeXML( QDomElement& elem, QDomDocument& doc ) const
atlasElem.setAttribute( "sortFeatures", mSortFeatures ? "true" : "false" );
if ( mSortFeatures )
{
atlasElem.setAttribute( "sortKey", QString::number( mSortKeyAttributeIdx ) );
atlasElem.setAttribute( "sortKey", mSortKeyAttributeName );
atlasElem.setAttribute( "sortAscending", mSortAscending ? "true" : "false" );
}
atlasElem.setAttribute( "filterFeatures", mFilterFeatures ? "true" : "false" );
Expand Down Expand Up @@ -637,7 +661,20 @@ void QgsAtlasComposition::readXML( const QDomElement& atlasElem, const QDomDocum
mSortFeatures = atlasElem.attribute( "sortFeatures", "false" ) == "true" ? true : false;
if ( mSortFeatures )
{
mSortKeyAttributeIdx = atlasElem.attribute( "sortKey", "0" ).toInt();
mSortKeyAttributeName = atlasElem.attribute( "sortKey", "" );
// since 2.3, the field name is saved instead of the field index
// following code keeps compatibility with version 2.2 projects
// to be removed in QGIS 3.0
bool isIndex;
int idx = mSortKeyAttributeName.toInt( &isIndex );
if ( isIndex && mCoverageLayer )
{
const QgsFields fields = mCoverageLayer->pendingFields();
if ( idx >= 0 && idx < fields.count() )
{
mSortKeyAttributeName = fields[idx].name();
}
}
mSortAscending = atlasElem.attribute( "sortAscending", "true" ) == "true" ? true : false;
}
mFilterFeatures = atlasElem.attribute( "filterFeatures", "false" ) == "true" ? true : false;
Expand Down
9 changes: 6 additions & 3 deletions src/core/composer/qgsatlascomposition.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,11 @@ class CORE_EXPORT QgsAtlasComposition : public QObject
QString featureFilter() const { return mFeatureFilter; }
void setFeatureFilter( const QString& expression ) { mFeatureFilter = expression; }

int sortKeyAttributeIndex() const { return mSortKeyAttributeIdx; }
void setSortKeyAttributeIndex( int idx ) { mSortKeyAttributeIdx = idx; }
QString sortKeyAttributeName() const { return mSortKeyAttributeName; }
void setSortKeyAttributeName( QString fieldName ) { mSortKeyAttributeName = fieldName; }

Q_DECL_DEPRECATED int sortKeyAttributeIndex() const;
Q_DECL_DEPRECATED void setSortKeyAttributeIndex( int idx );

/** Begins the rendering. Returns true if successful, false if no matching atlas
features found.*/
Expand Down Expand Up @@ -188,7 +191,7 @@ class CORE_EXPORT QgsAtlasComposition : public QObject
// value of field that is used for ordering of features
SorterKeys mFeatureKeys;
// key (attribute index) used for ordering
int mSortKeyAttributeIdx;
QString mSortKeyAttributeName;

// feature filtering
bool mFilterFeatures;
Expand Down
15 changes: 15 additions & 0 deletions src/gui/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ qgsexpressionhighlighter.cpp
qgsexpressionselectiondialog.cpp
qgsextentgroupbox.cpp
qgsfeatureselectiondlg.cpp
qgsfieldcombobox.cpp
qgsfieldmodel.cpp
qgsfieldvalidator.cpp
qgsfiledropedit.cpp
qgsfilterlineedit.cpp
Expand All @@ -103,6 +105,9 @@ qgsmapcanvasitem.cpp
qgsmapcanvasmap.cpp
qgsmapcanvassnapper.cpp
qgsmaplayeractionregistry.cpp
qgsmaplayercombobox.cpp
qgsmaplayermodel.cpp
qgsmaplayerproxymodel.cpp
qgsmapoverviewcanvas.cpp
qgsmaptip.cpp
qgsmaptool.cpp
Expand Down Expand Up @@ -227,6 +232,8 @@ qgsexpressionhighlighter.h
qgsexpressionselectiondialog.h
qgsextentgroupbox.h
qgsfeatureselectiondlg.h
qgsfieldcombobox.h
qgsfieldmodel.h
qgsfieldvalidator.h
qgsfilterlineedit.h
qgsformannotationitem.h
Expand All @@ -238,6 +245,9 @@ qgsludialog.h
qgsmanageconnectionsdialog.h
qgsmapcanvas.h
qgsmaplayeractionregistry.h
qgsmaplayercombobox.h
qgsmaplayermodel.h
qgsmaplayerproxymodel.h
qgsmapoverviewcanvas.h
qgsmaptool.h
qgsmaptoolemitpoint.h
Expand Down Expand Up @@ -292,6 +302,8 @@ qgsexpressionbuilderwidget.h
qgsexpressionhighlighter.h
qgsexpressionselectiondialog.h
qgsfeatureselectiondlg.h
qgsfieldcombobox.h
qgsfieldmodel.h
qgsfieldvalidator.h
qgsfiledropedit.h
qgsfilterlineedit.h
Expand All @@ -301,6 +313,9 @@ qgsmapcanvas.h
qgsmapcanvasitem.h
qgsmapcanvasmap.h
qgsmapcanvassnapper.h
qgsmaplayercombobox.h
qgsmaplayermodel.h
qgsmaplayerproxymodel.h
qgsmapoverviewcanvas.h
qgsmaptip.h
qgsmaptool.h
Expand Down
66 changes: 66 additions & 0 deletions src/gui/qgsfieldcombobox.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/***************************************************************************
qgsfieldcombobox.cpp
--------------------------------------
Date : 01.04.2014
Copyright : (C) 2014 Denis Rouzaud
Email : denis.rouzaud@gmail.com
***************************************************************************
* *
* 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 "qgsfieldcombobox.h"
#include "qgsfieldmodel.h"
#include "qgsmaplayer.h"

QgsFieldComboBox::QgsFieldComboBox( QWidget *parent ) :
QComboBox( parent )
{
mFieldModel = new QgsFieldModel( this );
setModel( mFieldModel );

connect( this, SIGNAL( currentIndexChanged( int ) ), this, SLOT( indexChanged( int ) ) );
}

void QgsFieldComboBox::setLayer( QgsMapLayer *layer )
{
mFieldModel->setLayer( layer );
}

void QgsFieldComboBox::setField( QString fieldName )
{
QModelIndex idx = mFieldModel->indexFromName( fieldName );
if ( idx.isValid() )
{
setCurrentIndex( idx.row() );
}
else
{
setCurrentIndex( -1 );
}
}

QString QgsFieldComboBox::currentField()
{
int i = currentIndex();

const QModelIndex index = mFieldModel->index( i, 0 );
if ( !index.isValid() )
{
return "";
}

QString name = mFieldModel->data( index, QgsFieldModel::FieldNameRole ).toString();
return name;
}

void QgsFieldComboBox::indexChanged( int i )
{
Q_UNUSED( i );
QString name = currentField();
emit fieldChanged( name );
}
67 changes: 67 additions & 0 deletions src/gui/qgsfieldcombobox.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/***************************************************************************
qgsfieldcombobox.h
--------------------------------------
Date : 01.04.2014
Copyright : (C) 2014 Denis Rouzaud
Email : denis.rouzaud@gmail.com
***************************************************************************
* *
* 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 QGSFIELDCOMBOBOX_H
#define QGSFIELDCOMBOBOX_H

#include <QComboBox>

class QgsFieldModel;
class QgsMapLayer;

/**
* @brief The QgsFieldComboBox is a combo box which displays the list of fields of a given layer.
* @note added in 2.3
*/
class GUI_EXPORT QgsFieldComboBox : public QComboBox
{
Q_OBJECT
public:
/**
* @brief QgsFieldComboBox creates a combo box to display the fields of a layer.
* The layer can be either manually given or dynamically set by connecting the signal QgsMapLayerComboBox::layerChanged to the slot setLayer.
*/
explicit QgsFieldComboBox( QWidget *parent = 0 );

/**
* @brief currentField returns the currently selected field
*/
QString currentField();

signals:
/**
* @brief fieldChanged the signal is emitted when the currently selected field changes
*/
void fieldChanged( QString fieldName );

public slots:
/**
* @brief setLayer sets the layer of which the fields are listed
*/
void setLayer( QgsMapLayer* layer );
/**
* @brief setField sets the currently selected field
*/
void setField( QString fieldName );

protected slots:
void indexChanged( int i );

private:
QgsFieldModel* mFieldModel;

};

#endif // QGSFIELDCOMBOBOX_H
137 changes: 137 additions & 0 deletions src/gui/qgsfieldmodel.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/***************************************************************************
qgsfieldmodel.cpp
--------------------------------------
Date : 01.04.2014
Copyright : (C) 2014 Denis Rouzaud
Email : denis.rouzaud@gmail.com
***************************************************************************
* *
* 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 "qgsfieldmodel.h"
#include "qgsmaplayermodel.h"
#include "qgsmaplayerproxymodel.h"
#include "qgslogger.h"


const int QgsFieldModel::FieldIndexRole = Qt::UserRole + 1;
const int QgsFieldModel::FieldNameRole = Qt::UserRole + 2;

QgsFieldModel::QgsFieldModel( QObject *parent )
: QAbstractItemModel( parent )
, mLayer( NULL )
{
}

QModelIndex QgsFieldModel::indexFromName( QString fieldName )
{
int r = mFields.indexFromName( fieldName );
return index( r, 0 );
}


void QgsFieldModel::setLayer( QgsMapLayer *layer )
{
if ( mLayer )
{
disconnect( mLayer, SIGNAL( updatedFields() ), this, SLOT( updateFields() ) );
disconnect( mLayer, SIGNAL( layerDeleted() ), this, SLOT( layerDeleted() ) );
}
QgsVectorLayer* vl = dynamic_cast<QgsVectorLayer*>( layer );
if ( vl )
{
mLayer = vl;
connect( mLayer, SIGNAL( updatedFields() ), this, SLOT( updateFields() ) );
connect( mLayer, SIGNAL( layerDeleted() ), this, SLOT( layerDeleted() ) );
}
else
{
mLayer = 0;
}
updateFields();
}

void QgsFieldModel::layerDeleted()
{
mLayer = 0;
updateFields();
}

void QgsFieldModel::updateFields()
{
beginResetModel();
if ( mLayer )
mFields = mLayer->pendingFields();
else
mFields = QgsFields();
endResetModel();
}

QModelIndex QgsFieldModel::index( int row, int column, const QModelIndex &parent ) const
{
Q_UNUSED( parent );
if ( row < 0 || row >= mFields.count() )
return QModelIndex();

return createIndex( row, column, row );
}

QModelIndex QgsFieldModel::parent( const QModelIndex &child ) const
{
Q_UNUSED( child );
return QModelIndex();
}

int QgsFieldModel::rowCount( const QModelIndex &parent ) const
{
Q_UNUSED( parent );
return mFields.count();
}

int QgsFieldModel::columnCount( const QModelIndex &parent ) const
{
Q_UNUSED( parent );
return 1;
}

QVariant QgsFieldModel::data( const QModelIndex &index, int role ) const
{
if ( !index.isValid() )
return QVariant();

if ( !mLayer )
return QVariant();

if ( role == FieldNameRole )
{
QgsField field = mFields[index.internalId()];
return field.name();
}

if ( role == FieldIndexRole )
{
return index.row();
}

if ( role == Qt::DisplayRole )
{
QgsField field = mFields[index.internalId()];
const QMap< QString, QString > aliases = mLayer->attributeAliases();
QString alias = aliases.value( field.name(), field.name() );
return alias;
}

if ( role == Qt::UserRole )
{
QgsField field = mFields[index.internalId()];
return field.name();
}

return QVariant();
}

72 changes: 72 additions & 0 deletions src/gui/qgsfieldmodel.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/***************************************************************************
qgsfieldmodel.h
--------------------------------------
Date : 01.04.2014
Copyright : (C) 2014 Denis Rouzaud
Email : denis.rouzaud@gmail.com
***************************************************************************
* *
* 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 QGSFIELDMODEL_H
#define QGSFIELDMODEL_H

#include <QAbstractItemModel>
#include <QItemSelectionModel>
#include <QComboBox>

#include "qgsvectorlayer.h"

/**
* @brief The QgsFieldModel class is a model to display the list of fields of a layer in widgets.
* It can be associated with a QgsMapLayerModel to dynamically display a layer and its fields.
* @note added in 2.3
*/

class GUI_EXPORT QgsFieldModel : public QAbstractItemModel
{
Q_OBJECT
public:
static const int FieldNameRole, FieldIndexRole;

/**
* @brief QgsFieldModel creates a model to display the fields of a given layer
*/
explicit QgsFieldModel( QObject *parent = 0 );

/**
* @brief indexFromName returns the index corresponding to a given fieldName
*/
QModelIndex indexFromName( QString fieldName );

public slots:
/**
* @brief setLayer sets the layer of whch fields are displayed
*/
void setLayer( QgsMapLayer *layer );

protected slots:
void updateFields();
void layerDeleted();

protected:
QgsFields mFields;
QgsVectorLayer* mLayer;

// QAbstractItemModel interface
public:
QModelIndex index( int row, int column, const QModelIndex &parent = QModelIndex() ) const;
QModelIndex parent( const QModelIndex &child ) const;
int rowCount( const QModelIndex &parent ) const;
int columnCount( const QModelIndex &parent ) const;
QVariant data( const QModelIndex &index, int role ) const;


};

#endif // QGSFIELDMODEL_H
79 changes: 79 additions & 0 deletions src/gui/qgsmaplayercombobox.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/***************************************************************************
qgsmaplayercombobox.cpp
--------------------------------------
Date : 01.04.2014
Copyright : (C) 2014 Denis Rouzaud
Email : denis.rouzaud@gmail.com
***************************************************************************
* *
* 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 "qgsmaplayercombobox.h"
#include "qgsmaplayermodel.h"

QgsMapLayerComboBox::QgsMapLayerComboBox( QWidget *parent ) :
QComboBox( parent )
{
mProxyModel = new QgsMapLayerProxyModel( this );
setModel( mProxyModel );

connect( this, SIGNAL( currentIndexChanged( int ) ), this, SLOT( indexChanged( int ) ) );
}

void QgsMapLayerComboBox::setFilters( QgsMapLayerProxyModel::Filters filters )
{
mProxyModel->setFilters( filters );
}

void QgsMapLayerComboBox::setLayer( QgsMapLayer *layer )
{
QModelIndex idx = mProxyModel->sourceLayerModel()->indexFromLayer( layer );
if ( idx.isValid() )
{
QModelIndex proxyIdx = mProxyModel->mapFromSource( idx );
if ( proxyIdx.isValid() )
{
setCurrentIndex( proxyIdx.row() );
return;
}
}
setCurrentIndex( -1 );
}

QgsMapLayer* QgsMapLayerComboBox::currentLayer()
{
int i = currentIndex();

const QModelIndex proxyIndex = mProxyModel->index( i, 0 );
if ( !proxyIndex.isValid() )
{
return 0;
}

const QModelIndex index = mProxyModel->mapToSource( proxyIndex );
if ( !index.isValid() )
{
return 0;
}

QgsMapLayer* layer = static_cast<QgsMapLayer*>( index.internalPointer() );
if ( layer )
{
return layer;
}
return 0;
}

void QgsMapLayerComboBox::indexChanged( int i )
{
Q_UNUSED( i );
QgsMapLayer* layer = currentLayer();
emit layerChanged( layer );
}


70 changes: 70 additions & 0 deletions src/gui/qgsmaplayercombobox.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/***************************************************************************
qgsmaplayercombobox.h
--------------------------------------
Date : 01.04.2014
Copyright : (C) 2014 Denis Rouzaud
Email : denis.rouzaud@gmail.com
***************************************************************************
* *
* 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 QGSMAPLAYERCOMBOBOX_H
#define QGSMAPLAYERCOMBOBOX_H

#include <QComboBox>

#include "qgsmaplayerproxymodel.h"

class QgsMapLayer;
class QgsVectorLayer;

/**
* @brief The QgsMapLayerComboBox class is a combo box which displays the list of layers
* @note added in 2.3
*/
class GUI_EXPORT QgsMapLayerComboBox : public QComboBox
{
Q_OBJECT
public:
/**
* @brief QgsMapLayerComboBox creates a combo box to dislpay the list of layers (currently in the registry).
* The layers can be filtered and/or ordered.
*/
explicit QgsMapLayerComboBox( QWidget *parent = 0 );

/**
* @brief setFilters allows fitering according to layer type and/or geometry type.
*/
void setFilters( QgsMapLayerProxyModel::Filters filters );

/**
* @brief currentLayer returns the current layer selected in the combo box
*/
QgsMapLayer* currentLayer();

public slots:
/**
* @brief setLayer set the current layer selected in the combo
*/
void setLayer( QgsMapLayer* layer );

signals:
/**
* @brief layerChanged this signal is emitted whenever the currently selected layer changes
*/
void layerChanged( QgsMapLayer* layer );

protected slots:
void indexChanged( int i );

private:
QgsMapLayerProxyModel* mProxyModel;

};

#endif // QGSMAPLAYERCOMBOBOX_H
238 changes: 238 additions & 0 deletions src/gui/qgsmaplayermodel.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
/***************************************************************************
qgsmaplayermodel.cpp
--------------------------------------
Date : 01.04.2014
Copyright : (C) 2014 Denis Rouzaud
Email : denis.rouzaud@gmail.com
***************************************************************************
* *
* 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 <QIcon>

#include "qgsmaplayermodel.h"
#include "qgsmaplayerregistry.h"
#include "qgsapplication.h"
#include "qgsvectorlayer.h"


const int QgsMapLayerModel::LayerIdRole = Qt::UserRole + 1;

QgsMapLayerModel::QgsMapLayerModel( QList<QgsMapLayer *> layers, QObject *parent )
: QAbstractItemModel( parent )
, mLayersChecked( QMap<QString, Qt::CheckState>() )
, mItemCheckable( false )
{
connect( QgsMapLayerRegistry::instance(), SIGNAL( removeLayers( QStringList ) ), this, SLOT( removeLayers( QStringList ) ) );
addLayers( layers );
}

QgsMapLayerModel::QgsMapLayerModel( QObject *parent )
: QAbstractItemModel( parent )
, mLayersChecked( QMap<QString, Qt::CheckState>() )
, mItemCheckable( false )
{
connect( QgsMapLayerRegistry::instance(), SIGNAL( layersAdded( QList<QgsMapLayer*> ) ), this, SLOT( addLayers( QList<QgsMapLayer*> ) ) );
connect( QgsMapLayerRegistry::instance(), SIGNAL( layersRemoved( QStringList ) ), this, SLOT( removeLayers( QStringList ) ) );
addLayers( QgsMapLayerRegistry::instance()->mapLayers().values() );
}

void QgsMapLayerModel::setItemsCheckable( bool checkable )
{
mItemCheckable = checkable;
}

void QgsMapLayerModel::checkAll( Qt::CheckState checkState )
{
foreach ( const QString key, mLayersChecked.keys() )
{
mLayersChecked[key] = checkState;
}
emit dataChanged( index( 0, 0 ), index( mLayers.length() - 1, 0 ) );
}

QList<QgsMapLayer *> QgsMapLayerModel::layersChecked( Qt::CheckState checkState )
{
QList<QgsMapLayer *> layers;
foreach ( QgsMapLayer* layer, mLayers )
{
if ( mLayersChecked[layer->id()] == checkState )
{
layers.append( layer );
}
}
return layers;
}

QModelIndex QgsMapLayerModel::indexFromLayer( QgsMapLayer *layer )
{
int r = mLayers.indexOf( layer );
return index( r, 0 );
}

void QgsMapLayerModel::removeLayers( const QStringList layerIds )
{
foreach ( const QString layerId, layerIds )
{
QModelIndex startIndex = index( 0, 0 );
QModelIndexList list = match( startIndex, LayerIdRole, layerId, 1 );
if ( list.count() )
{
QModelIndex index = list[0];
beginRemoveRows( QModelIndex(), index.row(), index.row() );
mLayersChecked.remove( layerId );
mLayers.removeAt( index.row() );
endRemoveRows();
}
}
}

void QgsMapLayerModel::addLayers( QList<QgsMapLayer *> layers )
{
beginInsertRows( QModelIndex(), mLayers.count(), mLayers.count() + layers.count() - 1 );
foreach ( QgsMapLayer* layer, layers )
{
mLayers.append( layer );
mLayersChecked.insert( layer->id(), Qt::Unchecked );
}
endInsertRows();
}

QModelIndex QgsMapLayerModel::index( int row, int column, const QModelIndex &parent ) const
{
Q_UNUSED( parent );
if ( row < 0 || row >= mLayers.length() )
return QModelIndex();

return createIndex( row, column, mLayers[row] );
}

QModelIndex QgsMapLayerModel::parent( const QModelIndex &child ) const
{
Q_UNUSED( child );
return QModelIndex();
}

int QgsMapLayerModel::rowCount( const QModelIndex &parent ) const
{
Q_UNUSED( parent );

return mLayers.length();
}

int QgsMapLayerModel::columnCount( const QModelIndex &parent ) const
{
Q_UNUSED( parent );
return 1;
}

QVariant QgsMapLayerModel::data( const QModelIndex &index, int role ) const
{
if ( !index.isValid() || !index.internalPointer() )
return QVariant();

if ( role == Qt::DisplayRole )
{
QgsMapLayer* layer = static_cast<QgsMapLayer*>( index.internalPointer() );
return layer->name();
}

if ( role == LayerIdRole )
{
QgsMapLayer* layer = static_cast<QgsMapLayer*>( index.internalPointer() );
return layer->id();
}

if ( role == Qt::CheckStateRole && mItemCheckable )
{
QgsMapLayer* layer = static_cast<QgsMapLayer*>( index.internalPointer() );
return mLayersChecked[layer->id()];
}

if ( role == Qt::DecorationRole )
{
QgsMapLayer* layer = static_cast<QgsMapLayer*>( index.internalPointer() );
QgsMapLayer::LayerType type = layer->type();
if ( role == Qt::DecorationRole )
{
switch ( type )
{
case QgsMapLayer::RasterLayer:
{
return QgsApplication::getThemeIcon( "/mIconRasterLayer.svg" );
}

case QgsMapLayer::VectorLayer:
{
QgsVectorLayer* vl = dynamic_cast<QgsVectorLayer*>( layer );
if ( !vl )
{
return QIcon();
}
QGis::GeometryType geomType = vl->geometryType();
switch ( geomType )
{
case QGis::Point:
{
return QgsApplication::getThemeIcon( "/mIconPointLayer.svg" );
}
case QGis::Polygon :
{
return QgsApplication::getThemeIcon( "/mIconPolygonLayer.svg" );
}
case QGis::Line :
{
return QgsApplication::getThemeIcon( "/mIconLineLayer.svg" );
}
case QGis::NoGeometry :
{
return QgsApplication::getThemeIcon( "/mIconTableLayer.png" );
}
default:
{
return QIcon();
}
}
}
default:
{
return QIcon();
}
}
}
}

return QVariant();
}


Qt::ItemFlags QgsMapLayerModel::flags( const QModelIndex &index ) const
{
Q_UNUSED( index );

Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
if ( mItemCheckable )
{
flags |= Qt::ItemIsUserCheckable;
}
return flags;
}


bool QgsMapLayerModel::setData( const QModelIndex &index, const QVariant &value, int role )
{
if ( role == Qt::CheckStateRole )
{
QgsMapLayer* layer = static_cast<QgsMapLayer*>( index.internalPointer() );
mLayersChecked[layer->id()] = ( Qt::CheckState )value.toInt();
emit dataChanged( index, index );
return true;
}

return false;
}
88 changes: 88 additions & 0 deletions src/gui/qgsmaplayermodel.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/***************************************************************************
qgsmaplayermodel.h
--------------------------------------
Date : 01.04.2014
Copyright : (C) 2014 Denis Rouzaud
Email : denis.rouzaud@gmail.com
***************************************************************************
* *
* 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 QGSMAPLAYERMODEL_H
#define QGSMAPLAYERMODEL_H

#include <QAbstractItemModel>
#include <QSortFilterProxyModel>
#include <QStringList>

class QgsMapLayer;


/**
* @brief The QgsMapLayerModel class is a model to display layers in widgets.
* @see QgsMapLayerProxyModel to sort and/filter the layers
* @see QgsFieldModel to combine in with a field selector.
* @note added in 2.3
*/
class GUI_EXPORT QgsMapLayerModel : public QAbstractItemModel
{
Q_OBJECT
public:
static const int LayerIdRole;

/**
* @brief QgsMapLayerModel creates a model to display layers in widgets.
*/
explicit QgsMapLayerModel( QObject *parent = 0 );
/**
* @brief QgsMapLayerModel creates a model to display a specific list of layers in a widget.
*/
explicit QgsMapLayerModel( QList<QgsMapLayer*> layers, QObject *parent = 0 );

/**
* @brief setItemsCheckable defines if layers should be selectable in the widget
*/
void setItemsCheckable( bool checkable );
/**
* @brief checkAll changes the checkstate for all the layers
*/
void checkAll( Qt::CheckState checkState );
/**
* @brief layersChecked returns the list of layers which are checked (or unchecked)
*/
QList<QgsMapLayer*> layersChecked( Qt::CheckState checkState = Qt::Checked );
//! returns if the items can be checked or not
bool itemsCheckable() {return mItemCheckable;}

/**
* @brief indexFromLayer returns the model index for a given layer
*/
QModelIndex indexFromLayer( QgsMapLayer* layer );


protected slots:
void removeLayers( const QStringList layerIds );
void addLayers( QList<QgsMapLayer*> layers );

protected:
QList<QgsMapLayer*> mLayers;
QMap<QString, Qt::CheckState> mLayersChecked;
bool mItemCheckable;

// QAbstractItemModel interface
public:
QModelIndex index( int row, int column, const QModelIndex &parent = QModelIndex() ) const;
QModelIndex parent( const QModelIndex &child ) const;
int rowCount( const QModelIndex &parent ) const;
int columnCount( const QModelIndex &parent ) const;
QVariant data( const QModelIndex &index, int role ) const;
bool setData( const QModelIndex &index, const QVariant &value, int role );
Qt::ItemFlags flags( const QModelIndex &index ) const;
};

#endif // QGSMAPLAYERMODEL_H
83 changes: 83 additions & 0 deletions src/gui/qgsmaplayerproxymodel.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/***************************************************************************
qgsmaplayerproxymodel.cpp
--------------------------------------
Date : 01.04.2014
Copyright : (C) 2014 Denis Rouzaud
Email : denis.rouzaud@gmail.com
***************************************************************************
* *
* 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 "qgsmaplayerproxymodel.h"
#include "qgsmaplayermodel.h"
#include "qgsmaplayer.h"
#include "qgsvectorlayer.h"

QgsMapLayerProxyModel::QgsMapLayerProxyModel( QObject *parent )
: QSortFilterProxyModel( parent )
, mFilters( NoFilter )
, mModel( new QgsMapLayerModel( this ) )
{
setSourceModel( mModel );
}

QgsMapLayerProxyModel *QgsMapLayerProxyModel::setFilters( Filters filters )
{
mFilters = filters;
return this;
}

bool QgsMapLayerProxyModel::filterAcceptsRow( int source_row, const QModelIndex &source_parent ) const
{
if ( mFilters.testFlag( NoFilter ) )
return true;

QModelIndex index = sourceModel()->index( source_row, 0, source_parent );
QgsMapLayer* layer = static_cast<QgsMapLayer*>( index.internalPointer() );
if ( !layer )
return false;

// layer type
if (( mFilters.testFlag( RasterLayer ) && layer->type() == QgsMapLayer::RasterLayer ) ||
( mFilters.testFlag( VectorLayer ) && layer->type() == QgsMapLayer::VectorLayer ) )
return true;

// geometry type
bool detectGeometry = mFilters.testFlag( NoGeometry ) ||
mFilters.testFlag( PointLayer ) ||
mFilters.testFlag( LineLayer ) ||
mFilters.testFlag( PolygonLayer ) ||
mFilters.testFlag( HasGeometry );
if ( detectGeometry && layer->type() == QgsMapLayer::VectorLayer )
{
QgsVectorLayer* vl = dynamic_cast<QgsVectorLayer*>( layer );
if ( vl )
{
if ( mFilters.testFlag( HasGeometry ) && vl->hasGeometryType() )
return true;
if ( mFilters.testFlag( NoGeometry ) && vl->geometryType() == QGis::NoGeometry )
return true;
if ( mFilters.testFlag( PointLayer ) && vl->geometryType() == QGis::Point )
return true;
if ( mFilters.testFlag( LineLayer ) && vl->geometryType() == QGis::Line )
return true;
if ( mFilters.testFlag( PolygonLayer ) && vl->geometryType() == QGis::Polygon )
return true;
}
}

return false;
}

bool QgsMapLayerProxyModel::lessThan( const QModelIndex &left, const QModelIndex &right ) const
{
// default mode is alphabetical order
QString leftId = sourceModel()->data( left ).toString();
QString rightId = sourceModel()->data( right ).toString();
return QString::localeAwareCompare( leftId, rightId ) < 0;
}
75 changes: 75 additions & 0 deletions src/gui/qgsmaplayerproxymodel.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/***************************************************************************
qgsmaplayerproxymodel.h
--------------------------------------
Date : 01.04.2014
Copyright : (C) 2014 Denis Rouzaud
Email : denis.rouzaud@gmail.com
***************************************************************************
* *
* 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 QGSMAPLAYERPROXYMODEL_H
#define QGSMAPLAYERPROXYMODEL_H

#include <QSortFilterProxyModel>

class QgsMapLayerModel;

/**
* @brief The QgsMapLayerProxModel class provides an easy to use model to display the list of layers in widgets.
* @note added in 2.3
*/
class GUI_EXPORT QgsMapLayerProxyModel : public QSortFilterProxyModel
{
Q_OBJECT
public:
enum Filter
{
NoFilter = 1,
RasterLayer = 2,
NoGeometry = 4,
PointLayer = 8,
LineLayer = 16,
PolygonLayer = 32,
HasGeometry = PointLayer | LineLayer | PolygonLayer,
VectorLayer = NoGeometry | HasGeometry
};
Q_DECLARE_FLAGS( Filters, Filter )

/**
* @brief QgsMapLayerProxModel creates a proxy model with a QgsMapLayerModel as source model.
* It can be used to filter the layers list in a widget.
*/
explicit QgsMapLayerProxyModel( QObject *parent = 0 );

/**
* @brief layerModel returns the QgsMapLayerModel used in this QSortFilterProxyModel
*/
QgsMapLayerModel* sourceLayerModel() {return mModel;}

/**
* @brief setFilters set flags that affect how layers are filtered
* @param filters are Filter flags
* @note added in 2.3
*/
QgsMapLayerProxyModel* setFilters( Filters filters );
const Filters& filters() const { return mFilters; }

private:
Filters mFilters;
QgsMapLayerModel* mModel;

// QSortFilterProxyModel interface
public:
bool filterAcceptsRow( int source_row, const QModelIndex &source_parent ) const;
bool lessThan( const QModelIndex &left, const QModelIndex &right ) const;
};

Q_DECLARE_OPERATORS_FOR_FLAGS( QgsMapLayerProxyModel::Filters )

#endif // QGSMAPLAYERPROXYMODEL_H
16 changes: 13 additions & 3 deletions src/ui/qgsatlascompositionwidgetbase.ui
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@
</widget>
</item>
<item row="0" column="2">
<widget class="QComboBox" name="mAtlasCoverageLayerComboBox">
<widget class="QgsMapLayerComboBox" name="mAtlasCoverageLayerComboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
Expand Down Expand Up @@ -206,7 +206,7 @@
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="mAtlasSortFeatureKeyComboBox"/>
<widget class="QgsFieldComboBox" name="mAtlasSortFeatureKeyComboBox"/>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="mAtlasSortFeatureCheckBox">
Expand Down Expand Up @@ -284,9 +284,19 @@
<customwidget>
<class>QgsCollapsibleGroupBoxBasic</class>
<extends>QGroupBox</extends>
<header location="global">qgscollapsiblegroupbox.h</header>
<header>qgscollapsiblegroupbox.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>QgsMapLayerComboBox</class>
<extends>QComboBox</extends>
<header location="global">qgsmaplayercombobox.h</header>
</customwidget>
<customwidget>
<class>QgsFieldComboBox</class>
<extends>QComboBox</extends>
<header location="global">qgsfieldcombobox.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="../../images/images.qrc"/>
Expand Down
10 changes: 7 additions & 3 deletions src/ui/qgsdxfexportdialogbase.ui
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>377</width>
<height>292</height>
<width>406</width>
<height>293</height>
</rect>
</property>
<property name="windowTitle">
Expand Down Expand Up @@ -80,7 +80,11 @@
<widget class="QLineEdit" name="mSymbologyScaleLineEdit"/>
</item>
<item row="3" column="0" colspan="3">
<widget class="QListWidget" name="mLayersListWidget"/>
<widget class="QListView" name="mLayersListView">
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
</widget>
</item>
</layout>
</item>
Expand Down
2 changes: 1 addition & 1 deletion tests/src/core/testqgsatlascomposition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ void TestQgsAtlasComposition::sorting_render()
mAtlas->setHideCoverage( false );

mAtlas->setSortFeatures( true );
mAtlas->setSortKeyAttributeIndex( 4 ); // departement name
mAtlas->setSortKeyAttributeName( "NAME_1" ); // departement name
mAtlas->setSortAscending( false );

mAtlas->beginRender();
Expand Down