Skip to content

Commit c0f7960

Browse files
committedAug 24, 2012
Merge branch 'master' of github.com:qgis/Quantum-GIS
2 parents 9d96e76 + f5c7753 commit c0f7960

23 files changed

+1880
-1237
lines changed
 

‎python/core/qgscomposermultiframe.sip

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,5 @@ public:
4343
void deleteFrames();
4444

4545
int nFrames() const;
46+
QgsComposerFrame* frame( int i );
4647
};

‎src/app/qgisapp.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@
163163
#include "qgsrasteriterator.h"
164164
#include "qgsrasterlayer.h"
165165
#include "qgsrasterlayerproperties.h"
166+
#include "qgsrasternuller.h"
166167
#include "qgsrasterrenderer.h"
167168
#include "qgsrasterlayersaveasdialog.h"
168169
#include "qgsrectangle.h"
@@ -3924,7 +3925,7 @@ void QgisApp::saveAsRasterFile()
39243925
return;
39253926
}
39263927

3927-
QgsRasterLayerSaveAsDialog d( rasterLayer->dataProvider(), mMapCanvas->extent(), rasterLayer->crs(), mMapCanvas->mapRenderer()->destinationCrs() );
3928+
QgsRasterLayerSaveAsDialog d( rasterLayer, rasterLayer->dataProvider(), mMapCanvas->extent(), rasterLayer->crs(), mMapCanvas->mapRenderer()->destinationCrs() );
39283929
if ( d.exec() == QDialog::Accepted )
39293930
{
39303931
QgsRasterFileWriter fileWriter( d.outputFileName() );
@@ -3953,12 +3954,21 @@ void QgisApp::saveAsRasterFile()
39533954
QgsDebugMsg( "Cannot set pipe provider" );
39543955
return;
39553956
}
3957+
3958+
QgsRasterNuller *nuller = new QgsRasterNuller();
3959+
nuller->setNoData( d.noData() );
3960+
if ( !pipe->insert( 1, nuller ) )
3961+
{
3962+
QgsDebugMsg( "Cannot set pipe nuller" );
3963+
return;
3964+
}
3965+
39563966
// add projector if necessary
39573967
if ( d.outputCrs() != rasterLayer->crs() )
39583968
{
39593969
QgsRasterProjector * projector = new QgsRasterProjector;
39603970
projector->setCRS( rasterLayer->crs(), d.outputCrs() );
3961-
if ( !pipe->set( projector ) )
3971+
if ( !pipe->insert( 2, projector ) )
39623972
{
39633973
QgsDebugMsg( "Cannot set pipe projector" );
39643974
return;

‎src/app/qgslabelinggui.cpp

Lines changed: 140 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -180,9 +180,6 @@ QgsLabelingGui::QgsLabelingGui( QgsPalLabeling* lbl, QgsVectorLayer* layer, QgsM
180180
mBufferTranspFillChbx->setChecked( !lyr.bufferNoFill );
181181
}
182182

183-
btnTextColor->setColor( lyr.textColor );
184-
mFontTranspSpinBox->setValue( lyr.textTransp );
185-
186183
bool formattedNumbers = lyr.formatNumbers;
187184
bool plusSign = lyr.plusSign;
188185

@@ -205,9 +202,14 @@ QgsLabelingGui::QgsLabelingGui( QgsPalLabeling* lbl, QgsVectorLayer* layer, QgsM
205202
mFontSizeUnitComboBox->setCurrentIndex( 0 );
206203
}
207204

208-
QFont textFont = lyr.textFont;
209-
updateFont( textFont );
210-
mFontSizeSpinBox->setValue( textFont.pointSizeF() );
205+
mRefFont = lyr.textFont;
206+
mFontSizeSpinBox->setValue( mRefFont.pointSizeF() );
207+
btnTextColor->setColor( lyr.textColor );
208+
mFontTranspSpinBox->setValue( lyr.textTransp );
209+
210+
updateFontViaStyle( lyr.textNamedStyle );
211+
updateFont( mRefFont );
212+
211213
updateUi();
212214

213215
updateOptions();
@@ -302,6 +304,7 @@ QgsPalLayerSettings QgsLabelingGui::layerSettings()
302304

303305
lyr.textColor = btnTextColor->color();
304306
lyr.textFont = mRefFont;
307+
lyr.textNamedStyle = mFontStyleComboBox->currentText();
305308
lyr.textTransp = mFontTranspSpinBox->value();
306309
lyr.previewBkgrdColor = mPreviewBackgroundBtn->color();
307310
lyr.enabled = chkEnableLabeling->isChecked();
@@ -528,6 +531,40 @@ void QgsLabelingGui::changeTextFont()
528531
}
529532
}
530533

534+
void QgsLabelingGui::updateFontViaStyle( const QString & fontstyle )
535+
{
536+
QFont styledfont;
537+
bool foundmatch = false;
538+
if ( !fontstyle.isEmpty() )
539+
{
540+
styledfont = mFontDB.font( mRefFont.family(), fontstyle, mRefFont.pointSizeF() );
541+
if ( QApplication::font().toString() != styledfont.toString() )
542+
{
543+
foundmatch = true;
544+
}
545+
}
546+
if ( !foundmatch )
547+
{
548+
foreach ( const QString &style, mFontDB.styles( mRefFont.family() ) )
549+
{
550+
styledfont = mFontDB.font( mRefFont.family(), style, mRefFont.pointSizeF() );
551+
styledfont = styledfont.resolve( mRefFont );
552+
if ( mRefFont.toString() == styledfont.toString() )
553+
{
554+
foundmatch = true;
555+
break;
556+
}
557+
}
558+
}
559+
if ( foundmatch )
560+
{
561+
styledfont.setUnderline( mRefFont.underline() );
562+
styledfont.setStrikeOut( mRefFont.strikeOut() );
563+
mRefFont = styledfont;
564+
}
565+
// if no match, style combobox will be left blank, which should not affect engine labeling
566+
}
567+
531568
void QgsLabelingGui::updateFont( QFont font )
532569
{
533570
// update background reference font
@@ -536,62 +573,106 @@ void QgsLabelingGui::updateFont( QFont font )
536573
mRefFont = font;
537574
}
538575

539-
lblFontName->setText( QString( "%1" ).arg( font.family() ) );
576+
// test if font is actually available
577+
QString missingtxt = QString( "" );
578+
bool missing = false;
579+
if ( QApplication::font().toString() != mRefFont.toString() )
580+
{
581+
QFont testfont = mFontDB.font( mRefFont.family(), mFontDB.styleString( mRefFont ), mRefFont.pointSizeF() );
582+
if ( QApplication::font().toString() == testfont.toString() )
583+
{
584+
missing = true;
585+
}
586+
}
587+
if ( missing )
588+
{
589+
missingtxt = tr( " (not found!)" );
590+
lblFontName->setStyleSheet( "color: #990000;" );
591+
}
592+
else
593+
{
594+
lblFontName->setStyleSheet( "color: #000000;" );
595+
}
596+
597+
lblFontName->setText( QString( "%1%2" ).arg( mRefFont.family() ).arg( missingtxt ) );
598+
599+
blockFontChangeSignals( true );
600+
populateFontStyleComboBox();
601+
mFontUnderlineBtn->setChecked( mRefFont.underline() );
602+
mFontStrikethroughBtn->setChecked( mRefFont.strikeOut() );
603+
blockFontChangeSignals( false );
540604

541605
// update font name with font face
542-
// QString dupFont = font.toString();
543-
// QFont lblFont = lblFontName->font();
544-
// lblFont.fromString( dupFont );
545-
// lblFont.setPointSizeF( 14 );
546-
// lblFontName->setFont(lblFont);
606+
// font.setPixelSize( 18 );
607+
// lblFontName->setFont( QFont( font ) );
547608

548609
updatePreview();
549610
}
550611

612+
void QgsLabelingGui::blockFontChangeSignals( bool blk )
613+
{
614+
mFontStyleComboBox->blockSignals( blk );
615+
mFontUnderlineBtn->blockSignals( blk );
616+
mFontStrikethroughBtn->blockSignals( blk );
617+
}
618+
551619
void QgsLabelingGui::updatePreview()
552620
{
553621
scrollPreview();
554622
lblFontPreview->setFont( mRefFont );
555623
QFont previewFont = lblFontPreview->font();
556624
double fontSize = mFontSizeSpinBox->value();
557-
double bufferSize = spinBufferSize->value();
558-
if ( mFontSizeUnitComboBox->currentIndex() == 1 )
625+
double bufferSize = 0.0;
626+
QString grpboxtitle;
627+
628+
if ( mFontSizeUnitComboBox->currentIndex() == 1 ) // map units
559629
{
560630
// TODO: maybe match current map zoom level instead?
561631
previewFont.setPointSize( mPreviewSize );
562632
mPreviewSizeSlider->setEnabled( true );
563-
if ( mBufferUnitComboBox->currentIndex() == 1 )
564-
{
565-
groupBox_mPreview->setTitle( tr( "Sample @ %1 pts (using map units)" ).arg( mPreviewSize ) );
566-
bufferSize = ( mPreviewSize / fontSize ) * bufferSize / 2.5;
567-
}
568-
else
633+
grpboxtitle = tr( "Sample @ %1 pts (using map units)" ).arg( mPreviewSize );
634+
635+
if ( chkBuffer->isChecked() )
569636
{
570-
groupBox_mPreview->setTitle( tr( "Sample @ %1 pts (using map units, STROKE IN mm)" ).arg( mPreviewSize ) );
637+
if ( mBufferUnitComboBox->currentIndex() == 1 ) // map units
638+
{
639+
bufferSize = ( mPreviewSize / fontSize ) * spinBufferSize->value() / 2.5;
640+
}
641+
else // millimeters
642+
{
643+
grpboxtitle = tr( "Sample @ %1 pts (using map units, BUFFER IN MILLIMETERS)" ).arg( mPreviewSize );
644+
bufferSize = spinBufferSize->value();
645+
}
571646
}
572647
}
573-
else
648+
else // in points
574649
{
650+
previewFont.setPointSize( fontSize );
575651
mPreviewSizeSlider->setEnabled( false );
576-
if ( mBufferUnitComboBox->currentIndex() == 1 )
577-
{
578-
groupBox_mPreview->setTitle( tr( "Sample (stroke in map units, NOT SHOWN)" ) );
579-
bufferSize = 0;
580-
}
581-
else
652+
grpboxtitle = tr( "Sample" );
653+
654+
if ( chkBuffer->isChecked() )
582655
{
583-
previewFont.setPointSize( fontSize );
584-
groupBox_mPreview->setTitle( tr( "Sample" ) );
656+
if ( mBufferUnitComboBox->currentIndex() == 0 ) // millimeters
657+
{
658+
bufferSize = spinBufferSize->value();
659+
}
660+
else // map units
661+
{
662+
grpboxtitle = tr( "Sample (BUFFER NOT SHOWN, in map units)" );
663+
}
585664
}
586665
}
666+
587667
lblFontPreview->setFont( previewFont );
668+
groupBox_mPreview->setTitle( grpboxtitle );
588669

589670
QColor prevColor = btnTextColor->color();
590671
prevColor.setAlphaF(( 100.0 - ( double )( mFontTranspSpinBox->value() ) ) / 100.0 );
591672
lblFontPreview->setTextColor( prevColor );
592673

593674
bool bufferNoFill = false;
594-
if ( chkBuffer->isChecked() )
675+
if ( chkBuffer->isChecked() && bufferSize != 0.0 )
595676
{
596677
QColor buffColor = btnBufferColor->color();
597678
buffColor.setAlphaF(( 100.0 - ( double )( mBufferTranspSpinBox->value() ) ) / 100.0 );
@@ -688,6 +769,16 @@ void QgsLabelingGui::updateOptions()
688769
}
689770
}
690771

772+
void QgsLabelingGui::populateFontStyleComboBox()
773+
{
774+
mFontStyleComboBox->clear();
775+
foreach ( const QString &style, mFontDB.styles( mRefFont.family() ) )
776+
{
777+
mFontStyleComboBox->addItem( style );
778+
}
779+
mFontStyleComboBox->setCurrentIndex( mFontStyleComboBox->findText( mFontDB.styleString( mRefFont ) ) );
780+
}
781+
691782
void QgsLabelingGui::on_mPreviewSizeSlider_valueChanged( int i )
692783
{
693784
mPreviewSize = i;
@@ -700,6 +791,24 @@ void QgsLabelingGui::on_mFontSizeSpinBox_valueChanged( double d )
700791
updateFont( mRefFont );
701792
}
702793

794+
void QgsLabelingGui::on_mFontStyleComboBox_currentIndexChanged( const QString & text )
795+
{
796+
updateFontViaStyle( text );
797+
updateFont( mRefFont );
798+
}
799+
800+
void QgsLabelingGui::on_mFontUnderlineBtn_toggled( bool ckd )
801+
{
802+
mRefFont.setUnderline( ckd );
803+
updateFont( mRefFont );
804+
}
805+
806+
void QgsLabelingGui::on_mFontStrikethroughBtn_toggled( bool ckd )
807+
{
808+
mRefFont.setStrikeOut( ckd );
809+
updateFont( mRefFont );
810+
}
811+
703812
void QgsLabelingGui::on_mFontWordSpacingSpinBox_valueChanged( double spacing )
704813
{
705814
mRefFont.setWordSpacing( spacing );

‎src/app/qgslabelinggui.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#define QgsLabelingGUI_H
2020

2121
#include <QDialog>
22+
#include <QFontDatabase>
2223
#include <ui_qgslabelingguibase.h>
2324

2425
class QgsVectorLayer;
@@ -51,6 +52,9 @@ class QgsLabelingGui : public QWidget, private Ui::QgsLabelingGuiBase
5152

5253
void on_mPreviewSizeSlider_valueChanged( int i );
5354
void on_mFontSizeSpinBox_valueChanged( double d );
55+
void on_mFontStyleComboBox_currentIndexChanged( const QString & text );
56+
void on_mFontUnderlineBtn_toggled( bool ckd );
57+
void on_mFontStrikethroughBtn_toggled( bool ckd );
5458
void on_mFontWordSpacingSpinBox_valueChanged( double spacing );
5559
void on_mFontLetterSpacingSpinBox_valueChanged( double spacing );
5660
void on_mBufferUnitComboBox_currentIndexChanged( int index );
@@ -62,6 +66,10 @@ class QgsLabelingGui : public QWidget, private Ui::QgsLabelingGuiBase
6266
void on_mPreviewBackgroundBtn_clicked();
6367

6468
protected:
69+
void blockFontChangeSignals( bool blk );
70+
void setPreviewBackground( QColor color );
71+
void updateFontViaStyle( const QString & fontstyle );
72+
void populateFontStyleComboBox();
6573
void populatePlacementMethods();
6674
void populateFieldNames();
6775
void populateDataDefinedCombos( QgsPalLayerSettings& s );
@@ -74,11 +82,11 @@ class QgsLabelingGui : public QWidget, private Ui::QgsLabelingGuiBase
7482
QgsPalLabeling* mLBL;
7583
QgsVectorLayer* mLayer;
7684
QgsMapCanvas* mMapCanvas;
85+
QFontDatabase mFontDB;
7786

7887
// background reference font
7988
QFont mRefFont;
8089
int mPreviewSize;
81-
void setPreviewBackground( QColor color );
8290

8391
void disableDataDefinedAlignment();
8492
void enableDataDefinedAlignment();

‎src/app/qgslabelpreview.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,12 @@ void QgsLabelPreview::paintEvent( QPaintEvent *e )
6161
if ( mBufferSize != 0 )
6262
QgsPalLabeling::drawLabelBuffer( &p, text(), font(), mBufferSize, mBufferColor, mBufferJoinStyle, mBufferNoFill );
6363

64-
p.setPen( mTextColor );
65-
p.drawText( 0, 0, text() );
64+
QPainterPath path;
65+
path.addText( 0, 0, font(), text() );
66+
p.setPen( Qt::NoPen );
67+
p.setBrush( mTextColor );
68+
p.drawPath( path );
69+
70+
// p.setPen( mTextColor );
71+
// p.drawText( 0, 0, text() );
6672
}

‎src/core/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ SET(QGIS_CORE_SRCS
166166
raster/qgsrasterinterface.cpp
167167
raster/qgsrasteriterator.cpp
168168
raster/qgsrasterlayer.cpp
169+
raster/qgsrasternuller.cpp
169170
raster/qgsrastertransparency.cpp
170171
raster/qgsrasterpipe.cpp
171172
raster/qgsrastershader.cpp

‎src/core/composer/qgscomposermultiframe.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,15 @@ void QgsComposerMultiFrame::deleteFrames()
238238
mResizeMode = bkResizeMode;
239239
}
240240

241+
QgsComposerFrame* QgsComposerMultiFrame::frame( int i )
242+
{
243+
if ( i >= mFrameItems.size() )
244+
{
245+
return 0;
246+
}
247+
return mFrameItems.at( i );
248+
}
249+
241250
bool QgsComposerMultiFrame::_writeXML( QDomElement& elem, QDomDocument& doc, bool ignoreFrames ) const
242251
{
243252
elem.setAttribute( "resizeMode", mResizeMode );

‎src/core/composer/qgscomposermultiframe.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ class CORE_EXPORT QgsComposerMultiFrame: public QObject
7070
void deleteFrames();
7171

7272
int nFrames() const { return mFrameItems.size(); }
73+
QgsComposerFrame* frame( int i );
7374

7475
protected:
7576
QgsComposition* mComposition;

‎src/core/qgspallabeling.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131

3232
#include <cmath>
3333

34+
#include <QApplication>
3435
#include <QByteArray>
3536
#include <QString>
3637
#include <QFontMetrics>
@@ -142,6 +143,7 @@ QgsPalLayerSettings::QgsPalLayerSettings()
142143
placement = AroundPoint;
143144
placementFlags = 0;
144145
//textFont = QFont();
146+
textNamedStyle = QString( "" );
145147
textColor = Qt::black;
146148
textTransp = 0;
147149
previewBkgrdColor = Qt::white;
@@ -180,6 +182,7 @@ QgsPalLayerSettings::QgsPalLayerSettings( const QgsPalLayerSettings& s )
180182
placement = s.placement;
181183
placementFlags = s.placementFlags;
182184
textFont = s.textFont;
185+
textNamedStyle = s.textNamedStyle;
183186
textColor = s.textColor;
184187
textTransp = s.textTransp;
185188
previewBkgrdColor = s.previewBkgrdColor;
@@ -319,6 +322,18 @@ static void _readDataDefinedPropertyMap( QgsVectorLayer* layer, QMap< QgsPalLaye
319322
_readDataDefinedProperty( layer, QgsPalLayerSettings::BufferTransp, propertyMap );
320323
}
321324

325+
void QgsPalLayerSettings::updateFontViaStyle( const QString & fontstyle )
326+
{
327+
if ( !fontstyle.isEmpty() )
328+
{
329+
QFont styledfont = mFontDB.font( textFont.family(), fontstyle, textFont.pointSizeF() );
330+
if ( QApplication::font().toString() != styledfont.toString() )
331+
{
332+
textFont = styledfont;
333+
}
334+
}
335+
}
336+
322337
void QgsPalLayerSettings::readFromLayer( QgsVectorLayer* layer )
323338
{
324339
if ( layer->customProperty( "labeling" ).toString() != QString( "pal" ) )
@@ -333,9 +348,11 @@ void QgsPalLayerSettings::readFromLayer( QgsVectorLayer* layer )
333348
int fontWeight = layer->customProperty( "labeling/fontWeight" ).toInt();
334349
bool fontItalic = layer->customProperty( "labeling/fontItalic" ).toBool();
335350
textFont = QFont( fontFamily, fontSize, fontWeight, fontItalic );
351+
textFont.setPointSizeF( fontSize ); //double precision needed because of map units
352+
textNamedStyle = layer->customProperty( "labeling/namedStyle", QVariant( "" ) ).toString();
353+
updateFontViaStyle( textNamedStyle );
336354
textFont.setUnderline( layer->customProperty( "labeling/fontUnderline" ).toBool() );
337355
textFont.setStrikeOut( layer->customProperty( "labeling/fontStrikeout" ).toBool() );
338-
textFont.setPointSizeF( fontSize ); //double precision needed because of map units
339356
textColor = _readColor( layer, "labeling/textColor" );
340357
textTransp = layer->customProperty( "labeling/textTransp" ).toInt();
341358
previewBkgrdColor = QColor( layer->customProperty( "labeling/previewBkgrdColor", "#ffffff" ).toString() );
@@ -376,6 +393,7 @@ void QgsPalLayerSettings::writeToLayer( QgsVectorLayer* layer )
376393
layer->setCustomProperty( "labeling/placementFlags", ( unsigned int )placementFlags );
377394

378395
layer->setCustomProperty( "labeling/fontFamily", textFont.family() );
396+
layer->setCustomProperty( "labeling/namedStyle", textNamedStyle );
379397
layer->setCustomProperty( "labeling/fontSize", textFont.pointSizeF() );
380398
layer->setCustomProperty( "labeling/fontWeight", textFont.weight() );
381399
layer->setCustomProperty( "labeling/fontItalic", textFont.italic() );

‎src/core/qgspallabeling.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ struct QgsDiagramLayerSettings;
3232

3333
#include <QString>
3434
#include <QFont>
35+
#include <QFontDatabase>
3536
#include <QColor>
3637
#include <QHash>
3738
#include <QList>
@@ -118,6 +119,7 @@ class CORE_EXPORT QgsPalLayerSettings
118119
Placement placement;
119120
unsigned int placementFlags;
120121
QFont textFont;
122+
QString textNamedStyle;
121123
QColor textColor;
122124
int textTransp;
123125
QColor previewBkgrdColor;
@@ -187,6 +189,10 @@ class CORE_EXPORT QgsPalLayerSettings
187189
@return true if above size, false if below*/
188190
bool checkMinimumSizeMM( const QgsRenderContext& ct, QgsGeometry* geom, double minSize ) const;
189191
QgsExpression* expression;
192+
193+
QFontDatabase mFontDB;
194+
/**Updates layer font with one of its named styles */
195+
void updateFontViaStyle( const QString & fontstyle );
190196
};
191197

192198
class CORE_EXPORT QgsLabelCandidate

‎src/core/qgsrasterdataprovider.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -525,8 +525,11 @@ class CORE_EXPORT QgsRasterDataProvider : public QgsDataProvider, public QgsRast
525525
return false;
526526
}
527527

528-
/** Set no data value on created dataset */
529-
virtual bool setNoDataValue( int, double ) { return false; }
528+
/** Set no data value on created dataset
529+
* @param bandNo band number
530+
* @param noDataValue no data value
531+
*/
532+
virtual bool setNoDataValue( int bandNo, double noDataValue ) { Q_UNUSED( bandNo ); Q_UNUSED( noDataValue ); return false; }
530533

531534
/**Returns the formats supported by create()*/
532535
virtual QStringList createFormats() const { return QStringList(); }

‎src/core/raster/qgsrasterinterface.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,3 +209,4 @@ double QgsRasterInterface::time( bool cumulative )
209209
}
210210
return t;
211211
}
212+

‎src/core/raster/qgsrasterinterface.h

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222

2323
#include "qgsrectangle.h"
2424

25+
#include "gdal.h"
26+
2527
/** \ingroup core
2628
* Base class for processing modules.
2729
*/
@@ -196,6 +198,9 @@ class CORE_EXPORT QgsRasterInterface
196198
// On/off state, if off, it does not do anything, replicates input
197199
bool mOn;
198200

201+
inline double readValue( void *data, QgsRasterInterface::DataType type, int index );
202+
inline void writeValue( void *data, QgsRasterInterface::DataType type, int index, double value );
203+
199204
private:
200205
// Last rendering cumulative (this and all preceding interfaces) times, from index 1
201206
QVector<double> mTime;
@@ -204,6 +209,84 @@ class CORE_EXPORT QgsRasterInterface
204209
int mStatsOn;
205210
};
206211

212+
inline double QgsRasterInterface::readValue( void *data, QgsRasterInterface::DataType type, int index )
213+
{
214+
if ( !mInput )
215+
{
216+
return 0;
217+
}
218+
219+
if ( !data )
220+
{
221+
return mInput->noDataValue();
222+
}
223+
224+
switch ( type )
225+
{
226+
case QgsRasterInterface::Byte:
227+
return ( double )(( GByte * )data )[index];
228+
break;
229+
case QgsRasterInterface::UInt16:
230+
return ( double )(( GUInt16 * )data )[index];
231+
break;
232+
case QgsRasterInterface::Int16:
233+
return ( double )(( GInt16 * )data )[index];
234+
break;
235+
case QgsRasterInterface::UInt32:
236+
return ( double )(( GUInt32 * )data )[index];
237+
break;
238+
case QgsRasterInterface::Int32:
239+
return ( double )(( GInt32 * )data )[index];
240+
break;
241+
case QgsRasterInterface::Float32:
242+
return ( double )(( float * )data )[index];
243+
break;
244+
case QgsRasterInterface::Float64:
245+
return ( double )(( double * )data )[index];
246+
break;
247+
default:
248+
//QgsMessageLog::logMessage( tr( "GDAL data type %1 is not supported" ).arg( type ), tr( "Raster" ) );
249+
break;
250+
}
251+
252+
// TODO: noDataValue is per band
253+
return mInput->noDataValue();
254+
}
255+
256+
inline void QgsRasterInterface::writeValue( void *data, QgsRasterInterface::DataType type, int index, double value )
257+
{
258+
if ( !mInput ) return;
259+
if ( !data ) return;
260+
261+
switch ( type )
262+
{
263+
case QgsRasterInterface::Byte:
264+
(( GByte * )data )[index] = ( GByte ) value;
265+
break;
266+
case QgsRasterInterface::UInt16:
267+
(( GUInt16 * )data )[index] = ( GUInt16 ) value;
268+
break;
269+
case QgsRasterInterface::Int16:
270+
(( GInt16 * )data )[index] = ( GInt16 ) value;
271+
break;
272+
case QgsRasterInterface::UInt32:
273+
(( GUInt32 * )data )[index] = ( GUInt32 ) value;
274+
break;
275+
case QgsRasterInterface::Int32:
276+
(( GInt32 * )data )[index] = ( GInt32 ) value;
277+
break;
278+
case QgsRasterInterface::Float32:
279+
(( float * )data )[index] = ( float ) value;
280+
break;
281+
case QgsRasterInterface::Float64:
282+
(( double * )data )[index] = value;
283+
break;
284+
default:
285+
//QgsMessageLog::logMessage( tr( "GDAL data type %1 is not supported" ).arg( type ), tr( "Raster" ) );
286+
break;
287+
}
288+
}
289+
207290
#endif
208291

209292

‎src/core/raster/qgsrasternuller.cpp

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/***************************************************************************
2+
qgsrasternuller.cpp
3+
---------------------
4+
begin : August 2012
5+
copyright : (C) 2012 by Radim Blazek
6+
email : radim dot blazek at gmail dot com
7+
***************************************************************************/
8+
9+
/***************************************************************************
10+
* *
11+
* This program is free software; you can redistribute it and/or modify *
12+
* it under the terms of the GNU General Public License as published by *
13+
* the Free Software Foundation; either version 2 of the License, or *
14+
* (at your option) any later version. *
15+
* *
16+
***************************************************************************/
17+
18+
#include "qgsrasterdataprovider.h"
19+
#include "qgsrasternuller.h"
20+
21+
QgsRasterNuller::QgsRasterNuller( QgsRasterInterface* input )
22+
: QgsRasterInterface( input )
23+
{
24+
}
25+
26+
QgsRasterNuller::~QgsRasterNuller()
27+
{
28+
}
29+
30+
QgsRasterInterface * QgsRasterNuller::clone() const
31+
{
32+
QgsDebugMsg( "Entered" );
33+
QgsRasterNuller * nuller = new QgsRasterNuller( 0 );
34+
nuller->mNoData = mNoData;
35+
return nuller;
36+
}
37+
38+
int QgsRasterNuller::bandCount() const
39+
{
40+
if ( mInput ) return mInput->bandCount();
41+
return 0;
42+
}
43+
44+
QgsRasterInterface::DataType QgsRasterNuller::dataType( int bandNo ) const
45+
{
46+
if ( mInput ) return mInput->dataType( bandNo );
47+
return QgsRasterInterface::UnknownDataType;
48+
}
49+
50+
void * QgsRasterNuller::readBlock( int bandNo, QgsRectangle const & extent, int width, int height )
51+
{
52+
QgsDebugMsg( "Entered" );
53+
if ( !mInput ) return 0;
54+
55+
//QgsRasterDataProvider *provider = dynamic_cast<QgsRasterDataProvider*>( mInput->srcInput() );
56+
57+
void * rasterData = mInput->block( bandNo, extent, width, height );
58+
59+
QgsRasterInterface::DataType dataType = mInput->dataType( bandNo );
60+
int pixelSize = mInput->typeSize( dataType ) / 8;
61+
62+
double noDataValue = mInput->noDataValue ( bandNo );
63+
64+
for ( int i = 0; i < height; ++i )
65+
{
66+
for ( int j = 0; j < width; ++j )
67+
{
68+
int index = pixelSize * ( i * width + j );
69+
70+
double value = readValue( rasterData, dataType, index );
71+
72+
foreach ( NoData noData, mNoData )
73+
{
74+
if ( ( value >= noData.min && value <= noData.max ) ||
75+
doubleNear( value, noData.min ) ||
76+
doubleNear( value, noData.max ) )
77+
{
78+
writeValue( rasterData, dataType, index, noDataValue );
79+
}
80+
}
81+
}
82+
}
83+
84+
return rasterData;
85+
}
86+

‎src/core/raster/qgsrasternuller.h

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/***************************************************************************
2+
qgsrasternuller.h
3+
-------------------
4+
begin : August 2012
5+
copyright : (C) 2012 by Radim Blazek
6+
email : radim dot blazek at gmail dot com
7+
***************************************************************************/
8+
9+
/***************************************************************************
10+
* *
11+
* This program is free software; you can redistribute it and/or modify *
12+
* it under the terms of the GNU General Public License as published by *
13+
* the Free Software Foundation; either version 2 of the License, or *
14+
* (at your option) any later version. *
15+
* *
16+
***************************************************************************/
17+
18+
#ifndef QGSRASTERNULLER_H
19+
#define QGSRASTERNULLER_H
20+
21+
#include "qgsrasterdataprovider.h"
22+
#include "qgsrasterinterface.h"
23+
24+
#include <QList>
25+
26+
class CORE_EXPORT QgsRasterNuller : public QgsRasterInterface
27+
{
28+
public:
29+
QgsRasterNuller( QgsRasterInterface* input = 0 );
30+
~QgsRasterNuller();
31+
32+
struct NoData
33+
{
34+
double min;
35+
double max;
36+
};
37+
38+
QgsRasterInterface * clone() const;
39+
40+
int bandCount() const;
41+
42+
QgsRasterInterface::DataType dataType( int bandNo ) const;
43+
44+
void * readBlock( int bandNo, QgsRectangle const & extent, int width, int height );
45+
46+
void setNoData( QList<QgsRasterNuller::NoData> noData ) { mNoData = noData; }
47+
48+
private:
49+
QList<QgsRasterNuller::NoData> mNoData;
50+
};
51+
52+
#endif // QGSRASTERNULLER_H

‎src/core/raster/qgsrastertransparency.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ int QgsRasterTransparency::alphaValue( double theValue, int theGlobalTransparenc
110110

111111
//Search through the transparency list looking for a match
112112
bool myTransparentPixelFound = false;
113-
TransparentSingleValuePixel myTransparentPixel = {0, 100};
113+
TransparentSingleValuePixel myTransparentPixel = {0, 0, 100};
114114
for ( int myListRunner = 0; myListRunner < mTransparentSingleValuePixelList.count(); myListRunner++ )
115115
{
116116
myTransparentPixel = mTransparentSingleValuePixelList[myListRunner];

‎src/gui/qgsrasterlayersaveasdialog.cpp

Lines changed: 159 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "qgsapplication.h"
22
#include "qgslogger.h"
33
#include "qgscoordinatetransform.h"
4+
#include "qgsrasterlayer.h"
45
#include "qgsrasterlayersaveasdialog.h"
56
#include "qgsrasterdataprovider.h"
67
#include "qgsrasterformatsaveoptionswidget.h"
@@ -15,6 +16,7 @@ QgsRasterLayerSaveAsDialog::QgsRasterLayerSaveAsDialog( QgsRasterDataProvider* s
1516
const QgsCoordinateReferenceSystem& currentCrs,
1617
QWidget* parent, Qt::WindowFlags f ):
1718
QDialog( parent, f )
19+
, mRasterLayer( rasterLayer )
1820
, mDataProvider( sourceProvider )
1921
, mCurrentExtent( currentExtent )
2022
, mLayerCrs( layerCrs )
@@ -27,7 +29,12 @@ QgsRasterLayerSaveAsDialog::QgsRasterLayerSaveAsDialog( QgsRasterDataProvider* s
2729
mLoadTransparentNoDataToolButton->setIcon( QgsApplication::getThemeIcon( "/mActionCopySelected.png" ) );
2830
mRemoveSelectedNoDataToolButton->setIcon( QgsApplication::getThemeIcon( "/mActionDeleteAttribute.png" ) );
2931
mRemoveAllNoDataToolButton->setIcon( QgsApplication::getThemeIcon( "/mActionRemove.png" ) );
30-
// mNoDataGroupBox->setEnabled( false ); // not yet implemented
32+
33+
mNoDataTableWidget->setColumnCount( 2 );
34+
mNoDataTableWidget->setHorizontalHeaderItem( 0, new QTableWidgetItem( tr( "From" ) ) );
35+
mNoDataTableWidget->setHorizontalHeaderItem( 1, new QTableWidgetItem( tr( "To" ) ) );
36+
37+
on_mRawModeRadioButton_toggled( true );
3138

3239
setValidators();
3340
// Translated labels + EPSG are updated later
@@ -503,3 +510,154 @@ QgsRasterLayerSaveAsDialog::Mode QgsRasterLayerSaveAsDialog::mode() const
503510
if ( mRenderedModeRadioButton->isChecked() ) return RenderedImageMode;
504511
return RawDataMode;
505512
}
513+
514+
void QgsRasterLayerSaveAsDialog::on_mRawModeRadioButton_toggled( bool checked )
515+
{
516+
mNoDataGroupBox->setEnabled( checked && mDataProvider->bandCount() == 1 );
517+
}
518+
519+
void QgsRasterLayerSaveAsDialog::on_mAddNoDataManuallyToolButton_clicked()
520+
{
521+
addNoDataRow( std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN() );
522+
}
523+
524+
void QgsRasterLayerSaveAsDialog::on_mLoadTransparentNoDataToolButton_clicked()
525+
{
526+
if ( !mRasterLayer->renderer() ) return;
527+
const QgsRasterTransparency* rasterTransparency = mRasterLayer->renderer()->rasterTransparency();
528+
if ( !rasterTransparency ) return;
529+
530+
foreach ( QgsRasterTransparency::TransparentSingleValuePixel transparencyPixel, rasterTransparency->transparentSingleValuePixelList() )
531+
{
532+
if ( transparencyPixel.percentTransparent == 100 )
533+
{
534+
addNoDataRow( transparencyPixel.min, transparencyPixel.max );
535+
if ( transparencyPixel.min != transparencyPixel.max )
536+
{
537+
setNoDataToEdited( mNoDataTableWidget->rowCount() - 1 );
538+
}
539+
}
540+
}
541+
}
542+
543+
void QgsRasterLayerSaveAsDialog::on_mRemoveSelectedNoDataToolButton_clicked()
544+
{
545+
mNoDataTableWidget->removeRow( mNoDataTableWidget->currentRow() );
546+
}
547+
548+
void QgsRasterLayerSaveAsDialog::on_mRemoveAllNoDataToolButton_clicked()
549+
{
550+
while ( mNoDataTableWidget->rowCount() > 0 )
551+
{
552+
mNoDataTableWidget->removeRow( 0 );
553+
}
554+
}
555+
556+
void QgsRasterLayerSaveAsDialog::addNoDataRow( double min, double max )
557+
{
558+
mNoDataTableWidget->insertRow( mNoDataTableWidget->rowCount() );
559+
for ( int i = 0; i < 2; i++ )
560+
{
561+
double value = i == 0 ? min : max;
562+
QLineEdit *lineEdit = new QLineEdit();
563+
lineEdit->setFrame( false );
564+
lineEdit->setContentsMargins( 1, 1, 1, 1 );
565+
QString valueString;
566+
switch ( mRasterLayer->dataProvider()->srcDataType( 1 ) )
567+
{
568+
case QgsRasterInterface::Float32:
569+
case QgsRasterInterface::Float64:
570+
lineEdit->setValidator( new QDoubleValidator( 0 ) );
571+
if ( !qIsNaN( value ) )
572+
{
573+
valueString = QString::number( value, 'f' );
574+
}
575+
break;
576+
default:
577+
lineEdit->setValidator( new QIntValidator( 0 ) );
578+
if ( !qIsNaN( value ) )
579+
{
580+
valueString = QString::number( static_cast<int>( value ) );
581+
}
582+
break;
583+
}
584+
lineEdit->setText( valueString );
585+
mNoDataTableWidget->setCellWidget( mNoDataTableWidget->rowCount() - 1, i, lineEdit );
586+
587+
connect( lineEdit, SIGNAL( textEdited( const QString & ) ), this, SLOT( noDataCellTextEdited( const QString & ) ) );
588+
}
589+
mNoDataTableWidget->resizeColumnsToContents();
590+
mNoDataTableWidget->resizeRowsToContents();
591+
}
592+
593+
void QgsRasterLayerSaveAsDialog::noDataCellTextEdited( const QString & text )
594+
{
595+
Q_UNUSED( text );
596+
597+
QLineEdit *lineEdit = dynamic_cast<QLineEdit *>( sender() );
598+
if ( !lineEdit ) return;
599+
int row = -1;
600+
int column = -1;
601+
for ( int r = 0 ; r < mNoDataTableWidget->rowCount(); r++ )
602+
{
603+
for ( int c = 0 ; c < mNoDataTableWidget->columnCount(); c++ )
604+
{
605+
if ( mNoDataTableWidget->cellWidget( r, c ) == sender() )
606+
{
607+
row = r;
608+
column = c;
609+
break;
610+
}
611+
}
612+
if ( row != -1 ) break;
613+
}
614+
QgsDebugMsg( QString( "row = %1 column =%2" ).arg( row ).arg( column ) );
615+
616+
if ( column == 0 )
617+
{
618+
QLineEdit *toLineEdit = dynamic_cast<QLineEdit *>( mNoDataTableWidget->cellWidget( row, 1 ) );
619+
if ( !toLineEdit ) return;
620+
bool toChanged = mNoDataToEdited.value( row );
621+
QgsDebugMsg( QString( "toChanged = %1" ).arg( toChanged ) );
622+
if ( !toChanged )
623+
{
624+
toLineEdit->setText( lineEdit->text() );
625+
}
626+
}
627+
else if ( column == 1 )
628+
{
629+
setNoDataToEdited( row );
630+
}
631+
}
632+
633+
void QgsRasterLayerSaveAsDialog::setNoDataToEdited( int row )
634+
{
635+
if ( row >= mNoDataToEdited.size() )
636+
{
637+
mNoDataToEdited.resize( row + 1 );
638+
}
639+
mNoDataToEdited[row] = true;
640+
}
641+
642+
double QgsRasterLayerSaveAsDialog::noDataCellValue( int row, int column ) const
643+
{
644+
QLineEdit *lineEdit = dynamic_cast<QLineEdit *>( mNoDataTableWidget->cellWidget( row, column ) );
645+
if ( !lineEdit || lineEdit->text().isEmpty() )
646+
{
647+
std::numeric_limits<double>::quiet_NaN();
648+
}
649+
return lineEdit->text().toDouble();
650+
}
651+
652+
QList<QgsRasterNuller::NoData> QgsRasterLayerSaveAsDialog::noData() const
653+
{
654+
QList<QgsRasterNuller::NoData> noDataList;
655+
for ( int r = 0 ; r < mNoDataTableWidget->rowCount(); r++ )
656+
{
657+
QgsRasterNuller::NoData noData;
658+
noData.min = noDataCellValue( r, 0 );
659+
noData.max = noDataCellValue( r, 1 );
660+
noDataList.append( noData );
661+
}
662+
return noDataList;
663+
}

‎src/gui/qgsrasterlayersaveasdialog.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
#include "ui_qgsrasterlayersaveasdialogbase.h"
55
#include "qgsrectangle.h"
66
#include "qgscoordinatereferencesystem.h"
7+
#include "qgsrasternuller.h"
78

9+
class QgsRasterLayer;
810
class QgsRasterDataProvider;
911
class QgsRasterFormatOptionsWidget;
1012

@@ -35,7 +37,7 @@ class GUI_EXPORT QgsRasterLayerSaveAsDialog: public QDialog, private Ui::QgsRast
3537
UserResolution
3638
};
3739

38-
QgsRasterLayerSaveAsDialog( QgsRasterDataProvider* sourceProvider, const QgsRectangle& currentExtent, const QgsCoordinateReferenceSystem& layerCrs, const QgsCoordinateReferenceSystem& currentCrs, QWidget* parent = 0, Qt::WindowFlags f = 0 );
40+
QgsRasterLayerSaveAsDialog( QgsRasterLayer* rasterLayer, QgsRasterDataProvider* sourceProvider, const QgsRectangle& currentExtent, const QgsCoordinateReferenceSystem& layerCrs, const QgsCoordinateReferenceSystem& currentCrs, QWidget* parent = 0, Qt::WindowFlags f = 0 );
3941
~QgsRasterLayerSaveAsDialog();
4042

4143
Mode mode() const;
@@ -51,11 +53,13 @@ class GUI_EXPORT QgsRasterLayerSaveAsDialog: public QDialog, private Ui::QgsRast
5153
QgsCoordinateReferenceSystem outputCrs();
5254
QStringList createOptions() const;
5355
QgsRectangle outputRectangle() const;
56+
QList<QgsRasterNuller::NoData> noData() const;
5457

5558
void hideFormat();
5659
void hideOutput();
5760

5861
private slots:
62+
void on_mRawModeRadioButton_toggled( bool );
5963
void on_mBrowseButton_clicked();
6064
void on_mSaveAsLineEdit_textChanged( const QString& text );
6165
void on_mCurrentExtentButton_clicked();
@@ -80,8 +84,14 @@ class GUI_EXPORT QgsRasterLayerSaveAsDialog: public QDialog, private Ui::QgsRast
8084
void on_mCrsComboBox_currentIndexChanged( int ) { crsChanged(); }
8185

8286
void groupBoxExpanded( QWidget * widget ) { mScrollArea->ensureWidgetVisible( widget ); }
87+
void on_mAddNoDataManuallyToolButton_clicked();
88+
void on_mLoadTransparentNoDataToolButton_clicked();
89+
void on_mRemoveSelectedNoDataToolButton_clicked();
90+
void on_mRemoveAllNoDataToolButton_clicked();
91+
void noDataCellTextEdited( const QString & text );
8392

8493
private:
94+
QgsRasterLayer* mRasterLayer;
8595
QgsRasterDataProvider* mDataProvider;
8696
QgsRectangle mCurrentExtent;
8797
QgsCoordinateReferenceSystem mLayerCrs; // may differ from provider CRS
@@ -90,6 +100,7 @@ class GUI_EXPORT QgsRasterLayerSaveAsDialog: public QDialog, private Ui::QgsRast
90100
QgsCoordinateReferenceSystem mPreviousCrs;
91101
ExtentState mExtentState;
92102
ResolutionState mResolutionState;
103+
QVector<bool> mNoDataToEdited;
93104

94105
void setValidators();
95106
void setOutputExtent( const QgsRectangle& r, const QgsCoordinateReferenceSystem& srcCrs, ExtentState state );
@@ -105,6 +116,10 @@ class GUI_EXPORT QgsRasterLayerSaveAsDialog: public QDialog, private Ui::QgsRast
105116
void recalcResolutionSize();
106117
void crsChanged();
107118
void updateCrsGroup();
119+
120+
void addNoDataRow( double min, double max );
121+
void setNoDataToEdited( int row );
122+
double noDataCellValue( int row, int column ) const;
108123
};
109124

110125

‎src/ui/qgslabelingguibase.ui

Lines changed: 1165 additions & 1192 deletions
Large diffs are not rendered by default.

‎src/ui/qgsrasterlayersaveasdialogbase.ui

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,7 @@
516516
<string>Additional no data values. The specified values will be set to no data in output raster.</string>
517517
</property>
518518
<property name="title">
519-
<string>No data values (not yet implemented)</string>
519+
<string>No data values</string>
520520
</property>
521521
<property name="checkable">
522522
<bool>true</bool>
@@ -553,6 +553,9 @@
553553
</item>
554554
<item row="2" column="0">
555555
<widget class="QToolButton" name="mLoadTransparentNoDataToolButton">
556+
<property name="enabled">
557+
<bool>true</bool>
558+
</property>
556559
<property name="toolTip">
557560
<string>Load user defined fully transparent (100%) values </string>
558561
</property>

‎tests/src/core/testqgscomposerhtml.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ void TestQgsComposerHtml::table()
6161
{
6262
QgsComposerHtml* htmlItem = new QgsComposerHtml( mComposition, false );
6363
QgsComposerFrame* htmlFrame = new QgsComposerFrame( mComposition, htmlItem, 0, 0, 100, 200 );
64+
htmlFrame->setFrame( true );
6465
htmlItem->addFrame( htmlFrame );
6566
htmlItem->setUrl( QUrl( QString( "file:///%1" ).arg( QString( TEST_DATA_DIR ) + QDir::separator() + "html_table.html" ) ) );
6667
QgsCompositionChecker checker( "Composer html table", mComposition, QString( QString( TEST_DATA_DIR ) + QDir::separator() +
@@ -77,6 +78,12 @@ void TestQgsComposerHtml::tableMultiFrame()
7778
QgsComposerFrame* htmlFrame = new QgsComposerFrame( mComposition, htmlItem, 10, 10, 100, 50 );
7879
htmlItem->addFrame( htmlFrame );
7980
htmlItem->setResizeMode( QgsComposerMultiFrame::RepeatUntilFinished );
81+
int nFrames = htmlItem->nFrames();
82+
for ( int i = 0; i < nFrames; ++i )
83+
{
84+
htmlItem->frame( i )->setFrame( true );
85+
}
86+
8087
bool result = true;
8188
//page1
8289
htmlItem->setUrl( QUrl( QString( "file:///%1" ).arg( QString( TEST_DATA_DIR ) + QDir::separator() + "html_table.html" ) ) );

‎tests/src/core/testqgscomposermap.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ void TestQgsComposerMap::initTestCase()
6767
mComposition = new QgsComposition( mMapRenderer );
6868
mComposition->setPaperSize( 297, 210 ); //A4 landscape
6969
mComposerMap = new QgsComposerMap( mComposition, 20, 20, 200, 100 );
70+
mComposerMap->setFrame( true );
7071
mComposition->addComposerMap( mComposerMap );
7172
}
7273

@@ -121,6 +122,7 @@ void TestQgsComposerMap::grid()
121122
void TestQgsComposerMap::overviewMap()
122123
{
123124
QgsComposerMap* overviewMap = new QgsComposerMap( mComposition, 20, 130, 70, 70 );
125+
overviewMap->setFrame( true );
124126
mComposition->addComposerMap( overviewMap );
125127
mComposerMap->setNewExtent( QgsRectangle( 785462.375, 3341423.125, 789262.375, 3343323.125 ) ); //zoom in
126128
overviewMap->setNewExtent( QgsRectangle( 781662.375, 3339523.125, 793062.375, 3350923.125 ) );

‎tests/src/python/test_qgsgeometry.py

Lines changed: 93 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
import unittest
22

33
from qgis.core import (QgsGeometry,
4+
QgsVectorLayer,
5+
QgsFeature,
46
QgsPoint,
57
QGis)
68

79
# Convenience instances in case you may need them
810
# not used in this test
9-
#from utilities import getQgisTestApp
10-
#QGISAPP, CANVAS, IFACE, PARENT = getQgisTestApp()
11+
from utilities import getQgisTestApp
12+
QGISAPP, CANVAS, IFACE, PARENT = getQgisTestApp()
1113

1214
class TestQgsGeometry(unittest.TestCase):
1315

@@ -55,6 +57,95 @@ def testFromMultiPolygon(self):
5557
(QGis.WKBMultiPolygon, myMultiPolygon.type()))
5658
assert myMultiPolygon.wkbType() == QGis.WKBMultiPolygon, myMessage
5759

60+
def testIntersection(self):
61+
myLine = QgsGeometry.fromPolyline([QgsPoint(0, 0),QgsPoint(1, 1),QgsPoint(2, 2)])
62+
myPoint = QgsGeometry.fromPoint(QgsPoint(1, 1))
63+
intersectionGeom = QgsGeometry.intersection(myLine, myPoint)
64+
myMessage = ('Expected:\n%s\nGot:\n%s\n' %
65+
(QGis.Point, intersectionGeom.type()))
66+
assert intersectionGeom.wkbType() == QGis.WKBPoint, myMessage
67+
68+
layer = QgsVectorLayer("Point", "intersection", "memory")
69+
assert layer.isValid(), "Failed to create valid point memory layer"
70+
71+
provider = layer.dataProvider()
72+
73+
ft = QgsFeature()
74+
ft.setGeometry(intersectionGeom)
75+
provider.addFeatures([ft])
76+
77+
myMessage = ('Expected:\n%s\nGot:\n%s\n' %
78+
(1, layer.featureCount()))
79+
assert layer.featureCount() == 1, myMessage
80+
81+
def testBuffer(self):
82+
myPoint = QgsGeometry.fromPoint(QgsPoint(1, 1))
83+
bufferGeom = myPoint.buffer(10, 5)
84+
myMessage = ('Expected:\n%s\nGot:\n%s\n' %
85+
(QGis.Polygon, bufferGeom.type()))
86+
assert bufferGeom.wkbType() == QGis.WKBPolygon, myMessage
87+
88+
layer = QgsVectorLayer("Polygon", "buffer", "memory")
89+
assert layer.isValid(), "Failed to create valid polygon memory layer"
90+
91+
provider = layer.dataProvider()
92+
93+
ft = QgsFeature()
94+
ft.setGeometry(bufferGeom)
95+
provider.addFeatures([ft])
96+
97+
myMessage = ('Expected:\n%s\nGot:\n%s\n' %
98+
(1, layer.featureCount()))
99+
assert layer.featureCount() == 1, myMessage
100+
101+
def testContains(self):
102+
myPoly = QgsGeometry.fromPolygon([[QgsPoint(0, 0),QgsPoint(2, 0),QgsPoint(2, 2),QgsPoint(0, 2), QgsPoint(0, 0)]])
103+
myPoint = QgsGeometry.fromPoint(QgsPoint(1, 1))
104+
containsGeom = QgsGeometry.contains(myPoly, myPoint)
105+
myMessage = ('Expected:\n%s\nGot:\n%s\n' %
106+
("True", containsGeom))
107+
assert containsGeom == True, myMessage
108+
109+
def testTouches(self):
110+
myLine = QgsGeometry.fromPolyline([QgsPoint(0, 0),QgsPoint(1, 1),QgsPoint(2, 2)])
111+
myPoly = QgsGeometry.fromPolygon([[QgsPoint(0, 0),QgsPoint(1, 1),QgsPoint(2, 0),QgsPoint(0, 0)]])
112+
touchesGeom = QgsGeometry.touches(myLine, myPoly)
113+
myMessage = ('Expected:\n%s\nGot:\n%s\n' %
114+
("True", touchesGeom))
115+
assert touchesGeom == True, myMessage
116+
117+
def testOverlaps(self):
118+
myPolyA = QgsGeometry.fromPolygon([[QgsPoint(0, 0),QgsPoint(1, 3),QgsPoint(2, 0),QgsPoint(0, 0)]])
119+
myPolyB = QgsGeometry.fromPolygon([[QgsPoint(0, 0),QgsPoint(2, 0),QgsPoint(2, 2),QgsPoint(0, 2), QgsPoint(0, 0)]])
120+
overlapsGeom = QgsGeometry.overlaps(myPolyA, myPolyB)
121+
myMessage = ('Expected:\n%s\nGot:\n%s\n' %
122+
("True", overlapsGeom))
123+
assert overlapsGeom == True, myMessage
124+
125+
def testWithin(self):
126+
myLine = QgsGeometry.fromPolyline([QgsPoint(0.5, 0.5),QgsPoint(1, 1),QgsPoint(1.5, 1.5)])
127+
myPoly = QgsGeometry.fromPolygon([[QgsPoint(0, 0),QgsPoint(2, 0),QgsPoint(2, 2),QgsPoint(0, 2), QgsPoint(0, 0)]])
128+
withinGeom = QgsGeometry.within(myLine, myPoly)
129+
myMessage = ('Expected:\n%s\nGot:\n%s\n' %
130+
("True", withinGeom))
131+
assert withinGeom == True, myMessage
132+
133+
def testEquals(self):
134+
myPointA = QgsGeometry.fromPoint(QgsPoint(1, 1))
135+
myPointB = QgsGeometry.fromPoint(QgsPoint(1, 1))
136+
equalsGeom = QgsGeometry.equals(myPointA, myPointB)
137+
myMessage = ('Expected:\n%s\nGot:\n%s\n' %
138+
("True", equalsGeom))
139+
assert equalsGeom == True, myMessage
140+
141+
def testCrosses(self):
142+
myLine = QgsGeometry.fromPolyline([QgsPoint(0, 0),QgsPoint(1, 1),QgsPoint(3, 3)])
143+
myPoly = QgsGeometry.fromPolygon([[QgsPoint(1, 0),QgsPoint(2, 0),QgsPoint(2, 2),QgsPoint(1, 2), QgsPoint(1, 0)]])
144+
crossesGeom = QgsGeometry.crosses(myLine, myPoly)
145+
myMessage = ('Expected:\n%s\nGot:\n%s\n' %
146+
("True", crossesGeom))
147+
assert crossesGeom == True, myMessage
148+
58149

59150
if __name__ == '__main__':
60151
unittest.main()

0 commit comments

Comments
 (0)
Please sign in to comment.