mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
[FEATURE][composer] Implement different resize modes for composer picture items, including zoom, stretch, clip, frame to image size (fix #7886). (Sponsored by City of Uster, Switzerland)
This commit is contained in:
parent
8ab3ce4c75
commit
23b660ec74
@ -198,6 +198,21 @@ void QgsComposerPictureWidget::on_mRemoveDirectoryButton_clicked()
|
||||
s.setValue( "/Composer/PictureWidgetDirectories", userDirList );
|
||||
}
|
||||
|
||||
void QgsComposerPictureWidget::on_mResizeModeComboBox_currentIndexChanged( int index )
|
||||
{
|
||||
if ( !mPicture )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mPicture->beginCommand( tr( "Picture resize mode changed" ) );
|
||||
mPicture->setResizeMode(( QgsComposerPicture::ResizeMode )index );
|
||||
mPicture->endCommand();
|
||||
|
||||
//disable picture rotation for non-zoom modes
|
||||
mRotationGroupBox->setEnabled( mPicture->resizeMode() == QgsComposerPicture::Zoom );
|
||||
}
|
||||
|
||||
void QgsComposerPictureWidget::on_mRotationFromComposerMapCheckBox_stateChanged( int state )
|
||||
{
|
||||
if ( !mPicture )
|
||||
@ -326,6 +341,7 @@ void QgsComposerPictureWidget::setGuiElementValues()
|
||||
mPictureLineEdit->blockSignals( true );
|
||||
mComposerMapComboBox->blockSignals( true );
|
||||
mRotationFromComposerMapCheckBox->blockSignals( true );
|
||||
mResizeModeComboBox->blockSignals( true );
|
||||
|
||||
mPictureLineEdit->setText( mPicture->pictureFile() );
|
||||
// QRectF pictureRect = mPicture->rect();
|
||||
@ -352,11 +368,15 @@ void QgsComposerPictureWidget::setGuiElementValues()
|
||||
mComposerMapComboBox->setEnabled( false );
|
||||
}
|
||||
|
||||
mResizeModeComboBox->setCurrentIndex(( int )mPicture->resizeMode() );
|
||||
//disable picture rotation for non-zoom modes
|
||||
mRotationGroupBox->setEnabled( mPicture->resizeMode() == QgsComposerPicture::Zoom );
|
||||
|
||||
mRotationFromComposerMapCheckBox->blockSignals( false );
|
||||
mPictureRotationSpinBox->blockSignals( false );
|
||||
mPictureLineEdit->blockSignals( false );
|
||||
mComposerMapComboBox->blockSignals( false );
|
||||
mResizeModeComboBox->blockSignals( false );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,6 +45,7 @@ class QgsComposerPictureWidget: public QWidget, private Ui::QgsComposerPictureWi
|
||||
void on_mRemoveDirectoryButton_clicked();
|
||||
void on_mRotationFromComposerMapCheckBox_stateChanged( int state );
|
||||
void on_mComposerMapComboBox_activated( const QString & text );
|
||||
void on_mResizeModeComboBox_currentIndexChanged( int index );
|
||||
|
||||
protected:
|
||||
void showEvent( QShowEvent * event );
|
||||
|
@ -28,12 +28,13 @@
|
||||
|
||||
|
||||
QgsComposerPicture::QgsComposerPicture( QgsComposition *composition )
|
||||
: QgsComposerItem( composition ), mMode( Unknown ), mPictureRotation( 0 ), mRotationMap( 0 )
|
||||
: QgsComposerItem( composition ), mMode( Unknown ), mPictureRotation( 0 ), mRotationMap( 0 ),
|
||||
mResizeMode( QgsComposerPicture::Zoom )
|
||||
{
|
||||
mPictureWidth = rect().width();
|
||||
}
|
||||
|
||||
QgsComposerPicture::QgsComposerPicture(): QgsComposerItem( 0 ), mMode( Unknown ), mPictureRotation( 0 ), mRotationMap( 0 )
|
||||
QgsComposerPicture::QgsComposerPicture(): QgsComposerItem( 0 ), mMode( Unknown ), mPictureRotation( 0 ), mRotationMap( 0 ), mResizeMode( QgsComposerPicture::Zoom )
|
||||
{
|
||||
mPictureHeight = rect().height();
|
||||
}
|
||||
@ -58,13 +59,39 @@ void QgsComposerPicture::paint( QPainter* painter, const QStyleOptionGraphicsIte
|
||||
|
||||
if ( mMode != Unknown )
|
||||
{
|
||||
double boundRectWidthMM = mPictureWidth;
|
||||
double boundRectHeightMM = mPictureHeight;
|
||||
|
||||
double boundRectWidthMM;
|
||||
double boundRectHeightMM;
|
||||
double imageRectWidthMM;
|
||||
double imageRectHeightMM;
|
||||
if ( mResizeMode == QgsComposerPicture::Zoom || mResizeMode == QgsComposerPicture::ZoomResizeFrame )
|
||||
{
|
||||
boundRectWidthMM = mPictureWidth;
|
||||
boundRectHeightMM = mPictureHeight;
|
||||
imageRectWidthMM = mImage.width();
|
||||
imageRectHeightMM = mImage.height();
|
||||
}
|
||||
else if ( mResizeMode == QgsComposerPicture::Stretch )
|
||||
{
|
||||
boundRectWidthMM = rect().width();
|
||||
boundRectHeightMM = rect().height();
|
||||
imageRectWidthMM = mImage.width();
|
||||
imageRectHeightMM = mImage.height();
|
||||
}
|
||||
else
|
||||
{
|
||||
boundRectWidthMM = rect().width();
|
||||
boundRectHeightMM = rect().height();
|
||||
imageRectWidthMM = rect().width() * mComposition->printResolution() / 25.4;
|
||||
imageRectHeightMM = rect().height() * mComposition->printResolution() / 25.4;
|
||||
}
|
||||
painter->save();
|
||||
painter->translate( rect().width() / 2.0, rect().height() / 2.0 );
|
||||
painter->rotate( mPictureRotation );
|
||||
painter->translate( -boundRectWidthMM / 2.0, -boundRectHeightMM / 2.0 );
|
||||
|
||||
if ( mResizeMode == Zoom )
|
||||
{
|
||||
painter->translate( rect().width() / 2.0, rect().height() / 2.0 );
|
||||
painter->rotate( mPictureRotation );
|
||||
painter->translate( -boundRectWidthMM / 2.0, -boundRectHeightMM / 2.0 );
|
||||
}
|
||||
|
||||
if ( mMode == SVG )
|
||||
{
|
||||
@ -72,7 +99,7 @@ void QgsComposerPicture::paint( QPainter* painter, const QStyleOptionGraphicsIte
|
||||
}
|
||||
else if ( mMode == RASTER )
|
||||
{
|
||||
painter->drawImage( QRectF( 0, 0, boundRectWidthMM, boundRectHeightMM ), mImage, QRectF( 0, 0, mImage.width(), mImage.height() ) );
|
||||
painter->drawImage( QRectF( 0, 0, boundRectWidthMM, boundRectHeightMM ), mImage, QRectF( 0, 0, imageRectWidthMM, imageRectHeightMM ) );
|
||||
}
|
||||
|
||||
painter->restore();
|
||||
@ -204,14 +231,53 @@ QRectF QgsComposerPicture::boundedSVGRect( double deviceWidth, double deviceHeig
|
||||
|
||||
void QgsComposerPicture::setSceneRect( const QRectF& rectangle )
|
||||
{
|
||||
QgsComposerItem::setSceneRect( rectangle );
|
||||
|
||||
QSizeF currentPictureSize = pictureSize();
|
||||
|
||||
if ( mResizeMode == QgsComposerPicture::Clip )
|
||||
{
|
||||
QgsComposerItem::setSceneRect( rectangle );
|
||||
mPictureWidth = rectangle.width();
|
||||
mPictureHeight = rectangle.height();
|
||||
return;
|
||||
}
|
||||
|
||||
QRectF newRect = rectangle;
|
||||
|
||||
if ( mResizeMode == ZoomResizeFrame && !rect().isEmpty() )
|
||||
{
|
||||
//if width has changed less than height, then fix width and set height correspondingly
|
||||
//else, do the opposite
|
||||
if ( qAbs( rect().width() - rectangle.width() ) <
|
||||
qAbs( rect().height() - rectangle.height() ) )
|
||||
{
|
||||
newRect.setHeight( currentPictureSize.height() * newRect.width() / currentPictureSize.width() );
|
||||
}
|
||||
else
|
||||
{
|
||||
newRect.setWidth( currentPictureSize.width() * newRect.height() / currentPictureSize.height() );
|
||||
}
|
||||
}
|
||||
else if ( mResizeMode == FrameToImageSize )
|
||||
{
|
||||
newRect.setWidth( currentPictureSize.width() * 25.4 / mComposition->printResolution() );
|
||||
newRect.setHeight( currentPictureSize.height() * 25.4 / mComposition->printResolution() );
|
||||
}
|
||||
|
||||
//find largest scaling of picture with this rotation which fits in item
|
||||
QSizeF currentPictureSize = pictureSize();
|
||||
QRectF rotatedImageRect = largestRotatedRectWithinBounds( QRectF( 0, 0, currentPictureSize.width(), currentPictureSize.height() ), rectangle, mPictureRotation );
|
||||
mPictureWidth = rotatedImageRect.width();
|
||||
mPictureHeight = rotatedImageRect.height();
|
||||
if ( mResizeMode == Zoom )
|
||||
{
|
||||
QRectF rotatedImageRect = largestRotatedRectWithinBounds( QRectF( 0, 0, currentPictureSize.width(), currentPictureSize.height() ), newRect, mPictureRotation );
|
||||
mPictureWidth = rotatedImageRect.width();
|
||||
mPictureHeight = rotatedImageRect.height();
|
||||
}
|
||||
else
|
||||
{
|
||||
mPictureWidth = newRect.width();
|
||||
mPictureHeight = newRect.height();
|
||||
}
|
||||
|
||||
QgsComposerItem::setSceneRect( newRect );
|
||||
emit itemChanged();
|
||||
}
|
||||
|
||||
@ -225,13 +291,16 @@ void QgsComposerPicture::setPictureRotation( double r )
|
||||
{
|
||||
mPictureRotation = r;
|
||||
|
||||
//find largest scaling of picture with this rotation which fits in item
|
||||
QSizeF currentPictureSize = pictureSize();
|
||||
QRectF rotatedImageRect = largestRotatedRectWithinBounds( QRectF( 0, 0, currentPictureSize.width(), currentPictureSize.height() ), rect(), mPictureRotation );
|
||||
mPictureWidth = rotatedImageRect.width();
|
||||
mPictureHeight = rotatedImageRect.height();
|
||||
if ( mResizeMode == Zoom )
|
||||
{
|
||||
//find largest scaling of picture with this rotation which fits in item
|
||||
QSizeF currentPictureSize = pictureSize();
|
||||
QRectF rotatedImageRect = largestRotatedRectWithinBounds( QRectF( 0, 0, currentPictureSize.width(), currentPictureSize.height() ), rect(), mPictureRotation );
|
||||
mPictureWidth = rotatedImageRect.width();
|
||||
mPictureHeight = rotatedImageRect.height();
|
||||
update();
|
||||
}
|
||||
|
||||
update();
|
||||
emit pictureRotationChanged( mPictureRotation );
|
||||
}
|
||||
|
||||
@ -264,6 +333,18 @@ void QgsComposerPicture::setRotationMap( int composerMapId )
|
||||
emit pictureRotationChanged( mPictureRotation );
|
||||
}
|
||||
|
||||
void QgsComposerPicture::setResizeMode( QgsComposerPicture::ResizeMode mode )
|
||||
{
|
||||
mResizeMode = mode;
|
||||
if ( mode == QgsComposerPicture::ZoomResizeFrame || mode == QgsComposerPicture::FrameToImageSize
|
||||
|| ( mode == QgsComposerPicture::Zoom && mPictureRotation != 0 ) )
|
||||
{
|
||||
//call set scene rect to force item to resize to fit picture
|
||||
setSceneRect( QRectF( pos().x(), pos().y(), rect().width(), rect().height() ) );
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
QString QgsComposerPicture::pictureFile() const
|
||||
{
|
||||
return mSourceFile.fileName();
|
||||
@ -279,6 +360,7 @@ bool QgsComposerPicture::writeXML( QDomElement& elem, QDomDocument & doc ) const
|
||||
composerPictureElem.setAttribute( "file", QgsProject::instance()->writePath( mSourceFile.fileName() ) );
|
||||
composerPictureElem.setAttribute( "pictureWidth", QString::number( mPictureWidth ) );
|
||||
composerPictureElem.setAttribute( "pictureHeight", QString::number( mPictureHeight ) );
|
||||
composerPictureElem.setAttribute( "resizeMode", QString::number(( int )mResizeMode ) );
|
||||
|
||||
//rotation
|
||||
composerPictureElem.setAttribute( "pictureRotation", QString::number( mPictureRotation ) );
|
||||
@ -305,6 +387,7 @@ bool QgsComposerPicture::readXML( const QDomElement& itemElem, const QDomDocumen
|
||||
|
||||
mPictureWidth = itemElem.attribute( "pictureWidth", "10" ).toDouble();
|
||||
mPictureHeight = itemElem.attribute( "pictureHeight", "10" ).toDouble();
|
||||
mResizeMode = QgsComposerPicture::ResizeMode( itemElem.attribute( "resizeMode", "0" ).toInt() );
|
||||
|
||||
QDomNodeList composerItemList = itemElem.elementsByTagName( "ComposerItem" );
|
||||
if ( composerItemList.size() > 0 )
|
||||
|
@ -31,6 +31,23 @@ class CORE_EXPORT QgsComposerPicture: public QgsComposerItem
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
enum ResizeMode
|
||||
{
|
||||
Zoom,
|
||||
Stretch,
|
||||
Clip,
|
||||
ZoomResizeFrame,
|
||||
FrameToImageSize
|
||||
};
|
||||
|
||||
enum Mode //SVG or raster graphic format
|
||||
{
|
||||
SVG,
|
||||
RASTER,
|
||||
Unknown
|
||||
};
|
||||
|
||||
QgsComposerPicture( QgsComposition *composition );
|
||||
~QgsComposerPicture();
|
||||
|
||||
@ -76,6 +93,10 @@ class CORE_EXPORT QgsComposerPicture: public QgsComposerItem
|
||||
/**True if the rotation is taken from a map item*/
|
||||
bool useRotationMap() const {return mRotationMap;}
|
||||
|
||||
/**Returns the resize mode used for drawing the picture within the composer item
|
||||
*/
|
||||
ResizeMode resizeMode() const { return mResizeMode;};
|
||||
|
||||
/**Calculates width and hight of the picture (in mm) such that it fits into the item frame with the given rotation
|
||||
* @deprecated Use bool QgsComposerItem::imageSizeConsideringRotation( double& width, double& height, double rotation )
|
||||
* instead
|
||||
@ -92,6 +113,8 @@ class CORE_EXPORT QgsComposerPicture: public QgsComposerItem
|
||||
*/
|
||||
Q_DECL_DEPRECATED void sizeChangedByRotation( double& width, double& height );
|
||||
|
||||
Mode mode() const { return mMode; };
|
||||
|
||||
public slots:
|
||||
/**Sets the picture rotation within the item bounds. This does not affect the item rectangle,
|
||||
only the way the picture is drawn within the item.
|
||||
@ -104,19 +127,16 @@ class CORE_EXPORT QgsComposerPicture: public QgsComposerItem
|
||||
@note this function was added in version 2.1*/
|
||||
virtual void setPictureRotation( double r );
|
||||
|
||||
/**Sets the resize mode used for drawing the picture within the item bounds
|
||||
@note this function was added in version 2.1*/
|
||||
virtual void setResizeMode( ResizeMode mode );
|
||||
|
||||
signals:
|
||||
/**Is emitted on picture rotation change*/
|
||||
void pictureRotationChanged( double newRotation );
|
||||
|
||||
private:
|
||||
|
||||
enum Mode //SVG or raster graphic format
|
||||
{
|
||||
SVG,
|
||||
RASTER,
|
||||
Unknown
|
||||
};
|
||||
|
||||
//default constructor is forbidden
|
||||
QgsComposerPicture();
|
||||
/**Calculates bounding rect for svg file (mSourcefile) such that aspect ratio is correct*/
|
||||
@ -142,6 +162,8 @@ class CORE_EXPORT QgsComposerPicture: public QgsComposerItem
|
||||
double mPictureWidth;
|
||||
/**Height of the picture (in mm)*/
|
||||
double mPictureHeight;
|
||||
|
||||
ResizeMode mResizeMode;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -105,6 +105,42 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Resize mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="mResizeModeComboBox">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Zoom</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Stretch</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Clip</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Zoom and resize frame</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Resize frame to image size</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
@ -211,7 +247,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QgsCollapsibleGroupBoxBasic" name="groupBox">
|
||||
<widget class="QgsCollapsibleGroupBoxBasic" name="mRotationGroupBox">
|
||||
<property name="title">
|
||||
<string>Image rotation</string>
|
||||
</property>
|
||||
|
Loading…
x
Reference in New Issue
Block a user