Skip to content

Commit

Permalink
Add QgsFontUtils methods for saving/loading font from XML (fix #12644)
Browse files Browse the repository at this point in the history
Fixes loss of font styles when restoring projects. Credit to @nirvn
for the initial implementation.
  • Loading branch information
nyalldawson committed Jun 15, 2015
1 parent 59f0cab commit 7a3a857
Show file tree
Hide file tree
Showing 15 changed files with 309 additions and 31 deletions.
33 changes: 33 additions & 0 deletions python/core/qgsfontutils.sip
Expand Up @@ -61,4 +61,37 @@ class QgsFontUtils
* @note Added in QGIS 2.1
*/
static QFont getStandardTestFont( const QString& style = "Roman", int pointsize = 12 );

/**Returns a DOM element containing the properties of the font.
* @param document DOM document
* @param elementName name for DOM element
* @returns DOM element containing font settings
* @note added in QGIS 2.10
* @see setFromXmlElement
*/
static QDomElement toXmlElement( const QFont& font, QDomDocument &document, const QString &elementName );

/**Sets the properties of a font to match the properties stored in an XML element. Calling
* this will overwrite the current properties of the font.
* @param font font to update
* @param element DOM element
* @returns true if properties were successfully read from element
* @note added in QGIS 2.10
* @see toXmlElement
* @see setFromXmlChildNode
*/
static bool setFromXmlElement( QFont& font, const QDomElement& element );

/**Sets the properties of a font to match the properties stored in an XML child node. Calling
* this will overwrite the current properties of the font.
* @param font font to update
* @param element DOM element
* @param childNode name of child node
* @returns true if child node exists and properties were successfully read from node
* @note added in QGIS 2.10
* @see setFromXmlElement
* @see toXmlElement
*/
static bool setFromXmlChildNode( QFont& font, const QDomElement& element, const QString& childNode );

};
11 changes: 3 additions & 8 deletions src/core/composer/qgscomposerlabel.cpp
Expand Up @@ -24,6 +24,7 @@
#include "qgsvectorlayer.h"
#include "qgsproject.h"
#include "qgsdistancearea.h"
#include "qgsfontutils.h"

#include "qgswebview.h"
#include "qgswebframe.h"
Expand Down Expand Up @@ -379,8 +380,7 @@ bool QgsComposerLabel::writeXML( QDomElement& elem, QDomDocument & doc ) const
composerLabelElem.setAttribute( "valign", mVAlignment );

//font
QDomElement labelFontElem = doc.createElement( "LabelFont" );
labelFontElem.setAttribute( "description", mFont.toString() );
QDomElement labelFontElem = QgsFontUtils::toXmlElement( mFont, doc, "LabelFont" );
composerLabelElem.appendChild( labelFontElem );

//font color
Expand Down Expand Up @@ -431,12 +431,7 @@ bool QgsComposerLabel::readXML( const QDomElement& itemElem, const QDomDocument&
mVAlignment = ( Qt::AlignmentFlag )( itemElem.attribute( "valign" ).toInt() );

//font
QDomNodeList labelFontList = itemElem.elementsByTagName( "LabelFont" );
if ( labelFontList.size() > 0 )
{
QDomElement labelFontElem = labelFontList.at( 0 ).toElement();
mFont.fromString( labelFontElem.attribute( "description" ) );
}
QgsFontUtils::setFromXmlChildNode( mFont, itemElem, "LabelFont" );

//font color
QDomNodeList fontColorList = itemElem.elementsByTagName( "FontColor" );
Expand Down
8 changes: 6 additions & 2 deletions src/core/composer/qgscomposerlegendstyle.cpp
Expand Up @@ -17,6 +17,7 @@

#include "qgscomposerlegendstyle.h"
#include "qgscomposition.h"
#include "qgsfontutils.h"
#include <QFont>
#include <QMap>
#include <QSettings>
Expand Down Expand Up @@ -61,7 +62,7 @@ void QgsComposerLegendStyle::writeXML( QString name, QDomElement& elem, QDomDocu
if ( mMarginMap[Left] != 0 ) styleElem.setAttribute( "marginLeft", QString::number( mMarginMap[Left] ) );
if ( mMarginMap[Right] != 0 ) styleElem.setAttribute( "marginRight", QString::number( mMarginMap[Right] ) );

styleElem.setAttribute( "font", mFont.toString() );
styleElem.appendChild( QgsFontUtils::toXmlElement( mFont, doc, "styleFont" ) );

elem.appendChild( styleElem );
}
Expand All @@ -71,7 +72,10 @@ void QgsComposerLegendStyle::readXML( const QDomElement& elem, const QDomDocumen
Q_UNUSED( doc );
if ( elem.isNull() ) return;

mFont.fromString( elem.attribute( "font" ) );
if ( !QgsFontUtils::setFromXmlChildNode( mFont, elem, "styleFont" ) )
{
mFont.fromString( elem.attribute( "font" ) );
}

mMarginMap[Top] = elem.attribute( "marginTop", "0" ).toDouble();
mMarginMap[Bottom] = elem.attribute( "marginBottom", "0" ).toDouble();
Expand Down
8 changes: 6 additions & 2 deletions src/core/composer/qgscomposermapgrid.cpp
Expand Up @@ -27,6 +27,7 @@
#include "qgssymbolv2.h"
#include "qgscoordinatereferencesystem.h"
#include "qgslogger.h"
#include "qgsfontutils.h"

#include <QPainter>
#include <QPen>
Expand Down Expand Up @@ -308,7 +309,7 @@ bool QgsComposerMapGrid::writeXML( QDomElement& elem, QDomDocument& doc ) const
mapGridElem.setAttribute( "topAnnotationDirection", mTopGridAnnotationDirection );
mapGridElem.setAttribute( "bottomAnnotationDirection", mBottomGridAnnotationDirection );
mapGridElem.setAttribute( "frameAnnotationDistance", QString::number( mAnnotationFrameDistance ) );
mapGridElem.setAttribute( "annotationFont", mGridAnnotationFont.toString() );
mapGridElem.appendChild( QgsFontUtils::toXmlElement( mGridAnnotationFont, doc, "annotationFontProperties" ) );
mapGridElem.setAttribute( "annotationFontColor", QgsSymbolLayerV2Utils::encodeColor( mGridAnnotationFontColor ) );
mapGridElem.setAttribute( "annotationPrecision", mGridAnnotationPrecision );
mapGridElem.setAttribute( "unit", mGridUnit );
Expand Down Expand Up @@ -429,7 +430,10 @@ bool QgsComposerMapGrid::readXML( const QDomElement& itemElem, const QDomDocumen
mTopGridAnnotationDirection = QgsComposerMapGrid::AnnotationDirection( itemElem.attribute( "topAnnotationDirection", "0" ).toInt() );
mBottomGridAnnotationDirection = QgsComposerMapGrid::AnnotationDirection( itemElem.attribute( "bottomAnnotationDirection", "0" ).toInt() );
mAnnotationFrameDistance = itemElem.attribute( "frameAnnotationDistance", "0" ).toDouble();
mGridAnnotationFont.fromString( itemElem.attribute( "annotationFont", "" ) );
if ( !QgsFontUtils::setFromXmlChildNode( mGridAnnotationFont, itemElem, "annotationFontProperties" ) )
{
mGridAnnotationFont.fromString( itemElem.attribute( "annotationFont", "" ) );
}
mGridAnnotationFontColor = QgsSymbolLayerV2Utils::decodeColor( itemElem.attribute( "annotationFontColor", "0,0,0,255" ) );
mGridAnnotationPrecision = itemElem.attribute( "annotationPrecision", "3" ).toInt();
int gridUnitInt = itemElem.attribute( "unit", QString::number( MapUnit ) ).toInt();
Expand Down
8 changes: 4 additions & 4 deletions src/core/composer/qgscomposerscalebar.cpp
Expand Up @@ -28,6 +28,7 @@
#include "qgsrectangle.h"
#include "qgsproject.h"
#include "qgssymbollayerv2utils.h"
#include "qgsfontutils.h"
#include <QDomDocument>
#include <QDomElement>
#include <QFontMetricsF>
Expand Down Expand Up @@ -668,7 +669,7 @@ bool QgsComposerScaleBar::writeXML( QDomElement& elem, QDomDocument & doc ) cons
composerScaleBarElem.setAttribute( "maxBarWidth", mMaxBarWidth );
composerScaleBarElem.setAttribute( "segmentMillimeters", QString::number( mSegmentMillimeters ) );
composerScaleBarElem.setAttribute( "numMapUnitsPerScaleBarUnit", QString::number( mNumMapUnitsPerScaleBarUnit ) );
composerScaleBarElem.setAttribute( "font", mFont.toString() );
composerScaleBarElem.appendChild( QgsFontUtils::toXmlElement( mFont, doc, "scaleBarFont" ) );
composerScaleBarElem.setAttribute( "outlineWidth", QString::number( mPen.widthF() ) );
composerScaleBarElem.setAttribute( "unitLabel", mUnitLabeling );
composerScaleBarElem.setAttribute( "units", mUnits );
Expand Down Expand Up @@ -755,10 +756,9 @@ bool QgsComposerScaleBar::readXML( const QDomElement& itemElem, const QDomDocume
mPen.setJoinStyle( mLineJoinStyle );
mLineCapStyle = QgsSymbolLayerV2Utils::decodePenCapStyle( itemElem.attribute( "lineCapStyle", "square" ) );
mPen.setCapStyle( mLineCapStyle );
QString fontString = itemElem.attribute( "font", "" );
if ( !fontString.isEmpty() )
if ( !QgsFontUtils::setFromXmlChildNode( mFont, itemElem, "scaleBarFont" ) )
{
mFont.fromString( fontString );
mFont.fromString( itemElem.attribute( "font", "" ) );
}

//colors
Expand Down
15 changes: 11 additions & 4 deletions src/core/composer/qgscomposertable.cpp
Expand Up @@ -19,6 +19,7 @@
#include "qgscomposertablecolumn.h"
#include "qgssymbollayerv2utils.h"
#include "qgscomposerutils.h"
#include "qgsfontutils.h"
#include <QPainter>
#include <QSettings>

Expand Down Expand Up @@ -267,10 +268,10 @@ void QgsComposerTable::setColumns( QList<QgsComposerTableColumn*> columns )
bool QgsComposerTable::tableWriteXML( QDomElement& elem, QDomDocument & doc ) const
{
elem.setAttribute( "lineTextDist", QString::number( mLineTextDistance ) );
elem.setAttribute( "headerFont", mHeaderFont.toString() );
elem.appendChild( QgsFontUtils::toXmlElement( mHeaderFont, doc, "headerFontProperties" ) );
elem.setAttribute( "headerFontColor", QgsSymbolLayerV2Utils::encodeColor( mHeaderFontColor ) );
elem.setAttribute( "headerHAlignment", QString::number(( int )mHeaderHAlignment ) );
elem.setAttribute( "contentFont", mContentFont.toString() );
elem.appendChild( QgsFontUtils::toXmlElement( mContentFont, doc, "contentFontProperties" ) );
elem.setAttribute( "contentFontColor", QgsSymbolLayerV2Utils::encodeColor( mContentFontColor ) );
elem.setAttribute( "gridStrokeWidth", QString::number( mGridStrokeWidth ) );
elem.setAttribute( "gridColor", QgsSymbolLayerV2Utils::encodeColor( mGridColor ) );
Expand All @@ -297,10 +298,16 @@ bool QgsComposerTable::tableReadXML( const QDomElement& itemElem, const QDomDocu
return false;
}

mHeaderFont.fromString( itemElem.attribute( "headerFont", "" ) );
if ( !QgsFontUtils::setFromXmlChildNode( mHeaderFont, itemElem, "headerFontProperties" ) )
{
mHeaderFont.fromString( itemElem.attribute( "headerFont", "" ) );
}
mHeaderFontColor = QgsSymbolLayerV2Utils::decodeColor( itemElem.attribute( "headerFontColor", "0,0,0,255" ) );
mHeaderHAlignment = QgsComposerTable::HeaderHAlignment( itemElem.attribute( "headerHAlignment", "0" ).toInt() );
mContentFont.fromString( itemElem.attribute( "contentFont", "" ) );
if ( !QgsFontUtils::setFromXmlChildNode( mContentFont, itemElem, "contentFontProperties" ) )
{
mContentFont.fromString( itemElem.attribute( "contentFont", "" ) );
}
mContentFontColor = QgsSymbolLayerV2Utils::decodeColor( itemElem.attribute( "contentFontColor", "0,0,0,255" ) );
mLineTextDistance = itemElem.attribute( "lineTextDist", "1.0" ).toDouble();
mGridStrokeWidth = itemElem.attribute( "gridStrokeWidth", "0.5" ).toDouble();
Expand Down
15 changes: 11 additions & 4 deletions src/core/composer/qgscomposertablev2.cpp
Expand Up @@ -20,6 +20,7 @@
#include "qgscomposertablecolumn.h"
#include "qgssymbollayerv2utils.h"
#include "qgscomposerframe.h"
#include "qgsfontutils.h"

QgsComposerTableV2::QgsComposerTableV2( QgsComposition *composition, bool createUndoCommands )
: QgsComposerMultiFrame( composition, createUndoCommands )
Expand Down Expand Up @@ -80,11 +81,11 @@ bool QgsComposerTableV2::writeXML( QDomElement& elem, QDomDocument & doc, bool i
elem.setAttribute( "emptyTableMode", QString::number(( int )mEmptyTableMode ) );
elem.setAttribute( "emptyTableMessage", mEmptyTableMessage );
elem.setAttribute( "showEmptyRows", mShowEmptyRows );
elem.setAttribute( "headerFont", mHeaderFont.toString() );
elem.appendChild( QgsFontUtils::toXmlElement( mHeaderFont, doc, "headerFontProperties" ) );
elem.setAttribute( "headerFontColor", QgsSymbolLayerV2Utils::encodeColor( mHeaderFontColor ) );
elem.setAttribute( "headerHAlignment", QString::number(( int )mHeaderHAlignment ) );
elem.setAttribute( "headerMode", QString::number(( int )mHeaderMode ) );
elem.setAttribute( "contentFont", mContentFont.toString() );
elem.appendChild( QgsFontUtils::toXmlElement( mContentFont, doc, "contentFontProperties" ) );
elem.setAttribute( "contentFontColor", QgsSymbolLayerV2Utils::encodeColor( mContentFontColor ) );
elem.setAttribute( "gridStrokeWidth", QString::number( mGridStrokeWidth ) );
elem.setAttribute( "gridColor", QgsSymbolLayerV2Utils::encodeColor( mGridColor ) );
Expand Down Expand Up @@ -124,11 +125,17 @@ bool QgsComposerTableV2::readXML( const QDomElement &itemElem, const QDomDocumen
mEmptyTableMode = QgsComposerTableV2::EmptyTableMode( itemElem.attribute( "emptyTableMode", "0" ).toInt() );
mEmptyTableMessage = itemElem.attribute( "emptyTableMessage", tr( "No matching records" ) );
mShowEmptyRows = itemElem.attribute( "showEmptyRows", "0" ).toInt();
mHeaderFont.fromString( itemElem.attribute( "headerFont", "" ) );
if ( !QgsFontUtils::setFromXmlChildNode( mHeaderFont, itemElem, "headerFontProperties" ) )
{
mHeaderFont.fromString( itemElem.attribute( "headerFont", "" ) );
}
mHeaderFontColor = QgsSymbolLayerV2Utils::decodeColor( itemElem.attribute( "headerFontColor", "0,0,0,255" ) );
mHeaderHAlignment = QgsComposerTableV2::HeaderHAlignment( itemElem.attribute( "headerHAlignment", "0" ).toInt() );
mHeaderMode = QgsComposerTableV2::HeaderMode( itemElem.attribute( "headerMode", "0" ).toInt() );
mContentFont.fromString( itemElem.attribute( "contentFont", "" ) );
if ( !QgsFontUtils::setFromXmlChildNode( mContentFont, itemElem, "contentFontProperties" ) )
{
mContentFont.fromString( itemElem.attribute( "contentFont", "" ) );
}
mContentFontColor = QgsSymbolLayerV2Utils::decodeColor( itemElem.attribute( "contentFontColor", "0,0,0,255" ) );
mCellMargin = itemElem.attribute( "cellMargin", "1.0" ).toDouble();
mGridStrokeWidth = itemElem.attribute( "gridStrokeWidth", "0.5" ).toDouble();
Expand Down
8 changes: 6 additions & 2 deletions src/core/qgsdiagramrendererv2.cpp
Expand Up @@ -19,6 +19,7 @@
#include "diagram/qgshistogramdiagram.h"
#include "qgsrendercontext.h"
#include "qgslayertreemodellegendnode.h"
#include "qgsfontutils.h"

#include <QDomElement>
#include <QPainter>
Expand Down Expand Up @@ -79,7 +80,10 @@ void QgsDiagramSettings::readXML( const QDomElement& elem, const QgsVectorLayer*
Q_UNUSED( layer );

enabled = ( elem.attribute( "enabled", "1" ) != "0" );
font.fromString( elem.attribute( "font" ) );
if ( !QgsFontUtils::setFromXmlChildNode( font, elem, "fontProperties" ) )
{
font.fromString( elem.attribute( "font" ) );
}
backgroundColor.setNamedColor( elem.attribute( "backgroundColor" ) );
backgroundColor.setAlpha( elem.attribute( "backgroundAlpha" ).toInt() );
size.setWidth( elem.attribute( "width" ).toDouble() );
Expand Down Expand Up @@ -206,7 +210,7 @@ void QgsDiagramSettings::writeXML( QDomElement& rendererElem, QDomDocument& doc,

QDomElement categoryElem = doc.createElement( "DiagramCategory" );
categoryElem.setAttribute( "enabled", enabled );
categoryElem.setAttribute( "font", font.toString() );
categoryElem.appendChild( QgsFontUtils::toXmlElement( font, doc, "fontProperties" ) );
categoryElem.setAttribute( "backgroundColor", backgroundColor.name() );
categoryElem.setAttribute( "backgroundAlpha", backgroundColor.alpha() );
categoryElem.setAttribute( "width", QString::number( size.width() ) );
Expand Down
43 changes: 43 additions & 0 deletions src/core/qgsfontutils.cpp
Expand Up @@ -277,3 +277,46 @@ QFont QgsFontUtils::getStandardTestFont( const QString& style, int pointsize )

return f;
}

QDomElement QgsFontUtils::toXmlElement( const QFont& font, QDomDocument& document, const QString& elementName )
{
QDomElement fontElem = document.createElement( elementName );
fontElem.setAttribute( "description", font.toString() );
fontElem.setAttribute( "style", font.styleName() );
return fontElem;
}

bool QgsFontUtils::setFromXmlElement( QFont& font, const QDomElement& element )
{
if ( element.isNull() )
{
return false;
}

font.fromString( element.attribute( "description" ) );
if ( element.hasAttribute( "style" ) )
{
( void )updateFontViaStyle( font, element.attribute( "style" ) );
}

return true;
}

bool QgsFontUtils::setFromXmlChildNode( QFont& font, const QDomElement& element, const QString& childNode )
{
if ( element.isNull() )
{
return false;
}

QDomNodeList nodeList = element.elementsByTagName( childNode );
if ( nodeList.size() > 0 )
{
QDomElement fontElem = nodeList.at( 0 ).toElement();
return setFromXmlElement( font, fontElem );
}
else
{
return false;
}
}
33 changes: 33 additions & 0 deletions src/core/qgsfontutils.h
Expand Up @@ -18,6 +18,7 @@

#include <QFont>
#include <QString>
#include <QDomElement>

class CORE_EXPORT QgsFontUtils
{
Expand Down Expand Up @@ -79,6 +80,38 @@ class CORE_EXPORT QgsFontUtils
* @note Added in QGIS 2.1
*/
static QFont getStandardTestFont( const QString& style = "Roman", int pointsize = 12 );

/**Returns a DOM element containing the properties of the font.
* @param document DOM document
* @param elementName name for DOM element
* @returns DOM element containing font settings
* @note added in QGIS 2.10
* @see setFromXmlElement
*/
static QDomElement toXmlElement( const QFont& font, QDomDocument &document, const QString &elementName );

/**Sets the properties of a font to match the properties stored in an XML element. Calling
* this will overwrite the current properties of the font.
* @param font font to update
* @param element DOM element
* @returns true if properties were successfully read from element
* @note added in QGIS 2.10
* @see toXmlElement
* @see setFromXmlChildNode
*/
static bool setFromXmlElement( QFont& font, const QDomElement& element );

/**Sets the properties of a font to match the properties stored in an XML child node. Calling
* this will overwrite the current properties of the font.
* @param font font to update
* @param element DOM element
* @param childNode name of child node
* @returns true if child node exists and properties were successfully read from node
* @note added in QGIS 2.10
* @see setFromXmlElement
* @see toXmlElement
*/
static bool setFromXmlChildNode( QFont& font, const QDomElement& element, const QString& childNode );
};

#endif // QGSFONTUTILS_H
2 changes: 1 addition & 1 deletion src/core/qgspallabeling.cpp
Expand Up @@ -4183,7 +4183,7 @@ void QgsPalLabeling::drawLabeling( QgsRenderContext& context )

//font
QFont dFont = palGeometry->definedFont();
QgsDebugMsgLevel( QString( "PAL font tmpLyr: %1, Style: %2" ).arg( tmpLyr.textFont.toString() ).arg( QFontInfo( tmpLyr.textFont ).styleName() ), 4 );
QgsDebugMsgLevel( QString( "PAL font tmpLyr: %1, Style: %2" ).arg( tmpLyr.textFont.toString() ).arg( tmpLyr.textFont.styleName() ), 4 );
QgsDebugMsgLevel( QString( "PAL font definedFont: %1, Style: %2" ).arg( dFont.toString() ).arg( dFont.styleName() ), 4 );
tmpLyr.textFont = dFont;

Expand Down

0 comments on commit 7a3a857

Please sign in to comment.