Port select next above/below actions

This commit is contained in:
Nyall Dawson 2017-10-03 15:06:47 +10:00
parent dbb31253e9
commit 4cba2b90ef
7 changed files with 234 additions and 0 deletions

View File

@ -177,6 +177,8 @@ class QgsLayoutView: QGraphicsView
Selects all items in the view.
.. seealso:: deselectAll()
.. seealso:: invertSelection()
.. seealso:: selectNextItemAbove()
.. seealso:: selectNextItemBelow()
%End
void deselectAll();
@ -192,6 +194,22 @@ class QgsLayoutView: QGraphicsView
and deselecting and selected items.
.. seealso:: selectAll()
.. seealso:: deselectAll()
%End
void selectNextItemAbove();
%Docstring
Selects the next item above the existing selection, by item z order.
.. seealso:: selectNextItemBelow()
.. seealso:: selectAll()
.. seealso:: deselectAll()
%End
void selectNextItemBelow();
%Docstring
Selects the next item below the existing selection, by item z order.
.. seealso:: selectNextItemAbove()
.. seealso:: selectAll()
.. seealso:: deselectAll()
%End
void viewChanged();

View File

@ -194,9 +194,14 @@ QgsLayoutDesignerDialog::QgsLayoutDesignerDialog( QWidget *parent, Qt::WindowFla
connect( mActionSelectAll, &QAction::triggered, mView, &QgsLayoutView::selectAll );
connect( mActionDeselectAll, &QAction::triggered, mView, &QgsLayoutView::deselectAll );
connect( mActionInvertSelection, &QAction::triggered, mView, &QgsLayoutView::invertSelection );
connect( mActionSelectNextAbove, &QAction::triggered, mView, &QgsLayoutView::selectNextItemAbove );
connect( mActionSelectNextBelow, &QAction::triggered, mView, &QgsLayoutView::selectNextItemBelow );
connect( mActionAddPages, &QAction::triggered, this, &QgsLayoutDesignerDialog::addPages );
connect( mActionUnlockAll, &QAction::triggered, this, &QgsLayoutDesignerDialog::unlockAllItems );
connect( mActionLockItems, &QAction::triggered, this, &QgsLayoutDesignerDialog::lockSelectedItems );
//create status bar labels
mStatusCursorXLabel = new QLabel( mStatusBar );
mStatusCursorXLabel->setMinimumWidth( 100 );
@ -477,6 +482,22 @@ void QgsLayoutDesignerDialog::snapToItems( bool enabled )
mLayout->snapper().setSnapToItems( enabled );
}
void QgsLayoutDesignerDialog::unlockAllItems()
{
if ( mLayout )
{
mLayout->unlockAllItems();
}
}
void QgsLayoutDesignerDialog::lockSelectedItems()
{
if ( mLayout )
{
mLayout->lockSelectedItems();
}
}
void QgsLayoutDesignerDialog::closeEvent( QCloseEvent * )
{
emit aboutToClose();

View File

@ -149,6 +149,18 @@ class QgsLayoutDesignerDialog: public QMainWindow, private Ui::QgsLayoutDesigner
*/
void snapToItems( bool enabled );
/**
* Unlocks all locked items in the layout.
* \see lockSelectedItems()
*/
void unlockAllItems();
/**
* Locks any selected items in the layout.
* \see unlockAllItems()
*/
void lockSelectedItems();
signals:
/**

View File

@ -24,6 +24,7 @@
#include "qgslayoutviewtooltemporarymousepan.h"
#include "qgslayoutmousehandles.h"
#include "qgslayoutruler.h"
#include "qgslayoutmodel.h"
#include "qgssettings.h"
#include "qgsrectangle.h"
#include "qgsapplication.h"
@ -353,6 +354,50 @@ void QgsLayoutView::invertSelection()
emit itemFocused( focusedItem );
}
void selectNextByZOrder( QgsLayout *layout, bool above )
{
if ( !layout )
return;
QgsLayoutItem *previousSelectedItem = nullptr;
const QList<QgsLayoutItem *> selectedItems = layout->selectedLayoutItems();
if ( !selectedItems.isEmpty() )
{
previousSelectedItem = selectedItems.at( 0 );
}
if ( !previousSelectedItem )
{
return;
}
//select item with target z value
QgsLayoutItem *selectedItem = nullptr;
if ( !above )
selectedItem = layout->itemsModel()->findItemBelow( previousSelectedItem );
else
selectedItem = layout->itemsModel()->findItemAbove( previousSelectedItem );
if ( !selectedItem )
{
return;
}
//OK, found a good target item
layout->setSelectedItem( selectedItem );
}
void QgsLayoutView::selectNextItemAbove()
{
selectNextByZOrder( currentLayout(), true );
}
void QgsLayoutView::selectNextItemBelow()
{
selectNextByZOrder( currentLayout(), false );
}
void QgsLayoutView::mousePressEvent( QMouseEvent *event )
{
mSnapMarker->setVisible( false );

View File

@ -219,6 +219,8 @@ class GUI_EXPORT QgsLayoutView: public QGraphicsView
* Selects all items in the view.
* \see deselectAll()
* \see invertSelection()
* \see selectNextItemAbove()
* \see selectNextItemBelow()
*/
void selectAll();
@ -237,6 +239,22 @@ class GUI_EXPORT QgsLayoutView: public QGraphicsView
*/
void invertSelection();
/**
* Selects the next item above the existing selection, by item z order.
* \see selectNextItemBelow()
* \see selectAll()
* \see deselectAll()
*/
void selectNextItemAbove();
/**
* Selects the next item below the existing selection, by item z order.
* \see selectNextItemAbove()
* \see selectAll()
* \see deselectAll()
*/
void selectNextItemBelow();
/**
* Updates associated rulers and other widgets after view extent or zoom has changed.
* This should be called after calling any of the QGraphicsView

View File

@ -151,9 +151,17 @@
<addaction name="mActionSelectNextBelow"/>
<addaction name="mActionSelectNextAbove"/>
</widget>
<widget class="QMenu" name="menuLayout">
<property name="title">
<string>Layout</string>
</property>
<addaction name="mActionLockItems"/>
<addaction name="mActionUnlockAll"/>
</widget>
<addaction name="mLayoutMenu"/>
<addaction name="menuEdit"/>
<addaction name="mMenuView"/>
<addaction name="menuLayout"/>
<addaction name="mItemMenu"/>
</widget>
<widget class="QToolBar" name="mNavigationToolbar">
@ -171,6 +179,19 @@
<addaction name="mActionZoomActual"/>
<addaction name="mActionZoomAll"/>
</widget>
<widget class="QToolBar" name="mActionsToolbar">
<property name="windowTitle">
<string>toolBar</string>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
<addaction name="mActionLockItems"/>
<addaction name="mActionUnlockAll"/>
</widget>
<action name="mActionClose">
<property name="text">
<string>&amp;Close</string>
@ -536,6 +557,33 @@
<string>Ctrl+Alt+]</string>
</property>
</action>
<action name="mActionLockItems">
<property name="icon">
<iconset resource="../../../images/images.qrc">
<normaloff>:/images/themes/default/locked.svg</normaloff>:/images/themes/default/locked.svg</iconset>
</property>
<property name="text">
<string>Loc&amp;k Selected Items</string>
</property>
<property name="shortcut">
<string>Ctrl+L</string>
</property>
</action>
<action name="mActionUnlockAll">
<property name="icon">
<iconset resource="../../../images/images.qrc">
<normaloff>:/images/themes/default/unlocked.svg</normaloff>:/images/themes/default/unlocked.svg</iconset>
</property>
<property name="text">
<string>Unl&amp;ock All</string>
</property>
<property name="toolTip">
<string>Unlock All Items</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+L</string>
</property>
</action>
</widget>
<resources>
<include location="../../../images/images.qrc"/>

View File

@ -179,6 +179,78 @@ class TestQgsLayoutView(unittest.TestCase):
self.assertFalse(item2.isSelected())
self.assertFalse(item3.isSelected()) # locked
def testSelectNextByZOrder(self):
p = QgsProject()
l = QgsLayout(p)
# add some items
item1 = QgsLayoutItemMap(l)
l.addItem(item1)
item2 = QgsLayoutItemMap(l)
l.addItem(item2)
item3 = QgsLayoutItemMap(l)
item3.setLocked(True)
l.addItem(item3)
view = QgsLayoutView()
# no layout, no crash
view.selectNextItemAbove()
view.selectNextItemBelow()
view.setCurrentLayout(l)
focused_item_spy = QSignalSpy(view.itemFocused)
# no selection
view.selectNextItemAbove()
view.selectNextItemBelow()
self.assertEqual(len(focused_item_spy), 0)
l.setSelectedItem(item1)
self.assertEqual(len(focused_item_spy), 1)
# already bottom most
view.selectNextItemBelow()
self.assertTrue(item1.isSelected())
self.assertFalse(item2.isSelected())
self.assertFalse(item3.isSelected())
self.assertEqual(len(focused_item_spy), 1)
view.selectNextItemAbove()
self.assertFalse(item1.isSelected())
self.assertTrue(item2.isSelected())
self.assertFalse(item3.isSelected())
self.assertEqual(len(focused_item_spy), 2)
view.selectNextItemAbove()
self.assertFalse(item1.isSelected())
self.assertFalse(item2.isSelected())
self.assertTrue(item3.isSelected())
self.assertEqual(len(focused_item_spy), 3)
view.selectNextItemAbove() # already top most
self.assertFalse(item1.isSelected())
self.assertFalse(item2.isSelected())
self.assertTrue(item3.isSelected())
self.assertEqual(len(focused_item_spy), 3)
view.selectNextItemBelow()
self.assertFalse(item1.isSelected())
self.assertTrue(item2.isSelected())
self.assertFalse(item3.isSelected())
self.assertEqual(len(focused_item_spy), 4)
view.selectNextItemBelow()
self.assertTrue(item1.isSelected())
self.assertFalse(item2.isSelected())
self.assertFalse(item3.isSelected())
self.assertEqual(len(focused_item_spy), 5)
view.selectNextItemBelow() # back to bottom most
self.assertTrue(item1.isSelected())
self.assertFalse(item2.isSelected())
self.assertFalse(item3.isSelected())
self.assertEqual(len(focused_item_spy), 5)
if __name__ == '__main__':
unittest.main()