QGIS/src/gui/qgsextentgroupbox.cpp
Juergen E. Fischer 34553d3624 fix warning
2018-02-20 20:40:35 +01:00

363 lines
10 KiB
C++

/***************************************************************************
qgsextentgroupbox.cpp
---------------------
begin : March 2014
copyright : (C) 2014 by Martin Dobias
email : wonder dot sk at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsextentgroupbox.h"
#include "qgslogger.h"
#include "qgscoordinatetransform.h"
#include "qgsmapcanvas.h"
#include "qgsmaplayermodel.h"
#include "qgsexception.h"
#include "qgsproject.h"
#include <QMenu>
#include <QAction>
QgsExtentGroupBox::QgsExtentGroupBox( QWidget *parent )
: QgsCollapsibleGroupBox( parent )
, mTitleBase( tr( "Extent" ) )
{
setupUi( this );
connect( mXMinLineEdit, &QLineEdit::textEdited, this, &QgsExtentGroupBox::setOutputExtentFromLineEdit );
connect( mXMaxLineEdit, &QLineEdit::textEdited, this, &QgsExtentGroupBox::setOutputExtentFromLineEdit );
connect( mYMinLineEdit, &QLineEdit::textEdited, this, &QgsExtentGroupBox::setOutputExtentFromLineEdit );
connect( mYMaxLineEdit, &QLineEdit::textEdited, this, &QgsExtentGroupBox::setOutputExtentFromLineEdit );
mLayerMenu = new QMenu( this );
mButtonCalcFromLayer->setMenu( mLayerMenu );
connect( mLayerMenu, &QMenu::aboutToShow, this, &QgsExtentGroupBox::layerMenuAboutToShow );
mMapLayerModel = new QgsMapLayerModel( this );
mXMinLineEdit->setValidator( new QDoubleValidator( this ) );
mXMaxLineEdit->setValidator( new QDoubleValidator( this ) );
mYMinLineEdit->setValidator( new QDoubleValidator( this ) );
mYMaxLineEdit->setValidator( new QDoubleValidator( this ) );
mOriginalExtentButton->setVisible( false );
mButtonDrawOnCanvas->setVisible( false );
mCurrentExtentButton->setVisible( false );
connect( mCurrentExtentButton, &QAbstractButton::clicked, this, &QgsExtentGroupBox::setOutputExtentFromCurrent );
connect( mOriginalExtentButton, &QAbstractButton::clicked, this, &QgsExtentGroupBox::setOutputExtentFromOriginal );
connect( mButtonDrawOnCanvas, &QAbstractButton::clicked, this, &QgsExtentGroupBox::setOutputExtentFromDrawOnCanvas );
connect( this, &QGroupBox::clicked, this, &QgsExtentGroupBox::groupBoxClicked );
}
void QgsExtentGroupBox::setOriginalExtent( const QgsRectangle &originalExtent, const QgsCoordinateReferenceSystem &originalCrs )
{
mOriginalExtent = originalExtent;
mOriginalCrs = originalCrs;
mOriginalExtentButton->setVisible( true );
}
void QgsExtentGroupBox::setCurrentExtent( const QgsRectangle &currentExtent, const QgsCoordinateReferenceSystem &currentCrs )
{
mCurrentExtent = currentExtent;
mCurrentCrs = currentCrs;
mCurrentExtentButton->setVisible( true );
}
void QgsExtentGroupBox::setOutputCrs( const QgsCoordinateReferenceSystem &outputCrs )
{
if ( mOutputCrs != outputCrs )
{
switch ( mExtentState )
{
case CurrentExtent:
mOutputCrs = outputCrs;
setOutputExtentFromCurrent();
break;
case OriginalExtent:
mOutputCrs = outputCrs;
setOutputExtentFromOriginal();
break;
case ProjectLayerExtent:
mOutputCrs = outputCrs;
setOutputExtentFromLayer( mExtentLayer.data() );
break;
case DrawOnCanvas:
mOutputCrs = outputCrs;
extentDrawn( outputExtent() );
break;
case UserExtent:
try
{
QgsCoordinateTransform ct( mOutputCrs, outputCrs, QgsProject::instance() );
QgsRectangle extent = ct.transformBoundingBox( outputExtent() );
mOutputCrs = outputCrs;
setOutputExtentFromUser( extent, outputCrs );
}
catch ( QgsCsException & )
{
// can't reproject
mOutputCrs = outputCrs;
}
break;
}
}
}
void QgsExtentGroupBox::setOutputExtent( const QgsRectangle &r, const QgsCoordinateReferenceSystem &srcCrs, ExtentState state )
{
QgsRectangle extent;
if ( mOutputCrs == srcCrs )
{
extent = r;
}
else
{
try
{
QgsCoordinateTransform ct( srcCrs, mOutputCrs, QgsProject::instance() );
extent = ct.transformBoundingBox( r );
}
catch ( QgsCsException & )
{
// can't reproject
extent = r;
}
}
int decimals = 4;
switch ( mOutputCrs.mapUnits() )
{
case QgsUnitTypes::DistanceDegrees:
case QgsUnitTypes::DistanceUnknownUnit:
decimals = 9;
break;
case QgsUnitTypes::DistanceMeters:
case QgsUnitTypes::DistanceKilometers:
case QgsUnitTypes::DistanceFeet:
case QgsUnitTypes::DistanceNauticalMiles:
case QgsUnitTypes::DistanceYards:
case QgsUnitTypes::DistanceMiles:
case QgsUnitTypes::DistanceCentimeters:
case QgsUnitTypes::DistanceMillimeters:
decimals = 4;
break;
}
mXMinLineEdit->setText( QString::number( extent.xMinimum(), 'f', decimals ) );
mXMaxLineEdit->setText( QString::number( extent.xMaximum(), 'f', decimals ) );
mYMinLineEdit->setText( QString::number( extent.yMinimum(), 'f', decimals ) );
mYMaxLineEdit->setText( QString::number( extent.yMaximum(), 'f', decimals ) );
mExtentState = state;
if ( isCheckable() && !isChecked() )
setChecked( true );
updateTitle();
emit extentChanged( extent );
}
void QgsExtentGroupBox::setOutputExtentFromLineEdit()
{
mExtentState = UserExtent;
updateTitle();
emit extentChanged( outputExtent() );
}
void QgsExtentGroupBox::updateTitle()
{
QString msg;
switch ( mExtentState )
{
case OriginalExtent:
msg = tr( "layer" );
break;
case CurrentExtent:
msg = tr( "map view" );
break;
case UserExtent:
msg = tr( "user defined" );
break;
case ProjectLayerExtent:
msg = mExtentLayerName;
break;
case DrawOnCanvas:
msg = tr( "drawn on canvas" );
break;
}
if ( isCheckable() && !isChecked() )
msg = tr( "none" );
msg = tr( "%1 (current: %2)" ).arg( mTitleBase, msg );
setTitle( msg );
}
void QgsExtentGroupBox::layerMenuAboutToShow()
{
qDeleteAll( mMenuActions );
mMenuActions.clear();
mLayerMenu->clear();
for ( int i = 0; i < mMapLayerModel->rowCount(); ++i )
{
QModelIndex index = mMapLayerModel->index( i, 0 );
QIcon icon = qvariant_cast<QIcon>( mMapLayerModel->data( index, Qt::DecorationRole ) );
QString text = mMapLayerModel->data( index, Qt::DisplayRole ).toString();
QAction *act = new QAction( icon, text, mLayerMenu );
act->setToolTip( mMapLayerModel->data( index, Qt::ToolTipRole ).toString() );
QString layerId = mMapLayerModel->data( index, QgsMapLayerModel::LayerIdRole ).toString();
if ( mExtentState == ProjectLayerExtent && mExtentLayer && mExtentLayer->id() == layerId )
{
act->setCheckable( true );
act->setChecked( true );
}
connect( act, &QAction::triggered, this, [this, layerId]
{
setExtentToLayerExtent( layerId );
} );
mLayerMenu->addAction( act );
mMenuActions << act;
}
}
void QgsExtentGroupBox::setExtentToLayerExtent( const QString &layerId )
{
QgsMapLayer *layer = QgsProject::instance()->mapLayer( layerId );
if ( !layer )
return;
setOutputExtentFromLayer( layer );
}
void QgsExtentGroupBox::setOutputExtentFromCurrent()
{
if ( mCanvas )
{
// Use unrotated visible extent to insure output size and scale matches canvas
QgsMapSettings ms = mCanvas->mapSettings();
ms.setRotation( 0 );
setOutputExtent( ms.visibleExtent(), ms.destinationCrs(), CurrentExtent );
}
else
{
setOutputExtent( mCurrentExtent, mCurrentCrs, CurrentExtent );
}
}
void QgsExtentGroupBox::setOutputExtentFromOriginal()
{
setOutputExtent( mOriginalExtent, mOriginalCrs, OriginalExtent );
}
void QgsExtentGroupBox::setOutputExtentFromUser( const QgsRectangle &extent, const QgsCoordinateReferenceSystem &crs )
{
setOutputExtent( extent, crs, UserExtent );
}
void QgsExtentGroupBox::setOutputExtentFromLayer( const QgsMapLayer *layer )
{
if ( !layer )
return;
mExtentLayer = layer;
mExtentLayerName = layer->name();
setOutputExtent( layer->extent(), layer->crs(), ProjectLayerExtent );
}
void QgsExtentGroupBox::setOutputExtentFromDrawOnCanvas()
{
if ( mCanvas )
{
mMapToolPrevious = mCanvas->mapTool();
if ( !mMapToolExtent )
{
mMapToolExtent.reset( new QgsMapToolExtent( mCanvas ) );
connect( mMapToolExtent.get(), &QgsMapToolExtent::extentChanged, this, &QgsExtentGroupBox::extentDrawn );
connect( mMapToolExtent.get(), &QgsMapTool::deactivated, this, [ = ]
{
window()->setVisible( true );
mMapToolPrevious = nullptr;
} );
}
mMapToolExtent->setRatio( mRatio );
mCanvas->setMapTool( mMapToolExtent.get() );
window()->setVisible( false );
}
}
void QgsExtentGroupBox::extentDrawn( const QgsRectangle &extent )
{
setOutputExtent( extent, mCanvas->mapSettings().destinationCrs(), DrawOnCanvas );
mCanvas->setMapTool( mMapToolPrevious );
window()->setVisible( true );
mMapToolPrevious = nullptr;
}
void QgsExtentGroupBox::groupBoxClicked()
{
if ( !isCheckable() )
return;
updateTitle();
// output extent just went from null to something (or vice versa)
emit extentChanged( outputExtent() );
}
QgsRectangle QgsExtentGroupBox::outputExtent() const
{
if ( isCheckable() && !isChecked() )
return QgsRectangle();
return QgsRectangle( mXMinLineEdit->text().toDouble(), mYMinLineEdit->text().toDouble(),
mXMaxLineEdit->text().toDouble(), mYMaxLineEdit->text().toDouble() );
}
void QgsExtentGroupBox::setTitleBase( const QString &title )
{
mTitleBase = title;
updateTitle();
}
QString QgsExtentGroupBox::titleBase() const
{
return mTitleBase;
}
void QgsExtentGroupBox::setMapCanvas( QgsMapCanvas *canvas )
{
if ( canvas )
{
mCanvas = canvas;
mButtonDrawOnCanvas->setVisible( true );
mCurrentExtentButton->setVisible( true );
}
else
{
mButtonDrawOnCanvas->setVisible( false );
mCurrentExtentButton->setVisible( false );
}
}