Showing with 185 additions and 4 deletions.
  1. +18 −0 src/app/composer/qgscomposer.cpp
  2. +6 −0 src/app/composer/qgscomposer.h
  3. +91 −2 src/core/composer/qgscomposition.cpp
  4. +16 −0 src/core/composer/qgscomposition.h
  5. +32 −2 src/gui/qgscomposerview.cpp
  6. +22 −0 src/ui/qgscomposerbase.ui
18 changes: 18 additions & 0 deletions src/app/composer/qgscomposer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,8 @@ QgsComposer::QgsComposer( QgisApp *qgis, const QString& title )
editMenu->addAction( mActionSelectAll );
editMenu->addAction( mActionDeselectAll );
editMenu->addAction( mActionInvertSelection );
editMenu->addAction( mActionSelectNextBelow );
editMenu->addAction( mActionSelectNextAbove );

QMenu *viewMenu = menuBar()->addMenu( tr( "View" ) );
viewMenu->addAction( mActionZoomIn );
Expand Down Expand Up @@ -1779,6 +1781,22 @@ void QgsComposer::on_mActionInvertSelection_triggered()
}
}

void QgsComposer::on_mActionSelectNextAbove_triggered()
{
if ( mComposition )
{
mComposition->selectNextByZOrder( QgsComposition::ZValueAbove );
}
}

void QgsComposer::on_mActionSelectNextBelow_triggered()
{
if ( mComposition )
{
mComposition->selectNextByZOrder( QgsComposition::ZValueBelow );
}
}

void QgsComposer::on_mActionRaiseItems_triggered()
{
if ( mComposition )
Expand Down
6 changes: 6 additions & 0 deletions src/app/composer/qgscomposer.h
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,12 @@ class QgsComposer: public QMainWindow, private Ui::QgsComposerBase
//! Unlock all items
void on_mActionUnlockAll_triggered();

//! Select next item below
void on_mActionSelectNextAbove_triggered();

//! Select next item above
void on_mActionSelectNextBelow_triggered();

//! Move selected items one position up
void on_mActionRaiseItems_triggered();

Expand Down
93 changes: 91 additions & 2 deletions src/core/composer/qgscomposition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,10 +170,16 @@ int QgsComposition::numPages() const

QgsComposerItem* QgsComposition::composerItemAt( const QPointF & position )
{
return composerItemAt( position, 0 );
}

QgsComposerItem* QgsComposition::composerItemAt( const QPointF & position, const QgsComposerItem* belowItem )
{
//get a list of items which intersect the specified position, in descending z order
QList<QGraphicsItem*> itemList;
if ( mSelectionTolerance <= 0.0 )
{
itemList = items( position );
itemList = items( position, Qt::IntersectsItemShape, Qt::DescendingOrder );
}
else
{
Expand All @@ -182,13 +188,27 @@ QgsComposerItem* QgsComposition::composerItemAt( const QPointF & position )
}
QList<QGraphicsItem *>::iterator itemIt = itemList.begin();

bool foundBelowItem = false;
for ( ; itemIt != itemList.end(); ++itemIt )
{
QgsComposerItem* composerItem = dynamic_cast<QgsComposerItem *>( *itemIt );
QgsPaperItem* paperItem = dynamic_cast<QgsPaperItem*>( *itemIt );
if ( composerItem && !paperItem )
{
return composerItem;
// If we are not checking for a an item below a specified item, or if we've
// already found that item, then we've found our target
if ( ! belowItem || foundBelowItem )
{
return composerItem;
}
else
{
if ( composerItem == belowItem )
{
//Target item is next in list
foundBelowItem = true;
}
}
}
}
return 0;
Expand Down Expand Up @@ -887,6 +907,75 @@ void QgsComposition::raiseItem( QgsComposerItem* item )
}
}

QgsComposerItem* QgsComposition::getComposerItemAbove( QgsComposerItem* item )
{
//search item z list for selected item
QLinkedListIterator<QgsComposerItem*> it( mItemZList );
if ( it.findNext( item ) )
{
//return next item (list is sorted from lowest->highest items)
if ( it.hasNext() )
{
return it.next();
}
}
return 0;
}

QgsComposerItem* QgsComposition::getComposerItemBelow( QgsComposerItem* item )
{
//search item z list for selected item
QLinkedListIterator<QgsComposerItem*> it( mItemZList );
if ( it.findNext( item ) )
{
//move position to before selected item
it.previous();
//now find previous item, since list is sorted from lowest->highest items
if ( it.hasPrevious() )
{
return it.previous();
}
}
return 0;
}

void QgsComposition::selectNextByZOrder( ZValueDirection direction )
{
QgsComposerItem* previousSelectedItem = 0;
QList<QgsComposerItem*> selectedItems = selectedComposerItems();
if ( selectedItems.size() > 0 )
{
previousSelectedItem = selectedItems.at( 0 );
}

if ( !previousSelectedItem )
{
return;
}

//select item with target z value
QgsComposerItem* selectedItem;
switch ( direction )
{
case QgsComposition::ZValueBelow:
selectedItem = getComposerItemBelow( previousSelectedItem );
break;
case QgsComposition::ZValueAbove:
selectedItem = getComposerItemAbove( previousSelectedItem );
break;
}

if ( !selectedItem )
{
return;
}

//ok, found a good target item
clearSelection();
selectedItem->setSelected( true );
emit selectedItemChanged( selectedItem );
}

void QgsComposition::lowerSelectedItems()
{
QList<QgsComposerItem*> selectedItems = selectedComposerItems();
Expand Down
16 changes: 16 additions & 0 deletions src/core/composer/qgscomposition.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ class CORE_EXPORT QgsComposition : public QGraphicsScene
Crosses
};

enum ZValueDirection
{
ZValueBelow,
ZValueAbove
};

QgsComposition( QgsMapRenderer* mapRenderer );
~QgsComposition();

Expand Down Expand Up @@ -131,6 +137,11 @@ class CORE_EXPORT QgsComposition : public QGraphicsScene
/**Returns the topmost composer item. Ignores mPaperItem*/
QgsComposerItem* composerItemAt( const QPointF & position );

/**Returns the highest composer item at a specified position which is below a specified item. Ignores mPaperItem
@note Added in QGIS 2.1
*/
QgsComposerItem* composerItemAt( const QPointF & position, const QgsComposerItem* belowItem );

/** Returns the page number (0-bsaed) given a coordinate */
int pageNumberAt( const QPointF& position ) const;

Expand Down Expand Up @@ -252,6 +263,11 @@ class CORE_EXPORT QgsComposition : public QGraphicsScene
void moveSelectedItemsToBottom();
void moveItemToBottom( QgsComposerItem* item );

//functions to find items by their position in the z list
void selectNextByZOrder( ZValueDirection direction );
QgsComposerItem* getComposerItemBelow( QgsComposerItem* item );
QgsComposerItem* getComposerItemAbove( QgsComposerItem* item );

//functions to align selected items
void alignSelectedItemsLeft();
void alignSelectedItemsHCenter();
Expand Down
34 changes: 32 additions & 2 deletions src/gui/qgscomposerview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,43 @@ void QgsComposerView::mousePressEvent( QMouseEvent* e )
//select/deselect items and pass mouse event further
case Select:
{
QgsComposerItem* selectedItem;
QgsComposerItem* previousSelectedItem = 0;

if ( e->modifiers() & Qt::ControlModifier )
{
//CTRL modifier, so we are trying to select the next item below the current one
//first, find currently selected item
QList<QgsComposerItem*> selectedItems = composition()->selectedComposerItems();
if ( selectedItems.size() > 0 )
{
previousSelectedItem = selectedItems.at( 0 );
}
}

if ( !( e->modifiers() & Qt::ShiftModifier ) ) //keep selection if shift key pressed
{
composition()->clearSelection();
}

//select topmost item at position of event
QgsComposerItem* selectedItem = composition()->composerItemAt( scenePoint );
if ( previousSelectedItem )
{
//select highest item just below previously selected item at position of event
selectedItem = composition()->composerItemAt( scenePoint, previousSelectedItem );

//if we didn't find a lower item we'll use the top-most as fall-back
//this duplicates mapinfo/illustrator/etc behaviour where ctrl-clicks are "cyclic"
if ( !selectedItem )
{
selectedItem = composition()->composerItemAt( scenePoint );
}
}
else
{
//select topmost item at position of event
selectedItem = composition()->composerItemAt( scenePoint );
}

if ( !selectedItem )
{
break;
Expand Down
22 changes: 22 additions & 0 deletions src/ui/qgscomposerbase.ui
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,28 @@
<string>Invert selection</string>
</property>
</action>
<action name="mActionSelectNextBelow">
<property name="text">
<string>Select Next Item &amp;Below</string>
</property>
<property name="toolTip">
<string>Select next item below</string>
</property>
<property name="shortcut">
<string>Ctrl+Alt+[</string>
</property>
</action>
<action name="mActionSelectNextAbove">
<property name="text">
<string>Select Next Item &amp;Above</string>
</property>
<property name="toolTip">
<string>Select next item above</string>
</property>
<property name="shortcut">
<string>Ctrl+Alt+]</string>
</property>
</action>
</widget>
<resources>
<include location="../../images/images.qrc"/>
Expand Down