Esempio n. 1
0
void QgsLayoutView::invertSelection()
{
  if ( !currentLayout() )
  {
    return;
  }

  QgsLayoutItem *focusedItem = nullptr;
  //check all items in layout
  const QList<QGraphicsItem *> itemList = currentLayout()->items();
  for ( QGraphicsItem *graphicsItem : itemList )
  {
    QgsLayoutItem *item = dynamic_cast<QgsLayoutItem *>( graphicsItem );
    QgsLayoutItemPage *paperItem = dynamic_cast<QgsLayoutItemPage *>( graphicsItem );
    if ( item && !paperItem )
    {
      //flip selected state for items (and deselect any locked items)
      if ( item->isSelected() || item->isLocked() )
      {
        item->setSelected( false );
      }
      else
      {
        item->setSelected( true );
        if ( !focusedItem )
          focusedItem = item;
      }
    }
  }
  if ( focusedItem )
    emit itemFocused( focusedItem );
}
void QgsLayoutViewToolSelect::layoutPressEvent( QgsLayoutViewMouseEvent *event )
{
  if ( mMouseHandles->shouldBlockEvent( event ) )
  {
    //swallow clicks while dragging/resizing items
    return;
  }

  if ( mMouseHandles->isVisible() )
  {
    //selection handles are being shown, get mouse action for current cursor position
    QgsLayoutMouseHandles::MouseAction mouseAction = mMouseHandles->mouseActionForScenePos( event->layoutPoint() );

    if ( mouseAction != QgsLayoutMouseHandles::MoveItem
         && mouseAction != QgsLayoutMouseHandles::NoAction
         && mouseAction != QgsLayoutMouseHandles::SelectItem )
    {
      //mouse is over a resize handle, so propagate event onward
      event->ignore();
      return;
    }
  }

  if ( event->button() != Qt::LeftButton )
  {
    event->ignore();
    return;
  }

  QgsLayoutItem *selectedItem = nullptr;
  QgsLayoutItem *previousSelectedItem = nullptr;

  QList<QgsLayoutItem *> selectedItems = layout()->selectedLayoutItems();

  if ( event->modifiers() & Qt::ControlModifier )
  {
    //CTRL modifier, so we are trying to select the next item below the current one
    //first, find currently selected item
    if ( !selectedItems.isEmpty() )
    {
      previousSelectedItem = selectedItems.at( 0 );
    }
  }

  if ( previousSelectedItem )
  {
    //select highest item just below previously selected item at position of event
    selectedItem = layout()->layoutItemAt( event->layoutPoint(), previousSelectedItem, true );

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

  if ( !selectedItem )
  {
    //not clicking over an item, so start marquee selection
    mIsSelecting = true;
    mMousePressStartPos = event->pos();
    mRubberBand->start( event->layoutPoint(), nullptr );
    return;
  }

  if ( ( event->modifiers() & Qt::ShiftModifier ) && ( selectedItem->isSelected() ) )
  {
    //SHIFT-clicking a selected item deselects it
    selectedItem->setSelected( false );

    //Check if we have any remaining selected items, and if so, update the item panel
    const QList<QgsLayoutItem *> selectedItems = layout()->selectedLayoutItems();
    if ( !selectedItems.isEmpty() )
    {
      emit itemFocused( selectedItems.at( 0 ) );
    }
    else
    {
      emit itemFocused( nullptr );
    }
  }
  else
  {
    if ( ( !selectedItem->isSelected() ) &&       //keep selection if an already selected item pressed
         !( event->modifiers() & Qt::ShiftModifier ) ) //keep selection if shift key pressed
    {
      layout()->setSelectedItem( selectedItem ); // clears existing selection
    }
    else
    {
      selectedItem->setSelected( true );
    }
    event->ignore();
    emit itemFocused( selectedItem );
  }
}