Skip to content

Commit

Permalink
[layouts] Add explicit button to insert expressions in legend text
Browse files Browse the repository at this point in the history
While this has been possible for a while by manually entering a
"[% expression %]" string as part of a legend item's text, this
is completely hidden from users and rather useless.

Now that we have a dedicated widget to allow configuration of
individual legend items, we've got the capacity to show a dedicated
"insert expression" button, just like we do for layout labels.

This makes it immediately clear to users that expressions CAN be
used in legend item text, and also helps them construct valid
expressions using the available expression context.
  • Loading branch information
nyalldawson committed Apr 23, 2020
1 parent 4f91bee commit 5dd3916
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 17 deletions.
54 changes: 51 additions & 3 deletions src/gui/layout/qgslayoutlegendwidget.cpp
Expand Up @@ -1434,15 +1434,17 @@ QgsLayoutLegendNodeWidget::QgsLayoutLegendNodeWidget( QgsLayoutItemLegend *legen
mPatchShapeButton->hide();
}

mLabelEdit->setText( currentLabel );
connect( mLabelEdit, &QLineEdit::textChanged, this, &QgsLayoutLegendNodeWidget::labelChanged );
mLabelEdit->setPlainText( currentLabel );
connect( mLabelEdit, &QPlainTextEdit::textChanged, this, &QgsLayoutLegendNodeWidget::labelChanged );
connect( mPatchShapeButton, &QgsLegendPatchShapeButton::changed, this, &QgsLayoutLegendNodeWidget::patchChanged );
connect( mInsertExpressionButton, &QPushButton::clicked, this, &QgsLayoutLegendNodeWidget::insertExpression );
}

void QgsLayoutLegendNodeWidget::labelChanged( const QString &label )
void QgsLayoutLegendNodeWidget::labelChanged()
{
mLegend->beginCommand( tr( "Edit Legend Item" ), QgsLayoutItem::UndoLegendText );

const QString label = mLabelEdit->toPlainText();
if ( QgsLayerTree::isGroup( mNode ) )
{
QgsLayerTree::toGroup( mNode )->setName( label );
Expand Down Expand Up @@ -1492,4 +1494,50 @@ void QgsLayoutLegendNodeWidget::patchChanged()
mLegend->endCommand();
}

void QgsLayoutLegendNodeWidget::insertExpression()
{
if ( !mLegend )
return;

QString selText = mLabelEdit->textCursor().selectedText();

// html editor replaces newlines with Paragraph Separator characters - see https://github.com/qgis/QGIS/issues/27568
selText = selText.replace( QChar( 0x2029 ), QChar( '\n' ) );

// edit the selected expression if there's one
if ( selText.startsWith( QLatin1String( "[%" ) ) && selText.endsWith( QLatin1String( "%]" ) ) )
selText = selText.mid( 2, selText.size() - 4 );

// use the atlas coverage layer, if any
QgsVectorLayer *layer = mLegend->layout() ? mLegend->layout()->reportContext().layer() : nullptr;

QgsExpressionContext context = mLegend->createExpressionContext();

if ( mLayer && mLayer->layer() )
{
context.appendScope( QgsExpressionContextUtils::layerScope( mLayer->layer() ) );
}

context.setHighlightedVariables( QStringList() << QStringLiteral( "legend_title" )
<< QStringLiteral( "legend_column_count" )
<< QStringLiteral( "legend_split_layers" )
<< QStringLiteral( "legend_wrap_string" )
<< QStringLiteral( "legend_filter_by_map" )
<< QStringLiteral( "legend_filter_out_atlas" ) );

QgsExpressionBuilderDialog exprDlg( layer, selText, this, QStringLiteral( "generic" ), context );

exprDlg.setWindowTitle( tr( "Insert Expression" ) );
if ( exprDlg.exec() == QDialog::Accepted )
{
QString expression = exprDlg.expressionText();
if ( !expression.isEmpty() )
{
mLegend->beginCommand( tr( "Insert expression" ) );
mLabelEdit->insertPlainText( "[%" + expression + "%]" );
mLegend->endCommand();
}
}
}

///@endcond
3 changes: 2 additions & 1 deletion src/gui/layout/qgslayoutlegendwidget.h
Expand Up @@ -185,8 +185,9 @@ class GUI_EXPORT QgsLayoutLegendNodeWidget: public QgsPanelWidget, private Ui::Q

private slots:

void labelChanged( const QString &label );
void labelChanged();
void patchChanged();
void insertExpression();

private:

Expand Down
40 changes: 27 additions & 13 deletions src/ui/layout/qgslayoutlegendnodewidgetbase.ui
Expand Up @@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
<height>282</height>
</rect>
</property>
<property name="windowTitle">
Expand All @@ -26,17 +26,17 @@
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Label</string>
<item row="0" column="1">
<widget class="QPlainTextEdit" name="mLabelEdit">
<property name="minimumSize">
<size>
<width>0</width>
<height>150</height>
</size>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="mLabelEdit"/>
</item>
<item row="2" column="1">
<item row="3" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
Expand All @@ -49,14 +49,14 @@
</property>
</spacer>
</item>
<item row="1" column="0">
<widget class="QLabel" name="mPatchShapeLabel">
<item row="1" column="1">
<widget class="QPushButton" name="mInsertExpressionButton">
<property name="text">
<string>Patch shape</string>
<string>Insert an Expression…</string>
</property>
</widget>
</item>
<item row="1" column="1">
<item row="2" column="1">
<widget class="QgsLegendPatchShapeButton" name="mPatchShapeButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
Expand All @@ -69,6 +69,20 @@
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="mPatchShapeLabel">
<property name="text">
<string>Patch shape</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Label</string>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
Expand Down

0 comments on commit 5dd3916

Please sign in to comment.