QGIS API Documentation 3.41.0-Master (88383c3d16f)
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 mTextEdit->setMode( QgsRichTextEditor::Mode::QgsTextRenderer );
318
319 mTextFormatButton->setMode( QgsFontButton::ModeTextRenderer );
320
321 mSpinTextAngle->setClearValue( 0 );
322
323 mRotationModeCombo->addItem( tr( "Ignore Map Rotation" ), QVariant::fromValue( Qgis::SymbolRotationMode::IgnoreMapRotation ) );
324 mRotationModeCombo->addItem( tr( "Rotate With Map" ), QVariant::fromValue( Qgis::SymbolRotationMode::RespectMapRotation ) );
325
326 mAlignmentComboBox->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight );
327
328 connect( mTextFormatButton, &QgsFontButton::changed, this, [=] {
329 mTextEdit->setMode(
330 mTextFormatButton->textFormat().allowHtmlFormatting() ? QgsRichTextEditor::Mode::QgsTextRenderer : QgsRichTextEditor::Mode::PlainText
331 );
332
333 if ( !mBlockChangedSignal )
334 emit itemChanged();
335 } );
336 connect( mTextEdit, &QgsRichTextEditor::textChanged, this, [=] {
337 if ( !mBlockChangedSignal )
338 emit itemChanged();
339 } );
340 connect( mInsertExpressionButton, &QPushButton::clicked, this, &QgsAnnotationPointTextItemWidget::mInsertExpressionButton_clicked );
341 connect( mPropertiesWidget, &QgsAnnotationItemCommonPropertiesWidget::itemChanged, this, [=] {
342 if ( !mBlockChangedSignal )
343 emit itemChanged();
344 } );
345
346 connect( mSpinTextAngle, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, [=] {
347 if ( !mBlockChangedSignal )
348 emit itemChanged();
349 } );
350
351 connect( mRotationModeCombo, qOverload<int>( &QComboBox::currentIndexChanged ), this, [=] {
352 if ( !mBlockChangedSignal )
353 emit itemChanged();
354 } );
355
356 connect( mAlignmentComboBox, &QgsAlignmentComboBox::changed, this, [=] {
357 if ( !mBlockChangedSignal )
358 emit itemChanged();
359 } );
360}
361
362QgsAnnotationItem *QgsAnnotationPointTextItemWidget::createItem()
363{
364 QgsAnnotationPointTextItem *newItem = mItem->clone();
365 updateItem( newItem );
366 return newItem;
367}
368
369void QgsAnnotationPointTextItemWidget::updateItem( QgsAnnotationItem *item )
370{
371 if ( QgsAnnotationPointTextItem *pointTextItem = dynamic_cast<QgsAnnotationPointTextItem *>( item ) )
372 {
373 mBlockChangedSignal = true;
374 pointTextItem->setFormat( mTextFormatButton->textFormat() );
375 pointTextItem->setText( mTextFormatButton->textFormat().allowHtmlFormatting() ? mTextEdit->toHtml() : mTextEdit->toPlainText() );
376 pointTextItem->setAngle( mSpinTextAngle->value() );
377 pointTextItem->setRotationMode( mRotationModeCombo->currentData().value<Qgis::SymbolRotationMode>() );
378 pointTextItem->setAlignment( mAlignmentComboBox->currentAlignment() );
379 mBlockChangedSignal = false;
380 mPropertiesWidget->updateItem( pointTextItem );
381 }
382}
383
384void QgsAnnotationPointTextItemWidget::setContext( const QgsSymbolWidgetContext &context )
385{
387 if ( mTextFormatButton )
388 {
389 mTextFormatButton->setMapCanvas( context.mapCanvas() );
390 mTextFormatButton->setMessageBar( context.messageBar() );
391 }
392 mPropertiesWidget->setContext( context );
393}
394
395void QgsAnnotationPointTextItemWidget::focusDefaultWidget()
396{
397 mTextEdit->textEdit()->selectAll();
398 mTextEdit->setFocus();
399}
400
401QgsAnnotationPointTextItemWidget::~QgsAnnotationPointTextItemWidget() = default;
402
403bool QgsAnnotationPointTextItemWidget::setNewItem( QgsAnnotationItem *item )
404{
405 QgsAnnotationPointTextItem *textItem = dynamic_cast<QgsAnnotationPointTextItem *>( item );
406 if ( !textItem )
407 return false;
408
409 mItem.reset( textItem->clone() );
410
411 mBlockChangedSignal = true;
412 mTextFormatButton->setTextFormat( mItem->format() );
413 mTextEdit->setMode( mItem->format().allowHtmlFormatting() ? QgsRichTextEditor::Mode::QgsTextRenderer : QgsRichTextEditor::Mode::PlainText );
414 mTextEdit->setText( mItem->text() );
415 mSpinTextAngle->setValue( mItem->angle() );
416 mRotationModeCombo->setCurrentIndex( mRotationModeCombo->findData( QVariant::fromValue( mItem->rotationMode() ) ) );
417 mAlignmentComboBox->setCurrentAlignment( mItem->alignment() & Qt::AlignHorizontal_Mask );
418 mPropertiesWidget->setItem( mItem.get() );
419 mBlockChangedSignal = false;
420
421 return true;
422}
423
424void QgsAnnotationPointTextItemWidget::mInsertExpressionButton_clicked()
425{
426 QString expression = QgsExpressionFinder::findAndSelectActiveExpression( mTextEdit->textEdit() );
427
428 QgsExpressionContext expressionContext;
429 if ( context().expressionContext() )
430 expressionContext = *( context().expressionContext() );
431 else
432 expressionContext = QgsProject::instance()->createExpressionContext();
433
434 QgsExpressionBuilderDialog exprDlg( nullptr, expression, this, QStringLiteral( "generic" ), expressionContext );
435
436 exprDlg.setWindowTitle( tr( "Insert Expression" ) );
437 if ( exprDlg.exec() == QDialog::Accepted )
438 {
439 expression = exprDlg.expressionText().trimmed();
440 if ( !expression.isEmpty() )
441 {
442 mTextEdit->textEdit()->insertPlainText( "[%" + expression + "%]" );
443 }
444 }
445}
446
447
448//
449// QgsAnnotationLineTextItemWidget
450//
451
452QgsAnnotationLineTextItemWidget::QgsAnnotationLineTextItemWidget( QWidget *parent )
454{
455 setupUi( this );
456
457 mTextFormatButton->setMode( QgsFontButton::ModeTextRenderer );
458
459 mTextEdit->setMode( QgsRichTextEditor::Mode::QgsTextRenderer );
460
461 connect( mTextFormatButton, &QgsFontButton::changed, this, [=] {
462 mTextEdit->setMode(
463 mTextFormatButton->textFormat().allowHtmlFormatting() ? QgsRichTextEditor::Mode::QgsTextRenderer : QgsRichTextEditor::Mode::PlainText
464 );
465
466 if ( !mBlockChangedSignal )
467 emit itemChanged();
468 } );
469 connect( mTextEdit, &QgsRichTextEditor::textChanged, this, [=] {
470 if ( !mBlockChangedSignal )
471 emit itemChanged();
472 } );
473 connect( mInsertExpressionButton, &QPushButton::clicked, this, &QgsAnnotationLineTextItemWidget::mInsertExpressionButton_clicked );
474 connect( mPropertiesWidget, &QgsAnnotationItemCommonPropertiesWidget::itemChanged, this, [=] {
475 if ( !mBlockChangedSignal )
476 emit itemChanged();
477 } );
478
480 mSpinOffset->setClearValue( 0.0 );
481 connect( mSpinOffset, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, [=] {
482 if ( !mBlockChangedSignal )
483 emit itemChanged();
484 } );
485
486 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, [=] {
487 if ( !mBlockChangedSignal )
488 emit itemChanged();
489 } );
490}
491
492QgsAnnotationLineTextItemWidget::~QgsAnnotationLineTextItemWidget() = default;
493
494QgsAnnotationItem *QgsAnnotationLineTextItemWidget::createItem()
495{
496 QgsAnnotationLineTextItem *newItem = mItem->clone();
497 updateItem( newItem );
498 return newItem;
499}
500
501void QgsAnnotationLineTextItemWidget::updateItem( QgsAnnotationItem *item )
502{
503 if ( QgsAnnotationLineTextItem *lineTextItem = dynamic_cast<QgsAnnotationLineTextItem *>( item ) )
504 {
505 mBlockChangedSignal = true;
506 lineTextItem->setFormat( mTextFormatButton->textFormat() );
507 lineTextItem->setText( mTextFormatButton->textFormat().allowHtmlFormatting() ? mTextEdit->toHtml() : mTextEdit->toPlainText() );
508
509 lineTextItem->setOffsetFromLine( mSpinOffset->value() );
510 lineTextItem->setOffsetFromLineUnit( mOffsetUnitWidget->unit() );
511 lineTextItem->setOffsetFromLineMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
512
513 mBlockChangedSignal = false;
514 mPropertiesWidget->updateItem( lineTextItem );
515 }
516}
517
518void QgsAnnotationLineTextItemWidget::setContext( const QgsSymbolWidgetContext &context )
519{
521 if ( mTextFormatButton )
522 {
523 mTextFormatButton->setMapCanvas( context.mapCanvas() );
524 mTextFormatButton->setMessageBar( context.messageBar() );
525 }
526 mPropertiesWidget->setContext( context );
527}
528
529void QgsAnnotationLineTextItemWidget::focusDefaultWidget()
530{
531 mTextEdit->textEdit()->selectAll();
532 mTextEdit->setFocus();
533}
534
535bool QgsAnnotationLineTextItemWidget::setNewItem( QgsAnnotationItem *item )
536{
537 QgsAnnotationLineTextItem *textItem = dynamic_cast<QgsAnnotationLineTextItem *>( item );
538 if ( !textItem )
539 return false;
540
541 mItem.reset( textItem->clone() );
542
543 mBlockChangedSignal = true;
544 mTextFormatButton->setTextFormat( mItem->format() );
545 mTextEdit->setMode( mItem->format().allowHtmlFormatting() ? QgsRichTextEditor::Mode::QgsTextRenderer : QgsRichTextEditor::Mode::PlainText );
546 mTextEdit->setText( mItem->text() );
547 mPropertiesWidget->setItem( mItem.get() );
548
549 mSpinOffset->setValue( mItem->offsetFromLine() );
550 mOffsetUnitWidget->setUnit( mItem->offsetFromLineUnit() );
551 mOffsetUnitWidget->setMapUnitScale( mItem->offsetFromLineMapUnitScale() );
552
553 mBlockChangedSignal = false;
554
555 return true;
556}
557
558void QgsAnnotationLineTextItemWidget::mInsertExpressionButton_clicked()
559{
560 QString expression = QgsExpressionFinder::findAndSelectActiveExpression( mTextEdit->textEdit() );
561
562 QgsExpressionContext expressionContext;
563 if ( context().expressionContext() )
564 expressionContext = *( context().expressionContext() );
565 else
566 expressionContext = QgsProject::instance()->createExpressionContext();
567
568 QgsExpressionBuilderDialog exprDlg( nullptr, expression, this, QStringLiteral( "generic" ), expressionContext );
569
570 exprDlg.setWindowTitle( tr( "Insert Expression" ) );
571 if ( exprDlg.exec() == QDialog::Accepted )
572 {
573 expression = exprDlg.expressionText().trimmed();
574 if ( !expression.isEmpty() )
575 {
576 mTextEdit->textEdit()->insertPlainText( "[%" + expression + "%]" );
577 }
578 }
579}
580
581
582//
583// QgsAnnotationRectangleTextItemWidget
584//
585
586QgsAnnotationRectangleTextItemWidget::QgsAnnotationRectangleTextItemWidget( QWidget *parent )
588{
589 setupUi( this );
590
591 mSizeModeCombo->addItem( tr( "Scale Dependent Size" ), QVariant::fromValue( Qgis::AnnotationPlacementMode::SpatialBounds ) );
592 mSizeModeCombo->addItem( tr( "Fixed Size" ), QVariant::fromValue( Qgis::AnnotationPlacementMode::FixedSize ) );
593 mSizeModeCombo->addItem( tr( "Relative to Map" ), QVariant::fromValue( Qgis::AnnotationPlacementMode::RelativeToMapFrame ) );
594
596
597 mBackgroundSymbolButton->setSymbolType( Qgis::SymbolType::Fill );
598 mBackgroundSymbolButton->setDialogTitle( tr( "Background" ) );
599 mBackgroundSymbolButton->registerExpressionContextGenerator( this );
600 mFrameSymbolButton->setSymbolType( Qgis::SymbolType::Fill );
601 mFrameSymbolButton->setDialogTitle( tr( "Frame" ) );
602 mFrameSymbolButton->registerExpressionContextGenerator( this );
603
604 mSpinBottomMargin->setClearValue( 0 );
605 mSpinTopMargin->setClearValue( 0 );
606 mSpinRightMargin->setClearValue( 0 );
607 mSpinLeftMargin->setClearValue( 0 );
609
610 mTextFormatButton->setMode( QgsFontButton::ModeTextRenderer );
611
612 mTextEdit->setMode( QgsRichTextEditor::Mode::QgsTextRenderer );
613
614 mAlignmentComboBox->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight | Qt::AlignJustify );
615 mVerticalAlignmentComboBox->setAvailableAlignments( Qt::AlignTop | Qt::AlignVCenter | Qt::AlignBottom );
616
617 connect( mTextFormatButton, &QgsFontButton::changed, this, [this] {
618 mTextEdit->setMode(
619 mTextFormatButton->textFormat().allowHtmlFormatting() ? QgsRichTextEditor::Mode::QgsTextRenderer : QgsRichTextEditor::Mode::PlainText
620 );
621
622 onWidgetChanged();
623 } );
624 connect( mTextEdit, &QgsRichTextEditor::textChanged, this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
625 connect( mInsertExpressionButton, &QPushButton::clicked, this, &QgsAnnotationRectangleTextItemWidget::mInsertExpressionButton_clicked );
626 connect( mPropertiesWidget, &QgsAnnotationItemCommonPropertiesWidget::itemChanged, this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
627 connect( mAlignmentComboBox, &QgsAlignmentComboBox::changed, this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
628 connect( mVerticalAlignmentComboBox, &QgsAlignmentComboBox::changed, this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
629 connect( mFrameCheckbox, &QGroupBox::toggled, this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
630 connect( mBackgroundCheckbox, &QGroupBox::toggled, this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
631 connect( mBackgroundSymbolButton, &QgsSymbolButton::changed, this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
632 connect( mFrameSymbolButton, &QgsSymbolButton::changed, this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
633 connect( mSpinTopMargin, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
634 connect( mSpinRightMargin, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
635 connect( mSpinLeftMargin, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
636 connect( mSpinBottomMargin, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
637 connect( mMarginUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
638
639 connect( mSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
640
641 connect( mWidthSpinBox, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, &QgsAnnotationRectangleTextItemWidget::setWidth );
642 connect( mHeightSpinBox, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, &QgsAnnotationRectangleTextItemWidget::setHeight );
643
644 connect( mSizeModeCombo, qOverload<int>( &QComboBox::currentIndexChanged ), this, &QgsAnnotationRectangleTextItemWidget::sizeModeChanged );
645 mWidgetFixedSize->hide();
646 sizeModeChanged();
647}
648
649QgsAnnotationItem *QgsAnnotationRectangleTextItemWidget::createItem()
650{
651 QgsAnnotationRectangleTextItem *newItem = mItem->clone();
652 updateItem( newItem );
653 return newItem;
654}
655
656void QgsAnnotationRectangleTextItemWidget::updateItem( QgsAnnotationItem *item )
657{
658 if ( QgsAnnotationRectangleTextItem *rectTextItem = dynamic_cast<QgsAnnotationRectangleTextItem *>( item ) )
659 {
660 mBlockChangedSignal = true;
661 rectTextItem->setFormat( mTextFormatButton->textFormat() );
662 rectTextItem->setText( mTextFormatButton->textFormat().allowHtmlFormatting() ? mTextEdit->toHtml() : mTextEdit->toPlainText() );
663 rectTextItem->setAlignment( mAlignmentComboBox->currentAlignment() | mVerticalAlignmentComboBox->currentAlignment() );
664
665 rectTextItem->setPlacementMode( mSizeModeCombo->currentData().value<Qgis::AnnotationPlacementMode>() );
666
667 rectTextItem->setFixedSize( QSizeF( mWidthSpinBox->value(), mHeightSpinBox->value() ) );
668 rectTextItem->setFixedSizeUnit( mSizeUnitWidget->unit() );
669
670 rectTextItem->setBackgroundEnabled( mBackgroundCheckbox->isChecked() );
671 rectTextItem->setFrameEnabled( mFrameCheckbox->isChecked() );
672 rectTextItem->setBackgroundSymbol( mBackgroundSymbolButton->clonedSymbol<QgsFillSymbol>() );
673 rectTextItem->setFrameSymbol( mFrameSymbolButton->clonedSymbol<QgsFillSymbol>() );
674
675 rectTextItem->setMargins( QgsMargins( mSpinLeftMargin->value(), mSpinTopMargin->value(), mSpinRightMargin->value(), mSpinBottomMargin->value() ) );
676 rectTextItem->setMarginsUnit( mMarginUnitWidget->unit() );
677
678 if ( mUpdateItemPosition )
679 {
680 rectTextItem->setBounds( mItem->bounds() );
681 mUpdateItemPosition = false;
682 }
683
684 mBlockChangedSignal = false;
685
686 mPropertiesWidget->updateItem( rectTextItem );
687 }
688}
689
690void QgsAnnotationRectangleTextItemWidget::setContext( const QgsSymbolWidgetContext &context )
691{
693 if ( mTextFormatButton )
694 {
695 mTextFormatButton->setMapCanvas( context.mapCanvas() );
696 mTextFormatButton->setMessageBar( context.messageBar() );
697 }
698 mBackgroundSymbolButton->setMapCanvas( context.mapCanvas() );
699 mBackgroundSymbolButton->setMessageBar( context.messageBar() );
700 mFrameSymbolButton->setMapCanvas( context.mapCanvas() );
701 mFrameSymbolButton->setMessageBar( context.messageBar() );
702 mPropertiesWidget->setContext( context );
703}
704
705QgsExpressionContext QgsAnnotationRectangleTextItemWidget::createExpressionContext() const
706{
707 QgsExpressionContext expressionContext;
708 if ( context().expressionContext() )
709 expressionContext = *( context().expressionContext() );
710 else
711 expressionContext = QgsProject::instance()->createExpressionContext();
712 return expressionContext;
713}
714
715void QgsAnnotationRectangleTextItemWidget::focusDefaultWidget()
716{
717 mTextEdit->textEdit()->selectAll();
718 mTextEdit->setFocus();
719}
720
721QgsAnnotationRectangleTextItemWidget::~QgsAnnotationRectangleTextItemWidget() = default;
722
723bool QgsAnnotationRectangleTextItemWidget::setNewItem( QgsAnnotationItem *item )
724{
725 QgsAnnotationRectangleTextItem *textItem = dynamic_cast<QgsAnnotationRectangleTextItem *>( item );
726 if ( !textItem )
727 return false;
728
729 mItem.reset( textItem->clone() );
730
731 mBlockChangedSignal = true;
732 mTextFormatButton->setTextFormat( mItem->format() );
733 mTextEdit->setMode( mItem->format().allowHtmlFormatting() ? QgsRichTextEditor::Mode::QgsTextRenderer : QgsRichTextEditor::Mode::PlainText );
734 mTextEdit->setText( mItem->text() );
735 mAlignmentComboBox->setCurrentAlignment( mItem->alignment() & Qt::AlignHorizontal_Mask );
736 mVerticalAlignmentComboBox->setCurrentAlignment( mItem->alignment() & Qt::AlignVertical_Mask );
737 mPropertiesWidget->setItem( mItem.get() );
738
739 mBackgroundCheckbox->setChecked( textItem->backgroundEnabled() );
740 if ( const QgsSymbol *symbol = textItem->backgroundSymbol() )
741 mBackgroundSymbolButton->setSymbol( symbol->clone() );
742
743 mFrameCheckbox->setChecked( textItem->frameEnabled() );
744 if ( const QgsSymbol *symbol = textItem->frameSymbol() )
745 mFrameSymbolButton->setSymbol( symbol->clone() );
746
747 mMarginUnitWidget->setUnit( textItem->marginsUnit() );
748 mSpinLeftMargin->setValue( textItem->margins().left() );
749 mSpinTopMargin->setValue( textItem->margins().top() );
750 mSpinRightMargin->setValue( textItem->margins().right() );
751 mSpinBottomMargin->setValue( textItem->margins().bottom() );
752
753 mWidthSpinBox->setValue( textItem->fixedSize().width() );
754 mHeightSpinBox->setValue( textItem->fixedSize().height() );
755 mSizeUnitWidget->setUnit( textItem->fixedSizeUnit() );
756 mSizeModeCombo->setCurrentIndex( mSizeModeCombo->findData( QVariant::fromValue( textItem->placementMode() ) ) );
757
758 mBlockChangedSignal = false;
759
760 return true;
761}
762
763void QgsAnnotationRectangleTextItemWidget::onWidgetChanged()
764{
765 if ( !mBlockChangedSignal )
766 emit itemChanged();
767}
768
769void QgsAnnotationRectangleTextItemWidget::sizeModeChanged()
770{
771 const Qgis::AnnotationPlacementMode mode = mSizeModeCombo->currentData().value<Qgis::AnnotationPlacementMode>();
772 switch ( mode )
773 {
775 mWidgetFixedSize->hide();
776 break;
777
779 if ( const QgsRenderedAnnotationItemDetails *details = renderedItemDetails() )
780 {
781 const QgsRectangle itemBoundsMapUnits = details->boundingBox();
782 if ( QgsMapCanvas *canvas = context().mapCanvas() )
783 {
784 const QgsPointXY topLeftPixels = canvas->mapSettings().mapToPixel().transform( itemBoundsMapUnits.xMinimum(), itemBoundsMapUnits.yMinimum() );
785 const QgsPointXY bottomRightPixels = canvas->mapSettings().mapToPixel().transform( itemBoundsMapUnits.xMaximum(), itemBoundsMapUnits.yMaximum() );
786 const double widthPixels = std::abs( bottomRightPixels.x() - topLeftPixels.x() );
787 const double heightPixels = std::abs( bottomRightPixels.y() - topLeftPixels.y() );
788
789 // convert width/height in pixels to mm
790 const double pixelsPerMm = canvas->mapSettings().outputDpi() / 25.4;
791 mItem->setFixedSizeUnit( Qgis::RenderUnit::Millimeters );
792 mItem->setFixedSize( QSizeF( widthPixels / pixelsPerMm, heightPixels / pixelsPerMm ) );
793
794 // and update widget UI accordingly
795 whileBlocking( mWidthSpinBox )->setValue( mItem->fixedSize().width() );
796 whileBlocking( mHeightSpinBox )->setValue( mItem->fixedSize().height() );
797 whileBlocking( mSizeUnitWidget )->setUnit( mItem->fixedSizeUnit() );
798
799 mUpdateItemPosition = true;
800 }
801 }
802
803 mWidgetFixedSize->show();
804 break;
805
807 {
808 if ( const QgsRenderedAnnotationItemDetails *details = renderedItemDetails() )
809 {
810 // convert item bounds to relative position
811 const QgsRectangle itemBounds = details->boundingBox();
812 if ( QgsMapCanvas *canvas = context().mapCanvas() )
813 {
814 const double centerX = ( itemBounds.center().x() - canvas->extent().xMinimum() ) / canvas->extent().width();
815 const double centerY = ( canvas->extent().yMaximum() - itemBounds.center().y() ) / canvas->extent().height();
816 mItem->setBounds( QgsRectangle::fromCenterAndSize( QgsPointXY( centerX, centerY ), 0.5, 0.5 ) );
817 mUpdateItemPosition = true;
818 }
819 }
820
821 mWidgetFixedSize->hide();
822 break;
823 }
824 }
825
826 onWidgetChanged();
827}
828
829void QgsAnnotationRectangleTextItemWidget::setWidth()
830{
831 onWidgetChanged();
832}
833
834void QgsAnnotationRectangleTextItemWidget::setHeight()
835{
836 onWidgetChanged();
837}
838
839void QgsAnnotationRectangleTextItemWidget::mInsertExpressionButton_clicked()
840{
841 QString expression = QgsExpressionFinder::findAndSelectActiveExpression( mTextEdit->textEdit() );
842
843 QgsExpressionBuilderDialog exprDlg( nullptr, expression, this, QStringLiteral( "generic" ), createExpressionContext() );
844
845 exprDlg.setWindowTitle( tr( "Insert Expression" ) );
846 if ( exprDlg.exec() == QDialog::Accepted )
847 {
848 expression = exprDlg.expressionText().trimmed();
849 if ( !expression.isEmpty() )
850 {
851 mTextEdit->textEdit()->insertPlainText( "[%" + expression + "%]" );
852 }
853 }
854}
855
856
857//
858// QgsAnnotationPictureItemWidget
859//
860
861QgsAnnotationPictureItemWidget::QgsAnnotationPictureItemWidget( QWidget *parent )
863{
864 setupUi( this );
865
866 mSizeStackedWidget->setSizeMode( QgsStackedWidget::SizeMode::CurrentPageOnly );
867
868 mSizeModeCombo->addItem( tr( "Scale Dependent Size" ), QVariant::fromValue( Qgis::AnnotationPlacementMode::SpatialBounds ) );
869 mSizeModeCombo->addItem( tr( "Fixed Size" ), QVariant::fromValue( Qgis::AnnotationPlacementMode::FixedSize ) );
870 mSizeModeCombo->addItem( tr( "Relative to Map" ), QVariant::fromValue( Qgis::AnnotationPlacementMode::RelativeToMapFrame ) );
871
873
874 mBackgroundSymbolButton->setSymbolType( Qgis::SymbolType::Fill );
875 mBackgroundSymbolButton->setDialogTitle( tr( "Background" ) );
876 mBackgroundSymbolButton->registerExpressionContextGenerator( this );
877 mFrameSymbolButton->setSymbolType( Qgis::SymbolType::Fill );
878 mFrameSymbolButton->setDialogTitle( tr( "Frame" ) );
879 mFrameSymbolButton->registerExpressionContextGenerator( this );
880
881 connect( mPropertiesWidget, &QgsAnnotationItemCommonPropertiesWidget::itemChanged, this, [=] {
882 if ( !mBlockChangedSignal )
883 emit itemChanged();
884 } );
885
886 connect( mSizeModeCombo, qOverload<int>( &QComboBox::currentIndexChanged ), this, &QgsAnnotationPictureItemWidget::sizeModeChanged );
887
888 connect( mRadioSVG, &QRadioButton::toggled, this, &QgsAnnotationPictureItemWidget::modeChanged );
889 connect( mRadioRaster, &QRadioButton::toggled, this, &QgsAnnotationPictureItemWidget::modeChanged );
890 connect( mSourceLineEdit, &QgsPictureSourceLineEditBase::sourceChanged, this, [=]( const QString &source ) {
891 if ( !mRadioSVG->isChecked() && QFileInfo( source ).suffix().compare( QLatin1String( "svg" ), Qt::CaseInsensitive ) == 0 )
892 {
893 mRadioSVG->setChecked( true );
894 }
895
896 onWidgetChanged();
897 } );
898
899 connect( mLockAspectRatioCheck, &QCheckBox::toggled, this, &QgsAnnotationPictureItemWidget::onWidgetChanged );
900 connect( mFrameCheckbox, &QGroupBox::toggled, this, &QgsAnnotationPictureItemWidget::onWidgetChanged );
901 connect( mBackgroundCheckbox, &QGroupBox::toggled, this, &QgsAnnotationPictureItemWidget::onWidgetChanged );
902 connect( mBackgroundSymbolButton, &QgsSymbolButton::changed, this, &QgsAnnotationPictureItemWidget::onWidgetChanged );
903 connect( mFrameSymbolButton, &QgsSymbolButton::changed, this, &QgsAnnotationPictureItemWidget::onWidgetChanged );
904 connect( mSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsAnnotationPictureItemWidget::onWidgetChanged );
905
906 connect( mWidthSpinBox, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, &QgsAnnotationPictureItemWidget::setWidth );
907 connect( mHeightSpinBox, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, &QgsAnnotationPictureItemWidget::setHeight );
908 connect( mLockAspectRatio, &QgsRatioLockButton::lockChanged, this, &QgsAnnotationPictureItemWidget::setLockAspectRatio );
909}
910
911QgsAnnotationPictureItemWidget::~QgsAnnotationPictureItemWidget() = default;
912
913QgsAnnotationItem *QgsAnnotationPictureItemWidget::createItem()
914{
915 QgsAnnotationPictureItem *newItem = mItem->clone();
916 updateItem( newItem );
917 return newItem;
918}
919
920void QgsAnnotationPictureItemWidget::updateItem( QgsAnnotationItem *item )
921{
922 if ( QgsAnnotationPictureItem *pictureItem = dynamic_cast<QgsAnnotationPictureItem *>( item ) )
923 {
924 const bool svg = mRadioSVG->isChecked();
926 const QString path = mSourceLineEdit->source();
927 pictureItem->setPath( newFormat, path );
928
929 pictureItem->setPlacementMode( mSizeModeCombo->currentData().value<Qgis::AnnotationPlacementMode>() );
930 switch ( pictureItem->placementMode() )
931 {
933 pictureItem->setLockAspectRatio( mLockAspectRatioCheck->isChecked() );
934 break;
937 pictureItem->setLockAspectRatio( mLockAspectRatio->isChecked() );
938 break;
939 }
940
941 pictureItem->setFixedSize( QSizeF( mWidthSpinBox->value(), mHeightSpinBox->value() ) );
942 pictureItem->setFixedSizeUnit( mSizeUnitWidget->unit() );
943
944 pictureItem->setBackgroundEnabled( mBackgroundCheckbox->isChecked() );
945 pictureItem->setFrameEnabled( mFrameCheckbox->isChecked() );
946 pictureItem->setBackgroundSymbol( mBackgroundSymbolButton->clonedSymbol<QgsFillSymbol>() );
947 pictureItem->setFrameSymbol( mFrameSymbolButton->clonedSymbol<QgsFillSymbol>() );
948
949 if ( mUpdateItemPosition )
950 {
951 pictureItem->setBounds( mItem->bounds() );
952 mUpdateItemPosition = false;
953 }
954
955 mPropertiesWidget->updateItem( pictureItem );
956 }
957}
958
959void QgsAnnotationPictureItemWidget::setDockMode( bool dockMode )
960{
962}
963
964void QgsAnnotationPictureItemWidget::setContext( const QgsSymbolWidgetContext &context )
965{
967 mPropertiesWidget->setContext( context );
968 mBackgroundSymbolButton->setMapCanvas( context.mapCanvas() );
969 mBackgroundSymbolButton->setMessageBar( context.messageBar() );
970 mFrameSymbolButton->setMapCanvas( context.mapCanvas() );
971 mFrameSymbolButton->setMessageBar( context.messageBar() );
972}
973
974QgsExpressionContext QgsAnnotationPictureItemWidget::createExpressionContext() const
975{
976 QgsExpressionContext expressionContext;
977 if ( context().expressionContext() )
978 expressionContext = *( context().expressionContext() );
979 else
980 expressionContext = QgsProject::instance()->createExpressionContext();
981 return expressionContext;
982}
983
984void QgsAnnotationPictureItemWidget::focusDefaultWidget()
985{
986 mSourceLineEdit->setFocus();
987}
988
989bool QgsAnnotationPictureItemWidget::setNewItem( QgsAnnotationItem *item )
990{
991 QgsAnnotationPictureItem *pictureItem = dynamic_cast<QgsAnnotationPictureItem *>( item );
992 if ( !pictureItem )
993 return false;
994
995 mItem.reset( pictureItem->clone() );
996
997 mBlockChangedSignal = true;
998 mPropertiesWidget->setItem( mItem.get() );
999
1000 mLockAspectRatioCheck->setChecked( mItem->lockAspectRatio() );
1001 mLockAspectRatio->setLocked( mItem->lockAspectRatio() );
1002 switch ( pictureItem->format() )
1003 {
1005 mRadioSVG->setChecked( true );
1006 break;
1008 mRadioRaster->setChecked( true );
1009 break;
1011 break;
1012 }
1013
1014 mSourceLineEdit->setSource( pictureItem->path() );
1015
1016 mBackgroundCheckbox->setChecked( pictureItem->backgroundEnabled() );
1017 if ( const QgsSymbol *symbol = pictureItem->backgroundSymbol() )
1018 mBackgroundSymbolButton->setSymbol( symbol->clone() );
1019
1020 mFrameCheckbox->setChecked( pictureItem->frameEnabled() );
1021 if ( const QgsSymbol *symbol = pictureItem->frameSymbol() )
1022 mFrameSymbolButton->setSymbol( symbol->clone() );
1023
1024 mWidthSpinBox->setValue( pictureItem->fixedSize().width() );
1025 mHeightSpinBox->setValue( pictureItem->fixedSize().height() );
1026 mSizeModeCombo->setCurrentIndex( mSizeModeCombo->findData( QVariant::fromValue( pictureItem->placementMode() ) ) );
1027 sizeModeChanged();
1028
1029 mBlockChangedSignal = false;
1030
1031 return true;
1032}
1033
1034void QgsAnnotationPictureItemWidget::onWidgetChanged()
1035{
1036 if ( !mBlockChangedSignal )
1037 emit itemChanged();
1038}
1039
1040void QgsAnnotationPictureItemWidget::modeChanged( bool checked )
1041{
1042 if ( !checked )
1043 return;
1044
1045 const bool svg = mRadioSVG->isChecked();
1046
1047 if ( svg )
1048 mSourceLineEdit->setMode( QgsPictureSourceLineEditBase::Svg );
1049 else
1050 mSourceLineEdit->setMode( QgsPictureSourceLineEditBase::Image );
1051
1052 onWidgetChanged();
1053}
1054
1055void QgsAnnotationPictureItemWidget::sizeModeChanged()
1056{
1057 const Qgis::AnnotationPlacementMode mode = mSizeModeCombo->currentData().value<Qgis::AnnotationPlacementMode>();
1058 switch ( mode )
1059 {
1061 mSizeStackedWidget->setCurrentWidget( mPageSpatialBounds );
1062 break;
1063
1065 mSizeStackedWidget->setCurrentWidget( mPageFixedSize );
1066 break;
1067
1069 {
1070 if ( const QgsRenderedAnnotationItemDetails *details = renderedItemDetails() )
1071 {
1072 // convert item bounds to relative position
1073 const QgsRectangle itemBounds = details->boundingBox();
1074 if ( QgsMapCanvas *canvas = context().mapCanvas() )
1075 {
1076 const double centerX = ( itemBounds.center().x() - canvas->extent().xMinimum() ) / canvas->extent().width();
1077 const double centerY = ( canvas->extent().yMaximum() - itemBounds.center().y() ) / canvas->extent().height();
1078 mItem->setBounds( QgsRectangle::fromCenterAndSize( QgsPointXY( centerX, centerY ), 0.5, 0.5 ) );
1079 mUpdateItemPosition = true;
1080 }
1081 }
1082
1083 mSizeStackedWidget->setCurrentWidget( mPageFixedSize );
1084 break;
1085 }
1086 }
1087
1088 onWidgetChanged();
1089}
1090
1091void QgsAnnotationPictureItemWidget::setWidth()
1092{
1093 if ( mLockAspectRatio->locked() )
1094 {
1095 const double ratio = pictureAspectRatio();
1096 if ( ratio > 0 )
1097 whileBlocking( mHeightSpinBox )->setValue( mWidthSpinBox->value() * ratio );
1098 }
1099
1100 onWidgetChanged();
1101}
1102
1103void QgsAnnotationPictureItemWidget::setHeight()
1104{
1105 if ( mLockAspectRatio->locked() )
1106 {
1107 const double ratio = pictureAspectRatio();
1108 if ( ratio > 0 )
1109 whileBlocking( mWidthSpinBox )->setValue( mHeightSpinBox->value() / ratio );
1110 }
1111
1112 onWidgetChanged();
1113}
1114
1115void QgsAnnotationPictureItemWidget::setLockAspectRatio( bool locked )
1116{
1117 if ( locked && !mBlockChangedSignal )
1118 {
1119 const double ratio = pictureAspectRatio();
1120 if ( ratio > 0 )
1121 whileBlocking( mHeightSpinBox )->setValue( mWidthSpinBox->value() * ratio );
1122 }
1123
1124 onWidgetChanged();
1125}
1126
1127double QgsAnnotationPictureItemWidget::pictureAspectRatio() const
1128{
1129 const bool svg = mRadioSVG->isChecked();
1130 const QString path = mSourceLineEdit->source();
1131 QSizeF size;
1132 if ( svg )
1133 {
1134 size = QgsApplication::svgCache()->svgViewboxSize( path, 100, QColor(), QColor(), 1, 1 );
1135 }
1136 else
1137 {
1138 size = QgsApplication::imageCache()->originalSize( path );
1139 }
1140 if ( size.isValid() && size.width() > 0 )
1141 return size.height() / size.width();
1142
1143 return 0;
1144}
1145
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:4984
@ 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:2395
@ 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 setText(const QString &text)
Sets the text rendered by 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 setText(const QString &text)
Sets the text rendered by the item.
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.
Qgis::RenderUnit fixedSizeUnit() const
Returns the units to use for fixed item sizes, when the placementMode() is Qgis::AnnotationPlacementM...
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.
void setText(const QString &text)
Sets the text rendered by the item.
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.
@ ModeTextRenderer
Configure font settings for use with QgsTextRenderer.
void changed()
Emitted when the widget's text format settings are changed.
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.
double xMinimum
double yMinimum
double xMaximum
double yMaximum
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
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:6029