diff --git a/python/core/composer/qgscomposition.sip b/python/core/composer/qgscomposition.sip index 57a0ee33078..f07b5619c80 100644 --- a/python/core/composer/qgscomposition.sip +++ b/python/core/composer/qgscomposition.sip @@ -538,6 +538,12 @@ class QgsComposition : QGraphicsScene * @param item item to set as selected * @note added in version 2.3*/ void setSelectedItem( QgsComposerItem* item ); + + /**Clears any selected items in the composition. Call this method rather than + * QGraphicsScene::clearSelection, as the latter does not correctly emit signals to allow + * the composition's model to update. + * @note added in version 2.5*/ + void setAllUnselected(); /**Refreshes a data defined property for the composition by reevaluating the property's value * and redrawing the composition with this new value. diff --git a/src/core/composer/qgscomposeritem.cpp b/src/core/composer/qgscomposeritem.cpp index 3b81e0d1fea..75ceb05d22d 100644 --- a/src/core/composer/qgscomposeritem.cpp +++ b/src/core/composer/qgscomposeritem.cpp @@ -171,6 +171,11 @@ void QgsComposerItem::setSelected( bool s ) { QgsDebugMsg( "entered." ); QGraphicsRectItem::setSelected( s ); + //inform model that id data has changed + if ( mComposition ) + { + mComposition->itemsModel()->updateItemSelectStatus( this ); + } update(); //to draw selection boxes } diff --git a/src/core/composer/qgscomposermodel.cpp b/src/core/composer/qgscomposermodel.cpp old mode 100755 new mode 100644 index 3abdf0596b0..5876f0b8879 --- a/src/core/composer/qgscomposermodel.cpp +++ b/src/core/composer/qgscomposermodel.cpp @@ -175,6 +175,20 @@ QVariant QgsComposerModel::data( const QModelIndex &index, int role ) const return QVariant(); } + case Qt::FontRole: + if ( index.column() == ItemId && item->isSelected() ) + { + //draw name of selected items in bold + QFont boldFont; + boldFont.setBold( true ); + return boldFont; + } + else + { + return QVariant(); + } + break; + default: return QVariant(); } @@ -499,6 +513,25 @@ void QgsComposerModel::updateItemVisibility( QgsComposerItem *item ) emit dataChanged( itemIndex, itemIndex ); } +void QgsComposerModel::updateItemSelectStatus( QgsComposerItem *item ) +{ + if ( !item ) + { + //nothing to do + return; + } + + //need to get QModelIndex of item + QModelIndex itemIndex = indexForItem( item, ItemId ); + if ( !itemIndex.isValid() ) + { + return; + } + + //emit signal for item visibility change + emit dataChanged( itemIndex, itemIndex ); +} + bool QgsComposerModel::reorderItemUp( QgsComposerItem *item ) { if ( mItemsInScene.first() == item ) diff --git a/src/core/composer/qgscomposermodel.h b/src/core/composer/qgscomposermodel.h index 45d02d64954..1a6782bc967 100755 --- a/src/core/composer/qgscomposermodel.h +++ b/src/core/composer/qgscomposermodel.h @@ -192,6 +192,7 @@ class CORE_EXPORT QgsComposerModel: public QAbstractItemModel * @param item item to update * @see updateItemLockStatus * @see updateItemVisibility + * @see updateItemSelectStatus * @note added in QGIS 2.5 */ void updateItemDisplayName( QgsComposerItem *item ); @@ -200,6 +201,7 @@ class CORE_EXPORT QgsComposerModel: public QAbstractItemModel * @param item item to update * @see updateItemDisplayName * @see updateItemVisibility + * @see updateItemSelectStatus * @note added in QGIS 2.5 */ void updateItemLockStatus( QgsComposerItem *item ); @@ -208,10 +210,20 @@ class CORE_EXPORT QgsComposerModel: public QAbstractItemModel * @param item item to update * @see updateItemDisplayName * @see updateItemLockStatus + * @see updateItemSelectStatus * @note added in QGIS 2.5 */ void updateItemVisibility( QgsComposerItem *item ); + /**Must be called when an item's selection status changes + * @param item item to update + * @see updateItemDisplayName + * @see updateItemVisibility + * @see updateItemLockStatus + * @note added in QGIS 2.5 + */ + void updateItemSelectStatus( QgsComposerItem *item ); + public slots: /**Sets an item as the current selection from a QModelIndex diff --git a/src/core/composer/qgscomposition.cpp b/src/core/composer/qgscomposition.cpp index c85e60a3f51..6dc8d5f433b 100644 --- a/src/core/composer/qgscomposition.cpp +++ b/src/core/composer/qgscomposition.cpp @@ -228,11 +228,30 @@ void QgsComposition::refreshItems() void QgsComposition::setSelectedItem( QgsComposerItem *item ) { - clearSelection(); + setAllUnselected(); item->setSelected( true ); emit selectedItemChanged( item ); } +void QgsComposition::setAllUnselected() +{ + //we can't use QGraphicsScene::clearSelection, as that emits no signals + //and we don't know which items are being unselected + //accordingly, we can't inform the composition model of selection changes + //instead, do the clear selection manually... + QList selectedItemList = selectedItems(); + QList::iterator itemIter = selectedItemList.begin(); + + for ( ; itemIter != selectedItemList.end(); ++itemIter ) + { + QgsComposerItem* composerItem = dynamic_cast( *itemIter ); + if ( composerItem ) + { + composerItem->setSelected( false ); + } + } +} + void QgsComposition::refreshDataDefinedProperty( const QgsComposerObject::DataDefinedProperty property ) { //updates data defined properties and redraws composition to match @@ -982,7 +1001,7 @@ void QgsComposition::addItemsFromXML( const QDomElement& elem, const QDomDocumen pasteShiftPos = *pos - minItemPos; //since we are pasting items, clear the existing selection - clearSelection(); + setAllUnselected(); } if ( pasteInPlace ) @@ -1384,7 +1403,7 @@ void QgsComposition::selectNextByZOrder( ZValueDirection direction ) } //ok, found a good target item - clearSelection(); + setAllUnselected(); selectedItem->setSelected( true ); emit selectedItemChanged( selectedItem ); } @@ -1658,7 +1677,7 @@ void QgsComposition::lockSelectedItems() subcommand->saveAfterState(); } - clearSelection(); + setAllUnselected(); mUndoStack->push( parentCommand ); QgsProject::instance()->dirty( true ); } @@ -1670,7 +1689,7 @@ void QgsComposition::unlockAllItems() QUndoCommand* parentCommand = new QUndoCommand( tr( "Items unlocked" ) ); //first, clear the selection - clearSelection(); + setAllUnselected(); QList itemList = items(); QList::iterator itemIt = itemList.begin(); diff --git a/src/core/composer/qgscomposition.h b/src/core/composer/qgscomposition.h index e53918c420b..0c4ea66e49c 100644 --- a/src/core/composer/qgscomposition.h +++ b/src/core/composer/qgscomposition.h @@ -598,6 +598,12 @@ class CORE_EXPORT QgsComposition : public QGraphicsScene * @note added in version 2.3*/ void setSelectedItem( QgsComposerItem* item ); + /**Clears any selected items in the composition. Call this method rather than + * QGraphicsScene::clearSelection, as the latter does not correctly emit signals to allow + * the composition's model to update. + * @note added in version 2.5*/ + void setAllUnselected(); + /**Refreshes a data defined property for the composition by reevaluating the property's value * and redrawing the composition with this new value. * @param property data defined property to refresh. If property is set to diff --git a/src/gui/qgscomposerview.cpp b/src/gui/qgscomposerview.cpp index 70e59ce1336..39c31428139 100644 --- a/src/gui/qgscomposerview.cpp +++ b/src/gui/qgscomposerview.cpp @@ -233,7 +233,7 @@ void QgsComposerView::mousePressEvent( QMouseEvent* e ) if (( !selectedItem->selected() ) && //keep selection if an already selected item pressed !( e->modifiers() & Qt::ShiftModifier ) ) //keep selection if shift key pressed { - composition()->clearSelection(); + composition()->setAllUnselected(); } if (( e->modifiers() & Qt::ShiftModifier ) && ( selectedItem->selected() ) ) @@ -372,7 +372,7 @@ void QgsComposerView::mousePressEvent( QMouseEvent* e ) } newScaleBar->applyDefaultSize(); //4 segments, 1/5 of composer map width - composition()->clearSelection(); + composition()->setAllUnselected(); newScaleBar->setSelected( true ); emit selectedItemChanged( newScaleBar ); @@ -447,7 +447,7 @@ void QgsComposerView::addShape( Tool currentTool ) composition()->addComposerShape( composerShape ); removeRubberBand(); - composition()->clearSelection(); + composition()->setAllUnselected(); composerShape->setSelected( true ); emit selectedItemChanged( composerShape ); @@ -511,7 +511,7 @@ void QgsComposerView::endMarqueeSelect( QMouseEvent* e ) else { //not adding to or removing from selection, so clear current selection - composition()->clearSelection(); + composition()->setAllUnselected(); } if ( !mRubberBandItem || ( mRubberBandItem->rect().width() < 0.1 && mRubberBandItem->rect().height() < 0.1 ) ) @@ -743,7 +743,7 @@ void QgsComposerView::mouseReleaseEvent( QMouseEvent* e ) QgsComposerArrow* composerArrow = new QgsComposerArrow( mRubberBandLineItem->line().p1(), mRubberBandLineItem->line().p2(), composition() ); composition()->addComposerArrow( composerArrow ); - composition()->clearSelection(); + composition()->setAllUnselected(); composerArrow->setSelected( true ); emit selectedItemChanged( composerArrow ); @@ -772,7 +772,7 @@ void QgsComposerView::mouseReleaseEvent( QMouseEvent* e ) QgsComposerMap* composerMap = new QgsComposerMap( composition(), mRubberBandItem->transform().dx(), mRubberBandItem->transform().dy(), mRubberBandItem->rect().width(), mRubberBandItem->rect().height() ); composition()->addComposerMap( composerMap ); - composition()->clearSelection(); + composition()->setAllUnselected(); composerMap->setSelected( true ); emit selectedItemChanged( composerMap ); @@ -794,7 +794,7 @@ void QgsComposerView::mouseReleaseEvent( QMouseEvent* e ) newPicture->setSceneRect( QRectF( mRubberBandItem->transform().dx(), mRubberBandItem->transform().dy(), mRubberBandItem->rect().width(), mRubberBandItem->rect().height() ) ); composition()->addComposerPicture( newPicture ); - composition()->clearSelection(); + composition()->setAllUnselected(); newPicture->setSelected( true ); emit selectedItemChanged( newPicture ); @@ -823,7 +823,7 @@ void QgsComposerView::mouseReleaseEvent( QMouseEvent* e ) composition()->addComposerLabel( newLabelItem ); - composition()->clearSelection(); + composition()->setAllUnselected(); newLabelItem->setSelected( true ); emit selectedItemChanged( newLabelItem ); @@ -846,7 +846,7 @@ void QgsComposerView::mouseReleaseEvent( QMouseEvent* e ) composition()->addComposerLegend( newLegend ); newLegend->updateLegend(); - composition()->clearSelection(); + composition()->setAllUnselected(); newLegend->setSelected( true ); emit selectedItemChanged( newLegend ); @@ -873,7 +873,7 @@ void QgsComposerView::mouseReleaseEvent( QMouseEvent* e ) } composition()->addComposerTable( newTable ); - composition()->clearSelection(); + composition()->setAllUnselected(); newTable->setSelected( true ); emit selectedItemChanged( newTable ); @@ -902,7 +902,7 @@ void QgsComposerView::mouseReleaseEvent( QMouseEvent* e ) composerHtml->addFrame( frame ); composition()->endMultiFrameCommand(); - composition()->clearSelection(); + composition()->setAllUnselected(); frame->setSelected( true ); emit selectedItemChanged( frame ); @@ -1263,7 +1263,7 @@ void QgsComposerView::selectNone() return; } - composition()->clearSelection(); + composition()->setAllUnselected(); } void QgsComposerView::selectInvert()