30#include <QDoubleValidator>
33#include <QImageReader>
36#include <QProgressDialog>
38#include <QSvgRenderer>
40#include "moc_qgslayoutpicturewidget.cpp"
42using namespace Qt::StringLiterals;
50 mSvgSelectorWidget->setAllowParameters(
true );
51 mSvgSelectorWidget->sourceLineEdit()->setPropertyOverrideToolButtonVisible(
true );
52 mSvgSelectorWidget->sourceLineEdit()->setLastPathSettingsKey( u
"/UI/lastComposerPictureDir"_s );
71 mClipItemComboBox->setCurrentLayout( picture->
layout() );
74 connect( mPictureRotationSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutPictureWidget::mPictureRotationSpinBox_valueChanged );
75 connect( mRotationFromComposerMapCheckBox, &QCheckBox::stateChanged,
this, &QgsLayoutPictureWidget::mRotationFromComposerMapCheckBox_stateChanged );
76 connect( mResizeModeComboBox,
static_cast<void ( QComboBox::* )(
int )
>( &QComboBox::currentIndexChanged ),
this, &QgsLayoutPictureWidget::mResizeModeComboBox_currentIndexChanged );
77 connect( mAnchorPointComboBox,
static_cast<void ( QComboBox::* )(
int )
>( &QComboBox::currentIndexChanged ),
this, &QgsLayoutPictureWidget::mAnchorPointComboBox_currentIndexChanged );
80 connect( mStrokeWidthSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutPictureWidget::mStrokeWidthSpinBox_valueChanged );
81 connect( mPictureRotationOffsetSpinBox,
static_cast<void ( QDoubleSpinBox::* )(
double )
>( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutPictureWidget::mPictureRotationOffsetSpinBox_valueChanged );
82 connect( mNorthTypeComboBox,
static_cast<void ( QComboBox::* )(
int )
>( &QComboBox::currentIndexChanged ),
this, &QgsLayoutPictureWidget::mNorthTypeComboBox_currentIndexChanged );
86 connect( mRadioSVG, &QRadioButton::toggled,
this, &QgsLayoutPictureWidget::modeChanged );
87 connect( mRadioRaster, &QRadioButton::toggled,
this, &QgsLayoutPictureWidget::modeChanged );
89 connect( mClipToItemCheckBox, &QGroupBox::toggled,
this, [
this](
bool active ) {
90 mPicture->beginCommand( tr(
"Toggle Picture Clipping" ) );
91 mPicture->setClipToItem( active );
92 mPicture->endCommand();
96 mPicture->beginCommand( tr(
"Change Picture Clipping Item" ) );
97 mPicture->setClippingItem( item );
98 mPicture->endCommand();
103 mFillColorButton->setAllowOpacity(
true );
104 mFillColorButton->setColorDialogTitle( tr(
"Select Fill Color" ) );
105 mFillColorButton->setContext( u
"composer"_s );
106 mStrokeColorButton->setAllowOpacity(
true );
107 mStrokeColorButton->setColorDialogTitle( tr(
"Select Stroke Color" ) );
108 mStrokeColorButton->setContext( u
"composer"_s );
110 mFillColorDDBtn->registerLinkedWidget( mFillColorButton );
111 mStrokeColorDDBtn->registerLinkedWidget( mStrokeColorButton );
113 mNorthTypeComboBox->blockSignals(
true );
116 mNorthTypeComboBox->blockSignals(
false );
117 mPictureRotationOffsetSpinBox->setClearValue( 0.0 );
118 mPictureRotationSpinBox->setClearValue( 0.0 );
122 mainLayout->addWidget( mItemPropertiesWidget );
124 if ( mPicture->layout() )
126 mComposerMapComboBox->setCurrentLayout( mPicture->layout() );
131 setGuiElementValues();
145 if ( mItemPropertiesWidget )
146 mItemPropertiesWidget->setMasterLayout( masterLayout );
149void QgsLayoutPictureWidget::mPictureRotationSpinBox_valueChanged(
double d )
154 mPicture->setPictureRotation( d );
155 mPicture->endCommand();
159void QgsLayoutPictureWidget::mResizeModeComboBox_currentIndexChanged(
int )
166 mPicture->beginCommand( tr(
"Change Resize Mode" ) );
168 mPicture->endCommand();
176 mAnchorPointComboBox->setEnabled(
true );
180 mAnchorPointComboBox->setEnabled(
false );
184void QgsLayoutPictureWidget::mAnchorPointComboBox_currentIndexChanged(
int )
191 mPicture->beginCommand( tr(
"Change Placement" ) );
193 mPicture->endCommand();
207 mPicture = qobject_cast<QgsLayoutItemPicture *>( item );
208 mItemPropertiesWidget->setItem( mPicture );
216 setGuiElementValues();
221void QgsLayoutPictureWidget::mRotationFromComposerMapCheckBox_stateChanged(
int state )
228 mPicture->beginCommand( tr(
"Toggle Rotation Sync" ) );
229 if ( state == Qt::Unchecked )
231 mPicture->setLinkedMap(
nullptr );
232 mPictureRotationSpinBox->setEnabled(
true );
233 mComposerMapComboBox->setEnabled(
false );
234 mNorthTypeComboBox->setEnabled(
false );
235 mPictureRotationOffsetSpinBox->setEnabled(
false );
236 mPicture->setPictureRotation( mPictureRotationSpinBox->value() );
240 QgsLayoutItemMap *map = qobject_cast<QgsLayoutItemMap *>( mComposerMapComboBox->currentItem() );
241 mPicture->setLinkedMap( map );
242 mPictureRotationSpinBox->setEnabled(
false );
243 mNorthTypeComboBox->setEnabled(
true );
244 mPictureRotationOffsetSpinBox->setEnabled(
true );
245 mComposerMapComboBox->setEnabled(
true );
247 mPicture->endCommand();
250void QgsLayoutPictureWidget::mapChanged(
QgsLayoutItem *item )
258 const QgsLayout *layout = mPicture->layout();
264 QgsLayoutItemMap *map = qobject_cast<QgsLayoutItemMap *>( item );
270 mPicture->beginCommand( tr(
"Change Rotation Map" ) );
271 mPicture->setLinkedMap( map );
273 mPicture->endCommand();
276void QgsLayoutPictureWidget::setPicRotationSpinValue(
double r )
278 mPictureRotationSpinBox->blockSignals(
true );
279 mPictureRotationSpinBox->setValue( r );
280 mPictureRotationSpinBox->blockSignals(
false );
283void QgsLayoutPictureWidget::setGuiElementValues()
288 mPictureRotationSpinBox->blockSignals(
true );
289 mComposerMapComboBox->blockSignals(
true );
290 mRotationFromComposerMapCheckBox->blockSignals(
true );
291 mNorthTypeComboBox->blockSignals(
true );
292 mPictureRotationOffsetSpinBox->blockSignals(
true );
293 mResizeModeComboBox->blockSignals(
true );
294 mAnchorPointComboBox->blockSignals(
true );
295 mFillColorButton->blockSignals(
true );
296 mStrokeColorButton->blockSignals(
true );
297 mStrokeWidthSpinBox->blockSignals(
true );
298 mClipToItemCheckBox->blockSignals(
true );
299 mClipItemComboBox->blockSignals(
true );
301 mPictureRotationSpinBox->setValue( mPicture->pictureRotation() );
303 mComposerMapComboBox->setItem( mPicture->linkedMap() );
305 if ( mPicture->linkedMap() )
307 mRotationFromComposerMapCheckBox->setCheckState( Qt::Checked );
308 mPictureRotationSpinBox->setEnabled(
false );
309 mComposerMapComboBox->setEnabled(
true );
310 mNorthTypeComboBox->setEnabled(
true );
311 mPictureRotationOffsetSpinBox->setEnabled(
true );
315 mRotationFromComposerMapCheckBox->setCheckState( Qt::Unchecked );
316 mPictureRotationSpinBox->setEnabled(
true );
317 mComposerMapComboBox->setEnabled(
false );
318 mNorthTypeComboBox->setEnabled(
false );
319 mPictureRotationOffsetSpinBox->setEnabled(
false );
321 mNorthTypeComboBox->setCurrentIndex( mNorthTypeComboBox->findData( mPicture->northMode() ) );
322 mPictureRotationOffsetSpinBox->setValue( mPicture->northOffset() );
324 mResizeModeComboBox->setCurrentIndex( mResizeModeComboBox->findData( mPicture->resizeMode() ) );
328 mAnchorPointComboBox->setCurrentIndex( mAnchorPointComboBox->findData( mPicture->pictureAnchor() ) );
332 mAnchorPointComboBox->setEnabled(
true );
336 mAnchorPointComboBox->setEnabled(
false );
339 switch ( mPicture->originalMode() )
343 mRadioSVG->setChecked(
true );
346 mRadioRaster->setChecked(
true );
350 mSvgSelectorWidget->setSvgPath( mPicture->picturePath() );
351 mSvgSelectorWidget->setSvgParameters( mPicture->svgDynamicParameters() );
353 updateSvgParamGui(
false );
354 mFillColorButton->setColor( mPicture->svgFillColor() );
355 mStrokeColorButton->setColor( mPicture->svgStrokeColor() );
356 mStrokeWidthSpinBox->setValue( mPicture->svgStrokeWidth() );
358 mClipToItemCheckBox->setChecked( mPicture->clipToItem() );
359 mClipItemComboBox->setItem( mPicture->clippingItem() );
361 mRotationFromComposerMapCheckBox->blockSignals(
false );
362 mPictureRotationSpinBox->blockSignals(
false );
363 mComposerMapComboBox->blockSignals(
false );
364 mNorthTypeComboBox->blockSignals(
false );
365 mPictureRotationOffsetSpinBox->blockSignals(
false );
366 mResizeModeComboBox->blockSignals(
false );
367 mAnchorPointComboBox->blockSignals(
false );
368 mFillColorButton->blockSignals(
false );
369 mStrokeColorButton->blockSignals(
false );
370 mStrokeWidthSpinBox->blockSignals(
false );
371 mClipToItemCheckBox->blockSignals(
false );
372 mClipItemComboBox->blockSignals(
false );
378void QgsLayoutPictureWidget::updateSvgParamGui(
bool resetValues )
383 const QString picturePath = mPicture->picturePath();
386 bool hasFillParam, hasFillOpacityParam, hasStrokeParam, hasStrokeWidthParam, hasStrokeOpacityParam;
387 QColor defaultFill, defaultStroke;
388 double defaultStrokeWidth, defaultFillOpacity, defaultStrokeOpacity;
389 bool hasDefaultFillColor, hasDefaultFillOpacity, hasDefaultStrokeColor, hasDefaultStrokeWidth, hasDefaultStrokeOpacity;
396 hasDefaultFillOpacity,
399 hasDefaultStrokeColor,
402 hasDefaultStrokeWidth,
404 hasStrokeOpacityParam,
405 hasDefaultStrokeOpacity,
411 QColor fill = mFillColorButton->color();
412 const double newOpacity = hasFillOpacityParam ? fill.alphaF() : 1.0;
413 if ( hasDefaultFillColor )
417 fill.setAlphaF( hasDefaultFillOpacity ? defaultFillOpacity : newOpacity );
418 mFillColorButton->setColor( fill );
420 mFillColorButton->setEnabled( hasFillParam );
421 mFillColorDDBtn->setEnabled( hasFillParam );
422 mFillColorButton->setAllowOpacity( hasFillOpacityParam );
425 QColor stroke = mStrokeColorButton->color();
426 const double newOpacity = hasStrokeOpacityParam ? stroke.alphaF() : 1.0;
427 if ( hasDefaultStrokeColor )
429 stroke = defaultStroke;
431 stroke.setAlphaF( hasDefaultStrokeOpacity ? defaultStrokeOpacity : newOpacity );
432 mStrokeColorButton->setColor( stroke );
434 mStrokeColorButton->setEnabled( hasStrokeParam );
435 mStrokeColorDDBtn->setEnabled( hasStrokeParam );
436 mStrokeColorButton->setAllowOpacity( hasStrokeOpacityParam );
437 if ( hasDefaultStrokeWidth && resetValues )
439 mStrokeWidthSpinBox->setValue( defaultStrokeWidth );
441 mStrokeWidthSpinBox->setEnabled( hasStrokeWidthParam );
442 mStrokeWidthDDBtn->setEnabled( hasStrokeWidthParam );
445void QgsLayoutPictureWidget::mFillColorButton_colorChanged(
const QColor &color )
448 mPicture->setSvgFillColor( color );
449 mPicture->endCommand();
453void QgsLayoutPictureWidget::mStrokeColorButton_colorChanged(
const QColor &color )
456 mPicture->setSvgStrokeColor( color );
457 mPicture->endCommand();
461void QgsLayoutPictureWidget::mStrokeWidthSpinBox_valueChanged(
double d )
464 mPicture->setSvgStrokeWidth( d );
465 mPicture->endCommand();
469void QgsLayoutPictureWidget::mPictureRotationOffsetSpinBox_valueChanged(
double d )
472 mPicture->setNorthOffset( d );
473 mPicture->endCommand();
477void QgsLayoutPictureWidget::mNorthTypeComboBox_currentIndexChanged(
int index )
479 mPicture->beginCommand( tr(
"Change Picture North Mode" ) );
481 mPicture->endCommand();
485void QgsLayoutPictureWidget::modeChanged(
bool checked )
490 const bool svg = mRadioSVG->isChecked();
498 mSvgSelectorWidget->setBrowserVisible( svg );
499 mSvgSelectorWidget->setAllowParameters( svg );
500 mSVGParamsGroupBox->setVisible( svg );
502 if ( mPicture && mPicture->mode() != newFormat )
504 mPicture->beginCommand( tr(
"Change Picture Type" ) );
505 mPicture->setMode( newFormat );
506 mPicture->endCommand();
510void QgsLayoutPictureWidget::sourceChanged(
const QString &source )
514 mPicture->beginCommand( tr(
"Change Picture" ) );
517 mPicture->endCommand();
522void QgsLayoutPictureWidget::setSvgDynamicParameters(
const QMap<QString, QgsProperty> ¶meters )
524 mPicture->beginCommand( tr(
"Set SVG parameters" ) );
525 mPicture->setSvgDynamicParameters( parameters );
527 mPicture->endCommand();
PictureFormat
Picture formats.
@ Unknown
Invalid or unknown image type.
static QgsSvgCache * svgCache()
Returns the application's SVG cache, used for caching SVG images and handling parameter replacement w...
void itemChanged(QgsLayoutItem *item)
Emitted whenever the currently selected item changes.
A layout item subclass that displays SVG files or raster format images (jpg, png, ....
void pictureRotationChanged(double newRotation)
Emitted on picture rotation change.
NorthMode
Method for syncing rotation to a map's North direction.
@ GridNorth
Align to grid north.
@ TrueNorth
Align to true north.
ResizeMode
Controls how pictures are scaled within the item's frame.
@ FrameToImageSize
Sets size of frame to match original size of image without scaling.
@ ZoomResizeFrame
Enlarges image to fit frame, then resizes frame to fit resultant image.
@ Clip
Draws image at original size and clips any portion which falls outside frame.
@ Stretch
Stretches image to fit frame, ignores aspect ratio.
@ Zoom
Enlarges image to fit frame while maintaining aspect ratio of picture.
@ LayoutPicture
Picture item.
Base class for graphical items within a QgsLayout.
@ UndoPictureStrokeWidth
Picture stroke width.
@ UndoPictureRotation
Picture rotation.
@ UndoPictureFillColor
Picture fill color.
@ UndoPictureNorthOffset
Picture north offset.
@ UndoPictureStrokeColor
Picture stroke color.
ReferencePoint
Fixed position reference point.
@ LowerMiddle
Lower center of item.
@ MiddleLeft
Middle left of item.
@ UpperRight
Upper right corner of item.
@ LowerLeft
Lower left corner of item.
@ UpperLeft
Upper left corner of item.
@ UpperMiddle
Upper center of item.
@ MiddleRight
Middle right of item.
@ LowerRight
Lower right corner of item.
int type() const override
Returns a unique graphics item type identifier.
@ FlagProvidesClipPath
Item can act as a clipping path provider (see clipPath()).
const QgsLayout * layout() const
Returns the layout the object is attached to.
void changed()
Emitted when the object's properties change.
@ PictureSvgStrokeColor
SVG stroke color.
@ PictureSvgBackgroundColor
SVG background color.
@ PictureSource
Picture source url.
@ PictureSvgStrokeWidth
SVG stroke width.
Interface for master layout type objects, such as print layouts and reports.
void containsParams(const QString &path, bool &hasFillParam, QColor &defaultFillColor, bool &hasStrokeParam, QColor &defaultStrokeColor, bool &hasStrokeWidthParam, double &defaultStrokeWidth, bool blocking=false) const
Tests if an SVG file contains parameters for fill, stroke color, stroke width.