diff --git a/python/core/composer/qgscomposermodel.sip b/python/core/composer/qgscomposermodel.sip index 332c78913e3..165f2948e09 100644 --- a/python/core/composer/qgscomposermodel.sip +++ b/python/core/composer/qgscomposermodel.sip @@ -23,6 +23,14 @@ class QgsComposerModel : QAbstractItemModel %End public: + //! Columns returned by the model + enum Columns + { + Visibility, /*!< Item visibility check box */ + LockStatus, /*!< Item lock status check box */ + ItemId, /*!< Item ID */ + }; + /** Constructor * @param composition composition to attach to * @param parent parent object @@ -202,6 +210,13 @@ class QgsComposerModel : QAbstractItemModel */ void updateItemSelectStatus( QgsComposerItem *item ); + /** Returns the QModelIndex corresponding to a QgsComposerItem, if possible + * @param item QgsComposerItem to find index for + * @param column column number for created QModelIndex + * @returns QModelIndex corresponding to item and specified column + */ + QModelIndex indexForItem( QgsComposerItem *item, const int column = 0 ); + public slots: /** Sets an item as the current selection from a QModelIndex @@ -210,3 +225,65 @@ class QgsComposerModel : QAbstractItemModel */ void setSelected( const QModelIndex &index ); }; + + +/** + * /class QgsComposerProxyModel + * /ingroup core + * /brief Allows for filtering a QgsComposerModel by item type. + * /note added in 2.16 + */ +class QgsComposerProxyModel: QSortFilterProxyModel +{ +%TypeHeaderCode +#include "qgscomposermodel.h" +%End + public: + + /** Constructor for QgsComposerProxyModel. + * @param composition composition to attach model to + * @param parent optional parent + */ + QgsComposerProxyModel( QgsComposition* composition, QObject *parent /TransferThis/ = nullptr ); + + /** Returns the current item type filter, or QgsComposerItem::ComposerItem if no + * item type filter is set. + * @see setFilterType() + */ + QgsComposerItem::ItemType filterType() const; + + /** Sets the item type filter. Only matching item types will be shown. + * @param itemType type to filter. Set to QgsComposerItem::ComposerItem to show all + * item types. + * @see filterType() + */ + void setFilterType( QgsComposerItem::ItemType itemType ); + + /** Sets a list of specific items to exclude from the model + * @param exceptList list of items to exclude + * @see exceptedItemList() + */ + void setExceptedItemList( const QList< QgsComposerItem* >& exceptList ); + + /** Returns the list of specific items excluded from the model. + * @see setExceptedItemList() + */ + QList< QgsComposerItem* > exceptedItemList() const; + + /** Returns the QgsComposerModel used in this proxy model. + */ + QgsComposerModel* sourceLayerModel() const; + + /** Returns the QgsComposerItem corresponding to an index from the source + * QgsComposerModel model. + * @param sourceIndex a QModelIndex + * @returns QgsComposerItem for specified index from QgsComposerModel + */ + QgsComposerItem* itemFromSourceIndex( const QModelIndex& sourceIndex ) const; + + protected: + bool filterAcceptsRow( int source_row, const QModelIndex & source_parent ) const; + bool lessThan( const QModelIndex &left, const QModelIndex &right ) const; + +}; + diff --git a/python/gui/gui.sip b/python/gui/gui.sip index e8ed80558c4..d4878a71760 100644 --- a/python/gui/gui.sip +++ b/python/gui/gui.sip @@ -49,6 +49,7 @@ %Include qgscolorschemelist.sip %Include qgscolorswatchgrid.sip %Include qgscolorwidgets.sip +%Include qgscomposeritemcombobox.sip %Include qgscomposerruler.sip %Include qgscomposerview.sip %Include qgscredentialdialog.sip diff --git a/python/gui/qgscomposeritemcombobox.sip b/python/gui/qgscomposeritemcombobox.sip new file mode 100644 index 00000000000..e690e002bcf --- /dev/null +++ b/python/gui/qgscomposeritemcombobox.sip @@ -0,0 +1,72 @@ +/** + * /class QgsComposerItemComboBox + * /ingroup gui + * /brief The QgsComposerItemComboBox class is a combo box which displays items of + * a matching type from a composition. + * /note added in 2.16 + */ +class QgsComposerItemComboBox : QComboBox +{ +%TypeHeaderCode +#include "qgscomposeritemcombobox.h" +%End + + public: + /** + * QgsComposerItemComboBox creates a combo box to display a list of items in a + * composition. The items can optionally be filtered by type. + * @param parent parent widget + * @param composition composition to show items from. If not set, no items will be shown + * until setComposition() is called + */ + explicit QgsComposerItemComboBox( QWidget* parent /TransferThis/ = nullptr, QgsComposition* composition = nullptr ); + + /** Sets the composition containing the items to list in the combo box. + */ + void setComposition( QgsComposition* composition ); + + /** Sets a filter for the item type to show in the combo box. + * @param itemType type of items to show. Set to QgsComposerItem::ComposerItem to + * show all items. + * @see itemType() + */ + void setItemType( QgsComposerItem::ItemType itemType ); + + /** Returns the filter for the item types to show in the combo box. + * @see setItemType() + */ + QgsComposerItem::ItemType itemType() const; + + /** Sets a list of specific items to exclude from the combo box. + * @param exceptList list of items to exclude + * @see exceptedItemList() + */ + void setExceptedItemList( const QList< QgsComposerItem* >& exceptList ); + + /** Returns the list of specific items excluded from the combo box. + * @see setExceptedItemList() + */ + QList< QgsComposerItem* > exceptedItemList() const; + + /** Return the item currently shown at the specified index within the combo box. + * @param index position of item to return + * @see currentItem() + */ + const QgsComposerItem* item( int index ) const; + + /** Returns the item currently selected in the combo box. + */ + const QgsComposerItem* currentItem() const; + + public slots: + /** Sets the currently selected item in the combo box. + * @param item selected item + */ + void setItem( const QgsComposerItem* item ); + + signals: + + //! Emitted whenever the currently selected item changes + void itemChanged( QgsComposerItem* item ); + +}; diff --git a/src/app/composer/qgscomposerattributetablewidget.cpp b/src/app/composer/qgscomposerattributetablewidget.cpp index 6521cf8a440..7d304b5eda9 100644 --- a/src/app/composer/qgscomposerattributetablewidget.cpp +++ b/src/app/composer/qgscomposerattributetablewidget.cpp @@ -61,7 +61,9 @@ QgsComposerAttributeTableWidget::QgsComposerAttributeTableWidget( QgsComposerAtt mLayerComboBox->setFilters( QgsMapLayerProxyModel::VectorLayer ); connect( mLayerComboBox, SIGNAL( layerChanged( QgsMapLayer* ) ), this, SLOT( changeLayer( QgsMapLayer* ) ) ); - refreshMapComboBox(); + mComposerMapComboBox->setComposition( mComposerTable->composition() ); + mComposerMapComboBox->setItemType( QgsComposerItem::ComposerMap ); + connect( mComposerMapComboBox, SIGNAL( itemChanged( const QgsComposerItem* ) ), this, SLOT( composerMapChanged( const QgsComposerItem* ) ) ); mHeaderFontColorButton->setColorDialogTitle( tr( "Select header font color" ) ); mHeaderFontColorButton->setAllowAlpha( true ); @@ -80,7 +82,6 @@ QgsComposerAttributeTableWidget::QgsComposerAttributeTableWidget( QgsComposerAtt mBackgroundColorButton->setNoColorString( tr( "No background" ) ); updateGuiElements(); - on_mComposerMapComboBox_activated( mComposerMapComboBox->currentIndex() ); if ( mComposerTable ) { @@ -107,47 +108,6 @@ QgsComposerAttributeTableWidget::QgsComposerAttributeTableWidget( QgsComposerAtt QgsComposerAttributeTableWidget::~QgsComposerAttributeTableWidget() { - -} - -void QgsComposerAttributeTableWidget::showEvent( QShowEvent* /* event */ ) -{ - refreshMapComboBox(); -} - -void QgsComposerAttributeTableWidget::refreshMapComboBox() -{ - //save the current entry in case it is still present after refresh - QString saveCurrentComboText = mComposerMapComboBox->currentText(); - - mComposerMapComboBox->blockSignals( true ); - mComposerMapComboBox->clear(); - if ( mComposerTable ) - { - const QgsComposition* tableComposition = mComposerTable->composition(); - if ( tableComposition ) - { - QList mapList = tableComposition->composerMapItems(); - QList::const_iterator mapIt = mapList.constBegin(); - for ( ; mapIt != mapList.constEnd(); ++mapIt ) - { - int mapId = ( *mapIt )->id(); - mComposerMapComboBox->addItem( tr( "Map %1" ).arg( mapId ), mapId ); - } - } - } - mComposerMapComboBox->blockSignals( false ); - - if ( mComposerMapComboBox->findText( saveCurrentComboText ) == -1 ) - { - //the former entry is no longer present. Inform the scalebar about the changed composer map - on_mComposerMapComboBox_activated( mComposerMapComboBox->currentIndex() ); - } - else - { - //the former entry is still present. Make it the current entry again - mComposerMapComboBox->setCurrentIndex( mComposerMapComboBox->findText( saveCurrentComboText ) ); - } } void QgsComposerAttributeTableWidget::on_mRefreshPushButton_clicked() @@ -213,31 +173,24 @@ void QgsComposerAttributeTableWidget::on_mAttributesPushButton_clicked() } } -void QgsComposerAttributeTableWidget::on_mComposerMapComboBox_activated( int index ) +void QgsComposerAttributeTableWidget::composerMapChanged( const QgsComposerItem* item ) { if ( !mComposerTable ) { return; } - QVariant itemData = mComposerMapComboBox->itemData( index ); - if ( itemData.type() == QVariant::Invalid ) - { - return; - } - - int mapId = itemData.toInt(); const QgsComposition* tableComposition = mComposerTable->composition(); if ( tableComposition ) { QgsComposition* composition = mComposerTable->composition(); - if ( sender() && composition ) //only create command if called from GUI + if ( composition ) { composition->beginMultiFrameCommand( mComposerTable, tr( "Table map changed" ) ); } - mComposerTable->setComposerMap( tableComposition->getComposerMapById( mapId ) ); + mComposerTable->setComposerMap( dynamic_cast< const QgsComposerMap* >( item ) ); mComposerTable->update(); - if ( sender() && composition ) + if ( composition ) { composition->endMultiFrameCommand(); } @@ -467,16 +420,7 @@ void QgsComposerAttributeTableWidget::updateGuiElements() } } - //map combo box - const QgsComposerMap* cm = mComposerTable->composerMap(); - if ( cm ) - { - int mapIndex = mComposerMapComboBox->findText( tr( "Map %1" ).arg( cm->id() ) ); - if ( mapIndex != -1 ) - { - mComposerMapComboBox->setCurrentIndex( mapIndex ); - } - } + mComposerMapComboBox->setItem( mComposerTable->composerMap() ); mMaximumRowsSpinBox->setValue( mComposerTable->maximumNumberOfFeatures() ); mMarginSpinBox->setValue( mComposerTable->cellMargin() ); mGridStrokeWidthSpinBox->setValue( mComposerTable->gridStrokeWidth() ); diff --git a/src/app/composer/qgscomposerattributetablewidget.h b/src/app/composer/qgscomposerattributetablewidget.h index 83889d6c32f..66d4b9e3cb5 100644 --- a/src/app/composer/qgscomposerattributetablewidget.h +++ b/src/app/composer/qgscomposerattributetablewidget.h @@ -31,16 +31,12 @@ class QgsComposerAttributeTableWidget: public QgsComposerItemBaseWidget, private QgsComposerAttributeTableWidget( QgsComposerAttributeTableV2* table, QgsComposerFrame* frame ); ~QgsComposerAttributeTableWidget(); - protected: - void showEvent( QShowEvent * event ) override; - private: QgsComposerAttributeTableV2* mComposerTable; QgsComposerFrame* mFrame; /** Blocks / unblocks the signals of all GUI elements*/ void blockAllSignals( bool b ); - void refreshMapComboBox(); void toggleSourceControls(); @@ -49,7 +45,7 @@ class QgsComposerAttributeTableWidget: public QgsComposerItemBaseWidget, private private slots: void on_mRefreshPushButton_clicked(); void on_mAttributesPushButton_clicked(); - void on_mComposerMapComboBox_activated( int index ); + void composerMapChanged( const QgsComposerItem* item ); void on_mMaximumRowsSpinBox_valueChanged( int i ); void on_mMarginSpinBox_valueChanged( double d ); void on_mGridStrokeWidthSpinBox_valueChanged( double d ); diff --git a/src/app/composer/qgscomposerlegendwidget.cpp b/src/app/composer/qgscomposerlegendwidget.cpp index 4aa9889a80d..aad4e7cae2d 100644 --- a/src/app/composer/qgscomposerlegendwidget.cpp +++ b/src/app/composer/qgscomposerlegendwidget.cpp @@ -64,6 +64,10 @@ QgsComposerLegendWidget::QgsComposerLegendWidget( QgsComposerLegend* legend ) mRasterBorderColorButton->setAllowAlpha( true ); mRasterBorderColorButton->setContext( "composer " ); + mMapComboBox->setComposition( legend->composition() ); + mMapComboBox->setItemType( QgsComposerItem::ComposerMap ); + connect( mMapComboBox, SIGNAL( itemChanged( const QgsComposerItem* ) ), this, SLOT( composerMapChanged( const QgsComposerItem* ) ) ); + //add widget for item properties QgsComposerItemWidget* itemPropertiesWidget = new QgsComposerItemWidget( this, legend ); mainLayout->addWidget( itemPropertiesWidget ); @@ -132,17 +136,9 @@ void QgsComposerLegendWidget::setGuiElements() mRasterBorderColorButton->setColor( mLegend->rasterBorderColor() ); mCheckBoxAutoUpdate->setChecked( mLegend->autoUpdateModel() ); - refreshMapComboBox(); const QgsComposerMap* map = mLegend->composerMap(); - if ( map ) - { - mMapComboBox->setCurrentIndex( mMapComboBox->findData( map->id() ) ); - } - else - { - mMapComboBox->setCurrentIndex( mMapComboBox->findData( -1 ) ); - } + mMapComboBox->setItem( map ); mFontColorButton->setColor( mLegend->fontColor() ); blockAllSignals( false ); @@ -553,40 +549,26 @@ void QgsComposerLegendWidget::on_mCheckBoxAutoUpdate_stateChanged( int state ) } } -void QgsComposerLegendWidget::on_mMapComboBox_currentIndexChanged( int index ) +void QgsComposerLegendWidget::composerMapChanged( const QgsComposerItem* item ) { if ( !mLegend ) { return; } - QVariant itemData = mMapComboBox->itemData( index ); - if ( itemData.type() == QVariant::Invalid ) - { - return; - } - const QgsComposition* comp = mLegend->composition(); if ( !comp ) { return; } - int mapNr = itemData.toInt(); - if ( mapNr < 0 ) + const QgsComposerMap* map = dynamic_cast< const QgsComposerMap* >( item ); + if ( map ) { - mLegend->setComposerMap( nullptr ); - } - else - { - const QgsComposerMap* map = comp->getComposerMapById( mapNr ); - if ( map ) - { - mLegend->beginCommand( tr( "Legend map changed" ) ); - mLegend->setComposerMap( map ); - mLegend->updateItem(); - mLegend->endCommand(); - } + mLegend->beginCommand( tr( "Legend map changed" ) ); + mLegend->setComposerMap( map ); + mLegend->updateItem(); + mLegend->endCommand(); } } @@ -959,48 +941,6 @@ void QgsComposerLegendWidget::blockAllSignals( bool b ) mRasterBorderWidthSpinBox->blockSignals( b ); } -void QgsComposerLegendWidget::refreshMapComboBox() -{ - if ( !mLegend ) - { - return; - } - - const QgsComposition* composition = mLegend->composition(); - if ( !composition ) - { - return; - } - - //save current entry - int currentMapId = mMapComboBox->itemData( mMapComboBox->currentIndex() ).toInt(); - mMapComboBox->clear(); - - QList availableMaps = composition->composerMapItems(); - QList::const_iterator mapItemIt = availableMaps.constBegin(); - for ( ; mapItemIt != availableMaps.constEnd(); ++mapItemIt ) - { - mMapComboBox->addItem( tr( "Map %1" ).arg(( *mapItemIt )->id() ), ( *mapItemIt )->id() ); - } - mMapComboBox->addItem( tr( "None" ), -1 ); - - //the former entry is not there anymore - int entry = mMapComboBox->findData( currentMapId ); - if ( entry == -1 ) - { - } - else - { - mMapComboBox->setCurrentIndex( entry ); - } -} - -void QgsComposerLegendWidget::showEvent( QShowEvent * event ) -{ - refreshMapComboBox(); - QWidget::showEvent( event ); -} - void QgsComposerLegendWidget::selectedChanged( const QModelIndex & current, const QModelIndex & previous ) { Q_UNUSED( current ); diff --git a/src/app/composer/qgscomposerlegendwidget.h b/src/app/composer/qgscomposerlegendwidget.h index b1ecd467566..73acba95df2 100644 --- a/src/app/composer/qgscomposerlegendwidget.h +++ b/src/app/composer/qgscomposerlegendwidget.h @@ -67,7 +67,7 @@ class QgsComposerLegendWidget: public QgsComposerItemBaseWidget, private Ui::Qgs void on_mBoxSpaceSpinBox_valueChanged( double d ); void on_mColumnSpaceSpinBox_valueChanged( double d ); void on_mCheckBoxAutoUpdate_stateChanged( int state ); - void on_mMapComboBox_currentIndexChanged( int index ); + void composerMapChanged( const QgsComposerItem* item ); void on_mRasterBorderGroupBox_toggled( bool state ); void on_mRasterBorderWidthSpinBox_valueChanged( double d ); @@ -92,9 +92,6 @@ class QgsComposerLegendWidget: public QgsComposerItemBaseWidget, private Ui::Qgs void setCurrentNodeStyleFromAction(); - protected: - void showEvent( QShowEvent * event ) override; - private slots: /** Sets GUI according to state of mLegend*/ void setGuiElements(); @@ -105,8 +102,6 @@ class QgsComposerLegendWidget: public QgsComposerItemBaseWidget, private Ui::Qgs private: QgsComposerLegendWidget(); void blockAllSignals( bool b ); - void refreshMapComboBox(); - QgsComposerLegend* mLegend; }; diff --git a/src/app/composer/qgscomposermapwidget.cpp b/src/app/composer/qgscomposermapwidget.cpp index 9a79347a2d5..db402e8aa1a 100644 --- a/src/app/composer/qgscomposermapwidget.cpp +++ b/src/app/composer/qgscomposermapwidget.cpp @@ -152,6 +152,11 @@ QgsComposerMapWidget::QgsComposerMapWidget( QgsComposerMap* composerMap ) compositionAtlasToggled( atlas->enabled() ); } + + mOverviewFrameMapComboBox->setComposition( composerMap->composition() ); + mOverviewFrameMapComboBox->setItemType( QgsComposerItem::ComposerMap ); + mOverviewFrameMapComboBox->setExceptedItemList( QList< QgsComposerItem* >() << composerMap ); + connect( mOverviewFrameMapComboBox, SIGNAL( itemChanged( const QgsComposerItem* ) ), this, SLOT( overviewMapChanged( const QgsComposerItem* ) ) ); } //connections for data defined buttons @@ -952,12 +957,6 @@ void QgsComposerMapWidget::on_mDrawCanvasItemsCheckBox_stateChanged( int state ) mComposerMap->endCommand(); } -void QgsComposerMapWidget::showEvent( QShowEvent * event ) -{ - refreshMapComboBox(); - QWidget::showEvent( event ); -} - void QgsComposerMapWidget::addPageToToolbox( QWidget* widget, const QString& name ) { Q_UNUSED( name ); @@ -1095,53 +1094,6 @@ void QgsComposerMapWidget::initAnnotationDirectionBox( QComboBox* c, QgsComposer c->setCurrentIndex( c->findData( dir ) ); } -void QgsComposerMapWidget::refreshMapComboBox() -{ - if ( !mComposerMap ) - { - return; - } - - mOverviewFrameMapComboBox->blockSignals( true ); - - //save the current entry in case it is still present after refresh - QString saveComboText = mOverviewFrameMapComboBox->currentText(); - - mOverviewFrameMapComboBox->clear(); - mOverviewFrameMapComboBox->addItem( tr( "None" ), -1 ); - const QgsComposition* composition = mComposerMap->composition(); - if ( !composition ) - { - return; - } - - QList availableMaps = composition->composerMapItems(); - QList::const_iterator mapItemIt = availableMaps.constBegin(); - for ( ; mapItemIt != availableMaps.constEnd(); ++mapItemIt ) - { - if (( *mapItemIt )->id() != mComposerMap->id() ) - { - mOverviewFrameMapComboBox->addItem( tr( "Map %1" ).arg(( *mapItemIt )->id() ), ( *mapItemIt )->id() ); - } - } - - if ( !saveComboText.isEmpty() ) - { - int saveTextIndex = mOverviewFrameMapComboBox->findText( saveComboText ); - if ( saveTextIndex == -1 ) - { - //entry is no longer present - mOverviewFrameMapComboBox->setCurrentIndex( mOverviewFrameMapComboBox->findText( tr( "None" ) ) ); - } - else - { - mOverviewFrameMapComboBox->setCurrentIndex( saveTextIndex ); - } - } - - mOverviewFrameMapComboBox->blockSignals( false ); -} - void QgsComposerMapWidget::atlasLayerChanged( QgsVectorLayer* layer ) { if ( !layer || layer->wkbType() == QGis::WKBNoGeometry ) @@ -2412,9 +2364,7 @@ void QgsComposerMapWidget::setOverviewItems( const QgsComposerMapOverview* overv mOverviewCheckBox->setChecked( overview->enabled() ); //overview frame - refreshMapComboBox(); - int overviewMapFrameId = overview->frameMapId(); - mOverviewFrameMapComboBox->setCurrentIndex( mOverviewFrameMapComboBox->findData( overviewMapFrameId ) ); + mOverviewFrameMapComboBox->setItem( mComposerMap->composition()->getComposerMapById( overview->frameMapId() ) ); //overview frame blending mode mOverviewBlendModeComboBox->setBlendMode( overview->blendMode() ); //overview inverted @@ -2508,7 +2458,7 @@ void QgsComposerMapWidget::on_mOverviewCheckBox_toggled( bool state ) mComposerMap->endCommand(); } -void QgsComposerMapWidget::on_mOverviewFrameMapComboBox_currentIndexChanged( const QString& text ) +void QgsComposerMapWidget::overviewMapChanged( const QgsComposerItem* item ) { QgsComposerMapOverview* overview = currentOverview(); if ( !overview ) @@ -2516,47 +2466,12 @@ void QgsComposerMapWidget::on_mOverviewFrameMapComboBox_currentIndexChanged( con return; } - int id; - - if ( text == tr( "None" ) ) - { - id = -1; - } - else - { - - //get composition - const QgsComposition* composition = mComposerMap->composition(); - if ( !composition ) - { - return; - } - - //extract id - bool conversionOk; - QStringList textSplit = text.split( ' ' ); - if ( textSplit.size() < 1 ) - { - return; - } - - QString idString = textSplit.at( textSplit.size() - 1 ); - id = idString.toInt( &conversionOk ); - - if ( !conversionOk ) - { - return; - } - - const QgsComposerMap* composerMap = composition->getComposerMapById( id ); - if ( !composerMap ) - { - return; - } - } + const QgsComposerMap* map = dynamic_cast< const QgsComposerMap* >( item ); + if ( !map ) + return; mComposerMap->beginCommand( tr( "Overview map changed" ) ); - overview->setFrameMap( id ); + overview->setFrameMap( map->id() ); mComposerMap->update(); mComposerMap->endCommand(); } diff --git a/src/app/composer/qgscomposermapwidget.h b/src/app/composer/qgscomposermapwidget.h index 06675fd11fd..01064f245ec 100644 --- a/src/app/composer/qgscomposermapwidget.h +++ b/src/app/composer/qgscomposermapwidget.h @@ -46,7 +46,7 @@ class QgsComposerMapWidget: public QgsComposerItemBaseWidget, private Ui::QgsCom void on_mKeepLayerListCheckBox_stateChanged( int state ); void on_mKeepLayerStylesCheckBox_stateChanged( int state ); void on_mDrawCanvasItemsCheckBox_stateChanged( int state ); - void on_mOverviewFrameMapComboBox_currentIndexChanged( const QString& text ); + void overviewMapChanged( const QgsComposerItem* item ); void on_mOverviewFrameStyleButton_clicked(); void on_mOverviewBlendModeComboBox_currentIndexChanged( int index ); void on_mOverviewInvertCheckbox_toggled( bool state ); @@ -145,7 +145,6 @@ class QgsComposerMapWidget: public QgsComposerItemBaseWidget, private Ui::QgsCom void blockOverviewItemsSignals( bool block ); protected: - void showEvent( QShowEvent * event ) override; void addPageToToolbox( QWidget * widget, const QString& name ); @@ -200,9 +199,6 @@ class QgsComposerMapWidget: public QgsComposerItemBaseWidget, private Ui::QgsCom void updateGridLineSymbolMarker( const QgsComposerMapGrid* grid ); void updateGridMarkerSymbolMarker( const QgsComposerMapGrid* grid ); - /** Updates the map combo box with the current composer map ids*/ - void refreshMapComboBox(); - /** Enables/disables grid frame related controls*/ void toggleFrameControls( bool frameEnabled, bool frameFillEnabled, bool frameSizeEnabled ); diff --git a/src/app/composer/qgscomposerpicturewidget.cpp b/src/app/composer/qgscomposerpicturewidget.cpp index 8374636c08d..b1243f1d390 100644 --- a/src/app/composer/qgscomposerpicturewidget.cpp +++ b/src/app/composer/qgscomposerpicturewidget.cpp @@ -48,6 +48,13 @@ QgsComposerPictureWidget::QgsComposerPictureWidget( QgsComposerPicture* picture QgsComposerItemWidget* itemPropertiesWidget = new QgsComposerItemWidget( this, picture ); mainLayout->addWidget( itemPropertiesWidget ); + if ( mPicture->composition() ) + { + mComposerMapComboBox->setComposition( mPicture->composition() ); + mComposerMapComboBox->setItemType( QgsComposerItem::ComposerMap ); + connect( mComposerMapComboBox, SIGNAL( itemChanged( const QgsComposerItem* ) ), this, SLOT( composerMapChanged( const QgsComposerItem* ) ) ); + } + setGuiElementValues(); mPreviewsLoadingLabel->hide(); @@ -277,23 +284,18 @@ void QgsComposerPictureWidget::on_mRotationFromComposerMapCheckBox_stateChanged( } else { - int currentItemIndex = mComposerMapComboBox->currentIndex(); - if ( currentItemIndex == -1 ) - { - return; - } - int composerId = mComposerMapComboBox->itemData( currentItemIndex, Qt::UserRole ).toInt(); - - mPicture->setRotationMap( composerId ); + const QgsComposerMap* map = dynamic_cast< const QgsComposerMap* >( mComposerMapComboBox->currentItem() ); + int mapId = map ? map->id() : -1; + mPicture->setRotationMap( mapId ); mPictureRotationSpinBox->setEnabled( false ); mComposerMapComboBox->setEnabled( true ); } mPicture->endCommand(); } -void QgsComposerPictureWidget::on_mComposerMapComboBox_activated( const QString & text ) +void QgsComposerPictureWidget::composerMapChanged( const QgsComposerItem* item ) { - if ( !mPicture || text.isEmpty() || !mPicture->useRotationMap() ) + if ( !mPicture ) { return; } @@ -305,24 +307,8 @@ void QgsComposerPictureWidget::on_mComposerMapComboBox_activated( const QString return; } - //extract id - int id; - bool conversionOk; - QStringList textSplit = text.split( ' ' ); - if ( textSplit.size() < 1 ) - { - return; - } - - QString idString = textSplit.at( textSplit.size() - 1 ); - id = idString.toInt( &conversionOk ); - - if ( !conversionOk ) - { - return; - } - - const QgsComposerMap* composerMap = composition->getComposerMapById( id ); + const QgsComposerMap* composerMap = dynamic_cast< const QgsComposerMap*>( item ); + int id = composerMap ? composerMap->id() : -1; if ( !composerMap ) { return; @@ -333,45 +319,6 @@ void QgsComposerPictureWidget::on_mComposerMapComboBox_activated( const QString mPicture->endCommand(); } -void QgsComposerPictureWidget::refreshMapComboBox() -{ - mComposerMapComboBox->blockSignals( true ); - //save the current entry in case it is still present after refresh - QString saveCurrentComboText = mComposerMapComboBox->currentText(); - - mComposerMapComboBox->clear(); - - if ( mPicture ) - { - //insert available maps into mMapComboBox - const QgsComposition* composition = mPicture->composition(); - if ( composition ) - { - QList availableMaps = composition->composerMapItems(); - QList::const_iterator mapItemIt = availableMaps.constBegin(); - for ( ; mapItemIt != availableMaps.constEnd(); ++mapItemIt ) - { - mComposerMapComboBox->addItem( tr( "Map %1" ).arg(( *mapItemIt )->id() ), ( *mapItemIt )->id() ); - } - } - } - - if ( !saveCurrentComboText.isEmpty() ) - { - if ( mComposerMapComboBox->findText( saveCurrentComboText ) == -1 ) - { - //the former entry is no longer present. Inform the scalebar about the changed composer map - on_mComposerMapComboBox_activated( mComposerMapComboBox->currentText() ); - } - else - { - //the former entry is still present. Make it the current entry again - mComposerMapComboBox->setCurrentIndex( mComposerMapComboBox->findText( saveCurrentComboText ) ); - } - } - mComposerMapComboBox->blockSignals( false ); -} - void QgsComposerPictureWidget::setPicRotationSpinValue( double r ) { mPictureRotationSpinBox->blockSignals( true ); @@ -397,19 +344,17 @@ void QgsComposerPictureWidget::setGuiElementValues() mPictureLineEdit->setText( mPicture->picturePath() ); mPictureRotationSpinBox->setValue( mPicture->pictureRotation() ); - refreshMapComboBox(); + const QgsComposerMap* map = mPicture->composition()->getComposerMapById( mPicture->rotationMap() ); + if ( map ) + mComposerMapComboBox->setItem( map ); + else + mComposerMapComboBox->setCurrentIndex( 0 ); if ( mPicture->useRotationMap() ) { mRotationFromComposerMapCheckBox->setCheckState( Qt::Checked ); mPictureRotationSpinBox->setEnabled( false ); mComposerMapComboBox->setEnabled( true ); - QString mapText = tr( "Map %1" ).arg( mPicture->rotationMap() ); - int itemId = mComposerMapComboBox->findText( mapText ); - if ( itemId >= 0 ) - { - mComposerMapComboBox->setCurrentIndex( itemId ); - } } else { @@ -720,12 +665,6 @@ void QgsComposerPictureWidget::on_mOutlineWidthSpinBox_valueChanged( double d ) mPicture->update(); } -void QgsComposerPictureWidget::showEvent( QShowEvent * event ) -{ - Q_UNUSED( event ); - refreshMapComboBox(); -} - void QgsComposerPictureWidget::resizeEvent( QResizeEvent * event ) { Q_UNUSED( event ); diff --git a/src/app/composer/qgscomposerpicturewidget.h b/src/app/composer/qgscomposerpicturewidget.h index a497f1baff8..00ff003a7fd 100644 --- a/src/app/composer/qgscomposerpicturewidget.h +++ b/src/app/composer/qgscomposerpicturewidget.h @@ -45,12 +45,11 @@ class QgsComposerPictureWidget: public QgsComposerItemBaseWidget, private Ui::Qg void on_mAddDirectoryButton_clicked(); void on_mRemoveDirectoryButton_clicked(); void on_mRotationFromComposerMapCheckBox_stateChanged( int state ); - void on_mComposerMapComboBox_activated( const QString & text ); + void composerMapChanged( const QgsComposerItem* item ); void on_mResizeModeComboBox_currentIndexChanged( int index ); void on_mAnchorPointComboBox_currentIndexChanged( int index ); protected: - void showEvent( QShowEvent * event ) override; void resizeEvent( QResizeEvent * event ) override; QgsComposerObject::DataDefinedProperty ddPropertyForWidget( QgsDataDefinedButton *widget ) override; @@ -86,8 +85,6 @@ class QgsComposerPictureWidget: public QgsComposerItemBaseWidget, private Ui::Qg bool testSvgFile( const QString& filename ) const; /** Tests if a file is a valid pixel format*/ bool testImageFile( const QString& filename ) const; - /** Updates the map combo box with the current composer map ids*/ - void refreshMapComboBox(); //! Renders an svg file to a QIcon, correctly handling any SVG parameters present in the file QIcon svgToIcon( const QString& filePath ) const; diff --git a/src/app/composer/qgscomposerscalebarwidget.cpp b/src/app/composer/qgscomposerscalebarwidget.cpp index f595def0802..04657325be5 100644 --- a/src/app/composer/qgscomposerscalebarwidget.cpp +++ b/src/app/composer/qgscomposerscalebarwidget.cpp @@ -79,6 +79,15 @@ QgsComposerScaleBarWidget::QgsComposerScaleBarWidget( QgsComposerScaleBar* scale mStrokeColorButton->setNoColorString( tr( "Transparent line" ) ); mStrokeColorButton->setShowNoColor( true ); + QgsComposition* scaleBarComposition = mComposerScaleBar->composition(); + if ( scaleBarComposition ) + { + mMapItemComboBox->setComposition( scaleBarComposition ); + mMapItemComboBox->setItemType( QgsComposerItem::ComposerMap ); + } + + connect( mMapItemComboBox, SIGNAL( itemChanged( const QgsComposerItem* ) ), this, SLOT( composerMapChanged( const QgsComposerItem* ) ) ); + blockMemberSignals( false ); setGuiElements(); //set the GUI elements to the state of scaleBar } @@ -88,97 +97,6 @@ QgsComposerScaleBarWidget::~QgsComposerScaleBarWidget() } -void QgsComposerScaleBarWidget::refreshMapComboBox() -{ - //save the current entry in case it is still present after refresh - QString saveCurrentComboText = mMapComboBox->currentText(); - - mMapComboBox->clear(); - - if ( mComposerScaleBar ) - { - //insert available maps into mMapComboBox - const QgsComposition* scaleBarComposition = mComposerScaleBar->composition(); - if ( scaleBarComposition ) - { - QList availableMaps = scaleBarComposition->composerMapItems(); - QList::const_iterator mapItemIt = availableMaps.constBegin(); - for ( ; mapItemIt != availableMaps.constEnd(); ++mapItemIt ) - { - mMapComboBox->addItem( tr( "Map %1" ).arg(( *mapItemIt )->id() ) ); - } - } - - if ( saveCurrentComboText.isEmpty() && mComposerScaleBar->composerMap() ) - { - //combo box was not initialized before - mMapComboBox->setCurrentIndex( mMapComboBox->findText( tr( "Map %1" ).arg( mComposerScaleBar->composerMap()->id() ) ) ); - } - } - if ( mMapComboBox->findText( saveCurrentComboText ) == -1 ) - { - //the former entry is no longer present. Inform the scalebar about the changed composer map - on_mMapComboBox_activated( mMapComboBox->currentText() ); - } - else - { - //the former entry is still present. Make it the current entry again - mMapComboBox->setCurrentIndex( mMapComboBox->findText( saveCurrentComboText ) ); - } -} - -void QgsComposerScaleBarWidget::showEvent( QShowEvent * event ) -{ - refreshMapComboBox(); - QWidget::showEvent( event ); -} - -void QgsComposerScaleBarWidget::on_mMapComboBox_activated( const QString& text ) -{ - if ( !mComposerScaleBar || text.isEmpty() ) - { - return; - } - - const QgsComposition* comp = mComposerScaleBar->composition(); - if ( !comp ) - { - return; - } - - //extract id - int id; - bool conversionOk; - QStringList textSplit = text.split( ' ' ); - if ( textSplit.size() < 1 ) - { - return; - } - - QString idString = textSplit.at( textSplit.size() - 1 ); - id = idString.toInt( &conversionOk ); - - if ( !conversionOk ) - { - return; - } - - //get QgsComposerMap object from composition - const QgsComposerMap* composerMap = comp->getComposerMapById( id ); - if ( !composerMap ) - { - return; - } - - //set it to scale bar - mComposerScaleBar->beginCommand( tr( "Scalebar map changed" ) ); - disconnectUpdateSignal(); - mComposerScaleBar->setComposerMap( composerMap ); - mComposerScaleBar->update(); - connectUpdateSignal(); - mComposerScaleBar->endCommand(); -} - void QgsComposerScaleBarWidget::setGuiElements() { if ( !mComposerScaleBar ) @@ -204,15 +122,7 @@ void QgsComposerScaleBarWidget::setGuiElements() mStrokeColorButton->setColor( mComposerScaleBar->pen().color() ); //map combo box - if ( mComposerScaleBar->composerMap() ) - { - QString mapText = tr( "Map %1" ).arg( mComposerScaleBar->composerMap()->id() ); - int itemId = mMapComboBox->findText( mapText ); - if ( itemId >= 0 ) - { - mMapComboBox->setCurrentIndex( itemId ); - } - } + mMapItemComboBox->setItem( mComposerScaleBar->composerMap() ); //style... QString style = mComposerScaleBar->style(); @@ -634,7 +544,6 @@ void QgsComposerScaleBarWidget::blockMemberSignals( bool block ) mStyleComboBox->blockSignals( block ); mUnitLabelLineEdit->blockSignals( block ); mMapUnitsPerBarUnitSpinBox->blockSignals( block ); - mMapComboBox->blockSignals( block ); mHeightSpinBox->blockSignals( block ); mLineWidthSpinBox->blockSignals( block ); mLabelBarSpaceSpinBox->blockSignals( block ); @@ -648,6 +557,7 @@ void QgsComposerScaleBarWidget::blockMemberSignals( bool block ) mFillColor2Button->blockSignals( block ); mStrokeColorButton->blockSignals( block ); mSegmentSizeRadioGroup.blockSignals( block ); + mMapItemComboBox->blockSignals( block ); } void QgsComposerScaleBarWidget::connectUpdateSignal() @@ -720,6 +630,23 @@ void QgsComposerScaleBarWidget::segmentSizeRadioChanged( QAbstractButton* radio mComposerScaleBar->endCommand(); } +void QgsComposerScaleBarWidget::composerMapChanged( const QgsComposerItem* item ) +{ + const QgsComposerMap* composerMap = dynamic_cast< const QgsComposerMap* >( item ); + if ( !composerMap ) + { + return; + } + + //set it to scale bar + mComposerScaleBar->beginCommand( tr( "Scalebar map changed" ) ); + disconnectUpdateSignal(); + mComposerScaleBar->setComposerMap( composerMap ); + mComposerScaleBar->update(); + connectUpdateSignal(); + mComposerScaleBar->endCommand(); +} + void QgsComposerScaleBarWidget::on_mMinWidthSpinBox_valueChanged( int ) { if ( !mComposerScaleBar ) diff --git a/src/app/composer/qgscomposerscalebarwidget.h b/src/app/composer/qgscomposerscalebarwidget.h index 725a3abb836..5ad2d78819f 100644 --- a/src/app/composer/qgscomposerscalebarwidget.h +++ b/src/app/composer/qgscomposerscalebarwidget.h @@ -34,7 +34,7 @@ class QgsComposerScaleBarWidget: public QgsComposerItemBaseWidget, private Ui::Q ~QgsComposerScaleBarWidget(); public slots: - void on_mMapComboBox_activated( const QString& text ); + void on_mHeightSpinBox_valueChanged( int i ); void on_mLineWidthSpinBox_valueChanged( double d ); void on_mSegmentSizeSpinBox_valueChanged( double d ); @@ -60,15 +60,12 @@ class QgsComposerScaleBarWidget: public QgsComposerItemBaseWidget, private Ui::Q private slots: void setGuiElements(); void segmentSizeRadioChanged( QAbstractButton*radio ); - - protected: - void showEvent( QShowEvent * event ) override; + void composerMapChanged( const QgsComposerItem* item ); private: QgsComposerScaleBar* mComposerScaleBar; QButtonGroup mSegmentSizeRadioGroup; - void refreshMapComboBox(); /** Enables/disables the signals of the input gui elements*/ void blockMemberSignals( bool enable ); diff --git a/src/app/composer/qgscompositionwidget.cpp b/src/app/composer/qgscompositionwidget.cpp index 588a57b86fb..ccf0e2a6592 100644 --- a/src/app/composer/qgscompositionwidget.cpp +++ b/src/app/composer/qgscompositionwidget.cpp @@ -81,26 +81,9 @@ QgsCompositionWidget::QgsCompositionWidget( QWidget* parent, QgsComposition* c ) mWorldFileMapComboBox->setEnabled( mComposition->generateWorldFile() ); // populate the map list - mWorldFileMapComboBox->clear(); - QList availableMaps = mComposition->composerMapItems(); - QList::const_iterator mapItemIt = availableMaps.constBegin(); - for ( ; mapItemIt != availableMaps.constEnd(); ++mapItemIt ) - { - mWorldFileMapComboBox->addItem( tr( "Map %1" ).arg(( *mapItemIt )->id() ), ( *mapItemIt )->id() ); - } - - if ( mComposition->worldFileMap() ) - { - int idx = mWorldFileMapComboBox->findData( mComposition->worldFileMap()->id() ); - if ( idx != -1 ) - { - mWorldFileMapComboBox->setCurrentIndex( idx ); - } - } - - // Connect to addition / removal of maps - connect( mComposition, SIGNAL( composerMapAdded( QgsComposerMap* ) ), this, SLOT( onComposerMapAdded( QgsComposerMap* ) ) ); - connect( mComposition, SIGNAL( itemRemoved( QgsComposerItem* ) ), this, SLOT( onItemRemoved( QgsComposerItem* ) ) ); + mWorldFileMapComboBox->setComposition( mComposition ); + mWorldFileMapComboBox->setItemType( QgsComposerItem::ComposerMap ); + mWorldFileMapComboBox->setItem( mComposition->worldFileMap() ); mSnapToleranceSpinBox->setValue( mComposition->snapTolerance() ); @@ -140,6 +123,8 @@ QgsCompositionWidget::QgsCompositionWidget( QWidget* parent, QgsComposition* c ) connect( mPaperOrientationDDBtn, SIGNAL( dataDefinedActivated( bool ) ), this, SLOT( updateDataDefinedProperty() ) ); connect( mPaperOrientationDDBtn, SIGNAL( dataDefinedActivated( bool ) ), mPaperOrientationComboBox, SLOT( setDisabled( bool ) ) ); + connect( mWorldFileMapComboBox, SIGNAL( itemChanged( const QgsComposerItem* ) ), this, SLOT( worldFileMapChanged( const QgsComposerItem* ) ) ); + //initialize data defined buttons populateDataDefinedButtons(); @@ -676,58 +661,15 @@ void QgsCompositionWidget::on_mGenerateWorldFileCheckBox_toggled( bool state ) mWorldFileMapComboBox->setEnabled( state ); } -void QgsCompositionWidget::onComposerMapAdded( QgsComposerMap* map ) +void QgsCompositionWidget::worldFileMapChanged( const QgsComposerItem* item ) { if ( !mComposition ) { return; } - mWorldFileMapComboBox->addItem( tr( "Map %1" ).arg( map->id() ), map->id() ); - if ( mWorldFileMapComboBox->count() == 1 ) - { - mComposition->setWorldFileMap( map ); - } -} - -void QgsCompositionWidget::onItemRemoved( QgsComposerItem* item ) -{ - if ( !mComposition ) - { - return; - } - - QgsComposerMap* map = dynamic_cast( item ); - if ( map ) - { - int idx = mWorldFileMapComboBox->findData( map->id() ); - if ( idx != -1 ) - { - mWorldFileMapComboBox->removeItem( idx ); - } - } - if ( mWorldFileMapComboBox->count() == 0 ) - { - mComposition->setWorldFileMap( nullptr ); - } -} - -void QgsCompositionWidget::on_mWorldFileMapComboBox_currentIndexChanged( int index ) -{ - if ( !mComposition ) - { - return; - } - if ( index == -1 ) - { - mComposition->setWorldFileMap( nullptr ); - } - else - { - int mapId = mWorldFileMapComboBox->itemData( index ).toInt(); - QgsComposerMap* map = const_cast< QgsComposerMap* >( mComposition->getComposerMapById( mapId ) ); - mComposition->setWorldFileMap( map ); - } + const QgsComposerMap* map = dynamic_cast< const QgsComposerMap* >( item ); + mComposition->setWorldFileMap( const_cast< QgsComposerMap* >( map ) ); } void QgsCompositionWidget::on_mGridResolutionSpinBox_valueChanged( double d ) diff --git a/src/app/composer/qgscompositionwidget.h b/src/app/composer/qgscompositionwidget.h index 52831559f8a..276905a3382 100644 --- a/src/app/composer/qgscompositionwidget.h +++ b/src/app/composer/qgscompositionwidget.h @@ -54,7 +54,7 @@ class QgsCompositionWidget: public QWidget, private Ui::QgsCompositionWidgetBase void on_mResolutionSpinBox_valueChanged( const int value ); void on_mPrintAsRasterCheckBox_toggled( bool state ); void on_mGenerateWorldFileCheckBox_toggled( bool state ); - void on_mWorldFileMapComboBox_currentIndexChanged( int index ); + void worldFileMapChanged( const QgsComposerItem* ); void on_mGridResolutionSpinBox_valueChanged( double d ); void on_mOffsetXSpinBox_valueChanged( double d ); @@ -73,10 +73,6 @@ class QgsCompositionWidget: public QWidget, private Ui::QgsCompositionWidgetBase void pageOrientationChanged( const QString& orientation ); private slots: - /* when a new map is added */ - void onComposerMapAdded( QgsComposerMap* ); - /* when a map is deleted */ - void onItemRemoved( QgsComposerItem* ); /** Must be called when a data defined button changes*/ void updateDataDefinedProperty(); diff --git a/src/core/composer/qgscomposermodel.cpp b/src/core/composer/qgscomposermodel.cpp index 1e6432edce1..8dc113a5339 100644 --- a/src/core/composer/qgscomposermodel.cpp +++ b/src/core/composer/qgscomposermodel.cpp @@ -18,7 +18,6 @@ #include "qgsapplication.h" #include "qgscomposermodel.h" #include "qgscomposition.h" -#include "qgscomposeritem.h" #include "qgspaperitem.h" #include "qgslogger.h" #include @@ -158,6 +157,9 @@ QVariant QgsComposerModel::data( const QModelIndex &index, int role ) const case Qt::UserRole: //store item uuid in userrole so we can later get the QModelIndex for a specific item return item->uuid(); + case Qt::UserRole+1: + //user role stores reference in column object + return qVariantFromValue( qobject_cast( item ) ); case Qt::TextAlignmentRole: return Qt::AlignLeft & Qt::AlignVCenter; @@ -208,19 +210,16 @@ bool QgsComposerModel::setData( const QModelIndex & index, const QVariant & valu case Visibility: //first column is item visibility item->setVisibility( value.toBool() ); - emit dataChanged( index, index ); return true; case LockStatus: //second column is item lock state item->setPositionLock( value.toBool() ); - emit dataChanged( index, index ); return true; case ItemId: //last column is item id item->setId( value.toString() ); - emit dataChanged( index, index ); return true; } @@ -945,3 +944,82 @@ void QgsComposerModel::setSelected( const QModelIndex &index ) mComposition->setSelectedItem( item ); } + + +// +// QgsComposerFilteredModel +// + +QgsComposerProxyModel::QgsComposerProxyModel( QgsComposition *composition, QObject *parent ) + : QSortFilterProxyModel( parent ) + , mComposition( composition ) + , mItemTypeFilter( QgsComposerItem::ComposerItem ) +{ + if ( mComposition ) + setSourceModel( mComposition->itemsModel() ); + + // TODO doesn't seem to work correctly - not updated when item changes + setDynamicSortFilter( true ); + setSortLocaleAware( true ); + sort( QgsComposerModel::ItemId ); +} + +bool QgsComposerProxyModel::lessThan( const QModelIndex &left, const QModelIndex &right ) const +{ + //sort by item id + const QgsComposerItem* item1 = itemFromSourceIndex( left ); + const QgsComposerItem* item2 = itemFromSourceIndex( right ); + if ( !item1 ) + return false; + + if ( !item2 ) + return true; + + return QString::localeAwareCompare( item1->displayName(), item2->displayName() ) < 0; +} + +QgsComposerItem* QgsComposerProxyModel::itemFromSourceIndex( const QModelIndex &sourceIndex ) const +{ + if ( !mComposition ) + return nullptr; + + //get column corresponding to an index from the source model + QVariant itemAsVariant = sourceModel()->data( sourceIndex, Qt::UserRole + 1 ); + return qobject_cast( itemAsVariant.value() ); +} + +void QgsComposerProxyModel::setFilterType( QgsComposerItem::ItemType itemType ) +{ + mItemTypeFilter = itemType; + invalidate(); +} + +void QgsComposerProxyModel::setExceptedItemList( const QList< QgsComposerItem*>& exceptList ) +{ + if ( mExceptedList == exceptList ) + return; + + mExceptedList = exceptList; + invalidateFilter(); +} + +bool QgsComposerProxyModel::filterAcceptsRow( int source_row, const QModelIndex &source_parent ) const +{ + //get QgsComposerItem corresponding to row + QModelIndex index = sourceModel()->index( source_row, 0, source_parent ); + QgsComposerItem* item = itemFromSourceIndex( index ); + + if ( !item ) + return false; + + // specific exceptions + if ( mExceptedList.contains( item ) ) + return false; + + // filter by type + if ( mItemTypeFilter != QgsComposerItem::ComposerItem && item->type() != mItemTypeFilter ) + return false; + + return true; +} + diff --git a/src/core/composer/qgscomposermodel.h b/src/core/composer/qgscomposermodel.h index ef5053a0a9f..4cd212d53b9 100644 --- a/src/core/composer/qgscomposermodel.h +++ b/src/core/composer/qgscomposermodel.h @@ -19,11 +19,12 @@ #define QGSCOMPOSERMODEL_H #include +#include #include #include +#include "qgscomposeritem.h" class QgsComposition; -class QgsComposerItem; class QGraphicsItem; /** @@ -50,6 +51,14 @@ class CORE_EXPORT QgsComposerModel: public QAbstractItemModel public: + //! Columns returned by the model + enum Columns + { + Visibility = 0, /*!< Item visibility check box */ + LockStatus, /*!< Item lock status check box */ + ItemId, /*!< Item ID */ + }; + /** Constructor * @param composition composition to attach to * @param parent parent object @@ -229,6 +238,13 @@ class CORE_EXPORT QgsComposerModel: public QAbstractItemModel */ void updateItemSelectStatus( QgsComposerItem *item ); + /** Returns the QModelIndex corresponding to a QgsComposerItem, if possible + * @param item QgsComposerItem to find index for + * @param column column number for created QModelIndex + * @returns QModelIndex corresponding to item and specified column + */ + QModelIndex indexForItem( QgsComposerItem *item, const int column = 0 ); + public slots: /** Sets an item as the current selection from a QModelIndex @@ -247,13 +263,6 @@ class CORE_EXPORT QgsComposerModel: public QAbstractItemModel private: - enum Columns - { - Visibility = 0, - LockStatus, - ItemId - }; - /** Parent composition*/ QgsComposition* mComposition; @@ -263,13 +272,6 @@ class CORE_EXPORT QgsComposerModel: public QAbstractItemModel */ QgsComposerItem* itemFromIndex( const QModelIndex &index ) const; - /** Returns the QModelIndex corresponding to a QgsComposerItem, if possible - * @param item QgsComposerItem to find index for - * @param column column number for created QModelIndex - * @returns QModelIndex corresponding to item and specified column - */ - QModelIndex indexForItem( QgsComposerItem *item, const int column = 0 ); - /** Rebuilds the list of all composer items which are present in the composition. This is * called when the stacking of order changes or when items are removed/restored to the * composition. Unlike rebuildSceneItemList, this method clears the existing scene item @@ -289,4 +291,71 @@ class CORE_EXPORT QgsComposerModel: public QAbstractItemModel friend class TestQgsComposerModel; }; + +/** + * /class QgsComposerProxyModel + * /ingroup core + * /brief Allows for filtering a QgsComposerModel by item type. + * /note added in 2.16 + */ +class CORE_EXPORT QgsComposerProxyModel: public QSortFilterProxyModel +{ + Q_OBJECT + + public: + + /** Constructor for QgsComposerProxyModel. + * @param composition composition to attach model to + * @param parent optional parent + */ + QgsComposerProxyModel( QgsComposition* composition, QObject *parent = nullptr ); + + /** Returns the current item type filter, or QgsComposerItem::ComposerItem if no + * item type filter is set. + * @see setFilterType() + */ + QgsComposerItem::ItemType filterType() const { return mItemTypeFilter; } + + /** Sets the item type filter. Only matching item types will be shown. + * @param itemType type to filter. Set to QgsComposerItem::ComposerItem to show all + * item types. + * @see filterType() + */ + void setFilterType( QgsComposerItem::ItemType itemType ); + + /** Sets a list of specific items to exclude from the model + * @param exceptList list of items to exclude + * @see exceptedItemList() + */ + void setExceptedItemList( const QList< QgsComposerItem* >& exceptList ); + + /** Returns the list of specific items excluded from the model. + * @see setExceptedItemList() + */ + QList< QgsComposerItem* > exceptedItemList() const { return mExceptedList; } + + /** Returns the QgsComposerModel used in this proxy model. + */ + QgsComposerModel* sourceLayerModel() const { return static_cast< QgsComposerModel* >( sourceModel() ); } + + /** Returns the QgsComposerItem corresponding to an index from the source + * QgsComposerModel model. + * @param sourceIndex a QModelIndex + * @returns QgsComposerItem for specified index from QgsComposerModel + */ + QgsComposerItem* itemFromSourceIndex( const QModelIndex& sourceIndex ) const; + + protected: + bool filterAcceptsRow( int source_row, const QModelIndex & source_parent ) const override; + bool lessThan( const QModelIndex &left, const QModelIndex &right ) const override; + + private: + QgsComposition* mComposition; + QgsComposerItem::ItemType mItemTypeFilter; + QList< QgsComposerItem* > mExceptedList; + +}; + + + #endif //QGSCOMPOSERMODEL diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index a5837d62eca..7e40579b117 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -174,6 +174,7 @@ SET(QGIS_GUI_SRCS qgscolorschemelist.cpp qgscolorswatchgrid.cpp qgscolorwidgets.cpp + qgscomposeritemcombobox.cpp qgscomposerruler.cpp qgscomposerview.cpp qgscredentialdialog.cpp @@ -317,6 +318,7 @@ SET(QGIS_GUI_MOC_HDRS qgscolorschemelist.h qgscolorswatchgrid.h qgscolorwidgets.h + qgscomposeritemcombobox.h qgscomposerruler.h qgscomposerview.h qgscredentialdialog.h diff --git a/src/gui/qgscomposeritemcombobox.cpp b/src/gui/qgscomposeritemcombobox.cpp new file mode 100644 index 00000000000..06155d39174 --- /dev/null +++ b/src/gui/qgscomposeritemcombobox.cpp @@ -0,0 +1,120 @@ +/*************************************************************************** + qgscomposeritemcombobox.cpp + -------------------------------------- + Date : August 2014 + Copyright : (C) 2014 Nyall Dawson + Email : nyall dot dawson at gmail dot 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 "qgscomposeritemcombobox.h" +#include "qgscomposermodel.h" + +QgsComposerItemComboBox::QgsComposerItemComboBox( QWidget *parent, QgsComposition* composition ) + : QComboBox( parent ) + , mProxyModel( nullptr ) +{ + setComposition( composition ); + + setModelColumn( QgsComposerModel::ItemId ); + connect( this, SIGNAL( activated( int ) ), this, SLOT( indexChanged( int ) ) ); + connect( mProxyModel, SIGNAL( rowsInserted( QModelIndex, int, int ) ), this, SLOT( rowsChanged() ) ); + connect( mProxyModel, SIGNAL( rowsRemoved( QModelIndex, int, int ) ), this, SLOT( rowsChanged() ) ); +} + +void QgsComposerItemComboBox::setComposition( QgsComposition *composition ) +{ + delete mProxyModel; + mProxyModel = new QgsComposerProxyModel( composition, this ); + connect( mProxyModel, SIGNAL( rowsInserted( QModelIndex, int, int ) ), this, SLOT( rowsChanged() ) ); + connect( mProxyModel, SIGNAL( rowsRemoved( QModelIndex, int, int ) ), this, SLOT( rowsChanged() ) ); + setModel( mProxyModel ); + setModelColumn( QgsComposerModel::ItemId ); + mProxyModel->sort( 0, Qt::AscendingOrder ); +} + +void QgsComposerItemComboBox::setItem( const QgsComposerItem* item ) +{ + if ( !mProxyModel->sourceLayerModel() ) + return; + + QModelIndex idx = mProxyModel->sourceLayerModel()->indexForItem( const_cast< QgsComposerItem* >( item ) ); + if ( idx.isValid() ) + { + QModelIndex proxyIdx = mProxyModel->mapFromSource( idx ); + if ( proxyIdx.isValid() ) + { + setCurrentIndex( proxyIdx.row() ); + emit itemChanged( currentItem() ); + return; + } + } + setCurrentIndex( -1 ); + emit itemChanged( currentItem() ); +} + +QgsComposerItem* QgsComposerItemComboBox::currentItem() const +{ + return item( currentIndex() ); +} + +void QgsComposerItemComboBox::indexChanged( int i ) +{ + Q_UNUSED( i ); + emit itemChanged( currentItem() ); +} + +void QgsComposerItemComboBox::rowsChanged() +{ + if ( count() == 1 ) + { + //currently selected item has changed + emit itemChanged( currentItem() ); + } + else if ( count() == 0 ) + { + emit itemChanged( nullptr ); + } +} + +void QgsComposerItemComboBox::setItemType( QgsComposerItem::ItemType itemType ) +{ + mProxyModel->setFilterType( itemType ); +} + +QgsComposerItem::ItemType QgsComposerItemComboBox::itemType() const +{ + return mProxyModel->filterType(); +} + +void QgsComposerItemComboBox::setExceptedItemList( const QList< QgsComposerItem*>& exceptList ) +{ + mProxyModel->setExceptedItemList( exceptList ); +} + +QList< QgsComposerItem*> QgsComposerItemComboBox::exceptedItemList() const +{ + return mProxyModel->exceptedItemList(); +} + QgsComposerItem* QgsComposerItemComboBox::item( int index ) const +{ + const QModelIndex proxyIndex = mProxyModel->index( index, 0 ); + if ( !proxyIndex.isValid() ) + { + return nullptr; + } + + QModelIndex sourceIndex = mProxyModel->mapToSource( proxyIndex ); + if ( !sourceIndex.isValid() ) + { + return nullptr; + } + + return mProxyModel->itemFromSourceIndex( sourceIndex ); +} diff --git a/src/gui/qgscomposeritemcombobox.h b/src/gui/qgscomposeritemcombobox.h new file mode 100644 index 00000000000..68eb5cb4ae7 --- /dev/null +++ b/src/gui/qgscomposeritemcombobox.h @@ -0,0 +1,102 @@ +/*************************************************************************** + qgscomposeritemcombobox.h + -------------------------------------- + Date : August 2014 + Copyright : (C) 2014 Nyall Dawson + Email : nyall dot dawson at gmail dot 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 QGSCOMPOSERITEMCOMBOBOX_H +#define QGSCOMPOSERITEMCOMBOBOX_H + +#include +#include "qgscomposeritem.h" + +class QgsComposerProxyModel; + +/** + * /class QgsComposerItemComboBox + * /ingroup gui + * /brief The QgsComposerItemComboBox class is a combo box which displays items of + * a matching type from a composition. + * /note added in 2.16 + */ +class GUI_EXPORT QgsComposerItemComboBox : public QComboBox +{ + Q_OBJECT + + public: + /** + * QgsComposerItemComboBox creates a combo box to display a list of items in a + * composition. The items can optionally be filtered by type. + * @param parent parent widget + * @param composition composition to show items from. If not set, no items will be shown + * until setComposition() is called + */ + explicit QgsComposerItemComboBox( QWidget* parent = nullptr, QgsComposition* composition = nullptr ); + + /** Sets the composition containing the items to list in the combo box. + */ + void setComposition( QgsComposition* composition ); + + /** Sets a filter for the item type to show in the combo box. + * @param itemType type of items to show. Set to QgsComposerItem::ComposerItem to + * show all items. + * @see itemType() + */ + void setItemType( QgsComposerItem::ItemType itemType ); + + /** Returns the filter for the item types to show in the combo box. + * @see setItemType() + */ + QgsComposerItem::ItemType itemType() const; + + /** Sets a list of specific items to exclude from the combo box. + * @param exceptList list of items to exclude + * @see exceptedItemList() + */ + void setExceptedItemList( const QList< QgsComposerItem* >& exceptList ); + + /** Returns the list of specific items excluded from the combo box. + * @see setExceptedItemList() + */ + QList< QgsComposerItem* > exceptedItemList() const; + + /** Return the item currently shown at the specified index within the combo box. + * @param index position of item to return + * @see currentItem() + */ + QgsComposerItem* item( int index ) const; + + /** Returns the item currently selected in the combo box. + */ + QgsComposerItem* currentItem() const; + + public slots: + /** Sets the currently selected item in the combo box. + * @param item selected item + */ + void setItem( const QgsComposerItem* item ); + + signals: + + //! Emitted whenever the currently selected item changes + void itemChanged( QgsComposerItem* item ); + + private slots: + void indexChanged( int i ); + void rowsChanged(); + + private: + QgsComposerProxyModel* mProxyModel; + +}; + +#endif // QGSCOMPOSERITEMCOMBOBOX_H diff --git a/src/ui/composer/qgscomposerattributetablewidgetbase.ui b/src/ui/composer/qgscomposerattributetablewidgetbase.ui index 98caf589ecf..dc26c1d5edb 100644 --- a/src/ui/composer/qgscomposerattributetablewidgetbase.ui +++ b/src/ui/composer/qgscomposerattributetablewidgetbase.ui @@ -54,9 +54,9 @@ 0 - -499 - 392 - 1291 + 0 + 391 + 1102 @@ -198,7 +198,7 @@ - + @@ -790,6 +790,11 @@ QSpinBox
qgsspinbox.h
+ + QgsComposerItemComboBox + QComboBox +
qgscomposeritemcombobox.h
+
scrollArea diff --git a/src/ui/composer/qgscomposerlegendwidgetbase.ui b/src/ui/composer/qgscomposerlegendwidgetbase.ui index 5c8b6f9e168..9d5ec5b60c9 100644 --- a/src/ui/composer/qgscomposerlegendwidgetbase.ui +++ b/src/ui/composer/qgscomposerlegendwidgetbase.ui @@ -64,8 +64,8 @@ 0 0 - 375 - 1478 + 374 + 1293 @@ -111,7 +111,7 @@
- + @@ -992,7 +992,7 @@ QgsCollapsibleGroupBoxBasic QGroupBox -
qgscollapsiblegroupbox.h
+
qgscollapsiblegroupbox.h
1
@@ -1011,6 +1011,11 @@ QSpinBox
qgsspinbox.h
+ + QgsComposerItemComboBox + QComboBox +
qgscomposeritemcombobox.h
+
QgsLayerTreeView QTreeView diff --git a/src/ui/composer/qgscomposermapwidgetbase.ui b/src/ui/composer/qgscomposermapwidgetbase.ui index 265b9442f3c..a22b87b95a6 100644 --- a/src/ui/composer/qgscomposermapwidgetbase.ui +++ b/src/ui/composer/qgscomposermapwidgetbase.ui @@ -23,7 +23,16 @@ 0 - + + 0 + + + 0 + + + 0 + + 0 @@ -54,9 +63,9 @@ 0 - -1446 - 444 - 2493 + -1044 + 438 + 2111 @@ -1350,7 +1359,7 @@
- + @@ -1436,6 +1445,11 @@ QComboBox
qgsblendmodecombobox.h
+ + QgsComposerItemComboBox + QComboBox +
qgscomposeritemcombobox.h
+
scrollArea diff --git a/src/ui/composer/qgscomposerpicturewidgetbase.ui b/src/ui/composer/qgscomposerpicturewidgetbase.ui index 0f694465caf..338d8a9a786 100644 --- a/src/ui/composer/qgscomposerpicturewidgetbase.ui +++ b/src/ui/composer/qgscomposerpicturewidgetbase.ui @@ -60,9 +60,9 @@ 0 - 0 - 314 - 805 + -166 + 313 + 719 @@ -471,7 +471,7 @@
- + @@ -501,9 +501,10 @@ 1 - QgsDataDefinedButton + QgsColorButtonV2 QToolButton -
qgsdatadefinedbutton.h
+
qgscolorbuttonv2.h
+ 1
QgsDoubleSpinBox @@ -511,10 +512,14 @@
qgsdoublespinbox.h
- QgsColorButtonV2 + QgsDataDefinedButton QToolButton -
qgscolorbuttonv2.h
- 1 +
qgsdatadefinedbutton.h
+
+ + QgsComposerItemComboBox + QComboBox +
qgscomposeritemcombobox.h
diff --git a/src/ui/composer/qgscomposerscalebarwidgetbase.ui b/src/ui/composer/qgscomposerscalebarwidgetbase.ui index a706a06e90c..2a44102e4a3 100644 --- a/src/ui/composer/qgscomposerscalebarwidgetbase.ui +++ b/src/ui/composer/qgscomposerscalebarwidgetbase.ui @@ -61,8 +61,8 @@ 0 0 - 438 - 914 + 437 + 768 @@ -80,7 +80,23 @@ false - + + + + + + + + + + + St&yle + + + mStyleComboBox + + + @@ -96,36 +112,10 @@ true - mMapComboBox + mMapItemComboBox - - - - true - - - - 0 - 0 - - - - - - - - St&yle - - - mStyleComboBox - - - - - -
@@ -706,11 +696,16 @@
qgscollapsiblegroupbox.h
1 + + QgsComposerItemComboBox + QComboBox +
qgscomposeritemcombobox.h
+
scrollArea groupBox - mMapComboBox + mMapItemComboBox mStyleComboBox mGroupBoxUnits mUnitsComboBox diff --git a/src/ui/composer/qgscompositionwidgetbase.ui b/src/ui/composer/qgscompositionwidgetbase.ui index 262ca55aa82..be63f0186dc 100644 --- a/src/ui/composer/qgscompositionwidgetbase.ui +++ b/src/ui/composer/qgscompositionwidgetbase.ui @@ -59,9 +59,9 @@ 0 - 0 - 327 - 1085 + -445 + 326 + 949 @@ -462,7 +462,7 @@ - + false @@ -648,22 +648,11 @@ - QgsCollapsibleGroupBox + QgsCollapsibleGroupBoxBasic QGroupBox
qgscollapsiblegroupbox.h
1
- - QgsVariableEditorWidget - QWidget -
qgsvariableeditorwidget.h
- 1 -
- - QgsDataDefinedButton - QToolButton -
qgsdatadefinedbutton.h
-
QgsDoubleSpinBox QDoubleSpinBox @@ -675,9 +664,25 @@
qgsspinbox.h
- QgsCollapsibleGroupBoxBasic + QgsComposerItemComboBox + QComboBox +
qgscomposeritemcombobox.h
+
+ + QgsDataDefinedButton + QToolButton +
qgsdatadefinedbutton.h
+
+ + QgsCollapsibleGroupBox QGroupBox -
qgscollapsiblegroupbox.h
+
qgscollapsiblegroupbox.h
+ 1 +
+ + QgsVariableEditorWidget + QWidget +
qgsvariableeditorwidget.h
1