349 changes: 291 additions & 58 deletions src/app/composer/qgscomposermapwidget.cpp

Large diffs are not rendered by default.

34 changes: 30 additions & 4 deletions src/app/composer/qgscomposermapwidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@
#define QGSCOMPOSERMAPWIDGET_H

#include "ui_qgscomposermapwidgetbase.h"

class QgsComposerMap;
#include "qgscomposermap.h"

/** \ingroup MapComposer
* Input widget for the configuration of QgsComposerMap
Expand All @@ -44,6 +43,8 @@ class QgsComposerMapWidget: public QWidget, private Ui::QgsComposerMapWidgetBase
void on_mUpdatePreviewButton_clicked();
void on_mKeepLayerListCheckBox_stateChanged( int state );
void on_mDrawCanvasItemsCheckBox_stateChanged( int state );
void on_mOverviewFrameMapComboBox_currentIndexChanged( const QString& text );
void on_mOverviewFrameStyleButton_clicked();

void on_mXMinLineEdit_editingFinished();
void on_mXMaxLineEdit_editingFinished();
Expand All @@ -61,11 +62,25 @@ class QgsComposerMapWidget: public QWidget, private Ui::QgsComposerMapWidgetBase
void on_mCrossWidthSpinBox_valueChanged( double d );
void on_mAnnotationFontButton_clicked();
void on_mDistanceToMapFrameSpinBox_valueChanged( double d );
void on_mAnnotationPositionComboBox_currentIndexChanged( const QString& text );

//annotation position
void on_mAnnotationPositionLeftComboBox_currentIndexChanged( const QString& text );
void on_mAnnotationPositionRightComboBox_currentIndexChanged( const QString& text );
void on_mAnnotationPositionTopComboBox_currentIndexChanged( const QString& text );
void on_mAnnotationPositionBottomComboBox_currentIndexChanged( const QString& text );

//annotation direction
void on_mAnnotationDirectionComboBoxLeft_currentIndexChanged( const QString& text );
void on_mAnnotationDirectionComboBoxRight_currentIndexChanged( const QString& text );
void on_mAnnotationDirectionComboBoxTop_currentIndexChanged( const QString& text );
void on_mAnnotationDirectionComboBoxBottom_currentIndexChanged( const QString& text );

void on_mDrawAnnotationCheckBox_stateChanged( int state );
void on_mAnnotationDirectionComboBox_currentIndexChanged( const QString& text );
void on_mCoordinatePrecisionSpinBox_valueChanged( int value );

void on_mFrameStyleComboBox_currentIndexChanged( const QString& text );
void on_mFrameWidthSpinBox_valueChanged( double d );

private slots:

/**Sets the GUI elements to the values of mPicture*/
Expand All @@ -82,6 +97,17 @@ class QgsComposerMapWidget: public QWidget, private Ui::QgsComposerMapWidgetBase

/**Blocks / unblocks the signals of all GUI elements*/
void blockAllSignals( bool b );

void handleChangedAnnotationPosition( QgsComposerMap::Border border, const QString& text );
void handleChangedAnnotationDirection( QgsComposerMap::Border border, const QString& text );

void insertAnnotationPositionEntries( QComboBox* c );
void insertAnnotationDirectionEntries( QComboBox* c );

void initAnnotationPositionBox( QComboBox* c, QgsComposerMap::GridAnnotationPosition pos );
void initAnnotationDirectionBox( QComboBox* c, QgsComposerMap::GridAnnotationDirection dir );

void updateOverviewSymbolMarker();
};

#endif
11 changes: 4 additions & 7 deletions src/app/qgisapp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3192,7 +3192,7 @@ bool QgisApp::fileSave()
lastUsedDir + "/" + QgsProject::instance()->title(),
tr( "QGis files" ) + " (*.qgs *.QGS)" );
if ( path.isEmpty() )
return true;
return false;

QFileInfo fullPath( path );

Expand Down Expand Up @@ -3276,10 +3276,6 @@ void QgisApp::fileSaveAs()
} // QgisApp::fileSaveAs






// Open the project file corresponding to the
// path at the given index in mRecentProjectPaths
void QgisApp::openProject( QAction *action )
Expand All @@ -3294,15 +3290,16 @@ void QgisApp::openProject( QAction *action )
if ( saveDirty() )
{
addProject( debugme );

}

//set the projections enabled icon in the status bar
int myProjectionEnabledFlag =
QgsProject::instance()->readNumEntry( "SpatialRefSys", "/ProjectionsEnabled", 0 );
mMapCanvas->mapRenderer()->setProjectionsEnabled( myProjectionEnabledFlag );

} // QgisApp::openProject


/**
Open the specified project file; prompt to save previous project if necessary.
Used to process a commandline argument or OpenDocument AppleEvent.
Expand All @@ -3315,7 +3312,7 @@ void QgisApp::openProject( const QString & fileName )
// error handling and reporting is in addProject() function
addProject( fileName );
}
return ;
return;
}


Expand Down
24 changes: 22 additions & 2 deletions src/app/qgsattributedialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -290,9 +290,29 @@ QgsAttributeDialog::QgsAttributeDialog( QgsVectorLayer *vl, QgsFeature *thepFeat
}

mFormNr = smFormCounter++;
QgsPythonRunner::run( QString( "_qgis_featureform_%1 = wrapinstance( %2, QtGui.QDialog )" ).arg( mFormNr ).arg(( unsigned long ) mDialog ) );

QString expr = QString( "%1(_qgis_featureform_%2,'%3',%4)" ).arg( vl->editFormInit() ).arg( mFormNr ).arg( vl->id() ).arg( mFeature->id() );
QString form = QString( "_qgis_featureform_%1 = wrapinstance( %2, QtGui.QDialog )" )
.arg( mFormNr )
.arg(( unsigned long ) mDialog );

QString layer = QString( "_qgis_layer_%1 = wrapinstance( %2, qgis.core.QgsVectorLayer )" )
.arg( vl->id() )
.arg(( unsigned long ) vl );

QString feature = QString( "_qgis_feature_%1 = wrapinstance( %2, qgis.core.QgsFeature )" )
.arg( mFeature->id() )
.arg(( unsigned long ) mFeature );

QgsPythonRunner::run( form );
QgsPythonRunner::run( feature );
QgsPythonRunner::run( layer );

QString expr = QString( "%1(_qgis_featureform_%2, _qgis_layer_%3, _qgis_feature_%4)" )
.arg( vl->editFormInit() )
.arg( mFormNr )
.arg( vl->id() )
.arg( mFeature->id() );

QgsDebugMsg( QString( "running featureForm init: %1" ).arg( expr ) );
QgsPythonRunner::run( expr );
}
Expand Down
218 changes: 107 additions & 111 deletions src/app/qgsrasterlayerproperties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,6 @@ QgsRasterLayerProperties::QgsRasterLayerProperties( QgsMapLayer* lyr, QgsMapCanv
.arg( pyramidSentence2 ).arg( pyramidSentence3 )
.arg( pyramidSentence4 ).arg( pyramidSentence5 ) );

// update based on lyr's current state
sync();

QSettings settings;
restoreGeometry( settings.value( "/Windows/RasterLayerProperties/geometry" ).toByteArray() );
tabBar->setCurrentIndex( settings.value( "/Windows/RasterLayerProperties/row" ).toInt() );
Expand Down Expand Up @@ -247,9 +244,18 @@ QgsRasterLayerProperties::QgsRasterLayerProperties( QgsMapLayer* lyr, QgsMapCanv
{
cboxTransparencyBand->addItem( tr( "None" ), -1 );
int nBands = provider->bandCount();
QString bandName;
for ( int i = 1; i <= nBands; ++i ) //band numbering seem to start at 1
{
cboxTransparencyBand->addItem( provider->colorInterpretationName( i ), i );
bandName = provider->colorInterpretationName( i );
if ( bandName == "Undefined" )
{
cboxTransparencyBand->addItem( provider->generateBandName( i ), i );
}
else
{
cboxTransparencyBand->addItem( bandName, i );
}
}

if ( renderer )
Expand Down Expand Up @@ -292,6 +298,9 @@ QgsRasterLayerProperties::QgsRasterLayerProperties( QgsMapLayer* lyr, QgsMapCanv
}
}
on_mRenderTypeComboBox_currentIndexChanged( mRenderTypeComboBox->currentIndex() );

// update based on lyr's current state
sync();
} // QgsRasterLayerProperties ctor


Expand All @@ -306,100 +315,64 @@ QgsRasterLayerProperties::~QgsRasterLayerProperties()
}
}

/*
*
* PUBLIC METHODS
*
*/

void QgsRasterLayerProperties::populateTransparencyTable()
void QgsRasterLayerProperties::populateTransparencyTable( QgsRasterRenderer* renderer )
{
QgsDebugMsg( "entering." );
if ( !mRasterLayer )
{
return;
}
QgsRasterRenderer* renderer = mRasterLayer->renderer();

if ( !renderer )
{
return;
}

const QgsRasterTransparency* rasterTransparency = renderer->rasterTransparency();
tableTransparency->clear();
tableTransparency->setColumnCount( 0 );
tableTransparency->setRowCount( 0 );

//Clear existing color transparency list
//NOTE: May want to just tableTransparency->clearContents() and fill back in after checking to be sure list and table are the same size
QString myNumberFormatter;
if ( mRasterLayer->bandCount() == 3 )
QList<int> bandList = renderer->usesBands();
tableTransparency->setColumnCount( bandList.size() + 1 );
for ( int i = 0; i < bandList.size(); ++i )
{
for ( int myTableRunner = tableTransparency->rowCount() - 1; myTableRunner >= 0; myTableRunner-- )
{
tableTransparency->removeRow( myTableRunner );
}

tableTransparency->clear();
tableTransparency->setColumnCount( 4 );
tableTransparency->setHorizontalHeaderItem( 0, new QTableWidgetItem( tr( "Red" ) ) );
tableTransparency->setHorizontalHeaderItem( 1, new QTableWidgetItem( tr( "Green" ) ) );
tableTransparency->setHorizontalHeaderItem( 2, new QTableWidgetItem( tr( "Blue" ) ) );
tableTransparency->setHorizontalHeaderItem( 3, new QTableWidgetItem( tr( "Percent Transparent" ) ) );
tableTransparency->setHorizontalHeaderItem( i, new QTableWidgetItem( QString::number( bandList.at( i ) ) ) );
}
tableTransparency->setHorizontalHeaderItem( bandList.size(), new QTableWidgetItem( tr( "Percent Transparent" ) ) );

const QgsRasterTransparency* rasterTransparency = renderer->rasterTransparency();
if ( !rasterTransparency )
{
return;
}

//populate three band transparency list
if ( rasterTransparency )
if ( bandList.count() == 1 )
{
QList<QgsRasterTransparency::TransparentSingleValuePixel> pixelList = rasterTransparency->transparentSingleValuePixelList();
for ( int i = 0; i < pixelList.size(); ++i )
{
QList<QgsRasterTransparency::TransparentThreeValuePixel> myTransparentThreeValuePixelList = rasterTransparency->transparentThreeValuePixelList();
for ( int myListRunner = 0; myListRunner < myTransparentThreeValuePixelList.count(); myListRunner++ )
{
tableTransparency->insertRow( myListRunner );
QTableWidgetItem* myRedItem = new QTableWidgetItem( myNumberFormatter.sprintf( "%.2f", myTransparentThreeValuePixelList[myListRunner].red ) );
QTableWidgetItem* myGreenItem = new QTableWidgetItem( myNumberFormatter.sprintf( "%.2f", myTransparentThreeValuePixelList[myListRunner].green ) );
QTableWidgetItem* myBlueItem = new QTableWidgetItem( myNumberFormatter.sprintf( "%.2f", myTransparentThreeValuePixelList[myListRunner].blue ) );
QTableWidgetItem* myPercentTransparentItem = new QTableWidgetItem( myNumberFormatter.sprintf( "%.2f", myTransparentThreeValuePixelList[myListRunner].percentTransparent ) );

tableTransparency->setItem( myListRunner, 0, myRedItem );
tableTransparency->setItem( myListRunner, 1, myGreenItem );
tableTransparency->setItem( myListRunner, 2, myBlueItem );
tableTransparency->setItem( myListRunner, 3, myPercentTransparentItem );
}
tableTransparency->insertRow( i );
QTableWidgetItem* grayItem = new QTableWidgetItem( QString::number( pixelList[i].pixelValue ) );
QTableWidgetItem* percentItem = new QTableWidgetItem( QString::number( pixelList[i].percentTransparent ) );
tableTransparency->setItem( i, 0, grayItem );
tableTransparency->setItem( i, 1, percentItem );
}
}
else if ( mRasterLayer->bandCount() == 1 )
else if ( bandList.count() == 3 )
{
//Clear existing single band or palette values transparency list
for ( int myTableRunner = tableTransparency->rowCount() - 1; myTableRunner >= 0; myTableRunner-- )
QList<QgsRasterTransparency::TransparentThreeValuePixel> pixelList = rasterTransparency->transparentThreeValuePixelList();
for ( int i = 0; i < pixelList.size(); ++i )
{
tableTransparency->removeRow( myTableRunner );
}

tableTransparency->clear();
tableTransparency->setColumnCount( 2 );
if ( QgsRasterLayer::PalettedColor != mRasterLayer->drawingStyle() &&
QgsRasterLayer::PalettedSingleBandGray != mRasterLayer->drawingStyle() &&
QgsRasterLayer::PalettedSingleBandPseudoColor != mRasterLayer->drawingStyle() &&
QgsRasterLayer::PalettedMultiBandColor != mRasterLayer->drawingStyle() )
{
tableTransparency->setHorizontalHeaderItem( 0, new QTableWidgetItem( tr( "Gray" ) ) );
}
else
{
tableTransparency->setHorizontalHeaderItem( 0, new QTableWidgetItem( tr( "Indexed Value" ) ) );
}
tableTransparency->setHorizontalHeaderItem( 1, new QTableWidgetItem( tr( "Percent Transparent" ) ) );

//populate gray transparency list
if ( rasterTransparency )
{
QList<QgsRasterTransparency::TransparentSingleValuePixel> myTransparentSingleValuePixelList = rasterTransparency->transparentSingleValuePixelList();
for ( int myListRunner = 0; myListRunner < myTransparentSingleValuePixelList.count(); myListRunner++ )
{
tableTransparency->insertRow( myListRunner );
QTableWidgetItem* myGrayItem = new QTableWidgetItem( myNumberFormatter.sprintf( "%g", myTransparentSingleValuePixelList[myListRunner].pixelValue ) );
QTableWidgetItem* myPercentTransparentItem = new QTableWidgetItem( myNumberFormatter.sprintf( "%.2f", myTransparentSingleValuePixelList[myListRunner].percentTransparent ) );

tableTransparency->setItem( myListRunner, 0, myGrayItem );
tableTransparency->setItem( myListRunner, 1, myPercentTransparentItem );
}
tableTransparency->insertRow( i );
QTableWidgetItem* redItem = new QTableWidgetItem( QString::number( pixelList[i].red ) );
QTableWidgetItem* greenItem = new QTableWidgetItem( QString::number( pixelList[i].green ) );
QTableWidgetItem* blueItem = new QTableWidgetItem( QString::number( pixelList[i].blue ) );
QTableWidgetItem* transparentItem = new QTableWidgetItem( QString::number( pixelList[i].percentTransparent ) );

tableTransparency->setItem( i, 0, redItem );
tableTransparency->setItem( i, 1, greenItem );
tableTransparency->setItem( i, 2, blueItem );
tableTransparency->setItem( i, 3, transparentItem );
}
}

Expand All @@ -409,8 +382,7 @@ void QgsRasterLayerProperties::populateTransparencyTable()

void QgsRasterLayerProperties::setRendererWidget( const QString& rendererName )
{
delete mRendererWidget;
mRendererWidget = 0;
QgsRasterRendererWidget* oldWidget = mRendererWidget;

QgsRasterRendererRegistryEntry rendererEntry;
if ( QgsRasterRendererRegistry::instance()->rendererData( rendererName, rendererEntry ) )
Expand All @@ -419,8 +391,23 @@ void QgsRasterLayerProperties::setRendererWidget( const QString& rendererName )
{
mRendererWidget = ( *rendererEntry.widgetCreateFunction )( mRasterLayer );
mRendererStackedWidget->addWidget( mRendererWidget );
if ( oldWidget )
{
//compare used bands in new and old renderer and reset transparency dialog if different
QgsRasterRenderer* oldRenderer = oldWidget->renderer();
QgsRasterRenderer* newRenderer = mRendererWidget->renderer();
QList<int> oldBands = oldRenderer->usesBands();
QList<int> newBands = newRenderer->usesBands();
if ( oldBands != newBands )
{
populateTransparencyTable( newRenderer );
}
delete oldRenderer;
delete newRenderer;
}
}
}
delete oldWidget;
}

/**
Expand Down Expand Up @@ -496,7 +483,7 @@ void QgsRasterLayerProperties::sync()
leNoDataValue->insert( "" );
}

populateTransparencyTable();
populateTransparencyTable( mRasterLayer->renderer() );

QgsDebugMsg( "populate colormap tab" );
/*
Expand Down Expand Up @@ -614,7 +601,7 @@ void QgsRasterLayerProperties::apply()

//Walk through each row in table and test value. If not valid set to 0.0 and continue building transparency list
QgsRasterTransparency* rasterTransparency = new QgsRasterTransparency();
if ( mRasterLayer->bandCount() == 3 )
if ( tableTransparency->columnCount() == 4 )
{
double myTransparentValue;
double myPercentTransparent;
Expand Down Expand Up @@ -714,7 +701,7 @@ void QgsRasterLayerProperties::apply()
}
rasterTransparency->setTransparentThreeValuePixelList( myTransparentThreeValuePixelList );
}
else if ( mRasterLayer->bandCount() == 1 )
else if ( tableTransparency->columnCount() == 2 )
{
double myTransparentValue;
double myPercentTransparent;
Expand Down Expand Up @@ -1003,9 +990,21 @@ void QgsRasterLayerProperties::on_pbnChangeSpatialRefSys_clicked()

void QgsRasterLayerProperties::on_pbnDefaultValues_clicked()
{
if ( !mRendererWidget )
{
return;
}

if ( /*rbtnThreeBand->isChecked() &&*/ QgsRasterLayer::PalettedColor != mRasterLayer->drawingStyle() &&
QgsRasterLayer::PalettedMultiBandColor != mRasterLayer->drawingStyle() )
QgsRasterRenderer* r = mRendererWidget->renderer();
if ( !r )
{
return;
}

int nBands = r->usesBands().size();
delete r;

if ( nBands == 3 )
{
tableTransparency->clear();
tableTransparency->setColumnCount( 4 );
Expand All @@ -1022,7 +1021,7 @@ void QgsRasterLayerProperties::on_pbnDefaultValues_clicked()
tableTransparency->setItem( 0, 3, new QTableWidgetItem( "100.0" ) );
}
}
else
else //1 band
{
tableTransparency->clear();
tableTransparency->setColumnCount( 2 );
Expand All @@ -1045,7 +1044,6 @@ void QgsRasterLayerProperties::on_pbnDefaultValues_clicked()
tableTransparency->setItem( 0, 0, new QTableWidgetItem( QString::number( mRasterLayer->noDataValue(), 'f' ) ) );
tableTransparency->setItem( 0, 1, new QTableWidgetItem( "100.0" ) );
}

}
}

Expand Down Expand Up @@ -1353,44 +1351,42 @@ void QgsRasterLayerProperties::on_pbnRemoveSelectedRow_clicked()

void QgsRasterLayerProperties::pixelSelected( const QgsPoint& canvasPoint )
{
#if 0 //needs to be fixed
//PixelSelectorTool has registered a mouse click on the canvas, so bring the dialog back to the front
QgsRasterRenderer* renderer = mRendererWidget->renderer();
if ( !renderer )
{
return;
}

raise();
setModal( true );
activateWindow();

//Get the pixel values and add a new entry to the transparency table
if ( mMapCanvas && mPixelSelectorTool )
{
QMap< QString, QString > myPixelMap;
QMap< int, QString > myPixelMap;
mMapCanvas->unsetMapTool( mPixelSelectorTool );
mRasterLayer->identify( mMapCanvas->mapRenderer()->mapToLayerCoordinates( mRasterLayer, canvasPoint ), myPixelMap );
if ( tableTransparency->columnCount() == 2 )
{
QString myValue = myPixelMap[ mRasterLayer->grayBandName()];
if ( myValue != tr( "out of extent" ) )
{
tableTransparency->insertRow( tableTransparency->rowCount() );
tableTransparency->setItem( tableTransparency->rowCount() - 1, tableTransparency->columnCount() - 1, new QTableWidgetItem( "100.0" ) );
tableTransparency->setItem( tableTransparency->rowCount() - 1, 0, new QTableWidgetItem( myValue ) );
}
}
else

QList<int> bands = renderer->usesBands();
tableTransparency->insertRow( tableTransparency->rowCount() );
tableTransparency->setItem( tableTransparency->rowCount() - 1, tableTransparency->columnCount() - 1, new QTableWidgetItem( "100.0" ) );

for ( int i = 0; i < bands.size(); ++i )
{
QString myValue = myPixelMap[ mRasterLayer->redBandName()];
if ( myValue != tr( "out of extent" ) )
QMap< int, QString >::const_iterator pixelResult = myPixelMap.find( bands.at( i ) );
if ( pixelResult != myPixelMap.constEnd() )
{
tableTransparency->insertRow( tableTransparency->rowCount() );
tableTransparency->setItem( tableTransparency->rowCount() - 1, tableTransparency->columnCount() - 1, new QTableWidgetItem( "100.0" ) );
tableTransparency->setItem( tableTransparency->rowCount() - 1, 0, new QTableWidgetItem( myValue ) );
tableTransparency->setItem( tableTransparency->rowCount() - 1, 1, new QTableWidgetItem( myPixelMap[ mRasterLayer->greenBandName()] ) );
tableTransparency->setItem( tableTransparency->rowCount() - 1, 2, new QTableWidgetItem( myPixelMap[ mRasterLayer->blueBandName()] ) );
QString value = pixelResult.value();
if ( value != tr( "out of extent" ) )
{
tableTransparency->setItem( tableTransparency->rowCount() - 1, i, new QTableWidgetItem( value ) );
}
}
}
}
#else
Q_UNUSED( canvasPoint );
#endif //0

delete renderer;
}

void QgsRasterLayerProperties::sliderTransparency_valueChanged( int theValue )
Expand Down
3 changes: 2 additions & 1 deletion src/app/qgsrasterlayerproperties.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class QgsMapLayer;
class QgsMapCanvas;
class QgsRasterLayer;
class QgsMapToolEmitPoint;
class QgsRasterRenderer;
class QgsRasterRendererWidget;

/**Property sheet for a raster map layer
Expand Down Expand Up @@ -137,7 +138,7 @@ class QgsRasterLayerProperties : public QDialog, private Ui::QgsRasterLayerPrope
QgsRasterRendererWidget* mRendererWidget;

/** \brief Clear the current transparency table and populate the table with the correct types for current drawing mode and data type*/
void populateTransparencyTable();
void populateTransparencyTable( QgsRasterRenderer* renderer );

void setRendererWidget( const QString& rendererName );

Expand Down
4 changes: 4 additions & 0 deletions src/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,8 @@ SET(QGIS_CORE_SRCS
symbology/qgssymbologyutils.cpp

qgsspatialindex.cpp

qgspaintenginehack.cpp
)

IF(WIN32)
Expand Down Expand Up @@ -426,6 +428,8 @@ SET(QGIS_CORE_HDRS
qgsdiagramrendererv2.h

qgsspatialindex.h

qgspaintenginehack.h
)

IF (QT_MOBILITY_LOCATION_FOUND)
Expand Down
35 changes: 8 additions & 27 deletions src/core/composer/qgscomposeritem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -943,6 +943,14 @@ bool QgsComposerItem::imageSizeConsideringRotation( double& width, double& heigh
return true;
}

if ( doubleNear( qAbs( mRotation ), 90 ) || doubleNear( qAbs( mRotation ), 270 ) )
{
double tmp = width;
width = height;
height = tmp;
return true;
}

double x1 = 0;
double y1 = 0;
double x2 = width;
Expand Down Expand Up @@ -990,33 +998,6 @@ bool QgsComposerItem::imageSizeConsideringRotation( double& width, double& heigh
width = sqrt(( x2 - p1.x() ) * ( x2 - p1.x() ) + ( y2 - p1.y() ) * ( y2 - p1.y() ) );
height = sqrt(( p3.x() - x2 ) * ( p3.x() - x2 ) + ( p3.y() - y2 ) * ( p3.y() - y2 ) );
return true;


#if 0
double x1 = 0;
double y1 = 0;
double x2 = width;
double y2 = 0;
double x3 = width;
double y3 = height;

if ( !cornerPointOnRotatedAndScaledRect( x1, y1, width, height ) )
{
return false;
}
if ( !cornerPointOnRotatedAndScaledRect( x2, y2, width, height ) )
{
return false;
}
if ( !cornerPointOnRotatedAndScaledRect( x3, y3, width, height ) )
{
return false;
}

width = sqrt(( x2 - x1 ) * ( x2 - x1 ) + ( y2 - y1 ) * ( y2 - y1 ) );
height = sqrt(( x3 - x2 ) * ( x3 - x2 ) + ( y3 - y2 ) * ( y3 - y2 ) );
return true;
#endif //0
}

bool QgsComposerItem::cornerPointOnRotatedAndScaledRect( double& x, double& y, double width, double height ) const
Expand Down
420 changes: 383 additions & 37 deletions src/core/composer/qgscomposermap.cpp

Large diffs are not rendered by default.

98 changes: 76 additions & 22 deletions src/core/composer/qgscomposermap.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class QDomNode;
class QDomDocument;
class QGraphicsView;
class QPainter;
class QgsFillSymbolV2;

/** \ingroup MapComposer
* \class QgsComposerMap
Expand Down Expand Up @@ -66,7 +67,8 @@ class CORE_EXPORT QgsComposerMap : public QgsComposerItem
enum GridAnnotationPosition
{
InsideMapFrame = 0,
OutsideMapFrame
OutsideMapFrame,
Disabled
};

enum GridAnnotationDirection
Expand All @@ -77,6 +79,21 @@ class CORE_EXPORT QgsComposerMap : public QgsComposerItem
BoundaryDirection
};

enum GridFrameStyle
{
NoGridFrame = 0,
Zebra //black / white pattern
};

/**Enum for different frame borders*/
enum Border
{
Left,
Right,
Bottom,
Top
};

/**This function is deprecated*/
void draw( QPainter *painter, const QgsRectangle& extent, const QSize& size, int dpi );

Expand Down Expand Up @@ -227,20 +244,26 @@ class CORE_EXPORT QgsComposerMap : public QgsComposerItem
void setShowGridAnnotation( bool show ) {mShowGridAnnotation = show;}
bool showGridAnnotation() const {return mShowGridAnnotation;}

/**Sets position of grid annotations. Possibilities are inside or outside of the map frame
@note this function was added in version 1.4*/
void setGridAnnotationPosition( GridAnnotationPosition p ) {mGridAnnotationPosition = p;}
GridAnnotationPosition gridAnnotationPosition() const {return mGridAnnotationPosition;}
void setGridAnnotationPosition( GridAnnotationPosition p, QgsComposerMap::Border border );
GridAnnotationPosition gridAnnotationPosition( QgsComposerMap::Border border ) const;

/**Sets distance between map frame and annotations
@note this function was added in version 1.4*/
void setAnnotationFrameDistance( double d ) {mAnnotationFrameDistance = d;}
double annotationFrameDistance() const {return mAnnotationFrameDistance;}

/**Sets grid annotation direction. Can be horizontal, vertical, direction of axis and horizontal and vertical
@note this function was added in version 1.4*/
void setGridAnnotationDirection( GridAnnotationDirection d ) {mGridAnnotationDirection = d;}
GridAnnotationDirection gridAnnotationDirection() const {return mGridAnnotationDirection;}
void setGridAnnotationDirection( GridAnnotationDirection d, QgsComposerMap::Border border );
GridAnnotationDirection gridAnnotationDirection( QgsComposerMap::Border border ) const;

/**Set grid frame style (NoGridFrame or Zebra)
@note: this function was added in version 1.9*/
void setGridFrameStyle( GridFrameStyle style ) { mGridFrameStyle = style; }
GridFrameStyle gridFrameStyle() const { return mGridFrameStyle; }

/**Set grid frame width
@note: this function was added in version 1.9*/
void setGridFrameWidth( double w ) { mGridFrameWidth = w; }
double gridFrameWidth() const { return mGridFrameWidth; }

/**In case of annotations, the bounding rectangle can be larger than the map item rectangle
@note this function was added in version 1.4*/
Expand All @@ -267,6 +290,16 @@ class CORE_EXPORT QgsComposerMap : public QgsComposerItem
/**Returns the conversion factor map units -> mm*/
double mapUnitsToMM() const;

/**Sets overview frame map. -1 disables the overview frame
@note: this function was added in version 1.9*/
void setOverviewFrameMap( int mapId );
/**Returns id of overview frame (or -1 if no overfiew frame)
@note: this function was added in version 1.9*/
int overviewFrameMapId() const { return mOverviewFrameMapId; }

void setOverviewFrameMapSymbol( QgsFillSymbolV2* symbol );
QgsFillSymbolV2* overviewFrameMapSymbol() { return mOverviewFrameMapSymbol; }

signals:
void extentChanged();

Expand All @@ -279,15 +312,6 @@ class CORE_EXPORT QgsComposerMap : public QgsComposerItem

private:

/**Enum for different frame borders*/
enum Border
{
Left,
Right,
Bottom,
Top
};

// Pointer to map renderer of the QGIS main map. Note that QgsComposerMap uses a different map renderer,
//it just copies some properties from the main map renderer.
QgsMapRenderer *mMapRenderer;
Expand Down Expand Up @@ -326,6 +350,11 @@ class CORE_EXPORT QgsComposerMap : public QgsComposerItem
/**Stored layer list (used if layer live-link mKeepLayerSet is disabled)*/
QStringList mLayerSet;

/**Id of map which displays its extent rectangle into this composer map (overview map functionality). -1 if not present*/
int mOverviewFrameMapId;
/**Drawing style for overview farme*/
QgsFillSymbolV2* mOverviewFrameMapSymbol;

/**Establishes signal/slot connection for update in case of layer change*/
void connectUpdateSlot();

Expand All @@ -352,12 +381,31 @@ class CORE_EXPORT QgsComposerMap : public QgsComposerItem
int mGridAnnotationPrecision;
/**True if coordinate values should be drawn*/
bool mShowGridAnnotation;
/**Annotation position inside or outside of map frame*/
GridAnnotationPosition mGridAnnotationPosition;

/**Annotation position for left map side (inside / outside / not shown)*/
GridAnnotationPosition mLeftGridAnnotationPosition;
/**Annotation position for right map side (inside / outside / not shown)*/
GridAnnotationPosition mRightGridAnnotationPosition;
/**Annotation position for top map side (inside / outside / not shown)*/
GridAnnotationPosition mTopGridAnnotationPosition;
/**Annotation position for bottom map side (inside / outside / not shown)*/
GridAnnotationPosition mBottomGridAnnotationPosition;

/**Distance between map frame and annotation*/
double mAnnotationFrameDistance;
/**Annotation can be horizontal / vertical or different for axes*/
GridAnnotationDirection mGridAnnotationDirection;

/**Annotation direction on left side ( horizontal or vertical )*/
GridAnnotationDirection mLeftGridAnnotationDirection;
/**Annotation direction on right side ( horizontal or vertical )*/
GridAnnotationDirection mRightGridAnnotationDirection;
/**Annotation direction on top side ( horizontal or vertical )*/
GridAnnotationDirection mTopGridAnnotationDirection;
/**Annotation direction on bottom side ( horizontal or vertical )*/
GridAnnotationDirection mBottomGridAnnotationDirection;

GridFrameStyle mGridFrameStyle;
double mGridFrameWidth;

/**Current bounding rectangle. This is used to check if notification to the graphics scene is necessary*/
QRectF mCurrentRectangle;
/**The length of the cross sides for mGridStyle Cross*/
Expand All @@ -368,6 +416,7 @@ class CORE_EXPORT QgsComposerMap : public QgsComposerItem

/**Draws the map grid*/
void drawGrid( QPainter* p );
void drawGridFrame( QPainter* p, const QList< QPair< double, QLineF > >& hLines, const QList< QPair< double, QLineF > >& vLines );
/**Draw coordinates for mGridAnnotationType Coordinate
@param p drawing painter
@param hLines horizontal coordinate lines in item coordinates
Expand Down Expand Up @@ -409,6 +458,11 @@ class CORE_EXPORT QgsComposerMap : public QgsComposerItem
void drawCanvasItems( QPainter* painter, const QStyleOptionGraphicsItem* itemStyle );
void drawCanvasItem( QGraphicsItem* item, QPainter* painter, const QStyleOptionGraphicsItem* itemStyle );
QPointF composerMapPosForItem( const QGraphicsItem* item ) const;
void sortGridLinesOnBorders( const QList< QPair< double, QLineF > >& hLines, const QList< QPair< double, QLineF > >& vLines, QMap< double, double >& leftFrameEntries,
QMap< double, double >& rightFrameEntries, QMap< double, double >& topFrameEntries, QMap< double, double >& bottomFrameEntries ) const;
void drawGridFrameBorder( QPainter* p, const QMap< double, double >& borderPos, Border border );
void drawOverviewMapExtent( QPainter* p );
void createDefaultOverviewFrameSymbol();
};

#endif
50 changes: 29 additions & 21 deletions src/core/qgsexpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,33 +64,33 @@ QgsExpression::Interval QgsExpression::Interval::fromString( QString string )
continue;
}

if ( match.contains( "day", Qt::CaseInsensitive ) ||
match.contains( QObject::tr("day", "Note: Word is part matched in code"), Qt::CaseInsensitive )||
match.contains( QObject::tr("days", "Note: Word is part matched in code"), Qt::CaseInsensitive) )
if ( match.contains( "day", Qt::CaseInsensitive ) ||
match.contains( QObject::tr( "day", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) ||
match.contains( QObject::tr( "days", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) )
seconds += value * QgsExpression::Interval::DAY;
if ( match.contains( "week", Qt::CaseInsensitive ) ||
match.contains( QObject::tr("week", "Note: Word is part matched in code"), Qt::CaseInsensitive ) ||
match.contains( QObject::tr("weeks", "Note: Word is part matched in code"), Qt::CaseInsensitive ) )
if ( match.contains( "week", Qt::CaseInsensitive ) ||
match.contains( QObject::tr( "week", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) ||
match.contains( QObject::tr( "weeks", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) )
seconds += value * QgsExpression::Interval::WEEKS;
if ( match.contains( "month", Qt::CaseInsensitive ) ||
match.contains( QObject::tr("month", "Note: Word is part matched in code"), Qt::CaseInsensitive ) ||
match.contains( QObject::tr("months", "Note: Word is part matched in code"), Qt::CaseInsensitive ) )
if ( match.contains( "month", Qt::CaseInsensitive ) ||
match.contains( QObject::tr( "month", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) ||
match.contains( QObject::tr( "months", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) )
seconds += value * QgsExpression::Interval::MONTHS;
if ( match.contains( "year", Qt::CaseInsensitive ) ||
match.contains( QObject::tr("year", "Note: Word is part matched in code"), Qt::CaseInsensitive ) ||
match.contains( QObject::tr("years", "Note: Word is part matched in code"), Qt::CaseInsensitive ) )
match.contains( QObject::tr( "year", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) ||
match.contains( QObject::tr( "years", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) )
seconds += value * QgsExpression::Interval::YEARS;
if ( match.contains( "second", Qt::CaseInsensitive ) ||
match.contains( QObject::tr("second", "Note: Word is part matched in code"), Qt::CaseInsensitive ) ||
match.contains( QObject::tr("seconds", "Note: Word is part matched in code"), Qt::CaseInsensitive ) )
if ( match.contains( "second", Qt::CaseInsensitive ) ||
match.contains( QObject::tr( "second", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) ||
match.contains( QObject::tr( "seconds", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) )
seconds += value;
if ( match.contains( "minute", Qt::CaseInsensitive ) ||
match.contains( QObject::tr("minute", "Note: Word is part matched in code"), Qt::CaseInsensitive ) ||
match.contains( QObject::tr("minutes", "Note: Word is part matched in code"), Qt::CaseInsensitive ) )
if ( match.contains( "minute", Qt::CaseInsensitive ) ||
match.contains( QObject::tr( "minute", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) ||
match.contains( QObject::tr( "minutes", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) )
seconds += value * QgsExpression::Interval::MINUTE;
if ( match.contains( "hour", Qt::CaseInsensitive ) ||
match.contains( QObject::tr("hour", "Note: Word is part matched in code"), Qt::CaseInsensitive ) ||
match.contains( QObject::tr("hours", "Note: Word is part matched in code"), Qt::CaseInsensitive ) )
if ( match.contains( "hour", Qt::CaseInsensitive ) ||
match.contains( QObject::tr( "hour", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) ||
match.contains( QObject::tr( "hours", "Note: Word is part matched in code" ), Qt::CaseInsensitive ) )
seconds += value * QgsExpression::Interval::HOUR;
}

Expand Down Expand Up @@ -494,6 +494,7 @@ static QVariant fcnFeatureId( const QVariantList& , QgsFeature* f, QgsExpression
// TODO: handling of 64-bit feature ids?
return f ? QVariant(( int )f->id() ) : QVariant();
}

static QVariant fcnConcat( const QVariantList& values, QgsFeature* , QgsExpression *parent )
{
QString concat;
Expand All @@ -504,6 +505,12 @@ static QVariant fcnConcat( const QVariantList& values, QgsFeature* , QgsExpressi
return concat;
}

static QVariant fcnStrpos( const QVariantList& values, QgsFeature* , QgsExpression *parent )
{
QString string = getStringValue( values.at( 0 ), parent );
return string.indexOf( QRegExp( getStringValue( values.at( 1 ), parent ) ) );
}

static QVariant fcnNow( const QVariantList&, QgsFeature* , QgsExpression * )
{
return QVariant( QDateTime::currentDateTime() );
Expand Down Expand Up @@ -767,6 +774,7 @@ const QList<QgsExpression::FunctionDef> &QgsExpression::BuiltinFunctions()
<< FunctionDef( "regexp_replace", 3, fcnRegexpReplace, QObject::tr( "String" ) )
<< FunctionDef( "substr", 3, fcnSubstr, QObject::tr( "String" ) )
<< FunctionDef( "concat", -1, fcnConcat, QObject::tr( "String" ) )
<< FunctionDef( "strpos", 2, fcnStrpos, QObject::tr( "String" ) )
// geometry accessors
<< FunctionDef( "xat", 1, fcnXat, QObject::tr( "Geometry" ), "", true )
<< FunctionDef( "yat", 1, fcnYat, QObject::tr( "Geometry" ), "", true )
Expand Down Expand Up @@ -1219,7 +1227,7 @@ QVariant QgsExpression::NodeBinaryOperator::eval( QgsExpression* parent, QgsFeat
QgsExpression::Interval iL = getInterval( vR, parent ); ENSURE_NO_EVAL_ERROR;
if ( mOp == boDiv || mOp == boMul || mOp == boMod )
{
parent->setEvalErrorString( QObject::tr("Can't preform /, *, or % on DateTime and Interval") );
parent->setEvalErrorString( QObject::tr( "Can't preform /, *, or % on DateTime and Interval" ) );
return QVariant();
}
return QVariant( computeDateTimeFromInterval( dL, &iL ) );
Expand Down
55 changes: 55 additions & 0 deletions src/core/qgspaintenginehack.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/***************************************************************************
qgspaintenginehack.cpp
Hack paint engine flags
-------------------
begin : July 2012
copyright : (C) Juergen E. Fischer
email : jef at norbit dot de
***************************************************************************
* *
* 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 "qgspaintenginehack.h"

// Hack to workaround Qt #5114 by disabling PatternTransform
void QgsPaintEngineHack::fixFlags()
{
gccaps = 0;
gccaps |= ( QPaintEngine::PrimitiveTransform
// | QPaintEngine::PatternTransform
| QPaintEngine::PixmapTransform
| QPaintEngine::PatternBrush
// | QPaintEngine::LinearGradientFill
// | QPaintEngine::RadialGradientFill
// | QPaintEngine::ConicalGradientFill
| QPaintEngine::AlphaBlend
// | QPaintEngine::PorterDuff
| QPaintEngine::PainterPaths
| QPaintEngine::Antialiasing
| QPaintEngine::BrushStroke
| QPaintEngine::ConstantOpacity
| QPaintEngine::MaskedBrush
// | QPaintEngine::PerspectiveTransform
| QPaintEngine::BlendModes
// | QPaintEngine::ObjectBoundingModeGradients
#if QT_VERSION >= 0x040500
| QPaintEngine::RasterOpModes
#endif
| QPaintEngine::PaintOutsidePaintEvent
);
}

void QgsPaintEngineHack::fixEngineFlags( QPaintEngine *engine )
{
if ( !engine )
return;

QgsPaintEngineHack *hack = static_cast<QgsPaintEngineHack*>( engine );
hack->fixFlags();
}
25 changes: 25 additions & 0 deletions src/core/qgspaintenginehack.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/***************************************************************************
qgspaintenginehack.cpp - Hack paint engine flags
------------------------------------------------
begin : July 2012
copyright : (C) Juergen E. Fischer
email : jef at norbit dot de
***************************************************************************
* *
* 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 <QPaintEngine>

// Hack to workaround Qt #5114 by disabling PatternTransform
class CORE_EXPORT QgsPaintEngineHack : public QPaintEngine
{
public:
void fixFlags();
static void fixEngineFlags( QPaintEngine *engine );
};
56 changes: 56 additions & 0 deletions src/core/qgsprojectfiletransform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,62 @@ void QgsProjectFileTransform::transform1800to1900()
rasterLayer.readXML( layerNode );
convertRasterProperties( mDom, layerNode, rasterPropertiesElem, &rasterLayer );
}

//composer: replace mGridAnnotationPosition with mLeftGridAnnotationPosition & co.
// and mGridAnnotationDirection with mLeftGridAnnotationDirection & co.
QDomNodeList composerMapList = mDom.elementsByTagName( "ComposerMap" );
for ( int i = 0; i < composerMapList.size(); ++i )
{
QDomNodeList gridList = composerMapList.at( i ).toElement().elementsByTagName( "Grid" );
for ( int j = 0; j < gridList.size(); ++j )
{
QDomNodeList annotationList = gridList.at( j ).toElement().elementsByTagName( "Annotation" );
for ( int k = 0; k < annotationList.size(); ++k )
{
QDomElement annotationElem = annotationList.at( k ).toElement();

//position
if ( annotationElem.hasAttribute( "position" ) )
{
int pos = annotationElem.attribute( "position" ).toInt();
annotationElem.setAttribute( "leftPosition", pos );
annotationElem.setAttribute( "rightPosition", pos );
annotationElem.setAttribute( "topPosition", pos );
annotationElem.setAttribute( "bottomPosition", pos );
annotationElem.removeAttribute( "position" );
}

//direction
if ( annotationElem.hasAttribute( "direction" ) )
{
int dir = annotationElem.attribute( "direction" ).toInt();
if ( dir == 2 )
{
annotationElem.setAttribute( "leftDirection", 0 );
annotationElem.setAttribute( "rightDirection", 0 );
annotationElem.setAttribute( "topDirection", 1 );
annotationElem.setAttribute( "bottomDirection", 1 );
}
else if ( dir == 3 )
{
annotationElem.setAttribute( "leftDirection", 1 );
annotationElem.setAttribute( "rightDirection", 1 );
annotationElem.setAttribute( "topDirection", 0 );
annotationElem.setAttribute( "bottomDirection", 0 );
}
else
{
annotationElem.setAttribute( "leftDirection", dir );
annotationElem.setAttribute( "rightDirection", dir );
annotationElem.setAttribute( "topDirection", dir );
annotationElem.setAttribute( "bottomDirection", dir );
}
annotationElem.removeAttribute( "direction" );
}
}
}
}

QgsDebugMsg( mDom.toString() );
}

Expand Down
7 changes: 7 additions & 0 deletions src/core/qgsrasterdataprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,13 @@ bool QgsRasterDataProvider::identify( const QgsPoint& thePoint, QMap<QString, QS
return false;
}

bool QgsRasterDataProvider::identify( const QgsPoint & point, QMap<int, QString>& results )
{
Q_UNUSED( point );
results.clear();
return false;
}

QString QgsRasterDataProvider::lastErrorFormat()
{
return "text/plain";
Expand Down
2 changes: 2 additions & 0 deletions src/core/qgsrasterdataprovider.h
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,8 @@ class CORE_EXPORT QgsRasterDataProvider : public QgsDataProvider
/** \brief Identify raster value(s) found on the point position */
virtual bool identify( const QgsPoint & point, QMap<QString, QString>& results );

virtual bool identify( const QgsPoint & point, QMap<int, QString>& results );

/**
* \brief Identify details from a server (e.g. WMS) from the last screen update
*
Expand Down
26 changes: 25 additions & 1 deletion src/core/raster/qgsmultibandcolorrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,9 @@ void QgsMultiBandColorRenderer::draw( QPainter* p, QgsRasterViewPort* viewPort,
int redVal = 0;
int greenVal = 0;
int blueVal = 0;
int redDataVal = 0;
int greenDataVal = 0;
int blueDataVal = 0;
QRgb defaultColor = qRgba( 255, 255, 255, 0 );
double currentOpacity = mOpacity; //opacity (between 0 and 1)

Expand All @@ -243,14 +246,17 @@ void QgsMultiBandColorRenderer::draw( QPainter* p, QgsRasterViewPort* viewPort,
if ( mRedBand > 0 )
{
redVal = readValue( redData, redType, currentRasterPos );
redDataVal = redVal;
}
if ( mGreenBand > 0 )
{
greenVal = readValue( greenData, greenType, currentRasterPos );
greenDataVal = greenVal;
}
if ( mBlueBand > 0 )
{
blueVal = readValue( blueData, blueType, currentRasterPos );
blueDataVal = blueVal;
}

//apply default color if red, green or blue not in displayable range
Expand Down Expand Up @@ -288,7 +294,7 @@ void QgsMultiBandColorRenderer::draw( QPainter* p, QgsRasterViewPort* viewPort,
currentOpacity = mOpacity;
if ( mRasterTransparency )
{
currentOpacity = mRasterTransparency->alphaValue( redVal, greenVal, blueVal, mOpacity * 255 ) / 255.0;
currentOpacity = mRasterTransparency->alphaValue( redDataVal, greenDataVal, blueDataVal, mOpacity * 255 ) / 255.0;
}
if ( mAlphaBand > 0 )
{
Expand Down Expand Up @@ -351,3 +357,21 @@ void QgsMultiBandColorRenderer::writeXML( QDomDocument& doc, QDomElement& parent
}
parentElem.appendChild( rasterRendererElem );
}

QList<int> QgsMultiBandColorRenderer::usesBands() const
{
QList<int> bandList;
if ( mRedBand != -1 )
{
bandList << mRedBand;
}
if ( mGreenBand != -1 )
{
bandList << mGreenBand;
}
if ( mBlueBand != -1 )
{
bandList << mBlueBand;
}
return bandList;
}
2 changes: 2 additions & 0 deletions src/core/raster/qgsmultibandcolorrenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ class CORE_EXPORT QgsMultiBandColorRenderer: public QgsRasterRenderer

void writeXML( QDomDocument& doc, QDomElement& parentElem ) const;

QList<int> usesBands() const;

private:
int mRedBand;
int mGreenBand;
Expand Down
10 changes: 10 additions & 0 deletions src/core/raster/qgspalettedrasterrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -217,3 +217,13 @@ void QgsPalettedRasterRenderer::legendSymbologyItems( QList< QPair< QString, QCo
symbolItems.push_back( qMakePair( QString::number( i ), mColors[i] ) );
}
}

QList<int> QgsPalettedRasterRenderer::usesBands() const
{
QList<int> bandList;
if ( mBandNumber != -1 )
{
bandList << mBandNumber;
}
return bandList;
}
2 changes: 2 additions & 0 deletions src/core/raster/qgspalettedrasterrenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ class CORE_EXPORT QgsPalettedRasterRenderer: public QgsRasterRenderer

void legendSymbologyItems( QList< QPair< QString, QColor > >& symbolItems ) const;

QList<int> usesBands() const;

private:
int mBandNumber;
/**Color array*/
Expand Down
12 changes: 12 additions & 0 deletions src/core/raster/qgsrasterlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -914,6 +914,18 @@ bool QgsRasterLayer::identify( const QgsPoint& thePoint, QMap<QString, QString>&
return ( mDataProvider->identify( thePoint, theResults ) );
}

bool QgsRasterLayer::identify( const QgsPoint & point, QMap<int, QString>& results )
{
if ( !mDataProvider )
{
return false;
}

results.clear();
return mDataProvider->identify( point, results );
}


/**
* @note The arbitraryness of the returned document is enforced by WMS standards up to at least v1.3.0
*
Expand Down
3 changes: 3 additions & 0 deletions src/core/raster/qgsrasterlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,9 @@ class CORE_EXPORT QgsRasterLayer : public QgsMapLayer
/** \brief Identify raster value(s) found on the point position */
bool identify( const QgsPoint & point, QMap<QString, QString>& results );

/** \brief Identify raster value(s) found on the point position */
bool identify( const QgsPoint & point, QMap<int, QString>& results );

/** \brief Identify arbitrary details from the WMS server found on the point position */
QString identifyAsText( const QgsPoint & point );

Expand Down
3 changes: 3 additions & 0 deletions src/core/raster/qgsrasterrenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ class CORE_EXPORT QgsRasterRenderer
/**Sets base class members from xml. Usually called from create() methods of subclasses*/
void readXML( const QDomElement& rendererElem );

/**Returns a list of band numbers used by the renderer*/
virtual QList<int> usesBands() const { return QList<int>(); }

protected:
inline double readValue( void *data, QgsRasterDataProvider::DataType type, int index );

Expand Down
23 changes: 23 additions & 0 deletions src/core/raster/qgsrasterrendererregistry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,29 @@ QgsRasterRenderer* QgsRasterRendererRegistry::defaultRendererForDrawingStyle( co
break;
}

QgsRasterTransparency* tr = new QgsRasterTransparency(); //renderer takes ownership
int bandCount = renderer->usesBands().size();
if ( bandCount == 1 )
{
QList<QgsRasterTransparency::TransparentSingleValuePixel> transparentSingleList;
QgsRasterTransparency::TransparentSingleValuePixel singleEntry;
singleEntry.pixelValue = provider->noDataValue();
singleEntry.percentTransparent = 100;
transparentSingleList.push_back( singleEntry );
tr->setTransparentSingleValuePixelList( transparentSingleList );
}
else if ( bandCount == 3 )
{
QList<QgsRasterTransparency::TransparentThreeValuePixel> transparentThreeValueList;
QgsRasterTransparency::TransparentThreeValuePixel threeValueEntry;
threeValueEntry.red = provider->noDataValue();
threeValueEntry.green = provider->noDataValue();
threeValueEntry.blue = provider->noDataValue();
threeValueEntry.percentTransparent = 100;
transparentThreeValueList.push_back( threeValueEntry );
tr->setTransparentThreeValuePixelList( transparentThreeValueList );
}
renderer->setRasterTransparency( tr );
#if 0
if ( !renderer )
{
Expand Down
10 changes: 10 additions & 0 deletions src/core/raster/qgssinglebandcolordatarenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,13 @@ void QgsSingleBandColorDataRenderer::writeXML( QDomDocument& doc, QDomElement& p
rasterRendererElem.setAttribute( "band", mBand );
parentElem.appendChild( rasterRendererElem );
}

QList<int> QgsSingleBandColorDataRenderer::usesBands() const
{
QList<int> bandList;
if ( mBand != -1 )
{
bandList << mBand;
}
return bandList;
}
2 changes: 2 additions & 0 deletions src/core/raster/qgssinglebandcolordatarenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ class CORE_EXPORT QgsSingleBandColorDataRenderer: public QgsRasterRenderer

void writeXML( QDomDocument& doc, QDomElement& parentElem ) const;

QList<int> usesBands() const;

private:
int mBand;
};
Expand Down
10 changes: 10 additions & 0 deletions src/core/raster/qgssinglebandgrayrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,3 +199,13 @@ void QgsSingleBandGrayRenderer::legendSymbologyItems( QList< QPair< QString, QCo
symbolItems.push_back( qMakePair( QString::number( mContrastEnhancement->maximumValue() ), QColor( 255, 255, 255 ) ) );
}
}

QList<int> QgsSingleBandGrayRenderer::usesBands() const
{
QList<int> bandList;
if ( mGrayBand != -1 )
{
bandList << mGrayBand;
}
return bandList;
}
2 changes: 2 additions & 0 deletions src/core/raster/qgssinglebandgrayrenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ class CORE_EXPORT QgsSingleBandGrayRenderer: public QgsRasterRenderer

void legendSymbologyItems( QList< QPair< QString, QColor > >& symbolItems ) const;

QList<int> usesBands() const;

private:
int mGrayBand;
QgsContrastEnhancement* mContrastEnhancement;
Expand Down
10 changes: 10 additions & 0 deletions src/core/raster/qgssinglebandpseudocolorrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,3 +191,13 @@ void QgsSingleBandPseudoColorRenderer::legendSymbologyItems( QList< QPair< QStri
}
}
}

QList<int> QgsSingleBandPseudoColorRenderer::usesBands() const
{
QList<int> bandList;
if ( mBand != -1 )
{
bandList << mBand;
}
return bandList;
}
2 changes: 2 additions & 0 deletions src/core/raster/qgssinglebandpseudocolorrenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ class CORE_EXPORT QgsSingleBandPseudoColorRenderer: public QgsRasterRenderer

void legendSymbologyItems( QList< QPair< QString, QColor > >& symbolItems ) const;

QList<int> usesBands() const;

private:
QgsRasterShader* mShader;
int mBand;
Expand Down
9 changes: 9 additions & 0 deletions src/gui/qgsnewhttpconnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,15 @@ void QgsNewHttpConnection::accept()
return;
}

if ( !txtPassword->text().isEmpty() &&
QMessageBox::question( this,
tr( "Saving passwords" ),
tr( "WARNING: You have entered a password. It will be stored in plain text in your project files and in your home directory on Unix-like systems, or in your user profile on Windows. If you do not want this to happen, please press the Cancel button.\nNote: giving the password is optional. It will be requested interactivly, when needed." ),
QMessageBox::Ok | QMessageBox::Cancel ) == QMessageBox::Cancel )
{
return;
}

// on rename delete original entry first
if ( !mOriginalConnName.isNull() && mOriginalConnName != key )
{
Expand Down
33 changes: 18 additions & 15 deletions src/gui/symbology-ng/qgssymbolv2selectordialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,25 +101,28 @@ void QgsSymbolV2SelectorDialog::populateSymbolView()
}
model->clear();

QStringList names = mStyle->symbolNames();
for ( int i = 0; i < names.count(); i++ )
if ( mStyle )
{
QgsSymbolV2* s = mStyle->symbol( names[i] );
if ( s->type() != mSymbol->type() )
QStringList names = mStyle->symbolNames();
for ( int i = 0; i < names.count(); i++ )
{
QgsSymbolV2* s = mStyle->symbol( names[i] );
if ( s->type() != mSymbol->type() )
{
delete s;
continue;
}
QStandardItem* item = new QStandardItem( names[i] );
item->setData( names[i], Qt::UserRole ); //so we can show a label when it is clicked
item->setText( "" ); //set the text to nothing and show in label when clicked rather
item->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable );
// create preview icon
QIcon icon = QgsSymbolLayerV2Utils::symbolPreviewIcon( s, previewSize );
item->setIcon( icon );
// add to model
model->appendRow( item );
delete s;
continue;
}
QStandardItem* item = new QStandardItem( names[i] );
item->setData( names[i], Qt::UserRole ); //so we can show a label when it is clicked
item->setText( "" ); //set the text to nothing and show in label when clicked rather
item->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable );
// create preview icon
QIcon icon = QgsSymbolLayerV2Utils::symbolPreviewIcon( s, previewSize );
item->setIcon( icon );
// add to model
model->appendRow( item );
delete s;
}
}

Expand Down
41 changes: 3 additions & 38 deletions src/mapserver/qgswmsserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
#include "qgslegendmodel.h"
#include "qgscomposerlegenditem.h"
#include "qgslogger.h"
#include "qgspaintenginehack.h"

#include <QImage>
#include <QPainter>
#include <QStringList>
Expand Down Expand Up @@ -505,38 +507,6 @@ QDomDocument QgsWMSServer::getStyle()
return mConfigParser->getStyle( styleName, layerName );
}

// Hack to workaround Qt #5114 by disabling PatternTransform
class QgsPaintEngineHack : public QPaintEngine
{
public:
void fixFlags()
{
gccaps = 0;
gccaps |= ( QPaintEngine::PrimitiveTransform
// | QPaintEngine::PatternTransform
| QPaintEngine::PixmapTransform
| QPaintEngine::PatternBrush
// | QPaintEngine::LinearGradientFill
// | QPaintEngine::RadialGradientFill
// | QPaintEngine::ConicalGradientFill
| QPaintEngine::AlphaBlend
// | QPaintEngine::PorterDuff
| QPaintEngine::PainterPaths
| QPaintEngine::Antialiasing
| QPaintEngine::BrushStroke
| QPaintEngine::ConstantOpacity
| QPaintEngine::MaskedBrush
// | QPaintEngine::PerspectiveTransform
| QPaintEngine::BlendModes
// | QPaintEngine::ObjectBoundingModeGradients
#if QT_VERSION >= 0x040500
| QPaintEngine::RasterOpModes
#endif
| QPaintEngine::PaintOutsidePaintEvent
);
}
};

QByteArray* QgsWMSServer::getPrint( const QString& formatString )
{
QStringList layersList, stylesList, layerIdList;
Expand Down Expand Up @@ -632,12 +602,7 @@ QByteArray* QgsWMSServer::getPrint( const QString& formatString )
QRectF paperRectMM = printer.pageRect( QPrinter::Millimeter );
QRectF paperRectPixel = printer.pageRect( QPrinter::DevicePixel );

QPaintEngine *engine = printer.paintEngine();
if ( engine )
{
QgsPaintEngineHack *hack = static_cast<QgsPaintEngineHack*>( engine );
hack->fixFlags();
}
QgsPaintEngineHack::fixEngineFlags( printer.paintEngine() );

QPainter p( &printer );
if ( c->printAsRaster() ) //embed one raster into the pdf
Expand Down
61 changes: 61 additions & 0 deletions src/providers/gdal/qgsgdalprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -973,6 +973,67 @@ int QgsGdalProvider::yBlockSize() const
int QgsGdalProvider::xSize() const { return mWidth; }
int QgsGdalProvider::ySize() const { return mHeight; }

bool QgsGdalProvider::identify( const QgsPoint & point, QMap<int, QString>& results )
{
// QgsDebugMsg( "Entered" );
if ( !mExtent.contains( point ) )
{
// Outside the raster
for ( int i = 1; i <= GDALGetRasterCount( mGdalDataset ); i++ )
{
results[ i ] = tr( "out of extent" );
}
}
else
{
double x = point.x();
double y = point.y();

// Calculate the row / column where the point falls
double xres = ( mExtent.xMaximum() - mExtent.xMinimum() ) / mWidth;
double yres = ( mExtent.yMaximum() - mExtent.yMinimum() ) / mHeight;

// Offset, not the cell index -> flor
int col = ( int ) floor(( x - mExtent.xMinimum() ) / xres );
int row = ( int ) floor(( mExtent.yMaximum() - y ) / yres );

// QgsDebugMsg( "row = " + QString::number( row ) + " col = " + QString::number( col ) );

for ( int i = 1; i <= GDALGetRasterCount( mGdalDataset ); i++ )
{
GDALRasterBandH gdalBand = GDALGetRasterBand( mGdalDataset, i );
double value;

CPLErr err = GDALRasterIO( gdalBand, GF_Read, col, row, 1, 1,
&value, 1, 1, GDT_Float64, 0, 0 );

if ( err != CPLE_None )
{
QgsLogger::warning( "RasterIO error: " + QString::fromUtf8( CPLGetLastErrorMsg() ) );
}

//double value = readValue( data, type, 0 );
// QgsDebugMsg( QString( "value=%1" ).arg( value ) );
QString v;

if ( mValidNoDataValue && ( fabs( value - mNoDataValue[i-1] ) <= TINY_VALUE || value != value ) )
{
v = tr( "null (no data)" );
}
else
{
v.setNum( value );
}

results[ i ] = v;

//CPLFree( data );
}
}

return true;
}

bool QgsGdalProvider::identify( const QgsPoint& thePoint, QMap<QString, QString>& theResults )
{
// QgsDebugMsg( "Entered" );
Expand Down
2 changes: 2 additions & 0 deletions src/providers/gdal/qgsgdalprovider.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ class QgsGdalProvider : public QgsRasterDataProvider, QgsGdalProviderBase
/** \brief Identify raster value(s) found on the point position */
bool identify( const QgsPoint & point, QMap<QString, QString>& results );

bool identify( const QgsPoint & point, QMap<int, QString>& results );

/**
* \brief Identify details from a GDAL layer from the last screen update
*
Expand Down
12 changes: 3 additions & 9 deletions src/providers/spatialite/qgsspatialiteprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3600,13 +3600,6 @@ bool QgsSpatiaLiteProvider::addFeatures( QgsFeatureList & flist )
values = QString( ") VALUES (" );
separator = "";

if ( !mPrimaryKey.isEmpty() )
{
sql += separator + quotedIdentifier( mPrimaryKey );
values += separator + "NULL";
separator = ",";
}

if ( !mGeometryColumn.isNull() )
{
sql += separator + quotedIdentifier( mGeometryColumn );
Expand All @@ -3621,11 +3614,12 @@ bool QgsSpatiaLiteProvider::addFeatures( QgsFeatureList & flist )
continue;

QString fieldname = fit->name();
if ( fieldname.isEmpty() || fieldname == mGeometryColumn || fieldname == mPrimaryKey )
if ( fieldname.isEmpty() || fieldname == mGeometryColumn )
continue;

sql += separator + quotedIdentifier( fieldname );
values += separator + "?";
separator = ",";
}

sql += values;
Expand Down Expand Up @@ -3673,7 +3667,7 @@ bool QgsSpatiaLiteProvider::addFeatures( QgsFeatureList & flist )
continue;

QString fieldname = fit->name();
if ( fieldname.isEmpty() || fieldname == mGeometryColumn || fieldname == mPrimaryKey )
if ( fieldname.isEmpty() || fieldname == mGeometryColumn )
continue;

QVariant::Type type = fit->type();
Expand Down
2 changes: 2 additions & 0 deletions src/providers/spatialite/qgsspatialitesourceselect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,8 @@ void QgsSpatiaLiteSourceSelect::setConnectionListPosition()
// If possible, set the item currently displayed database
QString toSelect = settings.value( "/SpatiaLite/connections/selected" ).toString();

toSelect += "@" + settings.value( "/SpatiaLite/connections/" + toSelect + "/sqlitepath" ).toString();

cmbConnections->setCurrentIndex( cmbConnections->findText( toSelect ) );

if ( cmbConnections->currentIndex() < 0 )
Expand Down
576 changes: 355 additions & 221 deletions src/ui/qgscomposermapwidgetbase.ui

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion tests/src/core/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Standard includes and utils to compile into all tests.
SET (util_SRCS qgsrenderchecker.cpp)
SET (util_SRCS qgsrenderchecker.cpp qgscompositionchecker.cpp)


#####################################################
Expand All @@ -8,6 +8,7 @@ SET (util_SRCS qgsrenderchecker.cpp)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_SOURCE_DIR}/src/core
${CMAKE_SOURCE_DIR}/src/core/composer
${CMAKE_SOURCE_DIR}/src/core/raster
${CMAKE_SOURCE_DIR}/src/core/renderer
${CMAKE_SOURCE_DIR}/src/core/symbology
Expand Down Expand Up @@ -96,3 +97,4 @@ ADD_QGIS_TEST(vectorlayertest testqgsvectorlayer.cpp)
ADD_QGIS_TEST(rulebasedrenderertest testqgsrulebasedrenderer.cpp)
ADD_QGIS_TEST(ziplayertest testziplayer.cpp)
ADD_QGIS_TEST(dataitemtest testqgsdataitem.cpp)
ADD_QGIS_TEST(composermaptest testqgscomposermap.cpp)
133 changes: 133 additions & 0 deletions tests/src/core/qgscompositionchecker.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/***************************************************************************
qgscompositionchecker.cpp - check rendering of Qgscomposition against an expected image
--------------------------------------
Date : 5 Juli 2012
Copyright : (C) 2012 by Marco Hugentobler
email : marco@sourcepole.ch
***************************************************************************
* *
* 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 "qgscompositionchecker.h"
#include "qgscomposition.h"
#include <QDebug>
#include <QDir>
#include <QFileInfo>
#include <QImage>
#include <QPainter>

QgsCompositionChecker::QgsCompositionChecker( const QString& testName, QgsComposition* composition, const QString& expectedImageFile ): mTestName( testName ),
mComposition( composition ), mExpectedImageFile( expectedImageFile )
{
}

QgsCompositionChecker::QgsCompositionChecker()
{
}

QgsCompositionChecker::~QgsCompositionChecker()
{
}

bool QgsCompositionChecker::testComposition()
{
if ( !mComposition )
{
return false;
}

#if 0 //fake mode to generate expected image
//assume 300 dpi and size of the control image 3507 * 2480
QImage outputImage( QSize( 3507, 2480 ), QImage::Format_ARGB32 );
mComposition->setPlotStyle( QgsComposition::Print );
outputImage.setDotsPerMeterX( 300 / 25.4 * 1000 );
outputImage.setDotsPerMeterY( 300 / 25.4 * 1000 );
outputImage.fill( 0 );
QPainter p( &outputImage );
QRectF sourceArea( 0, 0, mComposition->paperWidth(), mComposition->paperHeight() );
QRectF targetArea( 0, 0, 3507, 2480 );
mComposition->render( &p, targetArea, sourceArea );
p.end();
outputImage.save( "/tmp/composermap_control.png", "PNG" );
return false;
#endif //0

//load expected image
QImage expectedImage( mExpectedImageFile );

//get width/height, create image and render the composition to it
int width = expectedImage.width();
int height = expectedImage.height();
QImage outputImage( QSize( width, height ), QImage::Format_ARGB32 );

mComposition->setPlotStyle( QgsComposition::Print );
outputImage.setDotsPerMeterX( expectedImage.dotsPerMeterX() );
outputImage.setDotsPerMeterY( expectedImage.dotsPerMeterX() );
outputImage.fill( 0 );
QPainter p( &outputImage );
QRectF sourceArea( 0, 0, mComposition->paperWidth(), mComposition->paperHeight() );
QRectF targetArea( 0, 0, width, height );
mComposition->render( &p, targetArea, sourceArea );
p.end();

QString renderedFilePath = QDir::tempPath() + QDir::separator() + QFileInfo( mExpectedImageFile ).baseName() + "_rendered.png";
outputImage.save( renderedFilePath, "PNG" );

QString diffFilePath = QDir::tempPath() + QDir::separator() + QFileInfo( mExpectedImageFile ).baseName() + "_diff.png";
bool testResult = compareImages( expectedImage, outputImage, diffFilePath );

QString myDashMessage = "<DartMeasurementFile name=\"Rendered Image " + mTestName + "\""
" type=\"image/png\">" + renderedFilePath +
"</DartMeasurementFile>"
"<DartMeasurementFile name=\"Expected Image " + mTestName + "\" type=\"image/png\">" +
mExpectedImageFile + "</DartMeasurementFile>"
"<DartMeasurementFile name=\"Difference Image " + mTestName + "\" type=\"image/png\">" +
diffFilePath + "</DartMeasurementFile>";
qDebug( ) << myDashMessage;

return testResult;
}

bool QgsCompositionChecker::compareImages( const QImage& imgExpected, const QImage& imgRendered, const QString& differenceImagePath ) const
{
if ( imgExpected.width() != imgRendered.width() || imgExpected.height() != imgRendered.height() )
{
return false;
}

int imageWidth = imgExpected.width();
int imageHeight = imgExpected.height();
int mismatchCount = 0;

QImage differenceImage( imageWidth, imageHeight, QImage::Format_ARGB32_Premultiplied );
differenceImage.fill( qRgb( 152, 219, 249 ) );

QRgb pixel1, pixel2;
for ( int i = 0; i < imageHeight; ++i )
{
for ( int j = 0; j < imageWidth; ++j )
{
pixel1 = imgExpected.pixel( j, i );
pixel2 = imgRendered.pixel( j, i );
if ( pixel1 != pixel2 )
{
++mismatchCount;
differenceImage.setPixel( j, i, qRgb( 255, 0, 0 ) );
}
}
}

if ( !differenceImagePath.isEmpty() )
{
differenceImage.save( differenceImagePath, "PNG" );
}

//allow pixel deviation of 1 percent
int pixelCount = imageWidth * imageHeight;
return (( double )mismatchCount / ( double )pixelCount ) < 0.01;
}
41 changes: 41 additions & 0 deletions tests/src/core/qgscompositionchecker.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/***************************************************************************
qgscompositionchecker.h - check rendering of Qgscomposition against an expected image
--------------------------------------
Date : 5 Juli 2012
Copyright : (C) 2012 by Marco Hugentobler
email : marco@sourcepole.ch
***************************************************************************
* *
* 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. *
* *
***************************************************************************/

#ifndef QGSCOMPOSITIONCHECKER_H
#define QGSCOMPOSITIONCHECKER_H

#include <QString>
class QgsComposition;
class QImage;

/**Renders a composition to an image and compares with an expected output*/
class QgsCompositionChecker
{
public:
QgsCompositionChecker( const QString& testName, QgsComposition* composition, const QString& expectedImageFile );
~QgsCompositionChecker();

bool testComposition();

private:
QgsCompositionChecker(); //forbidden
bool compareImages( const QImage& imgExpected, const QImage& imgRendered, const QString& differenceImagePath = QString() ) const;

QString mTestName;
QgsComposition* mComposition;
QString mExpectedImageFile;
};

#endif // QGSCOMPOSITIONCHECKER_H
135 changes: 135 additions & 0 deletions tests/src/core/testqgscomposermap.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
/***************************************************************************
testqgscomposermap.cpp
----------------------
begin : Juli 2012
copyright : (C) 2012 by Marco Hugentobler
email : marco at sourcepole dot ch
***************************************************************************/

/***************************************************************************
* *
* 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 "qgsapplication.h"
#include "qgscomposition.h"
#include "qgscompositionchecker.h"
#include "qgscomposermap.h"
#include "qgsmaplayerregistry.h"
#include "qgsmaprenderer.h"
#include "qgsmultibandcolorrenderer.h"
#include "qgsrasterlayer.h"
#include <QObject>
#include <QtTest>

class TestQgsComposerMap: public QObject
{
Q_OBJECT;
private slots:
void initTestCase();// will be called before the first testfunction is executed.
void cleanupTestCase();// will be called after the last testfunction was executed.
void init();// will be called before each testfunction is executed.
void cleanup();// will be called after every testfunction.
void render(); //test if rendering of the composition with composr map is correct
void grid(); //test if grid and grid annotation works
void overviewMap(); //test if overview map frame works

private:
QgsComposition* mComposition;
QgsComposerMap* mComposerMap;
QgsMapRenderer* mMapRenderer;
QgsRasterLayer* mRasterLayer;
};

void TestQgsComposerMap::initTestCase()
{
QgsApplication::init( QString() );
QgsApplication::initQgis();

//create maplayers from testdata and add to layer registry
QFileInfo rasterFileInfo( QString( TEST_DATA_DIR ) + QDir::separator() + "landsat.tif" );
mRasterLayer = new QgsRasterLayer( rasterFileInfo.filePath(),
rasterFileInfo.completeBaseName() );
QgsMultiBandColorRenderer* rasterRenderer = new QgsMultiBandColorRenderer( mRasterLayer->dataProvider(), 2, 3, 4 );
mRasterLayer->setRenderer( rasterRenderer );

QgsMapLayerRegistry::instance()->addMapLayers( QList<QgsMapLayer*>() << mRasterLayer );

//create composition with composer map
mMapRenderer = new QgsMapRenderer();
mMapRenderer->setLayerSet( QStringList() << mRasterLayer->id() );
mMapRenderer->setProjectionsEnabled( false );
mComposition = new QgsComposition( mMapRenderer );
mComposition->setPaperSize( 297, 210 ); //A4 landscape
mComposerMap = new QgsComposerMap( mComposition, 20, 20, 200, 100 );
mComposition->addComposerMap( mComposerMap );
}

void TestQgsComposerMap::cleanupTestCase()
{
delete mComposition;
delete mMapRenderer;
delete mRasterLayer;
}

void TestQgsComposerMap::init()
{

}

void TestQgsComposerMap::cleanup()
{

}

void TestQgsComposerMap::render()
{
mComposerMap->setNewExtent( QgsRectangle( 781662.375, 3339523.125, 793062.375, 3345223.125 ) );
QgsCompositionChecker checker( "Composer map render", mComposition, QString( QString( TEST_DATA_DIR ) + QDir::separator() +
"control_images" + QDir::separator() + "expected_composermap" + QDir::separator() + "composermap_landsat_render.png" ) );
QVERIFY( checker.testComposition() );
}

void TestQgsComposerMap::grid()
{
mComposerMap->setNewExtent( QgsRectangle( 781662.375, 3339523.125, 793062.375, 3345223.125 ) );
mComposerMap->setGridEnabled( true );
mComposerMap->setGridIntervalX( 2000 );
mComposerMap->setGridIntervalY( 2000 );
mComposerMap->setShowGridAnnotation( true );
mComposerMap->setGridPenWidth( 0.5 );
mComposerMap->setGridAnnotationPrecision( 0 );
mComposerMap->setGridAnnotationPosition( QgsComposerMap::Disabled, QgsComposerMap::Left );
mComposerMap->setGridAnnotationPosition( QgsComposerMap::OutsideMapFrame, QgsComposerMap::Right );
mComposerMap->setGridAnnotationPosition( QgsComposerMap::Disabled, QgsComposerMap::Top );
mComposerMap->setGridAnnotationPosition( QgsComposerMap::OutsideMapFrame, QgsComposerMap::Bottom );
mComposerMap->setGridAnnotationDirection( QgsComposerMap::Horizontal, QgsComposerMap::Right );
mComposerMap->setGridAnnotationDirection( QgsComposerMap::Horizontal, QgsComposerMap::Bottom );
QgsCompositionChecker checker( "Composer map grid", mComposition, QString( QString( TEST_DATA_DIR ) + QDir::separator() +
"control_images" + QDir::separator() + "expected_composermap" + QDir::separator() + "composermap_landsat_grid.png" ) );
bool testResult = checker.testComposition();
mComposerMap->setGridEnabled( false );
mComposerMap->setShowGridAnnotation( false );
QVERIFY( testResult );
}

void TestQgsComposerMap::overviewMap()
{
QgsComposerMap* overviewMap = new QgsComposerMap( mComposition, 20, 130, 70, 70 );
mComposition->addComposerMap( overviewMap );
mComposerMap->setNewExtent( QgsRectangle( 785462.375, 3341423.125, 789262.375, 3343323.125 ) ); //zoom in
overviewMap->setNewExtent( QgsRectangle( 781662.375, 3339523.125, 793062.375, 3350923.125 ) );
overviewMap->setOverviewFrameMap( mComposerMap->id() );
QgsCompositionChecker checker( "Composer map overview", mComposition, QString( QString( TEST_DATA_DIR ) + QDir::separator() +
"control_images" + QDir::separator() + "expected_composermap" + QDir::separator() + "composermap_landsat_overview.png" ) );
bool testResult = checker.testComposition();
mComposition->removeComposerItem( overviewMap );
QVERIFY( testResult );
}

QTEST_MAIN( TestQgsComposerMap )
#include "moc_testqgscomposermap.cxx"
2 changes: 2 additions & 0 deletions tests/src/core/testqgsexpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,8 @@ class TestQgsExpression: public QObject
QTest::newRow( "regexp_replace invalid" ) << "regexp_replace('HeLLo','[[[', '-')" << true << QVariant();
QTest::newRow( "substr" ) << "substr('HeLLo', 3,2)" << false << QVariant( "LL" );
QTest::newRow( "substr outside" ) << "substr('HeLLo', -5,2)" << false << QVariant( "" );
QTest::newRow( "strpos" ) << "strpos('Hello World','World')" << false << QVariant( 6 );
QTest::newRow( "strpos outside" ) << "strpos('Hello World','blah')" << false << QVariant( -1 );

// implicit conversions
QTest::newRow( "implicit int->text" ) << "length(123)" << false << QVariant( 3 );
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.