Skip to content

Commit

Permalink
[labeling][ui] Change placement mode selection widget from radio
Browse files Browse the repository at this point in the history
buttons to combo box

The radio buttons don't work well here -- they cause a massive
gap in the placement UI layout for anything but polygon
layers. Using a combobox is also much more compact, giving us
some extra space to use for more helpful explanatory text
  • Loading branch information
nyalldawson committed Aug 18, 2020
1 parent 6712278 commit d4ca4a1
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 423 deletions.
9 changes: 9 additions & 0 deletions python/gui/auto_generated/qgstextformatwidget.sip.in
Expand Up @@ -155,6 +155,15 @@ Controls whether data defined alignment buttons are enabled.
virtual QgsExpressionContext createExpressionContext() const;


QgsWkbTypes::GeometryType labelGeometryType() const;
%Docstring
Returns the geometry type which will be used by the labeling engine
when registering labels for the labeling settings currently defined by the widget.

.. versionadded:: 3.16
%End





Expand Down
116 changes: 28 additions & 88 deletions src/gui/labeling/qgslabelinggui.cpp
Expand Up @@ -223,11 +223,11 @@ void QgsLabelingGui::showLineAnchorSettings()

QgsLabelingGui::QgsLabelingGui( QgsVectorLayer *layer, QgsMapCanvas *mapCanvas, const QgsPalLayerSettings &layerSettings, QWidget *parent, QgsWkbTypes::GeometryType geomType )
: QgsTextFormatWidget( mapCanvas, parent, QgsTextFormatWidget::Labeling, layer )
, mGeomType( geomType )
, mSettings( layerSettings )
, mMode( NoLabels )
, mCanvas( mapCanvas )
{
mGeomType = geomType;
static std::once_flag initialized;
std::call_once( initialized, [ = ]( )
{
Expand Down Expand Up @@ -350,41 +350,7 @@ void QgsLabelingGui::setLayer( QgsMapLayer *mapLayer )

mCheckAllowLabelsOutsidePolygons->setChecked( mSettings.polygonPlacementFlags() & QgsLabeling::PolygonPlacementFlag::AllowPlacementOutsideOfPolygon );

switch ( mSettings.placement )
{
case QgsPalLayerSettings::AroundPoint:
radAroundPoint->setChecked( true );
radAroundCentroid->setChecked( true );
//spinAngle->setValue( lyr.angle ); // TODO: uncomment when supported
break;
case QgsPalLayerSettings::OverPoint:
radOverPoint->setChecked( true );
radOverCentroid->setChecked( true );
break;
case QgsPalLayerSettings::OrderedPositionsAroundPoint:
radPredefinedOrder->setChecked( true );
break;
case QgsPalLayerSettings::Line:
radLineParallel->setChecked( true );
radPolygonPerimeter->setChecked( true );
break;
case QgsPalLayerSettings::Curved:
radLineCurved->setChecked( true );
break;
case QgsPalLayerSettings::Horizontal:
radPolygonHorizontal->setChecked( true );
radLineHorizontal->setChecked( true );
break;
case QgsPalLayerSettings::Free:
radPolygonFree->setChecked( true );
break;
case QgsPalLayerSettings::PerimeterCurved:
radPolygonPerimeterCurved->setChecked( true );
break;
case QgsPalLayerSettings::OutsidePolygons:
radPolygonOutside->setChecked( true );
break;
}
mPlacementModeComboBox->setCurrentIndex( mPlacementModeComboBox->findData( mSettings.placement ) );

// Label repeat distance
mRepeatDistanceSpinBox->setValue( mSettings.repeatDistance );
Expand Down Expand Up @@ -497,9 +463,7 @@ void QgsLabelingGui::blockInitSignals( bool block )
{
chkLineAbove->blockSignals( block );
chkLineBelow->blockSignals( block );
mPlacePointBtnGrp->blockSignals( block );
mPlaceLineBtnGrp->blockSignals( block );
mPlacePolygonBtnGrp->blockSignals( block );
mPlacementModeComboBox->blockSignals( block );
}

void QgsLabelingGui::setLabelMode( LabelMode mode )
Expand All @@ -526,7 +490,6 @@ QgsPalLayerSettings QgsLabelingGui::layerSettings()
polygonPlacementFlags |= QgsLabeling::PolygonPlacementFlag::AllowPlacementOutsideOfPolygon;
lyr.setPolygonPlacementFlags( polygonPlacementFlags );

QWidget *curPlacementWdgt = stackedPlacement->currentWidget();
lyr.centroidWhole = mCentroidRadioWhole->isChecked();
lyr.centroidInside = mCentroidInsideCheckBox->isChecked();
lyr.fitInPolygonOnly = mFitInsidePolygonCheckBox->isChecked();
Expand Down Expand Up @@ -555,50 +518,7 @@ QgsPalLayerSettings QgsLabelingGui::layerSettings()
linePlacementFlags |= QgsLabeling::LinePlacementFlag::MapOrientation;
lyr.lineSettings().setPlacementFlags( linePlacementFlags );

if ( ( curPlacementWdgt == pagePoint && radAroundPoint->isChecked() )
|| ( curPlacementWdgt == pagePolygon && radAroundCentroid->isChecked() ) )
{
lyr.placement = QgsPalLayerSettings::AroundPoint;
}
else if ( ( curPlacementWdgt == pagePoint && radOverPoint->isChecked() )
|| ( curPlacementWdgt == pagePolygon && radOverCentroid->isChecked() ) )
{
lyr.placement = QgsPalLayerSettings::OverPoint;
}
else if ( curPlacementWdgt == pagePoint && radPredefinedOrder->isChecked() )
{
lyr.placement = QgsPalLayerSettings::OrderedPositionsAroundPoint;
}
else if ( ( curPlacementWdgt == pageLine && radLineParallel->isChecked() )
|| ( curPlacementWdgt == pagePolygon && radPolygonPerimeter->isChecked() ) )
{
lyr.placement = QgsPalLayerSettings::Line;
}
else if ( curPlacementWdgt == pageLine && radLineCurved->isChecked() )
{
lyr.placement = QgsPalLayerSettings::Curved;
}
else if ( curPlacementWdgt == pagePolygon && radPolygonPerimeterCurved->isChecked() )
{
lyr.placement = QgsPalLayerSettings::PerimeterCurved;
}
else if ( ( curPlacementWdgt == pageLine && radLineHorizontal->isChecked() )
|| ( curPlacementWdgt == pagePolygon && radPolygonHorizontal->isChecked() ) )
{
lyr.placement = QgsPalLayerSettings::Horizontal;
}
else if ( radPolygonFree->isChecked() )
{
lyr.placement = QgsPalLayerSettings::Free;
}
else if ( radPolygonOutside->isChecked() )
{
lyr.placement = QgsPalLayerSettings::OutsidePolygons;
}
else
{
qFatal( "Invalid settings" );
}
lyr.placement = static_cast< QgsPalLayerSettings::Placement >( mPlacementModeComboBox->currentData().toInt() );

lyr.repeatDistance = mRepeatDistanceSpinBox->value();
lyr.repeatDistanceUnit = mRepeatDistanceUnitWidget->unit();
Expand Down Expand Up @@ -855,24 +775,44 @@ void QgsLabelingGui::updateGeometryTypeBasedWidgets()
mPolygonFeatureOptionsFrame->setVisible( geometryType == QgsWkbTypes::PolygonGeometry );


// set placement methods page based on geometry type
const QgsPalLayerSettings::Placement prevPlacement = static_cast< QgsPalLayerSettings::Placement >( mPlacementModeComboBox->currentData().toInt() );
mPlacementModeComboBox->clear();

switch ( geometryType )
{
case QgsWkbTypes::PointGeometry:
stackedPlacement->setCurrentWidget( pagePoint );
mPlacementModeComboBox->addItem( tr( "Cartographic" ), QgsPalLayerSettings::OrderedPositionsAroundPoint );
mPlacementModeComboBox->addItem( tr( "Around Point" ), QgsPalLayerSettings::AroundPoint );
mPlacementModeComboBox->addItem( tr( "Offset from Point" ), QgsPalLayerSettings::OverPoint );
break;

case QgsWkbTypes::LineGeometry:
stackedPlacement->setCurrentWidget( pageLine );
mPlacementModeComboBox->addItem( tr( "Parallel" ), QgsPalLayerSettings::Line );
mPlacementModeComboBox->addItem( tr( "Curved" ), QgsPalLayerSettings::Curved );
mPlacementModeComboBox->addItem( tr( "Horizontal" ), QgsPalLayerSettings::Horizontal );
break;

case QgsWkbTypes::PolygonGeometry:
stackedPlacement->setCurrentWidget( pagePolygon );
mPlacementModeComboBox->addItem( tr( "Offset from Centroid" ), QgsPalLayerSettings::OverPoint );
mPlacementModeComboBox->addItem( tr( "Around Centroid" ), QgsPalLayerSettings::AroundPoint );
mPlacementModeComboBox->addItem( tr( "Horizontal" ), QgsPalLayerSettings::Horizontal );
mPlacementModeComboBox->addItem( tr( "Free (Angled)" ), QgsPalLayerSettings::Free );
mPlacementModeComboBox->addItem( tr( "Using Perimeter" ), QgsPalLayerSettings::Line );
mPlacementModeComboBox->addItem( tr( "Using Perimeter (Curved)" ), QgsPalLayerSettings::PerimeterCurved );
mPlacementModeComboBox->addItem( tr( "Outside Polygons" ), QgsPalLayerSettings::OutsidePolygons );
break;

case QgsWkbTypes::NullGeometry:
break;
case QgsWkbTypes::UnknownGeometry:
qFatal( "unknown geometry type unexpected" );
}

if ( mPlacementModeComboBox->findData( prevPlacement ) != -1 )
{
mPlacementModeComboBox->setCurrentIndex( mPlacementModeComboBox->findData( prevPlacement ) );
}

if ( geometryType == QgsWkbTypes::PointGeometry || geometryType == QgsWkbTypes::PolygonGeometry )
{
// follow placement alignment is only valid for point or polygon layers
Expand Down
1 change: 0 additions & 1 deletion src/gui/labeling/qgslabelinggui.h
Expand Up @@ -85,7 +85,6 @@ class GUI_EXPORT QgsLabelingGui : public QgsTextFormatWidget

private:

QgsWkbTypes::GeometryType mGeomType = QgsWkbTypes::UnknownGeometry;
QgsPalLayerSettings mSettings;
LabelMode mMode;
QgsFeature mPreviewFeature;
Expand Down
101 changes: 36 additions & 65 deletions src/gui/qgstextformatwidget.cpp
Expand Up @@ -268,33 +268,7 @@ void QgsTextFormatWidget::initWidget()
connect( mCheckAllowLabelsOutsidePolygons, &QAbstractButton::toggled, this, &QgsTextFormatWidget::updatePlacementWidgets );
connect( mAllowOutsidePolygonsDDBtn, &QgsPropertyOverrideButton::changed, this, &QgsTextFormatWidget::updatePlacementWidgets );

// setup point placement button group
mPlacePointBtnGrp = new QButtonGroup( this );
mPlacePointBtnGrp->addButton( radPredefinedOrder, static_cast<int>( QgsPalLayerSettings::OrderedPositionsAroundPoint ) );
mPlacePointBtnGrp->addButton( radAroundPoint, static_cast<int>( QgsPalLayerSettings::AroundPoint ) );
mPlacePointBtnGrp->addButton( radOverPoint, static_cast<int>( QgsPalLayerSettings::OverPoint ) );
mPlacePointBtnGrp->setExclusive( true );
connect( mPlacePointBtnGrp, static_cast<void ( QButtonGroup::* )( int )>( &QButtonGroup::buttonClicked ), this, &QgsTextFormatWidget::updatePlacementWidgets );

// setup line placement button group (assigned enum id currently unused)
mPlaceLineBtnGrp = new QButtonGroup( this );
mPlaceLineBtnGrp->addButton( radLineParallel, static_cast<int>( QgsPalLayerSettings::Line ) );
mPlaceLineBtnGrp->addButton( radLineCurved, static_cast<int>( QgsPalLayerSettings::Curved ) );
mPlaceLineBtnGrp->addButton( radLineHorizontal, static_cast<int>( QgsPalLayerSettings::Horizontal ) );
mPlaceLineBtnGrp->setExclusive( true );
connect( mPlaceLineBtnGrp, static_cast<void ( QButtonGroup::* )( int )>( &QButtonGroup::buttonClicked ), this, &QgsTextFormatWidget::updatePlacementWidgets );

// setup polygon placement button group (assigned enum id currently unused)
mPlacePolygonBtnGrp = new QButtonGroup( this );
mPlacePolygonBtnGrp->addButton( radOverCentroid, static_cast<int>( QgsPalLayerSettings::OverPoint ) );
mPlacePolygonBtnGrp->addButton( radAroundCentroid, static_cast<int>( QgsPalLayerSettings::AroundPoint ) );
mPlacePolygonBtnGrp->addButton( radPolygonHorizontal, static_cast<int>( QgsPalLayerSettings::Horizontal ) );
mPlacePolygonBtnGrp->addButton( radPolygonFree, static_cast<int>( QgsPalLayerSettings::Free ) );
mPlacePolygonBtnGrp->addButton( radPolygonPerimeter, static_cast<int>( QgsPalLayerSettings::Line ) );
mPlacePolygonBtnGrp->addButton( radPolygonPerimeterCurved, static_cast<int>( QgsPalLayerSettings::PerimeterCurved ) );
mPlacePolygonBtnGrp->addButton( radPolygonOutside, static_cast<int>( QgsPalLayerSettings::OutsidePolygons ) );
mPlacePolygonBtnGrp->setExclusive( true );
connect( mPlacePolygonBtnGrp, static_cast<void ( QButtonGroup::* )( int )>( &QButtonGroup::buttonClicked ), this, &QgsTextFormatWidget::updatePlacementWidgets );
connect( mPlacementModeComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsTextFormatWidget::updatePlacementWidgets );

// Global settings group for groupboxes' saved/restored collapsed state
// maintains state across different dialogs
Expand Down Expand Up @@ -455,19 +429,7 @@ void QgsTextFormatWidget::initWidget()
<< mUpsidedownRadioAll
<< mUpsidedownRadioDefined
<< mUpsidedownRadioOff
<< radAroundCentroid
<< radAroundPoint
<< radLineCurved
<< radLineHorizontal
<< radLineParallel
<< radOverCentroid
<< radOverPoint
<< radPolygonFree
<< radPolygonHorizontal
<< radPolygonPerimeter
<< radPolygonPerimeterCurved
<< radPolygonOutside
<< radPredefinedOrder
<< mPlacementModeComboBox
<< mFieldExpressionWidget
<< mCheckBoxSubstituteText
<< mGeometryGeneratorGroupBox
Expand Down Expand Up @@ -1314,8 +1276,7 @@ void QgsTextFormatWidget::changeBufferColor( const QColor &color )

void QgsTextFormatWidget::updatePlacementWidgets()
{
QWidget *curWdgt = stackedPlacement->currentWidget();

const QgsWkbTypes::GeometryType currentGeometryType = labelGeometryType();
bool showLineFrame = false;
bool showCentroidFrame = false;
bool showQuadrantFrame = false;
Expand All @@ -1326,40 +1287,39 @@ void QgsTextFormatWidget::updatePlacementWidgets()
bool showDistanceFrame = false;
bool showRotationFrame = false;
bool showMaxCharAngleFrame = false;
bool showPolygonPlacementOptions = ( curWdgt == pagePolygon && !radPolygonPerimeter->isChecked() && !radPolygonPerimeterCurved->isChecked() && !radPolygonOutside->isChecked() );

const QgsPalLayerSettings::Placement currentPlacement = static_cast< QgsPalLayerSettings::Placement >( mPlacementModeComboBox->currentData().toInt() );
bool showPolygonPlacementOptions = ( currentGeometryType == QgsWkbTypes::PolygonGeometry && currentPlacement != QgsPalLayerSettings::Line && currentPlacement != QgsPalLayerSettings::PerimeterCurved && currentPlacement != QgsPalLayerSettings::OutsidePolygons );

bool enableMultiLinesFrame = true;

if ( ( curWdgt == pagePoint && radAroundPoint->isChecked() )
|| ( curWdgt == pagePolygon && radAroundCentroid->isChecked() ) )
if ( currentPlacement == QgsPalLayerSettings::AroundPoint
&& ( currentGeometryType == QgsWkbTypes::PointGeometry || currentGeometryType == QgsWkbTypes::PolygonGeometry ) )
{
showCentroidFrame = ( curWdgt == pagePolygon && radAroundCentroid->isChecked() );
showCentroidFrame = currentGeometryType == QgsWkbTypes::PolygonGeometry;
showDistanceFrame = true;
//showRotationFrame = true; // TODO: uncomment when supported
if ( curWdgt == pagePoint )
{
showQuadrantFrame = true;
}
showQuadrantFrame = currentGeometryType == QgsWkbTypes::PointGeometry;
}
else if ( ( curWdgt == pagePoint && radOverPoint->isChecked() )
|| ( curWdgt == pagePolygon && radOverCentroid->isChecked() ) )
else if ( currentPlacement == QgsPalLayerSettings::OverPoint
&& ( currentGeometryType == QgsWkbTypes::PointGeometry || currentGeometryType == QgsWkbTypes::PolygonGeometry ) )
{
showCentroidFrame = ( curWdgt == pagePolygon && radOverCentroid->isChecked() );
showCentroidFrame = currentGeometryType == QgsWkbTypes::PolygonGeometry;
showQuadrantFrame = true;
showFixedQuadrantFrame = true;
showOffsetFrame = true;
showRotationFrame = true;
}
else if ( curWdgt == pagePoint && radPredefinedOrder->isChecked() )
else if ( currentGeometryType == QgsWkbTypes::PointGeometry && currentPlacement == QgsPalLayerSettings::OrderedPositionsAroundPoint )
{
showDistanceFrame = true;
showPlacementPriorityFrame = true;
showOffsetTypeFrame = true;
}
else if ( ( curWdgt == pageLine && radLineParallel->isChecked() )
|| ( curWdgt == pagePolygon && radPolygonPerimeter->isChecked() )
|| ( curWdgt == pageLine && radLineCurved->isChecked() )
|| ( curWdgt == pagePolygon && radPolygonPerimeterCurved->isChecked() ) )
else if ( ( currentGeometryType == QgsWkbTypes::LineGeometry && currentPlacement == QgsPalLayerSettings::Line )
|| ( currentGeometryType == QgsWkbTypes::PolygonGeometry && currentPlacement == QgsPalLayerSettings::Line )
|| ( currentGeometryType == QgsWkbTypes::LineGeometry && currentPlacement == QgsPalLayerSettings::Curved )
|| ( currentGeometryType == QgsWkbTypes::PolygonGeometry && currentPlacement == QgsPalLayerSettings::PerimeterCurved ) )
{
showLineFrame = true;
showDistanceFrame = true;
Expand All @@ -1369,13 +1329,14 @@ void QgsTextFormatWidget::updatePlacementWidgets()
chkLineOrientationDependent->setEnabled( offline );
mPlacementDistanceFrame->setEnabled( offline );

bool isCurved = ( curWdgt == pageLine && radLineCurved->isChecked() )
|| ( curWdgt == pagePolygon && radPolygonPerimeterCurved->isChecked() );
bool isCurved = ( currentGeometryType == QgsWkbTypes::LineGeometry && currentPlacement == QgsPalLayerSettings::Curved )
|| ( currentGeometryType == QgsWkbTypes::PolygonGeometry && currentPlacement == QgsPalLayerSettings::PerimeterCurved );
showMaxCharAngleFrame = isCurved;
// TODO: enable mMultiLinesFrame when supported for curved labels
enableMultiLinesFrame = !isCurved;
}
else if ( curWdgt == pagePolygon && ( radPolygonOutside->isChecked() || mCheckAllowLabelsOutsidePolygons->isChecked() || mAllowOutsidePolygonsDDBtn->isActive() ) )
else if ( currentGeometryType == QgsWkbTypes::PolygonGeometry
&& ( currentPlacement == QgsPalLayerSettings::OutsidePolygons || mCheckAllowLabelsOutsidePolygons->isChecked() || mAllowOutsidePolygonsDDBtn->isActive() ) )
{
showDistanceFrame = true;
}
Expand All @@ -1390,10 +1351,10 @@ void QgsTextFormatWidget::updatePlacementWidgets()
mPlacementDistanceFrame->setVisible( showDistanceFrame );
mPlacementOffsetTypeFrame->setVisible( showOffsetTypeFrame );
mPlacementRotationFrame->setVisible( showRotationFrame );
mPlacementRepeatDistanceFrame->setVisible( curWdgt == pageLine || ( curWdgt == pagePolygon &&
( radPolygonPerimeter->isChecked() || radPolygonPerimeterCurved->isChecked() ) ) );
mPlacementOverrunDistanceFrame->setVisible( curWdgt == pageLine );
mLineAnchorGroupBox->setVisible( curWdgt == pageLine );
mPlacementRepeatDistanceFrame->setVisible( currentGeometryType == QgsWkbTypes::LineGeometry || ( currentGeometryType == QgsWkbTypes::PolygonGeometry &&
( currentPlacement == QgsPalLayerSettings::Line || currentPlacement == QgsPalLayerSettings::PerimeterCurved ) ) );
mPlacementOverrunDistanceFrame->setVisible( currentGeometryType == QgsWkbTypes::LineGeometry );
mLineAnchorGroupBox->setVisible( currentGeometryType == QgsWkbTypes::LineGeometry );
mPlacementMaxCharAngleFrame->setVisible( showMaxCharAngleFrame );

mMultiLinesFrame->setEnabled( enableMultiLinesFrame );
Expand Down Expand Up @@ -2035,6 +1996,16 @@ QgsExpressionContext QgsTextFormatWidget::createExpressionContext() const
return expContext;
}

QgsWkbTypes::GeometryType QgsTextFormatWidget::labelGeometryType() const
{
if ( mGeometryGeneratorGroupBox->isChecked() )
return mGeometryGeneratorType->currentData().value<QgsWkbTypes::GeometryType>();
else if ( mLayer )
return mLayer->geometryType();
else
return mGeomType;
}


//
// QgsTextFormatDialog
Expand Down

0 comments on commit d4ca4a1

Please sign in to comment.