[QGIS Commit] r11894 - in trunk/qgis/src: app/composer core/composer ui

svn_qgis at osgeo.org svn_qgis at osgeo.org
Mon Nov 2 12:26:18 EST 2009


Author: mhugent
Date: 2009-11-02 12:26:17 -0500 (Mon, 02 Nov 2009)
New Revision: 11894

Modified:
   trunk/qgis/src/app/composer/qgscomposerpicturewidget.cpp
   trunk/qgis/src/app/composer/qgscomposerpicturewidget.h
   trunk/qgis/src/core/composer/qgscomposermap.cpp
   trunk/qgis/src/core/composer/qgscomposermap.h
   trunk/qgis/src/core/composer/qgscomposerpicture.cpp
   trunk/qgis/src/core/composer/qgscomposerpicture.h
   trunk/qgis/src/ui/qgscomposerpicturewidgetbase.ui
Log:
[FEATURE]: Improve the rotation of composer pictures and added the possibility to synchronize composer map rotation and composer picture rotation (e.g. usefull for north arrows)

Modified: trunk/qgis/src/app/composer/qgscomposerpicturewidget.cpp
===================================================================
--- trunk/qgis/src/app/composer/qgscomposerpicturewidget.cpp	2009-11-02 13:58:09 UTC (rev 11893)
+++ trunk/qgis/src/app/composer/qgscomposerpicturewidget.cpp	2009-11-02 17:26:17 UTC (rev 11894)
@@ -17,6 +17,7 @@
 
 #include "qgscomposerpicturewidget.h"
 #include "qgsapplication.h"
+#include "qgscomposermap.h"
 #include "qgscomposerpicture.h"
 #include "qgscomposeritemwidget.h"
 #include <QDoubleValidator>
@@ -34,18 +35,16 @@
 
   //add widget for general composer item properties
   QgsComposerItemWidget* itemPropertiesWidget = new QgsComposerItemWidget( this, picture );
-  gridLayout->addWidget( itemPropertiesWidget, 6, 0, 1, 4 );
+  gridLayout->addWidget( itemPropertiesWidget, 8, 0, 1, 4 );
 
   mWidthLineEdit->setValidator( new QDoubleValidator( this ) );
   mHeightLineEdit->setValidator( new QDoubleValidator( this ) );
-
   setGuiElementValues();
 
   mPreviewListWidget->setIconSize( QSize( 30, 30 ) );
 
   //add preview icons
   addStandardDirectoriesToPreview();
-
   connect( mPicture, SIGNAL( settingsChanged() ), this, SLOT( setGuiElementValues() ) );
 }
 
@@ -198,6 +197,118 @@
   }
 }
 
+void QgsComposerPictureWidget::on_mRotationFromComposerMapCheckBox_stateChanged( int state )
+{
+  if ( !mPicture )
+  {
+    return;
+  }
+
+  if ( state == Qt::Unchecked )
+  {
+    mPicture->setRotationMap( -1 );
+    mRotationSpinBox->setEnabled( true );
+    mComposerMapComboBox->setEnabled( false );
+  }
+  else
+  {
+    int currentItemIndex = mComposerMapComboBox->currentIndex();
+    if ( currentItemIndex == -1 )
+    {
+      return;
+    }
+    int composerId = mComposerMapComboBox->itemData( currentItemIndex, Qt::UserRole ).toInt();
+    mPicture->setRotationMap( composerId );
+    mRotationSpinBox->setEnabled( false );
+    mComposerMapComboBox->setEnabled( true );
+  }
+}
+
+void QgsComposerPictureWidget::showEvent( QShowEvent * event )
+{
+  refreshMapComboBox();
+  QWidget::showEvent( event );
+}
+
+void QgsComposerPictureWidget::on_mComposerMapComboBox_activated( const QString & text )
+{
+  if ( !mPicture || text.isEmpty() || !mPicture->useRotationMap() )
+  {
+    return;
+  }
+
+  //get composition
+  const QgsComposition* composition = mPicture->composition();
+  if ( !composition )
+  {
+    return;
+  }
+
+  //extract id
+  int id;
+  bool conversionOk;
+  QStringList textSplit = text.split( " " );
+  if ( textSplit.size() < 1 )
+  {
+    return;
+  }
+
+  QString idString = textSplit.at( textSplit.size() - 1 );
+  id = idString.toInt( &conversionOk );
+
+  if ( !conversionOk )
+  {
+    return;
+  }
+
+  const QgsComposerMap* composerMap = composition->getComposerMapById( id );
+  if ( !composerMap )
+  {
+    return;
+  }
+  mPicture->setRotationMap( id );
+  mPicture->update();
+}
+
+void QgsComposerPictureWidget::refreshMapComboBox()
+{
+  mComposerMapComboBox->blockSignals( true );
+  //save the current entry in case it is still present after refresh
+  QString saveCurrentComboText = mComposerMapComboBox->currentText();
+
+  mComposerMapComboBox->clear();
+
+  if ( mPicture )
+  {
+    //insert available maps into mMapComboBox
+    const QgsComposition* composition = mPicture->composition();
+    if ( composition )
+    {
+      QList<const QgsComposerMap*> availableMaps = composition->composerMapItems();
+      QList<const QgsComposerMap*>::const_iterator mapItemIt = availableMaps.constBegin();
+      for ( ; mapItemIt != availableMaps.constEnd(); ++mapItemIt )
+      {
+        mComposerMapComboBox->addItem( tr( "Map %1" ).arg(( *mapItemIt )->id() ), ( *mapItemIt )->id() );
+      }
+    }
+  }
+
+  if ( !saveCurrentComboText.isEmpty() )
+  {
+    if ( mComposerMapComboBox->findText( saveCurrentComboText ) == -1 )
+    {
+      //the former entry is no longer present. Inform the scalebar about the changed composer map
+      on_mComposerMapComboBox_activated( mComposerMapComboBox->currentText() );
+    }
+    else
+    {
+      //the former entry is still present. Make it the current entry again
+      mComposerMapComboBox->setCurrentIndex( mComposerMapComboBox->findText( saveCurrentComboText ) );
+    }
+  }
+  mComposerMapComboBox->blockSignals( false );
+}
+
 void QgsComposerPictureWidget::setGuiElementValues()
 {
   //set initial gui values
@@ -207,6 +318,8 @@
     mHeightLineEdit->blockSignals( true );
     mRotationSpinBox->blockSignals( true );
     mPictureLineEdit->blockSignals( true );
+    mComposerMapComboBox->blockSignals( true );
+    mRotationFromComposerMapCheckBox->blockSignals( true );
 
     mPictureLineEdit->setText( mPicture->pictureFile() );
     QRectF pictureRect = mPicture->rect();
@@ -214,10 +327,34 @@
     mHeightLineEdit->setText( QString::number( pictureRect.height() ) );
     mRotationSpinBox->setValue( mPicture->rotation() );
 
+    refreshMapComboBox();
+
+    if ( mPicture->useRotationMap() )
+    {
+      mRotationFromComposerMapCheckBox->setCheckState( Qt::Checked );
+      mRotationSpinBox->setEnabled( false );
+      mComposerMapComboBox->setEnabled( true );
+      QString mapText = tr( "Map %1" ).arg( mPicture->rotationMap() );
+      int itemId = mComposerMapComboBox->findText( mapText );
+      if ( itemId >= 0 )
+      {
+        mComposerMapComboBox->setCurrentIndex( itemId );
+      }
+    }
+    else
+    {
+      mRotationFromComposerMapCheckBox->setCheckState( Qt::Unchecked );
+      mRotationSpinBox->setEnabled( true );
+      mComposerMapComboBox->setEnabled( false );
+    }
+
+
+    mRotationFromComposerMapCheckBox->blockSignals( false );
     mWidthLineEdit->blockSignals( false );
     mHeightLineEdit->blockSignals( false );
     mRotationSpinBox->blockSignals( false );
     mPictureLineEdit->blockSignals( false );
+    mComposerMapComboBox->blockSignals( false );
   }
 }
 
@@ -302,7 +439,8 @@
 {
   //list all directories in $prefix/share/qgis/svg
   QStringList svgPaths = QgsApplication::svgPaths();
-  for(int i=0; i<svgPaths.size(); i++) {
+  for ( int i = 0; i < svgPaths.size(); i++ )
+  {
     QDir svgDirectory( svgPaths[i] );
     if ( !svgDirectory.exists() || !svgDirectory.isReadable() )
     {
@@ -315,7 +453,7 @@
     {
       if ( addDirectoryToPreview( dirIt->absoluteFilePath() ) == 0 )
       {
-	mSearchDirectoriesComboBox->addItem( dirIt->absoluteFilePath() );
+        mSearchDirectoriesComboBox->addItem( dirIt->absoluteFilePath() );
       }
     }
   }

Modified: trunk/qgis/src/app/composer/qgscomposerpicturewidget.h
===================================================================
--- trunk/qgis/src/app/composer/qgscomposerpicturewidget.h	2009-11-02 13:58:09 UTC (rev 11893)
+++ trunk/qgis/src/app/composer/qgscomposerpicturewidget.h	2009-11-02 17:26:17 UTC (rev 11894)
@@ -42,9 +42,15 @@
     void on_mPreviewListWidget_currentItemChanged( QListWidgetItem* current, QListWidgetItem* previous );
     void on_mAddDirectoryButton_clicked();
     void on_mRemoveDirectoryButton_clicked();
+    void on_mRotationFromComposerMapCheckBox_stateChanged( int state );
+    void on_mComposerMapComboBox_activated( const QString & text );
+
     /**Sets the GUI elements to the values of mPicture*/
     void setGuiElementValues();
 
+  protected:
+    void showEvent( QShowEvent * event );
+
   private:
     QgsComposerPicture* mPicture;
     /**Add the icons of a directory to the preview. Returns 0 in case of success*/
@@ -55,6 +61,8 @@
     bool testSvgFile( const QString& filename ) const;
     /**Tests if a file is a valid pixel format*/
     bool testImageFile( const QString& filename ) const;
+    /**Updates the map combo box with the current composer map ids*/
+    void refreshMapComboBox();
 };
 
 #endif

Modified: trunk/qgis/src/core/composer/qgscomposermap.cpp
===================================================================
--- trunk/qgis/src/core/composer/qgscomposermap.cpp	2009-11-02 13:58:09 UTC (rev 11893)
+++ trunk/qgis/src/core/composer/qgscomposermap.cpp	2009-11-02 17:26:17 UTC (rev 11894)
@@ -505,6 +505,12 @@
   mYOffset = yOffset;
 }
 
+void QgsComposerMap::setRotation( double r )
+{
+  mRotation = r;
+  emit rotationChanged( r );
+}
+
 bool QgsComposerMap::containsWMSLayer() const
 {
   if ( !mMapRenderer )

Modified: trunk/qgis/src/core/composer/qgscomposermap.h
===================================================================
--- trunk/qgis/src/core/composer/qgscomposermap.h	2009-11-02 13:58:09 UTC (rev 11893)
+++ trunk/qgis/src/core/composer/qgscomposermap.h	2009-11-02 17:26:17 UTC (rev 11894)
@@ -241,7 +241,7 @@
 
     /**Sets the rotation of the map content
     @note this function was added in version 1.4*/
-    void setRotation( double r ) { mRotation = r; }
+    void setRotation( double r );
     double rotation() const { return mRotation; }
 
     /**Sets length of the cros segments (if grid style is cross)
@@ -259,6 +259,8 @@
   signals:
     /**Is emitted when width/height is changed as a result of user interaction*/
     void extentChanged();
+    /**Is emitted on rotation change to notify north arrow pictures*/
+    void rotationChanged( double newRotation );
 
   private:
 

Modified: trunk/qgis/src/core/composer/qgscomposerpicture.cpp
===================================================================
--- trunk/qgis/src/core/composer/qgscomposerpicture.cpp	2009-11-02 13:58:09 UTC (rev 11893)
+++ trunk/qgis/src/core/composer/qgscomposerpicture.cpp	2009-11-02 17:26:17 UTC (rev 11894)
@@ -17,6 +17,7 @@
 /* $Id$ */
 
 #include "qgscomposerpicture.h"
+#include "qgscomposermap.h"
 #include "qgsproject.h"
 #include <QDomDocument>
 #include <QDomElement>
@@ -25,11 +26,18 @@
 #include <QPainter>
 #include <QSvgRenderer>
 
-QgsComposerPicture::QgsComposerPicture( QgsComposition *composition ): QObject( 0 ), QgsComposerItem( composition ), mRotation( 0.0 ), mMode( Unknown ), mSvgCacheUpToDate( false ), mCachedDpi( 0 )
+#ifndef Q_OS_MACX
+#include <cmath>
+#else
+#include <math.h>
+#endif
+
+QgsComposerPicture::QgsComposerPicture( QgsComposition *composition ): QObject( 0 ), QgsComposerItem( composition ), mRotation( 0.0 ), mMode( Unknown ), \
+    mSvgCacheUpToDate( false ), mCachedDpi( 0 ), mRotationMap( 0 )
 {
 }
 
-QgsComposerPicture::QgsComposerPicture(): QgsComposerItem( 0 ), mRotation( 0.0 ), mMode( Unknown ), mSvgCacheUpToDate( false )
+QgsComposerPicture::QgsComposerPicture(): QgsComposerItem( 0 ), mRotation( 0.0 ), mMode( Unknown ), mSvgCacheUpToDate( false ), mRotationMap( 0 )
 {
 
 }
@@ -46,52 +54,61 @@
     return;
   }
 
-  if ( mMode == SVG )
+  drawBackground( painter );
+
+  int newDpi = ( painter->device()->logicalDpiX() + painter->device()->logicalDpiY() ) / 2;
+  if ( mMode != Unknown )
   {
-    int newDpi = ( painter->device()->logicalDpiX() + painter->device()->logicalDpiY() ) / 2;
-    if ( newDpi != mCachedDpi )
+    double rectPixelWidth = rect().width() * newDpi / 25.4;
+    double rectPixelHeight = rect().height() * newDpi / 25.4;
+    QRectF boundRect;
+    if ( mMode == SVG )
     {
-      mSvgCacheUpToDate = false;
-      mCachedDpi = newDpi;
-      mImage = QImage( rect().width() * newDpi / 25.4, rect().height() * newDpi / 25.4, QImage::Format_ARGB32 );
+      boundRect = boundedSVGRect( rectPixelWidth, rectPixelHeight );
     }
-
-    if ( !mSvgCacheUpToDate )
+    else if ( mMode == RASTER )
     {
-      updateImageFromSvg();
+      boundRect = boundedImageRect( rectPixelWidth, rectPixelHeight );
     }
-  }
 
-  painter->save();
-  painter->rotate( mRotation );
-  drawBackground( painter );
+    double boundRectWidthMM = boundRect.width() / newDpi * 25.4;
+    double boundRectHeightMM = boundRect.height() / newDpi * 25.4;
+    double unrotatedBoundImageWidth = boundRect.width();
+    double unrotatedBoundImageHeight = boundRect.height();
+    double unrotatedBoundImageWidthMM = unrotatedBoundImageWidth / newDpi * 25.4;
+    double unrotatedBoundImageHeightMM = unrotatedBoundImageHeight / newDpi * 25.4;
+    double rotatedBoundImageWidth = boundRect.width();
+    double rotatedBoundImageHeight = boundRect.height();
+    imageSizeConsideringRotation( rotatedBoundImageWidth, rotatedBoundImageHeight );
+    double rotatedBoundImageWidthMM = rotatedBoundImageWidth / newDpi * 25.4;
+    double rotatedBoundImageHeightMM = rotatedBoundImageHeight / newDpi * 25.4;
 
-  if ( mMode != Unknown )
-  {
-    double widthRatio = mImage.width() / rect().width();
-    double heightRatio = mImage.height() / rect().height();
-    double targetWidth, targetHeight;
-    if ( widthRatio > heightRatio )
+    if ( mMode == SVG )
     {
-      targetWidth = rect().width();
-      targetHeight = mImage.height() / widthRatio;
+      if ( !mSvgCacheUpToDate )
+      {
+        mImage = QImage( rotatedBoundImageWidth, rotatedBoundImageHeight, QImage::Format_ARGB32 );
+        updateImageFromSvg();
+      }
     }
-    else
-    {
-      targetHeight = rect().height();
-      targetWidth = mImage.width() / heightRatio;
-    }
-    painter->drawImage( QRectF( 0, 0, targetWidth, targetHeight ), mImage, QRectF( 0, 0, mImage.width(), mImage.height() ) );
+
+    painter->save();
+    painter->translate( boundRectWidthMM / 2.0, boundRectHeightMM / 2.0 );
+    painter->rotate( mRotation );
+    painter->translate( -rotatedBoundImageWidthMM / 2.0, -rotatedBoundImageHeightMM / 2.0 );
+    painter->drawImage( QRectF( 0, 0, rotatedBoundImageWidthMM,  rotatedBoundImageHeightMM ), mImage, QRectF( 0, 0, mImage.width(), mImage.height() ) );
+
+    painter->restore();
   }
 
+  mCachedDpi = newDpi;
+
   //frame and selection boxes
   drawFrame( painter );
   if ( isSelected() )
   {
     drawSelectionBoxes( painter );
   }
-
-  painter->restore();
 }
 
 void QgsComposerPicture::setPictureFile( const QString& path )
@@ -102,9 +119,6 @@
     mMode = Unknown;
   }
 
-  //mImage = QImage(mImage.width(), mImage.height(), QImage::Format_ARGB32 );
-  //setSceneRect
-
   QFileInfo sourceFileInfo( mSourceFile );
   QString sourceFileSuffix = sourceFileInfo.suffix();
   if ( sourceFileSuffix.compare( "svg", Qt::CaseInsensitive ) == 0 )
@@ -145,43 +159,124 @@
   emit settingsChanged();
 }
 
+QRectF QgsComposerPicture::boundedImageRect( double deviceWidth, double deviceHeight )
+{
+  double imageToDeviceRatio;
+  if ( mImage.width() / deviceWidth > mImage.height() / deviceHeight )
+  {
+    imageToDeviceRatio =  deviceWidth / mImage.width();
+    double height = imageToDeviceRatio * mImage.height();
+    return QRectF( 0, 0, deviceWidth, height );
+  }
+  else
+  {
+    imageToDeviceRatio = deviceHeight / mImage.height();
+    double width = imageToDeviceRatio * mImage.width();
+    return QRectF( 0, 0, width, deviceHeight );
+  }
+}
+
+QRectF QgsComposerPicture::boundedSVGRect( double deviceWidth, double deviceHeight )
+{
+  double imageToSvgRatio;
+  if ( deviceWidth / mDefaultSvgSize.width() < deviceHeight / mDefaultSvgSize.height() )
+  {
+    imageToSvgRatio = deviceWidth / mDefaultSvgSize.width();
+    double height = mDefaultSvgSize.height() * imageToSvgRatio;
+    return QRectF( 0, 0, deviceWidth, height );
+  }
+  else
+  {
+    imageToSvgRatio = deviceHeight / mDefaultSvgSize.height();
+    double width = mDefaultSvgSize.width() * imageToSvgRatio;
+    return QRectF( 0, 0, width, deviceHeight );
+  }
+}
+
 void QgsComposerPicture::updateImageFromSvg()
 {
   mImage.fill( 0 );
   QPainter p( &mImage );
   p.setRenderHints( QPainter::Antialiasing | QPainter::TextAntialiasing, true );
   QSvgRenderer theRenderer( mSourceFile.fileName() );
-  if ( theRenderer.isValid() )
-  {
-    theRenderer.render( &p );
-  }
+  theRenderer.render( &p );
   mSvgCacheUpToDate = true;
 }
 
-void QgsComposerPicture::setSceneRect( const QRectF& rectangle )
+bool QgsComposerPicture::imageSizeConsideringRotation( double& width, double& height ) const
 {
-  mSvgCacheUpToDate = false;
-  if ( mMode == SVG )
+  double x1 = 0;
+  double y1 = 0;
+  double x2 = width;
+  double y2 = 0;
+  double x3 = width;
+  double y3 = height;
+  double x4 = 0;
+  double y4 = height;
+
+  if ( !cornerPointOnRotatedAndScaledRect( x1, y1, width, height ) )
   {
-    //keep aspect ratio
-    double widthRatio = rectangle.width() / mDefaultSvgSize.width();
-    double heightRatio = rectangle.height() / mDefaultSvgSize.height();
+    return false;
+  }
+  if ( !cornerPointOnRotatedAndScaledRect( x2, y2, width, height ) )
+  {
+    return false;
+  }
+  if ( !cornerPointOnRotatedAndScaledRect( x3, y3, width, height ) )
+  {
+    return false;
+  }
+  /*
+  if(!cornerPointOnRotatedAndScaledRect(x4, y4, width, height))
+  {
+    return false;
+  }*/
 
-    double newImageWidth;
-    double newImageHeight;
+  width = sqrt(( x2 - x1 ) * ( x2 - x1 ) + ( y2 - y1 ) * ( y2 - y1 ) );
+  height = sqrt(( x3 - x2 ) * ( x3 - x2 ) + ( y3 - y2 ) * ( y3 - y2 ) );
+  return true;
+}
 
-    if ( widthRatio > heightRatio )
+bool QgsComposerPicture::cornerPointOnRotatedAndScaledRect( double& x, double& y, double width, double height ) const
+{
+  //first rotate point clockwise
+  double rotToRad = mRotation * M_PI / 180.0;
+  QPointF midpoint( width / 2.0, height / 2.0 );
+  double xVector = x - midpoint.x();
+  double yVector = y - midpoint.y();
+  //double xRotated = cos(rotToRad) * xVector + sin(rotToRad) * yVector;
+  //double yRotated = -sin(rotToRad) * xVector + cos(rotToRad) * yVector;
+  double xRotated = cos( rotToRad ) * xVector - sin( rotToRad ) * yVector;
+  double yRotated = sin( rotToRad ) * xVector + cos( rotToRad ) * yVector;
+
+  //create line from midpoint to rotated point
+  QLineF line( midpoint.x(), midpoint.y(), midpoint.x() + xRotated, midpoint.y() + yRotated );
+
+  //intersect with all four borders and return result
+  QList<QLineF> borders;
+  borders << QLineF( 0, 0, width, 0 );
+  borders << QLineF( width, 0, width, height );
+  borders << QLineF( width, height, 0, height );
+  borders << QLineF( 0, height, 0, 0 );
+
+  QList<QLineF>::const_iterator it = borders.constBegin();
+  QPointF intersectionPoint;
+
+  for ( ; it != borders.constEnd(); ++it )
+  {
+    if ( line.intersect( *it, &intersectionPoint ) == QLineF::BoundedIntersection )
     {
-      newImageWidth = rectangle.width() * mCachedDpi / 25.4;
-      newImageHeight = mDefaultSvgSize.height() * widthRatio * mCachedDpi / 25.4;
+      x = intersectionPoint.x();
+      y = intersectionPoint.y();
+      return true;
     }
-    else
-    {
-      newImageHeight = rectangle.height() * mCachedDpi / 25.4;
-      newImageWidth = mDefaultSvgSize.width() * heightRatio * mCachedDpi / 25.4;
-    }
-    mImage = QImage( newImageWidth, newImageHeight, QImage::Format_ARGB32 );
   }
+  return false;
+}
+
+void QgsComposerPicture::setSceneRect( const QRectF& rectangle )
+{
+  mSvgCacheUpToDate = false;
   QgsComposerItem::setSceneRect( rectangle );
   emit settingsChanged();
 }
@@ -196,8 +291,37 @@
   {
     mRotation = rotation;
   }
+  emit settingsChanged();
+  update();
 }
 
+void QgsComposerPicture::setRotationMap( int composerMapId )
+{
+  if ( !mComposition )
+  {
+    return;
+  }
+
+  if ( composerMapId == -1 ) //disable rotation from map
+  {
+    QObject::disconnect( mRotationMap, SIGNAL( rotationChanged( double ) ), this, SLOT( setRotation( double ) ) );
+    mRotationMap = 0;
+  }
+
+  const QgsComposerMap* map = mComposition->getComposerMapById( composerMapId );
+  if ( !map )
+  {
+    return;
+  }
+  if ( mRotationMap )
+  {
+    QObject::disconnect( mRotationMap, SIGNAL( rotationChanged( double ) ), this, SLOT( setRotation( double ) ) );
+  }
+  mRotation = map->rotation();
+  QObject::connect( map, SIGNAL( rotationChanged( double ) ), this, SLOT( setRotation( double ) ) );
+  mRotationMap = map;
+}
+
 QString QgsComposerPicture::pictureFile() const
 {
   return mSourceFile.fileName();
@@ -212,6 +336,15 @@
   QDomElement composerPictureElem = doc.createElement( "ComposerPicture" );
   composerPictureElem.setAttribute( "file", QgsProject::instance()->writePath( mSourceFile.fileName() ) );
   composerPictureElem.setAttribute( "rotation", QString::number( mRotation ) );
+  if ( !mRotationMap )
+  {
+    composerPictureElem.setAttribute( "mapId", -1 );
+  }
+  else
+  {
+    composerPictureElem.setAttribute( "mapId", mRotationMap->id() );
+  }
+
   _writeXML( composerPictureElem, doc );
   elem.appendChild( composerPictureElem );
   return true;
@@ -230,6 +363,7 @@
     _readXML( composerItemList.at( 0 ).toElement(), doc );
   }
 
+
   mSvgCacheUpToDate = false;
   mDefaultSvgSize = QSize( 0, 0 );
   mCachedDpi = 0;
@@ -239,5 +373,34 @@
 
   mRotation = itemElem.attribute( "rotation" ).toDouble();
 
+  //rotation map
+  int rotationMapId = itemElem.attribute( "mapId", "-1" ).toInt();
+  if ( rotationMapId == -1 )
+  {
+    mRotationMap = 0;
+  }
+  else if ( mComposition )
+  {
+
+    if ( mRotationMap )
+    {
+      QObject::disconnect( mRotationMap, SIGNAL( rotationChanged( double ) ), this, SLOT( setRotation( double ) ) );
+    }
+    mRotationMap = mComposition->getComposerMapById( rotationMapId );
+    QObject::connect( mRotationMap, SIGNAL( rotationChanged( double ) ), this, SLOT( setRotation( double ) ) );
+  }
+
   return true;
 }
+
+int QgsComposerPicture::rotationMap() const
+{
+  if ( !mRotationMap )
+  {
+    return -1;
+  }
+  else
+  {
+    return mRotationMap->id();
+  }
+}

Modified: trunk/qgis/src/core/composer/qgscomposerpicture.h
===================================================================
--- trunk/qgis/src/core/composer/qgscomposerpicture.h	2009-11-02 13:58:09 UTC (rev 11893)
+++ trunk/qgis/src/core/composer/qgscomposerpicture.h	2009-11-02 17:26:17 UTC (rev 11894)
@@ -43,8 +43,6 @@
        corresponds to 1 scene size unit*/
     void setSceneRect( const QRectF& rectangle );
 
-    void setRotation( double rotation );
-
     double rotation() const {return mRotation;}
 
     /** stores state in Dom node
@@ -58,6 +56,17 @@
       */
     bool readXML( const QDomElement& itemElem, const QDomDocument& doc );
 
+    /**Sets the map object for rotation (by id). A value of -1 disables the map rotation*/
+    void setRotationMap( int composerMapId );
+    /**Returns the id of the rotation map*/
+    int rotationMap() const;
+    /**True if the rotation is taken from a map item*/
+    bool useRotationMap() const {return mRotationMap;}
+
+  public slots:
+
+    void setRotation( double rotation );
+
   private:
 
     enum Mode //SVG or raster graphic format
@@ -69,8 +78,19 @@
 
     //default constructor is forbidden
     QgsComposerPicture();
-    /**Updates content of current image using svg generator*/
+    /**Calculates bounding rect for svg file (mSourcefile) such that aspect ratio is correct*/
+    QRectF boundedSVGRect( double deviceWidth, double deviceHeight );
+    /**Calculates bounding rect for image such that aspect ratio is correct*/
+    QRectF boundedImageRect( double deviceWidth, double deviceHeight );
+
+    /**Updates content of mImage using svg generator
+    @param out: boundWidth width of mImage that is used by the svg renderer. May different from mImage.width() to preserve aspect ratio
+    @param out: boundHeight height of mImage that is used by the svg renderer*/
     void updateImageFromSvg();
+    /**Calculates width and hight of the picture (in mm) such that it fits into the item frame with the given rotation*/
+    bool imageSizeConsideringRotation( double& width, double& height ) const;
+    /**Calculates corner point after rotation and scaling*/
+    bool cornerPointOnRotatedAndScaledRect( double& x, double& y, double width, double height ) const;
 
     QImage mImage;
     double mRotation;
@@ -80,7 +100,10 @@
     bool mSvgCacheUpToDate;
     int mCachedDpi; //store dpis for which the svg cache is valid
     QSize mDefaultSvgSize;
+    /**Map that sets the rotation (or 0 if this picture uses map independent rotation)*/
+    const QgsComposerMap* mRotationMap;
 
+
   signals:
     /**Tell the configuration widget that the settings need to be updated*/
     void settingsChanged();

Modified: trunk/qgis/src/ui/qgscomposerpicturewidgetbase.ui
===================================================================
--- trunk/qgis/src/ui/qgscomposerpicturewidgetbase.ui	2009-11-02 13:58:09 UTC (rev 11893)
+++ trunk/qgis/src/ui/qgscomposerpicturewidgetbase.ui	2009-11-02 17:26:17 UTC (rev 11894)
@@ -1,52 +1,53 @@
-<ui version="4.0" >
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
  <class>QgsComposerPictureWidgetBase</class>
- <widget class="QWidget" name="QgsComposerPictureWidgetBase" >
-  <property name="geometry" >
+ <widget class="QWidget" name="QgsComposerPictureWidgetBase">
+  <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>342</width>
+    <width>299</width>
     <height>613</height>
    </rect>
   </property>
-  <property name="sizePolicy" >
-   <sizepolicy vsizetype="Expanding" hsizetype="Expanding" >
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
     <horstretch>0</horstretch>
     <verstretch>0</verstretch>
    </sizepolicy>
   </property>
-  <property name="windowTitle" >
+  <property name="windowTitle">
    <string>Picture Options</string>
   </property>
-  <layout class="QGridLayout" >
-   <item row="0" column="0" colspan="4" >
-    <widget class="QGroupBox" name="mSearchDirectoriesGroupBox" >
-     <property name="sizePolicy" >
-      <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="0" column="0" colspan="2">
+    <widget class="QGroupBox" name="mSearchDirectoriesGroupBox">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
        <horstretch>0</horstretch>
        <verstretch>0</verstretch>
       </sizepolicy>
      </property>
-     <property name="title" >
+     <property name="title">
       <string>Search directories</string>
      </property>
-     <layout class="QGridLayout" >
-      <item row="0" column="0" colspan="3" >
-       <widget class="QComboBox" name="mSearchDirectoriesComboBox" >
-        <property name="sizePolicy" >
-         <sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
+     <layout class="QGridLayout">
+      <item row="0" column="0" colspan="3">
+       <widget class="QComboBox" name="mSearchDirectoriesComboBox">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
           <horstretch>0</horstretch>
           <verstretch>0</verstretch>
          </sizepolicy>
         </property>
        </widget>
       </item>
-      <item row="1" column="0" >
+      <item row="1" column="0">
        <spacer>
-        <property name="orientation" >
+        <property name="orientation">
          <enum>Qt::Horizontal</enum>
         </property>
-        <property name="sizeHint" >
+        <property name="sizeHint" stdset="0">
          <size>
           <width>101</width>
           <height>20</height>
@@ -54,16 +55,16 @@
         </property>
        </spacer>
       </item>
-      <item row="1" column="1" >
-       <widget class="QPushButton" name="mAddDirectoryButton" >
-        <property name="text" >
+      <item row="1" column="1">
+       <widget class="QPushButton" name="mAddDirectoryButton">
+        <property name="text">
          <string>Add...</string>
         </property>
        </widget>
       </item>
-      <item row="1" column="2" >
-       <widget class="QPushButton" name="mRemoveDirectoryButton" >
-        <property name="text" >
+      <item row="1" column="2">
+       <widget class="QPushButton" name="mRemoveDirectoryButton">
+        <property name="text">
          <string>Remove</string>
         </property>
        </widget>
@@ -71,45 +72,45 @@
      </layout>
     </widget>
    </item>
-   <item row="1" column="0" colspan="4" >
-    <widget class="QGroupBox" name="mPreviewGroupBox" >
-     <property name="sizePolicy" >
-      <sizepolicy vsizetype="Expanding" hsizetype="Expanding" >
+   <item row="1" column="0" colspan="2">
+    <widget class="QGroupBox" name="mPreviewGroupBox">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
        <horstretch>0</horstretch>
        <verstretch>0</verstretch>
       </sizepolicy>
      </property>
-     <property name="title" >
+     <property name="title">
       <string>Preview</string>
      </property>
-     <layout class="QGridLayout" >
-      <item row="0" column="0" >
-       <widget class="QListWidget" name="mPreviewListWidget" >
-        <property name="showDropIndicator" stdset="0" >
+     <layout class="QGridLayout">
+      <item row="0" column="0">
+       <widget class="QListWidget" name="mPreviewListWidget">
+        <property name="showDropIndicator" stdset="0">
          <bool>false</bool>
         </property>
-        <property name="dragDropMode" >
+        <property name="dragDropMode">
          <enum>QAbstractItemView::DragDrop</enum>
         </property>
-        <property name="movement" >
+        <property name="movement">
          <enum>QListView::Free</enum>
         </property>
-        <property name="flow" >
+        <property name="flow">
          <enum>QListView::LeftToRight</enum>
         </property>
-        <property name="isWrapping" stdset="0" >
+        <property name="isWrapping" stdset="0">
          <bool>true</bool>
         </property>
-        <property name="gridSize" >
+        <property name="gridSize">
          <size>
           <width>30</width>
           <height>30</height>
          </size>
         </property>
-        <property name="viewMode" >
+        <property name="viewMode">
          <enum>QListView::IconMode</enum>
         </property>
-        <property name="wordWrap" >
+        <property name="wordWrap">
          <bool>true</bool>
         </property>
        </widget>
@@ -117,107 +118,121 @@
      </layout>
     </widget>
    </item>
-   <item row="2" column="0" >
-    <widget class="QLabel" name="label" >
-     <property name="text" >
-      <string>Load</string>
-     </property>
-     <property name="buddy" >
-      <cstring>mPictureLineEdit</cstring>
-     </property>
-    </widget>
+   <item row="2" column="0" colspan="2">
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <item>
+      <widget class="QLabel" name="label">
+       <property name="text">
+        <string>Load</string>
+       </property>
+       <property name="buddy">
+        <cstring>mPictureLineEdit</cstring>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QLineEdit" name="mPictureLineEdit"/>
+     </item>
+     <item>
+      <widget class="QPushButton" name="mPictureBrowseButton">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="maximumSize">
+        <size>
+         <width>150</width>
+         <height>32767</height>
+        </size>
+       </property>
+       <property name="text">
+        <string>...</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
    </item>
-   <item row="2" column="1" colspan="2" >
-    <widget class="QLineEdit" name="mPictureLineEdit" />
-   </item>
-   <item row="2" column="3" >
-    <widget class="QPushButton" name="mPictureBrowseButton" >
-     <property name="sizePolicy" >
-      <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+   <item row="3" column="0">
+    <widget class="QLabel" name="textLabel3">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
        <horstretch>0</horstretch>
        <verstretch>0</verstretch>
       </sizepolicy>
      </property>
-     <property name="maximumSize" >
-      <size>
-       <width>150</width>
-       <height>32767</height>
-      </size>
-     </property>
-     <property name="text" >
-      <string>...</string>
-     </property>
-    </widget>
-   </item>
-   <item row="3" column="0" >
-    <widget class="QLabel" name="textLabel3" >
-     <property name="sizePolicy" >
-      <sizepolicy vsizetype="Preferred" hsizetype="Minimum" >
-       <horstretch>0</horstretch>
-       <verstretch>0</verstretch>
-      </sizepolicy>
-     </property>
-     <property name="text" >
+     <property name="text">
       <string>Width</string>
      </property>
-     <property name="wordWrap" >
+     <property name="wordWrap">
       <bool>true</bool>
      </property>
-     <property name="buddy" >
+     <property name="buddy">
       <cstring>mWidthLineEdit</cstring>
      </property>
     </widget>
    </item>
-   <item row="3" column="1" colspan="3" >
-    <widget class="QLineEdit" name="mWidthLineEdit" />
+   <item row="3" column="1">
+    <widget class="QLineEdit" name="mWidthLineEdit"/>
    </item>
-   <item row="4" column="0" >
-    <widget class="QLabel" name="textLabel4" >
-     <property name="sizePolicy" >
-      <sizepolicy vsizetype="Preferred" hsizetype="Minimum" >
+   <item row="4" column="0">
+    <widget class="QLabel" name="textLabel4">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
        <horstretch>0</horstretch>
        <verstretch>0</verstretch>
       </sizepolicy>
      </property>
-     <property name="text" >
+     <property name="text">
       <string>Height</string>
      </property>
-     <property name="wordWrap" >
+     <property name="wordWrap">
       <bool>true</bool>
      </property>
-     <property name="buddy" >
+     <property name="buddy">
       <cstring>mHeightLineEdit</cstring>
      </property>
     </widget>
    </item>
-   <item row="4" column="1" colspan="3" >
-    <widget class="QLineEdit" name="mHeightLineEdit" />
+   <item row="4" column="1">
+    <widget class="QLineEdit" name="mHeightLineEdit"/>
    </item>
-   <item row="5" column="0" colspan="2" >
-    <widget class="QLabel" name="mRotationLabel" >
-     <property name="sizePolicy" >
-      <sizepolicy vsizetype="Preferred" hsizetype="Minimum" >
+   <item row="5" column="0">
+    <widget class="QLabel" name="mRotationLabel">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
        <horstretch>0</horstretch>
        <verstretch>0</verstretch>
       </sizepolicy>
      </property>
-     <property name="text" >
+     <property name="text">
       <string>Rotation</string>
      </property>
-     <property name="wordWrap" >
+     <property name="wordWrap">
       <bool>true</bool>
      </property>
-     <property name="buddy" >
+     <property name="buddy">
       <cstring>mRotationSpinBox</cstring>
      </property>
     </widget>
    </item>
-   <item row="5" column="2" colspan="2" >
-    <widget class="QDoubleSpinBox" name="mRotationSpinBox" />
+   <item row="5" column="1">
+    <widget class="QDoubleSpinBox" name="mRotationSpinBox"/>
    </item>
+   <item row="6" column="0" colspan="2">
+    <widget class="QCheckBox" name="mRotationFromComposerMapCheckBox">
+     <property name="text">
+      <string>Take rotation from composer map</string>
+     </property>
+    </widget>
+   </item>
+   <item row="7" column="0" colspan="2">
+    <widget class="QComboBox" name="mComposerMapComboBox"/>
+   </item>
   </layout>
  </widget>
- <layoutdefault spacing="6" margin="11" />
+ <layoutdefault spacing="6" margin="11"/>
  <tabstops>
   <tabstop>mSearchDirectoriesComboBox</tabstop>
   <tabstop>mAddDirectoryButton</tabstop>



More information about the QGIS-commit mailing list