Skip to content
Permalink
Browse files
[feature][layout] Add ""Convert to Static Text" option to dropdown
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 5e98648913b82466ca9eb42ed68f4bb0b536ae96
@@ -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 );

@@ -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
@@ -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;
@@ -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 )
@@ -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">
@@ -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">
@@ -22,6 +22,7 @@
QgsLayoutItemPage,
QgsLayoutPoint)
from utilities import unitTestDataPath
from qgis.PyQt.QtTest import QSignalSpy

from test_qgslayoutitem import LayoutItemTestCase

@@ -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.