36#include <QRegularExpression>
38#include "moc_qgsextentwidget.cpp"
44 connect( mXMinLineEdit, &QLineEdit::textEdited,
this, &QgsExtentWidget::setOutputExtentFromLineEdit );
45 connect( mXMaxLineEdit, &QLineEdit::textEdited,
this, &QgsExtentWidget::setOutputExtentFromLineEdit );
46 connect( mYMinLineEdit, &QLineEdit::textEdited,
this, &QgsExtentWidget::setOutputExtentFromLineEdit );
47 connect( mYMaxLineEdit, &QLineEdit::textEdited,
this, &QgsExtentWidget::setOutputExtentFromLineEdit );
49 mCondensedRe = QRegularExpression( QStringLiteral(
"\\s*([\\d\\.\\-]+)\\s*,\\s*([\\d\\.\\-]+)\\s*,\\s*([\\d\\.\\-]+)\\s*,\\s*([\\d\\.\\-]+)\\s*(?:\\[(.*?)\\])?" ) );
50 mCondensedLineEdit->setValidator(
new QRegularExpressionValidator( mCondensedRe,
this ) );
51 mCondensedLineEdit->setShowClearButton(
false );
53 connect( mCondensedLineEdit, &QLineEdit::textEdited,
this, &QgsExtentWidget::setOutputExtentFromCondensedLineEdit );
55 mLayerMenu =
new QMenu( tr(
"Calculate from Layer" ),
this );
56 mButtonCalcFromLayer->setMenu( mLayerMenu );
57 connect( mLayerMenu, &QMenu::aboutToShow,
this, &QgsExtentWidget::layerMenuAboutToShow );
61 mLayoutMenu =
new QMenu( tr(
"Calculate from Layout Map" ),
this );
62 mButtonCalcFromLayout->setMenu( mLayoutMenu );
63 connect( mLayoutMenu, &QMenu::aboutToShow,
this, &QgsExtentWidget::layoutMenuAboutToShow );
65 mBookmarkMenu =
new QMenu( tr(
"Calculate from Bookmark" ),
this );
66 mButtonCalcFromBookmark->setMenu( mBookmarkMenu );
67 connect( mBookmarkMenu, &QMenu::aboutToShow,
this, &QgsExtentWidget::bookmarkMenuAboutToShow );
69 mMenu =
new QMenu(
this );
70 mUseCanvasExtentAction =
new QAction( tr(
"Use Current Map Canvas Extent" ),
this );
72 mUseCanvasExtentAction->setVisible(
false );
75 mUseCurrentExtentAction =
new QAction( tr(
"Use Current Layer/Default Extent" ),
this );
76 mUseCurrentExtentAction->setVisible(
false );
79 mDrawOnCanvasAction =
new QAction( tr(
"Draw on Map Canvas" ),
this );
80 mDrawOnCanvasAction->setVisible(
false );
83 mMenu->addMenu( mLayerMenu );
84 mMenu->addMenu( mLayoutMenu );
85 mMenu->addMenu( mBookmarkMenu );
86 mMenu->addSeparator();
87 mMenu->addAction( mUseCanvasExtentAction );
88 mMenu->addAction( mDrawOnCanvasAction );
89 mMenu->addAction( mUseCurrentExtentAction );
91 mCondensedToolButton->setMenu( mMenu );
92 mCondensedToolButton->setPopupMode( QToolButton::InstantPopup );
99 mOriginalExtentButton->setVisible(
false );
100 mButtonDrawOnCanvas->setVisible(
false );
101 mCurrentExtentButton->setVisible(
false );
110 mExpandedWidget->hide();
114 mCondensedFrame->hide();
118 setAcceptDrops(
true );
123 if ( mMapToolExtent )
137 mOriginalExtentButton->setVisible(
true );
146 mCurrentExtentButton->setVisible(
true );
147 mUseCurrentExtentAction->setVisible(
true );
152 mHasFixedOutputCrs =
true;
155 const bool prevExtentEnabled = mIsValid;
156 switch ( mExtentState )
195 if ( !prevExtentEnabled )
203 if ( !mHasFixedOutputCrs )
210 if ( mOutputCrs == srcCrs )
219 ct.setBallparkTransformsAreAppropriate(
true );
220 extent = ct.transformBoundingBox( r );
222 catch ( QgsCsException & )
231 switch ( mOutputCrs.mapUnits() )
288 mXMinLineEdit->setText( QLocale().toString( extent.
xMinimum(),
'f', decimals ) );
289 mXMaxLineEdit->setText( QLocale().toString( extent.
xMaximum(),
'f', decimals ) );
290 mYMinLineEdit->setText( QLocale().toString( extent.
yMinimum(),
'f', decimals ) );
291 mYMaxLineEdit->setText( QLocale().toString( extent.
yMaximum(),
'f', decimals ) );
293 QString condensed = QStringLiteral(
"%1,%2,%3,%4" ).arg( QString::number( extent.
xMinimum(),
'f', decimals ), QString::number( extent.
xMaximum(),
'f', decimals ), QString::number( extent.
yMinimum(),
'f', decimals ), QString::number( extent.
yMaximum(),
'f', decimals ) );
295 mCondensedLineEdit->setText( condensed );
297 mExtentState = state;
305void QgsExtentWidget::setOutputExtentFromLineEdit()
311void QgsExtentWidget::setOutputExtentFromCondensedLineEdit()
313 const QString text = mCondensedLineEdit->text();
314 if ( text.isEmpty() )
320 const QRegularExpressionMatch match = mCondensedRe.match( text );
321 if ( match.hasMatch() )
324 whileBlocking( mXMinLineEdit )->setText( QLocale().toString( match.captured( 1 ).toDouble(),
'f', 10 ) );
325 whileBlocking( mXMaxLineEdit )->setText( QLocale().toString( match.captured( 2 ).toDouble(),
'f', 10 ) );
326 whileBlocking( mYMinLineEdit )->setText( QLocale().toString( match.captured( 3 ).toDouble(),
'f', 10 ) );
327 whileBlocking( mYMaxLineEdit )->setText( QLocale().toString( match.captured( 4 ).toDouble(),
'f', 10 ) );
328 if ( !match.captured( 5 ).isEmpty() )
330 mOutputCrs = QgsCoordinateReferenceSystem( match.captured( 5 ) );
342 const bool prevWasNull = mIsValid;
357 return mExtentLayerName;
367 mCondensedLineEdit->setShowClearButton( allowed );
368 mCondensedLineEdit->setNullValue( notSetText );
371void QgsExtentWidget::setValid(
bool valid )
373 if ( valid == mIsValid )
380void QgsExtentWidget::layerMenuAboutToShow()
382 qDeleteAll( mLayerMenuActions );
383 mLayerMenuActions.clear();
385 for (
int i = 0; i < mMapLayerModel->rowCount(); ++i )
387 const QModelIndex index = mMapLayerModel->index( i, 0 );
388 const QIcon icon = qvariant_cast<QIcon>( mMapLayerModel->data( index, Qt::DecorationRole ) );
389 const QString text = mMapLayerModel->data( index, Qt::DisplayRole ).toString();
390 QAction *act =
new QAction( icon, text, mLayerMenu );
391 act->setToolTip( mMapLayerModel->data( index, Qt::ToolTipRole ).toString() );
393 if ( mExtentState ==
ProjectLayerExtent && mExtentLayer && mExtentLayer->id() == layerId )
395 act->setCheckable(
true );
396 act->setChecked(
true );
398 connect( act, &QAction::triggered,
this, [
this, layerId] {
399 setExtentToLayerExtent( layerId );
401 mLayerMenu->addAction( act );
402 mLayerMenuActions << act;
406void QgsExtentWidget::layoutMenuAboutToShow()
408 mLayoutMenu->clear();
412 const QList<QgsPrintLayout *> layouts = manager->printLayouts();
413 for (
const QgsPrintLayout *layout : layouts )
415 QList<QgsLayoutItemMap *> maps;
416 layout->layoutItems( maps );
420 QMenu *layoutMenu =
new QMenu( layout->name(), mMenu );
421 for (
const QgsLayoutItemMap *map : std::as_const( maps ) )
423 QgsRectangle extent = map->extent();
424 QgsCoordinateReferenceSystem crs = map->crs();
425 QAction *mapExtentAction =
new QAction( tr(
"%1" ).arg( map->displayName() ), mLayoutMenu );
426 connect( mapExtentAction, &QAction::triggered,
this, [
this, extent, crs] {
setOutputExtentFromUser( extent, crs ); } );
427 layoutMenu->addAction( mapExtentAction );
429 mLayoutMenu->addMenu( layoutMenu );
434void QgsExtentWidget::bookmarkMenuAboutToShow()
436 mBookmarkMenu->clear();
438 if ( !mBookmarkModel )
441 QMap<QString, QMenu *> groupMenus;
442 for (
int i = 0; i < mBookmarkModel->rowCount(); ++i )
445 QMenu *destMenu = mBookmarkMenu;
446 if ( !group.isEmpty() )
448 destMenu = groupMenus.value( group );
451 destMenu =
new QMenu( group, mBookmarkMenu );
452 groupMenus[group] = destMenu;
458 destMenu->addAction( action );
461 QStringList groupKeys = groupMenus.keys();
462 groupKeys.sort( Qt::CaseInsensitive );
463 for (
int i = 0; i < groupKeys.count(); ++i )
465 if ( mBookmarkMenu->actions().value( i ) )
466 mBookmarkMenu->insertMenu( mBookmarkMenu->actions().at( i ), groupMenus.value( groupKeys.at( i ) ) );
468 mBookmarkMenu->addMenu( groupMenus.value( groupKeys.at( i ) ) );
472void QgsExtentWidget::setExtentToLayerExtent(
const QString &layerId )
482QgsMapLayer *QgsExtentWidget::mapLayerFromMimeData(
const QMimeData *data )
const
485 for (
const QgsMimeDataUtils::Uri &u : uriList )
488 if ( QgsMapLayer *layer = u.mapLayer() )
507 setOutputExtent( mCurrentExtent, mCurrentCrs,
CurrentExtent );
527 mExtentLayer = layer;
528 mExtentLayerName = layer->
name();
537 mMapToolPrevious = mCanvas->mapTool();
538 if ( !mMapToolExtent )
540 mMapToolExtent = std::make_unique<QgsMapToolExtent>( mCanvas );
544 mMapToolExtent->setRatio( mRatio );
545 mCanvas->setMapTool( mMapToolExtent.get() );
551void QgsExtentWidget::extentDrawn(
const QgsRectangle &extent )
556 mMapToolPrevious =
nullptr;
559void QgsExtentWidget::mapToolDeactivated()
562 mMapToolPrevious =
nullptr;
589 mButtonDrawOnCanvas->setVisible( drawOnCanvasOption );
590 mCurrentExtentButton->setVisible(
true );
592 mUseCanvasExtentAction->setVisible(
true );
593 mDrawOnCanvasAction->setVisible( drawOnCanvasOption && !mBlockDrawOnCanvas );
595 mCondensedToolButton->setToolTip( tr(
"Set to current map canvas extent" ) );
598 mCondensedToolButton->setPopupMode( QToolButton::MenuButtonPopup );
602 mButtonDrawOnCanvas->setVisible(
false );
603 mCurrentExtentButton->setVisible(
false );
604 mUseCanvasExtentAction->setVisible(
false );
605 mUseCanvasExtentAction->setVisible(
false );
607 mCondensedToolButton->setToolTip( QString() );
608 mCondensedToolButton->setIcon( QIcon() );
610 mCondensedToolButton->setPopupMode( QToolButton::InstantPopup );
616 if ( !( event->possibleActions() & Qt::CopyAction ) )
622 if ( mapLayerFromMimeData( event->mimeData() ) )
625 event->setDropAction( Qt::CopyAction );
627 mCondensedLineEdit->setHighlighted(
true );
638 if ( mCondensedLineEdit->isHighlighted() )
641 mCondensedLineEdit->setHighlighted(
false );
652 if ( !( event->possibleActions() & Qt::CopyAction ) )
658 if (
QgsMapLayer *layer = mapLayerFromMimeData( event->mimeData() ) )
661 setFocus( Qt::MouseFocusReason );
662 event->setDropAction( Qt::CopyAction );
671 mCondensedLineEdit->setHighlighted(
false );
680 if ( QWidget *parentWindow = window() )
682 if ( parentWindow->isModal() )
684 mBlockDrawOnCanvas =
true;
685 mDrawOnCanvasAction->setVisible(
false );
@ ShortString
A heavily abbreviated string, for use when a compact representation is required.
@ YardsBritishSears1922Truncated
British yards (Sears 1922 truncated).
@ MilesUSSurvey
US Survey miles.
@ LinksBritishSears1922
British links (Sears 1922).
@ YardsBritishBenoit1895A
British yards (Benoit 1895 A).
@ LinksBritishBenoit1895A
British links (Benoit 1895 A).
@ Centimeters
Centimeters.
@ YardsIndian1975
Indian yards (1975).
@ FeetUSSurvey
US Survey feet.
@ Millimeters
Millimeters.
@ FeetBritishSears1922
British feet (Sears 1922).
@ YardsClarkes
Clarke's yards.
@ YardsIndian
Indian yards.
@ FeetBritishBenoit1895B
British feet (Benoit 1895 B).
@ Miles
Terrestrial miles.
@ LinksUSSurvey
US Survey links.
@ ChainsUSSurvey
US Survey chains.
@ FeetClarkes
Clarke's feet.
@ Unknown
Unknown distance unit.
@ FeetBritish1936
British feet (1936).
@ FeetIndian1962
Indian feet (1962).
@ YardsBritishSears1922
British yards (Sears 1922).
@ FeetIndian1937
Indian feet (1937).
@ YardsIndian1937
Indian yards (1937).
@ Degrees
Degrees, for planar geographic CRS distance measurements.
@ ChainsBritishBenoit1895B
British chains (Benoit 1895 B).
@ LinksBritishSears1922Truncated
British links (Sears 1922 truncated).
@ ChainsBritishBenoit1895A
British chains (Benoit 1895 A).
@ YardsBritishBenoit1895B
British yards (Benoit 1895 B).
@ FeetBritish1865
British feet (1865).
@ YardsIndian1962
Indian yards (1962).
@ FeetBritishSears1922Truncated
British feet (Sears 1922 truncated).
@ MetersGermanLegal
German legal meter.
@ LinksBritishBenoit1895B
British links (Benoit 1895 B).
@ ChainsInternational
International chains.
@ LinksInternational
International links.
@ ChainsBritishSears1922Truncated
British chains (Sears 1922 truncated).
@ FeetIndian
Indian (geodetic) feet.
@ NauticalMiles
Nautical miles.
@ ChainsClarkes
Clarke's chains.
@ LinksClarkes
Clarke's links.
@ ChainsBritishSears1922
British chains (Sears 1922).
@ FeetIndian1975
Indian feet (1975).
@ FeetGoldCoast
Gold Coast feet.
@ FeetBritishBenoit1895A
British feet (Benoit 1895 A).
@ SpatialLayer
All spatial layers.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
static QgsBookmarkManager * bookmarkManager()
Returns the application's bookmark manager, used for storing installation-wide bookmarks.
@ Extent
Bookmark extent as a QgsReferencedRectangle.
Represents a coordinate reference system (CRS).
Custom exception class for Coordinate Reference System related exceptions.
A custom validator which allows entry of doubles in a locale-tolerant way.
static double toDouble(const QString &input, bool *ok)
Converts input string to double value.
void cleared()
Emitted when the widget is cleared.
Map canvas is a class for displaying all GIS data types on a canvas.
void setMapTool(QgsMapTool *mapTool, bool clean=false)
Sets the map tool currently being used on the canvas.
const QgsMapSettings & mapSettings() const
Gets access to properties used for map rendering.
@ LayerId
Stores the map layer ID.
A proxy model which provides an easy to use model to display the list of layers in widgets.
Base class for all map layer types.
virtual QgsRectangle extent() const
Returns the extent of the layer.
QgsCoordinateReferenceSystem crs
Contains configuration for rendering maps.
QgsRectangle visibleExtent() const
Returns the actual extent derived from requested extent that takes output image size into account.
void setRotation(double rotation)
Sets the rotation of the resulting map image, in degrees clockwise.
QgsCoordinateReferenceSystem destinationCrs() const
Returns the destination coordinate reference system for the map render.
QList< QgsMimeDataUtils::Uri > UriList
static UriList decodeUriList(const QMimeData *data)
static QgsProject * instance()
Returns the QgsProject singleton instance.
Q_INVOKABLE QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
A rectangle specified with double values.
QgsCoordinateReferenceSystem crs() const
Returns the associated coordinate reference system, or an invalid CRS if no reference system is set.
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.