Skip to content

Commit

Permalink
[feature][layout] Add ""Convert to Static Text" option to dropdown
Browse files Browse the repository at this point in the history
menu next to "Insert/Edit Expression…" in layout label properties
widget

When selected any dynamic parts of the label's contents will be
evaluated and replaced with their current values.

Provides an easy way to convert a dynamic label to a static one,
so that the user can then manually tweak the resulting tweak
when needed.
  • Loading branch information
nyalldawson committed May 13, 2021
1 parent e3cb3e5 commit 5e98648
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 1 deletion.
8 changes: 8 additions & 0 deletions python/core/auto_generated/layout/qgslayoutitemlabel.sip.in
Expand Up @@ -232,6 +232,14 @@ Returns the label font color.
virtual void refresh();


void convertToStaticText();
%Docstring
Converts the label's :py:func:`~QgsLayoutItemLabel.text` to a static string, by evaluating any expressions included in the text
and replacing them with their current values.

.. versionadded:: 3.20
%End

protected:
virtual void draw( QgsLayoutItemRenderContext &context );

Expand Down
9 changes: 9 additions & 0 deletions src/core/layout/qgslayoutitemlabel.cpp
Expand Up @@ -516,6 +516,15 @@ void QgsLayoutItemLabel::refresh()
refreshExpressionContext();
}

void QgsLayoutItemLabel::convertToStaticText()
{
const QString evaluated = currentText();
if ( evaluated == mText )
return; // no changes

setText( evaluated );
}

void QgsLayoutItemLabel::itemShiftAdjustSize( double newWidth, double newHeight, double &xShift, double &yShift ) const
{
//keep alignment point constant
Expand Down
8 changes: 8 additions & 0 deletions src/core/layout/qgslayoutitemlabel.h
Expand Up @@ -218,6 +218,14 @@ class CORE_EXPORT QgsLayoutItemLabel: public QgsLayoutItem

void refresh() override;

/**
* Converts the label's text() to a static string, by evaluating any expressions included in the text
* and replacing them with their current values.
*
* \since QGIS 3.20
*/
void convertToStaticText();

protected:
void draw( QgsLayoutItemRenderContext &context ) override;
bool writePropertiesToElement( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const override;
Expand Down
5 changes: 5 additions & 0 deletions src/gui/layout/qgslayoutlabelwidget.cpp
Expand Up @@ -88,6 +88,11 @@ QgsLayoutLabelWidget::QgsLayoutLabelWidget( QgsLayoutItemLabel *label )
}
} );

QMenu *expressionMenu = new QMenu( this );
QAction *convertToStaticAction = new QAction( tr( "Convert to Static Text" ), this );
expressionMenu->addAction( convertToStaticAction );
connect( convertToStaticAction, &QAction::triggered, mLabel, &QgsLayoutItemLabel::convertToStaticText );
mInsertExpressionButton->setMenu( expressionMenu );
}

void QgsLayoutLabelWidget::setMasterLayout( QgsMasterLayoutInterface *masterLayout )
Expand Down
11 changes: 10 additions & 1 deletion src/ui/layout/qgslayoutlabelwidgetbase.ui
Expand Up @@ -62,7 +62,7 @@
<x>0</x>
<y>0</y>
<width>358</width>
<height>682</height>
<height>680</height>
</rect>
</property>
<layout class="QVBoxLayout" name="mainLayout">
Expand Down Expand Up @@ -111,6 +111,15 @@
<property name="text">
<string>Insert/Edit Expression…</string>
</property>
<property name="popupMode">
<enum>QToolButton::MenuButtonPopup</enum>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextOnly</enum>
</property>
<property name="arrowType">
<enum>Qt::DownArrow</enum>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
Expand Down
28 changes: 28 additions & 0 deletions tests/src/python/test_qgslayoutlabel.py
Expand Up @@ -22,6 +22,7 @@
QgsLayoutItemPage,
QgsLayoutPoint)
from utilities import unitTestDataPath
from qgis.PyQt.QtTest import QSignalSpy

from test_qgslayoutitem import LayoutItemTestCase

Expand Down Expand Up @@ -95,6 +96,33 @@ def page_evaluation_test(self, layout, label, mVectorLayer):
label.attemptMove(QgsLayoutPoint(0, 320))
self.assertEqual(label.currentText(), "2/2")

def test_convert_to_static(self):
layout = QgsPrintLayout(QgsProject.instance())
layout.initializeDefaults()

label = QgsLayoutItemLabel(layout)
layout.addLayoutItem(label)
layout.setName('my layout')

# no text yet
label.convertToStaticText()
self.assertFalse(label.text())

spy = QSignalSpy(label.changed)
label.setText('already static text')
self.assertEqual(len(spy), 1)
label.convertToStaticText()
self.assertEqual(label.text(), 'already static text')
self.assertEqual(len(spy), 1)

label.setText('with [% 1+2+3 %] some [% @layout_name %] dynamic bits')
self.assertEqual(len(spy), 2)
self.assertEqual(label.text(), 'with [% 1+2+3 %] some [% @layout_name %] dynamic bits')

label.convertToStaticText()
self.assertEqual(label.text(), 'with 6 some my layout dynamic bits')
self.assertEqual(len(spy), 3)


if __name__ == '__main__':
unittest.main()

0 comments on commit 5e98648

Please sign in to comment.