Add "Condensed" mode for QgsExtentWidget

The default appearance is very large, so this mode exposes a more
compact widget (e.g. with the buttons replaced by a toolbutton with
menu entries)
This commit is contained in:
Nyall Dawson 2020-03-25 13:08:39 +10:00
parent dbc022d8c9
commit f231b4a0ce
5 changed files with 311 additions and 170 deletions

View File

@ -41,7 +41,13 @@ When using the widget, make sure to call setOriginalExtent(), setCurrentExtent()
DrawOnCanvas,
};
explicit QgsExtentWidget( QWidget *parent /TransferThis/ = 0 );
enum WidgetStyle
{
CondensedStyle,
ExpandedStyle,
};
explicit QgsExtentWidget( QWidget *parent /TransferThis/ = 0, WidgetStyle style = CondensedStyle );
%Docstring
Constructor for QgsExtentWidget.
%End

View File

@ -20,7 +20,7 @@ QgsExtentGroupBox::QgsExtentGroupBox( QWidget *parent )
: QgsCollapsibleGroupBox( parent )
, mTitleBase( tr( "Extent" ) )
{
mWidget = new QgsExtentWidget();
mWidget = new QgsExtentWidget( nullptr, QgsExtentWidget::ExpandedStyle );
QVBoxLayout *layout = new QVBoxLayout();
layout->addWidget( mWidget );
setLayout( layout );

View File

@ -25,8 +25,9 @@
#include <QMenu>
#include <QAction>
#include <QDoubleValidator>
#include <QRegularExpression>
QgsExtentWidget::QgsExtentWidget( QWidget *parent )
QgsExtentWidget::QgsExtentWidget( QWidget *parent, WidgetStyle style )
: QWidget( parent )
{
setupUi( this );
@ -35,11 +36,31 @@ QgsExtentWidget::QgsExtentWidget( QWidget *parent )
connect( mYMinLineEdit, &QLineEdit::textEdited, this, &QgsExtentWidget::setOutputExtentFromLineEdit );
connect( mYMaxLineEdit, &QLineEdit::textEdited, this, &QgsExtentWidget::setOutputExtentFromLineEdit );
mLayerMenu = new QMenu( this );
mCondensedRe = QRegularExpression( QStringLiteral( "\\s*([\\d\\.]+)\\s*,\\s*([\\d\\.]+)\\s*,\\s*([\\d\\.]+)\\s*,\\s*([\\d\\.]+)\\s*(\\[.*?\\])" ) );
mCondensedLineEdit->setValidator( new QRegularExpressionValidator( mCondensedRe, this ) );
connect( mCondensedLineEdit, &QLineEdit::textEdited, this, &QgsExtentWidget::setOutputExtentFromCondensedLineEdit );
mLayerMenu = new QMenu( tr( "Calculate from Layer" ) );
mButtonCalcFromLayer->setMenu( mLayerMenu );
connect( mLayerMenu, &QMenu::aboutToShow, this, &QgsExtentWidget::layerMenuAboutToShow );
mMapLayerModel = new QgsMapLayerModel( this );
mMenu = new QMenu( this );
mUseCanvasExtentAction = new QAction( tr( "Use Map Canvas Extent" ), this );
connect( mUseCanvasExtentAction, &QAction::triggered, this, &QgsExtentWidget::setOutputExtentFromCurrent );
mUseCurrentExtentAction = new QAction( tr( "Use Current Layer Extent" ), this );
connect( mUseCurrentExtentAction, &QAction::triggered, this, &QgsExtentWidget::setOutputExtentFromCurrent );
mDrawOnCanvasAction = new QAction( tr( "Draw on Canvas" ), this );
connect( mDrawOnCanvasAction, &QAction::triggered, this, &QgsExtentWidget::setOutputExtentFromDrawOnCanvas );
mMenu->addMenu( mLayerMenu );
mCondensedToolButton->setMenu( mMenu );
mCondensedToolButton->setPopupMode( QToolButton::InstantPopup );
mXMinLineEdit->setValidator( new QDoubleValidator( this ) );
mXMaxLineEdit->setValidator( new QDoubleValidator( this ) );
mYMinLineEdit->setValidator( new QDoubleValidator( this ) );
@ -52,6 +73,17 @@ QgsExtentWidget::QgsExtentWidget( QWidget *parent )
connect( mCurrentExtentButton, &QAbstractButton::clicked, this, &QgsExtentWidget::setOutputExtentFromCurrent );
connect( mOriginalExtentButton, &QAbstractButton::clicked, this, &QgsExtentWidget::setOutputExtentFromOriginal );
connect( mButtonDrawOnCanvas, &QAbstractButton::clicked, this, &QgsExtentWidget::setOutputExtentFromDrawOnCanvas );
switch ( style )
{
case CondensedStyle:
mExpandedWidget->hide();
break;
case ExpandedStyle:
mCondensedFrame->hide();
break;
}
}
void QgsExtentWidget::setOriginalExtent( const QgsRectangle &originalExtent, const QgsCoordinateReferenceSystem &originalCrs )
@ -69,10 +101,12 @@ void QgsExtentWidget::setCurrentExtent( const QgsRectangle &currentExtent, const
mCurrentCrs = currentCrs;
mCurrentExtentButton->setVisible( true );
mMenu->addAction( mUseCurrentExtentAction );
}
void QgsExtentWidget::setOutputCrs( const QgsCoordinateReferenceSystem &outputCrs )
{
mHasFixedOutputCrs = true;
if ( mOutputCrs != outputCrs )
{
bool prevExtentEnabled = mIsValid;
@ -122,22 +156,30 @@ void QgsExtentWidget::setOutputCrs( const QgsCoordinateReferenceSystem &outputCr
void QgsExtentWidget::setOutputExtent( const QgsRectangle &r, const QgsCoordinateReferenceSystem &srcCrs, ExtentState state )
{
QgsRectangle extent;
if ( mOutputCrs == srcCrs )
if ( !mHasFixedOutputCrs )
{
mOutputCrs = srcCrs;
extent = r;
}
else
{
try
if ( mOutputCrs == srcCrs )
{
QgsCoordinateTransform ct( srcCrs, mOutputCrs, QgsProject::instance() );
extent = ct.transformBoundingBox( r );
}
catch ( QgsCsException & )
{
// can't reproject
extent = r;
}
else
{
try
{
QgsCoordinateTransform ct( srcCrs, mOutputCrs, QgsProject::instance() );
extent = ct.transformBoundingBox( r );
}
catch ( QgsCsException & )
{
// can't reproject
extent = r;
}
}
}
int decimals = 4;
@ -163,6 +205,13 @@ void QgsExtentWidget::setOutputExtent( const QgsRectangle &r, const QgsCoordinat
mYMinLineEdit->setText( QString::number( extent.yMinimum(), 'f', decimals ) );
mYMaxLineEdit->setText( QString::number( extent.yMaximum(), 'f', decimals ) );
QString condensed = QStringLiteral( "%1,%2,%3,%4" ).arg( mXMinLineEdit->text(),
mXMaxLineEdit->text(),
mYMinLineEdit->text(),
mYMaxLineEdit->text() );
condensed += QStringLiteral( " [%1]" ).arg( mOutputCrs.userFriendlyIdentifier( QgsCoordinateReferenceSystem::ShortString ) );
mCondensedLineEdit->setText( condensed );
mExtentState = state;
if ( !mIsValid )
@ -171,13 +220,26 @@ void QgsExtentWidget::setOutputExtent( const QgsRectangle &r, const QgsCoordinat
emit extentChanged( extent );
}
void QgsExtentWidget::setOutputExtentFromLineEdit()
{
mExtentState = UserExtent;
emit extentChanged( outputExtent() );
}
void QgsExtentWidget::setOutputExtentFromCondensedLineEdit()
{
const QString text = mCondensedLineEdit->text();
const QRegularExpressionMatch match = mCondensedRe.match( text );
if ( match.hasMatch() )
{
whileBlocking( mXMinLineEdit )->setText( match.captured( 1 ) );
whileBlocking( mXMaxLineEdit )->setText( match.captured( 2 ) );
whileBlocking( mYMinLineEdit )->setText( match.captured( 3 ) );
whileBlocking( mYMaxLineEdit )->setText( match.captured( 4 ) );
emit extentChanged( outputExtent() );
}
}
QString QgsExtentWidget::extentLayerName() const
{
return mExtentLayerName;
@ -199,8 +261,8 @@ void QgsExtentWidget::setValid( bool valid )
void QgsExtentWidget::layerMenuAboutToShow()
{
qDeleteAll( mMenuActions );
mMenuActions.clear();
qDeleteAll( mLayerMenuActions );
mLayerMenuActions.clear();
mLayerMenu->clear();
for ( int i = 0; i < mMapLayerModel->rowCount(); ++i )
{
@ -220,7 +282,7 @@ void QgsExtentWidget::layerMenuAboutToShow()
setExtentToLayerExtent( layerId );
} );
mLayerMenu->addAction( act );
mMenuActions << act;
mLayerMenuActions << act;
}
}
@ -312,10 +374,15 @@ void QgsExtentWidget::setMapCanvas( QgsMapCanvas *canvas )
mCanvas = canvas;
mButtonDrawOnCanvas->setVisible( true );
mCurrentExtentButton->setVisible( true );
mMenu->addAction( mUseCanvasExtentAction );
mMenu->addAction( mDrawOnCanvasAction );
}
else
{
mButtonDrawOnCanvas->setVisible( false );
mCurrentExtentButton->setVisible( false );
mMenu->removeAction( mUseCanvasExtentAction );
mMenu->removeAction( mDrawOnCanvasAction );
}
}

View File

@ -28,6 +28,7 @@
#include "qgis_gui.h"
#include <memory>
#include <QRegularExpression>
class QgsCoordinateReferenceSystem;
class QgsMapLayerModel;
@ -62,10 +63,17 @@ class GUI_EXPORT QgsExtentWidget : public QWidget, private Ui::QgsExtentGroupBox
DrawOnCanvas, //!< Extent taken from a rectangled drawn onto the map canvas
};
//! Widget styles
enum WidgetStyle
{
CondensedStyle, //!< Shows a compressed widget, for use when available space is minimal
ExpandedStyle, //!< Shows an expanded widget, for use when space is not constrained
};
/**
* Constructor for QgsExtentWidget.
*/
explicit QgsExtentWidget( QWidget *parent SIP_TRANSFERTHIS = nullptr );
explicit QgsExtentWidget( QWidget *parent SIP_TRANSFERTHIS = nullptr, WidgetStyle style = CondensedStyle );
/**
* Sets the original extent and coordinate reference system for the widget. This should be called as part of initialization.
@ -213,6 +221,7 @@ class GUI_EXPORT QgsExtentWidget : public QWidget, private Ui::QgsExtentGroupBox
private:
void setOutputExtent( const QgsRectangle &r, const QgsCoordinateReferenceSystem &srcCrs, QgsExtentWidget::ExtentState state );
void setOutputExtentFromLineEdit();
void setOutputExtentFromCondensedLineEdit();
ExtentState mExtentState = OriginalExtent;
@ -224,9 +233,14 @@ class GUI_EXPORT QgsExtentWidget : public QWidget, private Ui::QgsExtentGroupBox
QgsRectangle mOriginalExtent;
QgsCoordinateReferenceSystem mOriginalCrs;
QMenu *mMenu = nullptr;
QMenu *mLayerMenu = nullptr;
QgsMapLayerModel *mMapLayerModel = nullptr;
QList< QAction * > mMenuActions;
QList< QAction * > mLayerMenuActions;
QAction *mUseCanvasExtentAction = nullptr;
QAction *mUseCurrentExtentAction = nullptr;
QAction *mDrawOnCanvasAction = nullptr;
QPointer< const QgsMapLayer > mExtentLayer;
QString mExtentLayerName;
@ -236,6 +250,9 @@ class GUI_EXPORT QgsExtentWidget : public QWidget, private Ui::QgsExtentGroupBox
QSize mRatio;
bool mIsValid = false;
bool mHasFixedOutputCrs = false;
QRegularExpression mCondensedRe;
void setValid( bool valid );
void setExtentToLayerExtent( const QString &layerId );

View File

@ -2,14 +2,6 @@
<ui version="4.0">
<class>QgsExtentGroupBoxWidget</class>
<widget class="QWidget" name="QgsExtentGroupBoxWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>679</width>
<height>128</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
@ -33,68 +25,8 @@
<number>0</number>
</property>
<item>
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="1">
<widget class="QLabel" name="mYMaxLabel">
<property name="text">
<string>North</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLineEdit" name="mYMaxLineEdit">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="mYMinLabel">
<property name="text">
<string>South</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLineEdit" name="mYMinLineEdit"/>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="mXMinLineEdit"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="mXMinLabel">
<property name="text">
<string>West</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QLineEdit" name="mXMaxLineEdit"/>
</item>
<item row="1" column="2">
<widget class="QLabel" name="mXMaxLabel">
<property name="text">
<string>East</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QWidget" name="widget_2" native="true">
<layout class="QGridLayout" name="gridLayout">
<widget class="QWidget" name="mExpandedWidget" native="true">
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
@ -107,94 +39,213 @@
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="11">
<widget class="QPushButton" name="mButtonDrawOnCanvas">
<item>
<layout class="QGridLayout" name="gridLayout_4">
<item row="2" column="1">
<widget class="QLabel" name="mYMinLabel">
<property name="text">
<string>South</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLineEdit" name="mYMaxLineEdit">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLineEdit" name="mYMinLineEdit"/>
</item>
<item row="0" column="1">
<widget class="QLabel" name="mYMaxLabel">
<property name="text">
<string>North</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="mXMaxLabel">
<property name="text">
<string>East</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="mXMinLabel">
<property name="text">
<string>West</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QLineEdit" name="mXMaxLineEdit"/>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="mXMinLineEdit"/>
</item>
</layout>
</item>
<item>
<widget class="QWidget" name="widget_2" native="true">
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item row="2" column="11">
<widget class="QPushButton" name="mButtonDrawOnCanvas">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Draw on Canvas</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QPushButton" name="mOriginalExtentButton">
<property name="minimumSize">
<size>
<width>150</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Current Layer Extent</string>
</property>
</widget>
</item>
<item row="2" column="6">
<widget class="QPushButton" name="mCurrentExtentButton">
<property name="minimumSize">
<size>
<width>150</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Map Canvas Extent</string>
</property>
</widget>
</item>
<item row="2" column="1">
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="5">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="10">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="3">
<widget class="QPushButton" name="mButtonCalcFromLayer">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Calculate from Layer</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="mCondensedFrame" native="true">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLineEdit" name="mCondensedLineEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="mCondensedToolButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Draw on Canvas</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QPushButton" name="mOriginalExtentButton">
<property name="minimumSize">
<size>
<width>150</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Current Layer Extent</string>
</property>
</widget>
</item>
<item row="0" column="6">
<widget class="QPushButton" name="mCurrentExtentButton">
<property name="minimumSize">
<size>
<width>150</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Map Canvas Extent</string>
</property>
</widget>
</item>
<item row="0" column="1">
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="5">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="10">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="3">
<widget class="QPushButton" name="mButtonCalcFromLayer">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Calculate from Layer</string>
<string>…</string>
</property>
</widget>
</item>