960 changes: 960 additions & 0 deletions python/api/osgeo_gdal-ogr_1.9.1-1.api

Large diffs are not rendered by default.

Binary file added python/api/pyqgis_master.pap
Binary file not shown.
520 changes: 225 additions & 295 deletions python/console.py

Large diffs are not rendered by default.

500 changes: 500 additions & 0 deletions python/console_sci.py

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion python/core/qgsrasterdataprovider.sip
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* sense for Raster layers.
*/

class QgsRasterDataProvider : QgsDataProvider
class QgsRasterDataProvider : QgsDataProvider, QgsRasterInterface
{
%TypeHeaderCode
#include <qgsrasterdataprovider.h>
Expand Down
32 changes: 32 additions & 0 deletions python/core/qgsrasterinterface.sip
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,39 @@ class QgsRasterInterface
{
%TypeHeaderCode
#include <qgsrasterinterface.h>
#include <qgsrasterresamplefilter.h>
//#include <qgsrasternuller.h>
#include <qgsrasterrenderer.h>
#include <qgsrasterprojector.h>
#include <qgsrasterdataprovider.h>

// QgsRasterRenderer subclass headers must be here because ConvertToSubClassCode
// from QgsRasterRenderer is probably included
#include <qgspalettedrasterrenderer.h>
#include <qgsmultibandcolorrenderer.h>
#include <qgssinglebandpseudocolorrenderer.h>
#include <qgssinglebandgrayrenderer.h>
#include <qgssinglebandcolordatarenderer.h>
%End

%ConvertToSubClassCode
if (dynamic_cast<QgsRasterResampleFilter*>(sipCpp) != NULL)
sipClass = sipClass_QgsRasterResampleFilter;
// if (dynamic_cast<QgsRasterNuller*>(sipCpp) != NULL)
// sipClass = sipClass_QgsRasterNuller;
if (dynamic_cast<QgsRasterRenderer*>(sipCpp) != NULL)
sipClass = sipClass_QgsRasterRenderer;
if (dynamic_cast<QgsRasterProjector*>(sipCpp) != NULL)
sipClass = sipClass_QgsRasterProjector;
if (dynamic_cast<QgsRasterDataProvider*>(sipCpp) != NULL)
{
sipClass = sipClass_QgsRasterDataProvider;
*sipCppRet = static_cast<QgsRasterDataProvider*>(sipCpp);
}
else
sipClass = 0;
%End

public:

enum DataType
Expand Down
14 changes: 8 additions & 6 deletions python/core/qgsrasterlayer.sip
Original file line number Diff line number Diff line change
Expand Up @@ -217,16 +217,18 @@ public:
//void setUserDefinedRGBMinimumMaximum( bool theBool ); //removed with raster redesign

/**Set raster renderer. Takes ownership of the renderer object*/
void setRenderer( QgsRasterRenderer* renderer );
void setRenderer( QgsRasterRenderer* renderer /Transfer/ );
QgsRasterRenderer* renderer();

QgsRasterPipe * pipe();

/** \brief Accessor to find out how many standard deviations are being plotted */
double standardDeviations() const;

/** \brief Accessor for transparent band name mapping */
//QString transparentBandName() const; //removed with raster redesign

/** \brief [ data provider interface ] Does this layer use a provider for setting/retrieving data?
/** \brief [ data provider interface ] Does this layer use a provider for setting/retrieving data?
* @deprecated in 2.0
*/
bool usesProvider() /Deprecated/;
Expand Down Expand Up @@ -271,14 +273,14 @@ public:
/** \brief Wrapper for GDALComputeRasterMinMax with the estimate option
\note added in v1.6 */
void computeMinimumMaximumEstimates( int theBand, double& theMin /Out/, double& theMax /Out/ );

/** \brief Compute the actual minimum maximum pixel values based on the current (last) display extent */
// (would need MethodCode directive) void computeMinimumMaximumFromLastExtent( int theBand, double* theMinMax );

/** \brief Compute the actual minimum maximum pixel values based on the current (last) display extent */
// (would need MethodCode directive) void computeMinimumMaximumFromLastExtent( QString theBand, double* theMinMax );

/** \brief Compute the actual minimum maximum pixel values based on the current (last) display extent
/** \brief Compute the actual minimum maximum pixel values based on the current (last) display extent
\note added in v1.6 */
void computeMinimumMaximumFromLastExtent( int theBand, double& theMin /Out/, double& theMax /Out/ );

Expand Down Expand Up @@ -366,12 +368,12 @@ public:
/** \brief Get an 100x100 pixmap of the color palette. If the layer has no palette a white pixmap will be returned */
QPixmap paletteAsPixmap( int theBand = 1 );

/** \brief [ data provider interface ] Which provider is being used for this Raster Layer?
/** \brief [ data provider interface ] Which provider is being used for this Raster Layer?
* @note added in 2.0
*/
QString providerType() const;

/** \brief [ data provider interface ] Which provider is being used for this Raster Layer?
/** \brief [ data provider interface ] Which provider is being used for this Raster Layer?
* @deprecated in 2.0
*/
QString providerKey() const /Deprecated/;
Expand Down
6 changes: 3 additions & 3 deletions python/core/qgsrasterpipe.sip
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ class QgsRasterPipe

~QgsRasterPipe();

bool insert( int idx, QgsRasterInterface* theInterface );
bool insert( int idx, QgsRasterInterface* theInterface /Transfer/ );

bool replace( int idx, QgsRasterInterface* theInterface );
bool replace( int idx, QgsRasterInterface* theInterface /Transfer/ );

bool set( QgsRasterInterface * theInterface );
bool set( QgsRasterInterface * theInterface /Transfer/ );

bool remove( int idx );

Expand Down
2 changes: 1 addition & 1 deletion python/core/qgsrasterprojector.sip
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

/** Raster projector */

class QgsRasterProjector
class QgsRasterProjector : QgsRasterInterface
{
%TypeHeaderCode
#include <qgsrasterprojector.h>
Expand Down
11 changes: 7 additions & 4 deletions python/core/qgsrasterrenderer.sip
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
class QgsRasterRenderer
class QgsRasterRenderer : QgsRasterInterface
{
%TypeHeaderCode
#include "qgsrasterrenderer.h"
Expand All @@ -7,6 +7,7 @@ class QgsRasterRenderer
#include "qgssinglebandpseudocolorrenderer.h"
#include "qgssinglebandgrayrenderer.h"
#include "qgssinglebandcolordatarenderer.h"
#include "qgsrasterinterface.h"
%End

%ConvertToSubClassCode
Expand All @@ -18,8 +19,8 @@ class QgsRasterRenderer
sipClass = sipClass_QgsSingleBandPseudoColorRenderer;
else if (dynamic_cast<QgsSingleBandGrayRenderer*>(sipCpp) != NULL)
sipClass = sipClass_QgsSingleBandGrayRenderer;
else if (dynamic_cast<QgsSingleBandGrayRenderer*>(sipCpp) != NULL)
sipClass = sipClass_QgsSingleBandGrayRenderer;
else if (dynamic_cast<QgsSingleBandGrayRenderer*>(sipCpp) != NULL)
sipClass = sipClass_QgsSingleBandGrayRenderer;
else
sipClass = 0;
%End
Expand All @@ -32,6 +33,8 @@ class QgsRasterRenderer
virtual QString type() const;
virtual void * readBlock( int bandNo, const QgsRectangle & extent, int width, int height );

QgsRasterInterface::DataType dataType( int bandNo ) const;

bool usesTransparency() const;

void setOpacity( double opacity );
Expand Down Expand Up @@ -124,7 +127,7 @@ class QgsSingleBandPseudoColorRenderer: QgsRasterRenderer
%End
public:
/**Note: takes ownership of QgsRasterShader*/
QgsSingleBandPseudoColorRenderer( QgsRasterDataProvider* provider, int band, QgsRasterShader* shader );
QgsSingleBandPseudoColorRenderer( QgsRasterDataProvider* provider, int band, QgsRasterShader* shader /Transfer/ );
~QgsSingleBandPseudoColorRenderer();
QgsRasterInterface * clone();

Expand Down
2 changes: 1 addition & 1 deletion python/core/qgsrasterresamplefilter.sip
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

/** Raster resample filter */

class QgsRasterResampleFilter
class QgsRasterResampleFilter : QgsRasterInterface
{
%TypeHeaderCode
#include <qgsrasterresamplefilter.h>
Expand Down
3 changes: 3 additions & 0 deletions python/core/qgsrectangle.sip
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ class QgsRectangle
bool isEmpty() const;
//! returns string representation in Wkt form
QString asWktCoordinates() const;
//! returns string representation as WKT Polygon
//@note added om 2.0
QString asWktPolygon() const;
//! returns string representation of form xmin,ymin xmax,ymax
QString toString(bool automaticPrecision = false) const;
//! overloaded toString that allows precision of numbers to be set
Expand Down
37 changes: 37 additions & 0 deletions python/help.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from PyQt4 import QtCore, QtGui, QtWebKit
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import os

class HelpDialog(QtGui.QDialog):

def __init__(self):
QtGui.QDialog.__init__(self)
self.setModal(True)
self.setupUi()

def setupUi(self):
self.resize(400, 300)
self.webView = QtWebKit.QWebView()
self.setWindowTitle("Help Python Console")
self.verticalLayout= QtGui.QVBoxLayout()
self.verticalLayout.setSpacing(2)
self.verticalLayout.setMargin(0)
self.verticalLayout.addWidget(self.webView)
self.closeButton = QtGui.QPushButton()
self.closeButton.setText("Close")
self.closeButton.setMaximumWidth(150)
self.horizontalLayout= QtGui.QHBoxLayout()
self.horizontalLayout.setSpacing(2)
self.horizontalLayout.setMargin(0)
self.horizontalLayout.addStretch(1000)
self.horizontalLayout.addWidget(self.closeButton)
QObject.connect(self.closeButton, QtCore.SIGNAL("clicked()"), self.closeWindow)
self.verticalLayout.addLayout(self.horizontalLayout)
self.setLayout(self.verticalLayout)
filename = os.path.dirname(__file__) + "/helpConsole/help.htm"
url = QtCore.QUrl(filename)
self.webView.load(url)

def closeWindow(self):
self.close()
2 changes: 2 additions & 0 deletions python/helpConsole/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
FILE(GLOB HTML_FILES *.htm)
INSTALL(FILES ${HTML_FILES} DESTINATION ${QGIS_PYTHON_DIR}/helpConsole)
67 changes: 67 additions & 0 deletions python/helpConsole/help.htm
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Help Python Console</title>
<style>
body{
font-family: verdana,arial,helvetica,sans-serif;
/*font-family:Verdana,Geneva,sans-serif;*/
font-size : 12px;
}
</style>
</head>
<body>
<table>
<tr>
<td>
<img src="../iconConsole/imgHelpDialog.png" />
</td>
<td>
<h2>Python Console for QGIS</h2>
</td>
</tr>
</table>
<p align="justify">
Now you can use auto-completion for syntax in console!!!
<br>
(Thanks to Larry Shaffer who provided the API files)
<br><br>
To access Quantum GIS environment from this console
use qgis.utils.iface object (instance of QgisInterface class).
To import the class QgisInterface can also use the dedicated
button on the toolbar on the left.
<br><br>
The following is a description of the tools in the toolbar:
</p>
<table width="100%" bordercolor="#000" border="1">
<tr>
<td><img src="../iconConsole/iconClearConsole.png" /></td>
<td>Tool to clear python console</td>
</tr>
<tr>
<td><img src="../iconConsole/iconTempConsole.png" /></td>
<td>Tool to import iface class</td>
</tr>
<tr>
<td><img src="../iconConsole/iconSextanteConsole.png" /></td>
<td>Tool to import Sextante class</td>
</tr>
<tr>
<td><img src="../iconConsole/iconOpenConsole.png" /></td>
<td>Tool to open a python script and load in console</td>
</tr>
<tr>
<td><img src="../iconConsole/iconSaveConsole.png" /></td>
<td>Tool to save a python script</td>
</tr>
<tr>
<td><img src="../iconConsole/iconHelpConsole.png" /></td>
<td>This! ;-)</td>
</tr>
<tr>
<td><img src="../iconConsole/iconRunConsole.png" /></td>
<td>Run command (like Enter key pressed)</td>
</tr>
</table>
</body>
</html>
13 changes: 13 additions & 0 deletions python/iconConsole/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
SET(ICON_FILES
iconClearConsole.png
iconOpenConsole.png
iconRunConsole.png
iconTempConsole.png
iconSextanteConsole.png
iconSaveConsole.png
iconHelpConsole.png
imgHelpDialog.png
)

FILE(GLOB ICON_FILES *.png)
INSTALL(FILES ${ICON_FILES} DESTINATION ${QGIS_PYTHON_DIR}/iconConsole)
Binary file added python/iconConsole/iconClearConsole.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added python/iconConsole/iconHelpConsole.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added python/iconConsole/iconOpenConsole.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added python/iconConsole/iconRunConsole.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added python/iconConsole/iconSaveConsole.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added python/iconConsole/iconSextanteConsole.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added python/iconConsole/iconTempConsole.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added python/iconConsole/imgHelpDialog.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
55 changes: 47 additions & 8 deletions src/app/legend/qgsapplegendinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,13 @@ void QgsAppLegendInterface::updateIndex( QModelIndex oldIndex, QModelIndex newIn

void QgsAppLegendInterface::setGroupExpanded( int groupIndex, bool expand )
{
mLegend->setExpanded( mLegend->model()->index( groupIndex, 0 ), expand );
QTreeWidgetItem * item = getItem (groupIndex);
if ( !item )
{
return;
}

item->setExpanded(expand);
}

void QgsAppLegendInterface::setGroupVisible( int groupIndex, bool visible )
Expand All @@ -76,8 +82,29 @@ void QgsAppLegendInterface::setGroupVisible( int groupIndex, bool visible )
return;
}

Qt::CheckState state = visible ? Qt::Checked : Qt::Unchecked;
mLegend->topLevelItem( groupIndex )->setCheckState( 0, state );
Qt::CheckState state = visible ? Qt::Checked : Qt::Unchecked;
getItem (groupIndex)->setCheckState( 0, state );
}

QTreeWidgetItem *QgsAppLegendInterface::getItem(int itemIndex)
{
int itemCount = 0;
for (QTreeWidgetItem* theItem = mLegend->firstItem(); theItem; theItem = mLegend->nextItem( theItem ) )
{
QgsLegendItem* legendItem = dynamic_cast<QgsLegendItem *>( theItem );
if (legendItem->type() == QgsLegendItem::LEGEND_GROUP) {
if (itemCount == itemIndex)
{
return theItem;
}
else
{
itemCount = itemCount + 1;
}
}
}

return NULL;
}

void QgsAppLegendInterface::setLayerVisible( QgsMapLayer * ml, bool visible )
Expand All @@ -101,14 +128,26 @@ QList< GroupLayerInfo > QgsAppLegendInterface::groupLayerRelationship()

bool QgsAppLegendInterface::groupExists( int groupIndex )
{
QModelIndex mi = mLegend->model()->index( groupIndex, 0 );
return ( mi.isValid() &&
mLegend->isLegendGroup( mi ) );
QTreeWidgetItem * item = getItem (groupIndex);
QgsLegendItem* legendItem = dynamic_cast<QgsLegendItem *>( item );

if ( !legendItem )
{
return false;
}

return legendItem->type() == QgsLegendItem::LEGEND_GROUP;
}

bool QgsAppLegendInterface::isGroupExpanded( int groupIndex )
{
return mLegend->isExpanded( mLegend->model()->index( groupIndex, 0 ) );
QTreeWidgetItem * item = getItem (groupIndex);
if ( !item )
{
return false;
}

return item->isExpanded();
}

bool QgsAppLegendInterface::isGroupVisible( int groupIndex )
Expand All @@ -118,7 +157,7 @@ bool QgsAppLegendInterface::isGroupVisible( int groupIndex )
return false;
}

return ( Qt::Checked == mLegend->topLevelItem( groupIndex )->checkState( 0 ) );
return ( Qt::Checked == getItem( groupIndex )->checkState( 0 ) );
}

bool QgsAppLegendInterface::isLayerVisible( QgsMapLayer * ml )
Expand Down
1 change: 1 addition & 0 deletions src/app/legend/qgsapplegendinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ class QgsAppLegendInterface : public QgsLegendInterface

//! Pointer to QgsLegend object
QgsLegend *mLegend;
QTreeWidgetItem *getItem(int itemIndex);
};

#endif //QGSLEGENDAPPIFACE_H
68 changes: 63 additions & 5 deletions src/app/legend/qgslegend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -231,8 +231,27 @@ int QgsLegend::addGroup( QString name, bool expand, QTreeWidgetItem* parent )

int QgsLegend::addGroup( QString name, bool expand, int groupIndex )
{
QgsLegendGroup * lg = dynamic_cast<QgsLegendGroup *>( topLevelItem( groupIndex ) );
return addGroup( name, expand, lg );
QTreeWidgetItem * parentItem = invisibleRootItem();

int itemCount = 0;
for ( QTreeWidgetItem* theItem = firstItem(); theItem; theItem = nextItem( theItem ) )
{
QgsLegendItem* legendItem = dynamic_cast<QgsLegendItem *>( theItem );
if (legendItem->type() == QgsLegendItem::LEGEND_GROUP) {
if (itemCount == groupIndex)
{
// this is the matching group
parentItem = legendItem;
break;
}
else
{
itemCount = itemCount + 1;
}
}
}

return addGroup( name, expand, parentItem );
}

void QgsLegend::removeAll()
Expand Down Expand Up @@ -276,7 +295,26 @@ void QgsLegend::setLayersVisible( bool visible )

void QgsLegend::removeGroup( int groupIndex )
{
QgsLegendGroup * lg = dynamic_cast<QgsLegendGroup *>( topLevelItem( groupIndex ) );
QgsLegendGroup * lg = NULL;
int itemCount = 0;

for ( QTreeWidgetItem* theItem = firstItem(); theItem; theItem = nextItem( theItem ) )
{
QgsLegendItem* legendItem = dynamic_cast<QgsLegendItem *>( theItem );
if (legendItem->type() == QgsLegendItem::LEGEND_GROUP) {
if (itemCount == groupIndex)
{
// this is the matching group
lg = dynamic_cast<QgsLegendGroup*>( legendItem );
break;
}
else
{
itemCount = itemCount + 1;
}
}
}

if ( lg )
{
removeGroup( lg );
Expand Down Expand Up @@ -1252,8 +1290,28 @@ void QgsLegend::moveLayer( QgsMapLayer *ml, int groupIndex )
if ( !layer )
return;

QgsLegendGroup *group = dynamic_cast<QgsLegendGroup*>( topLevelItem( groupIndex ) );
if ( !group )
int itemCount = 0;
QgsLegendGroup *group = NULL;

for ( QTreeWidgetItem* theItem = firstItem(); theItem; theItem = nextItem( theItem ) )
{

QgsLegendItem* legendItem = dynamic_cast<QgsLegendItem *>( theItem );
if (legendItem->type() == QgsLegendItem::LEGEND_GROUP) {
if (itemCount == groupIndex)
{
// this is the matching group
group = dynamic_cast<QgsLegendGroup*>( legendItem );
break;
}
else
{
itemCount = itemCount + 1;
}
}
}

if ( group == NULL)
return;

insertItem( layer, group );
Expand Down
3 changes: 3 additions & 0 deletions src/app/qgisapp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4023,6 +4023,9 @@ void QgisApp::saveAsRasterFile()
}

QProgressDialog pd( 0, tr( "Abort..." ), 0, 0 );
// Show the dialo immediately because cloning pipe can take some time (WCS)
pd.setLabelText( QObject::tr( "Reading raster" ) );
pd.show();
pd.setWindowModality( Qt::WindowModal );

// TODO: show error dialogs
Expand Down
11 changes: 11 additions & 0 deletions src/app/qgslabelinggui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,17 @@ QgsLabelingGui::QgsLabelingGui( QgsPalLabeling* lbl, QgsVectorLayer* layer, QgsM
{
connect( quadrantRadios[i], SIGNAL( toggled( bool ) ), this, SLOT( updateQuadrant() ) );
}

// Label tab collapsed groupboxes
chkBuffer->setCollapsed( true );
mFontMultiLineGroupBox->setCollapsed( true );
chkFormattedNumbers->setCollapsed( true );
chkScaleBasedVisibility->setCollapsed( true );

// Data defined tab collapsed groupboxes
mBufferAttributesPropertiesGroupBox->setCollapsed( true );
mFontAttributePropertiesGroupBox->setCollapsed( true );

}

QgsLabelingGui::~QgsLabelingGui()
Expand Down
33 changes: 16 additions & 17 deletions src/app/qgsrasterlayerproperties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,34 +18,33 @@
#include <limits>
#include <typeinfo>

#include "qgsmaptopixel.h"
#include "qgsmapcanvas.h"
#include "qgsmaprenderer.h"
#include "qgslogger.h"
#include "qgsapplication.h"
#include "qgisapp.h"
#include "qgsapplication.h"
#include "qgsbilinearrasterresampler.h"
#include "qgscubicrasterresampler.h"
#include "qgscontexthelp.h"
#include "qgscontrastenhancement.h"
#include "qgscoordinatetransform.h"
#include "qgsrasterlayerproperties.h"
#include "qgsrasterrenderer.h"
#include "qgscubicrasterresampler.h"
#include "qgsgenericprojectionselector.h"
#include "qgslogger.h"
#include "qgsmapcanvas.h"
#include "qgsmaplayerregistry.h"
#include "qgsmaprenderer.h"
#include "qgsmaptoolemitpoint.h"
#include "qgsmaptopixel.h"
#include "qgsmultibandcolorrendererwidget.h"
#include "qgspalettedrendererwidget.h"
#include "qgsproject.h"
#include "qgsrasterbandstats.h"
#include "qgsrasterhistogramwidget.h"
#include "qgsrasterlayer.h"
#include "qgsrasterlayerproperties.h"
#include "qgsrasterpyramid.h"
#include "qgscontexthelp.h"
#include "qgsmaplayerregistry.h"
#include "qgscontrastenhancement.h"
#include "qgsrastertransparency.h"
#include "qgsmaptoolemitpoint.h"

#include "qgsrasterrenderer.h"
#include "qgsrasterrendererregistry.h"
#include "qgsmultibandcolorrendererwidget.h"
#include "qgspalettedrendererwidget.h"
#include "qgsrastertransparency.h"
#include "qgssinglebandgrayrendererwidget.h"
#include "qgssinglebandpseudocolorrendererwidget.h"
#include "qgsrasterhistogramwidget.h"

#include <QTableWidgetItem>
#include <QHeaderView>
Expand Down
2 changes: 1 addition & 1 deletion src/app/qgsvectorlayerproperties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@
#include "qgsstylev2.h"
#include "qgssymbologyv2conversion.h"


QgsVectorLayerProperties::QgsVectorLayerProperties(
QgsVectorLayer *lyr,
QWidget * parent,
Expand Down Expand Up @@ -447,6 +446,7 @@ void QgsVectorLayerProperties::updateButtons()
mAddAttributeButton->setEnabled( false );
mDeleteAttributeButton->setEnabled( false );
mToggleEditingButton->setChecked( false );
mToggleEditingButton->setEnabled( false );
mCalculateFieldButton->setEnabled( false );
}
}
Expand Down
11 changes: 8 additions & 3 deletions src/core/qgsrasterdataprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ void QgsRasterDataProvider::readBlock( int bandNo, QgsRectangle
return;

// Allocate memory for not projected source data
int mySize = dataTypeSize( bandNo ) / 8;
size_t mySize = dataTypeSize( bandNo ) / 8;
void *mySrcData = malloc( mySize * myProjector.srcRows() * myProjector.srcCols() );

time.restart();
Expand Down Expand Up @@ -101,6 +101,11 @@ void * QgsRasterDataProvider::readBlock( int bandNo, QgsRectangle const & exten

// TODO: replace VSIMalloc, it is GDAL function
void * data = VSIMalloc( dataTypeSize( bandNo ) * width * height );
if ( ! data )
{
QgsDebugMsg( QString( "Couldn't allocate data memory of % bytes" ).arg( dataTypeSize( bandNo ) * width * height ) );
return 0;
}
readBlock( bandNo, extent, width, height, data );

return data;
Expand Down Expand Up @@ -260,9 +265,9 @@ QString QgsRasterDataProvider::lastErrorFormat()
QByteArray QgsRasterDataProvider::noValueBytes( int theBandNo )
{
int type = dataType( theBandNo );
int size = dataTypeSize( theBandNo ) / 8;
size_t size = dataTypeSize( theBandNo ) / 8;
QByteArray ba;
ba.resize( size );
ba.resize(( int )size );
char * data = ba.data();
double noval = mNoDataValue[theBandNo-1];
unsigned char uc;
Expand Down
1 change: 1 addition & 0 deletions src/core/qgsrasterdataprovider.h
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,7 @@ class CORE_EXPORT QgsRasterDataProvider : public QgsDataProvider, public QgsRast
virtual QDateTime dataTimestamp() const { return QDateTime(); }

/**Writes into the provider datasource*/
// TODO: add data type (may be defferent from band type)
virtual bool write( void* data, int band, int width, int height, int xOffset, int yOffset )
{
Q_UNUSED( data );
Expand Down
52 changes: 41 additions & 11 deletions src/core/qgsrasterprojector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ QgsRasterProjector::QgsRasterProjector()
}

QgsRasterProjector::QgsRasterProjector( const QgsRasterProjector &projector )
: QgsRasterInterface( 0 )
{
mSrcCRS = projector.mSrcCRS;
mDestCRS = projector.mDestCRS;
Expand Down Expand Up @@ -594,10 +595,21 @@ bool QgsRasterProjector::checkCols()
QgsPoint mySrcPoint3 = mCPMatrix[r+1][c];

QgsPoint mySrcApprox(( mySrcPoint1.x() + mySrcPoint3.x() ) / 2, ( mySrcPoint1.y() + mySrcPoint3.y() ) / 2 );
QgsPoint myDestApprox = mCoordinateTransform.transform( mySrcApprox, QgsCoordinateTransform::ReverseTransform );
double mySqrDist = myDestApprox.sqrDist( myDestPoint );
if ( mySqrDist > mSqrTolerance )
try
{
QgsPoint myDestApprox = mCoordinateTransform.transform( mySrcApprox, QgsCoordinateTransform::ReverseTransform );
double mySqrDist = myDestApprox.sqrDist( myDestPoint );
if ( mySqrDist > mSqrTolerance )
{
return false;
}
}
catch ( QgsCsException &e )
{
Q_UNUSED( e );
// Caught an error in transform
return false;
}
}
}
return true;
Expand All @@ -618,10 +630,21 @@ bool QgsRasterProjector::checkRows()
QgsPoint mySrcPoint3 = mCPMatrix[r][c+1];

QgsPoint mySrcApprox(( mySrcPoint1.x() + mySrcPoint3.x() ) / 2, ( mySrcPoint1.y() + mySrcPoint3.y() ) / 2 );
QgsPoint myDestApprox = mCoordinateTransform.transform( mySrcApprox, QgsCoordinateTransform::ReverseTransform );
double mySqrDist = myDestApprox.sqrDist( myDestPoint );
if ( mySqrDist > mSqrTolerance )
try
{
QgsPoint myDestApprox = mCoordinateTransform.transform( mySrcApprox, QgsCoordinateTransform::ReverseTransform );
double mySqrDist = myDestApprox.sqrDist( myDestPoint );
if ( mySqrDist > mSqrTolerance )
{
return false;
}
}
catch ( QgsCsException &e )
{
Q_UNUSED( e );
// Caught an error in transform
return false;
}
}
}
return true;
Expand Down Expand Up @@ -657,13 +680,20 @@ void * QgsRasterProjector::readBlock( int bandNo, QgsRectangle const & extent,

if ( !inputData ) return 0;

int pixelSize = mInput->typeSize( mInput->dataType( bandNo ) ) / 8;
size_t pixelSize = mInput->typeSize( mInput->dataType( bandNo ) ) / 8;

int inputSize = pixelSize * srcCols() * srcRows();
size_t inputSize = pixelSize * srcCols() * srcRows();

int outputSize = width * height * pixelSize;
size_t outputSize = width * height * pixelSize;
void * outputData = malloc( outputSize );

// Check for allcoation error
if ( ! outputData )
{
QgsDebugMsg( QString( "Couldn't malloc %1 bytes!" ).arg( outputSize ) );
free( inputData );
return 0;
}
// TODO: fill by transparent

int srcRow, srcCol;
Expand All @@ -672,8 +702,8 @@ void * QgsRasterProjector::readBlock( int bandNo, QgsRectangle const & extent,
for ( int j = 0; j < width; ++j )
{
srcRowCol( i, j, &srcRow, &srcCol );
int srcIndex = pixelSize * ( srcRow * mSrcCols + srcCol );
int destIndex = pixelSize * ( i * width + j );
size_t srcIndex = pixelSize * ( srcRow * mSrcCols + srcCol );
size_t destIndex = pixelSize * ( i * width + j );

if ( srcIndex >= inputSize || destIndex >= outputSize ) continue; // should not happen

Expand Down
19 changes: 19 additions & 0 deletions src/core/qgsrectangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,25 @@ QString QgsRectangle::asWktCoordinates() const
return rep;
}

QString QgsRectangle::asWktPolygon() const
{
QString rep =
QString("POLYGON((") +
QString::number( xmin, 'f', 16 ) + " " +
QString::number( ymin, 'f', 16 ) + ", " +
QString::number( xmax, 'f', 16 ) + " " +
QString::number( ymin, 'f', 16 ) + ", " +
QString::number( xmax, 'f', 16 ) + " " +
QString::number( ymax, 'f', 16 ) + ", " +
QString::number( xmin, 'f', 16 ) + " " +
QString::number( ymax, 'f', 16 ) + ", " +
QString::number( xmin, 'f', 16 ) + " " +
QString::number( ymin, 'f', 16 ) +
QString("))");

return rep;
}

// Return a string representation of the rectangle with automatic or high precision
QString QgsRectangle::toString( bool automaticPrecision ) const
{
Expand Down
3 changes: 3 additions & 0 deletions src/core/qgsrectangle.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ class CORE_EXPORT QgsRectangle
bool isEmpty() const;
//! returns string representation in Wkt form
QString asWktCoordinates() const;
//! returns string representation as WKT Polygon
//@note added om 2.0
QString asWktPolygon() const;
//! returns string representation of form xmin,ymin xmax,ymax
QString toString( bool automaticPrecision = false ) const;
//! overloaded toString that allows precision of numbers to be set
Expand Down
28 changes: 27 additions & 1 deletion src/core/raster/qgsmultibandcolorrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,17 @@ void * QgsMultiBandColorRenderer::readBlock( int bandNo, QgsRectangle const & e
for ( ; bandIt != bands.constEnd(); ++bandIt )
{
bandData[*bandIt] = mInput->block( *bandIt, extent, width, height );
if ( !bandData[*bandIt] ) return 0;
if ( !bandData[*bandIt] )
{
// We should free the alloced mem from block().
QgsDebugMsg("No input band" );
bandIt--;
for ( ; bandIt != bands.constBegin(); bandIt-- )
{
VSIFree( bandData[*bandIt] );
}
return 0;
}
}

if ( mRedBand > 0 )
Expand All @@ -216,6 +226,17 @@ void * QgsMultiBandColorRenderer::readBlock( int bandNo, QgsRectangle const & e
}

QImage img( width, height, QImage::Format_ARGB32_Premultiplied );
if ( img.isNull() )
{
QgsDebugMsg( "Could not create QImage" );
bandIt = bands.constBegin();
for ( ; bandIt != bands.constEnd(); ++bandIt )
{
VSIFree( bandData[*bandIt] );
}
return 0;
}

QRgb* imageScanLine = 0;
int currentRasterPos = 0;
int redVal = 0;
Expand Down Expand Up @@ -334,6 +355,11 @@ void * QgsMultiBandColorRenderer::readBlock( int bandNo, QgsRectangle const & e
}

void * data = VSIMalloc( img.byteCount() );
if ( ! data )
{
QgsDebugMsg( QString( "Couldn't allocate output data memory of % bytes" ).arg( img.byteCount() ) );
return 0;
}
return memcpy( data, img.bits(), img.byteCount() );
}

Expand Down
28 changes: 27 additions & 1 deletion src/core/raster/qgspalettedrasterrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,12 @@ void * QgsPalettedRasterRenderer::readBlock( int bandNo, QgsRectangle const & e

QgsRasterInterface::DataType rasterType = ( QgsRasterInterface::DataType )mInput->dataType( mBandNumber );
void* rasterData = mInput->block( bandNo, extent, width, height );
if ( ! rasterData )
{
QgsDebugMsg("No raster data!" );
return 0;
}

double currentOpacity = mOpacity;

//rendering is faster without considering user-defined transparency
Expand All @@ -120,6 +126,13 @@ void * QgsPalettedRasterRenderer::readBlock( int bandNo, QgsRectangle const & e

//create image
QImage img( width, height, QImage::Format_ARGB32_Premultiplied );
if ( img.isNull() )
{
QgsDebugMsg( "Could not create QImage" );
VSIFree( rasterData );
return 0;
}

QRgb* imageScanLine = 0;
int val = 0;
int currentRasterPos = 0;
Expand All @@ -138,7 +151,14 @@ void * QgsPalettedRasterRenderer::readBlock( int bandNo, QgsRectangle const & e
}
if ( !hasTransparency )
{
imageScanLine[j] = mColors[ val ].rgba();
if ( val < 0 || val > mNColors )
{
imageScanLine[j] = myDefaultColor;
}
else
{
imageScanLine[j] = mColors[ val ].rgba();
}
}
else
{
Expand Down Expand Up @@ -167,7 +187,13 @@ void * QgsPalettedRasterRenderer::readBlock( int bandNo, QgsRectangle const & e
}

VSIFree( rasterData );

void * data = VSIMalloc( img.byteCount() );
if ( ! data )
{
QgsDebugMsg( QString( "Couldn't allocate output data memory of % bytes" ).arg( img.byteCount() ) );
return 0;
}
return memcpy( data, img.bits(), img.byteCount() );
}

Expand Down
44 changes: 33 additions & 11 deletions src/core/raster/qgsrasterfilewriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,11 +157,13 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster( const Qgs
QList<QgsRasterInterface::DataType> destDataTypeList;
for ( int bandNo = 1; bandNo <= nBands; bandNo++ )
{
QgsRasterNuller *nuller = pipe->nuller();

bool srcHasNoDataValue = srcProvider->srcHasNoDataValue( bandNo );
bool destHasNoDataValue = false;
double destNoDataValue;
QgsRasterInterface::DataType destDataType = srcProvider->srcDataType( bandNo );
//QgsRasterInterface::DataType destDataType = srcProvider->srcDataType( bandNo );
QgsRasterInterface::DataType destDataType = srcProvider->dataType( bandNo );
if ( srcHasNoDataValue )
{
// If source has no data value, it is used by provider
Expand All @@ -170,13 +172,12 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster( const Qgs
destNoDataValue = srcProvider->noDataValue();
destHasNoDataValue = true;
}
#if 0
else if ( )
else if ( nuller && nuller->noData().size() > 0 )
{
// TODO: see if nuller has user defined aditional values, in that case use one as no data value

// Use one user defined no data value
destNoDataValue = nuller->noData().value( 0 ).min;
destHasNoDataValue = true;
}
#endif
else
{
// Verify if we realy need no data value, i.e.
Expand Down Expand Up @@ -212,6 +213,8 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster( const Qgs
destHasNoDataValue = true;
}
}
if ( nuller ) nuller->setOutputNoData( destNoDataValue );

QgsDebugMsg( QString( "bandNo = %1 destDataType = %2 destHasNoDataValue = %3 destNoDataValue = %4" ).arg( bandNo ).arg( destDataType ).arg( destHasNoDataValue ).arg( destNoDataValue ) );
destDataTypeList.append( destDataType );
destHasNoDataValueList.append( destHasNoDataValue );
Expand Down Expand Up @@ -282,11 +285,12 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster(
int iterCols = 0;
int iterRows = 0;

int dataTypeSize = srcProvider->typeSize( srcProvider->srcDataType( 1 ) );
int dataTypeSize = srcProvider->typeSize( srcProvider->dataType( 1 ) ) / 8;
QList<void*> dataList;
for ( int i = 1; i <= nBands; ++i )
{
iter->startRasterRead( i, nCols, nRows, outputExtent );
// TODO: no need to alloc memory, change to readBlock() returning the allocated block
dataList.push_back( VSIMalloc( dataTypeSize * mMaxTileWidth * mMaxTileHeight ) );
// TODO - fix segfault here when using tiles+vrt (reported by Etienne)
destProvider->setNoDataValue( i, destNoDataValueList.value( i - 1 ) );
Expand Down Expand Up @@ -347,6 +351,24 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster(
}
}

// It may happen that internal data type (dataType) is wider than destDataType
QList<void*> destDataList;
for ( int i = 1; i <= nBands; ++i )
{
if ( srcProvider->dataType( i ) == destDataType )
{
destDataList.push_back( dataList[i-1] );
}
else
{
// TODO: this conversion should go to QgsRasterDataProvider::write with additional input data type param
void *destData = QgsRasterInterface::convert( dataList[i-1], srcProvider->srcDataType( i ), destDataType, iterCols * iterRows );
destDataList.push_back( destData );
CPLFree( dataList[i-1] );
}
dataList[i-1] = 0;
}

if ( mTiledMode ) //write to file
{
delete destProvider;
Expand All @@ -356,8 +378,8 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster(
//write data to output file. todo: loop over the data list
for ( int i = 1; i <= nBands; ++i )
{
destProvider->write( dataList[i - 1], i, iterCols, iterRows, 0, 0 );
CPLFree( dataList[i - 1] );
destProvider->write( destDataList[i - 1], i, iterCols, iterRows, 0, 0 );
CPLFree( destDataList[i - 1] );
addToVRT( QString::number( fileIndex ), i, iterCols, iterRows, iterLeft, iterTop );
}
}
Expand All @@ -366,8 +388,8 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster(
//loop over data
for ( int i = 1; i <= nBands; ++i )
{
destProvider->write( dataList[i - 1], i, iterCols, iterRows, iterLeft, iterTop );
CPLFree( dataList[i - 1] );
destProvider->write( destDataList[i - 1], i, iterCols, iterRows, iterLeft, iterTop );
CPLFree( destDataList[i - 1] );
}
}
++fileIndex;
Expand Down
14 changes: 14 additions & 0 deletions src/core/raster/qgsrasterinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
#include "qgslogger.h"
#include "qgsrasterinterface.h"

#include "cpl_conv.h"

QgsRasterInterface::QgsRasterInterface( QgsRasterInterface * input )
: mInput( input )
, mOn( true )
Expand Down Expand Up @@ -248,3 +250,15 @@ QString QgsRasterInterface::printValue( double value )
QgsDebugMsg( "Cannot correctly parse printed value" );
return s;
}

void * QgsRasterInterface::convert( void *srcData, QgsRasterInterface::DataType srcDataType, QgsRasterInterface::DataType destDataType, int size )
{
int destDataTypeSize = typeSize( destDataType ) / 8;
void *destData = VSIMalloc( destDataTypeSize * size );
for ( int i = 0; i < size; i++ )
{
double value = readValue( srcData, srcDataType, i );
writeValue( destData, destDataType, i, value );
}
return destData;
}
24 changes: 20 additions & 4 deletions src/core/raster/qgsrasterinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@
#ifndef QGSRASTERINTERFACE_H
#define QGSRASTERINTERFACE_H

#include <limits>

#include <QImage>

#include "qgslogger.h"
#include "qgsrectangle.h"

#include "gdal.h"
Expand Down Expand Up @@ -61,7 +64,7 @@ class CORE_EXPORT QgsRasterInterface

virtual ~QgsRasterInterface();

int typeSize( int dataType ) const
static int typeSize( int dataType )
{
// Modified and extended copy from GDAL
switch ( dataType )
Expand Down Expand Up @@ -114,6 +117,7 @@ class CORE_EXPORT QgsRasterInterface
virtual DataType dataType( int bandNo ) const
{
Q_UNUSED( bandNo );
QgsDebugMsg( "Entered" );
return UnknownDataType;
}

Expand Down Expand Up @@ -197,15 +201,24 @@ class CORE_EXPORT QgsRasterInterface
* @return string representing the value*/
static QString printValue( double value );

/** \brief Convert block of data from one type to another. Original block memory
* is not release.
* @param srcData source data
* @param srcDataType source data type
* @param destDataType dest data type
* @param size block size (width * height)
* @return block of data in destDataType */
static void * convert( void *srcData, QgsRasterInterface::DataType srcDataType, QgsRasterInterface::DataType destDataType, int size );

protected:
// QgsRasterInterface used as input
QgsRasterInterface* mInput;

// 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 );
inline static double readValue( void *data, QgsRasterInterface::DataType type, int index );
inline static void writeValue( void *data, QgsRasterInterface::DataType type, int index, double value );

private:
// Last rendering cumulative (this and all preceding interfaces) times, from index 1
Expand All @@ -217,6 +230,7 @@ class CORE_EXPORT QgsRasterInterface

inline double QgsRasterInterface::readValue( void *data, QgsRasterInterface::DataType type, int index )
{
#if 0
if ( !mInput )
{
return 0;
Expand All @@ -226,6 +240,7 @@ inline double QgsRasterInterface::readValue( void *data, QgsRasterInterface::Dat
{
return mInput->noDataValue();
}
#endif

switch ( type )
{
Expand Down Expand Up @@ -256,7 +271,8 @@ inline double QgsRasterInterface::readValue( void *data, QgsRasterInterface::Dat
}

// TODO: noDataValue is per band
return mInput->noDataValue();
//return mInput->noDataValue();
return std::numeric_limits<double>::quiet_NaN();
}

inline void QgsRasterInterface::writeValue( void *data, QgsRasterInterface::DataType type, int index, double value )
Expand Down
6 changes: 6 additions & 0 deletions src/core/raster/qgsrasteriterator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ bool QgsRasterIterator::readNextRasterPart( int bandNumber,

RasterPartInfo& pInfo = partIt.value();

// If we started with zero cols or zero rows, just return (avoids divide by zero below)
if ( 0 == pInfo.nCols || 0 == pInfo.nRows )
{
return false;
}

//remove last data block
// TODO: data are released somewhere else (check)
//free( pInfo.data );
Expand Down
4 changes: 3 additions & 1 deletion src/core/raster/qgsrasternuller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ void * QgsRasterNuller::readBlock( int bandNo, QgsRectangle const & extent, int

QgsRasterInterface::DataType dataType = mInput->dataType( bandNo );

double noDataValue = mInput->noDataValue( bandNo );
// Input may be without no data value
//double noDataValue = mInput->noDataValue( bandNo );
double noDataValue = mOutputNoData;

for ( int i = 0; i < height; i++ )
{
Expand Down
7 changes: 7 additions & 0 deletions src/core/raster/qgsrasternuller.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,15 @@ class CORE_EXPORT QgsRasterNuller : public QgsRasterInterface

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

QList<QgsRasterNuller::NoData> noData() const { return mNoData; }

/** \brief Set output no data value. */
void setOutputNoData( double noData ) { mOutputNoData = noData; }

private:
QList<QgsRasterNuller::NoData> mNoData;
// no data to be set in output
double mOutputNoData;
};

#endif // QGSRASTERNULLER_H
19 changes: 14 additions & 5 deletions src/core/raster/qgsrasterpipe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,11 +123,15 @@ bool QgsRasterPipe::replace( int idx, QgsRasterInterface* theInterface )

QgsRasterPipe::Role QgsRasterPipe::interfaceRole( QgsRasterInterface * interface ) const
{
if ( dynamic_cast<QgsRasterDataProvider *>( interface ) ) return ProviderRole;
if ( dynamic_cast<QgsRasterRenderer *>( interface ) ) return RendererRole;
if ( dynamic_cast<QgsRasterResampleFilter *>( interface ) ) return ResamplerRole;
if ( dynamic_cast<QgsRasterProjector *>( interface ) ) return ProjectorRole;
return UnknownRole;
Role role = UnknownRole;
if ( dynamic_cast<QgsRasterDataProvider *>( interface ) ) role = ProviderRole;
else if ( dynamic_cast<QgsRasterRenderer *>( interface ) ) role = RendererRole;
else if ( dynamic_cast<QgsRasterResampleFilter *>( interface ) ) role = ResamplerRole;
else if ( dynamic_cast<QgsRasterProjector *>( interface ) ) role = ProjectorRole;
else if ( dynamic_cast<QgsRasterNuller *>( interface ) ) role = NullerRole;

QgsDebugMsg( QString( "%1 role = %2" ).arg( typeid( *interface ).name() ).arg( role ) );
return role;
}

void QgsRasterPipe::setRole( QgsRasterInterface * theInterface, int idx )
Expand Down Expand Up @@ -225,6 +229,11 @@ QgsRasterProjector * QgsRasterPipe::projector() const
return dynamic_cast<QgsRasterProjector*>( interface( ProjectorRole ) );
}

QgsRasterNuller * QgsRasterPipe::nuller() const
{
return dynamic_cast<QgsRasterNuller*>( interface( NullerRole ) );
}

bool QgsRasterPipe::remove( int idx )
{
QgsDebugMsg( QString( "remove at %1" ).arg( idx ) );
Expand Down
5 changes: 4 additions & 1 deletion src/core/raster/qgsrasterpipe.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "qgsrasterinterface.h"
#include "qgsrasterresamplefilter.h"
#include "qgsrasterdataprovider.h"
#include "qgsrasternuller.h"
#include "qgsrasterrenderer.h"
#include "qgsrasterprojector.h"

Expand All @@ -45,7 +46,8 @@ class CORE_EXPORT QgsRasterPipe
ProviderRole = 1,
RendererRole = 2,
ResamplerRole = 3,
ProjectorRole = 4
ProjectorRole = 4,
NullerRole = 5,
};

QgsRasterPipe( );
Expand Down Expand Up @@ -91,6 +93,7 @@ class CORE_EXPORT QgsRasterPipe
QgsRasterRenderer * renderer() const;
QgsRasterResampleFilter * resampleFilter() const;
QgsRasterProjector * projector() const;
QgsRasterNuller * nuller() const;

/** Set on/off collection of statistics */
void setStatsOn( bool on ) { if ( last() ) last()->setStatsOn( on ); }
Expand Down
2 changes: 2 additions & 0 deletions src/core/raster/qgsrasterrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ int QgsRasterRenderer::bandCount() const

QgsRasterInterface::DataType QgsRasterRenderer::dataType( int bandNo ) const
{
QgsDebugMsg( "Entered" );

if ( mOn ) return QgsRasterInterface::ARGB32_Premultiplied;

if ( mInput ) return mInput->dataType( bandNo );
Expand Down
3 changes: 2 additions & 1 deletion src/core/raster/qgsrasterresamplefilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ bool QgsRasterResampleFilter::setInput( QgsRasterInterface* input )
return false;
}

if ( input->dataType( 1 ) != QgsRasterInterface::ARGB32_Premultiplied )
if ( input->dataType( 1 ) != QgsRasterInterface::ARGB32_Premultiplied &&
input->dataType( 1 ) != QgsRasterInterface::ARGB32 )
{
QgsDebugMsg( "Unknown input data type" );
return false;
Expand Down
17 changes: 17 additions & 0 deletions src/core/raster/qgssinglebandcolordatarenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,21 @@ void * QgsSingleBandColorDataRenderer::readBlock( int bandNo, QgsRectangle cons
bool hasTransparency = usesTransparency();

void* rasterData = mInput->block( bandNo, extent, width, height );
if ( ! rasterData )
{
QgsDebugMsg("No raster data!" );
return 0;
}

currentRasterPos = 0;
QImage img( width, height, QImage::Format_ARGB32 );
if ( img.isNull() )
{
QgsDebugMsg( "Could not create QImage" );
VSIFree( rasterData );
return 0;
}

uchar* scanLine = 0;
for ( int i = 0; i < height; ++i )
{
Expand All @@ -91,6 +103,11 @@ void * QgsSingleBandColorDataRenderer::readBlock( int bandNo, QgsRectangle cons
VSIFree( rasterData );

void * data = VSIMalloc( img.byteCount() );
if ( ! data )
{
QgsDebugMsg( QString( "Couldn't allocate output data memory of % bytes" ).arg( img.byteCount() ) );
return 0;
}
return memcpy( data, img.bits(), img.byteCount() );
}

Expand Down
17 changes: 17 additions & 0 deletions src/core/raster/qgssinglebandpseudocolorrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ void * QgsSingleBandPseudoColorRenderer::readBlock( int bandNo, QgsRectangle co
QgsRasterInterface::DataType rasterType = ( QgsRasterInterface::DataType )mInput->dataType( mBand );

void* rasterData = mInput->block( mBand, extent, width, height );
if ( ! rasterData )
{
QgsDebugMsg("No raster data!" );
return 0;
}

int red, green, blue;
QRgb myDefaultColor = qRgba( 255, 255, 255, 0 );
Expand All @@ -107,6 +112,13 @@ void * QgsSingleBandPseudoColorRenderer::readBlock( int bandNo, QgsRectangle co

//create image
QImage img( width, height, QImage::Format_ARGB32_Premultiplied );
if ( img.isNull() )
{
QgsDebugMsg( "Could not create QImage" );
VSIFree( rasterData );
return 0;
}

QRgb* imageScanLine = 0;
double val = 0;

Expand Down Expand Up @@ -156,6 +168,11 @@ void * QgsSingleBandPseudoColorRenderer::readBlock( int bandNo, QgsRectangle co
VSIFree( rasterData );

void * data = VSIMalloc( img.byteCount() );
if ( ! data )
{
QgsDebugMsg( QString( "Couldn't allocate output data memory of % bytes" ).arg( img.byteCount() ) );
return 0;
}
return memcpy( data, img.bits(), img.byteCount() );
}

Expand Down
212 changes: 129 additions & 83 deletions src/gui/qgscollapsiblegroupbox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,154 +21,200 @@
#include "qgslogger.h"

#include <QToolButton>

#include <QMouseEvent>
#include <QStyleOptionGroupBox>
#include <QSettings>

QIcon QgsCollapsibleGroupBox::mCollapseIcon;
QIcon QgsCollapsibleGroupBox::mExpandIcon;

QgsCollapsibleGroupBox::QgsCollapsibleGroupBox( QWidget *parent )
: QGroupBox( parent ), mCollapsed( true ), mMarginOffset( 0 )
: QGroupBox( parent ), mCollapsed( false ), mSaveState( true )
{
init();
}

QgsCollapsibleGroupBox::QgsCollapsibleGroupBox( const QString &title,
QWidget *parent )
: QGroupBox( title, parent ), mCollapsed( true ), mMarginOffset( 0 )
: QGroupBox( title, parent ), mCollapsed( false ), mSaveState( true )
{
init();
}

void QgsCollapsibleGroupBox::init()
QgsCollapsibleGroupBox::~QgsCollapsibleGroupBox()
{
/* Top margin fix is to increase the vertical default spacing
between multiple groupboxes, especially ones without title checkboxes
may not be necessary on certain platforms */
mMarginOffset = 0; // in pixels; for temporary testing across platforms
saveState();
}

void QgsCollapsibleGroupBox::init()
{
// init icons
if ( mCollapseIcon.isNull() )
{
mCollapseIcon = QgsApplication::getThemeIcon( "/mIconCollapse.png" );
mExpandIcon = QgsApplication::getThemeIcon( "/mIconExpand.png" );
}

// customize style sheet
// TODO: move to app stylesheet system, when appropriate
QString ss;
if ( mMarginOffset > 0 )
{
ss += "QgsCollapsibleGroupBox {";
ss += QString( " margin-top: %1px;" ).arg( mMarginOffset + 8 );
ss += "}";
}
ss += "QgsCollapsibleGroupBox::title {";
ss += " subcontrol-origin: margin;";
ss += " subcontrol-position: top left;";
// ss += QString( " font-size: %1";).arg( appFontSize );
ss += " margin-left: 24px;"; // offset for disclosure triangle
if ( mMarginOffset > 0 )
ss += QString( " margin-top: %1px;" ).arg( mMarginOffset );
ss += "}";
setStyleSheet( ss );

// collapse button
mCollapseButton = new QToolButton( this );
mCollapseButton->setObjectName( "collapseButton" );
mCollapseButton->setAutoRaise( true );
mCollapseButton->setFixedSize( 16, 16 );
// TODO set size (as well as margins) depending on theme
// TODO set size (as well as margins) depending on theme, in updateStyle()
mCollapseButton->setIconSize( QSize( 12, 12 ) );
mCollapseButton->setIcon( mExpandIcon );
if ( mMarginOffset > 0 )
mCollapseButton->move( 0, mMarginOffset ); // match title offset

// clear toolbutton default background and border
// TODO: move to app stylesheet system, when appropriate
QString ssd;
ssd = QString( "QgsCollapsibleGroupBox > QToolButton#%1 {" ).arg( mCollapseButton->objectName() );
ssd += " background-color: rgba(255, 255, 255, 0); border: none;";
ssd += "}";
mCollapseButton->setStyleSheet( ssd );
mCollapseButton->setIcon( mCollapseIcon );

connect( mCollapseButton, SIGNAL( clicked() ), this, SLOT( toggleCollapsed() ) );
connect( this, SIGNAL( clicked( bool ) ), this, SLOT( checkClicked() ) );
connect( this, SIGNAL( toggled( bool ) ), this, SLOT( checkToggled() ) );
connect( this, SIGNAL( toggled( bool ) ), this, SLOT( checkToggled( bool ) ) );
}

void QgsCollapsibleGroupBox::showEvent( QShowEvent * event )
{
QGroupBox::showEvent( event );
// expand if needed - any calls to setCollapsed() before have no effect
loadState();

updateStyle();

// expand if needed - any calls to setCollapsed() before only set mCollapsed
if ( mCollapsed )
{
setCollapsed( mCollapsed );
}
else
{
/* manually uncollapsing (already default) on show may scroll scroll areas
still emit signal for connections using uncollapsed state */
/* manually expanding (already default) on show may scroll scroll areas;
still emit signal for connections using expanded state */
emit collapsedStateChanged( this );
}
event->accept();
}

void QgsCollapsibleGroupBox::checkClicked()
void QgsCollapsibleGroupBox::mouseReleaseEvent( QMouseEvent *event )
{
mCollapseButton->setEnabled( true ); // always keep enabled
// expand/collapse when clicked
if ( isChecked() && isCollapsed() )
setCollapsed( false );
else if ( ! isChecked() && ! isCollapsed() )
setCollapsed( true );
// catch mouse release over title when non checkable, to collapse/expand
if ( !isCheckable() && event->button() == Qt::LeftButton )
{
if ( titleRect().contains( event->pos() ) )
{
toggleCollapsed();
return;
}
}
// default behaviour - pass to QGroupBox
QGroupBox::mouseReleaseEvent( event );
}

QRect QgsCollapsibleGroupBox::titleRect() const
{
QStyleOptionGroupBox box;
initStyleOption( &box );
return style()->subControlRect( QStyle::CC_GroupBox, &box,
QStyle::SC_GroupBoxLabel, this );
}

QString QgsCollapsibleGroupBox::saveKey() const
{
// save key for load/save state
// currently QgsCollapsibleGroupBox/window()/object
QString saveKey = "/" + objectName();
// QObject* parentWidget = parent();
// while ( parentWidget != NULL )
// {
// saveKey = "/" + parentWidget->objectName() + saveKey;
// parentWidget = parentWidget->parent();
// }
// if ( parent() != NULL )
// saveKey = "/" + parent()->objectName() + saveKey;
saveKey = "/" + window()->objectName() + saveKey;
saveKey = "QgsCollapsibleGroupBox" + saveKey;
return saveKey;
}

void QgsCollapsibleGroupBox::loadState()
{
if ( ! mSaveState )
return;

setUpdatesEnabled( false );

QSettings settings;
QString key = saveKey();
QVariant val = settings.value( key + "/checked" );
if ( ! val.isNull() )
setChecked( val.toBool() );
val = settings.value( key + "/collapsed" );
if ( ! val.isNull() )
setCollapsed( val.toBool() );

setUpdatesEnabled( true );
}

void QgsCollapsibleGroupBox::saveState()
{
if ( ! mSaveState )
return;
QgsDebugMsg( "key = " + saveKey() + " objectName = " + objectName() );
QSettings settings;
QString key = saveKey();
settings.setValue( key + "/checked", isChecked() );
settings.setValue( key + "/collapsed", isCollapsed() );
}

void QgsCollapsibleGroupBox::checkToggled()
void QgsCollapsibleGroupBox::checkToggled( bool chkd )
{
mCollapseButton->setEnabled( true ); // always keep enabled
// expand/collapse when toggled
if ( chkd && isCollapsed() )
setCollapsed( false );
else if ( ! chkd && ! isCollapsed() )
setCollapsed( true );
}

void QgsCollapsibleGroupBox::toggleCollapsed()
{
setCollapsed( !mCollapsed );
}

void QgsCollapsibleGroupBox::updateStyle()
{
setUpdatesEnabled( false );

// customize style sheet
// TODO: move to app stylesheet system, when appropriate
QString ss;
ss += "QgsCollapsibleGroupBox::title {";
ss += " subcontrol-origin: margin;";
ss += " subcontrol-position: top left;";
ss += " margin-left: 20px;"; // offset for disclosure triangle
ss += " margin-right: 5px;"; // a little bit of space on the right, to match space on the left
ss += "}";
setStyleSheet( ss );

// clear toolbutton default background and border
// TODO: move to app stylesheet system, when appropriate
QString ssd;
ssd = QString( "QgsCollapsibleGroupBox > QToolButton#%1 {" ).arg( mCollapseButton->objectName() );
ssd += " background-color: rgba(255, 255, 255, 0); border: none;";
ssd += "}";
mCollapseButton->setStyleSheet( ssd );

setUpdatesEnabled( true );
}

void QgsCollapsibleGroupBox::setCollapsed( bool collapse )
{
mCollapsed = collapse;

if ( !isVisible() )
return;

mCollapsed = collapse;

// for consistent look/spacing across platforms when collapsed
setFlat( collapse );
setMaximumHeight( collapse ? 36 : 16777215 );

// if we are collapsing, save hidden widgets in a list
if ( collapse )
{
mCollapseButton->setIcon( mExpandIcon );
mHiddenWidgets.clear();
foreach ( QWidget *widget, findChildren<QWidget*>() )
{
if ( widget->isHidden() && widget->objectName() != mCollapseButton->objectName() )
mHiddenWidgets << widget;
}
}

// show/hide widgets
foreach ( QWidget *widget, findChildren<QWidget*>() )
if ( widget->objectName() != mCollapseButton->objectName() )
widget->setHidden( collapse );

// if we are expanding, re-hide saved hidden widgets
if ( ! collapse )
{
mCollapseButton->setIcon( mCollapseIcon );
foreach ( QWidget *widget, mHiddenWidgets )
{
widget->setHidden( true );
}
}
// avoid flicker in X11
QApplication::processEvents();
// set maximum height to hide contents - does this work in all envs?
// setMaximumHeight( collapse ? 25 : 16777215 );
setMaximumHeight( collapse ? titleRect().bottom() + 6 : 16777215 );
mCollapseButton->setIcon( collapse ? mExpandIcon : mCollapseIcon );

emit collapsedStateChanged( this );
}
Expand Down
20 changes: 13 additions & 7 deletions src/gui/qgscollapsiblegroupbox.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,27 +36,33 @@ class GUI_EXPORT QgsCollapsibleGroupBox : public QGroupBox
public:
QgsCollapsibleGroupBox( QWidget *parent = 0 );
QgsCollapsibleGroupBox( const QString &title, QWidget *parent = 0 );

~QgsCollapsibleGroupBox();
bool isCollapsed() const { return mCollapsed; }
void setCollapsed( bool collapse );
void setSaveState( bool save ) { mSaveState = save; }

signals:
void collapsedStateChanged( QWidget* );

public slots:
void checkClicked();
void checkToggled();
void checkToggled( bool ckd );
void toggleCollapsed();
void updateStyle();

protected slots:
void loadState();
void saveState();

protected:
void init();
void showEvent( QShowEvent * event );
void showEvent( QShowEvent *event );
void mouseReleaseEvent( QMouseEvent *event );
QRect titleRect() const;
QString saveKey() const;

private:
bool mCollapsed;
QList< QWidget* > mHiddenWidgets;
bool mSaveState;
QToolButton* mCollapseButton;
int mMarginOffset;

static QIcon mCollapseIcon;
static QIcon mExpandIcon;
Expand Down
8 changes: 4 additions & 4 deletions src/gui/qgsrasterlayersaveasdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -251,10 +251,10 @@ void QgsRasterLayerSaveAsDialog::setOutputExtent( const QgsRectangle& r, const Q
extent = ct.transformBoundingBox( r );
}

mXMinLineEdit->setText( QString::number( extent.xMinimum() ) );
mXMaxLineEdit->setText( QString::number( extent.xMaximum() ) );
mYMinLineEdit->setText( QString::number( extent.yMinimum() ) );
mYMaxLineEdit->setText( QString::number( extent.yMaximum() ) );
mXMinLineEdit->setText( QgsRasterInterface::printValue( extent.xMinimum() ) );
mXMaxLineEdit->setText( QgsRasterInterface::printValue( extent.xMaximum() ) );
mYMinLineEdit->setText( QgsRasterInterface::printValue( extent.yMinimum() ) );
mYMaxLineEdit->setText( QgsRasterInterface::printValue( extent.yMaximum() ) );

mExtentState = state;
extentChanged();
Expand Down
2 changes: 2 additions & 0 deletions src/plugins/georeferencer/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ SET (GEOREF_SRCS
qgsimagewarper.cpp
qgsgeoreftransform.cpp
qgsgcplistwidget.cpp

qgsrasterchangecoords.cpp
)

SET (GEOREF_UIS
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 5 additions & 5 deletions src/plugins/georeferencer/qgsgcplistmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ void QgsGCPListModel::updateModel()
return;

bool bTransformUpdated = false;
QgsPoint origin;

vector<QgsPoint> mapCoords, pixelCoords;
mGCPList->createGCPVectors( mapCoords, pixelCoords );
Expand Down Expand Up @@ -125,7 +124,7 @@ void QgsGCPListModel::updateModel()
setItem( i, j++, si );
setItem( i, j++, new QgsStandardItem( i ) );
setItem( i, j++, new QgsStandardItem( p->pixelCoords().x() ) );
setItem( i, j++, new QgsStandardItem( -p->pixelCoords().y() ) );
setItem( i, j++, new QgsStandardItem( p->pixelCoords().y() ) );
setItem( i, j++, new QgsStandardItem( p->mapCoords().x() ) );
setItem( i, j++, new QgsStandardItem( p->mapCoords().y() ) );

Expand All @@ -136,6 +135,7 @@ void QgsGCPListModel::updateModel()
if ( mGeorefTransform && bTransformUpdated && mGeorefTransform->parametersInitialized() )
{
QgsPoint dst;
QgsPoint pixel = mGeorefTransform->hasCrs() ? mGeorefTransform->toColumnLine( p->pixelCoords() ) : p->pixelCoords();
if ( unitType == tr( "pixels" ) )
{
// Transform from world to raster coordinate:
Expand All @@ -144,13 +144,13 @@ void QgsGCPListModel::updateModel()
// interested in the residual in this direction
if ( mGeorefTransform->transformWorldToRaster( p->mapCoords(), dst ) )
{
dX = ( dst.x() - p->pixelCoords().x() );
dY = -( dst.y() - p->pixelCoords().y() );
dX = ( dst.x() - pixel.x() );
dY = -( dst.y() - pixel.y() );
}
}
else if ( unitType == tr( "map units" ) )
{
if ( mGeorefTransform->transformRasterToWorld( p->pixelCoords(), dst ) )
if ( mGeorefTransform->transformRasterToWorld( pixel, dst ) )
{
dX = ( dst.x() - p->mapCoords().x() );
dY = ( dst.y() - p->mapCoords().y() );
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/georeferencer/qgsgcplistwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ void QgsGCPListWidget::updateItemCoords( QWidget *editor )
}
else if ( mPrevColumn == 3 ) // srcY
{
newPixelCoords.setY( -value );
newPixelCoords.setY( value );
}
else if ( mPrevColumn == 4 ) // dstX
{
Expand Down
84 changes: 66 additions & 18 deletions src/plugins/georeferencer/qgsgeorefplugingui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ void QgsGeorefPluginGui::openRaster()
s.setValue( "/Plugin-GeoReferencer/lastusedfilter", lastUsedFilter );

mGeorefTransform.selectTransformParametrisation( mTransformParam );
mGeorefTransform.setRasterChangeCoords( mRasterFileName );
statusBar()->showMessage( tr( "Raster loaded: %1" ).arg( mRasterFileName ) );
setWindowTitle( tr( "Georeferencer - %1" ).arg( fileInfo.fileName() ) );

Expand Down Expand Up @@ -628,6 +629,23 @@ void QgsGeorefPluginGui::showGeorefConfigDialog()
}
}

// Histogram stretch slots
void QgsGeorefPluginGui::fullHistogramStretch()
{
mLayer->setContrastEnhancementAlgorithm( "StretchToMinimumMaximum" );
mLayer->setMinimumMaximumUsingDataset();
mLayer->setCacheImage( NULL );
mCanvas->refresh();
}

void QgsGeorefPluginGui::localHistogramStretch()
{
mLayer->setContrastEnhancementAlgorithm( "StretchToMinimumMaximum" );
mLayer->setMinimumMaximumUsingLastExtent();
mLayer->setCacheImage( NULL );
mCanvas->refresh();
}

// Info slots
void QgsGeorefPluginGui::contextHelp()
{
Expand Down Expand Up @@ -673,7 +691,8 @@ void QgsGeorefPluginGui::extentsChangedGeorefCanvas()
}

// Reproject the georeference plugin canvas into world coordinates and fit axis aligned bounding box
QgsRectangle boundingBox = transformViewportBoundingBox( mCanvas->extent(), mGeorefTransform, true );
QgsRectangle rectMap = mGeorefTransform.hasCrs() ? mGeorefTransform.getBoundingBox( mCanvas->extent(), true ) : mCanvas->extent();
QgsRectangle boundingBox = transformViewportBoundingBox( rectMap, mGeorefTransform, true );

mExtentsChangedRecursionGuard = true;
// Just set the whole extent for now
Expand Down Expand Up @@ -703,11 +722,12 @@ void QgsGeorefPluginGui::extentsChangedQGisCanvas()

// Reproject the canvas into raster coordinates and fit axis aligned bounding box
QgsRectangle boundingBox = transformViewportBoundingBox( mIface->mapCanvas()->extent(), mGeorefTransform, false );
QgsRectangle rectMap = mGeorefTransform.hasCrs() ? mGeorefTransform.getBoundingBox( boundingBox, false ) : boundingBox;

mExtentsChangedRecursionGuard = true;
// Just set the whole extent for now
// TODO: better fitting function which acounts for differing aspect ratios etc.
mCanvas->setExtent( boundingBox );
mCanvas->setExtent( rectMap );
mCanvas->refresh();
mExtentsChangedRecursionGuard = false;
}
Expand Down Expand Up @@ -840,6 +860,15 @@ void QgsGeorefPluginGui::createActions()
mActionGeorefConfig->setIcon( getThemeIcon( "/mActionGeorefConfig.png" ) );
connect( mActionGeorefConfig, SIGNAL( triggered() ), this, SLOT( showGeorefConfigDialog() ) );

// Histogram stretch
mActionLocalHistogramStretch->setIcon( getThemeIcon( "/mActionLocalHistogramStretch.png" ) );
connect( mActionLocalHistogramStretch, SIGNAL( triggered() ), this, SLOT( localHistogramStretch() ) );
mActionLocalHistogramStretch->setEnabled(false);

mActionFullHistogramStretch->setIcon( getThemeIcon( "/mActionFullHistogramStretch.png" ) );
connect( mActionFullHistogramStretch, SIGNAL( triggered() ), this, SLOT( fullHistogramStretch() ) );
mActionFullHistogramStretch->setEnabled(false);

// Help actions
mActionHelp = new QAction( tr( "Help" ), this );
connect( mActionHelp, SIGNAL( triggered() ), this, SLOT( contextHelp() ) );
Expand Down Expand Up @@ -985,32 +1014,35 @@ void QgsGeorefPluginGui::createDockWidgets()
connect( mGCPListWidget, SIGNAL( pointEnabled( QgsGeorefDataPoint*, int ) ), this, SLOT( updateGeorefTransform() ) );
}

void QgsGeorefPluginGui::createStatusBar()
QLabel* QgsGeorefPluginGui::createBaseLabelStatus()
{
QFont myFont( "Arial", 9 );
QLabel* label = new QLabel( statusBar() );
label->setFont( myFont );
label->setMinimumWidth( 10 );
label->setMaximumHeight( 20 );
label->setMargin( 3 );
label->setAlignment( Qt::AlignCenter );
label->setFrameStyle( QFrame::NoFrame );
return label;
}

mTransformParamLabel = new QLabel( statusBar() );
mTransformParamLabel->setFont( myFont );
mTransformParamLabel->setMinimumWidth( 10 );
mTransformParamLabel->setMaximumHeight( 20 );
mTransformParamLabel->setMargin( 3 );
mTransformParamLabel->setAlignment( Qt::AlignCenter );
mTransformParamLabel->setFrameStyle( QFrame::NoFrame );
void QgsGeorefPluginGui::createStatusBar()
{
mTransformParamLabel = createBaseLabelStatus();
mTransformParamLabel->setText( tr( "Transform: " ) + convertTransformEnumToString( mTransformParam ) );
mTransformParamLabel->setToolTip( tr( "Current transform parametrisation" ) );
statusBar()->addPermanentWidget( mTransformParamLabel, 0 );

mCoordsLabel = new QLabel( QString(), statusBar() );
mCoordsLabel->setFont( myFont );
mCoordsLabel->setMinimumWidth( 10 );
mCoordsLabel->setMaximumHeight( 20 );
mCoordsLabel = createBaseLabelStatus();
mCoordsLabel->setMaximumWidth( 100 );
mCoordsLabel->setMargin( 3 );
mCoordsLabel->setAlignment( Qt::AlignCenter );
mCoordsLabel->setFrameStyle( QFrame::NoFrame );
mCoordsLabel->setText( tr( "Coordinate: " ) );
mCoordsLabel->setToolTip( tr( "Current map coordinate" ) );
statusBar()->addPermanentWidget( mCoordsLabel, 0 );

mEPSG = createBaseLabelStatus();
mEPSG->setText("EPSG:");
statusBar()->addPermanentWidget( mEPSG, 0 );
}

void QgsGeorefPluginGui::setupConnections()
Expand Down Expand Up @@ -1088,6 +1120,22 @@ void QgsGeorefPluginGui::addRaster( QString file )
mCanvas->setLayerSet( layers );

mAgainAddRaster = false;

mActionLocalHistogramStretch->setEnabled(true);
mActionFullHistogramStretch->setEnabled(true);

// Status Bar
if ( mGeorefTransform.hasCrs() )
{
QString authid = mLayer->crs().authid();
mEPSG->setText( authid );
mEPSG->setToolTip( mLayer->crs().toProj4() );
}
else
{
mEPSG->setText( tr("None") );
mEPSG->setToolTip( tr("Coordinate of image(column/line)") );
}
}

// Settings
Expand Down Expand Up @@ -1894,7 +1942,7 @@ bool QgsGeorefPluginGui::updateGeorefTransform()
// Samples the given rectangle at numSamples per edge.
// Returns an axis aligned bounding box which contains the transformed samples.
QgsRectangle QgsGeorefPluginGui::transformViewportBoundingBox( const QgsRectangle &canvasExtent,
const QgsGeorefTransform &t,
QgsGeorefTransform &t,
bool rasterToWorld, uint numSamples )
{
double minX, minY;
Expand Down
9 changes: 8 additions & 1 deletion src/plugins/georeferencer/qgsgeorefplugingui.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@ class QgsGeorefPluginGui : public QMainWindow, private Ui::QgsGeorefPluginGuiBas
void showMouseCoords( const QgsPoint pt );
void updateMouseCoordinatePrecision();

// Histogram stretch
void localHistogramStretch();
void fullHistogramStretch();


// when one Layer is removed
void layerWillBeRemoved( QString theLayerId );
void extentsChanged(); // Use for need add again Raster (case above)
Expand All @@ -131,6 +136,7 @@ class QgsGeorefPluginGui : public QMainWindow, private Ui::QgsGeorefPluginGuiBas
void createMapCanvas();
void createMenus();
void createDockWidgets();
QLabel* createBaseLabelStatus();
void createStatusBar();
void setupConnections();
void removeOldLayer();
Expand Down Expand Up @@ -165,7 +171,7 @@ class QgsGeorefPluginGui : public QMainWindow, private Ui::QgsGeorefPluginGuiBas

// utils
bool checkReadyGeoref();
QgsRectangle transformViewportBoundingBox( const QgsRectangle &canvasExtent, const QgsGeorefTransform &t,
QgsRectangle transformViewportBoundingBox( const QgsRectangle &canvasExtent, QgsGeorefTransform &t,
bool rasterToWorld = true, uint numSamples = 4 );
QString convertTransformEnumToString( QgsGeorefTransform::TransformParametrisation transform );
QString convertResamplingEnumToString( QgsImageWarper::ResamplingMethod resampling );
Expand Down Expand Up @@ -202,6 +208,7 @@ class QgsGeorefPluginGui : public QMainWindow, private Ui::QgsGeorefPluginGuiBas
QLabel *mScaleLabel;
QLabel *mCoordsLabel;
QLabel *mTransformParamLabel;
QLabel *mEPSG;
unsigned int mMousePrecisionDecimalPlaces;

QString mRasterFileName;
Expand Down
31 changes: 27 additions & 4 deletions src/plugins/georeferencer/qgsgeorefpluginguibase.ui
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>900</width>
<height>800</height>
<width>872</width>
<height>621</height>
</rect>
</property>
<property name="windowTitle">
Expand All @@ -21,8 +21,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>900</width>
<height>23</height>
<width>872</width>
<height>25</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
Expand Down Expand Up @@ -164,6 +164,19 @@
<layout class="QHBoxLayout" name="horizontalLayout_2"/>
</widget>
</widget>
<widget class="QToolBar" name="toolBarHistogramStretch">
<property name="windowTitle">
<string>toolBar</string>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
<addaction name="mActionFullHistogramStretch"/>
<addaction name="mActionLocalHistogramStretch"/>
</widget>
<action name="mActionOpenRaster">
<property name="text">
<string>Open raster</string>
Expand Down Expand Up @@ -351,6 +364,16 @@
<string>Zoom Last</string>
</property>
</action>
<action name="mActionLocalHistogramStretch">
<property name="text">
<string>Local histogram stretch</string>
</property>
</action>
<action name="mActionFullHistogramStretch">
<property name="text">
<string>Full histogram stretch</string>
</property>
</action>
</widget>
<resources/>
<connections/>
Expand Down
23 changes: 19 additions & 4 deletions src/plugins/georeferencer/qgsgeoreftransform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,11 @@ void QgsGeorefTransform::selectTransformParametrisation( TransformParametrisatio
}
}

void QgsGeorefTransform::setRasterChangeCoords( const QString &fileRaster )
{
mRasterChangeCoords.setRaster( fileRaster );
}

bool QgsGeorefTransform::providesAccurateInverseTransformation() const
{
return ( mTransformParametrisation == Linear
Expand All @@ -203,7 +208,17 @@ bool QgsGeorefTransform::updateParametersFromGCPs( const std::vector<QgsPoint> &
{
return false;
}
return mParametersInitialized = mGeorefTransformImplementation->updateParametersFromGCPs( mapCoords, pixelCoords );
if ( mRasterChangeCoords.hasCrs() )
{
std::vector<QgsPoint> pixelCoordsCorrect = mRasterChangeCoords.getPixelCoords(pixelCoords);
mParametersInitialized = mGeorefTransformImplementation->updateParametersFromGCPs( mapCoords, pixelCoordsCorrect );
pixelCoordsCorrect.clear();
}
else
{
mParametersInitialized = mGeorefTransformImplementation->updateParametersFromGCPs( mapCoords, pixelCoords );
}
return mParametersInitialized;
}

uint QgsGeorefTransform::getMinimumGCPCount() const
Expand Down Expand Up @@ -248,22 +263,22 @@ QgsGeorefTransformInterface *QgsGeorefTransform::createImplementation( Transform
}
}

bool QgsGeorefTransform::transformRasterToWorld( const QgsPoint &raster, QgsPoint &world ) const
bool QgsGeorefTransform::transformRasterToWorld( const QgsPoint &raster, QgsPoint &world )
{
// flip y coordinate due to different CS orientation
QgsPoint raster_flipped( raster.x(), -raster.y() );
return gdal_transform( raster_flipped, world, 0 );
}

bool QgsGeorefTransform::transformWorldToRaster( const QgsPoint &world, QgsPoint &raster ) const
bool QgsGeorefTransform::transformWorldToRaster( const QgsPoint &world, QgsPoint &raster )
{
bool success = gdal_transform( world, raster, 1 );
// flip y coordinate due to different CS orientation
raster.setY( -raster.y() );
return success;
}

bool QgsGeorefTransform::transform( const QgsPoint &src, QgsPoint &dst, bool rasterToWorld ) const
bool QgsGeorefTransform::transform( const QgsPoint &src, QgsPoint &dst, bool rasterToWorld )
{
return rasterToWorld ? transformRasterToWorld( src, dst ) : transformWorldToRaster( src, dst );
}
Expand Down
23 changes: 20 additions & 3 deletions src/plugins/georeferencer/qgsgeoreftransform.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
#include <vector>
#include <stdexcept>

#include "qgsrasterchangecoords.h"

class QgsGeorefTransformInterface
{
public:
Expand Down Expand Up @@ -79,6 +81,20 @@ class QgsGeorefTransform : public QgsGeorefTransformInterface
*/
void selectTransformParametrisation( TransformParametrisation parametrisation );

/**
* Setting the mRasterChangeCoords for change type coordinate(map for pixel).
*/
void setRasterChangeCoords( const QString &fileRaster );

//! \returns Whether has Coordinate Reference Systems in image
bool hasCrs() const { return mRasterChangeCoords.hasCrs(); }

//! \returns Coordinates of image
QgsPoint toColumnLine(const QgsPoint &pntMap) { return mRasterChangeCoords.toColumnLine( pntMap ); }

//! \returns Bounding box of image(transform to coordinate of Map or Image )
QgsRectangle getBoundingBox(const QgsRectangle &rect, bool toPixel) { return mRasterChangeCoords.getBoundingBox( rect, toPixel); }

//! \brief The transform parametrisation currently in use.
TransformParametrisation transformParametrisation() const;

Expand Down Expand Up @@ -113,22 +129,22 @@ class QgsGeorefTransform : public QgsGeorefTransformInterface
*
* \note Negative y-axis points down in raster CS.
*/
bool transformRasterToWorld( const QgsPoint &raster, QgsPoint &world ) const;
bool transformRasterToWorld( const QgsPoint &raster, QgsPoint &world );

/**
* \brief Transform from referenced coordinates to raster coordinates.
*
* \note Negative y-axis points down in raster CS.
*/
bool transformWorldToRaster( const QgsPoint &world, QgsPoint &raster ) const;
bool transformWorldToRaster( const QgsPoint &world, QgsPoint &raster );

/**
* \brief Transforms from raster to world if rasterToWorld is true,
* \brief or from world to raster when rasterToWorld is false.
*
* \note Negative y-axis points down in raster CS.
*/
bool transform( const QgsPoint &src, QgsPoint &dst, bool rasterToWorld ) const;
bool transform( const QgsPoint &src, QgsPoint &dst, bool rasterToWorld );

//! \brief Returns origin and scale if this is a linear transform, fails otherwise.
bool getLinearOriginScale( QgsPoint &origin, double &scaleX, double &scaleY ) const;
Expand All @@ -149,6 +165,7 @@ class QgsGeorefTransform : public QgsGeorefTransformInterface
QgsGeorefTransformInterface *mGeorefTransformImplementation;
TransformParametrisation mTransformParametrisation;
bool mParametersInitialized;
QgsRasterChangeCoords mRasterChangeCoords;
};

#endif
8 changes: 4 additions & 4 deletions src/plugins/georeferencer/qgsmapcoordsdialogbase.ui
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>362</width>
<height>171</height>
<width>497</width>
<height>204</height>
</rect>
</property>
<property name="windowTitle">
Expand All @@ -32,7 +32,7 @@
<item row="0" column="0">
<widget class="QLabel" name="textLabel1">
<property name="text">
<string>X:</string>
<string>X / East:</string>
</property>
</widget>
</item>
Expand All @@ -46,7 +46,7 @@
<item row="0" column="0">
<widget class="QLabel" name="textLabel2">
<property name="text">
<string>Y:</string>
<string>Y / North:</string>
</property>
</widget>
</item>
Expand Down
91 changes: 91 additions & 0 deletions src/plugins/georeferencer/qgsrasterchangecoords.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/***************************************************************************
qgsrasterchangecoords.cpp
--------------------------------------
Date : 25-June-2011
Copyright : (C) 2011 by Luiz Motta
Email : motta.luiz at gmail.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 "qgsrasterchangecoords.h"

#include <qgspoint.h>
#include <gdal.h>

#include <QFile>

#if defined(GDAL_VERSION_NUM) && GDAL_VERSION_NUM >= 1800
#define TO8F(x) (x).toUtf8().constData()
#else
#define TO8F(x) QFile::encodeName( x ).constData()
#endif

QgsRasterChangeCoords::QgsRasterChangeCoords()
{
mHasCrs = false;
}

void QgsRasterChangeCoords::setRaster( const QString &fileRaster )
{
GDALAllRegister();
GDALDatasetH hDS = GDALOpen( TO8F( fileRaster ), GA_ReadOnly );
double adfGeoTransform[6];
if( GDALGetProjectionRef( hDS ) != NULL && GDALGetGeoTransform(hDS, adfGeoTransform) == CE_None)
//if ( false )
{
mHasCrs = true;
mUL_X = adfGeoTransform[0];
mUL_Y = adfGeoTransform[3];
mResX = adfGeoTransform[1];
mResY = adfGeoTransform[5];
}
else
{
mHasCrs = false;
}
GDALClose( hDS );
}

std::vector<QgsPoint> QgsRasterChangeCoords::getPixelCoords(const std::vector<QgsPoint> &mapCoords)
{
const int size = mapCoords.size();
std::vector<QgsPoint> pixelCoords( size );
for ( int i = 0; i < size; i++ )
{
pixelCoords[i] = toColumnLine( mapCoords.at( i ) );
}
return pixelCoords;
}

QgsRectangle QgsRasterChangeCoords::getBoundingBox(const QgsRectangle &rect, bool toPixel)
{
QgsRectangle rectReturn;
QgsPoint p1( rect.xMinimum(), rect.yMinimum() );
QgsPoint p2( rect.xMaximum(), rect.yMaximum() );
QgsPoint ( QgsRasterChangeCoords::* func )( const QgsPoint & );

func = toPixel ? &QgsRasterChangeCoords::toColumnLine : &QgsRasterChangeCoords::toXY;
rectReturn.set( ( this->*func ) (p1), ( this->*func )(p2) );

return rectReturn;
}

QgsPoint QgsRasterChangeCoords::toColumnLine(const QgsPoint &pntMap)
{
double col = ( pntMap.x() - mUL_X ) / mResX;
double line = ( mUL_Y - pntMap.y() ) / mResY;
return QgsPoint(col, line);
}

QgsPoint QgsRasterChangeCoords::toXY(const QgsPoint &pntPixel)
{
double x = mUL_X + ( pntPixel.x() * mResX );
double y = mUL_Y + ( pntPixel.y() * -mResY );
return QgsPoint(x, y);
}
43 changes: 43 additions & 0 deletions src/plugins/georeferencer/qgsrasterchangecoords.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/***************************************************************************
qgsrasterchangecoords.h
--------------------------------------
Date : 25-June-2011
Copyright : (C) 2011 by Luiz Motta
Email : motta.luiz at gmail.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 QGSRASTERCHANGECOORDS_H
#define QGSRASTERCHANGECOORDS_H

#include <vector>

#include "qgspoint.h"
#include "qgsrectangle.h"

class QgsRasterChangeCoords
{
public:
QgsRasterChangeCoords( );
void setRaster( const QString &fileRaster );
bool hasCrs() const { return mHasCrs; }
std::vector<QgsPoint> getPixelCoords(const std::vector<QgsPoint> &mapCoords);
QgsRectangle getBoundingBox(const QgsRectangle &rect, bool toPixel);
QgsPoint toColumnLine(const QgsPoint &pntMap);
QgsPoint toXY(const QgsPoint &pntPixel);

private:
bool mHasCrs;
double mUL_X;
double mUL_Y;
double mResX;
double mResY;
};

#endif // QGSRASTERCHANGECOORDS_H
6 changes: 5 additions & 1 deletion src/providers/gdal/qgsgdalprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,11 @@ void QgsGdalProvider::readBlock( int theBandNo, QgsRectangle const & theExtent,

// Allocate temporary block
char *tmpBlock = ( char * )malloc( dataSize * tmpWidth * tmpHeight );

if ( ! tmpBlock )
{
QgsDebugMsg( QString( "Coudn't allocate temporary buffer of %1 bytes" ).arg( dataSize * tmpWidth * tmpHeight ) );
return;
}
GDALRasterBandH gdalBand = GDALGetRasterBand( mGdalDataset, theBandNo );
GDALDataType type = ( GDALDataType )mGdalDataType[theBandNo-1];
CPLErrorReset();
Expand Down
1 change: 1 addition & 0 deletions src/providers/wcs/qgswcscapabilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -762,6 +762,7 @@ bool QgsWcsCapabilities::parseDescribeCoverageDom10( QByteArray const &xml, QgsW
QList<int> high = parseInts( domElementText( gridElement, "limits.GridEnvelope.high" ) );
if ( low.size() == 2 && high.size() == 2 )
{
// low/high are indexes in grid -> size is hight - low + 1
double width = high[0] - low[0] + 1;
double height = high[1] - low[1] + 1;
if ( width > 0 && height > 0 )
Expand Down
15 changes: 13 additions & 2 deletions src/providers/wcs/qgswcsprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,11 +171,14 @@ QgsWcsProvider::QgsWcsProvider( QString const &uri )
// in that case we continue without CRS and user is asked for it
//if ( mCoverageCrs.isEmpty() ) return;

// Native size
mWidth = mCoverageSummary.width;
mHeight = mCoverageSummary.height;
mHasSize = mCoverageSummary.hasSize;

QgsDebugMsg( QString( "mWidth = %1 mHeight = %2" ).arg( mWidth ).arg( mHeight ) ) ;
QgsDebugMsg( QString( "mWidth = %1 mHeight = %2" ).arg( mWidth ).arg( mHeight ) );

// TODO: Consider if/how to recalculate mWidth, mHeight if non native CRS is used

if ( !calculateExtent() )
{
Expand Down Expand Up @@ -534,6 +537,11 @@ void QgsWcsProvider::readBlock( int bandNo, QgsRectangle const & viewExtent, in
QgsDebugMsg( QString( "pixelSize = %1" ).arg( pixelSize ) );
int size = width * height * pixelSize;
void * tmpData = malloc( size );
if ( ! tmpData )
{
QgsDebugMsg( QString( "Couldn't allocate memory of %1 bytes" ).arg( size ) );
return;
}
GDALRasterIO( gdalBand, GF_Read, 0, 0, width, height, tmpData, width, height, ( GDALDataType ) mGdalDataType[bandNo-1], 0, 0 );
for ( int i = 0; i < pixelHeight; i++ )
{
Expand Down Expand Up @@ -1288,7 +1296,8 @@ bool QgsWcsProvider::calculateExtent()
// Prefer to use extent from capabilities / coverage description because
// transformation from WGS84 increases the extent
mCoverageExtent = mCoverageSummary.boundingBoxes.value( mCoverageCrs );
if ( !mCoverageExtent.isEmpty() && !mCoverageExtent.isFinite() )
QgsDebugMsg( "mCoverageCrs = " + mCoverageCrs + " mCoverageExtent = " + mCoverageExtent.toString() );
if ( !mCoverageExtent.isEmpty() && mCoverageExtent.isFinite() )
{
QgsDebugMsg( "mCoverageExtent = " + mCoverageExtent.toString() );
return true;
Expand All @@ -1308,9 +1317,11 @@ bool QgsWcsProvider::calculateExtent()
//QgsDebugMsg( "qgisSrsDest: " + qgisSrsDest.toWkt() );

mCoordinateTransform = new QgsCoordinateTransform( qgisSrsSource, qgisSrsDest );

}

QgsDebugMsg( "mCoverageSummary.wgs84BoundingBox= " + mCoverageSummary.wgs84BoundingBox.toString() );

// Convert to the user's CRS as required
try
{
Expand Down
10 changes: 7 additions & 3 deletions src/providers/wms/qgswmsprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -959,16 +959,20 @@ void QgsWmsProvider::readBlock( int bandNo, QgsRectangle const & viewExtent, in
return;
}
QgsDebugMsg( QString( "image height = %1 bytesPerLine = %2" ).arg( image->height() ) . arg( image->bytesPerLine() ) ) ;
int myExpectedSize = pixelWidth * pixelHeight * 4;
int myImageSize = image->height() * image->bytesPerLine();
size_t myExpectedSize = pixelWidth * pixelHeight * 4;
size_t myImageSize = image->height() * image->bytesPerLine();
if ( myExpectedSize != myImageSize ) // should not happen
{
QgsMessageLog::logMessage( tr( "unexpected image size" ), tr( "WMS" ) );
return;
}

uchar * ptr = image->bits() ;
memcpy( block, ptr, myExpectedSize );
if ( ptr )
{
// If image is too large, ptr can be NULL
memcpy( block, ptr, myExpectedSize );
}
// do not delete the image, it is handled by draw()
//delete image;
}
Expand Down
30 changes: 18 additions & 12 deletions src/ui/qgslabelingguibase.ui
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@
<number>20</number>
</property>
<item row="5" column="0">
<widget class="QGroupBox" name="groupBox_2">
<widget class="QgsCollapsibleGroupBox" name="mFontMultiLineGroupBox">
<property name="minimumSize">
<size>
<width>0</width>
Expand Down Expand Up @@ -586,7 +586,7 @@
</widget>
</item>
<item row="2" column="0">
<widget class="QGroupBox" name="groupBox_6">
<widget class="QgsCollapsibleGroupBox" name="mFontStyleGroupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
Expand Down Expand Up @@ -1058,7 +1058,7 @@
</widget>
</item>
<item row="4" column="0">
<widget class="QGroupBox" name="chkBuffer">
<widget class="QgsCollapsibleGroupBox" name="chkBuffer">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
Expand Down Expand Up @@ -1296,7 +1296,7 @@
</widget>
</item>
<item row="7" column="0">
<widget class="QGroupBox" name="chkScaleBasedVisibility">
<widget class="QgsCollapsibleGroupBox" name="chkScaleBasedVisibility">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
Expand Down Expand Up @@ -1375,7 +1375,7 @@
</spacer>
</item>
<item row="6" column="0">
<widget class="QGroupBox" name="chkFormattedNumbers">
<widget class="QgsCollapsibleGroupBox" name="chkFormattedNumbers">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
Expand Down Expand Up @@ -1478,7 +1478,7 @@
<number>6</number>
</property>
<item row="2" column="0">
<widget class="QGroupBox" name="groupBox">
<widget class="QgsCollapsibleGroupBox" name="mOptionsGroupBox">
<property name="maximumSize">
<size>
<width>16777215</width>
Expand Down Expand Up @@ -1579,7 +1579,7 @@
</widget>
</item>
<item row="1" column="0">
<widget class="QGroupBox" name="groupBox_7">
<widget class="QgsCollapsibleGroupBox" name="mPriorityGroupBox">
<property name="maximumSize">
<size>
<width>16777215</width>
Expand Down Expand Up @@ -1627,7 +1627,7 @@
</widget>
</item>
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox_5">
<widget class="QgsCollapsibleGroupBox" name="mPlacementGroupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
Expand Down Expand Up @@ -2281,7 +2281,7 @@
<number>6</number>
</property>
<item row="3" column="0">
<widget class="QGroupBox" name="mBufferAttributesPropertiesGroupBox">
<widget class="QgsCollapsibleGroupBox" name="mBufferAttributesPropertiesGroupBox">
<property name="title">
<string>Buffer properties</string>
</property>
Expand Down Expand Up @@ -2327,7 +2327,7 @@
</widget>
</item>
<item row="4" column="0">
<widget class="QGroupBox" name="mPositionAttributeGroupBox">
<widget class="QgsCollapsibleGroupBox" name="mPositionAttributeGroupBox">
<property name="title">
<string>Position</string>
</property>
Expand Down Expand Up @@ -2425,7 +2425,7 @@
</spacer>
</item>
<item row="1" column="0">
<widget class="QGroupBox" name="mDisplayAttributesPropertiesGroupBox">
<widget class="QgsCollapsibleGroupBox" name="mDisplayAttributesPropertiesGroupBox">
<property name="title">
<string>Display properties</string>
</property>
Expand Down Expand Up @@ -2479,7 +2479,7 @@
</widget>
</item>
<item row="2" column="0">
<widget class="QGroupBox" name="mFontAttributePropertiesGroupBox">
<widget class="QgsCollapsibleGroupBox" name="mFontAttributePropertiesGroupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
Expand Down Expand Up @@ -2707,6 +2707,12 @@
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
<customwidget>
<class>QgsCollapsibleGroupBox</class>
<extends>QGroupBox</extends>
<header>qgscollapsiblegroupbox.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>QgsColorButton</class>
<extends>QToolButton</extends>
Expand Down
330 changes: 172 additions & 158 deletions src/ui/qgsrasterlayersaveasdialogbase.ui
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,160 @@
<string>Save raster layer as...</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="QLabel" name="mModeLabel">
<property name="text">
<string>Output mode</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="mRawModeRadioButton">
<property name="toolTip">
<string>Write out raw raster layer data. Optionally user defined no data values may be applied.</string>
</property>
<property name="text">
<string>Raw data</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="mRenderedModeRadioButton">
<property name="toolTip">
<string>Write out 3 bands RGB image rendered using current layer style.</string>
</property>
<property name="text">
<string>Rendered image</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="mFormatLabel">
<property name="text">
<string>Format</string>
</property>
<property name="buddy">
<cstring>mFormatComboBox</cstring>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="mFormatComboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="mSaveAsLabel">
<property name="text">
<string>Save as</string>
</property>
<property name="buddy">
<cstring>mSaveAsLineEdit</cstring>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="mSaveAsLineEdit">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="mBrowseButton">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>Browse...</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="label_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>CRS</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="mCrsComboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="mChangeCrsPushButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Change ...</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QScrollArea" name="mScrollArea">
<property name="frameShape">
Expand All @@ -30,165 +184,26 @@
<rect>
<x>0</x>
<y>0</y>
<width>550</width>
<height>738</height>
<width>536</width>
<height>779</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="QLabel" name="mModeLabel">
<property name="text">
<string>Output mode</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="mRawModeRadioButton">
<property name="toolTip">
<string>Write out raw raster layer data. Optionally user defined no data values may be applied.</string>
</property>
<property name="text">
<string>Raw data</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="mRenderedModeRadioButton">
<property name="toolTip">
<string>Write out 3 bands RGB image rendered using current layer style.</string>
</property>
<property name="text">
<string>Rendered image</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="mFormatLabel">
<property name="text">
<string>Format</string>
</property>
<property name="buddy">
<cstring>mFormatComboBox</cstring>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="mFormatComboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="mSaveAsLabel">
<property name="text">
<string>Save as</string>
</property>
<property name="buddy">
<cstring>mSaveAsLineEdit</cstring>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="mSaveAsLineEdit">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="mBrowseButton">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>Browse...</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="label_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>CRS</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="mCrsComboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="mChangeCrsPushButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Change ...</string>
</property>
</widget>
</item>
</layout>
</item>
<property name="spacing">
<number>18</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QgsCollapsibleGroupBox" name="mExtentGroupBox">
<property name="sizePolicy">
Expand Down Expand Up @@ -640,8 +655,7 @@
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="3" column="0">
<widget class="QgsRasterPyramidsOptionsWidget" name="mPyramidsOptionsWidget" native="true">
</widget>
<widget class="QgsRasterPyramidsOptionsWidget" name="mPyramidsOptionsWidget" native="true"/>
</item>
<item row="2" column="0">
<widget class="Line" name="line">
Expand Down
1 change: 1 addition & 0 deletions tests/src/gui/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -118,4 +118,5 @@ ADD_QGIS_TEST(zoomtest testqgsmaptoolzoom.cpp)
#ADD_EXECUTABLE(qgis_rendererv2gui ${rendererv2gui_SRCS} ${rendererv2gui_MOC_SRCS})

ADD_QGIS_TEST(histogramtest testqgsrasterhistogram.cpp)
ADD_QGIS_TEST(projectionissues testprojectionissues.cpp)

105 changes: 105 additions & 0 deletions tests/src/gui/testprojectionissues.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/***************************************************************************
testprojectionissues.cpp
---------------------------
begin : September 2012
copyright : (C) 2012 by Magnus Homann
email : magnus at homann dot se
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include "qgsapplication.h"
#include "qgsmapcanvas.h"
#include "qgsmaplayerregistry.h"
#include "qgsmaprenderer.h"
#include "qgsmultibandcolorrenderer.h"
#include "qgsrasterlayer.h"
#include <QObject>
#include <QtTest>

class TestProjectionIssues: public QObject
{
Q_OBJECT;
private slots:
void initTestCase();// will be called before the first testfunction is executed.
void cleanupTestCase();// will be called after the last testfunction was executed.
void init();// will be called before each testfunction is executed.
void cleanup();// will be called after every testfunction.
void issue5895();// test for #5895
private:
QgsRasterLayer* mRasterLayer;
QgsMapCanvas* mMapCanvas;
};

void TestProjectionIssues::initTestCase()
{
QgsApplication::init();
QgsApplication::initQgis();

//create maplayer from testdata and add to layer registry
QFileInfo rasterFileInfo( QString( TEST_DATA_DIR ) + QDir::separator() + "checker360by180.asc" );
mRasterLayer = new QgsRasterLayer( rasterFileInfo.filePath(),
rasterFileInfo.completeBaseName() );
// Set to WGS84
QgsCoordinateReferenceSystem sourceCRS;
sourceCRS.createFromId( 4326, QgsCoordinateReferenceSystem::EpsgCrsId );
mRasterLayer->setCrs( sourceCRS, false);

QgsMultiBandColorRenderer* rasterRenderer = new QgsMultiBandColorRenderer( mRasterLayer->dataProvider(), 2, 3, 4 );
mRasterLayer->setRenderer( rasterRenderer );

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

// Add all layers in registry to the canvas
QList<QgsMapCanvasLayer> canvasLayers;
foreach ( QgsMapLayer* layer, QgsMapLayerRegistry::instance()->mapLayers().values() )
{
canvasLayers.append( QgsMapCanvasLayer( layer ) );
}

// create canvas
mMapCanvas = new QgsMapCanvas();
mMapCanvas->setLayerSet( canvasLayers );

//reproject to SWEDREF 99 TM
QgsCoordinateReferenceSystem destCRS;
destCRS.createFromId( 3006, QgsCoordinateReferenceSystem::EpsgCrsId );
mMapCanvas->mapRenderer()->setDestinationCrs( destCRS );
mMapCanvas->mapRenderer()->setProjectionsEnabled( true );

};

void TestProjectionIssues::cleanupTestCase()
{
delete mMapCanvas;
delete mRasterLayer;
};

void TestProjectionIssues::init()
{

};

void TestProjectionIssues::cleanup()
{

};

void TestProjectionIssues::issue5895()
{
QgsRectangle largeExtent( -610861, 5101721, 2523921, 6795055 );
mMapCanvas->setExtent( largeExtent );
mMapCanvas->zoomByFactor( 2.0 ); // Zoom out. This should exceed the transform limits.
};

QTEST_MAIN( TestProjectionIssues )
#include "moc_testprojectionissues.cxx"
Loading