QGIS API Documentation 3.99.0-Master (2fe06baccd8)
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
24#include "qgsapplication.h"
26#include "qgsexpressionfinder.h"
27#include "qgsfillsymbol.h"
28#include "qgsimagecache.h"
29#include "qgslinesymbol.h"
30#include "qgsmapcanvas.h"
31#include "qgsmarkersymbol.h"
34#include "qgsstyle.h"
35#include "qgssvgcache.h"
37#include "qgstextformatwidget.h"
38
39#include "moc_qgsannotationitemwidget_impl.cpp"
40
42
43QgsAnnotationPolygonItemWidget::QgsAnnotationPolygonItemWidget( QWidget *parent )
45{
46 setupUi( this );
47
48 mSelector = new QgsSymbolSelectorWidget( mSymbol.get(), QgsStyle::defaultStyle(), nullptr, nullptr );
49 mSelector->setDockMode( dockMode() );
50 connect( mSelector, &QgsSymbolSelectorWidget::symbolModified, this, [this] {
51 if ( !mBlockChangedSignal )
52 {
53 emit itemChanged();
54 QgsApplication::recentStyleHandler()->pushRecentSymbol( QStringLiteral( "polygon_annotation_item" ), qgis::down_cast<QgsFillSymbol *>( mSelector->symbol()->clone() ) );
55 }
56 } );
57 connect( mSelector, &QgsPanelWidget::showPanel, this, &QgsPanelWidget::openPanel );
58
59 QVBoxLayout *layout = new QVBoxLayout();
60 layout->setContentsMargins( 0, 0, 0, 0 );
61 layout->addWidget( mSelector );
62 mSymbolSelectorFrame->setLayout( layout );
63
64 connect( mPropertiesWidget, &QgsAnnotationItemCommonPropertiesWidget::itemChanged, this, [this] {
65 if ( !mBlockChangedSignal )
66 emit itemChanged();
67 } );
68}
69
70QgsAnnotationItem *QgsAnnotationPolygonItemWidget::createItem()
71{
72 QgsAnnotationPolygonItem *newItem = mItem->clone();
73 newItem->setSymbol( mSymbol->clone() );
74 mPropertiesWidget->updateItem( newItem );
75 return newItem;
76}
77
78void QgsAnnotationPolygonItemWidget::updateItem( QgsAnnotationItem *item )
79{
80 if ( QgsAnnotationPolygonItem *polygonItem = dynamic_cast<QgsAnnotationPolygonItem *>( item ) )
81 {
82 polygonItem->setSymbol( mSymbol->clone() );
83 mPropertiesWidget->updateItem( polygonItem );
84 }
85}
86
87void QgsAnnotationPolygonItemWidget::setDockMode( bool dockMode )
88{
90 if ( mSelector )
91 mSelector->setDockMode( dockMode );
92}
93
94void QgsAnnotationPolygonItemWidget::setContext( const QgsSymbolWidgetContext &context )
95{
97 if ( mSelector )
98 mSelector->setContext( context );
99 mPropertiesWidget->setContext( context );
100}
101
102QgsAnnotationPolygonItemWidget::~QgsAnnotationPolygonItemWidget() = default;
103
104bool QgsAnnotationPolygonItemWidget::setNewItem( QgsAnnotationItem *item )
105{
106 QgsAnnotationPolygonItem *polygonItem = dynamic_cast<QgsAnnotationPolygonItem *>( item );
107 if ( !polygonItem )
108 return false;
109
110 mItem.reset( polygonItem->clone() );
111 if ( mItem->symbol() )
112 {
113 mSymbol.reset( mItem->symbol()->clone() );
114 }
115 else
116 {
117 mSymbol = QgsFillSymbol::createSimple( {} );
118 }
119 mBlockChangedSignal = true;
120 mSelector->loadSymbol( mSymbol.get() );
121 mSelector->updatePreview();
122 mPropertiesWidget->setItem( mItem.get() );
123 mBlockChangedSignal = false;
124
125 return true;
126}
127
128
129//
130// QgsAnnotationLineItemWidget
131//
132
133QgsAnnotationLineItemWidget::QgsAnnotationLineItemWidget( QWidget *parent )
135{
136 setupUi( this );
137
138 mSelector = new QgsSymbolSelectorWidget( mSymbol.get(), QgsStyle::defaultStyle(), nullptr, nullptr );
139 mSelector->setDockMode( dockMode() );
140 connect( mSelector, &QgsSymbolSelectorWidget::symbolModified, this, [this] {
141 if ( !mBlockChangedSignal )
142 {
143 emit itemChanged();
144 QgsApplication::recentStyleHandler()->pushRecentSymbol( QStringLiteral( "line_annotation_item" ), qgis::down_cast<QgsLineSymbol *>( mSelector->symbol()->clone() ) );
145 }
146 } );
147 connect( mSelector, &QgsPanelWidget::showPanel, this, &QgsPanelWidget::openPanel );
148
149 QVBoxLayout *layout = new QVBoxLayout();
150 layout->setContentsMargins( 0, 0, 0, 0 );
151 layout->addWidget( mSelector );
152 mSymbolSelectorFrame->setLayout( layout );
153
154 connect( mPropertiesWidget, &QgsAnnotationItemCommonPropertiesWidget::itemChanged, this, [this] {
155 if ( !mBlockChangedSignal )
156 emit itemChanged();
157 } );
158}
159
160QgsAnnotationItem *QgsAnnotationLineItemWidget::createItem()
161{
162 QgsAnnotationLineItem *newItem = mItem->clone();
163 newItem->setSymbol( mSymbol->clone() );
164 mPropertiesWidget->updateItem( newItem );
165 return newItem;
166}
167
168void QgsAnnotationLineItemWidget::updateItem( QgsAnnotationItem *item )
169{
170 if ( QgsAnnotationLineItem *lineItem = dynamic_cast<QgsAnnotationLineItem *>( item ) )
171 {
172 lineItem->setSymbol( mSymbol->clone() );
173 mPropertiesWidget->updateItem( lineItem );
174 }
175}
176
177void QgsAnnotationLineItemWidget::setDockMode( bool dockMode )
178{
180 if ( mSelector )
181 mSelector->setDockMode( dockMode );
182}
183
184void QgsAnnotationLineItemWidget::setContext( const QgsSymbolWidgetContext &context )
185{
187 if ( mSelector )
188 mSelector->setContext( context );
189 mPropertiesWidget->setContext( context );
190}
191
192QgsAnnotationLineItemWidget::~QgsAnnotationLineItemWidget() = default;
193
194bool QgsAnnotationLineItemWidget::setNewItem( QgsAnnotationItem *item )
195{
196 QgsAnnotationLineItem *lineItem = dynamic_cast<QgsAnnotationLineItem *>( item );
197 if ( !lineItem )
198 return false;
199
200 mItem.reset( lineItem->clone() );
201 if ( mItem->symbol() )
202 {
203 mSymbol.reset( mItem->symbol()->clone() );
204 }
205 else
206 {
207 mSymbol = QgsLineSymbol::createSimple( {} );
208 }
209 mBlockChangedSignal = true;
210 mSelector->loadSymbol( mSymbol.get() );
211 mSelector->updatePreview();
212 mPropertiesWidget->setItem( mItem.get() );
213 mBlockChangedSignal = false;
214
215 return true;
216}
217
218
219//
220// QgsAnnotationMarkerItemWidget
221//
222
223QgsAnnotationMarkerItemWidget::QgsAnnotationMarkerItemWidget( QWidget *parent )
225{
226 setupUi( this );
227
228 mSelector = new QgsSymbolSelectorWidget( mSymbol.get(), QgsStyle::defaultStyle(), nullptr, nullptr );
229 mSelector->setDockMode( dockMode() );
230 connect( mSelector, &QgsSymbolSelectorWidget::symbolModified, this, [this] {
231 if ( !mBlockChangedSignal )
232 {
233 emit itemChanged();
234 QgsApplication::recentStyleHandler()->pushRecentSymbol( QStringLiteral( "marker_annotation_item" ), qgis::down_cast<QgsMarkerSymbol *>( mSelector->symbol()->clone() ) );
235 }
236 } );
237 connect( mSelector, &QgsPanelWidget::showPanel, this, &QgsPanelWidget::openPanel );
238
239 QVBoxLayout *layout = new QVBoxLayout();
240 layout->setContentsMargins( 0, 0, 0, 0 );
241 layout->addWidget( mSelector );
242 mSymbolSelectorFrame->setLayout( layout );
243
244 connect( mPropertiesWidget, &QgsAnnotationItemCommonPropertiesWidget::itemChanged, this, [this] {
245 if ( !mBlockChangedSignal )
246 emit itemChanged();
247 } );
248}
249
250QgsAnnotationItem *QgsAnnotationMarkerItemWidget::createItem()
251{
252 QgsAnnotationMarkerItem *newItem = mItem->clone();
253 newItem->setSymbol( mSymbol->clone() );
254 mPropertiesWidget->updateItem( newItem );
255 return newItem;
256}
257
258void QgsAnnotationMarkerItemWidget::updateItem( QgsAnnotationItem *item )
259{
260 if ( QgsAnnotationMarkerItem *markerItem = dynamic_cast<QgsAnnotationMarkerItem *>( item ) )
261 {
262 markerItem->setSymbol( mSymbol->clone() );
263 mPropertiesWidget->updateItem( markerItem );
264 }
265}
266
267void QgsAnnotationMarkerItemWidget::setDockMode( bool dockMode )
268{
270 if ( mSelector )
271 mSelector->setDockMode( dockMode );
272}
273
274void QgsAnnotationMarkerItemWidget::setContext( const QgsSymbolWidgetContext &context )
275{
277 if ( mSelector )
278 mSelector->setContext( context );
279 mPropertiesWidget->setContext( context );
280}
281
282QgsAnnotationMarkerItemWidget::~QgsAnnotationMarkerItemWidget() = default;
283
284bool QgsAnnotationMarkerItemWidget::setNewItem( QgsAnnotationItem *item )
285{
286 QgsAnnotationMarkerItem *markerItem = dynamic_cast<QgsAnnotationMarkerItem *>( item );
287 if ( !markerItem )
288 return false;
289
290 mItem.reset( markerItem->clone() );
291 if ( mItem->symbol() )
292 {
293 mSymbol.reset( mItem->symbol()->clone() );
294 }
295 else
296 {
297 mSymbol = QgsMarkerSymbol::createSimple( {} );
298 }
299 mBlockChangedSignal = true;
300 mSelector->loadSymbol( mSymbol.get() );
301 mSelector->updatePreview();
302 mPropertiesWidget->setItem( mItem.get() );
303 mBlockChangedSignal = false;
304
305 return true;
306}
307
308
309//
310// QgsAnnotationPointTextItemWidget
311//
312
313QgsAnnotationPointTextItemWidget::QgsAnnotationPointTextItemWidget( QWidget *parent )
315{
316 setupUi( this );
317
318 mTextEdit->setMode( QgsRichTextEditor::Mode::QgsTextRenderer );
319
320 mTextFormatButton->setMode( QgsFontButton::ModeTextRenderer );
321
322 mSpinTextAngle->setClearValue( 0 );
323
324 mRotationModeCombo->addItem( tr( "Ignore Map Rotation" ), QVariant::fromValue( Qgis::SymbolRotationMode::IgnoreMapRotation ) );
325 mRotationModeCombo->addItem( tr( "Rotate With Map" ), QVariant::fromValue( Qgis::SymbolRotationMode::RespectMapRotation ) );
326
327 mAlignmentComboBox->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight );
328
329 connect( mTextFormatButton, &QgsFontButton::changed, this, [this] {
330 mTextEdit->setMode(
331 mTextFormatButton->textFormat().allowHtmlFormatting() ? QgsRichTextEditor::Mode::QgsTextRenderer : QgsRichTextEditor::Mode::PlainText
332 );
333
334 if ( !mBlockChangedSignal )
335 emit itemChanged();
336 } );
337 connect( mTextEdit, &QgsRichTextEditor::textChanged, this, [this] {
338 if ( !mBlockChangedSignal )
339 emit itemChanged();
340 } );
341 connect( mInsertExpressionButton, &QPushButton::clicked, this, &QgsAnnotationPointTextItemWidget::mInsertExpressionButton_clicked );
342 connect( mPropertiesWidget, &QgsAnnotationItemCommonPropertiesWidget::itemChanged, this, [this] {
343 if ( !mBlockChangedSignal )
344 emit itemChanged();
345 } );
346
347 connect( mSpinTextAngle, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, [this] {
348 if ( !mBlockChangedSignal )
349 emit itemChanged();
350 } );
351
352 connect( mRotationModeCombo, qOverload<int>( &QComboBox::currentIndexChanged ), this, [this] {
353 if ( !mBlockChangedSignal )
354 emit itemChanged();
355 } );
356
357 connect( mAlignmentComboBox, &QgsAlignmentComboBox::changed, this, [this] {
358 if ( !mBlockChangedSignal )
359 emit itemChanged();
360 } );
361}
362
363QgsAnnotationItem *QgsAnnotationPointTextItemWidget::createItem()
364{
365 QgsAnnotationPointTextItem *newItem = mItem->clone();
366 updateItem( newItem );
367 return newItem;
368}
369
370void QgsAnnotationPointTextItemWidget::updateItem( QgsAnnotationItem *item )
371{
372 if ( QgsAnnotationPointTextItem *pointTextItem = dynamic_cast<QgsAnnotationPointTextItem *>( item ) )
373 {
374 mBlockChangedSignal = true;
375 pointTextItem->setFormat( mTextFormatButton->textFormat() );
376 pointTextItem->setText( mTextFormatButton->textFormat().allowHtmlFormatting() ? mTextEdit->toHtml() : mTextEdit->toPlainText() );
377 pointTextItem->setAngle( mSpinTextAngle->value() );
378 pointTextItem->setRotationMode( mRotationModeCombo->currentData().value<Qgis::SymbolRotationMode>() );
379 pointTextItem->setAlignment( mAlignmentComboBox->currentAlignment() );
380 mBlockChangedSignal = false;
381 mPropertiesWidget->updateItem( pointTextItem );
382 }
383}
384
385void QgsAnnotationPointTextItemWidget::setContext( const QgsSymbolWidgetContext &context )
386{
388 if ( mTextFormatButton )
389 {
390 mTextFormatButton->setMapCanvas( context.mapCanvas() );
391 mTextFormatButton->setMessageBar( context.messageBar() );
392 }
393 mPropertiesWidget->setContext( context );
394}
395
396void QgsAnnotationPointTextItemWidget::focusDefaultWidget()
397{
398 mTextEdit->textEdit()->selectAll();
399 mTextEdit->setFocus();
400}
401
402QgsAnnotationPointTextItemWidget::~QgsAnnotationPointTextItemWidget() = default;
403
404bool QgsAnnotationPointTextItemWidget::setNewItem( QgsAnnotationItem *item )
405{
406 QgsAnnotationPointTextItem *textItem = dynamic_cast<QgsAnnotationPointTextItem *>( item );
407 if ( !textItem )
408 return false;
409
410 mItem.reset( textItem->clone() );
411
412 mBlockChangedSignal = true;
413 mTextFormatButton->setTextFormat( mItem->format() );
414 mTextEdit->setMode( mItem->format().allowHtmlFormatting() ? QgsRichTextEditor::Mode::QgsTextRenderer : QgsRichTextEditor::Mode::PlainText );
415 mTextEdit->setText( mItem->text() );
416 mSpinTextAngle->setValue( mItem->angle() );
417 mRotationModeCombo->setCurrentIndex( mRotationModeCombo->findData( QVariant::fromValue( mItem->rotationMode() ) ) );
418 mAlignmentComboBox->setCurrentAlignment( mItem->alignment() & Qt::AlignHorizontal_Mask );
419 mPropertiesWidget->setItem( mItem.get() );
420 mBlockChangedSignal = false;
421
422 return true;
423}
424
425void QgsAnnotationPointTextItemWidget::mInsertExpressionButton_clicked()
426{
427 QString expression = QgsExpressionFinder::findAndSelectActiveExpression( mTextEdit->textEdit() );
428
429 QgsExpressionContext expressionContext;
430 if ( context().expressionContext() )
431 expressionContext = *( context().expressionContext() );
432 else
433 expressionContext = QgsProject::instance()->createExpressionContext();
434
435 QgsExpressionBuilderDialog exprDlg( nullptr, expression, this, QStringLiteral( "generic" ), expressionContext );
436
437 exprDlg.setWindowTitle( tr( "Insert Expression" ) );
438 if ( exprDlg.exec() == QDialog::Accepted )
439 {
440 expression = exprDlg.expressionText().trimmed();
441 if ( !expression.isEmpty() )
442 {
443 mTextEdit->textEdit()->insertPlainText( "[%" + expression + "%]" );
444 }
445 }
446}
447
448
449//
450// QgsAnnotationLineTextItemWidget
451//
452
453QgsAnnotationLineTextItemWidget::QgsAnnotationLineTextItemWidget( QWidget *parent )
455{
456 setupUi( this );
457
458 mTextFormatButton->setMode( QgsFontButton::ModeTextRenderer );
459
460 mTextEdit->setMode( QgsRichTextEditor::Mode::QgsTextRenderer );
461
462 connect( mTextFormatButton, &QgsFontButton::changed, this, [this] {
463 mTextEdit->setMode(
464 mTextFormatButton->textFormat().allowHtmlFormatting() ? QgsRichTextEditor::Mode::QgsTextRenderer : QgsRichTextEditor::Mode::PlainText
465 );
466
467 if ( !mBlockChangedSignal )
468 emit itemChanged();
469 } );
470 connect( mTextEdit, &QgsRichTextEditor::textChanged, this, [this] {
471 if ( !mBlockChangedSignal )
472 emit itemChanged();
473 } );
474 connect( mInsertExpressionButton, &QPushButton::clicked, this, &QgsAnnotationLineTextItemWidget::mInsertExpressionButton_clicked );
475 connect( mPropertiesWidget, &QgsAnnotationItemCommonPropertiesWidget::itemChanged, this, [this] {
476 if ( !mBlockChangedSignal )
477 emit itemChanged();
478 } );
479
481 mSpinOffset->setClearValue( 0.0 );
482 connect( mSpinOffset, static_cast<void ( QDoubleSpinBox::* )( double )>( &QDoubleSpinBox::valueChanged ), this, [this] {
483 if ( !mBlockChangedSignal )
484 emit itemChanged();
485 } );
486
487 connect( mOffsetUnitWidget, &QgsUnitSelectionWidget::changed, this, [this] {
488 if ( !mBlockChangedSignal )
489 emit itemChanged();
490 } );
491}
492
493QgsAnnotationLineTextItemWidget::~QgsAnnotationLineTextItemWidget() = default;
494
495QgsAnnotationItem *QgsAnnotationLineTextItemWidget::createItem()
496{
497 QgsAnnotationLineTextItem *newItem = mItem->clone();
498 updateItem( newItem );
499 return newItem;
500}
501
502void QgsAnnotationLineTextItemWidget::updateItem( QgsAnnotationItem *item )
503{
504 if ( QgsAnnotationLineTextItem *lineTextItem = dynamic_cast<QgsAnnotationLineTextItem *>( item ) )
505 {
506 mBlockChangedSignal = true;
507 lineTextItem->setFormat( mTextFormatButton->textFormat() );
508 lineTextItem->setText( mTextFormatButton->textFormat().allowHtmlFormatting() ? mTextEdit->toHtml() : mTextEdit->toPlainText() );
509
510 lineTextItem->setOffsetFromLine( mSpinOffset->value() );
511 lineTextItem->setOffsetFromLineUnit( mOffsetUnitWidget->unit() );
512 lineTextItem->setOffsetFromLineMapUnitScale( mOffsetUnitWidget->getMapUnitScale() );
513
514 mBlockChangedSignal = false;
515 mPropertiesWidget->updateItem( lineTextItem );
516 }
517}
518
519void QgsAnnotationLineTextItemWidget::setContext( const QgsSymbolWidgetContext &context )
520{
522 if ( mTextFormatButton )
523 {
524 mTextFormatButton->setMapCanvas( context.mapCanvas() );
525 mTextFormatButton->setMessageBar( context.messageBar() );
526 }
527 mPropertiesWidget->setContext( context );
528}
529
530void QgsAnnotationLineTextItemWidget::focusDefaultWidget()
531{
532 mTextEdit->textEdit()->selectAll();
533 mTextEdit->setFocus();
534}
535
536bool QgsAnnotationLineTextItemWidget::setNewItem( QgsAnnotationItem *item )
537{
538 QgsAnnotationLineTextItem *textItem = dynamic_cast<QgsAnnotationLineTextItem *>( item );
539 if ( !textItem )
540 return false;
541
542 mItem.reset( textItem->clone() );
543
544 mBlockChangedSignal = true;
545 mTextFormatButton->setTextFormat( mItem->format() );
546 mTextEdit->setMode( mItem->format().allowHtmlFormatting() ? QgsRichTextEditor::Mode::QgsTextRenderer : QgsRichTextEditor::Mode::PlainText );
547 mTextEdit->setText( mItem->text() );
548 mPropertiesWidget->setItem( mItem.get() );
549
550 mSpinOffset->setValue( mItem->offsetFromLine() );
551 mOffsetUnitWidget->setUnit( mItem->offsetFromLineUnit() );
552 mOffsetUnitWidget->setMapUnitScale( mItem->offsetFromLineMapUnitScale() );
553
554 mBlockChangedSignal = false;
555
556 return true;
557}
558
559void QgsAnnotationLineTextItemWidget::mInsertExpressionButton_clicked()
560{
561 QString expression = QgsExpressionFinder::findAndSelectActiveExpression( mTextEdit->textEdit() );
562
563 QgsExpressionContext expressionContext;
564 if ( context().expressionContext() )
565 expressionContext = *( context().expressionContext() );
566 else
567 expressionContext = QgsProject::instance()->createExpressionContext();
568
569 QgsExpressionBuilderDialog exprDlg( nullptr, expression, this, QStringLiteral( "generic" ), expressionContext );
570
571 exprDlg.setWindowTitle( tr( "Insert Expression" ) );
572 if ( exprDlg.exec() == QDialog::Accepted )
573 {
574 expression = exprDlg.expressionText().trimmed();
575 if ( !expression.isEmpty() )
576 {
577 mTextEdit->textEdit()->insertPlainText( "[%" + expression + "%]" );
578 }
579 }
580}
581
582
583//
584// QgsAnnotationRectangleTextItemWidget
585//
586
587QgsAnnotationRectangleTextItemWidget::QgsAnnotationRectangleTextItemWidget( QWidget *parent )
589{
590 setupUi( this );
591
592 mSizeModeCombo->addItem( tr( "Scale Dependent Size" ), QVariant::fromValue( Qgis::AnnotationPlacementMode::SpatialBounds ) );
593 mSizeModeCombo->addItem( tr( "Fixed Size" ), QVariant::fromValue( Qgis::AnnotationPlacementMode::FixedSize ) );
594 mSizeModeCombo->addItem( tr( "Relative to Map" ), QVariant::fromValue( Qgis::AnnotationPlacementMode::RelativeToMapFrame ) );
595
597
598 mBackgroundSymbolButton->setSymbolType( Qgis::SymbolType::Fill );
599 mBackgroundSymbolButton->setDialogTitle( tr( "Background" ) );
600 mBackgroundSymbolButton->registerExpressionContextGenerator( this );
601 mFrameSymbolButton->setSymbolType( Qgis::SymbolType::Fill );
602 mFrameSymbolButton->setDialogTitle( tr( "Frame" ) );
603 mFrameSymbolButton->registerExpressionContextGenerator( this );
604
605 mSpinBottomMargin->setClearValue( 0 );
606 mSpinTopMargin->setClearValue( 0 );
607 mSpinRightMargin->setClearValue( 0 );
608 mSpinLeftMargin->setClearValue( 0 );
610
611 mTextFormatButton->setMode( QgsFontButton::ModeTextRenderer );
612
613 mTextEdit->setMode( QgsRichTextEditor::Mode::QgsTextRenderer );
614
615 mAlignmentComboBox->setAvailableAlignments( Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight | Qt::AlignJustify );
616 mVerticalAlignmentComboBox->setAvailableAlignments( Qt::AlignTop | Qt::AlignVCenter | Qt::AlignBottom );
617
618 connect( mTextFormatButton, &QgsFontButton::changed, this, [this] {
619 mTextEdit->setMode(
620 mTextFormatButton->textFormat().allowHtmlFormatting() ? QgsRichTextEditor::Mode::QgsTextRenderer : QgsRichTextEditor::Mode::PlainText
621 );
622
623 onWidgetChanged();
624 } );
625 connect( mTextEdit, &QgsRichTextEditor::textChanged, this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
626 connect( mInsertExpressionButton, &QPushButton::clicked, this, &QgsAnnotationRectangleTextItemWidget::mInsertExpressionButton_clicked );
627 connect( mPropertiesWidget, &QgsAnnotationItemCommonPropertiesWidget::itemChanged, this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
628 connect( mAlignmentComboBox, &QgsAlignmentComboBox::changed, this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
629 connect( mVerticalAlignmentComboBox, &QgsAlignmentComboBox::changed, this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
630 connect( mFrameCheckbox, &QGroupBox::toggled, this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
631 connect( mBackgroundCheckbox, &QGroupBox::toggled, this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
632 connect( mBackgroundSymbolButton, &QgsSymbolButton::changed, this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
633 connect( mFrameSymbolButton, &QgsSymbolButton::changed, this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
634 connect( mSpinTopMargin, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
635 connect( mSpinRightMargin, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
636 connect( mSpinLeftMargin, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
637 connect( mSpinBottomMargin, qOverload<double>( &QgsDoubleSpinBox::valueChanged ), this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
638 connect( mMarginUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
639
640 connect( mSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsAnnotationRectangleTextItemWidget::onWidgetChanged );
641
642 connect( mWidthSpinBox, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, &QgsAnnotationRectangleTextItemWidget::setWidth );
643 connect( mHeightSpinBox, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, &QgsAnnotationRectangleTextItemWidget::setHeight );
644
645 connect( mSizeModeCombo, qOverload<int>( &QComboBox::currentIndexChanged ), this, &QgsAnnotationRectangleTextItemWidget::sizeModeChanged );
646 mWidgetFixedSize->hide();
647 sizeModeChanged();
648}
649
650QgsAnnotationItem *QgsAnnotationRectangleTextItemWidget::createItem()
651{
652 QgsAnnotationRectangleTextItem *newItem = mItem->clone();
653 updateItem( newItem );
654 return newItem;
655}
656
657void QgsAnnotationRectangleTextItemWidget::updateItem( QgsAnnotationItem *item )
658{
659 if ( QgsAnnotationRectangleTextItem *rectTextItem = dynamic_cast<QgsAnnotationRectangleTextItem *>( item ) )
660 {
661 mBlockChangedSignal = true;
662 rectTextItem->setFormat( mTextFormatButton->textFormat() );
663 rectTextItem->setText( mTextFormatButton->textFormat().allowHtmlFormatting() ? mTextEdit->toHtml() : mTextEdit->toPlainText() );
664 rectTextItem->setAlignment( mAlignmentComboBox->currentAlignment() | mVerticalAlignmentComboBox->currentAlignment() );
665
666 rectTextItem->setPlacementMode( mSizeModeCombo->currentData().value<Qgis::AnnotationPlacementMode>() );
667
668 rectTextItem->setFixedSize( QSizeF( mWidthSpinBox->value(), mHeightSpinBox->value() ) );
669 rectTextItem->setFixedSizeUnit( mSizeUnitWidget->unit() );
670
671 rectTextItem->setBackgroundEnabled( mBackgroundCheckbox->isChecked() );
672 rectTextItem->setFrameEnabled( mFrameCheckbox->isChecked() );
673 rectTextItem->setBackgroundSymbol( mBackgroundSymbolButton->clonedSymbol<QgsFillSymbol>() );
674 rectTextItem->setFrameSymbol( mFrameSymbolButton->clonedSymbol<QgsFillSymbol>() );
675
676 rectTextItem->setMargins( QgsMargins( mSpinLeftMargin->value(), mSpinTopMargin->value(), mSpinRightMargin->value(), mSpinBottomMargin->value() ) );
677 rectTextItem->setMarginsUnit( mMarginUnitWidget->unit() );
678
679 if ( mUpdateItemPosition )
680 {
681 rectTextItem->setBounds( mItem->bounds() );
682 mUpdateItemPosition = false;
683 }
684
685 mBlockChangedSignal = false;
686
687 mPropertiesWidget->updateItem( rectTextItem );
688 }
689}
690
691void QgsAnnotationRectangleTextItemWidget::setContext( const QgsSymbolWidgetContext &context )
692{
694 if ( mTextFormatButton )
695 {
696 mTextFormatButton->setMapCanvas( context.mapCanvas() );
697 mTextFormatButton->setMessageBar( context.messageBar() );
698 }
699 mBackgroundSymbolButton->setMapCanvas( context.mapCanvas() );
700 mBackgroundSymbolButton->setMessageBar( context.messageBar() );
701 mFrameSymbolButton->setMapCanvas( context.mapCanvas() );
702 mFrameSymbolButton->setMessageBar( context.messageBar() );
703 mPropertiesWidget->setContext( context );
704}
705
706QgsExpressionContext QgsAnnotationRectangleTextItemWidget::createExpressionContext() const
707{
708 QgsExpressionContext expressionContext;
709 if ( context().expressionContext() )
710 expressionContext = *( context().expressionContext() );
711 else
712 expressionContext = QgsProject::instance()->createExpressionContext();
713 return expressionContext;
714}
715
716void QgsAnnotationRectangleTextItemWidget::focusDefaultWidget()
717{
718 mTextEdit->textEdit()->selectAll();
719 mTextEdit->setFocus();
720}
721
722QgsAnnotationRectangleTextItemWidget::~QgsAnnotationRectangleTextItemWidget() = default;
723
724bool QgsAnnotationRectangleTextItemWidget::setNewItem( QgsAnnotationItem *item )
725{
726 QgsAnnotationRectangleTextItem *textItem = dynamic_cast<QgsAnnotationRectangleTextItem *>( item );
727 if ( !textItem )
728 return false;
729
730 mItem.reset( textItem->clone() );
731
732 mBlockChangedSignal = true;
733 mTextFormatButton->setTextFormat( mItem->format() );
734 mTextEdit->setMode( mItem->format().allowHtmlFormatting() ? QgsRichTextEditor::Mode::QgsTextRenderer : QgsRichTextEditor::Mode::PlainText );
735 mTextEdit->setText( mItem->text() );
736 mAlignmentComboBox->setCurrentAlignment( mItem->alignment() & Qt::AlignHorizontal_Mask );
737 mVerticalAlignmentComboBox->setCurrentAlignment( mItem->alignment() & Qt::AlignVertical_Mask );
738 mPropertiesWidget->setItem( mItem.get() );
739
740 mBackgroundCheckbox->setChecked( textItem->backgroundEnabled() );
741 if ( const QgsSymbol *symbol = textItem->backgroundSymbol() )
742 mBackgroundSymbolButton->setSymbol( symbol->clone() );
743
744 mFrameCheckbox->setChecked( textItem->frameEnabled() );
745 if ( const QgsSymbol *symbol = textItem->frameSymbol() )
746 mFrameSymbolButton->setSymbol( symbol->clone() );
747
748 mMarginUnitWidget->setUnit( textItem->marginsUnit() );
749 mSpinLeftMargin->setValue( textItem->margins().left() );
750 mSpinTopMargin->setValue( textItem->margins().top() );
751 mSpinRightMargin->setValue( textItem->margins().right() );
752 mSpinBottomMargin->setValue( textItem->margins().bottom() );
753
754 mWidthSpinBox->setValue( textItem->fixedSize().width() );
755 mHeightSpinBox->setValue( textItem->fixedSize().height() );
756 mSizeUnitWidget->setUnit( textItem->fixedSizeUnit() );
757 mSizeModeCombo->setCurrentIndex( mSizeModeCombo->findData( QVariant::fromValue( textItem->placementMode() ) ) );
758
759 mBlockChangedSignal = false;
760
761 return true;
762}
763
764void QgsAnnotationRectangleTextItemWidget::onWidgetChanged()
765{
766 if ( !mBlockChangedSignal )
767 emit itemChanged();
768}
769
770void QgsAnnotationRectangleTextItemWidget::sizeModeChanged()
771{
772 const Qgis::AnnotationPlacementMode mode = mSizeModeCombo->currentData().value<Qgis::AnnotationPlacementMode>();
773 switch ( mode )
774 {
776 mWidgetFixedSize->hide();
777 break;
778
780 if ( const QgsRenderedAnnotationItemDetails *details = renderedItemDetails() )
781 {
782 const QgsRectangle itemBoundsMapUnits = details->boundingBox();
783 if ( QgsMapCanvas *canvas = context().mapCanvas() )
784 {
785 const QgsPointXY topLeftPixels = canvas->mapSettings().mapToPixel().transform( itemBoundsMapUnits.xMinimum(), itemBoundsMapUnits.yMinimum() );
786 const QgsPointXY bottomRightPixels = canvas->mapSettings().mapToPixel().transform( itemBoundsMapUnits.xMaximum(), itemBoundsMapUnits.yMaximum() );
787 const double widthPixels = std::abs( bottomRightPixels.x() - topLeftPixels.x() );
788 const double heightPixels = std::abs( bottomRightPixels.y() - topLeftPixels.y() );
789
790 // convert width/height in pixels to mm
791 const double pixelsPerMm = canvas->mapSettings().outputDpi() / 25.4;
792 mItem->setFixedSizeUnit( Qgis::RenderUnit::Millimeters );
793 mItem->setFixedSize( QSizeF( widthPixels / pixelsPerMm, heightPixels / pixelsPerMm ) );
794
795 // and update widget UI accordingly
796 whileBlocking( mWidthSpinBox )->setValue( mItem->fixedSize().width() );
797 whileBlocking( mHeightSpinBox )->setValue( mItem->fixedSize().height() );
798 whileBlocking( mSizeUnitWidget )->setUnit( mItem->fixedSizeUnit() );
799
800 mUpdateItemPosition = true;
801 }
802 }
803
804 mWidgetFixedSize->show();
805 break;
806
808 {
809 if ( const QgsRenderedAnnotationItemDetails *details = renderedItemDetails() )
810 {
811 // convert item bounds to relative position
812 const QgsRectangle itemBounds = details->boundingBox();
813 if ( QgsMapCanvas *canvas = context().mapCanvas() )
814 {
815 const double centerX = ( itemBounds.center().x() - canvas->extent().xMinimum() ) / canvas->extent().width();
816 const double centerY = ( canvas->extent().yMaximum() - itemBounds.center().y() ) / canvas->extent().height();
817 mItem->setBounds( QgsRectangle::fromCenterAndSize( QgsPointXY( centerX, centerY ), 0.5, 0.5 ) );
818 mUpdateItemPosition = true;
819 }
820 }
821
822 mWidgetFixedSize->hide();
823 break;
824 }
825 }
826
827 onWidgetChanged();
828}
829
830void QgsAnnotationRectangleTextItemWidget::setWidth()
831{
832 onWidgetChanged();
833}
834
835void QgsAnnotationRectangleTextItemWidget::setHeight()
836{
837 onWidgetChanged();
838}
839
840void QgsAnnotationRectangleTextItemWidget::mInsertExpressionButton_clicked()
841{
842 QString expression = QgsExpressionFinder::findAndSelectActiveExpression( mTextEdit->textEdit() );
843
844 QgsExpressionBuilderDialog exprDlg( nullptr, expression, this, QStringLiteral( "generic" ), createExpressionContext() );
845
846 exprDlg.setWindowTitle( tr( "Insert Expression" ) );
847 if ( exprDlg.exec() == QDialog::Accepted )
848 {
849 expression = exprDlg.expressionText().trimmed();
850 if ( !expression.isEmpty() )
851 {
852 mTextEdit->textEdit()->insertPlainText( "[%" + expression + "%]" );
853 }
854 }
855}
856
857
858//
859// QgsAnnotationPictureItemWidget
860//
861
862QgsAnnotationPictureItemWidget::QgsAnnotationPictureItemWidget( QWidget *parent )
864{
865 setupUi( this );
866
867 mSizeStackedWidget->setSizeMode( QgsStackedWidget::SizeMode::CurrentPageOnly );
868
869 mSizeModeCombo->addItem( tr( "Scale Dependent Size" ), QVariant::fromValue( Qgis::AnnotationPlacementMode::SpatialBounds ) );
870 mSizeModeCombo->addItem( tr( "Fixed Size" ), QVariant::fromValue( Qgis::AnnotationPlacementMode::FixedSize ) );
871 mSizeModeCombo->addItem( tr( "Relative to Map" ), QVariant::fromValue( Qgis::AnnotationPlacementMode::RelativeToMapFrame ) );
872
874
875 mBackgroundSymbolButton->setSymbolType( Qgis::SymbolType::Fill );
876 mBackgroundSymbolButton->setDialogTitle( tr( "Background" ) );
877 mBackgroundSymbolButton->registerExpressionContextGenerator( this );
878 mFrameSymbolButton->setSymbolType( Qgis::SymbolType::Fill );
879 mFrameSymbolButton->setDialogTitle( tr( "Frame" ) );
880 mFrameSymbolButton->registerExpressionContextGenerator( this );
881
882 connect( mPropertiesWidget, &QgsAnnotationItemCommonPropertiesWidget::itemChanged, this, [this] {
883 if ( !mBlockChangedSignal )
884 emit itemChanged();
885 } );
886
887 connect( mSizeModeCombo, qOverload<int>( &QComboBox::currentIndexChanged ), this, &QgsAnnotationPictureItemWidget::sizeModeChanged );
888
889 connect( mRadioSVG, &QRadioButton::toggled, this, &QgsAnnotationPictureItemWidget::modeChanged );
890 connect( mRadioRaster, &QRadioButton::toggled, this, &QgsAnnotationPictureItemWidget::modeChanged );
891 connect( mSourceLineEdit, &QgsPictureSourceLineEditBase::sourceChanged, this, [this]( const QString &source ) {
892 if ( !mRadioSVG->isChecked() && QFileInfo( source ).suffix().compare( QLatin1String( "svg" ), Qt::CaseInsensitive ) == 0 )
893 {
894 mRadioSVG->setChecked( true );
895 }
896
897 onWidgetChanged();
898 } );
899
900 connect( mLockAspectRatioCheck, &QCheckBox::toggled, this, &QgsAnnotationPictureItemWidget::onWidgetChanged );
901 connect( mFrameCheckbox, &QGroupBox::toggled, this, &QgsAnnotationPictureItemWidget::onWidgetChanged );
902 connect( mBackgroundCheckbox, &QGroupBox::toggled, this, &QgsAnnotationPictureItemWidget::onWidgetChanged );
903 connect( mBackgroundSymbolButton, &QgsSymbolButton::changed, this, &QgsAnnotationPictureItemWidget::onWidgetChanged );
904 connect( mFrameSymbolButton, &QgsSymbolButton::changed, this, &QgsAnnotationPictureItemWidget::onWidgetChanged );
905 connect( mSizeUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsAnnotationPictureItemWidget::onWidgetChanged );
906
907 connect( mWidthSpinBox, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, &QgsAnnotationPictureItemWidget::setWidth );
908 connect( mHeightSpinBox, qOverload<double>( &QDoubleSpinBox::valueChanged ), this, &QgsAnnotationPictureItemWidget::setHeight );
909 connect( mLockAspectRatio, &QgsRatioLockButton::lockChanged, this, &QgsAnnotationPictureItemWidget::setLockAspectRatio );
910}
911
912QgsAnnotationPictureItemWidget::~QgsAnnotationPictureItemWidget() = default;
913
914QgsAnnotationItem *QgsAnnotationPictureItemWidget::createItem()
915{
916 QgsAnnotationPictureItem *newItem = mItem->clone();
917 updateItem( newItem );
918 return newItem;
919}
920
921void QgsAnnotationPictureItemWidget::updateItem( QgsAnnotationItem *item )
922{
923 if ( QgsAnnotationPictureItem *pictureItem = dynamic_cast<QgsAnnotationPictureItem *>( item ) )
924 {
925 const bool svg = mRadioSVG->isChecked();
927 const QString path = mSourceLineEdit->source();
928 pictureItem->setPath( newFormat, path );
929
930 pictureItem->setPlacementMode( mSizeModeCombo->currentData().value<Qgis::AnnotationPlacementMode>() );
931 switch ( pictureItem->placementMode() )
932 {
934 pictureItem->setLockAspectRatio( mLockAspectRatioCheck->isChecked() );
935 break;
938 pictureItem->setLockAspectRatio( mLockAspectRatio->isChecked() );
939 break;
940 }
941
942 pictureItem->setFixedSize( QSizeF( mWidthSpinBox->value(), mHeightSpinBox->value() ) );
943 pictureItem->setFixedSizeUnit( mSizeUnitWidget->unit() );
944
945 pictureItem->setBackgroundEnabled( mBackgroundCheckbox->isChecked() );
946 pictureItem->setFrameEnabled( mFrameCheckbox->isChecked() );
947 pictureItem->setBackgroundSymbol( mBackgroundSymbolButton->clonedSymbol<QgsFillSymbol>() );
948 pictureItem->setFrameSymbol( mFrameSymbolButton->clonedSymbol<QgsFillSymbol>() );
949
950 if ( mUpdateItemPosition )
951 {
952 pictureItem->setBounds( mItem->bounds() );
953 mUpdateItemPosition = false;
954 }
955
956 mPropertiesWidget->updateItem( pictureItem );
957 }
958}
959
960void QgsAnnotationPictureItemWidget::setDockMode( bool dockMode )
961{
963}
964
965void QgsAnnotationPictureItemWidget::setContext( const QgsSymbolWidgetContext &context )
966{
968 mPropertiesWidget->setContext( context );
969 mBackgroundSymbolButton->setMapCanvas( context.mapCanvas() );
970 mBackgroundSymbolButton->setMessageBar( context.messageBar() );
971 mFrameSymbolButton->setMapCanvas( context.mapCanvas() );
972 mFrameSymbolButton->setMessageBar( context.messageBar() );
973}
974
975QgsExpressionContext QgsAnnotationPictureItemWidget::createExpressionContext() const
976{
977 QgsExpressionContext expressionContext;
978 if ( context().expressionContext() )
979 expressionContext = *( context().expressionContext() );
980 else
981 expressionContext = QgsProject::instance()->createExpressionContext();
982 return expressionContext;
983}
984
985void QgsAnnotationPictureItemWidget::focusDefaultWidget()
986{
987 mSourceLineEdit->setFocus();
988}
989
990bool QgsAnnotationPictureItemWidget::setNewItem( QgsAnnotationItem *item )
991{
992 QgsAnnotationPictureItem *pictureItem = dynamic_cast<QgsAnnotationPictureItem *>( item );
993 if ( !pictureItem )
994 return false;
995
996 mItem.reset( pictureItem->clone() );
997
998 mBlockChangedSignal = true;
999 mPropertiesWidget->setItem( mItem.get() );
1000
1001 mLockAspectRatioCheck->setChecked( mItem->lockAspectRatio() );
1002 mLockAspectRatio->setLocked( mItem->lockAspectRatio() );
1003 switch ( pictureItem->format() )
1004 {
1006 mRadioSVG->setChecked( true );
1007 break;
1009 mRadioRaster->setChecked( true );
1010 break;
1012 break;
1013 }
1014
1015 mSourceLineEdit->setSource( pictureItem->path() );
1016
1017 mBackgroundCheckbox->setChecked( pictureItem->backgroundEnabled() );
1018 if ( const QgsSymbol *symbol = pictureItem->backgroundSymbol() )
1019 mBackgroundSymbolButton->setSymbol( symbol->clone() );
1020
1021 mFrameCheckbox->setChecked( pictureItem->frameEnabled() );
1022 if ( const QgsSymbol *symbol = pictureItem->frameSymbol() )
1023 mFrameSymbolButton->setSymbol( symbol->clone() );
1024
1025 mWidthSpinBox->setValue( pictureItem->fixedSize().width() );
1026 mHeightSpinBox->setValue( pictureItem->fixedSize().height() );
1027 mSizeModeCombo->setCurrentIndex( mSizeModeCombo->findData( QVariant::fromValue( pictureItem->placementMode() ) ) );
1028 sizeModeChanged();
1029
1030 mBlockChangedSignal = false;
1031
1032 return true;
1033}
1034
1035void QgsAnnotationPictureItemWidget::onWidgetChanged()
1036{
1037 if ( !mBlockChangedSignal )
1038 emit itemChanged();
1039}
1040
1041void QgsAnnotationPictureItemWidget::modeChanged( bool checked )
1042{
1043 if ( !checked )
1044 return;
1045
1046 const bool svg = mRadioSVG->isChecked();
1047
1048 if ( svg )
1049 mSourceLineEdit->setMode( QgsPictureSourceLineEditBase::Svg );
1050 else
1051 mSourceLineEdit->setMode( QgsPictureSourceLineEditBase::Image );
1052
1053 onWidgetChanged();
1054}
1055
1056void QgsAnnotationPictureItemWidget::sizeModeChanged()
1057{
1058 const Qgis::AnnotationPlacementMode mode = mSizeModeCombo->currentData().value<Qgis::AnnotationPlacementMode>();
1059 switch ( mode )
1060 {
1062 mSizeStackedWidget->setCurrentWidget( mPageSpatialBounds );
1063 break;
1064
1066 mSizeStackedWidget->setCurrentWidget( mPageFixedSize );
1067 break;
1068
1070 {
1071 if ( const QgsRenderedAnnotationItemDetails *details = renderedItemDetails() )
1072 {
1073 // convert item bounds to relative position
1074 const QgsRectangle itemBounds = details->boundingBox();
1075 if ( QgsMapCanvas *canvas = context().mapCanvas() )
1076 {
1077 const double centerX = ( itemBounds.center().x() - canvas->extent().xMinimum() ) / canvas->extent().width();
1078 const double centerY = ( canvas->extent().yMaximum() - itemBounds.center().y() ) / canvas->extent().height();
1079 mItem->setBounds( QgsRectangle::fromCenterAndSize( QgsPointXY( centerX, centerY ), 0.5, 0.5 ) );
1080 mUpdateItemPosition = true;
1081 }
1082 }
1083
1084 mSizeStackedWidget->setCurrentWidget( mPageFixedSize );
1085 break;
1086 }
1087 }
1088
1089 onWidgetChanged();
1090}
1091
1092void QgsAnnotationPictureItemWidget::setWidth()
1093{
1094 if ( mLockAspectRatio->locked() )
1095 {
1096 const double ratio = pictureAspectRatio();
1097 if ( ratio > 0 )
1098 whileBlocking( mHeightSpinBox )->setValue( mWidthSpinBox->value() * ratio );
1099 }
1100
1101 onWidgetChanged();
1102}
1103
1104void QgsAnnotationPictureItemWidget::setHeight()
1105{
1106 if ( mLockAspectRatio->locked() )
1107 {
1108 const double ratio = pictureAspectRatio();
1109 if ( ratio > 0 )
1110 whileBlocking( mWidthSpinBox )->setValue( mHeightSpinBox->value() / ratio );
1111 }
1112
1113 onWidgetChanged();
1114}
1115
1116void QgsAnnotationPictureItemWidget::setLockAspectRatio( bool locked )
1117{
1118 if ( locked && !mBlockChangedSignal )
1119 {
1120 const double ratio = pictureAspectRatio();
1121 if ( ratio > 0 )
1122 whileBlocking( mHeightSpinBox )->setValue( mWidthSpinBox->value() * ratio );
1123 }
1124
1125 onWidgetChanged();
1126}
1127
1128double QgsAnnotationPictureItemWidget::pictureAspectRatio() const
1129{
1130 const bool svg = mRadioSVG->isChecked();
1131 const QString path = mSourceLineEdit->source();
1132 QSizeF size;
1133 if ( svg )
1134 {
1135 size = QgsApplication::svgCache()->svgViewboxSize( path, 100, QColor(), QColor(), 1, 1 );
1136 }
1137 else
1138 {
1139 size = QgsApplication::imageCache()->originalSize( path );
1140 }
1141 if ( size.isValid() && size.width() > 0 )
1142 return size.height() / size.width();
1143
1144 return 0;
1145}
1146
SymbolRotationMode
Modes for handling how symbol and text entity rotation is handled when maps are rotated.
Definition qgis.h:786
@ RespectMapRotation
Entity is rotated along with the map.
Definition qgis.h:787
@ IgnoreMapRotation
Entity ignores map rotation.
Definition qgis.h:788
PictureFormat
Picture formats.
Definition qgis.h:5272
@ Raster
Raster image.
Definition qgis.h:5274
@ Unknown
Invalid or unknown image type.
Definition qgis.h:5275
@ SVG
SVG image.
Definition qgis.h:5273
@ Percentage
Percentage of another measurement (e.g., canvas size, feature size).
Definition qgis.h:5187
@ Millimeters
Millimeters.
Definition qgis.h:5184
@ Points
Points (e.g., for font sizes).
Definition qgis.h:5188
@ MapUnits
Map units.
Definition qgis.h:5185
@ Pixels
Pixels.
Definition qgis.h:5186
@ Inches
Inches.
Definition qgis.h:5189
@ MetersInMapUnits
Meters value as Map units.
Definition qgis.h:5191
@ Fill
Fill symbol.
Definition qgis.h:613
AnnotationPlacementMode
Annotation item placement modes.
Definition qgis.h:2480
@ SpatialBounds
Item is rendered inside fixed spatial bounds, and size will depend on map scale.
Definition qgis.h:2481
@ FixedSize
Item is rendered at a fixed size, regardless of map scale. Item's location is georeferenced to a spat...
Definition qgis.h:2482
@ RelativeToMapFrame
Items size and placement is relative to the map's frame, and the item will always be rendered in the ...
Definition qgis.h:2483
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.
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.
An annotation item which renders a text string at a point location.
void setText(const QString &text)
Sets the text rendered by the item.
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.
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 std::unique_ptr< 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 std::unique_ptr< 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.
Defines the four margins of a rectangle.
Definition qgsmargins.h:38
double top() const
Returns the top margin.
Definition qgsmargins.h:78
double right() const
Returns the right margin.
Definition qgsmargins.h:84
double bottom() const
Returns the bottom margin.
Definition qgsmargins.h:90
double left() const
Returns the left margin.
Definition qgsmargins.h:72
static std::unique_ptr< 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.
Represents 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.
@ 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:147
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:6511