mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-17 00:04:02 -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 );
|
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 )
|
void QgsComposerPictureWidget::on_mRotationFromComposerMapCheckBox_stateChanged( int state )
|
||||||
{
|
{
|
||||||
if ( !mPicture )
|
if ( !mPicture )
|
||||||
@ -326,6 +341,7 @@ void QgsComposerPictureWidget::setGuiElementValues()
|
|||||||
mPictureLineEdit->blockSignals( true );
|
mPictureLineEdit->blockSignals( true );
|
||||||
mComposerMapComboBox->blockSignals( true );
|
mComposerMapComboBox->blockSignals( true );
|
||||||
mRotationFromComposerMapCheckBox->blockSignals( true );
|
mRotationFromComposerMapCheckBox->blockSignals( true );
|
||||||
|
mResizeModeComboBox->blockSignals( true );
|
||||||
|
|
||||||
mPictureLineEdit->setText( mPicture->pictureFile() );
|
mPictureLineEdit->setText( mPicture->pictureFile() );
|
||||||
// QRectF pictureRect = mPicture->rect();
|
// QRectF pictureRect = mPicture->rect();
|
||||||
@ -352,11 +368,15 @@ void QgsComposerPictureWidget::setGuiElementValues()
|
|||||||
mComposerMapComboBox->setEnabled( false );
|
mComposerMapComboBox->setEnabled( false );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mResizeModeComboBox->setCurrentIndex(( int )mPicture->resizeMode() );
|
||||||
|
//disable picture rotation for non-zoom modes
|
||||||
|
mRotationGroupBox->setEnabled( mPicture->resizeMode() == QgsComposerPicture::Zoom );
|
||||||
|
|
||||||
mRotationFromComposerMapCheckBox->blockSignals( false );
|
mRotationFromComposerMapCheckBox->blockSignals( false );
|
||||||
mPictureRotationSpinBox->blockSignals( false );
|
mPictureRotationSpinBox->blockSignals( false );
|
||||||
mPictureLineEdit->blockSignals( false );
|
mPictureLineEdit->blockSignals( false );
|
||||||
mComposerMapComboBox->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_mRemoveDirectoryButton_clicked();
|
||||||
void on_mRotationFromComposerMapCheckBox_stateChanged( int state );
|
void on_mRotationFromComposerMapCheckBox_stateChanged( int state );
|
||||||
void on_mComposerMapComboBox_activated( const QString & text );
|
void on_mComposerMapComboBox_activated( const QString & text );
|
||||||
|
void on_mResizeModeComboBox_currentIndexChanged( int index );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void showEvent( QShowEvent * event );
|
void showEvent( QShowEvent * event );
|
||||||
|
@ -28,12 +28,13 @@
|
|||||||
|
|
||||||
|
|
||||||
QgsComposerPicture::QgsComposerPicture( QgsComposition *composition )
|
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();
|
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();
|
mPictureHeight = rect().height();
|
||||||
}
|
}
|
||||||
@ -58,13 +59,39 @@ void QgsComposerPicture::paint( QPainter* painter, const QStyleOptionGraphicsIte
|
|||||||
|
|
||||||
if ( mMode != Unknown )
|
if ( mMode != Unknown )
|
||||||
{
|
{
|
||||||
double boundRectWidthMM = mPictureWidth;
|
double boundRectWidthMM;
|
||||||
double boundRectHeightMM = mPictureHeight;
|
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->save();
|
||||||
|
|
||||||
|
if ( mResizeMode == Zoom )
|
||||||
|
{
|
||||||
painter->translate( rect().width() / 2.0, rect().height() / 2.0 );
|
painter->translate( rect().width() / 2.0, rect().height() / 2.0 );
|
||||||
painter->rotate( mPictureRotation );
|
painter->rotate( mPictureRotation );
|
||||||
painter->translate( -boundRectWidthMM / 2.0, -boundRectHeightMM / 2.0 );
|
painter->translate( -boundRectWidthMM / 2.0, -boundRectHeightMM / 2.0 );
|
||||||
|
}
|
||||||
|
|
||||||
if ( mMode == SVG )
|
if ( mMode == SVG )
|
||||||
{
|
{
|
||||||
@ -72,7 +99,7 @@ void QgsComposerPicture::paint( QPainter* painter, const QStyleOptionGraphicsIte
|
|||||||
}
|
}
|
||||||
else if ( mMode == RASTER )
|
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();
|
painter->restore();
|
||||||
@ -203,15 +230,54 @@ QRectF QgsComposerPicture::boundedSVGRect( double deviceWidth, double deviceHeig
|
|||||||
#endif //0
|
#endif //0
|
||||||
|
|
||||||
void QgsComposerPicture::setSceneRect( const QRectF& rectangle )
|
void QgsComposerPicture::setSceneRect( const QRectF& rectangle )
|
||||||
|
{
|
||||||
|
|
||||||
|
QSizeF currentPictureSize = pictureSize();
|
||||||
|
|
||||||
|
if ( mResizeMode == QgsComposerPicture::Clip )
|
||||||
{
|
{
|
||||||
QgsComposerItem::setSceneRect( rectangle );
|
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
|
//find largest scaling of picture with this rotation which fits in item
|
||||||
QSizeF currentPictureSize = pictureSize();
|
if ( mResizeMode == Zoom )
|
||||||
QRectF rotatedImageRect = largestRotatedRectWithinBounds( QRectF( 0, 0, currentPictureSize.width(), currentPictureSize.height() ), rectangle, mPictureRotation );
|
{
|
||||||
|
QRectF rotatedImageRect = largestRotatedRectWithinBounds( QRectF( 0, 0, currentPictureSize.width(), currentPictureSize.height() ), newRect, mPictureRotation );
|
||||||
mPictureWidth = rotatedImageRect.width();
|
mPictureWidth = rotatedImageRect.width();
|
||||||
mPictureHeight = rotatedImageRect.height();
|
mPictureHeight = rotatedImageRect.height();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mPictureWidth = newRect.width();
|
||||||
|
mPictureHeight = newRect.height();
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsComposerItem::setSceneRect( newRect );
|
||||||
emit itemChanged();
|
emit itemChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -225,13 +291,16 @@ void QgsComposerPicture::setPictureRotation( double r )
|
|||||||
{
|
{
|
||||||
mPictureRotation = r;
|
mPictureRotation = r;
|
||||||
|
|
||||||
|
if ( mResizeMode == Zoom )
|
||||||
|
{
|
||||||
//find largest scaling of picture with this rotation which fits in item
|
//find largest scaling of picture with this rotation which fits in item
|
||||||
QSizeF currentPictureSize = pictureSize();
|
QSizeF currentPictureSize = pictureSize();
|
||||||
QRectF rotatedImageRect = largestRotatedRectWithinBounds( QRectF( 0, 0, currentPictureSize.width(), currentPictureSize.height() ), rect(), mPictureRotation );
|
QRectF rotatedImageRect = largestRotatedRectWithinBounds( QRectF( 0, 0, currentPictureSize.width(), currentPictureSize.height() ), rect(), mPictureRotation );
|
||||||
mPictureWidth = rotatedImageRect.width();
|
mPictureWidth = rotatedImageRect.width();
|
||||||
mPictureHeight = rotatedImageRect.height();
|
mPictureHeight = rotatedImageRect.height();
|
||||||
|
|
||||||
update();
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
emit pictureRotationChanged( mPictureRotation );
|
emit pictureRotationChanged( mPictureRotation );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,6 +333,18 @@ void QgsComposerPicture::setRotationMap( int composerMapId )
|
|||||||
emit pictureRotationChanged( mPictureRotation );
|
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
|
QString QgsComposerPicture::pictureFile() const
|
||||||
{
|
{
|
||||||
return mSourceFile.fileName();
|
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( "file", QgsProject::instance()->writePath( mSourceFile.fileName() ) );
|
||||||
composerPictureElem.setAttribute( "pictureWidth", QString::number( mPictureWidth ) );
|
composerPictureElem.setAttribute( "pictureWidth", QString::number( mPictureWidth ) );
|
||||||
composerPictureElem.setAttribute( "pictureHeight", QString::number( mPictureHeight ) );
|
composerPictureElem.setAttribute( "pictureHeight", QString::number( mPictureHeight ) );
|
||||||
|
composerPictureElem.setAttribute( "resizeMode", QString::number(( int )mResizeMode ) );
|
||||||
|
|
||||||
//rotation
|
//rotation
|
||||||
composerPictureElem.setAttribute( "pictureRotation", QString::number( mPictureRotation ) );
|
composerPictureElem.setAttribute( "pictureRotation", QString::number( mPictureRotation ) );
|
||||||
@ -305,6 +387,7 @@ bool QgsComposerPicture::readXML( const QDomElement& itemElem, const QDomDocumen
|
|||||||
|
|
||||||
mPictureWidth = itemElem.attribute( "pictureWidth", "10" ).toDouble();
|
mPictureWidth = itemElem.attribute( "pictureWidth", "10" ).toDouble();
|
||||||
mPictureHeight = itemElem.attribute( "pictureHeight", "10" ).toDouble();
|
mPictureHeight = itemElem.attribute( "pictureHeight", "10" ).toDouble();
|
||||||
|
mResizeMode = QgsComposerPicture::ResizeMode( itemElem.attribute( "resizeMode", "0" ).toInt() );
|
||||||
|
|
||||||
QDomNodeList composerItemList = itemElem.elementsByTagName( "ComposerItem" );
|
QDomNodeList composerItemList = itemElem.elementsByTagName( "ComposerItem" );
|
||||||
if ( composerItemList.size() > 0 )
|
if ( composerItemList.size() > 0 )
|
||||||
|
@ -31,6 +31,23 @@ class CORE_EXPORT QgsComposerPicture: public QgsComposerItem
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
enum ResizeMode
|
||||||
|
{
|
||||||
|
Zoom,
|
||||||
|
Stretch,
|
||||||
|
Clip,
|
||||||
|
ZoomResizeFrame,
|
||||||
|
FrameToImageSize
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Mode //SVG or raster graphic format
|
||||||
|
{
|
||||||
|
SVG,
|
||||||
|
RASTER,
|
||||||
|
Unknown
|
||||||
|
};
|
||||||
|
|
||||||
QgsComposerPicture( QgsComposition *composition );
|
QgsComposerPicture( QgsComposition *composition );
|
||||||
~QgsComposerPicture();
|
~QgsComposerPicture();
|
||||||
|
|
||||||
@ -76,6 +93,10 @@ class CORE_EXPORT QgsComposerPicture: public QgsComposerItem
|
|||||||
/**True if the rotation is taken from a map item*/
|
/**True if the rotation is taken from a map item*/
|
||||||
bool useRotationMap() const {return mRotationMap;}
|
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
|
/**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 )
|
* @deprecated Use bool QgsComposerItem::imageSizeConsideringRotation( double& width, double& height, double rotation )
|
||||||
* instead
|
* instead
|
||||||
@ -92,6 +113,8 @@ class CORE_EXPORT QgsComposerPicture: public QgsComposerItem
|
|||||||
*/
|
*/
|
||||||
Q_DECL_DEPRECATED void sizeChangedByRotation( double& width, double& height );
|
Q_DECL_DEPRECATED void sizeChangedByRotation( double& width, double& height );
|
||||||
|
|
||||||
|
Mode mode() const { return mMode; };
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
/**Sets the picture rotation within the item bounds. This does not affect the item rectangle,
|
/**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.
|
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*/
|
@note this function was added in version 2.1*/
|
||||||
virtual void setPictureRotation( double r );
|
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:
|
signals:
|
||||||
/**Is emitted on picture rotation change*/
|
/**Is emitted on picture rotation change*/
|
||||||
void pictureRotationChanged( double newRotation );
|
void pictureRotationChanged( double newRotation );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
enum Mode //SVG or raster graphic format
|
|
||||||
{
|
|
||||||
SVG,
|
|
||||||
RASTER,
|
|
||||||
Unknown
|
|
||||||
};
|
|
||||||
|
|
||||||
//default constructor is forbidden
|
//default constructor is forbidden
|
||||||
QgsComposerPicture();
|
QgsComposerPicture();
|
||||||
/**Calculates bounding rect for svg file (mSourcefile) such that aspect ratio is correct*/
|
/**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;
|
double mPictureWidth;
|
||||||
/**Height of the picture (in mm)*/
|
/**Height of the picture (in mm)*/
|
||||||
double mPictureHeight;
|
double mPictureHeight;
|
||||||
|
|
||||||
|
ResizeMode mResizeMode;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -105,6 +105,42 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</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>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -211,7 +247,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QgsCollapsibleGroupBoxBasic" name="groupBox">
|
<widget class="QgsCollapsibleGroupBoxBasic" name="mRotationGroupBox">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Image rotation</string>
|
<string>Image rotation</string>
|
||||||
</property>
|
</property>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user