171 changes: 140 additions & 31 deletions src/app/qgslabelinggui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,9 +180,6 @@ QgsLabelingGui::QgsLabelingGui( QgsPalLabeling* lbl, QgsVectorLayer* layer, QgsM
mBufferTranspFillChbx->setChecked( !lyr.bufferNoFill );
}

btnTextColor->setColor( lyr.textColor );
mFontTranspSpinBox->setValue( lyr.textTransp );

bool formattedNumbers = lyr.formatNumbers;
bool plusSign = lyr.plusSign;

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

QFont textFont = lyr.textFont;
updateFont( textFont );
mFontSizeSpinBox->setValue( textFont.pointSizeF() );
mRefFont = lyr.textFont;
mFontSizeSpinBox->setValue( mRefFont.pointSizeF() );
btnTextColor->setColor( lyr.textColor );
mFontTranspSpinBox->setValue( lyr.textTransp );

updateFontViaStyle( lyr.textNamedStyle );
updateFont( mRefFont );

updateUi();

updateOptions();
Expand Down Expand Up @@ -302,6 +304,7 @@ QgsPalLayerSettings QgsLabelingGui::layerSettings()

lyr.textColor = btnTextColor->color();
lyr.textFont = mRefFont;
lyr.textNamedStyle = mFontStyleComboBox->currentText();
lyr.textTransp = mFontTranspSpinBox->value();
lyr.previewBkgrdColor = mPreviewBackgroundBtn->color();
lyr.enabled = chkEnableLabeling->isChecked();
Expand Down Expand Up @@ -528,6 +531,40 @@ void QgsLabelingGui::changeTextFont()
}
}

void QgsLabelingGui::updateFontViaStyle( const QString & fontstyle )
{
QFont styledfont;
bool foundmatch = false;
if ( !fontstyle.isEmpty() )
{
styledfont = mFontDB.font( mRefFont.family(), fontstyle, mRefFont.pointSizeF() );
if ( QApplication::font().toString() != styledfont.toString() )
{
foundmatch = true;
}
}
if ( !foundmatch )
{
foreach ( const QString &style, mFontDB.styles( mRefFont.family() ) )
{
styledfont = mFontDB.font( mRefFont.family(), style, mRefFont.pointSizeF() );
styledfont = styledfont.resolve( mRefFont );
if ( mRefFont.toString() == styledfont.toString() )
{
foundmatch = true;
break;
}
}
}
if ( foundmatch )
{
styledfont.setUnderline( mRefFont.underline() );
styledfont.setStrikeOut( mRefFont.strikeOut() );
mRefFont = styledfont;
}
// if no match, style combobox will be left blank, which should not affect engine labeling
}

void QgsLabelingGui::updateFont( QFont font )
{
// update background reference font
Expand All @@ -536,62 +573,106 @@ void QgsLabelingGui::updateFont( QFont font )
mRefFont = font;
}

lblFontName->setText( QString( "%1" ).arg( font.family() ) );
// test if font is actually available
QString missingtxt = QString( "" );
bool missing = false;
if ( QApplication::font().toString() != mRefFont.toString() )
{
QFont testfont = mFontDB.font( mRefFont.family(), mFontDB.styleString( mRefFont ), mRefFont.pointSizeF() );
if ( QApplication::font().toString() == testfont.toString() )
{
missing = true;
}
}
if ( missing )
{
missingtxt = tr( " (not found!)" );
lblFontName->setStyleSheet( "color: #990000;" );
}
else
{
lblFontName->setStyleSheet( "color: #000000;" );
}

lblFontName->setText( QString( "%1%2" ).arg( mRefFont.family() ).arg( missingtxt ) );

blockFontChangeSignals( true );
populateFontStyleComboBox();
mFontUnderlineBtn->setChecked( mRefFont.underline() );
mFontStrikethroughBtn->setChecked( mRefFont.strikeOut() );
blockFontChangeSignals( false );

// update font name with font face
// QString dupFont = font.toString();
// QFont lblFont = lblFontName->font();
// lblFont.fromString( dupFont );
// lblFont.setPointSizeF( 14 );
// lblFontName->setFont(lblFont);
// font.setPixelSize( 18 );
// lblFontName->setFont( QFont( font ) );

updatePreview();
}

void QgsLabelingGui::blockFontChangeSignals( bool blk )
{
mFontStyleComboBox->blockSignals( blk );
mFontUnderlineBtn->blockSignals( blk );
mFontStrikethroughBtn->blockSignals( blk );
}

void QgsLabelingGui::updatePreview()
{
scrollPreview();
lblFontPreview->setFont( mRefFont );
QFont previewFont = lblFontPreview->font();
double fontSize = mFontSizeSpinBox->value();
double bufferSize = spinBufferSize->value();
if ( mFontSizeUnitComboBox->currentIndex() == 1 )
double bufferSize = 0.0;
QString grpboxtitle;

if ( mFontSizeUnitComboBox->currentIndex() == 1 ) // map units
{
// TODO: maybe match current map zoom level instead?
previewFont.setPointSize( mPreviewSize );
mPreviewSizeSlider->setEnabled( true );
if ( mBufferUnitComboBox->currentIndex() == 1 )
{
groupBox_mPreview->setTitle( tr( "Sample @ %1 pts (using map units)" ).arg( mPreviewSize ) );
bufferSize = ( mPreviewSize / fontSize ) * bufferSize / 2.5;
}
else
grpboxtitle = tr( "Sample @ %1 pts (using map units)" ).arg( mPreviewSize );

if ( chkBuffer->isChecked() )
{
groupBox_mPreview->setTitle( tr( "Sample @ %1 pts (using map units, STROKE IN mm)" ).arg( mPreviewSize ) );
if ( mBufferUnitComboBox->currentIndex() == 1 ) // map units
{
bufferSize = ( mPreviewSize / fontSize ) * spinBufferSize->value() / 2.5;
}
else // millimeters
{
grpboxtitle = tr( "Sample @ %1 pts (using map units, BUFFER IN MILLIMETERS)" ).arg( mPreviewSize );
bufferSize = spinBufferSize->value();
}
}
}
else
else // in points
{
previewFont.setPointSize( fontSize );
mPreviewSizeSlider->setEnabled( false );
if ( mBufferUnitComboBox->currentIndex() == 1 )
{
groupBox_mPreview->setTitle( tr( "Sample (stroke in map units, NOT SHOWN)" ) );
bufferSize = 0;
}
else
grpboxtitle = tr( "Sample" );

if ( chkBuffer->isChecked() )
{
previewFont.setPointSize( fontSize );
groupBox_mPreview->setTitle( tr( "Sample" ) );
if ( mBufferUnitComboBox->currentIndex() == 0 ) // millimeters
{
bufferSize = spinBufferSize->value();
}
else // map units
{
grpboxtitle = tr( "Sample (BUFFER NOT SHOWN, in map units)" );
}
}
}

lblFontPreview->setFont( previewFont );
groupBox_mPreview->setTitle( grpboxtitle );

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

bool bufferNoFill = false;
if ( chkBuffer->isChecked() )
if ( chkBuffer->isChecked() && bufferSize != 0.0 )
{
QColor buffColor = btnBufferColor->color();
buffColor.setAlphaF(( 100.0 - ( double )( mBufferTranspSpinBox->value() ) ) / 100.0 );
Expand Down Expand Up @@ -688,6 +769,16 @@ void QgsLabelingGui::updateOptions()
}
}

void QgsLabelingGui::populateFontStyleComboBox()
{
mFontStyleComboBox->clear();
foreach ( const QString &style, mFontDB.styles( mRefFont.family() ) )
{
mFontStyleComboBox->addItem( style );
}
mFontStyleComboBox->setCurrentIndex( mFontStyleComboBox->findText( mFontDB.styleString( mRefFont ) ) );
}

void QgsLabelingGui::on_mPreviewSizeSlider_valueChanged( int i )
{
mPreviewSize = i;
Expand All @@ -700,6 +791,24 @@ void QgsLabelingGui::on_mFontSizeSpinBox_valueChanged( double d )
updateFont( mRefFont );
}

void QgsLabelingGui::on_mFontStyleComboBox_currentIndexChanged( const QString & text )
{
updateFontViaStyle( text );
updateFont( mRefFont );
}

void QgsLabelingGui::on_mFontUnderlineBtn_toggled( bool ckd )
{
mRefFont.setUnderline( ckd );
updateFont( mRefFont );
}

void QgsLabelingGui::on_mFontStrikethroughBtn_toggled( bool ckd )
{
mRefFont.setStrikeOut( ckd );
updateFont( mRefFont );
}

void QgsLabelingGui::on_mFontWordSpacingSpinBox_valueChanged( double spacing )
{
mRefFont.setWordSpacing( spacing );
Expand Down
10 changes: 9 additions & 1 deletion src/app/qgslabelinggui.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#define QgsLabelingGUI_H

#include <QDialog>
#include <QFontDatabase>
#include <ui_qgslabelingguibase.h>

class QgsVectorLayer;
Expand Down Expand Up @@ -51,6 +52,9 @@ class QgsLabelingGui : public QWidget, private Ui::QgsLabelingGuiBase

void on_mPreviewSizeSlider_valueChanged( int i );
void on_mFontSizeSpinBox_valueChanged( double d );
void on_mFontStyleComboBox_currentIndexChanged( const QString & text );
void on_mFontUnderlineBtn_toggled( bool ckd );
void on_mFontStrikethroughBtn_toggled( bool ckd );
void on_mFontWordSpacingSpinBox_valueChanged( double spacing );
void on_mFontLetterSpacingSpinBox_valueChanged( double spacing );
void on_mBufferUnitComboBox_currentIndexChanged( int index );
Expand All @@ -62,6 +66,10 @@ class QgsLabelingGui : public QWidget, private Ui::QgsLabelingGuiBase
void on_mPreviewBackgroundBtn_clicked();

protected:
void blockFontChangeSignals( bool blk );
void setPreviewBackground( QColor color );
void updateFontViaStyle( const QString & fontstyle );
void populateFontStyleComboBox();
void populatePlacementMethods();
void populateFieldNames();
void populateDataDefinedCombos( QgsPalLayerSettings& s );
Expand All @@ -74,11 +82,11 @@ class QgsLabelingGui : public QWidget, private Ui::QgsLabelingGuiBase
QgsPalLabeling* mLBL;
QgsVectorLayer* mLayer;
QgsMapCanvas* mMapCanvas;
QFontDatabase mFontDB;

// background reference font
QFont mRefFont;
int mPreviewSize;
void setPreviewBackground( QColor color );

void disableDataDefinedAlignment();
void enableDataDefinedAlignment();
Expand Down
10 changes: 8 additions & 2 deletions src/app/qgslabelpreview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ void QgsLabelPreview::paintEvent( QPaintEvent *e )
if ( mBufferSize != 0 )
QgsPalLabeling::drawLabelBuffer( &p, text(), font(), mBufferSize, mBufferColor, mBufferJoinStyle, mBufferNoFill );

p.setPen( mTextColor );
p.drawText( 0, 0, text() );
QPainterPath path;
path.addText( 0, 0, font(), text() );
p.setPen( Qt::NoPen );
p.setBrush( mTextColor );
p.drawPath( path );

// p.setPen( mTextColor );
// p.drawText( 0, 0, text() );
}
1 change: 1 addition & 0 deletions src/app/qgslabelpropertydialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ void QgsLabelPropertyDialog::on_mFontPushButton_clicked()
insertChangedValue( QgsPalLayerSettings::Bold, mLabelFont.bold() );
insertChangedValue( QgsPalLayerSettings::Italic, mLabelFont.italic() );
insertChangedValue( QgsPalLayerSettings::Underline, mLabelFont.underline() );
insertChangedValue( QgsPalLayerSettings::Strikeout, mLabelFont.strikeOut() );
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/app/qgsnewspatialitelayerdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ QgsNewSpatialiteLayerDialog::QgsNewSpatialiteLayerDialog( QWidget *parent, Qt::W
QgsCoordinateReferenceSystem srs;
srs.createFromOgcWmsCrs( GEO_EPSG_CRS_AUTHID );
srs.validate();
mCrsId = srs.srsid();
bool ok;
mCrsId = srs.authid().split( ':' ).at( 1 ).toInt( &ok );
leSRID->setText( srs.authid() + " - " + srs.description() );

pbnFindSRID->setEnabled( mDatabaseComboBox->count() );
Expand Down
466 changes: 255 additions & 211 deletions src/app/qgsrasterlayerproperties.cpp

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions src/app/qgsrasterlayerproperties.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ class QgsRasterLayerProperties : public QDialog, private Ui::QgsRasterLayerPrope
/** Update items in pipe list */
void pipeItemClicked( QTreeWidgetItem * item, int column );

/** Transparency cell changed */
void transparencyCellTextEdited( const QString & text );

signals:
/** emitted when changes to layer were saved to update legend */
void refreshLegend( QString layerID, bool expandItem );
Expand Down Expand Up @@ -137,9 +140,16 @@ class QgsRasterLayerProperties : public QDialog, private Ui::QgsRasterLayerPrope

QgsRasterRendererWidget* mRendererWidget;

void setupTransparencyTable( int nBands );

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

void setTransparencyCell( int row, int column, double value );
void setTransparencyCellValue( int row, int column, double value );
double transparencyCellValue( int row, int column );
void setTransparencyToEdited( int row );

void setRendererWidget( const QString& rendererName );

//@TODO we should move these gradient generators somewhere more generic
Expand All @@ -162,5 +172,7 @@ class QgsRasterLayerProperties : public QDialog, private Ui::QgsRasterLayerPrope
QgsMapToolEmitPoint* mPixelSelectorTool;

QgsRasterHistogramWidget* mHistogramWidget;

QVector<bool> mTransparencyToEdited;
};
#endif
1 change: 1 addition & 0 deletions src/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ SET(QGIS_CORE_SRCS
raster/qgsrasterinterface.cpp
raster/qgsrasteriterator.cpp
raster/qgsrasterlayer.cpp
raster/qgsrasternuller.cpp
raster/qgsrastertransparency.cpp
raster/qgsrasterpipe.cpp
raster/qgsrastershader.cpp
Expand Down
4 changes: 2 additions & 2 deletions src/core/composer/qgscomposeritem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ QgsComposerItem::QgsComposerItem( QgsComposition* composition, bool manageZValue
, QGraphicsRectItem( 0 )
, mComposition( composition )
, mBoundingResizeRectangle( 0 )
, mFrame( true )
, mFrame( false )
, mItemPositionLocked( false )
, mLastValidViewScaleFactor( -1 )
, mRotation( 0 )
Expand All @@ -55,7 +55,7 @@ QgsComposerItem::QgsComposerItem( qreal x, qreal y, qreal width, qreal height, Q
, QGraphicsRectItem( 0, 0, width, height, 0 )
, mComposition( composition )
, mBoundingResizeRectangle( 0 )
, mFrame( true )
, mFrame( false )
, mItemPositionLocked( false )
, mLastValidViewScaleFactor( -1 )
, mRotation( 0 )
Expand Down
106 changes: 93 additions & 13 deletions src/core/composer/qgscomposermultiframe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
QgsComposerMultiFrame::QgsComposerMultiFrame( QgsComposition* c, bool createUndoCommands ): mComposition( c ), mResizeMode( UseExistingFrames ), mCreateUndoCommands( createUndoCommands )
{
mComposition->addMultiFrame( this );
connect( mComposition, SIGNAL( nPagesChanged() ), this, SLOT( handlePageChange() ) );
}

QgsComposerMultiFrame::QgsComposerMultiFrame(): mComposition( 0 ), mResizeMode( UseExistingFrames )
Expand Down Expand Up @@ -61,9 +62,9 @@ void QgsComposerMultiFrame::recalculateFrameSizes()

for ( int i = 0; i < mFrameItems.size(); ++i )
{
if ( currentY >= totalHeight )
if ( mResizeMode != RepeatOnEveryPage && currentY >= totalHeight )
{
if ( mResizeMode == ExtendToNextPage ) //remove unneeded frames in extent mode
if ( mResizeMode == RepeatUntilFinished || mResizeMode == ExtendToNextPage ) //remove unneeded frames in extent mode
{
for ( int j = mFrameItems.size(); j > i; --j )
{
Expand All @@ -75,30 +76,67 @@ void QgsComposerMultiFrame::recalculateFrameSizes()

currentItem = mFrameItems.value( i );
currentHeight = currentItem->rect().height();
currentItem->setContentSection( QRectF( 0, currentY, currentItem->rect().width(), currentHeight ) );
if ( mResizeMode == RepeatOnEveryPage )
{
currentItem->setContentSection( QRectF( 0, 0, currentItem->rect().width(), currentHeight ) );
}
else
{
currentItem->setContentSection( QRectF( 0, currentY, currentItem->rect().width(), currentHeight ) );
}
currentItem->update();
currentY += currentHeight;
}

//at end of frames but there is still content left. Add other pages if ResizeMode ==
if ( mResizeMode == ExtendToNextPage )
if ( mResizeMode != UseExistingFrames )
{
while ( currentY < totalHeight )
while (( mResizeMode == RepeatOnEveryPage ) || currentY < totalHeight )
{
//find out on which page the lower left point of the last frame is
int page = currentItem->transform().dy() / ( mComposition->paperHeight() + mComposition->spaceBetweenPages() );
if ( mResizeMode == RepeatOnEveryPage )
{
if ( page > mComposition->numPages() - 2 )
{
break;
}
}
else
{
if ( mComposition->numPages() < ( page + 2 ) )
{
mComposition->setNumPages( page + 2 );
}
}

//add new pages if necessary
if ( mComposition->numPages() < ( page + 2 ) )
double frameHeight = 0;
if ( mResizeMode == RepeatUntilFinished || mResizeMode == RepeatOnEveryPage )
{
mComposition->setNumPages( page + 2 );
frameHeight = currentItem->rect().height();
}
else //mResizeMode == ExtendToNextPage
{
frameHeight = ( currentY + mComposition->paperHeight() ) > totalHeight ? totalHeight - currentY : mComposition->paperHeight();
}

//copy last frame
QgsComposerFrame* newFrame = new QgsComposerFrame( mComposition, this, currentItem->transform().dx(), currentItem->transform().dy() + mComposition->paperHeight() + mComposition->spaceBetweenPages(),
currentItem->rect().width(), currentItem->rect().height() );
newFrame->setContentSection( QRectF( 0, currentY, newFrame->rect().width(), newFrame->rect().height() ) );
currentY += newFrame->rect().height();
double newFrameY = ( page + 1 ) * ( mComposition->paperHeight() + mComposition->spaceBetweenPages() );
if ( mResizeMode == RepeatUntilFinished || mResizeMode == RepeatOnEveryPage )
{
newFrameY += currentItem->transform().dy() - page * ( mComposition->paperHeight() + mComposition->spaceBetweenPages() );
}
QgsComposerFrame* newFrame = new QgsComposerFrame( mComposition, this, currentItem->transform().dx(),
newFrameY,
currentItem->rect().width(), frameHeight );
if ( mResizeMode == RepeatOnEveryPage )
{
newFrame->setContentSection( QRectF( 0, 0, newFrame->rect().width(), newFrame->rect().height() ) );
}
else
{
newFrame->setContentSection( QRectF( 0, currentY, newFrame->rect().width(), newFrame->rect().height() ) );
}
currentY += frameHeight;
currentItem = newFrame;
addFrame( newFrame, false );
}
Expand All @@ -124,13 +162,55 @@ void QgsComposerMultiFrame::handleFrameRemoval( QgsComposerItem* item )
}
}

void QgsComposerMultiFrame::handlePageChange()
{
if ( mComposition->numPages() < 1 )
{
return;
}

if ( mResizeMode != RepeatOnEveryPage )
{
return;
}

//remove items beginning on non-existing pages
for ( int i = mFrameItems.size() - 1; i >= 0; --i )
{
QgsComposerFrame* frame = mFrameItems[i];
int page = frame->transform().dy() / ( mComposition->paperHeight() + mComposition->spaceBetweenPages() );
if ( page > ( mComposition->numPages() - 1 ) )
{
removeFrame( i );
}
}

//page number of the last item
QgsComposerFrame* lastFrame = mFrameItems.last();
int lastItemPage = lastFrame->transform().dy() / ( mComposition->paperHeight() + mComposition->spaceBetweenPages() );

for ( int i = lastItemPage + 1; i < mComposition->numPages(); ++i )
{
//copy last frame to current page
QgsComposerFrame* newFrame = new QgsComposerFrame( mComposition, this, lastFrame->transform().dx(),
lastFrame->transform().dy() + mComposition->paperHeight() + mComposition->spaceBetweenPages(),
lastFrame->rect().width(), lastFrame->rect().height() );
addFrame( newFrame, false );
lastFrame = newFrame;
}

recalculateFrameSizes();
update();
}

void QgsComposerMultiFrame::removeFrame( int i )
{
QgsComposerFrame* frameItem = mFrameItems[i];
if ( mComposition )
{
mComposition->removeComposerItem( frameItem );
}
mFrameItems.removeAt( i );
}

void QgsComposerMultiFrame::update()
Expand Down
6 changes: 5 additions & 1 deletion src/core/composer/qgscomposermultiframe.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ class CORE_EXPORT QgsComposerMultiFrame: public QObject
enum ResizeMode
{
UseExistingFrames = 0,
ExtendToNextPage //duplicates last frame to next page to fit the total size
ExtendToNextPage, //uses the next page(s) until the content has been printed
RepeatOnEveryPage, //repeats the same frame on every page
RepeatUntilFinished //duplicates last frame to next page to fit the total size
};

QgsComposerMultiFrame( QgsComposition* c, bool createUndoCommands );
Expand Down Expand Up @@ -80,6 +82,8 @@ class CORE_EXPORT QgsComposerMultiFrame: public QObject
void recalculateFrameSizes();
/**Called before a frame is going to be removed (update frame list)*/
void handleFrameRemoval( QgsComposerItem* item );
/**Adapts to changed number of pages if resize type is RepeatOnEveryPage*/
void handlePageChange();

private:
QgsComposerMultiFrame(); //forbidden
Expand Down
9 changes: 4 additions & 5 deletions src/core/composer/qgscomposerscalebar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,12 +168,11 @@ void QgsComposerScaleBar::refreshSegmentMillimeters()
QRectF composerItemRect = mComposerMap->rect();

//calculate size depending on mNumUnitsPerSegment
double itemDiagonal = sqrt( composerItemRect.width() * composerItemRect.width() + composerItemRect.height() * composerItemRect.height() );
mSegmentMillimeters = itemDiagonal / mapDiagonal() * mNumUnitsPerSegment;
mSegmentMillimeters = composerItemRect.width() / mapWidth() * mNumUnitsPerSegment;
}
}

double QgsComposerScaleBar::mapDiagonal() const
double QgsComposerScaleBar::mapWidth() const
{
if ( !mComposerMap )
{
Expand All @@ -183,7 +182,7 @@ double QgsComposerScaleBar::mapDiagonal() const
QgsRectangle composerMapRect = mComposerMap->extent();
if ( mUnits == MapUnits )
{
return sqrt( composerMapRect.width() * composerMapRect.width() + composerMapRect.height() * composerMapRect.height() );
return composerMapRect.width();
}
else
{
Expand All @@ -192,7 +191,7 @@ double QgsComposerScaleBar::mapDiagonal() const
da.setSourceCrs( mComposerMap->mapRenderer()->destinationCrs().srsid() );
QSettings s;
da.setEllipsoid( s.value( "/qgis/measure/ellipsoid", "WGS84" ).toString() );
double measure = da.measureLine( QgsPoint( composerMapRect.xMinimum(), composerMapRect.yMaximum() ), QgsPoint( composerMapRect.xMaximum(), composerMapRect.yMinimum() ) );
double measure = da.measureLine( QgsPoint( composerMapRect.xMinimum(), composerMapRect.yMinimum() ), QgsPoint( composerMapRect.xMaximum(), composerMapRect.yMinimum() ) );
if ( mUnits == Feet )
{
measure /= 0.3048;
Expand Down
2 changes: 1 addition & 1 deletion src/core/composer/qgscomposerscalebar.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ class CORE_EXPORT QgsComposerScaleBar: public QgsComposerItem
void refreshSegmentMillimeters();

/**Returns diagonal of composer map in selected units (map units / meters / feet)*/
double mapDiagonal() const;
double mapWidth() const;
};

#endif //QGSCOMPOSERSCALEBAR_H
Expand Down
1 change: 1 addition & 0 deletions src/core/composer/qgscomposition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ void QgsComposition::setNumPages( int pages )
mPages.removeLast();
}
}
emit nPagesChanged();
}

int QgsComposition::numPages() const
Expand Down
1 change: 1 addition & 0 deletions src/core/composer/qgscomposition.h
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ class CORE_EXPORT QgsComposition: public QGraphicsScene

signals:
void paperSizeChanged();
void nPagesChanged();

/**Is emitted when selected item changed. If 0, no item is selected*/
void selectedItemChanged( QgsComposerItem* selected );
Expand Down
9 changes: 0 additions & 9 deletions src/core/gps/qgsgpsdetector.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,6 @@
#include <QList>
#include <QPair>

#ifdef _MSC_VER
// qextserialport.h includes windows.h,
// which defines min()/max() macros w/o NOMINMAX,
// which in turn breaks limits std::numeric_limits<T>::min()/max()
#ifndef NOMINMAX
#define NOMINMAX
#endif
#endif

#include "qextserialport.h"

class QgsGPSConnection;
Expand Down
1 change: 0 additions & 1 deletion src/core/qgsmaprenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,6 @@ void QgsMapRenderer::render( QPainter* painter, double* forceWidthScale )
mRenderContext.painter()->scale( 1.0 / rasterScaleFactor, 1.0 / rasterScaleFactor );
}


if ( !ml->draw( mRenderContext ) )
{
emit drawError( ml );
Expand Down
20 changes: 19 additions & 1 deletion src/core/qgspallabeling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

#include <cmath>

#include <QApplication>
#include <QByteArray>
#include <QString>
#include <QFontMetrics>
Expand Down Expand Up @@ -142,6 +143,7 @@ QgsPalLayerSettings::QgsPalLayerSettings()
placement = AroundPoint;
placementFlags = 0;
//textFont = QFont();
textNamedStyle = QString( "" );
textColor = Qt::black;
textTransp = 0;
previewBkgrdColor = Qt::white;
Expand Down Expand Up @@ -180,6 +182,7 @@ QgsPalLayerSettings::QgsPalLayerSettings( const QgsPalLayerSettings& s )
placement = s.placement;
placementFlags = s.placementFlags;
textFont = s.textFont;
textNamedStyle = s.textNamedStyle;
textColor = s.textColor;
textTransp = s.textTransp;
previewBkgrdColor = s.previewBkgrdColor;
Expand Down Expand Up @@ -319,6 +322,18 @@ static void _readDataDefinedPropertyMap( QgsVectorLayer* layer, QMap< QgsPalLaye
_readDataDefinedProperty( layer, QgsPalLayerSettings::BufferTransp, propertyMap );
}

void QgsPalLayerSettings::updateFontViaStyle( const QString & fontstyle )
{
if ( !fontstyle.isEmpty() )
{
QFont styledfont = mFontDB.font( textFont.family(), fontstyle, textFont.pointSizeF() );
if ( QApplication::font().toString() != styledfont.toString() )
{
textFont = styledfont;
}
}
}

void QgsPalLayerSettings::readFromLayer( QgsVectorLayer* layer )
{
if ( layer->customProperty( "labeling" ).toString() != QString( "pal" ) )
Expand All @@ -333,9 +348,11 @@ void QgsPalLayerSettings::readFromLayer( QgsVectorLayer* layer )
int fontWeight = layer->customProperty( "labeling/fontWeight" ).toInt();
bool fontItalic = layer->customProperty( "labeling/fontItalic" ).toBool();
textFont = QFont( fontFamily, fontSize, fontWeight, fontItalic );
textFont.setPointSizeF( fontSize ); //double precision needed because of map units
textNamedStyle = layer->customProperty( "labeling/namedStyle", QVariant( "" ) ).toString();
updateFontViaStyle( textNamedStyle );
textFont.setUnderline( layer->customProperty( "labeling/fontUnderline" ).toBool() );
textFont.setStrikeOut( layer->customProperty( "labeling/fontStrikeout" ).toBool() );
textFont.setPointSizeF( fontSize ); //double precision needed because of map units
textColor = _readColor( layer, "labeling/textColor" );
textTransp = layer->customProperty( "labeling/textTransp" ).toInt();
previewBkgrdColor = QColor( layer->customProperty( "labeling/previewBkgrdColor", "#ffffff" ).toString() );
Expand Down Expand Up @@ -376,6 +393,7 @@ void QgsPalLayerSettings::writeToLayer( QgsVectorLayer* layer )
layer->setCustomProperty( "labeling/placementFlags", ( unsigned int )placementFlags );

layer->setCustomProperty( "labeling/fontFamily", textFont.family() );
layer->setCustomProperty( "labeling/namedStyle", textNamedStyle );
layer->setCustomProperty( "labeling/fontSize", textFont.pointSizeF() );
layer->setCustomProperty( "labeling/fontWeight", textFont.weight() );
layer->setCustomProperty( "labeling/fontItalic", textFont.italic() );
Expand Down
6 changes: 6 additions & 0 deletions src/core/qgspallabeling.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ struct QgsDiagramLayerSettings;

#include <QString>
#include <QFont>
#include <QFontDatabase>
#include <QColor>
#include <QHash>
#include <QList>
Expand Down Expand Up @@ -118,6 +119,7 @@ class CORE_EXPORT QgsPalLayerSettings
Placement placement;
unsigned int placementFlags;
QFont textFont;
QString textNamedStyle;
QColor textColor;
int textTransp;
QColor previewBkgrdColor;
Expand Down Expand Up @@ -187,6 +189,10 @@ class CORE_EXPORT QgsPalLayerSettings
@return true if above size, false if below*/
bool checkMinimumSizeMM( const QgsRenderContext& ct, QgsGeometry* geom, double minSize ) const;
QgsExpression* expression;

QFontDatabase mFontDB;
/**Updates layer font with one of its named styles */
void updateFontViaStyle( const QString & fontstyle );
};

class CORE_EXPORT QgsLabelCandidate
Expand Down
6 changes: 6 additions & 0 deletions src/core/qgsrasterdataprovider.h
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,9 @@ class CORE_EXPORT QgsRasterDataProvider : public QgsDataProvider, public QgsRast
/* Read a value from a data block at a given index. */
virtual double readValue( void *data, int type, int index );

/* Return true if source band has no data value */
virtual bool srcHasNoDataValue( int bandNo ) const { Q_UNUSED( bandNo ); return false; }

/** value representing null data */
virtual double noDataValue() const { return 0; }

Expand Down Expand Up @@ -522,6 +525,9 @@ class CORE_EXPORT QgsRasterDataProvider : public QgsDataProvider, public QgsRast
return false;
}

/** Set no data value on created dataset */
virtual bool setNoDataValue( int, double ) { return false; }

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

Expand Down
6 changes: 6 additions & 0 deletions src/core/qgsrasterprojector.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ class CORE_EXPORT QgsRasterProjector : public QgsRasterInterface
/** \brief set source and destination CRS */
void setCRS( QgsCoordinateReferenceSystem theSrcCRS, QgsCoordinateReferenceSystem theDestCRS );

/** \brief Get source CRS */
QgsCoordinateReferenceSystem srcCrs() const { return mSrcCRS; }

/** \brief Get destination CRS */
QgsCoordinateReferenceSystem destCrs() const { return mDestCRS; }

/** \brief set maximum source resolution */
void setMaxSrcRes( double theMaxSrcXRes, double theMaxSrcYRes )
{
Expand Down
22 changes: 21 additions & 1 deletion src/core/raster/qgsmultibandcolorrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,22 +234,42 @@ void * QgsMultiBandColorRenderer::readBlock( int bandNo, QgsRectangle const & e
redVal = readValue( redData, redType, currentRasterPos );
greenVal = readValue( greenData, greenType, currentRasterPos );
blueVal = readValue( blueData, blueType, currentRasterPos );
imageScanLine[j] = qRgba( redVal, greenVal, blueVal, 255 );
if ( mInput->isNoDataValue( mRedBand, redVal ) ||
mInput->isNoDataValue( mGreenBand, greenVal ) ||
mInput->isNoDataValue( mBlueBand, blueVal ) )
{
imageScanLine[j] = defaultColor;
}
else
{
imageScanLine[j] = qRgba( redVal, greenVal, blueVal, 255 );
}

++currentRasterPos;
continue;
}

bool isNoData = false;
if ( mRedBand > 0 )
{
redVal = readValue( redData, redType, currentRasterPos );
if ( mInput->isNoDataValue( mRedBand, redVal ) ) isNoData = true;
}
if ( mGreenBand > 0 )
{
greenVal = readValue( greenData, greenType, currentRasterPos );
if ( mInput->isNoDataValue( mGreenBand, greenVal ) ) isNoData = true;
}
if ( mBlueBand > 0 )
{
blueVal = readValue( blueData, blueType, currentRasterPos );
if ( mInput->isNoDataValue( mBlueBand, blueVal ) ) isNoData = true;
}
if ( isNoData )
{
imageScanLine[j] = defaultColor;
++currentRasterPos;
continue;
}

//apply default color if red, green or blue not in displayable range
Expand Down
7 changes: 7 additions & 0 deletions src/core/raster/qgspalettedrasterrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ void * QgsPalettedRasterRenderer::readBlock( int bandNo, QgsRectangle const & e
{
return 0;
}
QRgb myDefaultColor = qRgba( 0, 0, 0, 0 );

QgsRasterInterface::DataType transparencyType = QgsRasterInterface::UnknownDataType;
if ( mAlphaBand > 0 )
Expand Down Expand Up @@ -129,6 +130,12 @@ void * QgsPalettedRasterRenderer::readBlock( int bandNo, QgsRectangle const & e
for ( int j = 0; j < width; ++j )
{
val = readValue( rasterData, rasterType, currentRasterPos );
if ( mInput->isNoDataValue( mBandNumber, val ) )
{
imageScanLine[j] = myDefaultColor;
++currentRasterPos;
continue;
}
if ( !hasTransparency )
{
imageScanLine[j] = mColors[ val ].rgba();
Expand Down
228 changes: 182 additions & 46 deletions src/core/raster/qgsrasterfilewriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "qgsrasterinterface.h"
#include "qgsrasteriterator.h"
#include "qgsrasterlayer.h"
#include "qgsrasterprojector.h"
#include <QCoreApplication>
#include <QProgressDialog>
#include <QTextStream>
Expand All @@ -38,16 +39,20 @@ QgsRasterFileWriter::~QgsRasterFileWriter()

}

QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeRaster( QgsRasterIterator* iter, int nCols, int nRows, QgsRectangle outputExtent,
const QgsCoordinateReferenceSystem& crs, QProgressDialog* p )
//QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeRaster( QgsRasterIterator* iter, int nCols, int nRows, QgsRectangle outputExtent,
QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeRaster( const QgsRasterPipe* pipe, int nCols, int nRows, QgsRectangle outputExtent,
const QgsCoordinateReferenceSystem& crs, QProgressDialog* progressDialog )
{
QgsDebugMsg( "Entered" );
if ( !iter )

//if ( !iter )
if ( !pipe )
{
return SourceProviderError;
}

const QgsRasterInterface* iface = iter->input();
//const QgsRasterInterface* iface = iter->input();
const QgsRasterInterface* iface = pipe->last();
if ( !iface )
{
return SourceProviderError;
Expand All @@ -59,39 +64,44 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeRaster( QgsRasterIter
return SourceProviderError;
}

mProgressDialog = p;
mProgressDialog = progressDialog;

QgsRasterIterator iter( pipe->last() );

if ( iface->dataType( 1 ) == QgsRasterInterface::ARGB32 ||
iface->dataType( 1 ) == QgsRasterInterface::ARGB32_Premultiplied )
{
WriterError e = writeImageRaster( iter, nCols, nRows, outputExtent, crs, p );
WriterError e = writeImageRaster( &iter, nCols, nRows, outputExtent, crs, progressDialog );
mProgressDialog = 0;
return e;
}
else
{
mProgressDialog = 0;
WriterError e = writeDataRaster( iter, nCols, nRows, outputExtent, crs, p );
WriterError e = writeDataRaster( pipe, &iter, nCols, nRows, outputExtent, crs, progressDialog );
return e;
}
}

QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster( QgsRasterIterator* iter, int nCols, int nRows, const QgsRectangle& outputExtent,
const QgsCoordinateReferenceSystem& crs, QProgressDialog* p )
QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster( const QgsRasterPipe* pipe, QgsRasterIterator* iter, int nCols, int nRows, const QgsRectangle& outputExtent,
const QgsCoordinateReferenceSystem& crs, QProgressDialog* progressDialog )
{
QgsDebugMsg( "Entered" );
if ( !iter )
{
return SourceProviderError;
}

const QgsRasterInterface* iface = iter->input();
//const QgsRasterInterface* iface = iter->input();
const QgsRasterInterface* iface = pipe->last();
if ( !iface )
{
return SourceProviderError;
}

const QgsRasterDataProvider* srcProvider = dynamic_cast<const QgsRasterDataProvider*>( iface->srcInput() );
//const QgsRasterDataProvider* srcProvider = dynamic_cast<const QgsRasterDataProvider*>( iface->srcInput() );
//QgsRasterDataProvider* srcProvider = dynamic_cast<QgsRasterDataProvider*>( iface->srcInput() );
QgsRasterDataProvider* srcProvider = const_cast<QgsRasterDataProvider*>( dynamic_cast<const QgsRasterDataProvider*>( iface->srcInput() ) );
if ( !srcProvider )
{
QgsDebugMsg( "Cannot get source data provider" );
Expand All @@ -105,12 +115,6 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster( QgsRaster
destDir.mkdir( mOutputUrl );
}

//Get output map units per pixel
int iterLeft = 0;
int iterTop = 0;
int iterCols = 0;
int iterRows = 0;

iter->setMaximumTileWidth( mMaxTileWidth );
iter->setMaximumTileHeight( mMaxTileHeight );

Expand All @@ -137,25 +141,159 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster( QgsRaster
}
}

// Output data type - source data type is preferred but it may happen that we need
// to set 'no data' value (which was not set on source data) if output extent
// is larger than source extent (with or without reprojection) and there is no 'free'
// (not used) value available
QList<bool> destHasNoDataValueList;
QList<double> destNoDataValueList;
QList<QgsRasterInterface::DataType> destDataTypeList;
for ( int bandNo = 1; bandNo <= nBands; bandNo++ )
{

bool srcHasNoDataValue = srcProvider->srcHasNoDataValue( bandNo );
bool destHasNoDataValue = false;
double destNoDataValue;
QgsRasterInterface::DataType destDataType = srcProvider->srcDataType( bandNo );
if ( srcHasNoDataValue )
{
// If source has no data value, it is used by provider
// TODO: this is not realy source no data, we would need srcNoDataValue() but it
// can be safely used I think
destNoDataValue = srcProvider->noDataValue();
destHasNoDataValue = true;
}
#if 0
else if ( )
// TODO: see if nuller has user defined aditional values, in that case use one as no data value

}
#endif
else
{
// Verify if we realy need no data value, i.e.
QgsRectangle srcExtent = outputExtent;
QgsRasterProjector *projector = pipe->projector();
if ( projector && projector->destCrs() != projector->srcCrs() )
{
QgsCoordinateTransform ct( projector->destCrs(), projector->srcCrs() );
srcExtent = ct.transformBoundingBox( outputExtent );
}
if ( !srcProvider->extent().contains( srcExtent ) )
{
// Destination extent is larger than source extent, we need destination no data values
// Get src sample statistics (estimation from sample)
QgsRasterBandStats stats = srcProvider->bandStatistics( bandNo, QgsRasterBandStats::Min | QgsRasterBandStats::Max, srcExtent, 250000 );

// Test if we have free (not used) values
double typeMinValue = QgsContrastEnhancement::maximumValuePossible(( QgsContrastEnhancement::QgsRasterDataType )srcProvider->srcDataType( bandNo ) );
double typeMaxValue = QgsContrastEnhancement::maximumValuePossible(( QgsContrastEnhancement::QgsRasterDataType )srcProvider->srcDataType( bandNo ) );
if ( stats.minimumValue > typeMinValue )
{
destNoDataValue = typeMinValue;
}
else if ( stats.maximumValue < typeMaxValue )
{
destNoDataValue = typeMaxValue;
}
else
{
// We have to use wider type
destDataType = QgsRasterInterface::typeWithNoDataValue( destDataType, &destNoDataValue );
}
destHasNoDataValue = true;
}
}
QgsDebugMsg( QString( "bandNo = %1 destDataType = %2 destHasNoDataValue = %3 destNoDataValue = %4" ).arg( bandNo ).arg( destDataType ).arg( destHasNoDataValue ).arg( destNoDataValue ) );
destDataTypeList.append( destDataType );
destHasNoDataValueList.append( destHasNoDataValue );
destNoDataValueList.append( destNoDataValue );
}


QgsRasterInterface::DataType destDataType = destDataTypeList.value( 0 );
// Currently write API supports one output type for dataset only -> find the widest
for ( int i = 1; i < nBands; i++ )
{
if ( destDataTypeList.value( i ) > destDataType )
{
destDataType = destDataTypeList.value( i );
// no data value may be left per band (for future)
}
}

destProvider = initOutput( nCols, nRows, crs, geoTransform, nBands, destDataType );

WriterError error = writeDataRaster( pipe, iter, nCols, nRows, outputExtent, crs, destDataType, destHasNoDataValueList, destNoDataValueList, destProvider, progressDialog );

if ( error == NoDataConflict )
{
// The value used for no data was found in source data, we must use wider data type
destProvider->remove();
delete destProvider;

// But we dont know which band -> wider all
for ( int i = 0; i < nBands; i++ )
{
double destNoDataValue;
QgsRasterInterface::DataType destDataType = QgsRasterInterface::typeWithNoDataValue( destDataTypeList.value( i ), &destNoDataValue );
destDataTypeList.replace( i, destDataType );
destNoDataValueList.replace( i, destNoDataValue );
}

// Try again
destProvider = initOutput( nCols, nRows, crs, geoTransform, nBands, destDataType );
error = writeDataRaster( pipe, iter, nCols, nRows, outputExtent, crs, destDataType, destHasNoDataValueList, destNoDataValueList, destProvider, progressDialog );
}

return error;
}

QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster(
const QgsRasterPipe* pipe,
QgsRasterIterator* iter,
int nCols, int nRows,
const QgsRectangle& outputExtent,
const QgsCoordinateReferenceSystem& crs,
QgsRasterInterface::DataType destDataType,
QList<bool> destHasNoDataValueList,
QList<double> destNoDataValueList,
QgsRasterDataProvider* destProvider,
QProgressDialog* progressDialog )
{
Q_UNUSED( pipe );
Q_UNUSED( destHasNoDataValueList );
QgsDebugMsg( "Entered" );

const QgsRasterInterface* iface = iter->input();
const QgsRasterDataProvider* srcProvider = dynamic_cast<const QgsRasterDataProvider*>( iface->srcInput() );
int nBands = iface->bandCount();

//Get output map units per pixel
int iterLeft = 0;
int iterTop = 0;
int iterCols = 0;
int iterRows = 0;

int dataTypeSize = srcProvider->typeSize( srcProvider->srcDataType( 1 ) );
QList<void*> dataList;
for ( int i = 1; i <= nBands; ++i )
{
iter->startRasterRead( i, nCols, nRows, outputExtent );
dataList.push_back( VSIMalloc( dataTypeSize * mMaxTileWidth * mMaxTileHeight ) );
destProvider->setNoDataValue( i, destNoDataValueList.value( i - 1 ) );
}

destProvider = initOutput( nCols, nRows, crs, geoTransform, nBands, srcProvider->srcDataType( 1 ) );

int nParts = 0;
int fileIndex = 0;
if ( p )
if ( progressDialog )
{
int nPartsX = nCols / iter->maximumTileWidth() + 1;
int nPartsY = nRows / iter->maximumTileHeight() + 1;
nParts = nPartsX * nPartsY;
p->setMaximum( nParts );
p->show();
p->setLabelText( QObject::tr( "Reading raster part %1 of %2" ).arg( fileIndex + 1 ).arg( nParts ) );
progressDialog->setMaximum( nParts );
progressDialog->show();
progressDialog->setLabelText( QObject::tr( "Reading raster part %1 of %2" ).arg( fileIndex + 1 ).arg( nParts ) );
}

while ( true )
Expand All @@ -175,14 +313,15 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster( QgsRaster

return NoError; //reached last tile, bail out
}
// TODO: verify if NoDataConflict happened, to do that we need the whole pipe or nuller interface
}

if ( p && fileIndex < ( nParts - 1 ) )
if ( progressDialog && fileIndex < ( nParts - 1 ) )
{
p->setValue( fileIndex + 1 );
p->setLabelText( QObject::tr( "Reading raster part %1 of %2" ).arg( fileIndex + 2 ).arg( nParts ) );
progressDialog->setValue( fileIndex + 1 );
progressDialog->setLabelText( QObject::tr( "Reading raster part %1 of %2" ).arg( fileIndex + 2 ).arg( nParts ) );
QCoreApplication::processEvents( QEventLoop::AllEvents, 1000 );
if ( p->wasCanceled() )
if ( progressDialog->wasCanceled() )
{
for ( int i = 0; i < nBands; ++i )
{
Expand All @@ -196,7 +335,7 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster( QgsRaster
{
delete destProvider;
destProvider = createPartProvider( outputExtent, nCols, iterCols, iterRows,
iterLeft, iterTop, mOutputUrl, fileIndex, nBands, iface->dataType( 1 ), crs );
iterLeft, iterTop, mOutputUrl, fileIndex, nBands, destDataType, crs );

//write data to output file. todo: loop over the data list
for ( int i = 1; i <= nBands; ++i )
Expand All @@ -215,16 +354,13 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster( QgsRaster
CPLFree( dataList[i - 1] );
}
}



++fileIndex;
}
return NoError;
}

QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeImageRaster( QgsRasterIterator* iter, int nCols, int nRows, const QgsRectangle& outputExtent,
const QgsCoordinateReferenceSystem& crs, QProgressDialog* p )
const QgsCoordinateReferenceSystem& crs, QProgressDialog* progressDialog )
{
QgsDebugMsg( "Entered" );
if ( !iter )
Expand Down Expand Up @@ -270,14 +406,14 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeImageRaster( QgsRaste
iter->startRasterRead( 1, nCols, nRows, outputExtent );

int nParts = 0;
if ( p )
if ( progressDialog )
{
int nPartsX = nCols / iter->maximumTileWidth() + 1;
int nPartsY = nRows / iter->maximumTileHeight() + 1;
nParts = nPartsX * nPartsY;
p->setMaximum( nParts );
p->show();
p->setLabelText( QObject::tr( "Reading raster part %1 of %2" ).arg( fileIndex + 1 ).arg( nParts ) );
progressDialog->setMaximum( nParts );
progressDialog->show();
progressDialog->setLabelText( QObject::tr( "Reading raster part %1 of %2" ).arg( fileIndex + 1 ).arg( nParts ) );
}

while ( iter->readNextRasterPart( 1, iterCols, iterRows, &data, iterLeft, iterTop ) )
Expand All @@ -288,12 +424,12 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeImageRaster( QgsRaste
continue;
}

if ( p && fileIndex < ( nParts - 1 ) )
if ( progressDialog && fileIndex < ( nParts - 1 ) )
{
p->setValue( fileIndex + 1 );
p->setLabelText( QObject::tr( "Reading raster part %1 of %2" ).arg( fileIndex + 2 ).arg( nParts ) );
progressDialog->setValue( fileIndex + 1 );
progressDialog->setLabelText( QObject::tr( "Reading raster part %1 of %2" ).arg( fileIndex + 2 ).arg( nParts ) );
QCoreApplication::processEvents( QEventLoop::AllEvents, 1000 );
if ( p->wasCanceled() )
if ( progressDialog->wasCanceled() )
{
CPLFree( data );
break;
Expand Down Expand Up @@ -349,9 +485,9 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeImageRaster( QgsRaste
delete destProvider;
CPLFree( redData ); CPLFree( greenData ); CPLFree( blueData ); CPLFree( alphaData );

if ( p )
if ( progressDialog )
{
p->setValue( p->maximum() );
progressDialog->setValue( progressDialog->maximum() );
}

if ( mTiledMode )
Expand Down Expand Up @@ -462,16 +598,16 @@ int QgsRasterFileWriter::pyramidsProgress( double dfComplete, const char *pszMes
{
Q_UNUSED( pszMessage );
GDALTermProgress( dfComplete, 0, 0 );
QProgressDialog* p = static_cast<QProgressDialog*>( pData );
if ( pData && p->wasCanceled() )
QProgressDialog* progressDialog = static_cast<QProgressDialog*>( pData );
if ( pData && progressDialog->wasCanceled() )
{
return 0;
}

if ( pData )
{
p->setRange( 0, 100 );
p->setValue( dfComplete * 100 );
progressDialog->setRange( 0, 100 );
progressDialog->setValue( dfComplete * 100 );
}
return 1;
}
Expand Down
29 changes: 23 additions & 6 deletions src/core/raster/qgsrasterfilewriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,20 +35,23 @@ class CORE_EXPORT QgsRasterFileWriter
SourceProviderError = 1,
DestProviderError = 2,
CreateDatasourceError = 3,
WriteError = 4
WriteError = 4,
// Internal error if a value used for 'no data' was found in input
NoDataConflict = 5
};

QgsRasterFileWriter( const QString& outputUrl );
~QgsRasterFileWriter();

/**Write raster file
@param iter raster iterator
@param pipe raster pipe
@param nCols number of output columns
@param nRows number of output rows (or -1 to automatically calculate row number to have square pixels)
@param outputExtent extent to output
@param crs crs to reproject to
@param p dialog to show progress in */
WriterError writeRaster( QgsRasterIterator* iter, int nCols, int nRows, QgsRectangle outputExtent,
//WriterError writeRaster( QgsRasterIterator* iter, int nCols, int nRows, QgsRectangle outputExtent,
WriterError writeRaster( const QgsRasterPipe* pipe, int nCols, int nRows, QgsRectangle outputExtent,
const QgsCoordinateReferenceSystem& crs, QProgressDialog* p = 0 );

void setOutputFormat( const QString& format ) { mOutputFormat = format; }
Expand All @@ -72,10 +75,24 @@ class CORE_EXPORT QgsRasterFileWriter

private:
QgsRasterFileWriter(); //forbidden
WriterError writeDataRaster( QgsRasterIterator* iter, int nCols, int nRows, const QgsRectangle& outputExtent,
const QgsCoordinateReferenceSystem& crs, QProgressDialog* p = 0 );
//WriterError writeDataRaster( QgsRasterIterator* iter, int nCols, int nRows, const QgsRectangle& outputExtent,
WriterError writeDataRaster( const QgsRasterPipe* pipe, QgsRasterIterator* iter, int nCols, int nRows, const QgsRectangle& outputExtent,
const QgsCoordinateReferenceSystem& crs, QProgressDialog* progressDialog = 0 );

// Helper method used by previous one
WriterError writeDataRaster( const QgsRasterPipe* pipe,
QgsRasterIterator* iter,
int nCols, int nRows,
const QgsRectangle& outputExtent,
const QgsCoordinateReferenceSystem& crs,
QgsRasterInterface::DataType destDataType,
QList<bool> destHasNoDataValueList,
QList<double> destNoDataValueList,
QgsRasterDataProvider* destProvider,
QProgressDialog* progressDialog );

WriterError writeImageRaster( QgsRasterIterator* iter, int nCols, int nRows, const QgsRectangle& outputExtent,
const QgsCoordinateReferenceSystem& crs, QProgressDialog* p = 0 );
const QgsCoordinateReferenceSystem& crs, QProgressDialog* progressDialog = 0 );

//initialize vrt member variables
void createVRT( int xSize, int ySize, const QgsCoordinateReferenceSystem& crs, double* geoTransform );
Expand Down
47 changes: 47 additions & 0 deletions src/core/raster/qgsrasterinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
* *
***************************************************************************/

#include <limits>
#include <typeinfo>

#include <QByteArray>
Expand Down Expand Up @@ -86,6 +87,51 @@ bool QgsRasterInterface::typeIsColor( DataType dataType ) const
return false;
}

QgsRasterInterface::DataType QgsRasterInterface::typeWithNoDataValue( DataType dataType, double *noDataValue )
{
DataType newDataType;

switch ( dataType )
{
case QgsRasterInterface::Byte:
*noDataValue = -32768.0;
newDataType = QgsRasterInterface::Int16;
break;
case QgsRasterInterface::Int16:
*noDataValue = -2147483648.0;
newDataType = QgsRasterInterface::Int32;
break;
case QgsRasterInterface::UInt16:
*noDataValue = -2147483648.0;
newDataType = QgsRasterInterface::Int32;
break;
case QgsRasterInterface::UInt32:
case QgsRasterInterface::Int32:
case QgsRasterInterface::Float32:
case QgsRasterInterface::Float64:
*noDataValue = std::numeric_limits<double>::max() * -1.0;
newDataType = QgsRasterInterface::Float64;
default:
QgsDebugMsg( QString( "Unknow data type %1" ).arg( dataType ) );
return UnknownDataType;
break;
}
QgsDebugMsg( QString( "newDataType = %1 noDataValue = %2" ).arg( newDataType ).arg( *noDataValue ) );
return newDataType;
}

inline bool QgsRasterInterface::isNoDataValue( int bandNo, double value ) const
{
// More precise would be qIsNaN(value) && qIsNaN(noDataValue(bandNo)), but probably
// not important and slower
if ( qIsNaN( value ) ||
doubleNear( value, noDataValue( bandNo ) ) )
{
return true;
}
return false;
}

// To give to an image preallocated memory is the only way to avoid memcpy
// when we want to keep data but delete QImage
QImage * QgsRasterInterface::createImage( int width, int height, QImage::Format format )
Expand Down Expand Up @@ -163,3 +209,4 @@ double QgsRasterInterface::time( bool cumulative )
}
return t;
}

100 changes: 100 additions & 0 deletions src/core/raster/qgsrasterinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@

#include "qgsrectangle.h"

#include "gdal.h"

/** \ingroup core
* Base class for processing modules.
*/
Expand Down Expand Up @@ -115,15 +117,32 @@ class CORE_EXPORT QgsRasterInterface
return UnknownDataType;
}

/** For given data type returns wider type and sets no data value */
static DataType typeWithNoDataValue( DataType dataType, double *noDataValue );

/** Get number of bands */
virtual int bandCount() const
{
return 1;
}

/** Retruns value representing 'no data' (NULL) */
// TODO: Q_DECL_DEPRECATED
virtual double noDataValue() const { return 0; }

/** Return no data value for specific band. Each band/provider must have
* no data value, if there is no one set in original data, provider decides one
* possibly using wider data type.
* @param bandNo band number
* @return No data value */
virtual double noDataValue( int bandNo ) const { Q_UNUSED( bandNo ); return noDataValue(); }

/** Test if value is nodata for specific band
* @param bandNo band number
* @param value tested value
* @return true if value is nodata */
virtual bool isNoDataValue( int bandNo, double value ) const ;

/** Read block of data using given extent and size.
* Returns pointer to data.
* Caller is responsible to free the memory returned.
Expand Down Expand Up @@ -179,6 +198,9 @@ class CORE_EXPORT QgsRasterInterface
// On/off state, if off, it does not do anything, replicates input
bool mOn;

inline double readValue( void *data, QgsRasterInterface::DataType type, int index );
inline void writeValue( void *data, QgsRasterInterface::DataType type, int index, double value );

private:
// Last rendering cumulative (this and all preceding interfaces) times, from index 1
QVector<double> mTime;
Expand All @@ -187,6 +209,84 @@ class CORE_EXPORT QgsRasterInterface
int mStatsOn;
};

inline double QgsRasterInterface::readValue( void *data, QgsRasterInterface::DataType type, int index )
{
if ( !mInput )
{
return 0;
}

if ( !data )
{
return mInput->noDataValue();
}

switch ( type )
{
case QgsRasterInterface::Byte:
return ( double )(( GByte * )data )[index];
break;
case QgsRasterInterface::UInt16:
return ( double )(( GUInt16 * )data )[index];
break;
case QgsRasterInterface::Int16:
return ( double )(( GInt16 * )data )[index];
break;
case QgsRasterInterface::UInt32:
return ( double )(( GUInt32 * )data )[index];
break;
case QgsRasterInterface::Int32:
return ( double )(( GInt32 * )data )[index];
break;
case QgsRasterInterface::Float32:
return ( double )(( float * )data )[index];
break;
case QgsRasterInterface::Float64:
return ( double )(( double * )data )[index];
break;
default:
//QgsMessageLog::logMessage( tr( "GDAL data type %1 is not supported" ).arg( type ), tr( "Raster" ) );
break;
}

// TODO: noDataValue is per band
return mInput->noDataValue();
}

inline void QgsRasterInterface::writeValue( void *data, QgsRasterInterface::DataType type, int index, double value )
{
if ( !mInput ) return;
if ( !data ) return;

switch ( type )
{
case QgsRasterInterface::Byte:
(( GByte * )data )[index] = ( GByte ) value;
break;
case QgsRasterInterface::UInt16:
(( GUInt16 * )data )[index] = ( GUInt16 ) value;
break;
case QgsRasterInterface::Int16:
(( GInt16 * )data )[index] = ( GInt16 ) value;
break;
case QgsRasterInterface::UInt32:
(( GUInt32 * )data )[index] = ( GUInt32 ) value;
break;
case QgsRasterInterface::Int32:
(( GInt32 * )data )[index] = ( GInt32 ) value;
break;
case QgsRasterInterface::Float32:
(( float * )data )[index] = ( float ) value;
break;
case QgsRasterInterface::Float64:
(( double * )data )[index] = value;
break;
default:
//QgsMessageLog::logMessage( tr( "GDAL data type %1 is not supported" ).arg( type ), tr( "Raster" ) );
break;
}
}

#endif


17 changes: 5 additions & 12 deletions src/core/raster/qgsrasterlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,6 @@ email : tim at linfiniti.com
typedef void buildsupportedrasterfilefilter_t( QString & theFileFiltersString );
typedef bool isvalidrasterfilename_t( QString const & theFileNameQString, QString & retErrMsg );

// workaround for MSVC compiler which already has defined macro max
// that interferes with calling std::numeric_limits<int>::max
#ifdef _MSC_VER
# ifdef max
# undef max
# endif
#endif

// Comparison value for equality; i.e., we shouldn't directly compare two
// floats so it's better to take their difference and see if they're within
// a certain range -- in this case twenty times the smallest value that
Expand Down Expand Up @@ -339,6 +331,7 @@ int QgsRasterLayer::bandNumber( QString const & theBandName ) const
return 0; //no band was found
}

#if 0
/**
* Private method to calculate statistics for a band. Populates rasterStatsMemArray.
* Calculates:
Expand All @@ -358,7 +351,6 @@ int QgsRasterLayer::bandNumber( QString const & theBandName ) const
* @sa RasterBandStats
* @note This is a cpu intensive and slow task!
*/
/*
const QgsRasterBandStats QgsRasterLayer::bandStatistics( int theBandNo )
{
QgsDebugMsg( "theBandNo = " + QString::number( theBandNo ) );
Expand Down Expand Up @@ -431,7 +423,7 @@ const QgsRasterBandStats QgsRasterLayer::bandStatistics( QString const & theBand

return QgsRasterBandStats(); // return a null one
}
*/
#endif

QString QgsRasterLayer::buildPyramids( RasterPyramidList const & theRasterPyramidList,
QString const & theResamplingMethod, bool theTryInternalFlag )
Expand Down Expand Up @@ -2234,8 +2226,8 @@ void QgsRasterLayer::setRenderer( QgsRasterRenderer* theRenderer )
mPipe.set( theRenderer );
}

#if 0
// not sure if we want it
/*
void QgsRasterLayer::setResampleFilter( QgsRasterResampleFilter* resampleFilter )
{
QgsDebugMsg( "Entered" );
Expand All @@ -2246,7 +2238,8 @@ void QgsRasterLayer::setResampleFilter( QgsRasterResampleFilter* resampleFilter
QgsDebugMsg( "Cannot set resample filter." );
}
}
*/
#endif

void QgsRasterLayer::showProgress( int theValue )
{
emit progressUpdate( theValue );
Expand Down
86 changes: 86 additions & 0 deletions src/core/raster/qgsrasternuller.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/***************************************************************************
qgsrasternuller.cpp
---------------------
begin : August 2012
copyright : (C) 2012 by Radim Blazek
email : radim dot blazek at gmail dot com
***************************************************************************/

/***************************************************************************
* *
* 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 "qgsrasterdataprovider.h"
#include "qgsrasternuller.h"

QgsRasterNuller::QgsRasterNuller( QgsRasterInterface* input )
: QgsRasterInterface( input )
{
}

QgsRasterNuller::~QgsRasterNuller()
{
}

QgsRasterInterface * QgsRasterNuller::clone() const
{
QgsDebugMsg( "Entered" );
QgsRasterNuller * nuller = new QgsRasterNuller( 0 );
nuller->mNoData = mNoData;
return nuller;
}

int QgsRasterNuller::bandCount() const
{
if ( mInput ) return mInput->bandCount();
return 0;
}

QgsRasterInterface::DataType QgsRasterNuller::dataType( int bandNo ) const
{
if ( mInput ) return mInput->dataType( bandNo );
return QgsRasterInterface::UnknownDataType;
}

void * QgsRasterNuller::readBlock( int bandNo, QgsRectangle const & extent, int width, int height )
{
QgsDebugMsg( "Entered" );
if ( !mInput ) return 0;

//QgsRasterDataProvider *provider = dynamic_cast<QgsRasterDataProvider*>( mInput->srcInput() );

void * rasterData = mInput->block( bandNo, extent, width, height );

QgsRasterInterface::DataType dataType = mInput->dataType( bandNo );
int pixelSize = mInput->typeSize( dataType ) / 8;

double noDataValue = mInput->noDataValue ( bandNo );

for ( int i = 0; i < height; ++i )
{
for ( int j = 0; j < width; ++j )
{
int index = pixelSize * ( i * width + j );

double value = readValue( rasterData, dataType, index );

foreach ( NoData noData, mNoData )
{
if ( ( value >= noData.min && value <= noData.max ) ||
doubleNear( value, noData.min ) ||
doubleNear( value, noData.max ) )
{
writeValue( rasterData, dataType, index, noDataValue );
}
}
}
}

return rasterData;
}

52 changes: 52 additions & 0 deletions src/core/raster/qgsrasternuller.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/***************************************************************************
qgsrasternuller.h
-------------------
begin : August 2012
copyright : (C) 2012 by Radim Blazek
email : radim dot blazek at gmail dot com
***************************************************************************/

/***************************************************************************
* *
* 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 QGSRASTERNULLER_H
#define QGSRASTERNULLER_H

#include "qgsrasterdataprovider.h"
#include "qgsrasterinterface.h"

#include <QList>

class CORE_EXPORT QgsRasterNuller : public QgsRasterInterface
{
public:
QgsRasterNuller( QgsRasterInterface* input = 0 );
~QgsRasterNuller();

struct NoData
{
double min;
double max;
};

QgsRasterInterface * clone() const;

int bandCount() const;

QgsRasterInterface::DataType dataType( int bandNo ) const;

void * readBlock( int bandNo, QgsRectangle const & extent, int width, int height );

void setNoData( QList<QgsRasterNuller::NoData> noData ) { mNoData = noData; }

private:
QList<QgsRasterNuller::NoData> mNoData;
};

#endif // QGSRASTERNULLER_H
8 changes: 7 additions & 1 deletion src/core/raster/qgsrasterrendererregistry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,21 +275,27 @@ QgsRasterRenderer* QgsRasterRendererRegistry::defaultRendererForDrawingStyle( co
if ( bandCount == 1 )
{
QList<QgsRasterTransparency::TransparentSingleValuePixel> transparentSingleList;
// No need to set no data value in transparency list, I think
#if 0
QgsRasterTransparency::TransparentSingleValuePixel singleEntry;
singleEntry.pixelValue = provider->noDataValue();
singleEntry.min = provider->noDataValue();
singleEntry.max = provider->noDataValue();
singleEntry.percentTransparent = 100;
transparentSingleList.push_back( singleEntry );
#endif
tr->setTransparentSingleValuePixelList( transparentSingleList );
}
else if ( bandCount == 3 )
{
QList<QgsRasterTransparency::TransparentThreeValuePixel> transparentThreeValueList;
#if 0
QgsRasterTransparency::TransparentThreeValuePixel threeValueEntry;
threeValueEntry.red = provider->noDataValue();
threeValueEntry.green = provider->noDataValue();
threeValueEntry.blue = provider->noDataValue();
threeValueEntry.percentTransparent = 100;
transparentThreeValueList.push_back( threeValueEntry );
#endif
tr->setTransparentThreeValuePixelList( transparentThreeValueList );
}
renderer->setRasterTransparency( tr );
Expand Down
32 changes: 25 additions & 7 deletions src/core/raster/qgsrastertransparency.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ void QgsRasterTransparency::initializeTransparentPixelList( double theValue )

//add the initial value
TransparentSingleValuePixel myTransparentSingleValuePixel;
myTransparentSingleValuePixel.pixelValue = theValue;
myTransparentSingleValuePixel.min = theValue;
myTransparentSingleValuePixel.max = theValue;
myTransparentSingleValuePixel.percentTransparent = 100.0;
mTransparentSingleValuePixelList.append( myTransparentSingleValuePixel );
}
Expand Down Expand Up @@ -113,7 +114,7 @@ int QgsRasterTransparency::alphaValue( double theValue, int theGlobalTransparenc
for ( int myListRunner = 0; myListRunner < mTransparentSingleValuePixelList.count(); myListRunner++ )
{
myTransparentPixel = mTransparentSingleValuePixelList[myListRunner];
if ( myTransparentPixel.pixelValue == theValue )
if ( theValue >= myTransparentPixel.min && theValue <= myTransparentPixel.max )
{
myTransparentPixelFound = true;
break;
Expand Down Expand Up @@ -177,11 +178,17 @@ bool QgsRasterTransparency::isEmpty( double nodataValue ) const
{
return (
( mTransparentSingleValuePixelList.isEmpty() ||
( mTransparentSingleValuePixelList.size() == 1 && doubleNear( mTransparentSingleValuePixelList.at( 0 ).pixelValue, nodataValue ) ) )
( mTransparentSingleValuePixelList.size() == 1 &&
( doubleNear( mTransparentSingleValuePixelList.at( 0 ).min, nodataValue ) ||
doubleNear( mTransparentSingleValuePixelList.at( 0 ).max, nodataValue ) ||
( nodataValue > mTransparentSingleValuePixelList.at( 0 ).min &&
nodataValue < mTransparentSingleValuePixelList.at( 0 ).max ) ) ) )
&&
( mTransparentThreeValuePixelList.isEmpty() ||
( mTransparentThreeValuePixelList.size() < 4 && doubleNear( mTransparentThreeValuePixelList.at( 0 ).red, nodataValue ) &&
doubleNear( mTransparentThreeValuePixelList.at( 0 ).green, nodataValue ) && doubleNear( mTransparentThreeValuePixelList.at( 0 ).blue, nodataValue ) ) ) );
( mTransparentThreeValuePixelList.size() == 1 &&
doubleNear( mTransparentThreeValuePixelList.at( 0 ).red, nodataValue ) &&
doubleNear( mTransparentThreeValuePixelList.at( 0 ).green, nodataValue ) &&
doubleNear( mTransparentThreeValuePixelList.at( 0 ).blue, nodataValue ) ) ) );
}

void QgsRasterTransparency::writeXML( QDomDocument& doc, QDomElement& parentElem ) const
Expand All @@ -194,7 +201,9 @@ void QgsRasterTransparency::writeXML( QDomDocument& doc, QDomElement& parentElem
for ( ; it != mTransparentSingleValuePixelList.constEnd(); ++it )
{
QDomElement pixelListElement = doc.createElement( "pixelListEntry" );
pixelListElement.setAttribute( "pixelValue", QString::number( it->pixelValue, 'f' ) );
//pixelListElement.setAttribute( "pixelValue", QString::number( it->pixelValue, 'f' ) );
pixelListElement.setAttribute( "min", QString::number( it->min, 'f' ) );
pixelListElement.setAttribute( "max", QString::number( it->max, 'f' ) );
pixelListElement.setAttribute( "percentTransparent", QString::number( it->percentTransparent ) );
singleValuePixelListElement.appendChild( pixelListElement );
}
Expand Down Expand Up @@ -239,7 +248,16 @@ void QgsRasterTransparency::readXML( const QDomElement& elem )
{
currentEntryElem = entryList.at( i ).toElement();
sp.percentTransparent = currentEntryElem.attribute( "percentTransparent" ).toDouble();
sp.pixelValue = currentEntryElem.attribute( "pixelValue" ).toDouble();
// Backward compoatibility < 1.9 : pixelValue (before ranges)
if ( currentEntryElem.hasAttribute( "pixelValue" ) )
{
sp.min = sp.max = currentEntryElem.attribute( "pixelValue" ).toDouble();
}
else
{
sp.min = currentEntryElem.attribute( "min" ).toDouble();
sp.max = currentEntryElem.attribute( "max" ).toDouble();
}
mTransparentSingleValuePixelList.append( sp );
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/core/raster/qgsrastertransparency.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ class CORE_EXPORT QgsRasterTransparency

struct TransparentSingleValuePixel
{
double pixelValue;
double min;
double max;
double percentTransparent;
};

Expand Down
7 changes: 7 additions & 0 deletions src/core/raster/qgssinglebandgrayrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,13 @@ void * QgsSingleBandGrayRenderer::readBlock( int bandNo, QgsRectangle const & e
{
grayVal = readValue( rasterData, rasterType, currentRasterPos );

if ( mInput->isNoDataValue( mGrayBand, grayVal ) )
{
imageScanLine[j] = myDefaultColor;
++currentRasterPos;
continue;
}

//alpha
currentAlpha = mOpacity;
if ( mRasterTransparency )
Expand Down
6 changes: 6 additions & 0 deletions src/core/raster/qgssinglebandpseudocolorrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,12 @@ void * QgsSingleBandPseudoColorRenderer::readBlock( int bandNo, QgsRectangle co
for ( int j = 0; j < width; ++j )
{
val = readValue( rasterData, rasterType, currentRasterPos );
if ( mInput->isNoDataValue( mBand, val ) )
{
imageScanLine[j] = myDefaultColor;
++currentRasterPos;
continue;
}
if ( !mShader->shade( val, &red, &green, &blue ) )
{
imageScanLine[j] = myDefaultColor;
Expand Down
685 changes: 405 additions & 280 deletions src/core/symbology-ng/qgsstylev2.cpp

Large diffs are not rendered by default.

228 changes: 181 additions & 47 deletions src/core/symbology-ng/qgsstylev2.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,42 @@ class QDomElement;

typedef QMap<QString, QgsVectorColorRampV2* > QgsVectorColorRampV2Map;
typedef QMap<int, QString> QgsSymbolGroupMap;

/*!
* A multimap to hold the smart group conditions as constraint and parameter pairs.
* Both the key and the value of the map are QString. The key is the constraint of the condition and the value is the parameter which is applied for the constraint.
*
* The supported constraints are:
* tag -> symbol has the tag matching the parameter
* !tag -> symbol doesnot have the tag matching the parameter
* group -> symbol belongs to group specified by the parameter
* !group -> symbol doesn't belong to the group specified by the parameter
* name -> symbol has a part of its name matching the parameter
* !name -> symbol doesn't have any part of the name matching the parameter
*
* Example Usage:
* QgsSmartConditionMap conditions;
* conditions.insert( "tag", "red" ); // adds the condition: Symbol has the tag red
* conditions.insert( "!name", "way" ); // add the condition: Symbol doesn't have any part of its name matching `way`
*
* \note This is a Multimap, which means it will contain multiple values for the same key.
*/
typedef QMultiMap<QString, QString> QgsSmartConditionMap;

// Enumeraters representing sqlite DB columns
// enumerators representing sqlite DB columns
enum SymbolTable { SymbolId, SymbolName, SymbolXML, SymbolGroupId };
enum SymgroupTable { SymgroupId, SymgroupName, SymgroupParent };
enum TagTable { TagId, TagName };
enum TagmapTable { TagmapTagId, TagmapSymbolId };
enum ColorrampTable { ColorrampId, ColorrampName, ColorrampXML, ColorrampGroupId };
enum SmartgroupTable { SmartgroupId, SmartgroupName, SmartgroupXML };

// Enums for types
//! Enum for Entities involved in a style
/*!
The enumarator is used for identifying the entity being operated on when generic
database functions are being run.
\sa group(), rename(), remove(), symbolsOfGroup(), symbolsWithTag(), symbolsOfSmartgroup()
*/
enum StyleEntity { SymbolEntity, GroupEntity, TagEntity, ColorrampEntity, SmartgroupEntity };

class CORE_EXPORT QgsStyleV2
Expand All @@ -53,14 +78,93 @@ class CORE_EXPORT QgsStyleV2
QgsStyleV2();
~QgsStyleV2();

//! return default application-wide style
static QgsStyleV2* defaultStyle();
//! add color ramp to style. takes ramp's ownership
/*!
* \note Adding a color ramp with the name of existing one replaces it.
* \param name is the name of the color ramp being added or updated
* \param colorRamp is the Vector color ramp
* \param update set to true when the style DB has to be updated, by default it is false
* \return sucess status of the operation
*/
bool addColorRamp( QString name, QgsVectorColorRampV2* colorRamp, bool update = false );

//! adds a new group and returns the group's id
/*!
* \param groupName the name of the new group as QString
* \param parent is the id of the parent group when a subgrouo is to be created. By default it is 0 indicating it is not a sub-group
* \return returns an int, which is the DB id of the new group created, 0 if the group couldn't be created
*/
int addGroup( QString groupName, int parent = 0 );

//! adds new smartgroup to the database and returns the id
/*!
* \param name is the name of the new Smart Group to be added
* \param op is the operator between the conditions; AND/OR as QString
* \param conditions are the smart group conditions
*/
int addSmartgroup( QString name, QString op, QgsSmartConditionMap conditions );

//! add symbol to style. takes symbol's ownership
/*!
* \note Adding a symbol with the name of existing one replaces it.
* \param name is the name of the symbol being added or updated
* \param symbol is the Vector symbol
* \param update set to true when the style DB has to be updated, by default it is false
* \return sucess status of the operation
*/
bool addSymbol( QString name, QgsSymbolV2* symbol, bool update = false );

//! adds a new tag and returns the tag's id
/*!
* \param tagName the name of the new tag to be created
* \return returns an int, which is the DB id of the new tag created, 0 if the tag couldn't be created
*/
int addTag( QString tagName );

//! return a map of groupid and names for the given parent group
QgsSymbolGroupMap childGroupNames( QString parent = "" );

//! remove all contents of the style
void clear();

//! add symbol to style. takes symbol's ownership
bool addSymbol( QString name, QgsSymbolV2* symbol );
//! return a NEW copy of color ramp
QgsVectorColorRampV2* colorRamp( QString name );

//! return count of color ramps
int colorRampCount();

//! return a list of names of color ramps
QStringList colorRampNames();

//! return a const pointer to a symbol (doesn't create new instance)
const QgsVectorColorRampV2* colorRampRef( QString name ) const;

//! return the id in the style database for the given colorramp name
//! returns 0 if not found
int colorrampId( QString name );

//! return default application-wide style
static QgsStyleV2* defaultStyle();

//! tags the symbol with the tags in the list
/*!
* Applies the given tags to the given symbol or colorramp
* \param type is either SymbolEntity or ColorrampEntity
* \param symbol is the name of the symbol or colorramp as QString
* \param tags is the list of the tags that are to be applied as QStringList
* \return returns the success state of the operation
*/
bool tagSymbol( StyleEntity type, QString symbol, QStringList tags );

//! detags the symbol with the given list
/*!
* Removes the given tags for the specified symbol or colorramp
* \param type is either SymbolEntity or ColorrampEntity
* \param symbol is the name of the symbol or colorramp
* \param tags is the list of tags that are to be removed as QStringList
* \return returns the sucess state of the operation
*/
bool detagSymbol( StyleEntity type, QString symbol, QStringList tags );

//! remove symbol from style (and delete it)
bool removeSymbol( QString name );
Expand All @@ -84,63 +188,83 @@ class CORE_EXPORT QgsStyleV2
//! return the id in the style database for the given symbol name
//! returns 0 if not found
int symbolId( QString name );
int colorrampId( QString name );

//! return the id in the style database for the given group name
//! return the DB id for the given group name
int groupId( QString group );
//! return the DB id for the given tag name
int tagId( QString tag );
//! return the DB id for the given smartgroup name
int smartgroupId( QString smartgroup );

//! return the all the groups in the style
QStringList groupNames();

//! return a map of groupid and names for the given parent
QgsSymbolGroupMap childGroupNames( QString parent = "" );

//! returns the symbolnames of a given groupid
/*!
* \param type is either SymbolEntity or ColorampEntity
* \param groupid is id of the group to which the symbols belong to, as int
* \return A QStringList of the symbol or colorramp names for the given group id
*/
QStringList symbolsOfGroup( StyleEntity type, int groupid );

//! returns the symbol names with which have the given tag
/*!
* \param type is either SymbolEntity or ColorampEntity
* \param tagid is id of the tag which has been applied over the symbol as int
* \return A QStringList of the symbol or colorramp names for the given tag id
*/
QStringList symbolsWithTag( StyleEntity type, int tagid );
//! adds a new group and returns the group's id
int addGroup( QString groupName, int parent = 0 );
//! adds a new tag and returns the tag's id
int addTag( QString tagName );

//! applies the specifed group to the symbol or colorramp specified by StyleEntity
/*!
* \param type is either SymbolEntity of ColorrampEntity
* \param name is the name of the symbol or coloramp whose group is to be set
* \param groupid is the id of the group to which the entity is assigned
* \return returns the success state as bool
*/
bool group( StyleEntity type, QString name, int groupid );

//! rename the given entity with the specified id
/*!
* \param type is any of the style entites. Refer enum StyleEntity.
* \param id is the DB id of the entity which is to be renamed
* \param newName is the new name of the entity
*/
void rename( StyleEntity type, int id, QString newName );

//! remove the specified entity from the db
/*!
* \param type is any of the style entites. Refer enum StyleEntity.
* \param id is the DB id of the entity to be removed
*/
void remove( StyleEntity type, int id );

//! add the symbol to the DB with the tags
/*!
* \param name is the name of the symbol as QString
* \param symbol is the pointer to the new QgsSymbolV2 being saved
* \param groupid is the id of the group to which the symbol belongs. Pass 0 if it doesn't belong to any group or not known.
* \param tags is a list of tags that are associated with the symbol as a QStringList.
* \return returns the sucess state of the save operation
*/
bool saveSymbol( QString name, QgsSymbolV2* symbol, int groupid, QStringList tags );

//! add the colorramp to the DB
/*!
* \param name is the name of the colorramp as QString
* \param ramp is the pointer to the new QgsVectorColorRampV2 being saved
* \param groupid is the id of the group to which the Color Ramp belongs. Pass 0 if it doesn't belong to any group or not known.
* \param tags is a list of tags that are associated with the color ramp as a QStringList.
* \return returns the sucess state of the save operation
*/
bool saveColorRamp( QString name, QgsVectorColorRampV2* ramp, int groupid, QStringList tags );

//! add color ramp to style. takes ramp's ownership
bool addColorRamp( QString name, QgsVectorColorRampV2* colorRamp );

//! remove color ramp from style (and delete it)
bool removeColorRamp( QString name );

//! change ramp's name
//! @note added in v1.7
bool renameColorRamp( QString oldName, QString newName );

//! return a NEW copy of color ramp
QgsVectorColorRampV2* colorRamp( QString name );

//! return a const pointer to a symbol (doesn't create new instance)
const QgsVectorColorRampV2* colorRampRef( QString name ) const;

//! return count of color ramps
int colorRampCount();

//! return a list of names of color ramps
QStringList colorRampNames();


//! load a file into the style
bool load( QString filename );
Expand All @@ -157,19 +281,15 @@ class CORE_EXPORT QgsStyleV2
//! return the names of the symbols which have a matching 'substring' in its defintion
QStringList findSymbols( QString qword );

//! tags the symbol with the tags in the list, the remove flag DE-TAGS
bool tagSymbol( StyleEntity type, QString symbol, QStringList tags );

//! detags the symbol with the given list
bool detagSymbol( StyleEntity type, QString symbol, QStringList tags );

//! return the tags associated with the symbol
/*!
* \param type is either SymbolEntity or ColorrampEntity
* \param symbol is the name of the symbol or color ramp
* \return A QStringList of the tags that have been applied to that symbol/colorramp
*/
QStringList tagsOfSymbol( StyleEntity type, QString symbol );

//! adds the smartgroup to the database and returns the id
int addSmartgroup( QString name, QString op, QgsSmartConditionMap conditions );

//! returns the smart groups map
//! returns the smart groups map with id as key and name as value
QgsSymbolGroupMap smartgroupsListMap();

//! returns the smart groups list
Expand All @@ -179,7 +299,7 @@ class CORE_EXPORT QgsStyleV2
QgsSmartConditionMap smartgroup( int id );

//! returns the operator for the smartgroup
//! @note: clumsy implementation TODO create a class for smartgroups
//clumsy implementation TODO create a class for smartgroups
QString smartgroupOperator( int id );

//! returns the symbols for the smartgroup
Expand All @@ -203,15 +323,29 @@ class CORE_EXPORT QgsStyleV2

static QgsStyleV2* mDefaultStyle;

//! Convinence function to open the DB and return a sqlite3 object
//! convenience function to open the DB and return a sqlite3 object
bool openDB( QString filename );
//! Convinence function that would run queries which donot generate return values
//! it returns sucess result
bool runEmptyQuery( char* query );
//! prepares the complex query for removing a group,so that the children are not abandoned

//! convenience function that would run queries which don't generate return values
//! \param query query to run
//! \param freeQuery release query memory
//! \return success true on success
bool runEmptyQuery( char* query, bool freeQuery = true );

//! prepares the complex query for removing a group, so that the children are not abandoned
char* getGroupRemoveQuery( int id );

//! gets the id from the table for the given name from the database, 0 if not found
int getId( QString table, QString name );

//! updates the properties of an existing symbol/colorramp
/*!
* \note This should not be called seperately, only called through addSymbol or addColorRamp
* \param type is either SymbolEntity or ColorrampEntity
* \param name is the name of an existing symbol or a color ramp
* \return Success state of the update operation
*/
bool updateSymbol( StyleEntity type, QString name );
};


Expand Down
2 changes: 1 addition & 1 deletion src/gui/qgsmapcanvasmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ void QgsMapCanvasMap::render()

paint.end();

// convert QImage to QPixmap to acheive faster drawing on screen
// convert QImage to QPixmap to achieve faster drawing on screen
mPixmap = QPixmap::fromImage( mImage );
}
else
Expand Down
1 change: 1 addition & 0 deletions src/gui/qgsmessagelogviewer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ void QgsMessageLogViewer::logMessage( QString message, QString tag, int level )
w->verticalHeader()->setVisible( false );
w->setGridStyle( Qt::DotLine );
w->setEditTriggers( QAbstractItemView::NoEditTriggers );
w->setHorizontalScrollMode( QAbstractItemView::ScrollPerPixel );
w->setHorizontalHeaderLabels( QStringList() << tr( "Timestamp" ) << tr( "Message" ) << tr( "Level" ) );
tabWidget->addTab( w, tag );

Expand Down
14 changes: 7 additions & 7 deletions src/gui/qgsowssourceselect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ void QgsOWSSourceSelect::populateFormats()
formatsMap.insert( "jpg", "jpeg" );
formatsMap.insert( "png", "png" );

int prefered = -1;
int preferred = -1;
int firstEnabled = -1;
QStringList layersFormats = selectedLayersFormats();
for ( int i = 0; i < layersFormats.size(); i++ )
Expand Down Expand Up @@ -213,9 +213,9 @@ void QgsOWSSourceSelect::populateFormats()
if ( firstEnabled < 0 ) { firstEnabled = i; }
if ( simpleFormat.contains( "tif" ) ) // prefer *tif*
{
if ( prefered < 0 || simpleFormat.startsWith( "g" ) ) // prefere geotiff
if ( preferred < 0 || simpleFormat.startsWith( "g" ) ) // prefer geotiff
{
prefered = i;
preferred = i;
}
}
}
Expand All @@ -230,12 +230,12 @@ void QgsOWSSourceSelect::populateFormats()
btn->setText( label );
btn->setToolTip( tip );
}
// Set prefered
// Set preferred
// TODO: all enabled for now, see above
prefered = prefered >= 0 ? prefered : firstEnabled;
if ( prefered >= 0 )
preferred = preferred >= 0 ? preferred : firstEnabled;
if ( preferred >= 0 )
{
mImageFormatGroup->button( prefered )->setChecked( true );
mImageFormatGroup->button( preferred )->setChecked( true );
}

mImageFormatsGroupBox->setEnabled( true );
Expand Down
287 changes: 280 additions & 7 deletions src/gui/qgsrasterlayersaveasdialog.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "qgsapplication.h"
#include "qgslogger.h"
#include "qgscoordinatetransform.h"
#include "qgsrasterlayer.h"
#include "qgsrasterlayersaveasdialog.h"
#include "qgsrasterdataprovider.h"
#include "qgsrasterformatsaveoptionswidget.h"
Expand All @@ -8,17 +10,133 @@
#include <QFileDialog>
#include <QSettings>

QgsRasterLayerSaveAsDialog::QgsRasterLayerSaveAsDialog( QgsRasterDataProvider* sourceProvider, const QgsRectangle& currentExtent,
// this widget class will go into its separate file

// #include <QMouseEvent>
// #include <QStyleOptionGroupBox>
// #include <QStylePainter>

GroupBox::GroupBox( QWidget *parent )
: QGroupBox( parent ), m_collapsed( false )
{
connect( this, SIGNAL( toggled ( bool ) ), this, SLOT( setToggled( bool ) ) );
//setToggled( isChecked() );
}

GroupBox::GroupBox( const QString &title, QWidget *parent )
: QGroupBox(title, parent ), m_collapsed( false )
{}

bool GroupBox::isCollapsed() { return m_collapsed; }

// void GroupBox::mousePressEvent( QMouseEvent *e )
// {
// QgsDebugMsg("press event");
// if( e->button() == Qt::LeftButton )
// {
// QgsDebugMsg("left but");
// QStyleOptionGroupBox option;
// initStyleOption( &option );
// QRect buttonArea( 0, 0, 16, 16 );
// buttonArea.moveTopRight( option.rect.adjusted( 0, 0, -10, 0
// ).topRight() );
// if( buttonArea.contains( e->pos() ) )
// {
// clickPos = e->pos();
// return;
// }
// }
// QGroupBox::mousePressEvent( e );
// }

// void GroupBox::mouseReleaseEvent( QMouseEvent *e )
// {
// QgsDebugMsg("release");
// if( e->button() == Qt::LeftButton && clickPos == e->pos() )
// setCollapse( !isCollapsed() );
// }

// void GroupBox::paintEvent( QPaintEvent * )
// {
// QgsDebugMsg("paint event");

// QStylePainter paint( this );
// QStyleOptionGroupBox option;
// initStyleOption( &option );
// paint.drawComplexControl( QStyle::CC_GroupBox, option );
// paint.drawItemPixmap(
// option.rect.adjusted( 0, 0, -10, 0 ),
// Qt::AlignTop | Qt::AlignRight,
// QPixmap( m_collapsed ?
// ":/images/images/navigate_down2_16x16.png" :
// ":/images/images/navigate_up2_16x16.png" ) );
// }

void GroupBox::showEvent( QShowEvent * event )
{
// QgsDebugMsg(QString("%1 showEvent %2 %3").arg(objectName()).arg(isChecked()).arg(isCollapsed()));
QGroupBox::showEvent( event );
if ( ! isChecked() && ! isCollapsed() )
setCollapsed( true );
}

void GroupBox::setCollapsed( bool collapse )
{
if ( ! isVisible() )
return;
// QgsDebugMsg(QString("%1 setcollapse %2").arg(objectName()).arg(collapse));

// minimize layout margins, restore later
if ( collapse )
{
if ( layout() )
{
margins = layout()->contentsMargins();
layout()->setContentsMargins(1,1,1,1);
}
}
else
{
if ( layout() )
{
layout()->setContentsMargins( margins );
}
}
m_collapsed = collapse;
foreach( QWidget *widget, findChildren<QWidget*>() )
widget->setHidden( collapse );

if ( m_collapsed )
emit collapsed( this );
else
emit expanded( this );
}

QgsRasterLayerSaveAsDialog::QgsRasterLayerSaveAsDialog( QgsRasterLayer* rasterLayer, QgsRasterDataProvider* sourceProvider, const QgsRectangle& currentExtent,
const QgsCoordinateReferenceSystem& layerCrs,
const QgsCoordinateReferenceSystem& currentCrs,
QWidget* parent, Qt::WindowFlags f ):
QDialog( parent, f )
, mRasterLayer( rasterLayer )
, mDataProvider( sourceProvider )
, mCurrentExtent( currentExtent )
, mLayerCrs( layerCrs )
, mCurrentCrs( currentCrs )
, mExtentState( OriginalExtent )
, mResolutionState( OriginalResolution )
{
setupUi( this );
mAddNoDataManuallyToolButton->setIcon( QgsApplication::getThemeIcon( "/mActionNewAttribute.png" ) );
mLoadTransparentNoDataToolButton->setIcon( QgsApplication::getThemeIcon( "/mActionCopySelected.png" ) );
mRemoveSelectedNoDataToolButton->setIcon( QgsApplication::getThemeIcon( "/mActionDeleteAttribute.png" ) );
mRemoveAllNoDataToolButton->setIcon( QgsApplication::getThemeIcon( "/mActionRemove.png" ) );

mNoDataTableWidget->setColumnCount( 2 );
mNoDataTableWidget->setHorizontalHeaderItem( 0, new QTableWidgetItem( tr( "From" ) ) );
mNoDataTableWidget->setHorizontalHeaderItem( 1, new QTableWidgetItem( tr( "To" ) ) );

on_mRawModeRadioButton_toggled( true );

setValidators();
// Translated labels + EPSG are updated later
mCrsComboBox->addItem( "Layer", OriginalCrs );
Expand All @@ -40,7 +158,7 @@ QgsRasterLayerSaveAsDialog::QgsRasterLayerSaveAsDialog( QgsRasterDataProvider* s
if ( mDataProvider )
{
//extent
setOutputExtent( mDataProvider->extent(), mDataProvider->crs(), OriginalExtent );
setOutputExtent( mDataProvider->extent(), mLayerCrs, OriginalExtent );

if ( mDataProvider->capabilities() & QgsRasterDataProvider::ExactResolution )
{
Expand Down Expand Up @@ -72,6 +190,12 @@ QgsRasterLayerSaveAsDialog::QgsRasterLayerSaveAsDialog( QgsRasterDataProvider* s
{
okButton->setEnabled( false );
}

// this should scroll down to make widget visible, but it's not happening
// (at least part of it is visible)...
connect( mCreateOptionsGroupBox, SIGNAL( expanded( QWidget* ) ),
this, SLOT( groupBoxExpanded( QWidget* ) ) );

}

void QgsRasterLayerSaveAsDialog::setValidators()
Expand Down Expand Up @@ -130,7 +254,7 @@ void QgsRasterLayerSaveAsDialog::on_mOriginalExtentButton_clicked()
{
if ( mDataProvider )
{
setOutputExtent( mDataProvider->extent(), mDataProvider->crs(), OriginalExtent );
setOutputExtent( mDataProvider->extent(), mLayerCrs, OriginalExtent );
}
}

Expand Down Expand Up @@ -266,7 +390,7 @@ void QgsRasterLayerSaveAsDialog::setOriginalResolution()
// Init to something if no original resolution is available
xRes = yRes = mDataProvider->extent().width() / 100;
}
setResolution( xRes, yRes, mDataProvider->crs() );
setResolution( xRes, yRes, mLayerCrs );
mResolutionState = OriginalResolution;
recalcSize();
}
Expand Down Expand Up @@ -414,7 +538,7 @@ void QgsRasterLayerSaveAsDialog::crsChanged()
if ( mExtentState == OriginalExtent )
{
previousExtent = mDataProvider->extent();
previousCrs = mDataProvider->crs();
previousCrs = mLayerCrs;
}
else if ( mExtentState == CurrentExtent )
{
Expand Down Expand Up @@ -456,7 +580,7 @@ void QgsRasterLayerSaveAsDialog::updateCrsGroup()
QgsDebugMsg( "Entered" );

mCrsComboBox->setItemText( mCrsComboBox->findData( OriginalCrs ),
tr( "Layer" ) + " (" + mDataProvider->crs().description() + ", " + mDataProvider->crs().authid() + ")" );
tr( "Layer" ) + " (" + mLayerCrs.description() + ", " + mLayerCrs.authid() + ")" );

mCrsComboBox->setItemText( mCrsComboBox->findData( CurrentCrs ),
tr( "Project" ) + " (" + mCurrentCrs.description() + ", " + mCurrentCrs.authid() + ")" );
Expand All @@ -470,7 +594,7 @@ QgsCoordinateReferenceSystem QgsRasterLayerSaveAsDialog::outputCrs()
int state = mCrsComboBox->itemData( mCrsComboBox->currentIndex() ).toInt();
if ( state == OriginalCrs )
{
return mDataProvider->crs();
return mLayerCrs;
}
else if ( state == CurrentCrs )
{
Expand All @@ -484,3 +608,152 @@ QgsRasterLayerSaveAsDialog::Mode QgsRasterLayerSaveAsDialog::mode() const
if ( mRenderedModeRadioButton->isChecked() ) return RenderedImageMode;
return RawDataMode;
}

void QgsRasterLayerSaveAsDialog::on_mRawModeRadioButton_toggled( bool checked )
{
mNoDataGroupBox->setEnabled( checked && mDataProvider->bandCount() == 1 );
}

void QgsRasterLayerSaveAsDialog::on_mAddNoDataManuallyToolButton_clicked()
{
addNoDataRow( std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN() );
}

void QgsRasterLayerSaveAsDialog::on_mLoadTransparentNoDataToolButton_clicked()
{
if ( !mRasterLayer->renderer() ) return;
const QgsRasterTransparency* rasterTransparency = mRasterLayer->renderer()->rasterTransparency();
if ( !rasterTransparency ) return;

foreach ( QgsRasterTransparency::TransparentSingleValuePixel transparencyPixel, rasterTransparency->transparentSingleValuePixelList() )
{
if ( transparencyPixel.percentTransparent == 100 )
{
addNoDataRow( transparencyPixel.min, transparencyPixel.max );
if ( transparencyPixel.min != transparencyPixel.max )
{
setNoDataToEdited( mNoDataTableWidget->rowCount() - 1 );
}
}
}
}

void QgsRasterLayerSaveAsDialog::on_mRemoveSelectedNoDataToolButton_clicked()
{
mNoDataTableWidget->removeRow( mNoDataTableWidget->currentRow() );
}

void QgsRasterLayerSaveAsDialog::on_mRemoveAllNoDataToolButton_clicked()
{
while ( mNoDataTableWidget->rowCount() > 0 )
{
mNoDataTableWidget->removeRow( 0 );
}
}

void QgsRasterLayerSaveAsDialog::addNoDataRow( double min, double max )
{
mNoDataTableWidget->insertRow( mNoDataTableWidget->rowCount() );
for ( int i = 0; i < 2; i++ )
{
double value = i == 0 ? min : max;
QLineEdit *lineEdit = new QLineEdit();
lineEdit->setFrame( false );
lineEdit->setContentsMargins( 1, 1, 1, 1 );
QString valueString;
switch ( mRasterLayer->dataProvider()->srcDataType( 1 ) )
{
case QgsRasterInterface::Float32:
case QgsRasterInterface::Float64:
lineEdit->setValidator( new QDoubleValidator( 0 ) );
if ( !qIsNaN( value ) )
{
valueString = QString::number( value, 'f' );
}
break;
default:
lineEdit->setValidator( new QIntValidator( 0 ) );
if ( !qIsNaN( value ) )
{
valueString = QString::number( static_cast<int>( value ) );
}
break;
}
lineEdit->setText( valueString );
mNoDataTableWidget->setCellWidget( mNoDataTableWidget->rowCount() - 1, i, lineEdit );

connect( lineEdit, SIGNAL( textEdited( const QString & ) ), this, SLOT( noDataCellTextEdited( const QString & ) ) );
}
mNoDataTableWidget->resizeColumnsToContents();
mNoDataTableWidget->resizeRowsToContents();
}

void QgsRasterLayerSaveAsDialog::noDataCellTextEdited( const QString & text )
{
QLineEdit *lineEdit = dynamic_cast<QLineEdit *>( sender() );
if ( !lineEdit ) return;
int row = -1;
int column = -1;
for ( int r = 0 ; r < mNoDataTableWidget->rowCount(); r++ )
{
for ( int c = 0 ; c < mNoDataTableWidget->columnCount(); c++ )
{
if ( mNoDataTableWidget->cellWidget( r, c ) == sender() )
{
row = r;
column = c;
break;
}
}
if ( row != -1 ) break;
}
QgsDebugMsg( QString( "row = %1 column =%2" ).arg( row ).arg( column ) );

if ( column == 0 )
{
QLineEdit *toLineEdit = dynamic_cast<QLineEdit *>( mNoDataTableWidget->cellWidget( row, 1 ) );
if ( !toLineEdit ) return;
bool toChanged = mNoDataToEdited.value( row );
QgsDebugMsg( QString( "toChanged = %1" ).arg( toChanged ) );
if ( !toChanged )
{
toLineEdit->setText( lineEdit->text() );
}
}
else if ( column == 1 )
{
setNoDataToEdited( row );
}
}

void QgsRasterLayerSaveAsDialog::setNoDataToEdited( int row )
{
if ( row >= mNoDataToEdited.size() )
{
mNoDataToEdited.resize( row + 1 );
}
mNoDataToEdited[row] = true;
}

double QgsRasterLayerSaveAsDialog::noDataCellValue( int row, int column ) const
{
QLineEdit *lineEdit = dynamic_cast<QLineEdit *>( mNoDataTableWidget->cellWidget( row, column ) );
if ( !lineEdit || lineEdit->text().isEmpty() )
{
std::numeric_limits<double>::quiet_NaN();
}
return lineEdit->text().toDouble();
}

QList<QgsRasterNuller::NoData> QgsRasterLayerSaveAsDialog::noData() const
{
QList<QgsRasterNuller::NoData> noDataList;
for ( int r = 0 ; r < mNoDataTableWidget->rowCount(); r++ )
{
QgsRasterNuller::NoData noData;
noData.min = noDataCellValue( r, 0 );
noData.max = noDataCellValue( r, 1 );
noDataList.append( noData );
}
return noDataList;
}
60 changes: 59 additions & 1 deletion src/gui/qgsrasterlayersaveasdialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
#include "ui_qgsrasterlayersaveasdialogbase.h"
#include "qgsrectangle.h"
#include "qgscoordinatereferencesystem.h"
#include "qgsrasternuller.h"

class QgsRasterLayer;
class QgsRasterDataProvider;
class QgsRasterFormatOptionsWidget;

Expand Down Expand Up @@ -35,7 +37,7 @@ class GUI_EXPORT QgsRasterLayerSaveAsDialog: public QDialog, private Ui::QgsRast
UserResolution
};

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

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

void hideFormat();
void hideOutput();

private slots:
void on_mRawModeRadioButton_toggled( bool );
void on_mBrowseButton_clicked();
void on_mSaveAsLineEdit_textChanged( const QString& text );
void on_mCurrentExtentButton_clicked();
Expand All @@ -79,14 +83,24 @@ class GUI_EXPORT QgsRasterLayerSaveAsDialog: public QDialog, private Ui::QgsRast

void on_mCrsComboBox_currentIndexChanged( int ) { crsChanged(); }

void groupBoxExpanded( QWidget * widget ) { mScrollArea->ensureWidgetVisible( widget ); }
void on_mAddNoDataManuallyToolButton_clicked();
void on_mLoadTransparentNoDataToolButton_clicked();
void on_mRemoveSelectedNoDataToolButton_clicked();
void on_mRemoveAllNoDataToolButton_clicked();
void noDataCellTextEdited( const QString & text );

private:
QgsRasterLayer* mRasterLayer;
QgsRasterDataProvider* mDataProvider;
QgsRectangle mCurrentExtent;
QgsCoordinateReferenceSystem mLayerCrs; // may differ from provider CRS
QgsCoordinateReferenceSystem mCurrentCrs;
QgsCoordinateReferenceSystem mUserCrs;
QgsCoordinateReferenceSystem mPreviousCrs;
ExtentState mExtentState;
ResolutionState mResolutionState;
QVector<bool> mNoDataToEdited;

void setValidators();
void setOutputExtent( const QgsRectangle& r, const QgsCoordinateReferenceSystem& srcCrs, ExtentState state );
Expand All @@ -102,6 +116,50 @@ class GUI_EXPORT QgsRasterLayerSaveAsDialog: public QDialog, private Ui::QgsRast
void recalcResolutionSize();
void crsChanged();
void updateCrsGroup();

void addNoDataRow( double min, double max );
void setNoDataToEdited( int row );
double noDataCellValue( int row, int column ) const;
};


#endif // QGSRASTERLAYERSAVEASDIALOG_H


// this widget class will go into its separate file
#ifndef GROUPBOX_H
#define GROUPBOX_H

#include <QGroupBox>

class GroupBox : public QGroupBox
{
Q_OBJECT

public:
GroupBox( QWidget *parent = 0 );
GroupBox( const QString &title, QWidget *parent = 0 );

bool isCollapsed();

signals:
void collapsed( QWidget* );
void expanded( QWidget* );

public slots:
void setToggled( bool toggled ) { setCollapsed( ! toggled ); }
void setCollapsed( bool collapsed );

protected:
/* void mousePressEvent( QMouseEvent *e ); */
/* void mouseReleaseEvent( QMouseEvent *e ); */
/* void paintEvent( QPaintEvent * ); */
void showEvent( QShowEvent * event );

private:
QPoint clickPos;
bool m_collapsed;
QMargins margins;
};

#endif
10 changes: 5 additions & 5 deletions src/gui/symbology-ng/qgsstylev2managerdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -351,9 +351,8 @@ bool QgsStyleV2ManagerDialog::addSymbol()
}

// add new symbol to style and re-populate the list
mStyle->addSymbol( name, symbol );
mStyle->addSymbol( name, symbol, true );
// TODO groups and tags
mStyle->saveSymbol( name, symbol, 0, QStringList() );
mModified = true;
return true;
}
Expand Down Expand Up @@ -436,7 +435,8 @@ QString QgsStyleV2ManagerDialog::addColorRampStatic( QWidget* parent, QgsStyleV2
}

// add new symbol to style and re-populate the list
style->addColorRamp( name, ramp );
style->addColorRamp( name, ramp, true );
// TODO groups and tags
return name;
}

Expand Down Expand Up @@ -491,7 +491,7 @@ bool QgsStyleV2ManagerDialog::editSymbol()
}

// by adding symbol to style with the same name the old effectively gets overwritten
mStyle->addSymbol( symbolName, symbol );
mStyle->addSymbol( symbolName, symbol, true );
mModified = true;
return true;
}
Expand Down Expand Up @@ -549,7 +549,7 @@ bool QgsStyleV2ManagerDialog::editColorRamp()
Q_ASSERT( 0 && "invalid ramp type" );
}

mStyle->addColorRamp( name, ramp );
mStyle->addColorRamp( name, ramp, true );
mModified = true;
return true;
}
Expand Down
Loading