mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
[FEATURE] Add background shapes and svg symbols to labels
- Rectangle, square, circle and ellipse generated symbols - SVG background via new symbology, so uses cache - Add new gui class QgsSvgSelectorWidget, symbol selector setup culled from symbologyV2 - Does not include any associated data defined mappings, yet - Does not auto-search for missing SVGs, yet - Caveat: does not currently account for background size in PAL collision calculations (overlaps occur) - Allow direct update of QgsColorButton background
This commit is contained in:
parent
f832a34fa0
commit
b809723977
11
images/svg/geometric/Square_with-params.svg
Normal file
11
images/svg/geometric/Square_with-params.svg
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 9.0, SVG Export Plug-In -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20000303 Stylable//EN" "http://www.w3.org/TR/2000/03/WD-SVG-20000303/DTD/svg-20000303-stylable.dtd" [
|
||||
<!ENTITY st0 "fill:param(fill) #ffffff;fill-opacity:1;stroke-width:param(outline-width) 3;">
|
||||
<!ENTITY st1 "fill-rule:nonzero;clip-rule:nonzero;stroke:param(outline) #000000;stroke-miterlimit:4;stroke-opacity:1;">
|
||||
]>
|
||||
<svg width="109pt" height="109.5pt" viewBox="0 0 109 109.5" xml:space="preserve">
|
||||
<g id="Layer_x0020_1" style="&st1;">
|
||||
<path style="&st0;" d="M107.5,108H1.5V1.5h106V108z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 657 B |
@ -87,6 +87,26 @@ class QgsMapRenderer : QObject
|
||||
//MAP_UNITS probably supported in future versions
|
||||
};
|
||||
|
||||
/** Blending modes enum defining the available composition modes that can
|
||||
* be used when rendering a layer
|
||||
*/
|
||||
enum BlendMode
|
||||
{
|
||||
BlendNormal,
|
||||
BlendLighten,
|
||||
BlendScreen,
|
||||
BlendDodge,
|
||||
BlendAddition,
|
||||
BlendDarken,
|
||||
BlendMultiply,
|
||||
BlendBurn,
|
||||
BlendOverlay,
|
||||
BlendSoftLight,
|
||||
BlendHardLight,
|
||||
BlendDifference,
|
||||
BlendSubtract
|
||||
};
|
||||
|
||||
//! constructor
|
||||
QgsMapRenderer();
|
||||
|
||||
|
@ -48,6 +48,38 @@ class QgsPalLayerSettings
|
||||
MultiRight
|
||||
};
|
||||
|
||||
enum ShapeType
|
||||
{
|
||||
ShapeRectangle = 0,
|
||||
ShapeSquare,
|
||||
ShapeEllipse,
|
||||
ShapeCircle,
|
||||
ShapeSVG
|
||||
};
|
||||
|
||||
enum SizeType
|
||||
{
|
||||
SizeBuffer = 0,
|
||||
SizeFixed,
|
||||
SizePercent
|
||||
};
|
||||
|
||||
enum RotationType
|
||||
{
|
||||
RotationSync = 0,
|
||||
RotationOffset,
|
||||
RotationFixed
|
||||
};
|
||||
|
||||
/** Units used for option sizes, before being converted to rendered sizes */
|
||||
enum SizeUnit
|
||||
{
|
||||
Points = 0,
|
||||
MM,
|
||||
MapUnits,
|
||||
Percent
|
||||
};
|
||||
|
||||
// update mDataDefinedNames QList in constructor when adding/deleting enum value
|
||||
enum DataDefinedProperties
|
||||
{
|
||||
@ -100,6 +132,7 @@ class QgsPalLayerSettings
|
||||
QString textNamedStyle;
|
||||
QColor textColor;
|
||||
int textTransp;
|
||||
QPainter::CompositionMode blendMode;
|
||||
QColor previewBkgrdColor;
|
||||
bool enabled;
|
||||
int priority; // 0 = low, 10 = high
|
||||
@ -111,11 +144,34 @@ class QgsPalLayerSettings
|
||||
// disabled if both are zero
|
||||
int scaleMin;
|
||||
int scaleMax;
|
||||
double bufferSize; //buffer size (in mm)
|
||||
double bufferSize; //buffer size
|
||||
QColor bufferColor;
|
||||
int bufferTransp;
|
||||
QPainter::CompositionMode bufferBlendMode;
|
||||
Qt::PenJoinStyle bufferJoinStyle;
|
||||
bool bufferNoFill; //set interior of buffer to 100% transparent
|
||||
|
||||
// shape background
|
||||
bool shapeDraw;
|
||||
ShapeType shapeType;
|
||||
QString shapeSVGFile;
|
||||
SizeType shapeSizeType;
|
||||
QPointF shapeSize;
|
||||
SizeUnit shapeSizeUnits;
|
||||
RotationType shapeRotationType;
|
||||
double shapeRotation;
|
||||
QPointF shapeOffset;
|
||||
SizeUnit shapeOffsetUnits;
|
||||
QPointF shapeRadii;
|
||||
SizeUnit shapeRadiiUnits;
|
||||
QColor shapeFillColor;
|
||||
QColor shapeBorderColor;
|
||||
double shapeBorderWidth;
|
||||
SizeUnit shapeBorderWidthUnits;
|
||||
Qt::PenJoinStyle shapeJoinStyle;
|
||||
int shapeTransparency;
|
||||
QPainter::CompositionMode shapeBlendMode;
|
||||
|
||||
bool formatNumbers;
|
||||
int decimals;
|
||||
bool plusSign;
|
||||
@ -161,16 +217,18 @@ class QgsPalLayerSettings
|
||||
void removeDataDefinedProperty( DataDefinedProperties p );
|
||||
|
||||
/**Stores field names for data defined layer properties*/
|
||||
// QMap< DataDefinedProperties, int > dataDefinedProperties;
|
||||
// QMap< DataDefinedProperties, QString > dataDefinedProperties;
|
||||
|
||||
bool preserveRotation; // preserve predefined rotation data during label pin/unpin operations
|
||||
|
||||
/**Calculates pixel size (considering output size should be in pixel or map units, scale factors and oversampling)
|
||||
@param size size to convert
|
||||
@param c rendercontext
|
||||
@param buffer whether it buffer size being calculated
|
||||
@return font pixel size*/
|
||||
int sizeToPixel( double size, const QgsRenderContext& c , bool buffer = false ) const;
|
||||
/** Calculates pixel size (considering output size should be in pixel or map units, scale factors and optionally oversampling)
|
||||
* @param size size to convert
|
||||
* @param c rendercontext
|
||||
* @param unit SizeUnit enum value of size
|
||||
* @param rasterfactor whether to consider oversampling
|
||||
* @return font pixel size
|
||||
*/
|
||||
int sizeToPixel( double size, const QgsRenderContext& c , SizeUnit unit, bool rasterfactor ) const;
|
||||
|
||||
/** List of data defined enum names
|
||||
* @note adding in 1.9
|
||||
@ -198,6 +256,15 @@ class QgsPalLabeling : QgsLabelingEngineInterface
|
||||
%End
|
||||
|
||||
public:
|
||||
enum DrawLabelType
|
||||
{
|
||||
LabelText = 0,
|
||||
LabelBuffer,
|
||||
LabelShape,
|
||||
LabelSVG,
|
||||
LabelShadow
|
||||
};
|
||||
|
||||
QgsPalLabeling();
|
||||
~QgsPalLabeling();
|
||||
|
||||
@ -246,9 +313,19 @@ class QgsPalLabeling : QgsLabelingEngineInterface
|
||||
/*
|
||||
void drawLabelCandidateRect( pal::LabelPosition* lp, QPainter* painter, const QgsMapToPixel* xform );
|
||||
//!drawLabel
|
||||
void drawLabel( pal::LabelPosition* label, QPainter* painter, const QFont& f, const QColor& c, const QgsMapToPixel* xform, double bufferSize = -1,
|
||||
const QColor& bufferColor = QColor( 255, 255, 255 ), bool drawBuffer = false );
|
||||
void drawLabel( pal::LabelPosition* label, QgsRenderContext& context, QgsPalLayerSettings& tmplyr, DrawLabelType drawType );
|
||||
*/
|
||||
static void drawLabelBuffer( QPainter* p, QString text, const QFont& font, double size, QColor color , Qt::PenJoinStyle joinstyle = Qt::BevelJoin, bool noFill = false );
|
||||
static void drawLabelBuffer( QgsRenderContext& context, QString text, const QgsPalLayerSettings& tmpLyr );
|
||||
|
||||
static void drawLabelBackground( QgsRenderContext& context,
|
||||
const QgsPoint& centerPt, double labelRotation, double labelWidth, double labelHeight,
|
||||
const QgsPalLayerSettings& tmpLyr );
|
||||
|
||||
//! load/save engine settings to project file
|
||||
//! @note added in QGIS 1.9
|
||||
void loadEngineSettings();
|
||||
void saveEngineSettings();
|
||||
void clearEngineSettings();
|
||||
bool isStoredWithProject() const;
|
||||
void setStoredWithProject( bool store );
|
||||
};
|
||||
|
@ -86,6 +86,17 @@ class QgsColorButton: QPushButton
|
||||
*/
|
||||
void setAcceptLiveUpdates( bool accept );
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* Sets the background pixmap for the button based upon set color and transparency.
|
||||
* Call directly to update background after adding/removing QColorDialog::ShowAlphaChannel option
|
||||
* but the color has not changed, i.e. setColor() wouldn't update button and
|
||||
* you want the button to retain the set color's alpha component regardless
|
||||
*
|
||||
* @note added in 1.9
|
||||
*/
|
||||
void setButtonBackground();
|
||||
|
||||
signals:
|
||||
/**
|
||||
* Is emitted, whenever a new color is accepted. The color is always valid.
|
||||
|
@ -26,10 +26,14 @@
|
||||
#include "qgsexpressionbuilderdialog.h"
|
||||
#include "qgsexpression.h"
|
||||
#include "qgisapp.h"
|
||||
#include "qgsmaprenderer.h"
|
||||
#include "qgsproject.h"
|
||||
#include "qgssvgcache.h"
|
||||
#include "qgscharacterselectdialog.h"
|
||||
#include "qgssvgselectorwidget.h"
|
||||
|
||||
#include <QColorDialog>
|
||||
#include <QFileDialog>
|
||||
#include <QFontDialog>
|
||||
#include <QTextEdit>
|
||||
#include <QApplication>
|
||||
@ -299,6 +303,52 @@ QgsLabelingGui::QgsLabelingGui( QgsPalLabeling* lbl, QgsVectorLayer* layer, QgsM
|
||||
updateFontViaStyle( lyr.textNamedStyle );
|
||||
updateFont( mRefFont );
|
||||
|
||||
// shape background
|
||||
mShapeBackgroundGrpBx->setChecked( lyr.shapeDraw );
|
||||
mShapeTypeCmbBx->blockSignals( true );
|
||||
mShapeTypeCmbBx->setCurrentIndex( lyr.shapeType );
|
||||
mShapeTypeCmbBx->blockSignals( false );
|
||||
// set up SVG preview
|
||||
mSvgSelector = new QgsSvgSelectorWidget( this );
|
||||
mSVGSelectGrpBx->layout()->addWidget( mSvgSelector );
|
||||
mSvgSelector->setSvgPath( lyr.shapeSVGFile );
|
||||
|
||||
mShapeSizeCmbBx->setCurrentIndex( lyr.shapeSizeType );
|
||||
mShapeSizeXSpnBx->setValue( lyr.shapeSize.x() );
|
||||
mShapeSizeYSpnBx->setValue( lyr.shapeSize.y() );
|
||||
mShapeSizeUnitsCmbBx->setCurrentIndex( lyr.shapeSizeUnits - 1 );
|
||||
mShapeRotationCmbBx->setCurrentIndex( lyr.shapeRotationType );
|
||||
mShapeRotationDblSpnBx->setEnabled( lyr.shapeRotationType != QgsPalLayerSettings::RotationSync );
|
||||
mShapeRotationDblSpnBx->setValue( lyr.shapeRotation );
|
||||
mShapeOffsetXSpnBx->setValue( lyr.shapeOffset.x() );
|
||||
mShapeOffsetYSpnBx->setValue( lyr.shapeOffset.y() );
|
||||
mShapeOffsetUnitsCmbBx->setCurrentIndex( lyr.shapeOffsetUnits - 1 );
|
||||
mShapeRadiusXDbSpnBx->setValue( lyr.shapeRadii.x() );
|
||||
mShapeRadiusYDbSpnBx->setValue( lyr.shapeRadii.y() );
|
||||
mShapeRadiusUnitsCmbBx->setCurrentIndex( lyr.shapeRadiiUnits - 1 );
|
||||
|
||||
mShapeFillColorBtn->setColor( lyr.shapeFillColor );
|
||||
mShapeBorderColorBtn->setColor( lyr.shapeBorderColor );
|
||||
mShapeBorderWidthSpnBx->setValue( lyr.shapeBorderWidth );
|
||||
mShapeBorderWidthUnitsCmbBx->setCurrentIndex( lyr.shapeBorderWidthUnits - 1 );
|
||||
mShapePenStyleCmbBx->setPenJoinStyle( lyr.shapeJoinStyle );
|
||||
|
||||
connect( mShapeTranspSlider, SIGNAL( valueChanged( int ) ), mShapeTranspSpinBox, SLOT( setValue( int ) ) );
|
||||
connect( mShapeTranspSpinBox, SIGNAL( valueChanged( int ) ), mShapeTranspSlider, SLOT( setValue( int ) ) );
|
||||
mShapeTranspSpinBox->setValue( lyr.shapeTransparency );
|
||||
mShapeBlendCmbBx->setBlendMode( QgsMapRenderer::getBlendModeEnum( lyr.shapeBlendMode ) );
|
||||
|
||||
mLoadSvgParams = false;
|
||||
on_mShapeTypeCmbBx_currentIndexChanged( lyr.shapeType ); // force update of shape background gui
|
||||
|
||||
connect( mSvgSelector, SIGNAL( svgSelected( const QString& ) ), this, SLOT( updateSvgWidgets( const QString& ) ) );
|
||||
|
||||
mShapeCollisionsChkBx->setVisible( false ); // until implemented
|
||||
|
||||
// drop shadow
|
||||
mShadowGrpBx->setVisible( false ); // until implemented
|
||||
|
||||
|
||||
updateUi();
|
||||
|
||||
updateOptions();
|
||||
@ -448,7 +498,7 @@ QgsPalLayerSettings QgsLabelingGui::layerSettings()
|
||||
lyr.textFont = mRefFont;
|
||||
lyr.textNamedStyle = mFontStyleComboBox->currentText();
|
||||
lyr.textTransp = mFontTranspSpinBox->value();
|
||||
lyr.blendMode = ( QgsMapRenderer::BlendMode ) comboBlendMode->blendMode();
|
||||
lyr.blendMode = QgsMapRenderer::getCompositionMode(( QgsMapRenderer::BlendMode )comboBlendMode->blendMode() );
|
||||
lyr.previewBkgrdColor = mPreviewBackgroundBtn->color();
|
||||
lyr.enabled = chkEnableLabeling->isChecked();
|
||||
lyr.priority = sliderPriority->value();
|
||||
@ -473,12 +523,37 @@ QgsPalLayerSettings QgsLabelingGui::layerSettings()
|
||||
lyr.bufferSizeInMapUnits = ( mBufferUnitComboBox->currentIndex() == 1 );
|
||||
lyr.bufferJoinStyle = mBufferJoinStyleComboBox->penJoinStyle();
|
||||
lyr.bufferNoFill = !mBufferTranspFillChbx->isChecked();
|
||||
lyr.bufferBlendMode = ( QgsMapRenderer::BlendMode ) comboBufferBlendMode->blendMode();
|
||||
lyr.bufferBlendMode = QgsMapRenderer::getCompositionMode(( QgsMapRenderer::BlendMode )comboBufferBlendMode->blendMode() );
|
||||
}
|
||||
else
|
||||
{
|
||||
lyr.bufferSize = 0;
|
||||
}
|
||||
|
||||
// shape background
|
||||
lyr.shapeDraw = mShapeBackgroundGrpBx->isChecked();
|
||||
lyr.shapeType = ( QgsPalLayerSettings::ShapeType )mShapeTypeCmbBx->currentIndex();
|
||||
lyr.shapeSVGFile = mSvgSelector->currentSvgPath();
|
||||
|
||||
lyr.shapeSizeType = ( QgsPalLayerSettings::SizeType )mShapeSizeCmbBx->currentIndex();
|
||||
lyr.shapeSize = QPointF( mShapeSizeXSpnBx->value(), mShapeSizeYSpnBx->value() );
|
||||
lyr.shapeSizeUnits = ( QgsPalLayerSettings::SizeUnit )( mShapeSizeUnitsCmbBx->currentIndex() + 1 );
|
||||
lyr.shapeRotationType = ( QgsPalLayerSettings::RotationType )( mShapeRotationCmbBx->currentIndex() );
|
||||
lyr.shapeRotation = mShapeRotationDblSpnBx->value();
|
||||
lyr.shapeOffset = QPointF( mShapeOffsetXSpnBx->value(), mShapeOffsetYSpnBx->value() );
|
||||
lyr.shapeOffsetUnits = ( QgsPalLayerSettings::SizeUnit )( mShapeOffsetUnitsCmbBx->currentIndex() + 1 );
|
||||
lyr.shapeRadii = QPointF( mShapeRadiusXDbSpnBx->value(), mShapeRadiusYDbSpnBx->value() );
|
||||
lyr.shapeRadiiUnits = ( QgsPalLayerSettings::SizeUnit )( mShapeRadiusUnitsCmbBx->currentIndex() + 1 );
|
||||
|
||||
lyr.shapeFillColor = mShapeFillColorBtn->color();
|
||||
lyr.shapeBorderColor = mShapeBorderColorBtn->color();
|
||||
lyr.shapeBorderWidth = mShapeBorderWidthSpnBx->value();
|
||||
lyr.shapeBorderWidthUnits = ( QgsPalLayerSettings::SizeUnit )( mShapeBorderWidthUnitsCmbBx->currentIndex() + 1 );
|
||||
lyr.shapeJoinStyle = mShapePenStyleCmbBx->penJoinStyle();
|
||||
lyr.shapeTransparency = mShapeTranspSpinBox->value();
|
||||
lyr.shapeBlendMode = QgsMapRenderer::getCompositionMode(( QgsMapRenderer::BlendMode )mShapeBlendCmbBx->blendMode() );
|
||||
|
||||
|
||||
if ( chkFormattedNumbers->isChecked() )
|
||||
{
|
||||
lyr.formatNumbers = true;
|
||||
@ -821,13 +896,14 @@ void QgsLabelingGui::updatePreview()
|
||||
double previewRatio = mPreviewSize / fontSize;
|
||||
double bufferSize = 0.0;
|
||||
QString grpboxtitle;
|
||||
QString sampleTxt = tr( "Text/Buffer sample" );
|
||||
|
||||
if ( mFontSizeUnitComboBox->currentIndex() == 1 ) // map units
|
||||
{
|
||||
// TODO: maybe match current map zoom level instead?
|
||||
previewFont.setPointSize( mPreviewSize );
|
||||
mPreviewSizeSlider->setEnabled( true );
|
||||
grpboxtitle = tr( "Sample @ %1 pts (using map units)" ).arg( mPreviewSize );
|
||||
grpboxtitle = sampleTxt + tr( " @ %1 pts (using map units)" ).arg( mPreviewSize );
|
||||
|
||||
previewFont.setWordSpacing( previewRatio * mFontWordSpacingSpinBox->value() );
|
||||
previewFont.setLetterSpacing( QFont::AbsoluteSpacing, previewRatio * mFontLetterSpacingSpinBox->value() );
|
||||
@ -840,7 +916,7 @@ void QgsLabelingGui::updatePreview()
|
||||
}
|
||||
else // millimeters
|
||||
{
|
||||
grpboxtitle = tr( "Sample @ %1 pts (using map units, BUFFER IN MILLIMETERS)" ).arg( mPreviewSize );
|
||||
grpboxtitle = sampleTxt + tr( " @ %1 pts (using map units, BUFFER IN MILLIMETERS)" ).arg( mPreviewSize );
|
||||
bufferSize = spinBufferSize->value();
|
||||
}
|
||||
}
|
||||
@ -849,7 +925,7 @@ void QgsLabelingGui::updatePreview()
|
||||
{
|
||||
previewFont.setPointSize( fontSize );
|
||||
mPreviewSizeSlider->setEnabled( false );
|
||||
grpboxtitle = tr( "Sample" );
|
||||
grpboxtitle = sampleTxt;
|
||||
|
||||
if ( chkBuffer->isChecked() )
|
||||
{
|
||||
@ -859,7 +935,7 @@ void QgsLabelingGui::updatePreview()
|
||||
}
|
||||
else // map units
|
||||
{
|
||||
grpboxtitle = tr( "Sample (BUFFER NOT SHOWN, in map units)" );
|
||||
grpboxtitle = sampleTxt + tr( " (BUFFER NOT SHOWN, in map units)" );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1134,6 +1210,110 @@ void QgsLabelingGui::on_mYCoordinateComboBox_currentIndexChanged( const QString
|
||||
}
|
||||
}
|
||||
|
||||
void QgsLabelingGui::on_mShapeTypeCmbBx_currentIndexChanged( int index )
|
||||
{
|
||||
// shape background
|
||||
bool isRect = (( QgsPalLayerSettings::ShapeType )index == QgsPalLayerSettings::ShapeRectangle
|
||||
|| ( QgsPalLayerSettings::ShapeType )index == QgsPalLayerSettings::ShapeSquare );
|
||||
bool isSVG = (( QgsPalLayerSettings::ShapeType )index == QgsPalLayerSettings::ShapeSVG );
|
||||
|
||||
mShapePenStyleLine->setVisible( isRect );
|
||||
mShapePenStyleLabel->setVisible( isRect );
|
||||
mShapePenStyleCmbBx->setVisible( isRect );
|
||||
mShapeRadiusLabel->setVisible( isRect );
|
||||
mShapeRadiusFrame->setVisible( isRect );
|
||||
|
||||
mSvgSelector->setMinimumHeight( isSVG ? 240 : 0 );
|
||||
mSVGSelectGrpBx->setVisible( isSVG );
|
||||
// mSVGSelectGrpBx->setCollapsed( !isSVG );
|
||||
// symbology SVG renderer only supports size^2 scaling, so we only use the x size spinbox
|
||||
mShapeSizeYSpnBx->setVisible( !isSVG );
|
||||
|
||||
// SVG parameter setting doesn't support color's alpha component yet
|
||||
mShapeFillColorBtn->setColorDialogOptions( isSVG ? QColorDialog::ColorDialogOptions( 0 ) : QColorDialog::ShowAlphaChannel );
|
||||
mShapeFillColorBtn->setButtonBackground();
|
||||
mShapeBorderColorBtn->setColorDialogOptions( isSVG ? QColorDialog::ColorDialogOptions( 0 ) : QColorDialog::ShowAlphaChannel );
|
||||
mShapeBorderColorBtn->setButtonBackground();
|
||||
|
||||
// configure SVG parameter widgets
|
||||
mShapeSVGParamsBtn->setVisible( isSVG );
|
||||
QString svgPath = mSvgSelector->currentSvgPath();
|
||||
if ( isSVG )
|
||||
{
|
||||
mShapePenStyleLine->setVisible( true );
|
||||
updateSvgWidgets( svgPath );
|
||||
}
|
||||
else
|
||||
{
|
||||
mShapeFillColorLabel->setEnabled( true );
|
||||
mShapeFillColorBtn->setEnabled( true );
|
||||
mShapeBorderColorLabel->setEnabled( true );
|
||||
mShapeBorderColorBtn->setEnabled( true );
|
||||
mShapeBorderWidthLabel->setEnabled( true );
|
||||
mShapeBorderWidthSpnBx->setEnabled( true );
|
||||
}
|
||||
// TODO: fix overriding SVG symbol's border width units in QgsSvgCache
|
||||
// currently broken, fall back to symbol's
|
||||
mShapeBorderWidthUnitsCmbBx->setVisible( !isSVG );
|
||||
mShapeSVGUnitsLabel->setVisible( isSVG );
|
||||
}
|
||||
|
||||
void QgsLabelingGui::updateSvgWidgets( const QString& svgPath )
|
||||
{
|
||||
bool validSVG = false;
|
||||
QFileInfo finfo( svgPath );
|
||||
validSVG = finfo.exists();
|
||||
|
||||
if ( !validSVG )
|
||||
validSVG = ( QUrl( svgPath ).isValid() );
|
||||
|
||||
QString grpbxTitle = tr( "Select SVG symbol" );
|
||||
mSVGSelectGrpBx->setTitle( validSVG ? grpbxTitle + ": " + finfo.fileName() : grpbxTitle );
|
||||
|
||||
QColor fill, outline;
|
||||
double outlineWidth = 0.0;
|
||||
bool fillParam = false, outlineParam = false, outlineWidthParam = false;
|
||||
if ( validSVG )
|
||||
{
|
||||
QgsSvgCache::instance()->containsParams( svgPath, fillParam, fill, outlineParam, outline, outlineWidthParam, outlineWidth );
|
||||
}
|
||||
|
||||
mShapeSVGParamsBtn->setEnabled( validSVG && ( fillParam || outlineParam || outlineWidthParam ) );
|
||||
|
||||
mShapeFillColorLabel->setEnabled( validSVG && fillParam );
|
||||
mShapeFillColorBtn->setEnabled( validSVG && fillParam );
|
||||
if ( mLoadSvgParams && validSVG && fillParam )
|
||||
mShapeFillColorBtn->setColor( fill );
|
||||
|
||||
mShapeBorderColorLabel->setEnabled( validSVG && outlineParam );
|
||||
mShapeBorderColorBtn->setEnabled( validSVG && outlineParam );
|
||||
if ( mLoadSvgParams && validSVG && outlineParam )
|
||||
mShapeBorderColorBtn->setColor( outline );
|
||||
|
||||
mShapeBorderWidthLabel->setEnabled( validSVG && outlineWidthParam );
|
||||
mShapeBorderWidthSpnBx->setEnabled( validSVG && outlineWidthParam );
|
||||
if ( mLoadSvgParams && validSVG && outlineWidthParam )
|
||||
mShapeBorderWidthSpnBx->setValue( outlineWidth );
|
||||
|
||||
// TODO: fix overriding SVG symbol's border width units in QgsSvgCache
|
||||
// currently broken, fall back to symbol's
|
||||
//mShapeBorderWidthUnitsCmbBx->setEnabled( validSVG && outlineWidthParam );
|
||||
mShapeSVGUnitsLabel->setEnabled( validSVG && outlineWidthParam );
|
||||
}
|
||||
|
||||
void QgsLabelingGui::on_mShapeSVGParamsBtn_clicked()
|
||||
{
|
||||
QString svgPath = mSvgSelector->currentSvgPath();
|
||||
mLoadSvgParams = true;
|
||||
updateSvgWidgets( svgPath );
|
||||
mLoadSvgParams = false;
|
||||
}
|
||||
|
||||
void QgsLabelingGui::on_mShapeRotationCmbBx_currentIndexChanged( int index )
|
||||
{
|
||||
mShapeRotationDblSpnBx->setEnabled(( QgsPalLayerSettings::RotationType )index != QgsPalLayerSettings::RotationSync );
|
||||
}
|
||||
|
||||
void QgsLabelingGui::on_mPreviewTextEdit_textChanged( const QString & text )
|
||||
{
|
||||
lblFontPreview->setText( text );
|
||||
|
@ -25,6 +25,7 @@
|
||||
class QgsVectorLayer;
|
||||
class QgsMapCanvas;
|
||||
class QgsCharacterSelectorDialog;
|
||||
class QgsSvgSelectorWidget;
|
||||
|
||||
#include "qgspallabeling.h"
|
||||
|
||||
@ -53,6 +54,7 @@ class QgsLabelingGui : public QWidget, private Ui::QgsLabelingGuiBase
|
||||
void scrollPreview();
|
||||
void updateOptions();
|
||||
void updateQuadrant();
|
||||
void updateSvgWidgets( const QString& svgPath );
|
||||
|
||||
void on_mPreviewSizeSlider_valueChanged( int i );
|
||||
void on_mFontSizeSpinBox_valueChanged( double d );
|
||||
@ -69,6 +71,10 @@ class QgsLabelingGui : public QWidget, private Ui::QgsLabelingGuiBase
|
||||
void on_mXCoordinateComboBox_currentIndexChanged( const QString & text );
|
||||
void on_mYCoordinateComboBox_currentIndexChanged( const QString & text );
|
||||
|
||||
void on_mShapeTypeCmbBx_currentIndexChanged( int index );
|
||||
void on_mShapeRotationCmbBx_currentIndexChanged( int index );
|
||||
void on_mShapeSVGParamsBtn_clicked();
|
||||
|
||||
void on_mPreviewTextEdit_textChanged( const QString & text );
|
||||
void on_mPreviewTextBtn_clicked();
|
||||
void on_mPreviewBackgroundBtn_colorChanged( const QColor &color );
|
||||
@ -95,6 +101,7 @@ class QgsLabelingGui : public QWidget, private Ui::QgsLabelingGuiBase
|
||||
QgsMapCanvas* mMapCanvas;
|
||||
QFontDatabase mFontDB;
|
||||
QgsCharacterSelectorDialog* mCharDlg;
|
||||
QgsSvgSelectorWidget* mSvgSelector;
|
||||
|
||||
// background reference font
|
||||
QFont mRefFont;
|
||||
@ -104,6 +111,8 @@ class QgsLabelingGui : public QWidget, private Ui::QgsLabelingGuiBase
|
||||
int mYQuadOffset;
|
||||
int mMinPixelLimit;
|
||||
|
||||
bool mLoadSvgParams;
|
||||
|
||||
void disableDataDefinedAlignment();
|
||||
void enableDataDefinedAlignment();
|
||||
};
|
||||
|
@ -22,6 +22,19 @@
|
||||
QgsLabelPreview::QgsLabelPreview( QWidget* parent )
|
||||
: QLabel( parent )
|
||||
{
|
||||
mTmpLyr = new QgsPalLayerSettings();
|
||||
|
||||
// construct a device-based render context
|
||||
QgsMapToPixel newCoordXForm;
|
||||
newCoordXForm.setParameters( 0, 0, 0, 0 );
|
||||
mContext = new QgsRenderContext();
|
||||
mContext->setMapToPixel( newCoordXForm );
|
||||
}
|
||||
|
||||
QgsLabelPreview::~QgsLabelPreview()
|
||||
{
|
||||
delete mTmpLyr;
|
||||
delete mContext;
|
||||
}
|
||||
|
||||
void QgsLabelPreview::setTextColor( QColor color )
|
||||
@ -32,10 +45,13 @@ void QgsLabelPreview::setTextColor( QColor color )
|
||||
|
||||
void QgsLabelPreview::setBuffer( double size, QColor color, Qt::PenJoinStyle joinStyle, bool noFill )
|
||||
{
|
||||
mBufferSize = size * 88 / 25.4; //assume standard dpi for preview
|
||||
mBufferColor = color;
|
||||
mBufferJoinStyle = joinStyle;
|
||||
mBufferNoFill = noFill;
|
||||
mTmpLyr->bufferSize = size * 88 / 25.4; //assume standard dpi for preview;
|
||||
mTmpLyr->bufferSizeInMapUnits = false;
|
||||
mTmpLyr->bufferColor = color;
|
||||
mTmpLyr->bufferJoinStyle = joinStyle;
|
||||
mTmpLyr->bufferNoFill = noFill;
|
||||
|
||||
mTmpLyr->textFont = font();
|
||||
update();
|
||||
}
|
||||
|
||||
@ -49,17 +65,20 @@ void QgsLabelPreview::paintEvent( QPaintEvent *e )
|
||||
QFontMetrics fm( font() );
|
||||
|
||||
// otherwise thin buffers don't look like those on canvas
|
||||
if ( mBufferSize != 0 && mBufferSize < 1 )
|
||||
mBufferSize = 1;
|
||||
if ( mTmpLyr->bufferSize != 0 && mTmpLyr->bufferSize < 1 )
|
||||
mTmpLyr->bufferSize = 1;
|
||||
|
||||
double xtrans = 0;
|
||||
if ( mBufferSize != 0 )
|
||||
xtrans = mBufferSize / 4;
|
||||
if ( mTmpLyr->bufferSize != 0 )
|
||||
xtrans = mTmpLyr->bufferSize / 4;
|
||||
|
||||
p.translate( xtrans, fm.ascent() + 4 );
|
||||
|
||||
if ( mBufferSize != 0 )
|
||||
QgsPalLabeling::drawLabelBuffer( &p, text(), font(), mBufferSize, mBufferColor, mBufferJoinStyle, mBufferNoFill );
|
||||
if ( mTmpLyr->bufferSize != 0 )
|
||||
{
|
||||
mContext->setPainter( &p );
|
||||
QgsPalLabeling::drawLabelBuffer( *mContext, text(), *mTmpLyr );
|
||||
}
|
||||
|
||||
QPainterPath path;
|
||||
path.addText( 0, 0, font(), text() );
|
||||
|
@ -15,12 +15,17 @@
|
||||
#ifndef QGSLABELPREVIEW_H
|
||||
#define QGSLABELPREVIEW_H
|
||||
|
||||
#include "qgspallabeling.h"
|
||||
|
||||
#include <QLabel>
|
||||
|
||||
class QgsRenderContext;
|
||||
|
||||
class QgsLabelPreview : public QLabel
|
||||
{
|
||||
public:
|
||||
QgsLabelPreview( QWidget* parent = NULL );
|
||||
~QgsLabelPreview();
|
||||
|
||||
void setTextColor( QColor color );
|
||||
|
||||
@ -32,12 +37,12 @@ class QgsLabelPreview : public QLabel
|
||||
void paintEvent( QPaintEvent* e );
|
||||
|
||||
private:
|
||||
double mBufferSize;
|
||||
QColor mBufferColor;
|
||||
Qt::PenJoinStyle mBufferJoinStyle;
|
||||
bool mBufferNoFill;
|
||||
QgsPalLayerSettings* mTmpLyr;
|
||||
QColor mTextColor;
|
||||
QFont mFont;
|
||||
|
||||
// device-based render context
|
||||
QgsRenderContext* mContext;
|
||||
};
|
||||
|
||||
#endif // LABELPREVIEW_H
|
||||
|
@ -260,7 +260,8 @@ QFont QgsMapToolLabel::labelFontCurrentFeature()
|
||||
{
|
||||
if ( layerSettings.fontSizeInMapUnits )
|
||||
{
|
||||
font.setPixelSize( layerSettings.sizeToPixel( f.attribute( *sizeIt ).toDouble(), QgsRenderContext() ) );
|
||||
font.setPixelSize( layerSettings.sizeToPixel( f.attribute( *sizeIt ).toDouble(),
|
||||
QgsRenderContext(), QgsPalLayerSettings::MapUnits, true ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1191,4 +1191,40 @@ QPainter::CompositionMode QgsMapRenderer::getCompositionMode( const QgsMapRender
|
||||
}
|
||||
}
|
||||
|
||||
QgsMapRenderer::BlendMode QgsMapRenderer::getBlendModeEnum( const QPainter::CompositionMode blendMode )
|
||||
{
|
||||
// Map QPainter::CompositionMode to QgsMapRenderer::BlendNormal
|
||||
switch ( blendMode )
|
||||
{
|
||||
case QPainter::CompositionMode_SourceOver:
|
||||
return QgsMapRenderer::BlendNormal;
|
||||
case QPainter::CompositionMode_Lighten:
|
||||
return QgsMapRenderer::BlendLighten;
|
||||
case QPainter::CompositionMode_Screen:
|
||||
return QgsMapRenderer::BlendScreen;
|
||||
case QPainter::CompositionMode_ColorDodge:
|
||||
return QgsMapRenderer::BlendDodge;
|
||||
case QPainter::CompositionMode_Plus:
|
||||
return QgsMapRenderer::BlendAddition;
|
||||
case QPainter::CompositionMode_Darken:
|
||||
return QgsMapRenderer::BlendDarken;
|
||||
case QPainter::CompositionMode_Multiply:
|
||||
return QgsMapRenderer::BlendMultiply;
|
||||
case QPainter::CompositionMode_ColorBurn:
|
||||
return QgsMapRenderer::BlendBurn;
|
||||
case QPainter::CompositionMode_Overlay:
|
||||
return QgsMapRenderer::BlendOverlay;
|
||||
case QPainter::CompositionMode_SoftLight:
|
||||
return QgsMapRenderer::BlendSoftLight;
|
||||
case QPainter::CompositionMode_HardLight:
|
||||
return QgsMapRenderer::BlendHardLight;
|
||||
case QPainter::CompositionMode_Difference:
|
||||
return QgsMapRenderer::BlendDifference;
|
||||
case QPainter::CompositionMode_Exclusion:
|
||||
return QgsMapRenderer::BlendSubtract;
|
||||
default:
|
||||
return QgsMapRenderer::BlendNormal;
|
||||
}
|
||||
}
|
||||
|
||||
bool QgsMapRenderer::mDrawing = false;
|
||||
|
@ -252,7 +252,11 @@ class CORE_EXPORT QgsMapRenderer : public QObject
|
||||
void setLabelingEngine( QgsLabelingEngineInterface* iface );
|
||||
|
||||
//! Returns a QPainter::CompositionMode corresponding to a BlendMode
|
||||
//! Added in 1.9
|
||||
static QPainter::CompositionMode getCompositionMode( const QgsMapRenderer::BlendMode blendMode );
|
||||
//! Returns a BlendMode corresponding to a QPainter::CompositionMode
|
||||
//! Added in 1.9
|
||||
static QgsMapRenderer::BlendMode getBlendModeEnum( const QPainter::CompositionMode blendMode );
|
||||
|
||||
signals:
|
||||
|
||||
@ -347,7 +351,6 @@ class CORE_EXPORT QgsMapRenderer : public QObject
|
||||
|
||||
private:
|
||||
const QgsCoordinateTransform* tr( QgsMapLayer *layer );
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -49,7 +49,10 @@
|
||||
#include <qgsvectordataprovider.h>
|
||||
#include <qgsgeometry.h>
|
||||
#include <qgsmaprenderer.h>
|
||||
#include <qgsmarkersymbollayerv2.h>
|
||||
#include <qgsproject.h>
|
||||
#include "qgssymbolv2.h"
|
||||
#include "qgssymbollayerv2utils.h"
|
||||
#include <QMessageBox>
|
||||
|
||||
using namespace pal;
|
||||
@ -202,7 +205,7 @@ QgsPalLayerSettings::QgsPalLayerSettings()
|
||||
textNamedStyle = QString( "" );
|
||||
textColor = Qt::black;
|
||||
textTransp = 0;
|
||||
blendMode = QgsMapRenderer::BlendNormal;
|
||||
blendMode = QPainter::CompositionMode_SourceOver;
|
||||
previewBkgrdColor = Qt::white;
|
||||
enabled = false;
|
||||
priority = 5;
|
||||
@ -213,7 +216,7 @@ QgsPalLayerSettings::QgsPalLayerSettings()
|
||||
bufferSize = 1;
|
||||
bufferColor = Qt::white;
|
||||
bufferTransp = 0;
|
||||
bufferBlendMode = QgsMapRenderer::BlendNormal;
|
||||
bufferBlendMode = QPainter::CompositionMode_SourceOver;
|
||||
bufferNoFill = false;
|
||||
bufferJoinStyle = Qt::BevelJoin;
|
||||
formatNumbers = false;
|
||||
@ -247,6 +250,27 @@ QgsPalLayerSettings::QgsPalLayerSettings()
|
||||
multilineAlign = MultiLeft;
|
||||
preserveRotation = true;
|
||||
|
||||
// shape background
|
||||
shapeDraw = false;
|
||||
shapeType = ShapeRectangle;
|
||||
shapeSVGFile = QString();
|
||||
shapeSizeType = SizeBuffer;
|
||||
shapeSize = QPointF( 0.0, 0.0 );
|
||||
shapeSizeUnits = MM;
|
||||
shapeRotationType = RotationSync;
|
||||
shapeRotation = 0.0;
|
||||
shapeOffset = QPointF( 0.0, 0.0 );
|
||||
shapeOffsetUnits = MM;
|
||||
shapeRadii = QPointF( 0.0, 0.0 );
|
||||
shapeRadiiUnits = MM;
|
||||
shapeFillColor = Qt::white;
|
||||
shapeBorderColor = Qt::darkGray;
|
||||
shapeBorderWidth = 0.0;
|
||||
shapeBorderWidthUnits = MM;
|
||||
shapeJoinStyle = Qt::BevelJoin;
|
||||
shapeTransparency = 0;
|
||||
shapeBlendMode = QPainter::CompositionMode_SourceOver;
|
||||
|
||||
// data defined string values
|
||||
mDataDefinedNames << "Size";
|
||||
mDataDefinedNames << "Bold";
|
||||
@ -269,6 +293,8 @@ QgsPalLayerSettings::QgsPalLayerSettings()
|
||||
mDataDefinedNames << "FontTransp";
|
||||
mDataDefinedNames << "BufferTransp";
|
||||
mDataDefinedNames << "AlwaysShow";
|
||||
|
||||
// temp stuff for drawing different label types (don't copy)
|
||||
}
|
||||
|
||||
QgsPalLayerSettings::QgsPalLayerSettings( const QgsPalLayerSettings& s )
|
||||
@ -333,6 +359,28 @@ QgsPalLayerSettings::QgsPalLayerSettings( const QgsPalLayerSettings& s )
|
||||
multilineAlign = s.multilineAlign;
|
||||
preserveRotation = s.preserveRotation;
|
||||
|
||||
// shape background
|
||||
shapeDraw = s.shapeDraw;
|
||||
shapeType = s.shapeType;
|
||||
shapeSVGFile = s.shapeSVGFile;
|
||||
shapeSizeType = s.shapeSizeType;
|
||||
shapeSize = s.shapeSize;
|
||||
shapeSizeUnits = s.shapeSizeUnits;
|
||||
shapeRotationType = s.shapeRotationType;
|
||||
shapeRotation = s.shapeRotation;
|
||||
shapeOffset = s.shapeOffset;
|
||||
shapeOffsetUnits = s.shapeOffsetUnits;
|
||||
shapeRadii = s.shapeRadii;
|
||||
shapeRadiiUnits = s.shapeRadiiUnits;
|
||||
shapeFillColor = s.shapeFillColor;
|
||||
shapeBorderColor = s.shapeBorderColor;
|
||||
shapeBorderWidth = s.shapeBorderWidth;
|
||||
shapeBorderWidthUnits = s.shapeBorderWidthUnits;
|
||||
shapeJoinStyle = s.shapeJoinStyle;
|
||||
shapeTransparency = s.shapeTransparency;
|
||||
shapeBlendMode = s.shapeBlendMode;
|
||||
|
||||
|
||||
dataDefinedProperties = s.dataDefinedProperties;
|
||||
mDataDefinedNames = s.mDataDefinedNames;
|
||||
|
||||
@ -360,19 +408,22 @@ QgsExpression* QgsPalLayerSettings::getLabelExpression()
|
||||
return expression;
|
||||
}
|
||||
|
||||
static QColor _readColor( QgsVectorLayer* layer, QString property )
|
||||
static QColor _readColor( QgsVectorLayer* layer, QString property, QColor defaultColor = Qt::black, bool withAlpha = true )
|
||||
{
|
||||
int r = layer->customProperty( property + "R" ).toInt();
|
||||
int g = layer->customProperty( property + "G" ).toInt();
|
||||
int b = layer->customProperty( property + "B" ).toInt();
|
||||
return QColor( r, g, b );
|
||||
int r = layer->customProperty( property + "R", QVariant( defaultColor.red() ) ).toInt();
|
||||
int g = layer->customProperty( property + "G", QVariant( defaultColor.green() ) ).toInt();
|
||||
int b = layer->customProperty( property + "B", QVariant( defaultColor.blue() ) ).toInt();
|
||||
int a = withAlpha ? layer->customProperty( property + "A", QVariant( defaultColor.alpha() ) ).toInt() : 255;
|
||||
return QColor( r, g, b, a );
|
||||
}
|
||||
|
||||
static void _writeColor( QgsVectorLayer* layer, QString property, QColor color )
|
||||
static void _writeColor( QgsVectorLayer* layer, QString property, QColor color, bool withAlpha = true )
|
||||
{
|
||||
layer->setCustomProperty( property + "R", color.red() );
|
||||
layer->setCustomProperty( property + "G", color.green() );
|
||||
layer->setCustomProperty( property + "B", color.blue() );
|
||||
if ( withAlpha )
|
||||
layer->setCustomProperty( property + "A", color.alpha() );
|
||||
}
|
||||
|
||||
void QgsPalLayerSettings::readDataDefinedPropertyMap( QgsVectorLayer* layer,
|
||||
@ -526,9 +577,10 @@ void QgsPalLayerSettings::readFromLayer( QgsVectorLayer* layer )
|
||||
textFont.setStrikeOut( layer->customProperty( "labeling/fontStrikeout" ).toBool() );
|
||||
textFont.setLetterSpacing( QFont::AbsoluteSpacing, layer->customProperty( "labeling/fontLetterSpacing", QVariant( 0.0 ) ).toDouble() );
|
||||
textFont.setWordSpacing( layer->customProperty( "labeling/fontWordSpacing", QVariant( 0.0 ) ).toDouble() );
|
||||
textColor = _readColor( layer, "labeling/textColor" );
|
||||
textColor = _readColor( layer, "labeling/textColor", Qt::black, false );
|
||||
textTransp = layer->customProperty( "labeling/textTransp" ).toInt();
|
||||
blendMode = ( QgsMapRenderer::BlendMode ) layer->customProperty( "labeling/blendMode" ).toInt();
|
||||
blendMode = QgsMapRenderer::getCompositionMode(
|
||||
( QgsMapRenderer::BlendMode )layer->customProperty( "labeling/blendMode", QVariant( QgsMapRenderer::BlendNormal ) ).toUInt() );
|
||||
previewBkgrdColor = QColor( layer->customProperty( "labeling/previewBkgrdColor", QVariant( "#ffffff" ) ).toString() );
|
||||
enabled = layer->customProperty( "labeling/enabled" ).toBool();
|
||||
priority = layer->customProperty( "labeling/priority" ).toInt();
|
||||
@ -537,9 +589,10 @@ void QgsPalLayerSettings::readFromLayer( QgsVectorLayer* layer )
|
||||
scaleMin = layer->customProperty( "labeling/scaleMin" ).toInt();
|
||||
scaleMax = layer->customProperty( "labeling/scaleMax" ).toInt();
|
||||
bufferSize = layer->customProperty( "labeling/bufferSize" ).toDouble();
|
||||
bufferColor = _readColor( layer, "labeling/bufferColor" );
|
||||
bufferColor = _readColor( layer, "labeling/bufferColor", Qt::white, false );
|
||||
bufferTransp = layer->customProperty( "labeling/bufferTransp" ).toInt();
|
||||
bufferBlendMode = ( QgsMapRenderer::BlendMode ) layer->customProperty( "labeling/bufferBlendMode" ).toInt();
|
||||
bufferBlendMode = QgsMapRenderer::getCompositionMode(
|
||||
( QgsMapRenderer::BlendMode )layer->customProperty( "labeling/bufferBlendMode", QVariant( QgsMapRenderer::BlendNormal ) ).toUInt() );
|
||||
bufferJoinStyle = ( Qt::PenJoinStyle ) layer->customProperty( "labeling/bufferJoinStyle", QVariant( Qt::BevelJoin ) ).toUInt();
|
||||
bufferNoFill = layer->customProperty( "labeling/bufferNoFill", QVariant( false ) ).toBool();
|
||||
formatNumbers = layer->customProperty( "labeling/formatNumbers" ).toBool();
|
||||
@ -570,6 +623,32 @@ void QgsPalLayerSettings::readFromLayer( QgsVectorLayer* layer )
|
||||
multilineHeight = layer->customProperty( "labeling/multilineHeight", QVariant( 1.0 ) ).toDouble();
|
||||
multilineAlign = ( MultiLineAlign ) layer->customProperty( "labeling/multilineAlign", QVariant( MultiLeft ) ).toUInt();
|
||||
preserveRotation = layer->customProperty( "labeling/preserveRotation", QVariant( true ) ).toBool();
|
||||
|
||||
// shape background
|
||||
shapeDraw = layer->customProperty( "labeling/shapeDraw", QVariant( false ) ).toBool();
|
||||
shapeType = ( ShapeType ) layer->customProperty( "labeling/shapeType", QVariant( ShapeRectangle ) ).toUInt();
|
||||
shapeSVGFile = layer->customProperty( "labeling/shapeSVGFile", QVariant( "" ) ).toString();
|
||||
shapeSizeType = ( SizeType ) layer->customProperty( "labeling/shapeSizeType", QVariant( SizeBuffer ) ).toUInt();
|
||||
shapeSize = QPointF( layer->customProperty( "labeling/shapeSizeX", QVariant( 0.0 ) ).toDouble(),
|
||||
layer->customProperty( "labeling/shapeSizeY", QVariant( 0.0 ) ).toDouble() );
|
||||
shapeSizeUnits = ( SizeUnit )layer->customProperty( "labeling/shapeSizeUnits", QVariant( MM ) ).toUInt();
|
||||
shapeRotationType = ( RotationType ) layer->customProperty( "labeling/shapeRotationType", QVariant( RotationSync ) ).toUInt();
|
||||
shapeRotation = layer->customProperty( "labeling/shapeRotation", QVariant( 0.0 ) ).toDouble();
|
||||
shapeOffset = QPointF( layer->customProperty( "labeling/shapeOffsetX", QVariant( 0.0 ) ).toDouble(),
|
||||
layer->customProperty( "labeling/shapeOffsetY", QVariant( 0.0 ) ).toDouble() );
|
||||
shapeOffsetUnits = ( SizeUnit )layer->customProperty( "labeling/shapeOffsetUnits", QVariant( MM ) ).toUInt();
|
||||
shapeRadii = QPointF( layer->customProperty( "labeling/shapeRadiiX", QVariant( 0.0 ) ).toDouble(),
|
||||
layer->customProperty( "labeling/shapeRadiiY", QVariant( 0.0 ) ).toDouble() );
|
||||
shapeRadiiUnits = ( SizeUnit )layer->customProperty( "labeling/shapeRadiiUnits", QVariant( MM ) ).toUInt();
|
||||
shapeFillColor = _readColor( layer, "labeling/shapeFillColor", Qt::white, true );
|
||||
shapeBorderColor = _readColor( layer, "labeling/shapeBorderColor", Qt::darkGray, true );
|
||||
shapeBorderWidth = layer->customProperty( "labeling/shapeBorderWidth", QVariant( .0 ) ).toDouble();
|
||||
shapeBorderWidthUnits = ( SizeUnit )layer->customProperty( "labeling/shapeBorderWidthUnits", QVariant( MM ) ).toUInt();
|
||||
shapeJoinStyle = ( Qt::PenJoinStyle ) layer->customProperty( "labeling/shapeJoinStyle", QVariant( Qt::BevelJoin ) ).toUInt();
|
||||
shapeTransparency = layer->customProperty( "labeling/shapeTransparency", QVariant( 0 ) ).toInt();
|
||||
shapeBlendMode = QgsMapRenderer::getCompositionMode(
|
||||
( QgsMapRenderer::BlendMode )layer->customProperty( "labeling/shapeBlendMode", QVariant( QgsMapRenderer::BlendNormal ) ).toUInt() );
|
||||
|
||||
readDataDefinedPropertyMap( layer, dataDefinedProperties );
|
||||
}
|
||||
|
||||
@ -602,7 +681,7 @@ void QgsPalLayerSettings::writeToLayer( QgsVectorLayer* layer )
|
||||
|
||||
_writeColor( layer, "labeling/textColor", textColor );
|
||||
layer->setCustomProperty( "labeling/textTransp", textTransp );
|
||||
layer->setCustomProperty( "labeling/blendMode", ( unsigned int )blendMode );
|
||||
layer->setCustomProperty( "labeling/blendMode", QgsMapRenderer::getBlendModeEnum( blendMode ) );
|
||||
layer->setCustomProperty( "labeling/previewBkgrdColor", previewBkgrdColor.name() );
|
||||
layer->setCustomProperty( "labeling/enabled", enabled );
|
||||
layer->setCustomProperty( "labeling/priority", priority );
|
||||
@ -613,7 +692,7 @@ void QgsPalLayerSettings::writeToLayer( QgsVectorLayer* layer )
|
||||
layer->setCustomProperty( "labeling/bufferSize", bufferSize );
|
||||
_writeColor( layer, "labeling/bufferColor", bufferColor );
|
||||
layer->setCustomProperty( "labeling/bufferTransp", bufferTransp );
|
||||
layer->setCustomProperty( "labeling/bufferBlendMode", ( unsigned int )bufferBlendMode );
|
||||
layer->setCustomProperty( "labeling/bufferBlendMode", QgsMapRenderer::getBlendModeEnum( bufferBlendMode ) );
|
||||
layer->setCustomProperty( "labeling/bufferJoinStyle", ( unsigned int )bufferJoinStyle );
|
||||
layer->setCustomProperty( "labeling/bufferNoFill", bufferNoFill );
|
||||
layer->setCustomProperty( "labeling/formatNumbers", formatNumbers );
|
||||
@ -644,6 +723,31 @@ void QgsPalLayerSettings::writeToLayer( QgsVectorLayer* layer )
|
||||
layer->setCustomProperty( "labeling/multilineHeight", multilineHeight );
|
||||
layer->setCustomProperty( "labeling/multilineAlign", ( unsigned int )multilineAlign );
|
||||
layer->setCustomProperty( "labeling/preserveRotation", preserveRotation );
|
||||
|
||||
// shape background
|
||||
layer->setCustomProperty( "labeling/shapeDraw", shapeDraw );
|
||||
layer->setCustomProperty( "labeling/shapeType", ( unsigned int )shapeType );
|
||||
layer->setCustomProperty( "labeling/shapeSVGFile", shapeSVGFile );
|
||||
layer->setCustomProperty( "labeling/shapeSizeType", ( unsigned int )shapeSizeType );
|
||||
layer->setCustomProperty( "labeling/shapeSizeX", shapeSize.x() );
|
||||
layer->setCustomProperty( "labeling/shapeSizeY", shapeSize.y() );
|
||||
layer->setCustomProperty( "labeling/shapeSizeUnits", ( unsigned int )shapeSizeUnits );
|
||||
layer->setCustomProperty( "labeling/shapeRotationType", ( unsigned int )shapeRotationType );
|
||||
layer->setCustomProperty( "labeling/shapeRotation", shapeRotation );
|
||||
layer->setCustomProperty( "labeling/shapeOffsetX", shapeOffset.x() );
|
||||
layer->setCustomProperty( "labeling/shapeOffsetY", shapeOffset.y() );
|
||||
layer->setCustomProperty( "labeling/shapeOffsetUnits", ( unsigned int )shapeOffsetUnits );
|
||||
layer->setCustomProperty( "labeling/shapeRadiiX", shapeRadii.x() );
|
||||
layer->setCustomProperty( "labeling/shapeRadiiY", shapeRadii.y() );
|
||||
layer->setCustomProperty( "labeling/shapeRadiiUnits", ( unsigned int )shapeRadiiUnits );
|
||||
_writeColor( layer, "labeling/shapeFillColor", shapeFillColor, true );
|
||||
_writeColor( layer, "labeling/shapeBorderColor", shapeBorderColor, true );
|
||||
layer->setCustomProperty( "labeling/shapeBorderWidth", shapeBorderWidth );
|
||||
layer->setCustomProperty( "labeling/shapeBorderWidthUnits", ( unsigned int )shapeBorderWidthUnits );
|
||||
layer->setCustomProperty( "labeling/shapeJoinStyle", ( unsigned int )shapeJoinStyle );
|
||||
layer->setCustomProperty( "labeling/shapeTransparency", shapeTransparency );
|
||||
layer->setCustomProperty( "labeling/shapeBlendMode", QgsMapRenderer::getBlendModeEnum( shapeBlendMode ) );
|
||||
|
||||
writeDataDefinedPropertyMap( layer, dataDefinedProperties );
|
||||
}
|
||||
|
||||
@ -719,7 +823,7 @@ void QgsPalLayerSettings::calculateLabelSize( const QFontMetricsF* fm, QString t
|
||||
}
|
||||
else
|
||||
{
|
||||
text.append( dirSym + wrapchr ); // SymbolAbove or SymbolBelow
|
||||
text.prepend( dirSym + wrapchr ); // SymbolAbove or SymbolBelow
|
||||
}
|
||||
}
|
||||
|
||||
@ -808,11 +912,11 @@ void QgsPalLayerSettings::registerFeature( QgsVectorLayer* layer, QgsFeature& f
|
||||
if ( size.isValid() )
|
||||
{
|
||||
double sizeDouble = size.toDouble();
|
||||
if ( sizeDouble <= 0.0 || sizeToPixel( sizeDouble, context ) < 1 )
|
||||
if ( sizeDouble <= 0.0 || sizeToPixel( sizeDouble, context, fontSizeInMapUnits ? MapUnits : Points, true ) < 1 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
labelFont.setPixelSize( sizeToPixel( sizeDouble, context ) );
|
||||
labelFont.setPixelSize( sizeToPixel( sizeDouble, context, fontSizeInMapUnits ? MapUnits : Points, true ) );
|
||||
}
|
||||
}
|
||||
|
||||
@ -965,21 +1069,22 @@ void QgsPalLayerSettings::registerFeature( QgsVectorLayer* layer, QgsFeature& f
|
||||
}
|
||||
|
||||
// adjust offset of labels to match chosen unit and map scale
|
||||
// offsets match those of symbology: -x = left, -y = up
|
||||
double mapUntsPerMM = context.mapToPixel().mapUnitsPerPixel() * context.scaleFactor();
|
||||
if ( xOffset != 0 )
|
||||
{
|
||||
offsetX = xOffset;
|
||||
offsetX = xOffset; // must be positive to match symbology offset direction
|
||||
if ( !labelOffsetInMapUnits )
|
||||
{
|
||||
offsetX = xOffset * mapUntsPerMM; //convert offset from mm to map units
|
||||
offsetX *= mapUntsPerMM; //convert offset from mm to map units
|
||||
}
|
||||
}
|
||||
if ( yOffset != 0 )
|
||||
{
|
||||
offsetY = yOffset;
|
||||
offsetY = -yOffset; // must be negative to match symbology offset direction
|
||||
if ( !labelOffsetInMapUnits )
|
||||
{
|
||||
offsetY = yOffset * mapUntsPerMM; //convert offset from mm to map units
|
||||
offsetY *= mapUntsPerMM; //convert offset from mm to map units
|
||||
}
|
||||
}
|
||||
|
||||
@ -1174,23 +1279,27 @@ void QgsPalLayerSettings::registerFeature( QgsVectorLayer* layer, QgsFeature& f
|
||||
lbl->setIsPinned( labelIsPinned );
|
||||
}
|
||||
|
||||
int QgsPalLayerSettings::sizeToPixel( double size, const QgsRenderContext& c, bool buffer ) const
|
||||
int QgsPalLayerSettings::sizeToPixel( double size, const QgsRenderContext& c, SizeUnit unit, bool rasterfactor ) const
|
||||
{
|
||||
double pixelSize;
|
||||
if (( !buffer && fontSizeInMapUnits ) || ( buffer && bufferSizeInMapUnits ) )
|
||||
// if render context is that of device (i.e. not a scaled map), just return rounded size
|
||||
double pixelSize = size;
|
||||
double mapUnitsPerPixel = c.mapToPixel().mapUnitsPerPixel();
|
||||
|
||||
if ( mapUnitsPerPixel > 0.0 )
|
||||
{
|
||||
pixelSize = size / c.mapToPixel().mapUnitsPerPixel() * c.rasterScaleFactor();
|
||||
}
|
||||
else //font size in points, or buffer in mm
|
||||
{
|
||||
double ptsTomm = buffer ? 1 : 0.3527;
|
||||
// set font size from points to output size
|
||||
pixelSize = ptsTomm * size * c.scaleFactor() * c.rasterScaleFactor();
|
||||
if ( unit == MapUnits )
|
||||
{
|
||||
pixelSize = size / mapUnitsPerPixel * ( rasterfactor ? c.rasterScaleFactor() : 1 );
|
||||
}
|
||||
else // e.g. in points or mm
|
||||
{
|
||||
double ptsTomm = ( unit == Points ? 0.352778 : 1 );
|
||||
pixelSize = ptsTomm * size * c.scaleFactor() * ( rasterfactor ? c.rasterScaleFactor() : 1 );
|
||||
}
|
||||
}
|
||||
return ( int )( pixelSize + 0.5 );
|
||||
}
|
||||
|
||||
|
||||
// -------------
|
||||
|
||||
QgsPalLabeling::QgsPalLabeling()
|
||||
@ -1331,7 +1440,9 @@ int QgsPalLabeling::prepareLayer( QgsVectorLayer* layer, QSet<int>& attrIndices,
|
||||
l->setUpsidedownLabels( upsdnlabels );
|
||||
|
||||
// fix for font size in map units causing font to show pointsize at small map scales
|
||||
int pixelFontSize = lyr.sizeToPixel( lyr.textFont.pointSizeF(), ctx );
|
||||
int pixelFontSize = lyr.sizeToPixel( lyr.textFont.pointSizeF(), ctx,
|
||||
lyr.fontSizeInMapUnits ? QgsPalLayerSettings::MapUnits : QgsPalLayerSettings::Points,
|
||||
true );
|
||||
|
||||
if ( pixelFontSize < 1 )
|
||||
{
|
||||
@ -1650,30 +1761,29 @@ void QgsPalLabeling::drawLabeling( QgsRenderContext& context )
|
||||
}
|
||||
|
||||
const QgsPalLayerSettings& lyr = layer( layerNameUtf8 );
|
||||
QFont fontForLabel = lyr.textFont;
|
||||
QColor fontColor = lyr.textColor;
|
||||
int fontTransp = lyr.textTransp;
|
||||
QgsMapRenderer::BlendMode blendMode = lyr.blendMode;
|
||||
double bufferSize = lyr.bufferSize;
|
||||
QColor bufferColor = lyr.bufferColor;
|
||||
int bufferTransp = lyr.bufferTransp;
|
||||
QgsMapRenderer::BlendMode bufferBlendMode = lyr.bufferBlendMode;
|
||||
|
||||
// Copy to temp, editable layer settings
|
||||
// these settings will be changed by any data defined values, then used for rendering label components
|
||||
// settings may be adjusted during rendering of components
|
||||
QgsPalLayerSettings tmpLyr( lyr );
|
||||
|
||||
//apply data defined settings for the label
|
||||
//font size
|
||||
QVariant dataDefinedSize = palGeometry->dataDefinedValues().value( QgsPalLayerSettings::Size );
|
||||
if ( dataDefinedSize.isValid() )
|
||||
{
|
||||
fontForLabel.setPixelSize( lyr.sizeToPixel( dataDefinedSize.toDouble(), context ) );
|
||||
tmpLyr.textFont.setPixelSize( lyr.sizeToPixel( dataDefinedSize.toDouble(), context,
|
||||
( lyr.fontSizeInMapUnits ? QgsPalLayerSettings::MapUnits : QgsPalLayerSettings::Points ),
|
||||
true ) );
|
||||
}
|
||||
//font color
|
||||
QVariant dataDefinedColor = palGeometry->dataDefinedValues().value( QgsPalLayerSettings::Color );
|
||||
if ( dataDefinedColor.isValid() )
|
||||
{
|
||||
fontColor.setNamedColor( dataDefinedColor.toString() );
|
||||
if ( !fontColor.isValid() )
|
||||
tmpLyr.textColor.setNamedColor( dataDefinedColor.toString() );
|
||||
if ( !tmpLyr.textColor.isValid() )
|
||||
{
|
||||
fontColor = lyr.textColor;
|
||||
tmpLyr.textColor = lyr.textColor;
|
||||
}
|
||||
}
|
||||
//font transparency
|
||||
@ -1684,56 +1794,56 @@ void QgsPalLabeling::drawLabeling( QgsRenderContext& context )
|
||||
int ft = dataDefinedFontTransp.toInt( &ftOk );
|
||||
if ( ftOk && ft >= 0 && ft <= 100 )
|
||||
{
|
||||
fontTransp = ft;
|
||||
tmpLyr.textTransp = ft;
|
||||
}
|
||||
}
|
||||
fontColor.setAlphaF(( 100.0 - ( double )( fontTransp ) ) / 100.0 );
|
||||
tmpLyr.textColor.setAlphaF(( 100.0 - ( double )( tmpLyr.textTransp ) ) / 100.0 );
|
||||
|
||||
//font bold
|
||||
QVariant dataDefinedBold = palGeometry->dataDefinedValues().value( QgsPalLayerSettings::Bold );
|
||||
if ( dataDefinedBold.isValid() )
|
||||
{
|
||||
fontForLabel.setBold(( bool )dataDefinedBold.toInt() );
|
||||
tmpLyr.textFont.setBold(( bool ) dataDefinedBold.toInt() );
|
||||
}
|
||||
//font italic
|
||||
QVariant dataDefinedItalic = palGeometry->dataDefinedValues().value( QgsPalLayerSettings::Italic );
|
||||
if ( dataDefinedItalic.isValid() )
|
||||
{
|
||||
fontForLabel.setItalic(( bool ) dataDefinedItalic.toInt() );
|
||||
tmpLyr.textFont.setItalic(( bool ) dataDefinedItalic.toInt() );
|
||||
}
|
||||
//font underline
|
||||
QVariant dataDefinedUnderline = palGeometry->dataDefinedValues().value( QgsPalLayerSettings::Underline );
|
||||
if ( dataDefinedUnderline.isValid() )
|
||||
{
|
||||
fontForLabel.setUnderline(( bool ) dataDefinedUnderline.toInt() );
|
||||
tmpLyr.textFont.setUnderline(( bool ) dataDefinedUnderline.toInt() );
|
||||
}
|
||||
//font strikeout
|
||||
QVariant dataDefinedStrikeout = palGeometry->dataDefinedValues().value( QgsPalLayerSettings::Strikeout );
|
||||
if ( dataDefinedStrikeout.isValid() )
|
||||
{
|
||||
fontForLabel.setStrikeOut(( bool ) dataDefinedStrikeout.toInt() );
|
||||
tmpLyr.textFont.setStrikeOut(( bool ) dataDefinedStrikeout.toInt() );
|
||||
}
|
||||
//font family
|
||||
QVariant dataDefinedFontFamily = palGeometry->dataDefinedValues().value( QgsPalLayerSettings::Family );
|
||||
if ( dataDefinedFontFamily.isValid() )
|
||||
{
|
||||
fontForLabel.setFamily( dataDefinedFontFamily.toString() );
|
||||
tmpLyr.textFont.setFamily( dataDefinedFontFamily.toString() );
|
||||
}
|
||||
//buffer size
|
||||
QVariant dataDefinedBufferSize = palGeometry->dataDefinedValues().value( QgsPalLayerSettings::BufferSize );
|
||||
if ( dataDefinedBufferSize.isValid() )
|
||||
{
|
||||
bufferSize = dataDefinedBufferSize.toDouble();
|
||||
tmpLyr.bufferSize = dataDefinedBufferSize.toDouble();
|
||||
}
|
||||
|
||||
//buffer color
|
||||
QVariant dataDefinedBufferColor = palGeometry->dataDefinedValues().value( QgsPalLayerSettings::BufferColor );
|
||||
if ( dataDefinedBufferColor.isValid() )
|
||||
{
|
||||
bufferColor.setNamedColor( dataDefinedBufferColor.toString() );
|
||||
if ( !bufferColor.isValid() )
|
||||
tmpLyr.bufferColor.setNamedColor( dataDefinedBufferColor.toString() );
|
||||
if ( !tmpLyr.bufferColor.isValid() )
|
||||
{
|
||||
bufferColor = lyr.bufferColor;
|
||||
tmpLyr.bufferColor = lyr.bufferColor;
|
||||
}
|
||||
}
|
||||
//buffer transparency
|
||||
@ -1744,24 +1854,25 @@ void QgsPalLabeling::drawLabeling( QgsRenderContext& context )
|
||||
int bt = dataDefinedBufTransp.toInt( &btOk );
|
||||
if ( btOk && bt >= 0 && bt <= 100 )
|
||||
{
|
||||
bufferTransp = bt;
|
||||
tmpLyr.bufferTransp = bt;
|
||||
}
|
||||
}
|
||||
bufferColor.setAlphaF(( 100.0 - ( double )( bufferTransp ) ) / 100.0 );
|
||||
tmpLyr.bufferColor.setAlphaF(( 100.0 - ( double )( tmpLyr.bufferTransp ) ) / 100.0 );
|
||||
|
||||
if ( lyr.bufferSize != 0 )
|
||||
// Render the components of a label in reverse order
|
||||
// (backgrounds -> text)
|
||||
|
||||
if ( lyr.shapeDraw )
|
||||
{
|
||||
// Set the painter composition mode for the buffer
|
||||
painter->setCompositionMode( mMapRenderer->getCompositionMode( bufferBlendMode ) );
|
||||
|
||||
int bufferPixelSize = lyr.sizeToPixel( bufferSize, context, true );
|
||||
drawLabel( *it, painter, fontForLabel, fontColor, xform, bufferPixelSize, bufferColor, true );
|
||||
drawLabel( *it, context, tmpLyr, LabelShape );
|
||||
}
|
||||
|
||||
// Set the painter composition mode before rendering the label
|
||||
painter->setCompositionMode( mMapRenderer->getCompositionMode( blendMode ) );
|
||||
if ( lyr.bufferSize > 0 )
|
||||
{
|
||||
drawLabel( *it, context, tmpLyr, LabelBuffer );
|
||||
}
|
||||
|
||||
drawLabel( *it, painter, fontForLabel, fontColor, xform );
|
||||
drawLabel( *it, context, tmpLyr, LabelText );
|
||||
|
||||
if ( mLabelSearchTree )
|
||||
{
|
||||
@ -1889,152 +2000,400 @@ void QgsPalLabeling::drawLabelCandidateRect( pal::LabelPosition* lp, QPainter* p
|
||||
drawLabelCandidateRect( lp->getNextPart(), painter, xform );
|
||||
}
|
||||
|
||||
void QgsPalLabeling::drawLabel( pal::LabelPosition* label, QPainter* painter, const QFont& f, const QColor& c, const QgsMapToPixel* xform, double bufferPixelSize,
|
||||
const QColor& bufferColor, bool drawBuffer )
|
||||
void QgsPalLabeling::drawLabel( pal::LabelPosition* label, QgsRenderContext& context, QgsPalLayerSettings& tmpLyr, DrawLabelType drawType )
|
||||
{
|
||||
// NOTE: this is repeatedly called for multi-part labels
|
||||
QPainter* painter = context.painter();
|
||||
const QgsMapToPixel* xform = &context.mapToPixel();
|
||||
|
||||
QgsPoint outPt = xform->transform( label->getX(), label->getY() );
|
||||
|
||||
// TODO: optimize access :)
|
||||
const QgsPalLayerSettings& lyr = layer( QString::fromUtf8( label->getLayerName() ) );
|
||||
QString text = (( QgsPalGeometry* )label->getFeaturePart()->getUserGeometry() )->text();
|
||||
QString txt = ( label->getPartId() == -1 ? text : QString( text[label->getPartId()] ) );
|
||||
QFontMetricsF* labelfm = (( QgsPalGeometry* )label->getFeaturePart()->getUserGeometry() )->getLabelFontMetrics();
|
||||
|
||||
QString wrapchr = !lyr.wrapChar.isEmpty() ? lyr.wrapChar : QString( "\n" );
|
||||
|
||||
//add the direction symbol if needed
|
||||
if ( !txt.isEmpty() && lyr.placement == QgsPalLayerSettings::Line &&
|
||||
lyr.addDirectionSymbol )
|
||||
if ( drawType == QgsPalLabeling::LabelShape )
|
||||
{
|
||||
bool prependSymb = false;
|
||||
QString symb = lyr.rightDirectionSymbol;
|
||||
// get rotated label's center point
|
||||
QgsPoint centerPt( outPt );
|
||||
QgsPoint outPt2 = xform->transform( label->getX() + label->getWidth() / 2,
|
||||
label->getY() + label->getHeight() / 2 );
|
||||
|
||||
if ( label->getReversed() )
|
||||
{
|
||||
prependSymb = true;
|
||||
symb = lyr.leftDirectionSymbol;
|
||||
}
|
||||
double xc = outPt2.x() - outPt.x();
|
||||
double yc = outPt2.y() - outPt.y();
|
||||
|
||||
if ( lyr.reverseDirectionSymbol )
|
||||
double angle = -label->getAlpha();
|
||||
double xd = xc * cos( angle ) - yc * sin( angle );
|
||||
double yd = xc * sin( angle ) + yc * cos( angle );
|
||||
|
||||
centerPt.setX( centerPt.x() + xd );
|
||||
centerPt.setY( centerPt.y() + yd );
|
||||
|
||||
drawLabelBackground( context,
|
||||
centerPt,
|
||||
label->getAlpha() * 180 / M_PI, // converted to degrees
|
||||
label->getWidth(), // in map units
|
||||
label->getHeight(), // in map units
|
||||
tmpLyr );
|
||||
}
|
||||
|
||||
if ( drawType == QgsPalLabeling::LabelBuffer
|
||||
|| drawType == QgsPalLabeling::LabelText )
|
||||
{
|
||||
|
||||
// TODO: optimize access :)
|
||||
QString text = (( QgsPalGeometry* )label->getFeaturePart()->getUserGeometry() )->text();
|
||||
QString txt = ( label->getPartId() == -1 ? text : QString( text[label->getPartId()] ) );
|
||||
QFontMetricsF* labelfm = (( QgsPalGeometry* )label->getFeaturePart()->getUserGeometry() )->getLabelFontMetrics();
|
||||
|
||||
QString wrapchr = !tmpLyr.wrapChar.isEmpty() ? tmpLyr.wrapChar : QString( "\n" );
|
||||
|
||||
//add the direction symbol if needed
|
||||
if ( !txt.isEmpty() && tmpLyr.placement == QgsPalLayerSettings::Line &&
|
||||
tmpLyr.addDirectionSymbol )
|
||||
{
|
||||
if ( symb == lyr.rightDirectionSymbol )
|
||||
bool prependSymb = false;
|
||||
QString symb = tmpLyr.rightDirectionSymbol;
|
||||
|
||||
if ( label->getReversed() )
|
||||
{
|
||||
prependSymb = true;
|
||||
symb = lyr.leftDirectionSymbol;
|
||||
symb = tmpLyr.leftDirectionSymbol;
|
||||
}
|
||||
|
||||
if ( tmpLyr.reverseDirectionSymbol )
|
||||
{
|
||||
if ( symb == tmpLyr.rightDirectionSymbol )
|
||||
{
|
||||
prependSymb = true;
|
||||
symb = tmpLyr.leftDirectionSymbol;
|
||||
}
|
||||
else
|
||||
{
|
||||
prependSymb = false;
|
||||
symb = tmpLyr.rightDirectionSymbol;
|
||||
}
|
||||
}
|
||||
|
||||
if ( tmpLyr.placeDirectionSymbol == QgsPalLayerSettings::SymbolAbove )
|
||||
{
|
||||
prependSymb = true;
|
||||
symb = symb + wrapchr;
|
||||
}
|
||||
else if ( tmpLyr.placeDirectionSymbol == QgsPalLayerSettings::SymbolBelow )
|
||||
{
|
||||
prependSymb = false;
|
||||
symb = wrapchr + symb;
|
||||
}
|
||||
|
||||
if ( prependSymb )
|
||||
{
|
||||
txt.prepend( symb );
|
||||
}
|
||||
else
|
||||
{
|
||||
prependSymb = false;
|
||||
symb = lyr.rightDirectionSymbol;
|
||||
txt.append( symb );
|
||||
}
|
||||
}
|
||||
|
||||
if ( lyr.placeDirectionSymbol == QgsPalLayerSettings::SymbolAbove )
|
||||
{
|
||||
prependSymb = true;
|
||||
symb = symb + wrapchr;
|
||||
}
|
||||
else if ( lyr.placeDirectionSymbol == QgsPalLayerSettings::SymbolBelow )
|
||||
{
|
||||
prependSymb = false;
|
||||
symb = wrapchr + symb;
|
||||
}
|
||||
//QgsDebugMsg( "drawLabel " + txt );
|
||||
|
||||
if ( prependSymb )
|
||||
{
|
||||
txt.prepend( symb );
|
||||
}
|
||||
else
|
||||
{
|
||||
txt.append( symb );
|
||||
}
|
||||
}
|
||||
QStringList multiLineList = txt.split( wrapchr );
|
||||
int lines = multiLineList.size();
|
||||
|
||||
//QgsDebugMsg( "drawLabel " + QString::number( drawBuffer ) + " " + txt );
|
||||
|
||||
QStringList multiLineList = txt.split( wrapchr );
|
||||
int lines = multiLineList.size();
|
||||
|
||||
double labelWidest = 0.0;
|
||||
for ( int i = 0; i < lines; ++i )
|
||||
{
|
||||
double labelWidth = labelfm->width( multiLineList.at( i ) );
|
||||
if ( labelWidth > labelWidest )
|
||||
{
|
||||
labelWidest = labelWidth;
|
||||
}
|
||||
}
|
||||
|
||||
double labelHeight = labelfm->ascent() + labelfm->descent(); // ignore +1 for baseline
|
||||
|
||||
// needed to move bottom of text's descender to within bottom edge of label
|
||||
double ascentOffset = 0.25 * labelfm->ascent(); // labelfm->descent() is not enough
|
||||
|
||||
for ( int i = 0; i < lines; ++i )
|
||||
{
|
||||
painter->save();
|
||||
painter->translate( QPointF( outPt.x(), outPt.y() ) );
|
||||
painter->rotate( -label->getAlpha() * 180 / M_PI );
|
||||
|
||||
// scale down painter: the font size has been multiplied by raster scale factor
|
||||
// to workaround a Qt font scaling bug with small font sizes
|
||||
painter->scale( 1.0 / lyr.rasterCompressFactor, 1.0 / lyr.rasterCompressFactor );
|
||||
|
||||
// figure x offset for horizontal alignment of multiple lines
|
||||
double xMultiLineOffset = 0.0;
|
||||
if ( lines > 1 && lyr.multilineAlign != QgsPalLayerSettings::MultiLeft )
|
||||
double labelWidest = 0.0;
|
||||
for ( int i = 0; i < lines; ++i )
|
||||
{
|
||||
double labelWidth = labelfm->width( multiLineList.at( i ) );
|
||||
double labelWidthDiff = labelWidest - labelWidth;
|
||||
if ( lyr.multilineAlign == QgsPalLayerSettings::MultiCenter )
|
||||
if ( labelWidth > labelWidest )
|
||||
{
|
||||
labelWidthDiff /= 2;
|
||||
labelWidest = labelWidth;
|
||||
}
|
||||
xMultiLineOffset = labelWidthDiff;
|
||||
//QgsDebugMsg( QString( "xMultiLineOffset: %1" ).arg( xMultiLineOffset ) );
|
||||
}
|
||||
|
||||
double yMultiLineOffset = ( lines - 1 - i ) * labelHeight * lyr.multilineHeight;
|
||||
painter->translate( QPointF( xMultiLineOffset, - ascentOffset - yMultiLineOffset ) );
|
||||
double labelHeight = labelfm->ascent() + labelfm->descent(); // ignore +1 for baseline
|
||||
// double labelHighest = labelfm->height() + ( double )(( lines - 1 ) * labelHeight * tmpLyr.multilineHeight );
|
||||
|
||||
if ( drawBuffer )
|
||||
// needed to move bottom of text's descender to within bottom edge of label
|
||||
double ascentOffset = 0.25 * labelfm->ascent(); // labelfm->descent() is not enough
|
||||
|
||||
for ( int i = 0; i < lines; ++i )
|
||||
{
|
||||
// we're drawing buffer
|
||||
//drawLabelBuffer( painter, multiLineList.at( i ), f, bufferSize * lyr.vectorScaleFactor * lyr.rasterCompressFactor , bufferColor );
|
||||
drawLabelBuffer( painter, multiLineList.at( i ), f, bufferPixelSize , bufferColor, lyr.bufferJoinStyle, lyr.bufferNoFill );
|
||||
painter->save();
|
||||
painter->translate( QPointF( outPt.x(), outPt.y() ) );
|
||||
painter->rotate( -label->getAlpha() * 180 / M_PI );
|
||||
|
||||
// scale down painter: the font size has been multiplied by raster scale factor
|
||||
// to workaround a Qt font scaling bug with small font sizes
|
||||
painter->scale( 1.0 / tmpLyr.rasterCompressFactor, 1.0 / tmpLyr.rasterCompressFactor );
|
||||
|
||||
// figure x offset for horizontal alignment of multiple lines
|
||||
double xMultiLineOffset = 0.0;
|
||||
if ( lines > 1 && tmpLyr.multilineAlign != QgsPalLayerSettings::MultiLeft )
|
||||
{
|
||||
double labelWidth = labelfm->width( multiLineList.at( i ) );
|
||||
double labelWidthDiff = labelWidest - labelWidth;
|
||||
if ( tmpLyr.multilineAlign == QgsPalLayerSettings::MultiCenter )
|
||||
{
|
||||
labelWidthDiff /= 2;
|
||||
}
|
||||
xMultiLineOffset = labelWidthDiff;
|
||||
//QgsDebugMsg( QString( "xMultiLineOffset: %1" ).arg( xMultiLineOffset ) );
|
||||
}
|
||||
|
||||
double yMultiLineOffset = ( lines - 1 - i ) * labelHeight * tmpLyr.multilineHeight;
|
||||
painter->translate( QPointF( xMultiLineOffset, - ascentOffset - yMultiLineOffset ) );
|
||||
|
||||
if ( drawType == QgsPalLabeling::LabelBuffer )
|
||||
{
|
||||
// draw label's buffer
|
||||
drawLabelBuffer( context, multiLineList.at( i ), tmpLyr );
|
||||
}
|
||||
else
|
||||
{
|
||||
// draw label's text
|
||||
QPainterPath path;
|
||||
path.addText( 0, 0, tmpLyr.textFont, multiLineList.at( i ) );
|
||||
painter->setPen( Qt::NoPen );
|
||||
painter->setBrush( tmpLyr.textColor );
|
||||
painter->setCompositionMode( tmpLyr.blendMode );
|
||||
painter->drawPath( path );
|
||||
|
||||
// regular text draw, for testing
|
||||
// painter->setFont( tmpLyr.textFont );
|
||||
// painter->setPen( tmpLyr.textColor );
|
||||
// painter->setCompositionMode( tmpLyr.blendMode );
|
||||
// painter->drawText( 0, 0, multiLineList.at( i ) );
|
||||
|
||||
}
|
||||
painter->restore();
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: this used to be within above multi-line loop block, at end. (a mistake since 2010? [LS])
|
||||
if ( label->getNextPart() )
|
||||
drawLabel( label->getNextPart(), context, tmpLyr, drawType );
|
||||
}
|
||||
|
||||
void QgsPalLabeling::drawLabelBuffer( QgsRenderContext& context, QString text, const QgsPalLayerSettings& tmpLyr )
|
||||
{
|
||||
QPainter* p = context.painter();
|
||||
|
||||
QPainterPath path;
|
||||
path.addText( 0, 0, tmpLyr.textFont, text );
|
||||
QPen pen( tmpLyr.bufferColor );
|
||||
pen.setWidthF( tmpLyr.sizeToPixel( tmpLyr.bufferSize, context,
|
||||
( tmpLyr.bufferSizeInMapUnits ? QgsPalLayerSettings::MapUnits : QgsPalLayerSettings::MM ),
|
||||
true ) );
|
||||
pen.setJoinStyle( tmpLyr.bufferJoinStyle );
|
||||
p->setPen( pen );
|
||||
QColor tmpColor( tmpLyr.bufferColor );
|
||||
// honor pref for whether to fill buffer interior
|
||||
if ( tmpLyr.bufferNoFill )
|
||||
{
|
||||
tmpColor.setAlpha( 0 );
|
||||
}
|
||||
p->setBrush( tmpColor );
|
||||
p->setCompositionMode( tmpLyr.bufferBlendMode );
|
||||
p->drawPath( path );
|
||||
}
|
||||
|
||||
void QgsPalLabeling::drawLabelBackground( QgsRenderContext& context,
|
||||
const QgsPoint& centerPt, double labelRotation, double labelWidth, double labelHeight,
|
||||
const QgsPalLayerSettings& tmpLyr )
|
||||
{
|
||||
QPainter* p = context.painter();
|
||||
|
||||
// shared calculations between shapes and SVG
|
||||
|
||||
// aggregate angle
|
||||
double angle = 0.0; // as degrees
|
||||
if ( tmpLyr.shapeRotationType != QgsPalLayerSettings::RotationFixed )
|
||||
{
|
||||
angle = -labelRotation; // RotationSync
|
||||
|
||||
if ( tmpLyr.shapeRotationType == QgsPalLayerSettings::RotationOffset )
|
||||
{
|
||||
angle += tmpLyr.shapeRotation;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
angle += tmpLyr.shapeRotation; // RotationFixed
|
||||
}
|
||||
|
||||
// mm to map units conversion factor
|
||||
double mmToMapUnits = context.mapToPixel().mapUnitsPerPixel() * context.scaleFactor();
|
||||
|
||||
// convert offsets to map pixels
|
||||
double xoff = tmpLyr.sizeToPixel( tmpLyr.shapeOffset.x(), context, tmpLyr.shapeOffsetUnits );
|
||||
double yoff = tmpLyr.sizeToPixel( tmpLyr.shapeOffset.y(), context, tmpLyr.shapeOffsetUnits );
|
||||
|
||||
|
||||
// TODO: the following label-buffered generated shapes and SVG symbols should be moved into marker symbology classes
|
||||
|
||||
if ( tmpLyr.shapeType == QgsPalLayerSettings::ShapeSVG )
|
||||
{
|
||||
// all calculations done in shapeSizeUnits, which are then passed to symbology class for painting
|
||||
|
||||
if ( tmpLyr.shapeSVGFile.isEmpty() )
|
||||
return;
|
||||
|
||||
double sizeOut = 0.0;
|
||||
// only one size used for SVG sizing/scaling (no use of shapeSize.y() or Y field in gui)
|
||||
if ( tmpLyr.shapeSizeType == QgsPalLayerSettings::SizeFixed )
|
||||
{
|
||||
sizeOut = tmpLyr.shapeSize.x();
|
||||
}
|
||||
else if ( tmpLyr.shapeSizeType == QgsPalLayerSettings::SizeBuffer )
|
||||
{
|
||||
// add buffer to greatest dimension of label
|
||||
if ( labelWidth >= labelHeight )
|
||||
sizeOut = labelWidth;
|
||||
else if ( labelHeight > labelWidth )
|
||||
sizeOut = labelHeight;
|
||||
|
||||
// label size in map units, convert to shapeSizeUnits, if different
|
||||
if ( tmpLyr.shapeSizeUnits == QgsPalLayerSettings::MM )
|
||||
{
|
||||
sizeOut /= mmToMapUnits;
|
||||
}
|
||||
|
||||
// add buffer
|
||||
sizeOut += tmpLyr.shapeSize.x() * 2;
|
||||
}
|
||||
|
||||
// don't bother rendering symbols smaller than 1x1 pixels in size
|
||||
if ( tmpLyr.sizeToPixel( sizeOut, context, tmpLyr.shapeSizeUnits ) < 1 )
|
||||
return;
|
||||
|
||||
QgsStringMap map; // for SVG symbology marker
|
||||
map["name"] = tmpLyr.shapeSVGFile;
|
||||
map["size"] = QString::number( sizeOut );
|
||||
map["size_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit(
|
||||
tmpLyr.shapeSizeUnits == QgsPalLayerSettings::MapUnits ? QgsSymbolV2::MapUnit : QgsSymbolV2::MM );
|
||||
map["angle"] = QString::number( angle );
|
||||
|
||||
// offset is added into QPointF passed to SVG renderer
|
||||
// TODO: see why the marker renderer doesn't seem to translate offset *after* applying rotation
|
||||
//map["offset"] = QgsSymbolLayerV2Utils::encodePoint( tmpLyr.shapeOffset );
|
||||
//map["offset_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit(
|
||||
// tmpLyr.shapeOffsetUnits == QgsPalLayerSettings::MapUnits ? QgsSymbolV2::MapUnit : QgsSymbolV2::MM );
|
||||
|
||||
map["fill"] = tmpLyr.shapeFillColor.name();
|
||||
map["outline"] = tmpLyr.shapeBorderColor.name();
|
||||
map["outline-width"] = QString::number( tmpLyr.shapeBorderWidth );
|
||||
|
||||
// TODO: fix overriding SVG symbol's border width units in QgsSvgCache
|
||||
// currently broken, fall back to symbol's
|
||||
//map["outline_width_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit(
|
||||
// tmpLyr.shapeBorderWidthUnits == QgsPalLayerSettings::MapUnits ? QgsSymbolV2::MapUnit : QgsSymbolV2::MM );
|
||||
|
||||
QgsSymbolLayerV2* symL = QgsSvgMarkerSymbolLayerV2::create( map );
|
||||
QgsSvgMarkerSymbolLayerV2* svgM = static_cast<QgsSvgMarkerSymbolLayerV2*>( symL );
|
||||
QgsSymbolV2RenderContext svgContext( context, QgsSymbolV2::Mixed,
|
||||
( 100.0 - ( double )( tmpLyr.shapeTransparency ) ) / 100.0 );
|
||||
|
||||
p->save();
|
||||
p->setCompositionMode( tmpLyr.shapeBlendMode );
|
||||
svgM->renderPoint( QPointF( centerPt.x() + xoff, centerPt.y() + yoff ), svgContext );
|
||||
p->setCompositionMode( QPainter::CompositionMode_SourceOver ); // just to be sure
|
||||
p->restore();
|
||||
|
||||
delete svgM;
|
||||
svgM = 0;
|
||||
}
|
||||
else // Generated Shapes
|
||||
{
|
||||
// all calculations done in map units
|
||||
|
||||
double w = labelWidth;
|
||||
double h = labelHeight;
|
||||
|
||||
double xsize = tmpLyr.shapeSize.x() * ( tmpLyr.shapeSizeUnits == QgsPalLayerSettings::MM ? mmToMapUnits : 1 );
|
||||
double ysize = tmpLyr.shapeSize.y() * ( tmpLyr.shapeSizeUnits == QgsPalLayerSettings::MM ? mmToMapUnits : 1 );
|
||||
|
||||
if ( tmpLyr.shapeSizeType == QgsPalLayerSettings::SizeFixed )
|
||||
{
|
||||
w = xsize;
|
||||
h = ysize;
|
||||
}
|
||||
else if ( tmpLyr.shapeSizeType == QgsPalLayerSettings::SizeBuffer )
|
||||
{
|
||||
if ( tmpLyr.shapeType == QgsPalLayerSettings::ShapeSquare )
|
||||
{
|
||||
if ( w > h )
|
||||
h = w;
|
||||
else if ( h > w )
|
||||
w = h;
|
||||
}
|
||||
else if ( tmpLyr.shapeType == QgsPalLayerSettings::ShapeCircle )
|
||||
{
|
||||
// start with label bound by circle
|
||||
h = sqrt( pow( w, 2 ) + pow( h, 2 ) );
|
||||
w = h;
|
||||
}
|
||||
else if ( tmpLyr.shapeType == QgsPalLayerSettings::ShapeEllipse )
|
||||
{
|
||||
// start with label bound by ellipse
|
||||
h = h / sqrt( 2.0 ) * 2;
|
||||
w = w / sqrt( 2.0 ) * 2;
|
||||
}
|
||||
|
||||
w += xsize * 2;
|
||||
h += ysize * 2;
|
||||
}
|
||||
|
||||
// convert everything over to map pixels from here on
|
||||
|
||||
// offsets match those of symbology: -x = left, -y = up
|
||||
QRectF rect( -( w / 2 / context.mapToPixel().mapUnitsPerPixel() ),
|
||||
-( h / 2 / context.mapToPixel().mapUnitsPerPixel() ),
|
||||
( w / context.mapToPixel().mapUnitsPerPixel() ),
|
||||
( h / context.mapToPixel().mapUnitsPerPixel() ) );
|
||||
|
||||
if ( rect.isNull() )
|
||||
return;
|
||||
|
||||
p->save();
|
||||
p->translate( QPointF( centerPt.x() + xoff, centerPt.y() + yoff ) );
|
||||
p->rotate( angle );
|
||||
|
||||
if ( tmpLyr.shapeBorderWidth > 0 )
|
||||
{
|
||||
QPen pen( tmpLyr.shapeBorderColor );
|
||||
pen.setWidthF( tmpLyr.sizeToPixel( tmpLyr.shapeBorderWidth, context, tmpLyr.shapeBorderWidthUnits ) );
|
||||
if ( tmpLyr.shapeType == QgsPalLayerSettings::ShapeRectangle )
|
||||
pen.setJoinStyle( tmpLyr.shapeJoinStyle );
|
||||
p->setPen( pen );
|
||||
}
|
||||
else
|
||||
{
|
||||
// we're drawing real label
|
||||
QPainterPath path;
|
||||
path.addText( 0, 0, f, multiLineList.at( i ) );
|
||||
painter->setPen( Qt::NoPen );
|
||||
painter->setBrush( c );
|
||||
painter->drawPath( path );
|
||||
p->setPen( Qt::NoPen );
|
||||
}
|
||||
painter->restore();
|
||||
p->setBrush( tmpLyr.shapeFillColor );
|
||||
|
||||
if ( label->getNextPart() )
|
||||
drawLabel( label->getNextPart(), painter, f, c, xform, bufferPixelSize, bufferColor, drawBuffer );
|
||||
p->setOpacity(( 100.0 - ( double )( tmpLyr.shapeTransparency ) ) / 100.0 );
|
||||
p->setCompositionMode( tmpLyr.shapeBlendMode );
|
||||
|
||||
if ( tmpLyr.shapeType == QgsPalLayerSettings::ShapeRectangle
|
||||
|| tmpLyr.shapeType == QgsPalLayerSettings::ShapeSquare )
|
||||
{
|
||||
if ( tmpLyr.shapeRadiiUnits == QgsPalLayerSettings::Percent )
|
||||
{
|
||||
p->drawRoundedRect( rect, tmpLyr.shapeRadii.x(), tmpLyr.shapeRadii.y(), Qt::RelativeSize );
|
||||
}
|
||||
else
|
||||
{
|
||||
double xRadius = tmpLyr.sizeToPixel( tmpLyr.shapeRadii.x(), context, tmpLyr.shapeRadiiUnits );
|
||||
double yRadius = tmpLyr.sizeToPixel( tmpLyr.shapeRadii.y(), context, tmpLyr.shapeRadiiUnits );
|
||||
p->drawRoundedRect( rect, xRadius, yRadius );
|
||||
}
|
||||
}
|
||||
else if ( tmpLyr.shapeType == QgsPalLayerSettings::ShapeEllipse
|
||||
|| tmpLyr.shapeType == QgsPalLayerSettings::ShapeCircle )
|
||||
{
|
||||
p->drawEllipse( rect );
|
||||
}
|
||||
p->restore();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void QgsPalLabeling::drawLabelBuffer( QPainter* p, QString text, const QFont& font, double size, QColor color, Qt::PenJoinStyle joinstyle, bool noFill )
|
||||
{
|
||||
QPainterPath path;
|
||||
path.addText( 0, 0, font, text );
|
||||
QPen pen( color );
|
||||
pen.setWidthF( size );
|
||||
pen.setJoinStyle( joinstyle );
|
||||
p->setPen( pen );
|
||||
// honor pref for whether to fill buffer
|
||||
if ( noFill )
|
||||
{
|
||||
color.setAlpha( 0 );
|
||||
}
|
||||
p->setBrush( color );
|
||||
p->drawPath( path );
|
||||
}
|
||||
|
||||
void QgsPalLabeling::loadEngineSettings()
|
||||
|
@ -102,6 +102,38 @@ class CORE_EXPORT QgsPalLayerSettings
|
||||
MultiRight
|
||||
};
|
||||
|
||||
enum ShapeType
|
||||
{
|
||||
ShapeRectangle = 0,
|
||||
ShapeSquare,
|
||||
ShapeEllipse,
|
||||
ShapeCircle,
|
||||
ShapeSVG
|
||||
};
|
||||
|
||||
enum SizeType
|
||||
{
|
||||
SizeBuffer = 0,
|
||||
SizeFixed,
|
||||
SizePercent
|
||||
};
|
||||
|
||||
enum RotationType
|
||||
{
|
||||
RotationSync = 0,
|
||||
RotationOffset,
|
||||
RotationFixed
|
||||
};
|
||||
|
||||
/** Units used for option sizes, before being converted to rendered sizes */
|
||||
enum SizeUnit
|
||||
{
|
||||
Points = 0,
|
||||
MM,
|
||||
MapUnits,
|
||||
Percent
|
||||
};
|
||||
|
||||
// update mDataDefinedNames QList in constructor when adding/deleting enum value
|
||||
enum DataDefinedProperties
|
||||
{
|
||||
@ -154,7 +186,7 @@ class CORE_EXPORT QgsPalLayerSettings
|
||||
QString textNamedStyle;
|
||||
QColor textColor;
|
||||
int textTransp;
|
||||
QgsMapRenderer::BlendMode blendMode;
|
||||
QPainter::CompositionMode blendMode;
|
||||
QColor previewBkgrdColor;
|
||||
bool enabled;
|
||||
int priority; // 0 = low, 10 = high
|
||||
@ -166,12 +198,34 @@ class CORE_EXPORT QgsPalLayerSettings
|
||||
// disabled if both are zero
|
||||
int scaleMin;
|
||||
int scaleMax;
|
||||
double bufferSize; //buffer size (in mm)
|
||||
double bufferSize; //buffer size
|
||||
QColor bufferColor;
|
||||
int bufferTransp;
|
||||
QgsMapRenderer::BlendMode bufferBlendMode;
|
||||
QPainter::CompositionMode bufferBlendMode;
|
||||
Qt::PenJoinStyle bufferJoinStyle;
|
||||
bool bufferNoFill; //set interior of buffer to 100% transparent
|
||||
|
||||
// shape background
|
||||
bool shapeDraw;
|
||||
ShapeType shapeType;
|
||||
QString shapeSVGFile;
|
||||
SizeType shapeSizeType;
|
||||
QPointF shapeSize;
|
||||
SizeUnit shapeSizeUnits;
|
||||
RotationType shapeRotationType;
|
||||
double shapeRotation;
|
||||
QPointF shapeOffset;
|
||||
SizeUnit shapeOffsetUnits;
|
||||
QPointF shapeRadii;
|
||||
SizeUnit shapeRadiiUnits;
|
||||
QColor shapeFillColor;
|
||||
QColor shapeBorderColor;
|
||||
double shapeBorderWidth;
|
||||
SizeUnit shapeBorderWidthUnits;
|
||||
Qt::PenJoinStyle shapeJoinStyle;
|
||||
int shapeTransparency;
|
||||
QPainter::CompositionMode shapeBlendMode;
|
||||
|
||||
bool formatNumbers;
|
||||
int decimals;
|
||||
bool plusSign;
|
||||
@ -222,12 +276,14 @@ class CORE_EXPORT QgsPalLayerSettings
|
||||
|
||||
bool preserveRotation; // preserve predefined rotation data during label pin/unpin operations
|
||||
|
||||
/**Calculates pixel size (considering output size should be in pixel or map units, scale factors and oversampling)
|
||||
@param size size to convert
|
||||
@param c rendercontext
|
||||
@param buffer whether it buffer size being calculated
|
||||
@return font pixel size*/
|
||||
int sizeToPixel( double size, const QgsRenderContext& c , bool buffer = false ) const;
|
||||
/** Calculates pixel size (considering output size should be in pixel or map units, scale factors and optionally oversampling)
|
||||
* @param size size to convert
|
||||
* @param c rendercontext
|
||||
* @param unit SizeUnit enum value of size
|
||||
* @param rasterfactor whether to consider oversampling
|
||||
* @return font pixel size
|
||||
*/
|
||||
int sizeToPixel( double size, const QgsRenderContext& c , SizeUnit unit, bool rasterfactor = false ) const;
|
||||
|
||||
/** List of data defined enum names
|
||||
* @note adding in 1.9
|
||||
@ -282,6 +338,15 @@ class CORE_EXPORT QgsLabelCandidate
|
||||
class CORE_EXPORT QgsPalLabeling : public QgsLabelingEngineInterface
|
||||
{
|
||||
public:
|
||||
enum DrawLabelType
|
||||
{
|
||||
LabelText = 0,
|
||||
LabelBuffer,
|
||||
LabelShape,
|
||||
LabelSVG,
|
||||
LabelShadow
|
||||
};
|
||||
|
||||
QgsPalLabeling();
|
||||
~QgsPalLabeling();
|
||||
|
||||
@ -331,9 +396,13 @@ class CORE_EXPORT QgsPalLabeling : public QgsLabelingEngineInterface
|
||||
void drawLabelCandidateRect( pal::LabelPosition* lp, QPainter* painter, const QgsMapToPixel* xform );
|
||||
//!drawLabel
|
||||
//! @note not available in python bindings
|
||||
void drawLabel( pal::LabelPosition* label, QPainter* painter, const QFont& f, const QColor& c, const QgsMapToPixel* xform, double bufferSize = -1,
|
||||
const QColor& bufferColor = QColor( 255, 255, 255 ), bool drawBuffer = false );
|
||||
static void drawLabelBuffer( QPainter* p, QString text, const QFont& font, double size, QColor color , Qt::PenJoinStyle joinstyle = Qt::BevelJoin, bool noFill = false );
|
||||
void drawLabel( pal::LabelPosition* label, QgsRenderContext& context, QgsPalLayerSettings& tmpLyr, DrawLabelType drawType );
|
||||
|
||||
static void drawLabelBuffer( QgsRenderContext& context, QString text, const QgsPalLayerSettings& tmpLyr );
|
||||
|
||||
static void drawLabelBackground( QgsRenderContext& context,
|
||||
const QgsPoint& centerPt, double labelRotation, double labelWidth, double labelHeight,
|
||||
const QgsPalLayerSettings& tmpLyr );
|
||||
|
||||
//! load/save engine settings to project file
|
||||
//! @note added in QGIS 1.9
|
||||
|
@ -998,7 +998,7 @@ QgsSymbolLayerV2* QgsSvgMarkerSymbolLayerV2::create( const QgsStringMap& props )
|
||||
}
|
||||
|
||||
if ( props.contains( "size_unit" ) )
|
||||
m->setSizeUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( "size_unit" ) );
|
||||
m->setSizeUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( props["size_unit"] ) );
|
||||
if ( props.contains( "offset" ) )
|
||||
m->setOffset( QgsSymbolLayerV2Utils::decodePoint( props["offset"] ) );
|
||||
if ( props.contains( "offset_unit" ) )
|
||||
|
@ -34,6 +34,7 @@ symbology-ng/qgsellipsesymbollayerv2widget.cpp
|
||||
symbology-ng/qgspointdisplacementrendererwidget.cpp
|
||||
symbology-ng/qgsvectorfieldsymbollayerwidget.cpp
|
||||
symbology-ng/qgssymbolslistwidget.cpp
|
||||
symbology-ng/qgssvgselectorwidget.cpp
|
||||
symbology-ng/qgslayerpropertieswidget.cpp
|
||||
symbology-ng/qgssmartgroupeditordialog.cpp
|
||||
|
||||
@ -158,6 +159,7 @@ symbology-ng/qgsellipsesymbollayerv2widget.h
|
||||
symbology-ng/qgspointdisplacementrendererwidget.h
|
||||
symbology-ng/qgsvectorfieldsymbollayerwidget.h
|
||||
symbology-ng/qgssymbolslistwidget.h
|
||||
symbology-ng/qgssvgselectorwidget.h
|
||||
symbology-ng/qgslayerpropertieswidget.h
|
||||
symbology-ng/qgssmartgroupeditordialog.h
|
||||
|
||||
|
@ -105,6 +105,17 @@ class GUI_EXPORT QgsColorButton: public QPushButton
|
||||
*/
|
||||
void setAcceptLiveUpdates( bool accept ) { mAcceptLiveUpdates = accept; }
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* Sets the background pixmap for the button based upon set color and transparency.
|
||||
* Call directly to update background after adding/removing QColorDialog::ShowAlphaChannel option
|
||||
* but the color has not changed, i.e. setColor() wouldn't update button and
|
||||
* you want the button to retain the set color's alpha component regardless
|
||||
*
|
||||
* @note added in 1.9
|
||||
*/
|
||||
void setButtonBackground();
|
||||
|
||||
signals:
|
||||
/**
|
||||
* Is emitted, whenever a new color is accepted. The color is always valid.
|
||||
@ -133,13 +144,6 @@ class GUI_EXPORT QgsColorButton: public QPushButton
|
||||
private slots:
|
||||
void onButtonClicked();
|
||||
|
||||
/**
|
||||
* Sets the background pixmap for the button based upon set color and transparency.
|
||||
*
|
||||
* @note added in 1.9
|
||||
*/
|
||||
void setButtonBackground();
|
||||
|
||||
/**
|
||||
* Sets color for button, if valid.
|
||||
*
|
||||
|
291
src/gui/symbology-ng/qgssvgselectorwidget.cpp
Normal file
291
src/gui/symbology-ng/qgssvgselectorwidget.cpp
Normal file
@ -0,0 +1,291 @@
|
||||
/***************************************************************************
|
||||
qgssvgselectorwidget.cpp - group and preview selector for SVG files
|
||||
built off of work in qgssymbollayerv2widget
|
||||
|
||||
---------------------
|
||||
begin : April 2, 2013
|
||||
copyright : (C) 2013 by Larry Shaffer
|
||||
email : larrys at dakcarto dot com
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
#include "qgssvgselectorwidget.h"
|
||||
|
||||
#include "qgsapplication.h"
|
||||
#include "qgslogger.h"
|
||||
#include "qgssvgcache.h"
|
||||
#include "qgssymbollayerv2utils.h"
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QDir>
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QModelIndex>
|
||||
#include <QPixmapCache>
|
||||
#include <QSettings>
|
||||
#include <QStyle>
|
||||
#include <QTime>
|
||||
|
||||
|
||||
//--- QgsSvgSelectorListModel
|
||||
|
||||
QgsSvgSelectorListModel::QgsSvgSelectorListModel( QObject* parent )
|
||||
: QAbstractListModel( parent )
|
||||
{
|
||||
mSvgFiles = QgsSymbolLayerV2Utils::listSvgFiles();
|
||||
}
|
||||
|
||||
// Constructor to create model for icons in a specific path
|
||||
QgsSvgSelectorListModel::QgsSvgSelectorListModel( QObject* parent, QString path )
|
||||
: QAbstractListModel( parent )
|
||||
{
|
||||
mSvgFiles = QgsSymbolLayerV2Utils::listSvgFilesAt( path );
|
||||
}
|
||||
|
||||
int QgsSvgSelectorListModel::rowCount( const QModelIndex & parent ) const
|
||||
{
|
||||
Q_UNUSED( parent );
|
||||
return mSvgFiles.count();
|
||||
}
|
||||
|
||||
QVariant QgsSvgSelectorListModel::data( const QModelIndex & index, int role ) const
|
||||
{
|
||||
QString entry = mSvgFiles.at( index.row() );
|
||||
|
||||
if ( role == Qt::DecorationRole ) // icon
|
||||
{
|
||||
QPixmap pixmap;
|
||||
if ( !QPixmapCache::find( entry, pixmap ) )
|
||||
{
|
||||
// render SVG file
|
||||
QColor fill, outline;
|
||||
double outlineWidth;
|
||||
bool fillParam, outlineParam, outlineWidthParam;
|
||||
QgsSvgCache::instance()->containsParams( entry, fillParam, fill, outlineParam, outline, outlineWidthParam, outlineWidth );
|
||||
|
||||
bool fitsInCache; // should always fit in cache at these sizes (i.e. under 559 px ^ 2, or half cache size)
|
||||
const QImage& img = QgsSvgCache::instance()->svgAsImage( entry, 30.0, fill, outline, outlineWidth, 3.5 /*appr. 88 dpi*/, 1.0, fitsInCache );
|
||||
pixmap = QPixmap::fromImage( img );
|
||||
QPixmapCache::insert( entry, pixmap );
|
||||
}
|
||||
|
||||
return pixmap;
|
||||
}
|
||||
else if ( role == Qt::UserRole || role == Qt::ToolTipRole )
|
||||
{
|
||||
return entry;
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
|
||||
//--- QgsSvgSelectorGroupsModel
|
||||
|
||||
QgsSvgSelectorGroupsModel::QgsSvgSelectorGroupsModel( QObject* parent )
|
||||
: QStandardItemModel( parent )
|
||||
{
|
||||
QStringList svgPaths = QgsApplication::svgPaths();
|
||||
QStandardItem *parentItem = invisibleRootItem();
|
||||
|
||||
for ( int i = 0; i < svgPaths.size(); i++ )
|
||||
{
|
||||
QDir dir( svgPaths[i] );
|
||||
QStandardItem *baseGroup;
|
||||
|
||||
if ( dir.path().contains( QgsApplication::pkgDataPath() ) )
|
||||
{
|
||||
baseGroup = new QStandardItem( tr( "App Symbols" ) );
|
||||
}
|
||||
else if ( dir.path().contains( QgsApplication::qgisSettingsDirPath() ) )
|
||||
{
|
||||
baseGroup = new QStandardItem( tr( "User Symbols" ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
baseGroup = new QStandardItem( dir.dirName() );
|
||||
}
|
||||
baseGroup->setData( QVariant( svgPaths[i] ) );
|
||||
baseGroup->setEditable( false );
|
||||
baseGroup->setCheckable( false );
|
||||
baseGroup->setIcon( QgsApplication::style()->standardIcon( QStyle::SP_DirIcon ) );
|
||||
baseGroup->setToolTip( dir.path() );
|
||||
parentItem->appendRow( baseGroup );
|
||||
createTree( baseGroup );
|
||||
QgsDebugMsg( QString( "SVG base path %1: %2" ).arg( i ).arg( baseGroup->data().toString() ) );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsSvgSelectorGroupsModel::createTree( QStandardItem* &parentGroup )
|
||||
{
|
||||
QDir parentDir( parentGroup->data().toString() );
|
||||
foreach ( QString item, parentDir.entryList( QDir::Dirs | QDir::NoDotAndDotDot ) )
|
||||
{
|
||||
QStandardItem* group = new QStandardItem( item );
|
||||
group->setData( QVariant( parentDir.path() + "/" + item ) );
|
||||
group->setEditable( false );
|
||||
group->setCheckable( false );
|
||||
group->setToolTip( parentDir.path() + "/" + item );
|
||||
group->setIcon( QgsApplication::style()->standardIcon( QStyle::SP_DirIcon ) );
|
||||
parentGroup->appendRow( group );
|
||||
createTree( group );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-- QgsSvgSelectorWidget
|
||||
|
||||
QgsSvgSelectorWidget::QgsSvgSelectorWidget( QWidget* parent )
|
||||
: QWidget( parent )
|
||||
{
|
||||
setupUi( this );
|
||||
|
||||
mGroupsTreeView->setHeaderHidden( true );
|
||||
populateList();
|
||||
|
||||
connect( mImagesListView->selectionModel(), SIGNAL( currentChanged( const QModelIndex&, const QModelIndex& ) ),
|
||||
this, SLOT( svgSelectionChanged( const QModelIndex& ) ) );
|
||||
connect( mGroupsTreeView->selectionModel(), SIGNAL( currentChanged( const QModelIndex&, const QModelIndex& ) ),
|
||||
this, SLOT( populateIcons( const QModelIndex& ) ) );
|
||||
connect( this, SIGNAL( svgSelected( const QString& ) ), this, SLOT( updateCurrentSvgPath( const QString& ) ) );
|
||||
}
|
||||
|
||||
QgsSvgSelectorWidget::~QgsSvgSelectorWidget()
|
||||
{
|
||||
}
|
||||
|
||||
void QgsSvgSelectorWidget::setSvgPath( const QString& svgPath )
|
||||
{
|
||||
mCurrentSvgPath = svgPath;
|
||||
|
||||
mFileLineEdit->blockSignals( true );
|
||||
mFileLineEdit->setText( svgPath );
|
||||
mFileLineEdit->blockSignals( false );
|
||||
|
||||
mImagesListView->selectionModel()->blockSignals( true );
|
||||
QAbstractItemModel* m = mImagesListView->model();
|
||||
QItemSelectionModel* selModel = mImagesListView->selectionModel();
|
||||
for ( int i = 0; i < m->rowCount(); i++ )
|
||||
{
|
||||
QModelIndex idx( m->index( i, 0 ) );
|
||||
if ( m->data( idx ).toString() == svgPath )
|
||||
{
|
||||
selModel->select( idx, QItemSelectionModel::SelectCurrent );
|
||||
selModel->setCurrentIndex( idx, QItemSelectionModel::SelectCurrent );
|
||||
mImagesListView->scrollTo( idx );
|
||||
break;
|
||||
}
|
||||
}
|
||||
mImagesListView->selectionModel()->blockSignals( false );
|
||||
}
|
||||
|
||||
QString QgsSvgSelectorWidget::currentSvgPath() const
|
||||
{
|
||||
return mCurrentSvgPath;
|
||||
}
|
||||
|
||||
void QgsSvgSelectorWidget::updateCurrentSvgPath( const QString& svgPath )
|
||||
{
|
||||
mCurrentSvgPath = svgPath;
|
||||
}
|
||||
|
||||
void QgsSvgSelectorWidget::svgSelectionChanged( const QModelIndex& idx )
|
||||
{
|
||||
QString filePath = idx.data( Qt::UserRole ).toString();
|
||||
mFileLineEdit->setText( filePath );
|
||||
emit svgSelected( filePath );
|
||||
}
|
||||
|
||||
void QgsSvgSelectorWidget::populateIcons( const QModelIndex& idx )
|
||||
{
|
||||
QString path = idx.data( Qt::UserRole + 1 ).toString();
|
||||
|
||||
QgsSvgSelectorListModel* m = new QgsSvgSelectorListModel( mImagesListView, path );
|
||||
mImagesListView->setModel( m );
|
||||
|
||||
connect( mImagesListView->selectionModel(), SIGNAL( currentChanged( const QModelIndex&, const QModelIndex& ) ),
|
||||
this, SLOT( svgSelectionChanged( const QModelIndex& ) ) );
|
||||
}
|
||||
|
||||
void QgsSvgSelectorWidget::on_mFilePushButton_clicked()
|
||||
{
|
||||
QSettings settings;
|
||||
QString openDir = settings.value( "/UI/lastSVGMarkerDir", "." ).toString();
|
||||
|
||||
QString lineEditText = mFileLineEdit->text();
|
||||
if ( !lineEditText.isEmpty() )
|
||||
{
|
||||
QFileInfo openDirFileInfo( lineEditText );
|
||||
openDir = openDirFileInfo.path();
|
||||
}
|
||||
|
||||
QString file = QFileDialog::getOpenFileName( 0,
|
||||
tr( "Select SVG file" ),
|
||||
openDir,
|
||||
tr( "SVG files" ) + " (*.svg *.SVG)" );
|
||||
|
||||
activateWindow(); // return window focus
|
||||
|
||||
if ( file.isNull() )
|
||||
return;
|
||||
|
||||
QFileInfo fi( file );
|
||||
if ( !fi.exists() || !fi.isReadable() )
|
||||
{
|
||||
emit svgSelected( QString( "" ) );
|
||||
QMessageBox::critical( 0, tr( "Invalid file" ), tr( "Error, file does not exist or is not readable" ) );
|
||||
return;
|
||||
}
|
||||
settings.setValue( "/UI/lastSVGMarkerDir", fi.absolutePath() );
|
||||
mFileLineEdit->setText( file );
|
||||
emit svgSelected( file );
|
||||
}
|
||||
|
||||
void QgsSvgSelectorWidget::on_mFileLineEdit_textEdited( const QString& text )
|
||||
{
|
||||
if ( !QFileInfo( text ).exists() )
|
||||
{
|
||||
emit svgSelected( QString( "" ) );
|
||||
return;
|
||||
}
|
||||
emit svgSelected( text );
|
||||
}
|
||||
|
||||
void QgsSvgSelectorWidget::on_mFileLineEdit_editingFinished()
|
||||
{
|
||||
if ( !QFileInfo( mFileLineEdit->text() ).exists() )
|
||||
{
|
||||
QUrl url( mFileLineEdit->text() );
|
||||
if ( !url.isValid() )
|
||||
{
|
||||
emit svgSelected( QString( "" ) );
|
||||
QMessageBox::critical( 0, tr( "Invalid file url" ), tr( "Error, file URL is invalid" ) );
|
||||
return;
|
||||
}
|
||||
emit svgSelected( QString( "" ) );
|
||||
QMessageBox::critical( 0, tr( "Invalid file" ), tr( "Error, file does not exist or is not readable" ) );
|
||||
return;
|
||||
}
|
||||
emit svgSelected( mFileLineEdit->text() );
|
||||
}
|
||||
|
||||
void QgsSvgSelectorWidget::populateList()
|
||||
{
|
||||
QgsSvgSelectorGroupsModel* g = new QgsSvgSelectorGroupsModel( mGroupsTreeView );
|
||||
mGroupsTreeView->setModel( g );
|
||||
// Set the tree expanded at the first level
|
||||
int rows = g->rowCount( g->indexFromItem( g->invisibleRootItem() ) );
|
||||
for ( int i = 0; i < rows; i++ )
|
||||
{
|
||||
mGroupsTreeView->setExpanded( g->indexFromItem( g->item( i ) ), true );
|
||||
}
|
||||
|
||||
// Initally load the icons in the List view without any grouping
|
||||
QgsSvgSelectorListModel* m = new QgsSvgSelectorListModel( mImagesListView );
|
||||
mImagesListView->setModel( m );
|
||||
}
|
99
src/gui/symbology-ng/qgssvgselectorwidget.h
Normal file
99
src/gui/symbology-ng/qgssvgselectorwidget.h
Normal file
@ -0,0 +1,99 @@
|
||||
/***************************************************************************
|
||||
qgssvgselectorwidget.h - group and preview selector for SVG files
|
||||
built off of work in qgssymbollayerv2widget
|
||||
|
||||
---------------------
|
||||
begin : April 2, 2013
|
||||
copyright : (C) 2013 by Larry Shaffer
|
||||
email : larrys at dakcarto dot com
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
#ifndef QGSSVGSELECTORWIDGET_H
|
||||
#define QGSSVGSELECTORWIDGET_H
|
||||
|
||||
#include "ui_widget_svgselector.h"
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QStandardItemModel>
|
||||
#include <QWidget>
|
||||
|
||||
class QLayout;
|
||||
class QLineEdit;
|
||||
class QListView;
|
||||
class QPushButton;
|
||||
class QTreeView;
|
||||
|
||||
class GUI_EXPORT QgsSvgSelectorListModel : public QAbstractListModel
|
||||
{
|
||||
public:
|
||||
QgsSvgSelectorListModel( QObject* parent );
|
||||
|
||||
// Constructor to create model for icons in a specific path
|
||||
QgsSvgSelectorListModel( QObject* parent, QString path );
|
||||
|
||||
int rowCount( const QModelIndex & parent = QModelIndex() ) const;
|
||||
|
||||
QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const;
|
||||
|
||||
protected:
|
||||
QStringList mSvgFiles;
|
||||
};
|
||||
|
||||
|
||||
class GUI_EXPORT QgsSvgSelectorGroupsModel : public QStandardItemModel
|
||||
{
|
||||
public:
|
||||
QgsSvgSelectorGroupsModel( QObject* parent );
|
||||
|
||||
private:
|
||||
void createTree( QStandardItem* &parentGroup );
|
||||
};
|
||||
|
||||
|
||||
class GUI_EXPORT QgsSvgSelectorWidget : public QWidget, private Ui::WidgetSvgSelector
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QgsSvgSelectorWidget( QWidget* parent = 0 );
|
||||
~QgsSvgSelectorWidget();
|
||||
|
||||
static QgsSvgSelectorWidget* create( QWidget* parent = 0 ) { return new QgsSvgSelectorWidget( parent ); }
|
||||
|
||||
QString currentSvgPath() const;
|
||||
|
||||
QTreeView* groupsTreeView() { return mGroupsTreeView; }
|
||||
QListView* imagesListView() { return mImagesListView; }
|
||||
QLineEdit* filePathLineEdit() { return mFileLineEdit; }
|
||||
QPushButton* filePathButton() { return mFilePushButton; }
|
||||
QLayout* selectorLayout() { return this->layout(); }
|
||||
|
||||
public slots:
|
||||
void setSvgPath( const QString& svgPath );
|
||||
|
||||
signals:
|
||||
void svgSelected( const QString& path );
|
||||
|
||||
protected:
|
||||
void populateList();
|
||||
|
||||
private slots:
|
||||
void populateIcons( const QModelIndex& idx );
|
||||
void svgSelectionChanged( const QModelIndex& idx );
|
||||
void updateCurrentSvgPath( const QString& svgPath );
|
||||
|
||||
void on_mFilePushButton_clicked();
|
||||
void on_mFileLineEdit_textEdited( const QString& text );
|
||||
void on_mFileLineEdit_editingFinished();
|
||||
|
||||
private:
|
||||
QString mCurrentSvgPath;
|
||||
};
|
||||
|
||||
#endif // QGSSVGSELECTORWIDGET_H
|
File diff suppressed because it is too large
Load Diff
117
src/ui/symbollayer/widget_svgselector.ui
Normal file
117
src/ui/symbollayer/widget_svgselector.ui
Normal file
@ -0,0 +1,117 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>WidgetSvgSelector</class>
|
||||
<widget class="QWidget" name="WidgetSvgSelector">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>405</width>
|
||||
<height>490</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="mImagesLabel">
|
||||
<property name="text">
|
||||
<string>SVG Images</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="mGroupsLabel">
|
||||
<property name="text">
|
||||
<string>SVG Groups</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QTreeView" name="mGroupsTreeView">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>3</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QListView" name="mImagesListView">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>5</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>32</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="movement">
|
||||
<enum>QListView::Static</enum>
|
||||
</property>
|
||||
<property name="resizeMode">
|
||||
<enum>QListView::Adjust</enum>
|
||||
</property>
|
||||
<property name="layoutMode">
|
||||
<enum>QListView::Batched</enum>
|
||||
</property>
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="gridSize">
|
||||
<size>
|
||||
<width>36</width>
|
||||
<height>36</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="viewMode">
|
||||
<enum>QListView::IconMode</enum>
|
||||
</property>
|
||||
<property name="uniformItemSizes">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<layout class="QHBoxLayout" name="mFileLayout">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="mFileLineEdit"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="mFilePushButton">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>mImagesListView</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
Loading…
x
Reference in New Issue
Block a user