QGIS API Documentation 3.41.0-Master (57ec4277f5e)
Loading...
Searching...
No Matches
qgsannotationitemwidget_impl.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsannotationitemwidget_impl.cpp
3 ------------------------
4 Date : September 2021
5 Copyright : (C) 2021 Nyall Dawson
6 Email : nyall dot dawson at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
16#include "moc_qgsannotationitemwidget_impl.cpp"
17
19#include "qgsstyle.h"
20#include "qgsfillsymbol.h"
21#include "qgslinesymbol.h"
22#include "qgsmarkersymbol.h"
31#include "qgstextformatwidget.h"
32#include "qgsapplication.h"
34#include "qgsexpressionfinder.h"
35#include "qgsimagecache.h"
36#include "qgssvgcache.h"
38#include "qgsmapcanvas.h"
39
41
42QgsAnnotationPolygonItemWidget::QgsAnnotationPolygonItemWidget( QWidget *parent )
44{
45 setupUi( this );
46
47 mSelector = new QgsSymbolSelectorWidget( mSymbol.get(), QgsStyle::defaultStyle(), nullptr, nullptr );
48 mSelector->setDockMode( dockMode() );
49 connect( mSelector, &QgsSymbolSelectorWidget::symbolModified, this, [=] {
50 if ( !mBlockChangedSignal )
51 {
52 emit itemChanged();
53 QgsApplication::recentStyleHandler()->pushRecentSymbol( QStringLiteral( "polygon_annotation_item" ), qgis::down_cast<QgsFillSymbol *>( mSelector->symbol()->clone() ) );
54 }
55 } );
56 connect( mSelector, &QgsPanelWidget::showPanel, this, &QgsPanelWidget::openPanel );
57
58 QVBoxLayout *layout = new QVBoxLayout();
59 layout->setContentsMargins( 0, 0, 0, 0 );
60 layout->addWidget( mSelector );
61 mSymbolSelectorFrame->setLayout( layout );
62
63 connect( mPropertiesWidget, &QgsAnnotationItemCommonPropertiesWidget::itemChanged, this, [=] {
64 if ( !mBlockChangedSignal )
65 emit itemChanged();
66 } );
67}
68
69QgsAnnotationItem *QgsAnnotationPolygonItemWidget::createItem()
70{
71 QgsAnnotationPolygonItem *newItem = mItem->clone();
72 newItem->setSymbol( mSymbol->clone() );
73 mPropertiesWidget->updateItem( newItem );
74 return newItem;
75}
76
77void QgsAnnotationPolygonItemWidget::updateItem( QgsAnnotationItem *item )
78{
79 if ( QgsAnnotationPolygonItem *polygonItem = dynamic_cast<QgsAnnotationPolygonItem *>( item ) )
80 {
81 polygonItem->setSymbol( mSymbol->clone() );
82 mPropertiesWidget->updateItem( polygonItem );
83 }
84}
85
86void QgsAnnotationPolygonItemWidget::setDockMode( bool dockMode )
87{
89 if ( mSelector )
90 mSelector->setDockMode( dockMode );
91}
92
93void QgsAnnotationPolygonItemWidget::setContext( const QgsSymbolWidgetContext &context )
94{
96 if ( mSelector )
97 mSelector->setContext( context );
98 mPropertiesWidget->setContext( context );
99}
100
101QgsAnnotationPolygonItemWidget::~QgsAnnotationPolygonItemWidget() = default;
102
103bool QgsAnnotationPolygonItemWidget::setNewItem( QgsAnnotationItem *item )
104{
105 QgsAnnotationPolygonItem *polygonItem = dynamic_cast<QgsAnnotationPolygonItem *>( item );
106 if ( !polygonItem )
107 return false;
108
109 mItem.reset( polygonItem->clone() );
110 if ( mItem->symbol() )
111 {
112 mSymbol.reset( mItem->symbol()->clone() );
113 }
114 else
115 {
116 mSymbol.reset( QgsFillSymbol::createSimple( {} ) );
117 }
118 mBlockChangedSignal = true;
119 mSelector->loadSymbol( mSymbol.get() );
120 mSelector->updatePreview();
121 mPropertiesWidget->setItem( mItem.get() );
122 mBlockChangedSignal = false;
123
124 return true;
125}
126
127
128//
129// QgsAnnotationLineItemWidget
130//
131
132QgsAnnotationLineItemWidget::QgsAnnotationLineItemWidget( QWidget *parent )
134{
135 setupUi( this );
136
137 mSelector = new QgsSymbolSelectorWidget( mSymbol.get(), QgsStyle::defaultStyle(), nullptr, nullptr );
138 mSelector->setDockMode( dockMode() );
139 connect( mSelector, &QgsSymbolSelectorWidget::symbolModified, this, [=] {
140 if ( !mBlockChangedSignal )
141 {
142 emit itemChanged();
143 QgsApplication::recentStyleHandler()->pushRecentSymbol( QStringLiteral( "line_annotation_item" ), qgis::down_cast<QgsLineSymbol *>( mSelector->symbol()->clone() ) );
144 }
145 } );
146 connect( mSelector, &QgsPanelWidget::showPanel, this, &QgsPanelWidget::openPanel );
147
148 QVBoxLayout *layout = new QVBoxLayout();
149 layout->setContentsMargins( 0, 0, 0, 0 );
150 layout->addWidget( mSelector );
151 mSymbolSelectorFrame->setLayout( layout );
152
153 connect( mPropertiesWidget, &QgsAnnotationItemCommonPropertiesWidget::itemChanged, this, [=] {
154 if ( !mBlockChangedSignal )
155 emit itemChanged();
156 } );
157}
158
159QgsAnnotationItem *QgsAnnotationLineItemWidget::createItem()
160{
161 QgsAnnotationLineItem *newItem = mItem->clone();
162 newItem->setSymbol( mSymbol->clone() );
163 mPropertiesWidget->updateItem( newItem );
164 return newItem;
165}
166
167void QgsAnnotationLineItemWidget::updateItem( QgsAnnotationItem *item )
168{
169 if ( QgsAnnotationLineItem *lineItem = dynamic_cast<QgsAnnotationLineItem *>( item ) )
170 {
171 lineItem->setSymbol( mSymbol->clone() );
172 mPropertiesWidget->updateItem( lineItem );
173 }
174}
175
176void QgsAnnotationLineItemWidget::setDockMode( bool dockMode )
177{
179 if ( mSelector )
180 mSelector->setDockMode( dockMode );
181}
182
183void QgsAnnotationLineItemWidget::setContext( const QgsSymbolWidgetContext &context )
184{
186 if ( mSelector )
187 mSelector->setContext( context );
188 mPropertiesWidget->setContext( context );
189}
190
191QgsAnnotationLineItemWidget::~QgsAnnotationLineItemWidget() = default;
192
193bool QgsAnnotationLineItemWidget::setNewItem( QgsAnnotationItem *item )
194{
195 QgsAnnotationLineItem *lineItem = dynamic_cast<QgsAnnotationLineItem *>( item );
196 if ( !lineItem )
197 return false;
198
199 mItem.reset( lineItem->clone() );
200 if ( mItem->symbol() )
201 {
202 mSymbol.reset( mItem->symbol()->clone() );
203 }
204 else
205 {
206 mSymbol.reset( QgsLineSymbol::createSimple( {} ) );
207 }
208 mBlockChangedSignal = true;
209 mSelector->loadSymbol( mSymbol.get() );
210 mSelector->updatePreview();
211 mPropertiesWidget->setItem( mItem.get() );
212 mBlockChangedSignal = false;
213
214 return true;
215}
216
217
218//
219// QgsAnnotationMarkerItemWidget
220//
221
222QgsAnnotationMarkerItemWidget::QgsAnnotationMarkerItemWidget( QWidget *parent )
224{
225 setupUi( this );
226
227 mSelector = new QgsSymbolSelectorWidget( mSymbol.get(), QgsStyle::defaultStyle(), nullptr, nullptr );
228 mSelector->setDockMode( dockMode() );
229 connect( mSelector, &QgsSymbolSelectorWidget::symbolModified, this, [=] {
230 if ( !mBlockChangedSignal )
231 {
232 emit itemChanged();
233 QgsApplication::recentStyleHandler()->pushRecentSymbol( QStringLiteral( "marker_annotation_item" ), qgis::down_cast<QgsMarkerSymbol *>( mSelector->symbol()->clone() ) );
234 }
235 } );
236 connect( mSelector, &QgsPanelWidget::showPanel, this, &QgsPanelWidget::openPanel );
237
238 QVBoxLayout *layout = new QVBoxLayout();
239 layout->setContentsMargins( 0, 0, 0, 0 );
240 layout->addWidget( mSelector );
241 mSymbolSelectorFrame->setLayout( layout );
242
243 connect( mPropertiesWidget, &QgsAnnotationItemCommonPropertiesWidget::itemChanged, this, [=] {
244 if ( !mBlockChangedSignal )
245 emit itemChanged();
246 } );
247}
248
249QgsAnnotationItem *QgsAnnotationMarkerItemWidget::createItem()
250{
251 QgsAnnotationMarkerItem *newItem = mItem->clone();
252 newItem->setSymbol( mSymbol->clone() );
253 mPropertiesWidget->updateItem( newItem );
254 return newItem;
255}
256
257void QgsAnnotationMarkerItemWidget::updateItem( QgsAnnotationItem *item )
258{
259 if ( QgsAnnotationMarkerItem *markerItem = dynamic_cast<QgsAnnotationMarkerItem *>( item ) )
260 {
261 markerItem->setSymbol( mSymbol->clone() );
262 mPropertiesWidget->updateItem( markerItem );
263 }
264}
265
266void QgsAnnotationMarkerItemWidget::setDockMode( bool dockMode )
267{
269 if ( mSelector )
270 mSelector->setDockMode( dockMode );
271}
272
273void QgsAnnotationMarkerItemWidget::setContext( const QgsSymbolWidgetContext &context )
274{
276 if ( mSelector )
277 mSelector->setContext( context );
278 mPropertiesWidget->setContext( context );
279}
280
281QgsAnnotationMarkerItemWidget::~QgsAnnotationMarkerItemWidget() = default;
282
283bool QgsAnnotationMarkerItemWidget::setNewItem( QgsAnnotationItem *item )
284{
285 QgsAnnotationMarkerItem *markerItem = dynamic_cast<QgsAnnotationMarkerItem *>( item );
286 if ( !markerItem )
287 return false;
288
289 mItem.reset( markerItem->clone() );
290 if ( mItem->symbol() )
291 {
292 mSymbol.reset( mItem->symbol()->clone() );
293 }
294 else
295 {
296 mSymbol.reset( QgsMarkerSymbol::createSimple( {} ) );
297 }
298 mBlockChangedSignal = true;
299 mSelector->loadSymbol( mSymbol.get() );
300 mSelector->updatePreview();
301 mPropertiesWidget->setItem( mItem.get() );
302 mBlockChangedSignal = false;
303
304 return true;
305}
306
307
308//
309// QgsAnnotationPointTextItemWidget
310//
311
312QgsAnnotationPointTextItemWidget::QgsAnnotationPointTextItemWidget( QWidget *parent )
314{
315 setupUi( this );
316
317 mTextFormatWidget = new QgsTextFormatWidget();
318 QVBoxLayout *vLayout = new QVBoxLayout();
319 vLayout->setContentsMargins( 0, 0, 0, 0 );
320 vLayout->addWidget( mTextFormatWidget );
321 mTextFormatWidgetContainer->setLayout( vLayout );
322
323 mTextEdit->setMode( QgsRichTextEditor::Mode::QgsTextRenderer );
324 mTextEdit->setMaximumHeight( mTextEdit->fontMetrics().height() * 10 );
325
326 mSpinTextAngle->setClearValue( 0 );
327
328 mRotationModeCombo->addItem( tr( "Ignore Map Rotation" ), QVariant::fromValue( Qgis::SymbolRotationMode::IgnoreMapRotation ) );
329 mRotationModeCombo->addItem( tr( "Rotate With Map" ), QVariant::fromValue( Qgis::SymbolRotationMode::RespectMapRotation ) );
330
331 mAlignmentComboBox->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight );
332
333 mTextFormatWidget->setDockMode( dockMode() );
334 connect( mTextFormatWidget, &QgsTextFormatWidget::widgetChanged, this, [=] {
335 mTextEdit->setMode(
336 mTextFormatWidget->format().allowHtmlFormatting() ? QgsRichTextEditor::Mode::QgsTextRenderer : QgsRichTextEditor::Mode::PlainText
337 );
338
339 if ( !mBlockChangedSignal )
340 emit itemChanged();
341 } );
342 connect( mTextEdit, &QgsRichTextEditor::textChanged, this, [=] {
343 if ( !mBlockChangedSignal )
344 emit itemChanged();
345 } );
346 connect( mInsertExpressionButton, &QPushButton::clicked, this, &QgsAnnotationPointTextItemWidget::mInsertExpressionButton_clicked );
347 connect( mPropertiesWidget, &QgsAnnotationItemCommonPropertiesWidget::itemChanged, this, [=] {
348 if ( !mBlockChangedSignal )
349 emit itemChanged();
350 } );
351
352 connect( mSpinTextAngle, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, [=] {
353 if ( !mBlockChangedSignal )
354 emit itemChanged();
355 } );
356
357 connect( mRotationModeCombo, qOverload<int>( &QComboBox::currentIndexChanged ), this, [=] {
358 if ( !mBlockChangedSignal )
359 emit itemChanged();
360 } );
361
362 connect( mAlignmentComboBox, &QgsAlignmentComboBox::changed, this, [=] {
363 if ( !mBlockChangedSignal )
364 emit itemChanged();
365 } );
366}
367
368QgsAnnotationItem *QgsAnnotationPointTextItemWidget::createItem()
369{
370 QgsAnnotationPointTextItem *newItem = mItem->clone();
371 updateItem( newItem );
372 return newItem;
373}
374
375void QgsAnnotationPointTextItemWidget::updateItem( QgsAnnotationItem *item )
376{
377 if ( QgsAnnotationPointTextItem *pointTextItem = dynamic_cast<QgsAnnotationPointTextItem *>( item ) )
378 {
379 mBlockChangedSignal = true;
380 pointTextItem->setFormat( mTextFormatWidget->format() );
381 pointTextItem->setText( mTextFormatWidget->format().allowHtmlFormatting() ? mTextEdit->toHtml() : mTextEdit->toPlainText() );
382 pointTextItem->setAngle( mSpinTextAngle->value() );
383 pointTextItem->setRotationMode( mRotationModeCombo->currentData().value<Qgis::SymbolRotationMode>() );
384 pointTextItem->setAlignment( mAlignmentComboBox->currentAlignment() );
385 mBlockChangedSignal = false;
386 mPropertiesWidget->updateItem( pointTextItem );
387 }
388}
389
390void QgsAnnotationPointTextItemWidget::setDockMode( bool dockMode )
391{
393 if ( mTextFormatWidget )
394 mTextFormatWidget->setDockMode( dockMode );
395}
396
397void QgsAnnotationPointTextItemWidget::setContext( const QgsSymbolWidgetContext &context )
398{
400 if ( mTextFormatWidget )
401 mTextFormatWidget->setContext( context );
402 mPropertiesWidget->setContext( context );
403}
404
405void QgsAnnotationPointTextItemWidget::focusDefaultWidget()
406{
407 mTextEdit->textEdit()->selectAll();
408 mTextEdit->setFocus();
409}
410
411QgsAnnotationPointTextItemWidget::~QgsAnnotationPointTextItemWidget() = default;
412
413bool QgsAnnotationPointTextItemWidget::setNewItem( QgsAnnotationItem *item )
414{
415 QgsAnnotationPointTextItem *textItem = dynamic_cast<QgsAnnotationPointTextItem *>( item );
416 if ( !textItem )
417 return false;
418
419 mItem.reset( textItem->clone() );
420
421 mBlockChangedSignal = true;
422 mTextFormatWidget->setFormat( mItem->format() );
423 mTextEdit->setMode( mItem->format().allowHtmlFormatting() ? QgsRichTextEditor::Mode::QgsTextRenderer : QgsRichTextEditor::Mode::PlainText );
424 mTextEdit->setText( mItem->text() );
425 mSpinTextAngle->setValue( mItem->angle() );
426 mRotationModeCombo->setCurrentIndex( mRotationModeCombo->findData( QVariant::fromValue( mItem->rotationMode() ) ) );
427 mAlignmentComboBox->setCurrentAlignment( mItem->alignment() & Qt::AlignHorizontal_Mask );
428 mPropertiesWidget->setItem( mItem.get() );
429 mBlockChangedSignal = false;
430
431 return true;
432}
433
434void QgsAnnotationPointTextItemWidget::mInsertExpressionButton_clicked()
435{
436 QString expression = QgsExpressionFinder::findAndSelectActiveExpression( mTextEdit->textEdit() );
437
438 QgsExpressionContext expressionContext;
439 if ( context().expressionContext() )
440 expressionContext = *( context().expressionContext() );
441 else
442 expressionContext = QgsProject::instance()->createExpressionContext();
443
444 QgsExpressionBuilderDialog exprDlg( nullptr, expression, this, QStringLiteral( "generic" ), expressionContext );
445
446 exprDlg.setWindowTitle( tr( "Insert Expression" ) );
447 if ( exprDlg.exec() == QDialog::Accepted )
448 {
449 expression = exprDlg.expressionText().trimmed();
450 if ( !expression.isEmpty() )
451 {
452 mTextEdit->textEdit()->insertPlainText( "[%" + expression + "%]" );
453 }
454 }
455}
456
457
458//
459// QgsAnnotationLineTextItemWidget
460//
461
462QgsAnnotationLineTextItemWidget::QgsAnnotationLineTextItemWidget( QWidget *parent )
464{
465 setupUi( this );
466
467 mTextFormatWidget = new QgsTextFormatWidget();
468 QVBoxLayout *vLayout = new QVBoxLayout();
469 vLayout->setContentsMargins( 0, 0, 0, 0 );
470 vLayout->addWidget( mTextFormatWidget );
471 mTextFormatWidgetContainer->setLayout( vLayout );
472
473 mTextEdit->setMode( QgsRichTextEditor::Mode::QgsTextRenderer );
474 mTextEdit->setMaximumHeight( mTextEdit->fontMetrics().height() * 10 );
475
476 mTextFormatWidget->setDockMode( dockMode() );
477 connect( mTextFormatWidget, &QgsTextFormatWidget::widgetChanged, this, [=] {
478 mTextEdit->setMode(
479 mTextFormatWidget->format().allowHtmlFormatting() ? QgsRichTextEditor::Mode::QgsTextRenderer : QgsRichTextEditor::Mode::PlainText
480 );
481
482 if ( !mBlockChangedSignal )
483 emit itemChanged();
484 } );
485 connect( mTextEdit, &QgsRichTextEditor::textChanged, this, [=] {
486 if ( !mBlockChangedSignal )
487 emit itemChanged();
488 } );
489 connect( mInsertExpressionButton, &QPushButton::clicked, this, &QgsAnnotationLineTextItemWidget::mInsertExpressionButton_clicked );
490 connect( mPropertiesWidget, &QgsAnnotationItemCommonPropertiesWidget::itemChanged, this, [=] {
491 if ( !mBlockChangedSignal )
492 emit itemChanged();
493 } );
494
496 mSpinOffset->setClearValue( 0.0 );
497 connect( mSpinOffset, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, [=] {
498 if ( !mBlockChangedSignal )
499 emit itemChanged();
500 } );
501
502 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, [=] {
503 if ( !mBlockChangedSignal )
504 emit itemChanged();
505 } );
506}
507
508QgsAnnotationLineTextItemWidget::~QgsAnnotationLineTextItemWidget() = default;
509
510QgsAnnotationItem *QgsAnnotationLineTextItemWidget::createItem()
511{
512 QgsAnnotationLineTextItem *newItem = mItem->clone();
513 updateItem( newItem );
514 return newItem;
515}
516
517void QgsAnnotationLineTextItemWidget::updateItem( QgsAnnotationItem *item )
518{
519 if ( QgsAnnotationLineTextItem *lineTextItem = dynamic_cast<QgsAnnotationLineTextItem *>( item ) )
520 {
521 mBlockChangedSignal = true;
522 lineTextItem->setFormat( mTextFormatWidget->format() );
523 lineTextItem->setText( mTextFormatWidget->format().allowHtmlFormatting() ? mTextEdit->toHtml() : mTextEdit->toPlainText() );
524
525 lineTextItem->setOffsetFromLine( mSpinOffset->value() );
526 lineTextItem->setOffsetFromLineUnit( mOffsetUnitWidget->unit() );
527 lineTextItem->setOffsetFromLineMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
528
529 mBlockChangedSignal = false;
530 mPropertiesWidget->updateItem( lineTextItem );
531 }
532}
533
534void QgsAnnotationLineTextItemWidget::setDockMode( bool dockMode )
535{
537 if ( mTextFormatWidget )
538 mTextFormatWidget->setDockMode( dockMode );
539}
540
541void QgsAnnotationLineTextItemWidget::setContext( const QgsSymbolWidgetContext &context )
542{
544 if ( mTextFormatWidget )
545 mTextFormatWidget->setContext( context );
546 mPropertiesWidget->setContext( context );
547}
548
549void QgsAnnotationLineTextItemWidget::focusDefaultWidget()
550{
551 mTextEdit->textEdit()->selectAll();
552 mTextEdit->setFocus();
553}
554
555bool QgsAnnotationLineTextItemWidget::setNewItem( QgsAnnotationItem *item )
556{
557 QgsAnnotationLineTextItem *textItem = dynamic_cast<QgsAnnotationLineTextItem *>( item );
558 if ( !textItem )
559 return false;
560
561 mItem.reset( textItem->clone() );
562
563 mBlockChangedSignal = true;
564 mTextFormatWidget->setFormat( mItem->format() );
565 mTextEdit->setMode( mItem->format().allowHtmlFormatting() ? QgsRichTextEditor::Mode::QgsTextRenderer : QgsRichTextEditor::Mode::PlainText );
566 mTextEdit->setText( mItem->text() );
567 mPropertiesWidget->setItem( mItem.get() );
568
569 mSpinOffset->setValue( mItem->offsetFromLine() );
570 mOffsetUnitWidget->setUnit( mItem->offsetFromLineUnit() );
571 mOffsetUnitWidget->setMapUnitScale( mItem->offsetFromLineMapUnitScale() );
572
573 mBlockChangedSignal = false;
574
575 return true;
576}
577
578void QgsAnnotationLineTextItemWidget::mInsertExpressionButton_clicked()
579{
580 QString expression = QgsExpressionFinder::findAndSelectActiveExpression( mTextEdit->textEdit() );
581
582 QgsExpressionContext expressionContext;
583 if ( context().expressionContext() )
584 expressionContext = *( context().expressionContext() );
585 else
586 expressionContext = QgsProject::instance()->createExpressionContext();
587
588 QgsExpressionBuilderDialog exprDlg( nullptr, expression, this, QStringLiteral( "generic" ), expressionContext );
589
590 exprDlg.setWindowTitle( tr( "Insert Expression" ) );
591 if ( exprDlg.exec() == QDialog::Accepted )
592 {
593 expression = exprDlg.expressionText().trimmed();
594 if ( !expression.isEmpty() )
595 {
596 mTextEdit->textEdit()->insertPlainText( "[%" + expression + "%]" );
597 }
598 }
599}
600
601
602//
603// QgsAnnotationRectangleTextItemWidget
604//
605
606QgsAnnotationRectangleTextItemWidget::QgsAnnotationRectangleTextItemWidget( QWidget *parent )
608{
609 setupUi( this );
610
611 mSizeModeCombo->addItem( tr( "Scale Dependent Size" ), QVariant::fromValue( Qgis::AnnotationPlacementMode::SpatialBounds ) );
612 mSizeModeCombo->addItem( tr( "Fixed Size" ), QVariant::fromValue( Qgis::AnnotationPlacementMode::FixedSize ) );
613 mSizeModeCombo->addItem( tr( "Relative to Map" ), QVariant::fromValue( Qgis::AnnotationPlacementMode::RelativeToMapFrame ) );
614
616
617
618 mBackgroundSymbolButton->setSymbolType( Qgis::SymbolType::Fill );
619 mBackgroundSymbolButton->setDialogTitle( tr( "Background" ) );
620 mBackgroundSymbolButton->registerExpressionContextGenerator( this );
621 mFrameSymbolButton->setSymbolType( Qgis::SymbolType::Fill );
622 mFrameSymbolButton->setDialogTitle( tr( "Frame" ) );
623 mFrameSymbolButton->registerExpressionContextGenerator( this );
624
625 mSpinBottomMargin->setClearValue( 0 );
626 mSpinTopMargin->setClearValue( 0 );
627 mSpinRightMargin->setClearValue( 0 );
628 mSpinLeftMargin->setClearValue( 0 );
630
631 mTextFormatWidget = new QgsTextFormatWidget();
632 QVBoxLayout *vLayout = new QVBoxLayout();
633 vLayout->setContentsMargins( 0, 0, 0, 0 );
634 vLayout->addWidget( mTextFormatWidget );
635 mTextFormatWidgetContainer->setLayout( vLayout );
636
637 mTextEdit->setMode( QgsRichTextEditor::Mode::QgsTextRenderer );
638 mTextEdit->setMaximumHeight( mTextEdit->fontMetrics().height() * 10 );
639
640 mAlignmentComboBox->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight | Qt::AlignJustify );
641 mVerticalAlignmentComboBox->setAvailableAlignments( Qt::AlignTop | Qt::AlignVCenter | Qt::AlignBottom );
642
643 mTextFormatWidget->setDockMode( dockMode() );
644 connect( mTextFormatWidget, &QgsTextFormatWidget::widgetChanged, this, [this] {
645 mTextEdit->setMode(
646 mTextFormatWidget->format().allowHtmlFormatting() ? QgsRichTextEditor::Mode::QgsTextRenderer : QgsRichTextEditor::Mode::PlainText
647 );
648
649 onWidgetChanged();
650 } );
651 connect( mTextEdit, &QgsRichTextEditor::textChanged, this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
652 connect( mInsertExpressionButton, &QPushButton::clicked, this, &QgsAnnotationRectangleTextItemWidget::mInsertExpressionButton_clicked );
653 connect( mPropertiesWidget, &QgsAnnotationItemCommonPropertiesWidget::itemChanged, this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
654 connect( mAlignmentComboBox, &QgsAlignmentComboBox::changed, this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
655 connect( mVerticalAlignmentComboBox, &QgsAlignmentComboBox::changed, this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
656 connect( mFrameCheckbox, &QGroupBox::toggled, this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
657 connect( mBackgroundCheckbox, &QGroupBox::toggled, this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
658 connect( mBackgroundSymbolButton, &QgsSymbolButton::changed, this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
659 connect( mFrameSymbolButton, &QgsSymbolButton::changed, this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
660 connect( mSpinTopMargin, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
661 connect( mSpinRightMargin, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
662 connect( mSpinLeftMargin, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
663 connect( mSpinBottomMargin, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
664 connect( mMarginUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
665
666 connect( mSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
667
668 connect( mWidthSpinBox, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, &QgsAnnotationRectangleTextItemWidget::setWidth );
669 connect( mHeightSpinBox, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, &QgsAnnotationRectangleTextItemWidget::setHeight );
670
671 connect( mSizeModeCombo, qOverload<int>( &QComboBox::currentIndexChanged ), this, &QgsAnnotationRectangleTextItemWidget::sizeModeChanged );
672 mWidgetFixedSize->hide();
673 sizeModeChanged();
674}
675
676QgsAnnotationItem *QgsAnnotationRectangleTextItemWidget::createItem()
677{
678 QgsAnnotationRectangleTextItem *newItem = mItem->clone();
679 updateItem( newItem );
680 return newItem;
681}
682
683void QgsAnnotationRectangleTextItemWidget::updateItem( QgsAnnotationItem *item )
684{
685 if ( QgsAnnotationRectangleTextItem *rectTextItem = dynamic_cast<QgsAnnotationRectangleTextItem *>( item ) )
686 {
687 mBlockChangedSignal = true;
688 rectTextItem->setFormat( mTextFormatWidget->format() );
689 rectTextItem->setText( mTextFormatWidget->format().allowHtmlFormatting() ? mTextEdit->toHtml() : mTextEdit->toPlainText() );
690 rectTextItem->setAlignment( mAlignmentComboBox->currentAlignment() | mVerticalAlignmentComboBox->currentAlignment() );
691
692 rectTextItem->setPlacementMode( mSizeModeCombo->currentData().value<Qgis::AnnotationPlacementMode>() );
693
694 rectTextItem->setFixedSize( QSizeF( mWidthSpinBox->value(), mHeightSpinBox->value() ) );
695 rectTextItem->setFixedSizeUnit( mSizeUnitWidget->unit() );
696
697 rectTextItem->setBackgroundEnabled( mBackgroundCheckbox->isChecked() );
698 rectTextItem->setFrameEnabled( mFrameCheckbox->isChecked() );
699 rectTextItem->setBackgroundSymbol( mBackgroundSymbolButton->clonedSymbol<QgsFillSymbol>() );
700 rectTextItem->setFrameSymbol( mFrameSymbolButton->clonedSymbol<QgsFillSymbol>() );
701
702 rectTextItem->setMargins( QgsMargins( mSpinLeftMargin->value(), mSpinTopMargin->value(), mSpinRightMargin->value(), mSpinBottomMargin->value() ) );
703 rectTextItem->setMarginsUnit( mMarginUnitWidget->unit() );
704
705 if ( mUpdateItemPosition )
706 {
707 rectTextItem->setBounds( mItem->bounds() );
708 mUpdateItemPosition = false;
709 }
710
711 mBlockChangedSignal = false;
712
713 mPropertiesWidget->updateItem( rectTextItem );
714 }
715}
716
717void QgsAnnotationRectangleTextItemWidget::setDockMode( bool dockMode )
718{
720 if ( mTextFormatWidget )
721 mTextFormatWidget->setDockMode( dockMode );
722}
723
724void QgsAnnotationRectangleTextItemWidget::setContext( const QgsSymbolWidgetContext &context )
725{
727 if ( mTextFormatWidget )
728 mTextFormatWidget->setContext( context );
729 mBackgroundSymbolButton->setMapCanvas( context.mapCanvas() );
730 mBackgroundSymbolButton->setMessageBar( context.messageBar() );
731 mFrameSymbolButton->setMapCanvas( context.mapCanvas() );
732 mFrameSymbolButton->setMessageBar( context.messageBar() );
733 mPropertiesWidget->setContext( context );
734}
735
736QgsExpressionContext QgsAnnotationRectangleTextItemWidget::createExpressionContext() const
737{
738 QgsExpressionContext expressionContext;
739 if ( context().expressionContext() )
740 expressionContext = *( context().expressionContext() );
741 else
742 expressionContext = QgsProject::instance()->createExpressionContext();
743 return expressionContext;
744}
745
746void QgsAnnotationRectangleTextItemWidget::focusDefaultWidget()
747{
748 mTextEdit->textEdit()->selectAll();
749 mTextEdit->setFocus();
750}
751
752QgsAnnotationRectangleTextItemWidget::~QgsAnnotationRectangleTextItemWidget() = default;
753
754bool QgsAnnotationRectangleTextItemWidget::setNewItem( QgsAnnotationItem *item )
755{
756 QgsAnnotationRectangleTextItem *textItem = dynamic_cast<QgsAnnotationRectangleTextItem *>( item );
757 if ( !textItem )
758 return false;
759
760 mItem.reset( textItem->clone() );
761
762 mBlockChangedSignal = true;
763 mTextFormatWidget->setFormat( mItem->format() );
764 mTextEdit->setMode( mItem->format().allowHtmlFormatting() ? QgsRichTextEditor::Mode::QgsTextRenderer : QgsRichTextEditor::Mode::PlainText );
765 mTextEdit->setText( mItem->text() );
766 mAlignmentComboBox->setCurrentAlignment( mItem->alignment() & Qt::AlignHorizontal_Mask );
767 mVerticalAlignmentComboBox->setCurrentAlignment( mItem->alignment() & Qt::AlignVertical_Mask );
768 mPropertiesWidget->setItem( mItem.get() );
769
770 mBackgroundCheckbox->setChecked( textItem->backgroundEnabled() );
771 if ( const QgsSymbol *symbol = textItem->backgroundSymbol() )
772 mBackgroundSymbolButton->setSymbol( symbol->clone() );
773
774 mFrameCheckbox->setChecked( textItem->frameEnabled() );
775 if ( const QgsSymbol *symbol = textItem->frameSymbol() )
776 mFrameSymbolButton->setSymbol( symbol->clone() );
777
778 mMarginUnitWidget->setUnit( textItem->marginsUnit() );
779 mSpinLeftMargin->setValue( textItem->margins().left() );
780 mSpinTopMargin->setValue( textItem->margins().top() );
781 mSpinRightMargin->setValue( textItem->margins().right() );
782 mSpinBottomMargin->setValue( textItem->margins().bottom() );
783
784 mWidthSpinBox->setValue( textItem->fixedSize().width() );
785 mHeightSpinBox->setValue( textItem->fixedSize().height() );
786 mSizeModeCombo->setCurrentIndex( mSizeModeCombo->findData( QVariant::fromValue( textItem->placementMode() ) ) );
787
788 mBlockChangedSignal = false;
789
790 return true;
791}
792
793void QgsAnnotationRectangleTextItemWidget::onWidgetChanged()
794{
795 if ( !mBlockChangedSignal )
796 emit itemChanged();
797}
798
799void QgsAnnotationRectangleTextItemWidget::sizeModeChanged()
800{
801 const Qgis::AnnotationPlacementMode mode = mSizeModeCombo->currentData().value<Qgis::AnnotationPlacementMode>();
802 switch ( mode )
803 {
805 mWidgetFixedSize->hide();
806 break;
807
809 mWidgetFixedSize->show();
810 break;
811
813 {
814 if ( const QgsRenderedAnnotationItemDetails *details = renderedItemDetails() )
815 {
816 // convert item bounds to relative position
817 const QgsRectangle itemBounds = details->boundingBox();
818 if ( QgsMapCanvas *canvas = context().mapCanvas() )
819 {
820 const double centerX = ( itemBounds.center().x() - canvas->extent().xMinimum() ) / canvas->extent().width();
821 const double centerY = ( canvas->extent().yMaximum() - itemBounds.center().y() ) / canvas->extent().height();
822 mItem->setBounds( QgsRectangle::fromCenterAndSize( QgsPointXY( centerX, centerY ), 0.5, 0.5 ) );
823 mUpdateItemPosition = true;
824 }
825 }
826
827 mWidgetFixedSize->hide();
828 break;
829 }
830 }
831
832 onWidgetChanged();
833}
834
835void QgsAnnotationRectangleTextItemWidget::setWidth()
836{
837 onWidgetChanged();
838}
839
840void QgsAnnotationRectangleTextItemWidget::setHeight()
841{
842 onWidgetChanged();
843}
844
845void QgsAnnotationRectangleTextItemWidget::mInsertExpressionButton_clicked()
846{
847 QString expression = QgsExpressionFinder::findAndSelectActiveExpression( mTextEdit->textEdit() );
848
849 QgsExpressionBuilderDialog exprDlg( nullptr, expression, this, QStringLiteral( "generic" ), createExpressionContext() );
850
851 exprDlg.setWindowTitle( tr( "Insert Expression" ) );
852 if ( exprDlg.exec() == QDialog::Accepted )
853 {
854 expression = exprDlg.expressionText().trimmed();
855 if ( !expression.isEmpty() )
856 {
857 mTextEdit->textEdit()->insertPlainText( "[%" + expression + "%]" );
858 }
859 }
860}
861
862
863//
864// QgsAnnotationPictureItemWidget
865//
866
867QgsAnnotationPictureItemWidget::QgsAnnotationPictureItemWidget( QWidget *parent )
869{
870 setupUi( this );
871
872 mSizeStackedWidget->setSizeMode( QgsStackedWidget::SizeMode::CurrentPageOnly );
873
874 mSizeModeCombo->addItem( tr( "Scale Dependent Size" ), QVariant::fromValue( Qgis::AnnotationPlacementMode::SpatialBounds ) );
875 mSizeModeCombo->addItem( tr( "Fixed Size" ), QVariant::fromValue( Qgis::AnnotationPlacementMode::FixedSize ) );
876 mSizeModeCombo->addItem( tr( "Relative to Map" ), QVariant::fromValue( Qgis::AnnotationPlacementMode::RelativeToMapFrame ) );
877
879
880 mBackgroundSymbolButton->setSymbolType( Qgis::SymbolType::Fill );
881 mBackgroundSymbolButton->setDialogTitle( tr( "Background" ) );
882 mBackgroundSymbolButton->registerExpressionContextGenerator( this );
883 mFrameSymbolButton->setSymbolType( Qgis::SymbolType::Fill );
884 mFrameSymbolButton->setDialogTitle( tr( "Frame" ) );
885 mFrameSymbolButton->registerExpressionContextGenerator( this );
886
887 connect( mPropertiesWidget, &QgsAnnotationItemCommonPropertiesWidget::itemChanged, this, [=] {
888 if ( !mBlockChangedSignal )
889 emit itemChanged();
890 } );
891
892 connect( mSizeModeCombo, qOverload<int>( &QComboBox::currentIndexChanged ), this, &QgsAnnotationPictureItemWidget::sizeModeChanged );
893
894 connect( mRadioSVG, &QRadioButton::toggled, this, &QgsAnnotationPictureItemWidget::modeChanged );
895 connect( mRadioRaster, &QRadioButton::toggled, this, &QgsAnnotationPictureItemWidget::modeChanged );
896 connect( mSourceLineEdit, &QgsPictureSourceLineEditBase::sourceChanged, this, [=]( const QString &source ) {
897 if ( !mRadioSVG->isChecked() && QFileInfo( source ).suffix().compare( QLatin1String( "svg" ), Qt::CaseInsensitive ) == 0 )
898 {
899 mRadioSVG->setChecked( true );
900 }
901
902 onWidgetChanged();
903 } );
904
905 connect( mLockAspectRatioCheck, &QCheckBox::toggled, this, &QgsAnnotationPictureItemWidget::onWidgetChanged );
906 connect( mFrameCheckbox, &QGroupBox::toggled, this, &QgsAnnotationPictureItemWidget::onWidgetChanged );
907 connect( mBackgroundCheckbox, &QGroupBox::toggled, this, &QgsAnnotationPictureItemWidget::onWidgetChanged );
908 connect( mBackgroundSymbolButton, &QgsSymbolButton::changed, this, &QgsAnnotationPictureItemWidget::onWidgetChanged );
909 connect( mFrameSymbolButton, &QgsSymbolButton::changed, this, &QgsAnnotationPictureItemWidget::onWidgetChanged );
910 connect( mSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsAnnotationPictureItemWidget::onWidgetChanged );
911
912 connect( mWidthSpinBox, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, &QgsAnnotationPictureItemWidget::setWidth );
913 connect( mHeightSpinBox, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, &QgsAnnotationPictureItemWidget::setHeight );
914 connect( mLockAspectRatio, &QgsRatioLockButton::lockChanged, this, &QgsAnnotationPictureItemWidget::setLockAspectRatio );
915}
916
917QgsAnnotationPictureItemWidget::~QgsAnnotationPictureItemWidget() = default;
918
919QgsAnnotationItem *QgsAnnotationPictureItemWidget::createItem()
920{
921 QgsAnnotationPictureItem *newItem = mItem->clone();
922 updateItem( newItem );
923 return newItem;
924}
925
926void QgsAnnotationPictureItemWidget::updateItem( QgsAnnotationItem *item )
927{
928 if ( QgsAnnotationPictureItem *pictureItem = dynamic_cast<QgsAnnotationPictureItem *>( item ) )
929 {
930 const bool svg = mRadioSVG->isChecked();
932 const QString path = mSourceLineEdit->source();
933 pictureItem->setPath( newFormat, path );
934
935 pictureItem->setPlacementMode( mSizeModeCombo->currentData().value<Qgis::AnnotationPlacementMode>() );
936 switch ( pictureItem->placementMode() )
937 {
939 pictureItem->setLockAspectRatio( mLockAspectRatioCheck->isChecked() );
940 break;
943 pictureItem->setLockAspectRatio( mLockAspectRatio->isChecked() );
944 break;
945 }
946
947 pictureItem->setFixedSize( QSizeF( mWidthSpinBox->value(), mHeightSpinBox->value() ) );
948 pictureItem->setFixedSizeUnit( mSizeUnitWidget->unit() );
949
950 pictureItem->setBackgroundEnabled( mBackgroundCheckbox->isChecked() );
951 pictureItem->setFrameEnabled( mFrameCheckbox->isChecked() );
952 pictureItem->setBackgroundSymbol( mBackgroundSymbolButton->clonedSymbol<QgsFillSymbol>() );
953 pictureItem->setFrameSymbol( mFrameSymbolButton->clonedSymbol<QgsFillSymbol>() );
954
955 if ( mUpdateItemPosition )
956 {
957 pictureItem->setBounds( mItem->bounds() );
958 mUpdateItemPosition = false;
959 }
960
961 mPropertiesWidget->updateItem( pictureItem );
962 }
963}
964
965void QgsAnnotationPictureItemWidget::setDockMode( bool dockMode )
966{
968}
969
970void QgsAnnotationPictureItemWidget::setContext( const QgsSymbolWidgetContext &context )
971{
973 mPropertiesWidget->setContext( context );
974 mBackgroundSymbolButton->setMapCanvas( context.mapCanvas() );
975 mBackgroundSymbolButton->setMessageBar( context.messageBar() );
976 mFrameSymbolButton->setMapCanvas( context.mapCanvas() );
977 mFrameSymbolButton->setMessageBar( context.messageBar() );
978}
979
980QgsExpressionContext QgsAnnotationPictureItemWidget::createExpressionContext() const
981{
982 QgsExpressionContext expressionContext;
983 if ( context().expressionContext() )
984 expressionContext = *( context().expressionContext() );
985 else
986 expressionContext = QgsProject::instance()->createExpressionContext();
987 return expressionContext;
988}
989
990void QgsAnnotationPictureItemWidget::focusDefaultWidget()
991{
992 mSourceLineEdit->setFocus();
993}
994
995bool QgsAnnotationPictureItemWidget::setNewItem( QgsAnnotationItem *item )
996{
997 QgsAnnotationPictureItem *pictureItem = dynamic_cast<QgsAnnotationPictureItem *>( item );
998 if ( !pictureItem )
999 return false;
1000
1001 mItem.reset( pictureItem->clone() );
1002
1003 mBlockChangedSignal = true;
1004 mPropertiesWidget->setItem( mItem.get() );
1005
1006 mLockAspectRatioCheck->setChecked( mItem->lockAspectRatio() );
1007 mLockAspectRatio->setLocked( mItem->lockAspectRatio() );
1008 switch ( pictureItem->format() )
1009 {
1011 mRadioSVG->setChecked( true );
1012 break;
1014 mRadioRaster->setChecked( true );
1015 break;
1017 break;
1018 }
1019
1020 mSourceLineEdit->setSource( pictureItem->path() );
1021
1022 mBackgroundCheckbox->setChecked( pictureItem->backgroundEnabled() );
1023 if ( const QgsSymbol *symbol = pictureItem->backgroundSymbol() )
1024 mBackgroundSymbolButton->setSymbol( symbol->clone() );
1025
1026 mFrameCheckbox->setChecked( pictureItem->frameEnabled() );
1027 if ( const QgsSymbol *symbol = pictureItem->frameSymbol() )
1028 mFrameSymbolButton->setSymbol( symbol->clone() );
1029
1030 mWidthSpinBox->setValue( pictureItem->fixedSize().width() );
1031 mHeightSpinBox->setValue( pictureItem->fixedSize().height() );
1032 mSizeModeCombo->setCurrentIndex( mSizeModeCombo->findData( QVariant::fromValue( pictureItem->placementMode() ) ) );
1033 sizeModeChanged();
1034
1035 mBlockChangedSignal = false;
1036
1037 return true;
1038}
1039
1040void QgsAnnotationPictureItemWidget::onWidgetChanged()
1041{
1042 if ( !mBlockChangedSignal )
1043 emit itemChanged();
1044}
1045
1046void QgsAnnotationPictureItemWidget::modeChanged( bool checked )
1047{
1048 if ( !checked )
1049 return;
1050
1051 const bool svg = mRadioSVG->isChecked();
1052
1053 if ( svg )
1054 mSourceLineEdit->setMode( QgsPictureSourceLineEditBase::Svg );
1055 else
1056 mSourceLineEdit->setMode( QgsPictureSourceLineEditBase::Image );
1057
1058 onWidgetChanged();
1059}
1060
1061void QgsAnnotationPictureItemWidget::sizeModeChanged()
1062{
1063 const Qgis::AnnotationPlacementMode mode = mSizeModeCombo->currentData().value<Qgis::AnnotationPlacementMode>();
1064 switch ( mode )
1065 {
1067 mSizeStackedWidget->setCurrentWidget( mPageSpatialBounds );
1068 break;
1069
1071 mSizeStackedWidget->setCurrentWidget( mPageFixedSize );
1072 break;
1073
1075 {
1076 if ( const QgsRenderedAnnotationItemDetails *details = renderedItemDetails() )
1077 {
1078 // convert item bounds to relative position
1079 const QgsRectangle itemBounds = details->boundingBox();
1080 if ( QgsMapCanvas *canvas = context().mapCanvas() )
1081 {
1082 const double centerX = ( itemBounds.center().x() - canvas->extent().xMinimum() ) / canvas->extent().width();
1083 const double centerY = ( canvas->extent().yMaximum() - itemBounds.center().y() ) / canvas->extent().height();
1084 mItem->setBounds( QgsRectangle::fromCenterAndSize( QgsPointXY( centerX, centerY ), 0.5, 0.5 ) );
1085 mUpdateItemPosition = true;
1086 }
1087 }
1088
1089 mSizeStackedWidget->setCurrentWidget( mPageFixedSize );
1090 break;
1091 }
1092 }
1093
1094 onWidgetChanged();
1095}
1096
1097void QgsAnnotationPictureItemWidget::setWidth()
1098{
1099 if ( mLockAspectRatio->locked() )
1100 {
1101 const double ratio = pictureAspectRatio();
1102 if ( ratio > 0 )
1103 whileBlocking( mHeightSpinBox )->setValue( mWidthSpinBox->value() * ratio );
1104 }
1105
1106 onWidgetChanged();
1107}
1108
1109void QgsAnnotationPictureItemWidget::setHeight()
1110{
1111 if ( mLockAspectRatio->locked() )
1112 {
1113 const double ratio = pictureAspectRatio();
1114 if ( ratio > 0 )
1115 whileBlocking( mWidthSpinBox )->setValue( mHeightSpinBox->value() / ratio );
1116 }
1117
1118 onWidgetChanged();
1119}
1120
1121void QgsAnnotationPictureItemWidget::setLockAspectRatio( bool locked )
1122{
1123 if ( locked && !mBlockChangedSignal )
1124 {
1125 const double ratio = pictureAspectRatio();
1126 if ( ratio > 0 )
1127 whileBlocking( mHeightSpinBox )->setValue( mWidthSpinBox->value() * ratio );
1128 }
1129
1130 onWidgetChanged();
1131}
1132
1133double QgsAnnotationPictureItemWidget::pictureAspectRatio() const
1134{
1135 const bool svg = mRadioSVG->isChecked();
1136 const QString path = mSourceLineEdit->source();
1137 QSizeF size;
1138 if ( svg )
1139 {
1140 size = QgsApplication::svgCache()->svgViewboxSize( path, 100, QColor(), QColor(), 1, 1 );
1141 }
1142 else
1143 {
1144 size = QgsApplication::imageCache()->originalSize( path );
1145 }
1146 if ( size.isValid() && size.width() > 0 )
1147 return size.height() / size.width();
1148
1149 return 0;
1150}
1151
SymbolRotationMode
Modes for handling how symbol and text entity rotation is handled when maps are rotated.
Definition qgis.h:750
@ RespectMapRotation
Entity is rotated along with the map.
@ IgnoreMapRotation
Entity ignores map rotation.
PictureFormat
Picture formats.
Definition qgis.h:4964
@ Raster
Raster image.
@ Unknown
Invalid or unknown image type.
@ Percentage
Percentage of another measurement (e.g., canvas size, feature size)
@ Millimeters
Millimeters.
@ Points
Points (e.g., for font sizes)
@ MapUnits
Map units.
@ MetersInMapUnits
Meters value as Map units.
@ Fill
Fill symbol.
AnnotationPlacementMode
Annotation item placement modes.
Definition qgis.h:2375
@ SpatialBounds
Item is rendered inside fixed spatial bounds, and size will depend on map scale.
@ FixedSize
Item is rendered at a fixed size, regardless of map scale. Item's location is georeferenced to a spat...
@ RelativeToMapFrame
Items size and placement is relative to the map's frame, and the item will always be rendered in the ...
void sourceChanged(const QString &source)
Emitted whenever the file source is changed in the widget.
void changed()
Emitted when the alignment is changed.
A base class for property widgets for annotation items.
virtual void setContext(const QgsSymbolWidgetContext &context)
Sets the context in which the widget is shown, e.g., the associated map canvas and expression context...
void itemChanged()
Emitted when the annotation item definition in the widget is changed by the user.
Abstract base class for annotation items which are drawn with QgsAnnotationLayers.
An annotation item which renders a line symbol along a line geometry.
void setSymbol(QgsLineSymbol *symbol)
Sets the symbol used to render the marker item.
QgsAnnotationLineItem * clone() const override
Returns a clone of the item.
An annotation item which renders text along a line geometry.
QgsAnnotationLineTextItem * clone() const override
Returns a clone of the item.
void setFormat(const QgsTextFormat &format)
Sets the text format used to render the text.
An annotation item which renders a marker symbol at a point location.
void setSymbol(QgsMarkerSymbol *symbol)
Sets the symbol used to render the marker item.
QgsAnnotationMarkerItem * clone() const override
Returns a clone of the item.
An annotation item which renders a picture.
Qgis::PictureFormat format() const
Returns the picture format.
QString path() const
Returns the path of the image used to render the item.
QgsAnnotationPictureItem * clone() const override
Returns a clone of the item.
void setPath(Qgis::PictureFormat format, const QString &path)
Sets the format and path of the image used to render the item.
An annotation item which renders a text string at a point location.
void setFormat(const QgsTextFormat &format)
Sets the text format used to render the text.
QgsAnnotationPointTextItem * clone() const override
Returns a clone of the item.
An annotation item which renders a fill symbol for a polygon geometry.
void setSymbol(QgsFillSymbol *symbol)
Sets the symbol used to render the polygon item.
QgsAnnotationPolygonItem * clone() const override
Returns a clone of the item.
QSizeF fixedSize() const
Returns the fixed size to use for the item, when the placementMode() is Qgis::AnnotationPlacementMode...
bool frameEnabled() const
Returns true if the item's frame should be rendered.
const QgsFillSymbol * frameSymbol() const
Returns the symbol used to render the item's frame.
Qgis::AnnotationPlacementMode placementMode() const
Returns the placement mode for the item.
bool backgroundEnabled() const
Returns true if the item's background should be rendered.
const QgsFillSymbol * backgroundSymbol() const
Returns the symbol used to render the item's background.
An annotation item which renders paragraphs of text within a rectangle.
void setFormat(const QgsTextFormat &format)
Sets the text format used to render the text.
QgsAnnotationRectangleTextItem * clone() const override
Returns a clone of the item.
const QgsMargins & margins() const
Returns the margins between the outside of the item's frame and the interior text.
Qgis::RenderUnit marginsUnit() const
Returns the units for the margins between the item's frame and the interior text.
static QgsRecentStyleHandler * recentStyleHandler()
Returns the handler for recently used style items.
static QgsImageCache * imageCache()
Returns the application's image cache, used for caching resampled versions of raster images.
static QgsSvgCache * svgCache()
Returns the application's SVG cache, used for caching SVG images and handling parameter replacement w...
A generic dialog for building expression strings.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
static QString findAndSelectActiveExpression(QgsCodeEditor *editor, const QString &pattern=QString())
Find the expression under the cursor in the given editor and select it.
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
static QgsFillSymbol * createSimple(const QVariantMap &properties)
Create a fill symbol with one symbol layer: SimpleFill with specified properties.
QSize originalSize(const QString &path, bool blocking=false) const
Returns the original size (in pixels) of the image at the specified path.
static QgsLineSymbol * createSimple(const QVariantMap &properties)
Create a line symbol with one symbol layer: SimpleLine with specified properties.
Map canvas is a class for displaying all GIS data types on a canvas.
The QgsMargins class defines the four margins of a rectangle.
Definition qgsmargins.h:37
double top() const
Returns the top margin.
Definition qgsmargins.h:77
double right() const
Returns the right margin.
Definition qgsmargins.h:83
double bottom() const
Returns the bottom margin.
Definition qgsmargins.h:89
double left() const
Returns the left margin.
Definition qgsmargins.h:71
static QgsMarkerSymbol * createSimple(const QVariantMap &properties)
Create a marker symbol with one symbol layer: SimpleMarker with specified properties.
void showPanel(QgsPanelWidget *panel)
Emit when you require a panel to be show in the interface.
void openPanel(QgsPanelWidget *panel)
Open a panel or dialog depending on dock mode setting If dock mode is true this method will emit the ...
virtual void setDockMode(bool dockMode)
Set the widget in dock mode which tells the widget to emit panel widgets and not open dialogs.
A class to represent a 2D point.
Definition qgspointxy.h:60
double y
Definition qgspointxy.h:64
double x
Definition qgspointxy.h:63
static QgsProject * instance()
Returns the QgsProject singleton instance.
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
void lockChanged(bool locked)
Emitted whenever the lock state changes.
void pushRecentSymbol(const QString &identifier, QgsSymbol *symbol)
Pushes a recently used symbol with the specified identifier.
A rectangle specified with double values.
static QgsRectangle fromCenterAndSize(const QgsPointXY &center, double width, double height)
Creates a new rectangle, given the specified center point and width and height.
QgsPointXY center
Contains information about a rendered annotation item.
A widget for editing rich text documents, with support for user controlled formatting of text and ins...
@ PlainText
Plain text mode.
@ QgsTextRenderer
QGIS text renderer mode, exposes the HTML/CSS subset supported by the QgsTextRenderer class.
void textChanged()
Emitted when the text contents are changed.
@ CurrentPageOnly
Only the size of the current page is considered when calculating the stacked widget size.
static QgsStyle * defaultStyle(bool initialize=true)
Returns the default application-wide style.
Definition qgsstyle.cpp:146
QSizeF svgViewboxSize(const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth, double widthScaleFactor, double fixedAspectRatio=0, bool blocking=false, const QMap< QString, QString > &parameters=QMap< QString, QString >())
Calculates the viewbox size of a (possibly cached) SVG file.
void changed()
Emitted when the symbol's settings are changed.
Symbol selector widget that can be used to select and build a symbol.
void symbolModified()
Emitted when a symbol is modified in the widget.
Contains settings which reflect the context in which a symbol (or renderer) widget is shown,...
QgsExpressionContext * expressionContext() const
Returns the expression context used for the widget, if set.
QgsMapCanvas * mapCanvas() const
Returns the map canvas associated with the widget.
QgsMessageBar * messageBar() const
Returns the message bar associated with the widget.
Abstract base class for all rendered symbols.
Definition qgssymbol.h:231
A widget for customizing text formatting settings.
void widgetChanged()
Emitted when the text format defined by the widget changes.
void changed()
Emitted when the selected unit is changed, or the definition of the map unit scale is changed.
QList< Qgis::RenderUnit > RenderUnitList
List of render units.
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition qgis.h:5970