28 #include <QDoubleValidator>
29 #include <QFileDialog>
31 #include <QImageReader>
32 #include <QMessageBox>
34 #include <QProgressDialog>
35 #include <QSvgRenderer>
59 connect( mPictureRotationSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutPictureWidget::mPictureRotationSpinBox_valueChanged );
60 connect( mRotationFromComposerMapCheckBox, &QCheckBox::stateChanged,
this, &QgsLayoutPictureWidget::mRotationFromComposerMapCheckBox_stateChanged );
61 connect( mResizeModeComboBox,
static_cast<void ( QComboBox::* )(
int )
>( &QComboBox::currentIndexChanged ),
this, &QgsLayoutPictureWidget::mResizeModeComboBox_currentIndexChanged );
62 connect( mAnchorPointComboBox,
static_cast<void ( QComboBox::* )(
int )
>( &QComboBox::currentIndexChanged ),
this, &QgsLayoutPictureWidget::mAnchorPointComboBox_currentIndexChanged );
65 connect( mStrokeWidthSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutPictureWidget::mStrokeWidthSpinBox_valueChanged );
66 connect( mPictureRotationOffsetSpinBox,
static_cast < void ( QDoubleSpinBox::* )(
double )
> ( &QDoubleSpinBox::valueChanged ),
this, &QgsLayoutPictureWidget::mPictureRotationOffsetSpinBox_valueChanged );
67 connect( mNorthTypeComboBox,
static_cast<void ( QComboBox::* )(
int )
>( &QComboBox::currentIndexChanged ),
this, &QgsLayoutPictureWidget::mNorthTypeComboBox_currentIndexChanged );
68 connect( mRadioSVG, &QRadioButton::toggled,
this, &QgsLayoutPictureWidget::modeChanged );
69 connect( mRadioRaster, &QRadioButton::toggled,
this, &QgsLayoutPictureWidget::modeChanged );
73 mSvgSourceLineEdit->setLastPathSettingsKey( QStringLiteral(
"/UI/lastComposerPictureDir" ) );
77 mFillColorButton->setAllowOpacity(
true );
78 mFillColorButton->setColorDialogTitle( tr(
"Select Fill Color" ) );
79 mFillColorButton->setContext( QStringLiteral(
"composer" ) );
80 mStrokeColorButton->setAllowOpacity(
true );
81 mStrokeColorButton->setColorDialogTitle( tr(
"Select Stroke Color" ) );
82 mStrokeColorButton->setContext( QStringLiteral(
"composer" ) );
84 mFillColorDDBtn->registerLinkedWidget( mFillColorButton );
85 mStrokeColorDDBtn->registerLinkedWidget( mStrokeColorButton );
87 mNorthTypeComboBox->blockSignals(
true );
90 mNorthTypeComboBox->blockSignals(
false );
91 mPictureRotationOffsetSpinBox->setClearValue( 0.0 );
92 mPictureRotationSpinBox->setClearValue( 0.0 );
94 viewGroups->setHeaderHidden(
true );
95 #if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)
96 mIconSize = std::max( 30,
static_cast< int >( std::round(
Qgis::UI_SCALE_FACTOR * fontMetrics().width(
'X' ) * 4 ) ) );
98 mIconSize = std::max( 30,
static_cast< int >( std::round(
Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance(
'X' ) * 4 ) ) );
100 viewImages->setGridSize( QSize( mIconSize * 1.2, mIconSize * 1.2 ) );
101 viewImages->setUniformItemSizes(
false );
104 connect( viewImages->selectionModel(), &QItemSelectionModel::currentChanged,
this, &QgsLayoutPictureWidget::setSvgName );
105 connect( viewGroups->selectionModel(), &QItemSelectionModel::currentChanged,
this, &QgsLayoutPictureWidget::populateIcons );
110 mainLayout->addWidget( mItemPropertiesWidget );
112 if ( mPicture->layout() )
114 mComposerMapComboBox->setCurrentLayout( mPicture->layout() );
119 setGuiElementValues();
125 mSourceDDBtn->registerEnabledWidget( mImageSourceLineEdit,
false );
126 mSourceDDBtn->registerEnabledWidget( mSvgSourceLineEdit,
false );
133 updatePictureTypeWidgets();
138 if ( mItemPropertiesWidget )
142 void QgsLayoutPictureWidget::mPictureRotationSpinBox_valueChanged(
double d )
147 mPicture->setPictureRotation( d );
148 mPicture->endCommand();
152 void QgsLayoutPictureWidget::mResizeModeComboBox_currentIndexChanged(
int )
159 mPicture->beginCommand( tr(
"Change Resize Mode" ) );
161 mPicture->endCommand();
171 mAnchorPointComboBox->setEnabled(
true );
175 mAnchorPointComboBox->setEnabled(
false );
179 void QgsLayoutPictureWidget::mAnchorPointComboBox_currentIndexChanged(
int )
186 mPicture->beginCommand( tr(
"Change Placement" ) );
188 mPicture->endCommand();
202 mPicture = qobject_cast< QgsLayoutItemPicture * >( item );
203 mItemPropertiesWidget->
setItem( mPicture );
211 setGuiElementValues();
216 void QgsLayoutPictureWidget::mRotationFromComposerMapCheckBox_stateChanged(
int state )
223 mPicture->beginCommand( tr(
"Toggle Rotation Sync" ) );
224 if ( state == Qt::Unchecked )
226 mPicture->setLinkedMap(
nullptr );
227 mPictureRotationSpinBox->setEnabled(
true );
228 mComposerMapComboBox->setEnabled(
false );
229 mNorthTypeComboBox->setEnabled(
false );
230 mPictureRotationOffsetSpinBox->setEnabled(
false );
231 mPicture->setPictureRotation( mPictureRotationSpinBox->value() );
235 QgsLayoutItemMap *map = qobject_cast< QgsLayoutItemMap * >( mComposerMapComboBox->currentItem() );
236 mPicture->setLinkedMap( map );
237 mPictureRotationSpinBox->setEnabled(
false );
238 mNorthTypeComboBox->setEnabled(
true );
239 mPictureRotationOffsetSpinBox->setEnabled(
true );
240 mComposerMapComboBox->setEnabled(
true );
242 mPicture->endCommand();
245 void QgsLayoutPictureWidget::mapChanged(
QgsLayoutItem *item )
253 const QgsLayout *layout = mPicture->layout();
265 mPicture->beginCommand( tr(
"Change Rotation Map" ) );
266 mPicture->setLinkedMap( map );
268 mPicture->endCommand();
271 void QgsLayoutPictureWidget::setPicRotationSpinValue(
double r )
273 mPictureRotationSpinBox->blockSignals(
true );
274 mPictureRotationSpinBox->setValue( r );
275 mPictureRotationSpinBox->blockSignals(
false );
278 void QgsLayoutPictureWidget::setGuiElementValues()
283 mPictureRotationSpinBox->blockSignals(
true );
284 mComposerMapComboBox->blockSignals(
true );
285 mRotationFromComposerMapCheckBox->blockSignals(
true );
286 mNorthTypeComboBox->blockSignals(
true );
287 mPictureRotationOffsetSpinBox->blockSignals(
true );
288 mResizeModeComboBox->blockSignals(
true );
289 mAnchorPointComboBox->blockSignals(
true );
290 mFillColorButton->blockSignals(
true );
291 mStrokeColorButton->blockSignals(
true );
292 mStrokeWidthSpinBox->blockSignals(
true );
294 mPictureRotationSpinBox->setValue( mPicture->pictureRotation() );
296 mComposerMapComboBox->setItem( mPicture->linkedMap() );
298 if ( mPicture->linkedMap() )
300 mRotationFromComposerMapCheckBox->setCheckState( Qt::Checked );
301 mPictureRotationSpinBox->setEnabled(
false );
302 mComposerMapComboBox->setEnabled(
true );
303 mNorthTypeComboBox->setEnabled(
true );
304 mPictureRotationOffsetSpinBox->setEnabled(
true );
308 mRotationFromComposerMapCheckBox->setCheckState( Qt::Unchecked );
309 mPictureRotationSpinBox->setEnabled(
true );
310 mComposerMapComboBox->setEnabled(
false );
311 mNorthTypeComboBox->setEnabled(
false );
312 mPictureRotationOffsetSpinBox->setEnabled(
false );
314 mNorthTypeComboBox->setCurrentIndex( mNorthTypeComboBox->findData( mPicture->northMode() ) );
315 mPictureRotationOffsetSpinBox->setValue( mPicture->northOffset() );
317 mResizeModeComboBox->setCurrentIndex( mResizeModeComboBox->findData( mPicture->resizeMode() ) );
322 mAnchorPointComboBox->setCurrentIndex( mAnchorPointComboBox->findData( mPicture->pictureAnchor() ) );
327 mAnchorPointComboBox->setEnabled(
true );
331 mAnchorPointComboBox->setEnabled(
false );
336 updatePictureTypeWidgets();
338 if ( mRadioSVG->isChecked() )
340 whileBlocking( mSvgSourceLineEdit )->setSource( mPicture->picturePath() );
342 mBlockSvgModelChanges++;
343 QAbstractItemModel *m = viewImages->model();
344 QItemSelectionModel *selModel = viewImages->selectionModel();
345 for (
int i = 0; i < m->rowCount(); i++ )
347 QModelIndex idx( m->index( i, 0 ) );
348 if ( m->data( idx ).toString() == mPicture->picturePath() )
350 selModel->select( idx, QItemSelectionModel::SelectCurrent );
351 selModel->setCurrentIndex( idx, QItemSelectionModel::SelectCurrent );
355 mBlockSvgModelChanges--;
357 else if ( mRadioRaster->isChecked() )
359 whileBlocking( mImageSourceLineEdit )->setSource( mPicture->picturePath() );
362 updateSvgParamGui(
false );
363 mFillColorButton->setColor( mPicture->svgFillColor() );
364 mStrokeColorButton->setColor( mPicture->svgStrokeColor() );
365 mStrokeWidthSpinBox->setValue( mPicture->svgStrokeWidth() );
367 mRotationFromComposerMapCheckBox->blockSignals(
false );
368 mPictureRotationSpinBox->blockSignals(
false );
369 mComposerMapComboBox->blockSignals(
false );
370 mNorthTypeComboBox->blockSignals(
false );
371 mPictureRotationOffsetSpinBox->blockSignals(
false );
372 mResizeModeComboBox->blockSignals(
false );
373 mAnchorPointComboBox->blockSignals(
false );
374 mFillColorButton->blockSignals(
false );
375 mStrokeColorButton->blockSignals(
false );
376 mStrokeWidthSpinBox->blockSignals(
false );
382 void QgsLayoutPictureWidget::updateSvgParamGui(
bool resetValues )
387 QString picturePath = mPicture->picturePath();
390 bool hasFillParam, hasFillOpacityParam, hasStrokeParam, hasStrokeWidthParam, hasStrokeOpacityParam;
391 QColor defaultFill, defaultStroke;
392 double defaultStrokeWidth, defaultFillOpacity, defaultStrokeOpacity;
393 bool hasDefaultFillColor, hasDefaultFillOpacity, hasDefaultStrokeColor, hasDefaultStrokeWidth, hasDefaultStrokeOpacity;
395 hasFillOpacityParam, hasDefaultFillOpacity, defaultFillOpacity,
396 hasStrokeParam, hasDefaultStrokeColor, defaultStroke,
397 hasStrokeWidthParam, hasDefaultStrokeWidth, defaultStrokeWidth,
398 hasStrokeOpacityParam, hasDefaultStrokeOpacity, defaultStrokeOpacity );
402 QColor fill = mFillColorButton->color();
403 double newOpacity = hasFillOpacityParam ? fill.alphaF() : 1.0;
404 if ( hasDefaultFillColor )
408 fill.setAlphaF( hasDefaultFillOpacity ? defaultFillOpacity : newOpacity );
409 mFillColorButton->setColor( fill );
411 mFillColorButton->setEnabled( hasFillParam );
412 mFillColorButton->setAllowOpacity( hasFillOpacityParam );
415 QColor stroke = mStrokeColorButton->color();
416 double newOpacity = hasStrokeOpacityParam ? stroke.alphaF() : 1.0;
417 if ( hasDefaultStrokeColor )
419 stroke = defaultStroke;
421 stroke.setAlphaF( hasDefaultStrokeOpacity ? defaultStrokeOpacity : newOpacity );
422 mStrokeColorButton->setColor( stroke );
424 mStrokeColorButton->setEnabled( hasStrokeParam );
425 mStrokeColorButton->setAllowOpacity( hasStrokeOpacityParam );
426 if ( hasDefaultStrokeWidth && resetValues )
428 mStrokeWidthSpinBox->setValue( defaultStrokeWidth );
430 mStrokeWidthSpinBox->setEnabled( hasStrokeWidthParam );
433 void QgsLayoutPictureWidget::mFillColorButton_colorChanged(
const QColor &color )
436 mPicture->setSvgFillColor( color );
437 mPicture->endCommand();
441 void QgsLayoutPictureWidget::mStrokeColorButton_colorChanged(
const QColor &color )
444 mPicture->setSvgStrokeColor( color );
445 mPicture->endCommand();
449 void QgsLayoutPictureWidget::mStrokeWidthSpinBox_valueChanged(
double d )
452 mPicture->setSvgStrokeWidth( d );
453 mPicture->endCommand();
457 void QgsLayoutPictureWidget::mPictureRotationOffsetSpinBox_valueChanged(
double d )
460 mPicture->setNorthOffset( d );
461 mPicture->endCommand();
465 void QgsLayoutPictureWidget::mNorthTypeComboBox_currentIndexChanged(
int index )
467 mPicture->beginCommand( tr(
"Change Picture North Mode" ) );
469 mPicture->endCommand();
473 void QgsLayoutPictureWidget::modeChanged()
476 if ( mPicture && mPicture->mode() != newFormat )
479 whileBlocking( mImageSourceLineEdit )->setSource( QString() );
480 mPicture->beginCommand( tr(
"Change Picture Type" ) );
481 mPicture->setPicturePath( QString(), newFormat );
482 mPicture->endCommand();
484 updatePictureTypeWidgets();
487 void QgsLayoutPictureWidget::updatePictureTypeWidgets()
489 mRasterFrame->setVisible( mRadioRaster->isChecked() );
490 mSVGFrame->setVisible( mRadioSVG->isChecked() );
491 mSVGParamsGroupBox->setVisible( mRadioSVG->isChecked() );
494 if ( mRadioSVG->isChecked() )
495 mSvgDDBtnFrame->layout()->addWidget( mSourceDDBtn );
497 mRasterDDBtnFrame->layout()->addWidget( mSourceDDBtn );
500 void QgsLayoutPictureWidget::populateList()
502 QAbstractItemModel *oldModel = viewGroups->model();
504 viewGroups->setModel( g );
508 int rows = g->rowCount( g->indexFromItem( g->invisibleRootItem() ) );
509 for (
int i = 0; i < rows; i++ )
511 viewGroups->setExpanded( g->indexFromItem( g->item( i ) ),
true );
515 oldModel = viewImages->model();
517 viewImages->setModel( m );
522 void QgsLayoutPictureWidget::populateIcons(
const QModelIndex &idx )
524 QString path = idx.data( Qt::UserRole + 1 ).toString();
526 QAbstractItemModel *oldModel = viewImages->model();
528 viewImages->setModel( m );
531 connect( viewImages->selectionModel(), &QItemSelectionModel::currentChanged,
this, &QgsLayoutPictureWidget::setSvgName );
534 void QgsLayoutPictureWidget::setSvgName(
const QModelIndex &idx )
536 if ( mBlockSvgModelChanges )
539 QString name = idx.data( Qt::UserRole ).toString();
541 svgSourceChanged( name );
544 void QgsLayoutPictureWidget::svgSourceChanged(
const QString &source )
548 mPicture->beginCommand( tr(
"Change Picture" ) );
551 mPicture->endCommand();
556 void QgsLayoutPictureWidget::rasterSourceChanged(
const QString &source )
560 mPicture->beginCommand( tr(
"Change Picture" ) );
563 mPicture->endCommand();
575 mImageSourceLineEdit->setEnabled( !mSourceDDBtn->isActive() );
576 mSvgSourceLineEdit->setEnabled( !mSourceDDBtn->isActive() );
static const double UI_SCALE_FACTOR
UI scaling factor.
void sourceChanged(const QString &source)
Emitted whenever the file source is changed in the widget.
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.
Layout graphical items for displaying a map.
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.
Format
Format of source image.
@ FormatRaster
Raster image.
@ 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.
void changed()
Emitted when the object's properties change.
@ PictureSvgStrokeColor
SVG stroke color.
@ PictureSvgStrokeWidth
SVG stroke width.
@ PictureSvgBackgroundColor
SVG background color.
@ PictureSource
Picture source url.
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
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.
A model for displaying SVG search paths.
A model for displaying SVG files with a preview icon.
void sourceChanged(const QString &source)
Emitted whenever the SVG source is changed in the widget.
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.