mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-12 00:06:43 -04:00
[FEATURE] Add diagram system that uses the same pal instance as labeling-ng
git-svn-id: http://svn.osgeo.org/qgis/trunk@15503 c8812cc2-4d05-0410-92ff-de0c093fc19c
This commit is contained in:
parent
393e206e2d
commit
c3ac6df9ee
160
python/core/qgsdiagramrendererv2.sip
Normal file
160
python/core/qgsdiagramrendererv2.sip
Normal file
@ -0,0 +1,160 @@
|
||||
struct QgsDiagramLayerSettings
|
||||
{
|
||||
%TypeHeaderCode
|
||||
#include <qgsdiagramrendererv2.h>
|
||||
%End
|
||||
|
||||
//avoid inclusion of QgsPalLabeling
|
||||
enum Placement
|
||||
{
|
||||
AroundPoint, // Point / Polygon
|
||||
OverPoint, // Point / Polygon
|
||||
Line, // Line / Polygon
|
||||
Curved, // Line
|
||||
Horizontal, // Polygon
|
||||
Free // Polygon
|
||||
};
|
||||
|
||||
enum LinePlacementFlags
|
||||
{
|
||||
OnLine = 1,
|
||||
AboveLine = 2,
|
||||
BelowLine = 4,
|
||||
MapOrientation = 8
|
||||
};
|
||||
|
||||
QgsDiagramLayerSettings();
|
||||
|
||||
//pal placement properties
|
||||
Placement placement;
|
||||
LinePlacementFlags placementFlags;
|
||||
int priority; // 0 = low, 10 = high
|
||||
bool obstacle; // whether it's an obstacle
|
||||
double dist; // distance from the feature (in mm)
|
||||
QgsDiagramRendererV2* renderer;
|
||||
int xPosColumn; //attribute index for x coordinate (or -1 if position not data defined)
|
||||
int yPosColumn;//attribute index for y coordinate (or -1 if position not data defined)
|
||||
|
||||
void readXML( const QDomElement& elem );
|
||||
void writeXML( QDomElement& layerElem, QDomDocument& doc ) const;
|
||||
};
|
||||
|
||||
//diagram settings for rendering
|
||||
struct QgsDiagramSettings
|
||||
{
|
||||
%TypeHeaderCode
|
||||
#include <qgsdiagramrendererv2.h>
|
||||
%End
|
||||
enum SizeType
|
||||
{
|
||||
MM,
|
||||
MapUnits
|
||||
};
|
||||
|
||||
QgsDiagramSettings();
|
||||
QFont font;
|
||||
QList< QColor > categoryColors;
|
||||
QList< int > categoryIndices;
|
||||
QSizeF size; //size
|
||||
SizeType sizeType; //mm or map units
|
||||
QColor backgroundColor;
|
||||
QColor penColor;
|
||||
double penWidth;
|
||||
|
||||
//scale range (-1 if no lower / upper bound )
|
||||
double minScaleDenominator;
|
||||
double maxScaleDenominator;
|
||||
|
||||
void readXML( const QDomElement& elem );
|
||||
void writeXML( QDomElement& rendererElem, QDomDocument& doc ) const;
|
||||
};
|
||||
|
||||
/**Returns diagram settings for a feature*/
|
||||
class QgsDiagramRendererV2
|
||||
{
|
||||
%TypeHeaderCode
|
||||
#include <qgsdiagramrendererv2.h>
|
||||
%End
|
||||
public:
|
||||
|
||||
QgsDiagramRendererV2();
|
||||
virtual ~QgsDiagramRendererV2();
|
||||
|
||||
/**Returns size of the diagram for feature f in map units. Returns an invalid QSizeF in case of error*/
|
||||
virtual QSizeF sizeMapUnits( const QgsAttributeMap& attributes, const QgsRenderContext& c );
|
||||
|
||||
virtual QString rendererName() const = 0;
|
||||
|
||||
/**Returns attribute indices needed for diagram rendering*/
|
||||
virtual QList<int> diagramAttributes() const = 0;
|
||||
|
||||
void renderDiagram( const QgsAttributeMap& att, QgsRenderContext& c, const QPointF& pos );
|
||||
|
||||
void setDiagram( QgsDiagram* d );
|
||||
const QgsDiagram* diagram() const;
|
||||
|
||||
/**Returns list with all diagram settings in the renderer*/
|
||||
virtual QList<QgsDiagramSettings> diagramSettings() const = 0;
|
||||
|
||||
virtual void readXML( const QDomElement& elem ) = 0;
|
||||
virtual void writeXML( QDomElement& layerElem, QDomDocument& doc ) const = 0;
|
||||
};
|
||||
|
||||
/**Renders the diagrams for all features with the same settings*/
|
||||
class QgsSingleCategoryDiagramRenderer: QgsDiagramRendererV2
|
||||
{
|
||||
%TypeHeaderCode
|
||||
#include <qgsdiagramrendererv2.h>
|
||||
%End
|
||||
public:
|
||||
QgsSingleCategoryDiagramRenderer();
|
||||
~QgsSingleCategoryDiagramRenderer();
|
||||
|
||||
QString rendererName() const;
|
||||
|
||||
QList<int> diagramAttributes() const;
|
||||
|
||||
void setDiagramSettings( const QgsDiagramSettings& s );
|
||||
|
||||
QList<QgsDiagramSettings> diagramSettings() const;
|
||||
|
||||
void readXML( const QDomElement& elem );
|
||||
void writeXML( QDomElement& layerElem, QDomDocument& doc ) const;
|
||||
};
|
||||
|
||||
class QgsLinearlyInterpolatedDiagramRenderer: QgsDiagramRendererV2
|
||||
{
|
||||
%TypeHeaderCode
|
||||
#include <qgsdiagramrendererv2.h>
|
||||
%End
|
||||
public:
|
||||
QgsLinearlyInterpolatedDiagramRenderer();
|
||||
~QgsLinearlyInterpolatedDiagramRenderer();
|
||||
|
||||
/**Returns list with all diagram settings in the renderer*/
|
||||
QList<QgsDiagramSettings> diagramSettings() const;
|
||||
|
||||
void setDiagramSettings( const QgsDiagramSettings& s );
|
||||
|
||||
QList<int> diagramAttributes() const;
|
||||
|
||||
QString rendererName() const;
|
||||
|
||||
void setLowerValue( double val );
|
||||
double lowerValue() const;
|
||||
|
||||
void setUpperValue( double val );
|
||||
double upperValue() const;
|
||||
|
||||
void setLowerSize( QSizeF s );
|
||||
QSizeF lowerSize() const;
|
||||
|
||||
void setUpperSize( QSizeF s );
|
||||
QSizeF upperSize() const;
|
||||
|
||||
int classificationAttribute() const;
|
||||
void setClassificationAttribute( int index );
|
||||
|
||||
void readXML( const QDomElement& elem );
|
||||
void writeXML( QDomElement& layerElem, QDomDocument& doc ) const;
|
||||
};
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "qgsinterpolator.h"
|
||||
#include "qgsvectordataprovider.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
#include "qgsgeometry.h"
|
||||
|
||||
QgsInterpolator::QgsInterpolator( const QList<LayerData>& layerData ): mDataIsCached( false ), mLayerData( layerData )
|
||||
|
@ -5663,14 +5663,17 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer* layer )
|
||||
for ( QMap<QString, QgsMapLayer*>::iterator it = layers.begin(); it != layers.end(); it++ )
|
||||
{
|
||||
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( it.value() );
|
||||
if ( !vlayer || !vlayer->isEditable() || vlayer->customProperty( "labeling" ).toString() != QString( "pal" ) )
|
||||
if ( !vlayer || !vlayer->isEditable() ||
|
||||
( !vlayer->diagramRenderer() && vlayer->customProperty( "labeling" ).toString() != QString( "pal" ) ) )
|
||||
continue;
|
||||
|
||||
int colX, colY, colAng;
|
||||
enableMove =
|
||||
enableMove ||
|
||||
( qobject_cast<QgsMapToolMoveLabel*>( mMapTools.mMoveLabel ) &&
|
||||
qobject_cast<QgsMapToolMoveLabel*>( mMapTools.mMoveLabel )->layerIsMoveable( vlayer, colX, colY ) );
|
||||
( qobject_cast<QgsMapToolMoveLabel*>( mMapTools.mMoveLabel )->labelMoveable( vlayer, colX, colY )
|
||||
|| qobject_cast<QgsMapToolMoveLabel*>( mMapTools.mMoveLabel )->diagramMoveable( vlayer, colX, colY ) )
|
||||
);
|
||||
|
||||
enableRotate =
|
||||
enableRotate ||
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "qgslabelpropertydialog.h"
|
||||
#include "qgsmaplayerregistry.h"
|
||||
#include "qgsmaprenderer.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
#include <QColorDialog>
|
||||
#include <QFontDialog>
|
||||
|
||||
|
@ -280,6 +280,14 @@ bool QgsMapToolLabel::rotationPoint( QgsPoint& pos )
|
||||
pos = mCurrentLabelPos.cornerPoints.at( 0 );
|
||||
}
|
||||
|
||||
//alignment always center/center and rotation 0 for diagrams
|
||||
if ( mCurrentLabelPos.isDiagram )
|
||||
{
|
||||
pos.setX( pos.x() + mCurrentLabelPos.labelRect.width() / 2.0 );
|
||||
pos.setY( pos.y() + mCurrentLabelPos.labelRect.height() / 2.0 );
|
||||
return true;
|
||||
}
|
||||
|
||||
//adapt pos depending on data defined alignment
|
||||
QString haliString, valiString;
|
||||
currentAlignment( haliString, valiString );
|
||||
@ -356,7 +364,14 @@ bool QgsMapToolLabel::dataDefinedPosition( QgsVectorLayer* vlayer, int featureId
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !layerIsMoveable( vlayer, xCol, yCol ) )
|
||||
if ( mCurrentLabelPos.isDiagram )
|
||||
{
|
||||
if ( !diagramMoveable( vlayer, xCol, yCol ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if ( !labelMoveable( vlayer, xCol, yCol ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -374,7 +389,23 @@ bool QgsMapToolLabel::dataDefinedPosition( QgsVectorLayer* vlayer, int featureId
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QgsMapToolLabel::layerIsMoveable( const QgsMapLayer* ml, int& xCol, int& yCol ) const
|
||||
bool QgsMapToolLabel:: diagramMoveable( const QgsMapLayer* ml, int& xCol, int& yCol ) const
|
||||
{
|
||||
const QgsVectorLayer* vlayer = dynamic_cast<const QgsVectorLayer*>( ml );
|
||||
if ( vlayer && vlayer->diagramRenderer() )
|
||||
{
|
||||
QgsDiagramLayerSettings dls = vlayer->diagramLayerSettings();
|
||||
if ( dls.xPosColumn >= 0 && dls.yPosColumn >= 0 )
|
||||
{
|
||||
xCol = dls.xPosColumn;
|
||||
yCol = dls.yPosColumn;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QgsMapToolLabel::labelMoveable( const QgsMapLayer* ml, int& xCol, int& yCol ) const
|
||||
{
|
||||
const QgsVectorLayer* vlayer = dynamic_cast<const QgsVectorLayer*>( ml );
|
||||
if ( !vlayer || !vlayer->isEditable() )
|
||||
|
@ -31,11 +31,16 @@ class QgsMapToolLabel: public QgsMapTool
|
||||
QgsMapToolLabel( QgsMapCanvas* canvas );
|
||||
~QgsMapToolLabel();
|
||||
|
||||
/**Returns true if layer move can be applied to a layer
|
||||
/**Returns true if label move can be applied to a layer
|
||||
@param xCol out: index of the attribute for data defined x coordinate
|
||||
@param yCol out: index of the attribute for data defined y coordinate
|
||||
@return true if labels of layer can be moved*/
|
||||
bool layerIsMoveable( const QgsMapLayer* ml, int& xCol, int& yCol ) const;
|
||||
bool labelMoveable( const QgsMapLayer* ml, int& xCol, int& yCol ) const;
|
||||
/**Returns true if diagram move can be applied to a layer
|
||||
@param xCol out: index of the attribute for data defined x coordinate
|
||||
@param yCol out: index of the attribute for data defined y coordinate
|
||||
@return true if labels of layer can be moved*/
|
||||
bool diagramMoveable( const QgsMapLayer* ml, int& xCol, int& yCol ) const;
|
||||
|
||||
protected:
|
||||
QgsRubberBand* mLabelRubberBand;
|
||||
|
@ -40,13 +40,13 @@ void QgsMapToolMoveLabel::canvasPressEvent( QMouseEvent * e )
|
||||
}
|
||||
|
||||
QgsMapLayer* layer = QgsMapLayerRegistry::instance()->mapLayer( mCurrentLabelPos.layerID );
|
||||
if ( !layer )
|
||||
if ( !layer || !layer->isEditable() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int xCol, yCol;
|
||||
if ( layerIsMoveable( layer, xCol, yCol ) )
|
||||
if ( labelMoveable( layer, xCol, yCol ) || diagramMoveable( layer, xCol, yCol ) )
|
||||
{
|
||||
mStartPointMapCoords = toMapCoordinates( e->pos() );
|
||||
mClickOffsetX = mStartPointMapCoords.x() - mCurrentLabelPos.labelRect.xMinimum();
|
||||
|
@ -28,6 +28,8 @@
|
||||
#include "qgscontexthelp.h"
|
||||
#include "qgscontinuouscolordialog.h"
|
||||
#include "qgscoordinatetransform.h"
|
||||
#include "qgsdiagram.h"
|
||||
#include "qgsdiagramrendererv2.h"
|
||||
#include "qgsfieldcalculator.h"
|
||||
#include "qgsgraduatedsymboldialog.h"
|
||||
#include "qgslabeldialog.h"
|
||||
@ -53,10 +55,12 @@
|
||||
#include <QFile>
|
||||
#include <QFileDialog>
|
||||
#include <QFileInfo>
|
||||
#include <QFontDialog>
|
||||
#include <QSettings>
|
||||
#include <QComboBox>
|
||||
#include <QCheckBox>
|
||||
#include <QHeaderView>
|
||||
#include <QColorDialog>
|
||||
|
||||
#include "qgsrendererv2propertiesdialog.h"
|
||||
#include "qgsstylev2.h"
|
||||
@ -142,6 +146,8 @@ QgsVectorLayerProperties::QgsVectorLayerProperties(
|
||||
addJoinToTreeWidget( joins[i] );
|
||||
}
|
||||
|
||||
initDiagramTab();
|
||||
|
||||
//for each overlay plugin create a new tab
|
||||
int position;
|
||||
QList<QgsVectorOverlayPlugin*> overlayPluginList = overlayPlugins();
|
||||
@ -678,6 +684,92 @@ void QgsVectorLayerProperties::apply()
|
||||
|
||||
}
|
||||
|
||||
//apply diagram settings
|
||||
if ( !mDisplayDiagramsCheckBox->isChecked() )
|
||||
{
|
||||
layer->setDiagramRenderer( 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsDiagram* diagram = 0;
|
||||
if ( mDiagramTypeComboBox->currentText() == tr( "Text diagram" ) )
|
||||
{
|
||||
diagram = new QgsTextDiagram();
|
||||
}
|
||||
else if ( mDiagramTypeComboBox->currentText() == tr( "Pie chart" ) )
|
||||
{
|
||||
diagram = new QgsPieDiagram();
|
||||
}
|
||||
|
||||
QgsDiagramSettings ds;
|
||||
ds.font = mDiagramFont;
|
||||
QList<QColor> categoryColors;
|
||||
QList<int> categoryAttributes;
|
||||
for ( int i = 0; i < mDiagramAttributesTreeWidget->topLevelItemCount(); ++i )
|
||||
{
|
||||
categoryColors.append( mDiagramAttributesTreeWidget->topLevelItem( i )->background( 1 ).color() );
|
||||
categoryAttributes.append( mDiagramAttributesTreeWidget->topLevelItem( i )->data( 0, Qt::UserRole ).toInt() );
|
||||
}
|
||||
ds.categoryColors = categoryColors;
|
||||
ds.categoryIndices = categoryAttributes;
|
||||
ds.size = QSizeF( mDiagramSizeSpinBox->value(), mDiagramSizeSpinBox->value() );
|
||||
if ( mDiagramUnitComboBox->currentText() == tr( "Map units" ) )
|
||||
{
|
||||
ds.sizeType = QgsDiagramSettings::MapUnits;
|
||||
}
|
||||
else
|
||||
{
|
||||
ds.sizeType = QgsDiagramSettings::MM;
|
||||
}
|
||||
ds.backgroundColor = mBackgroundColorButton->color();
|
||||
ds.penColor = mDiagramPenColorButton->color();
|
||||
ds.penWidth = mPenWidthSpinBox->value();
|
||||
if ( mScaleDependentDiagramVisibilityCheckBox->isChecked() )
|
||||
{
|
||||
ds.minScaleDenominator = mMinimumDiagramScaleLineEdit->text().toDouble();
|
||||
ds.maxScaleDenominator = mMaximumDiagramScaleLineEdit->text().toDouble();
|
||||
}
|
||||
else
|
||||
{
|
||||
ds.minScaleDenominator = -1;
|
||||
ds.maxScaleDenominator = -1;
|
||||
}
|
||||
|
||||
QgsDiagramRendererV2* r = 0;
|
||||
if ( mFixedSizeCheckBox->isChecked() )
|
||||
{
|
||||
QgsSingleCategoryDiagramRenderer* dr = new QgsSingleCategoryDiagramRenderer();
|
||||
dr->setDiagram( diagram );
|
||||
dr->setDiagramSettings( ds );
|
||||
layer->setDiagramRenderer( dr );
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsLinearlyInterpolatedDiagramRenderer* dr = new QgsLinearlyInterpolatedDiagramRenderer();
|
||||
dr->setLowerValue( 0.0 );
|
||||
dr->setLowerSize( QSizeF( 0.0, 0.0 ) );
|
||||
dr->setUpperValue( mValueLineEdit->text().toDouble() );
|
||||
dr->setUpperSize( QSizeF( mSizeSpinBox->value(), mSizeSpinBox->value() ) );
|
||||
dr->setClassificationAttribute( mSizeAttributeComboBox->itemData( mSizeAttributeComboBox->currentIndex() ).toInt() );
|
||||
dr->setDiagram( diagram );
|
||||
dr->setDiagramSettings( ds );
|
||||
layer->setDiagramRenderer( dr );
|
||||
}
|
||||
|
||||
QgsDiagramLayerSettings dls;
|
||||
dls.dist = mDiagramDistanceSpinBox->value();
|
||||
dls.priority = mPrioritySlider->value();
|
||||
dls.xPosColumn = mDataDefinedXComboBox->itemData( mDataDefinedXComboBox->currentIndex() ).toInt();
|
||||
dls.yPosColumn = mDataDefinedYComboBox->itemData( mDataDefinedYComboBox->currentIndex() ).toInt();
|
||||
dls.placement = ( QgsDiagramLayerSettings::Placement )mPlacementComboBox->itemData( mPlacementComboBox->currentIndex() ).toInt();
|
||||
if ( mLineOptionsComboBox->isEnabled() )
|
||||
{
|
||||
dls.placementFlags = ( QgsDiagramLayerSettings::LinePlacementFlags )mLineOptionsComboBox->itemData( mLineOptionsComboBox->currentIndex() ).toInt();
|
||||
}
|
||||
layer->setDiagramLayerSettings( dls );
|
||||
}
|
||||
|
||||
|
||||
//apply overlay dialogs
|
||||
for ( QList<QgsApplyDialog*>::iterator it = mOverlayDialogs.begin(); it != mOverlayDialogs.end(); ++it )
|
||||
{
|
||||
@ -1243,6 +1335,18 @@ void QgsVectorLayerProperties::on_mButtonRemoveJoin_clicked()
|
||||
mJoinTreeWidget->takeTopLevelItem( mJoinTreeWidget->indexOfTopLevelItem( currentJoinItem ) );
|
||||
}
|
||||
|
||||
void QgsVectorLayerProperties::handleDiagramItemDoubleClick( QTreeWidgetItem * item, int column )
|
||||
{
|
||||
if ( column == 1 ) //change color
|
||||
{
|
||||
QColor newColor = QColorDialog::getColor();
|
||||
if ( newColor.isValid() )
|
||||
{
|
||||
item->setBackground( 1, QBrush( newColor ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QgsVectorLayerProperties::useNewSymbology()
|
||||
{
|
||||
int res = QMessageBox::question( this, tr( "Symbology" ),
|
||||
@ -1338,3 +1442,271 @@ void QgsVectorLayerProperties::enableLabelOptions( bool theFlag )
|
||||
{
|
||||
labelOptionsFrame->setEnabled( theFlag );
|
||||
}
|
||||
|
||||
void QgsVectorLayerProperties::on_mAddCategoryPushButton_clicked()
|
||||
{
|
||||
QTreeWidgetItem *newItem = new QTreeWidgetItem( mDiagramAttributesTreeWidget );
|
||||
newItem->setText( 0, mDiagramAttributesComboBox->currentText() );
|
||||
newItem->setData( 0, Qt::UserRole, mDiagramAttributesComboBox->itemData( mDiagramAttributesComboBox->currentIndex() ) );
|
||||
|
||||
//set initial color for diagram category
|
||||
int red = 1 + ( int )( 255.0 * rand() / ( RAND_MAX + 1.0 ) );
|
||||
int green = 1 + ( int )( 255.0 * rand() / ( RAND_MAX + 1.0 ) );
|
||||
int blue = 1 + ( int )( 255.0 * rand() / ( RAND_MAX + 1.0 ) );
|
||||
QColor randomColor( red, green, blue );
|
||||
newItem->setBackground( 1, QBrush( randomColor ) );
|
||||
mDiagramAttributesTreeWidget->addTopLevelItem( newItem );
|
||||
}
|
||||
|
||||
void QgsVectorLayerProperties::on_mRemoveCategoryPushButton_clicked()
|
||||
{
|
||||
QTreeWidgetItem* currentItem = mDiagramAttributesTreeWidget->currentItem();
|
||||
if ( currentItem )
|
||||
{
|
||||
delete currentItem;
|
||||
}
|
||||
}
|
||||
|
||||
void QgsVectorLayerProperties::on_mDiagramFontButton_clicked()
|
||||
{
|
||||
bool ok;
|
||||
mDiagramFont = QFontDialog::getFont( &ok, mDiagramFont );
|
||||
}
|
||||
|
||||
void QgsVectorLayerProperties::on_mFixedSizeCheckBox_stateChanged( int state )
|
||||
{
|
||||
mDiagramSizeSpinBox->setEnabled( state == Qt::Checked );
|
||||
|
||||
//enable / disable all widget in the scaling layout
|
||||
mLinearlyScalingLabel->setEnabled( state != Qt::Checked );
|
||||
QWidget* currentWidget = 0;
|
||||
for ( int i = 0; i < mLinearlyScalingLayout->count(); ++i )
|
||||
{
|
||||
currentWidget = mLinearlyScalingLayout->itemAt( i )->widget();
|
||||
if ( currentWidget )
|
||||
{
|
||||
currentWidget->setEnabled( state != Qt::Checked );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QgsVectorLayerProperties::on_mScaleDependentDiagramVisibilityCheckBox_stateChanged( int state )
|
||||
{
|
||||
mMinimumDiagramScaleLabel->setEnabled( state == Qt::Checked );
|
||||
mMinimumDiagramScaleLineEdit->setEnabled( state == Qt::Checked );
|
||||
mMaximumDiagramScaleLabel->setEnabled( state == Qt::Checked );
|
||||
mMaximumDiagramScaleLineEdit->setEnabled( state == Qt::Checked );
|
||||
}
|
||||
|
||||
void QgsVectorLayerProperties::on_mFindMaximumValueButton_clicked()
|
||||
{
|
||||
//get maximum value from provider (ignoring not-commited edits)
|
||||
if ( layer )
|
||||
{
|
||||
QgsVectorDataProvider* provider = layer->dataProvider();
|
||||
if ( provider )
|
||||
{
|
||||
mValueLineEdit->setText( provider->maximumValue( mSizeAttributeComboBox->itemData( mSizeAttributeComboBox->currentIndex() ).toInt() ).toString() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QgsVectorLayerProperties::on_mBackgroundColorButton_clicked()
|
||||
{
|
||||
QColor newColor = QColorDialog::getColor( mBackgroundColorButton->color(), 0, tr( "Background color" ), QColorDialog::ShowAlphaChannel );
|
||||
if ( newColor.isValid() )
|
||||
{
|
||||
mBackgroundColorButton->setColor( newColor );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsVectorLayerProperties::on_mDiagramPenColorButton_clicked()
|
||||
{
|
||||
QColor newColor = QColorDialog::getColor( mDiagramPenColorButton->color(), 0, tr( "Pen color" ), QColorDialog::ShowAlphaChannel );
|
||||
if ( newColor.isValid() )
|
||||
{
|
||||
mDiagramPenColorButton->setColor( newColor );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsVectorLayerProperties::initDiagramTab()
|
||||
{
|
||||
if ( !layer )
|
||||
{
|
||||
mDiagramPage->setEnabled( false );
|
||||
}
|
||||
|
||||
mValueLineEdit->setValidator( new QDoubleValidator( mValueLineEdit ) );
|
||||
mMinimumDiagramScaleLineEdit->setValidator( new QDoubleValidator( mMinimumDiagramScaleLineEdit ) );
|
||||
mMaximumDiagramScaleLineEdit->setValidator( new QDoubleValidator( mMaximumDiagramScaleLineEdit ) );
|
||||
|
||||
mDiagramUnitComboBox->insertItem( 0, tr( "MM" ) );
|
||||
mDiagramUnitComboBox->insertItem( 1, tr( "Map units" ) );
|
||||
|
||||
QGis::GeometryType layerType = layer->geometryType();
|
||||
if ( layerType == QGis::UnknownGeometry || layerType == QGis::NoGeometry )
|
||||
{
|
||||
mDiagramPage->setEnabled( false );
|
||||
}
|
||||
|
||||
//insert placement options
|
||||
|
||||
if ( layerType == QGis::Point || layerType == QGis::Polygon )
|
||||
{
|
||||
mPlacementComboBox->addItem( tr( "AroundPoint" ), 0 );
|
||||
mPlacementComboBox->addItem( tr( "OverPoint" ), 1 );
|
||||
}
|
||||
|
||||
if ( layerType == QGis::Line || layerType == QGis::Polygon )
|
||||
{
|
||||
mPlacementComboBox->addItem( tr( "Line" ), 2 );
|
||||
mPlacementComboBox->addItem( tr( "Horizontal" ), 3 );
|
||||
}
|
||||
|
||||
if ( layerType == QGis::Polygon )
|
||||
{
|
||||
mPlacementComboBox->addItem( tr( "Free" ), 4 );
|
||||
}
|
||||
|
||||
if ( layerType == QGis::Line )
|
||||
{
|
||||
mLineOptionsComboBox->addItem( tr( "On line" ), 1 );
|
||||
mLineOptionsComboBox->addItem( tr( "Above line" ), 2 );
|
||||
mLineOptionsComboBox->addItem( tr( "Below Line" ), 4 );
|
||||
mLineOptionsComboBox->addItem( tr( "Map orientation" ), 8 );
|
||||
}
|
||||
else
|
||||
{
|
||||
mLineOptionsComboBox->setEnabled( false );
|
||||
}
|
||||
|
||||
mDiagramTypeComboBox->addItem( tr( "Pie chart" ) );
|
||||
mDiagramTypeComboBox->addItem( tr( "Text diagram" ) );
|
||||
|
||||
//insert all attributes into the combo boxes
|
||||
const QgsFieldMap& layerFields = layer->pendingFields();
|
||||
QgsFieldMap::const_iterator fieldIt = layerFields.constBegin();
|
||||
for ( ; fieldIt != layerFields.constEnd(); ++fieldIt )
|
||||
{
|
||||
mDiagramAttributesComboBox->addItem( fieldIt.value().name(), fieldIt.key() );
|
||||
if ( fieldIt.value().type() != QVariant::String )
|
||||
{
|
||||
mSizeAttributeComboBox->addItem( fieldIt.value().name(), fieldIt.key() );
|
||||
}
|
||||
}
|
||||
|
||||
mDataDefinedXComboBox->addItem( tr( "None" ), -1 );
|
||||
for ( fieldIt = layerFields.constBegin(); fieldIt != layerFields.constEnd(); ++fieldIt )
|
||||
{
|
||||
mDataDefinedXComboBox->addItem( fieldIt.value().name(), fieldIt.key() );
|
||||
}
|
||||
mDataDefinedYComboBox->addItem( tr( "None" ), -1 );
|
||||
for ( fieldIt = layerFields.constBegin(); fieldIt != layerFields.constEnd(); ++fieldIt )
|
||||
{
|
||||
mDataDefinedYComboBox->addItem( fieldIt.value().name(), fieldIt.key() );
|
||||
}
|
||||
|
||||
const QgsDiagramRendererV2* dr = layer->diagramRenderer();
|
||||
if ( !dr ) //no diagram renderer yet, insert reasonable default
|
||||
{
|
||||
mDisplayDiagramsCheckBox->setChecked( false );
|
||||
mFixedSizeCheckBox->setChecked( true );
|
||||
mDiagramUnitComboBox->setCurrentIndex( mDiagramUnitComboBox->findText( tr( "MM" ) ) );
|
||||
mDiagramSizeSpinBox->setValue( 30 );
|
||||
mScaleDependentDiagramVisibilityCheckBox->setChecked( false );
|
||||
|
||||
switch ( layerType )
|
||||
{
|
||||
case QGis::Point:
|
||||
mPlacementComboBox->setCurrentIndex( mPlacementComboBox->findData( 0 ) );
|
||||
break;
|
||||
case QGis::Line:
|
||||
mPlacementComboBox->setCurrentIndex( mPlacementComboBox->findData( 3 ) );
|
||||
mLineOptionsComboBox->setCurrentIndex( mLineOptionsComboBox->findData( 2 ) );
|
||||
break;
|
||||
case QGis::Polygon:
|
||||
mPlacementComboBox->setCurrentIndex( mPlacementComboBox->findData( 0 ) );
|
||||
break;
|
||||
}
|
||||
mBackgroundColorButton->setColor( QColor( 255, 255, 255, 255 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
mDisplayDiagramsCheckBox->setChecked( true );
|
||||
|
||||
//single category renderer or interpolated one?
|
||||
mFixedSizeCheckBox->setChecked( dr->rendererName() == "SingleCategory" );
|
||||
|
||||
//assume single category or linearly interpolated diagram renderer for now
|
||||
QList<QgsDiagramSettings> settingList = dr->diagramSettings();
|
||||
if ( settingList.size() > 0 )
|
||||
{
|
||||
mDiagramFont = settingList.at( 0 ).font;
|
||||
QSizeF size = settingList.at( 0 ).size;
|
||||
mBackgroundColorButton->setColor( settingList.at( 0 ).backgroundColor );
|
||||
mDiagramPenColorButton->setColor( settingList.at( 0 ).penColor );
|
||||
mPenWidthSpinBox->setValue( settingList.at( 0 ).penWidth );
|
||||
mDiagramSizeSpinBox->setValue(( size.width() + size.height() ) / 2.0 );
|
||||
mMinimumDiagramScaleLineEdit->setText( QString::number( settingList.at( 0 ).minScaleDenominator ) );
|
||||
mMaximumDiagramScaleLineEdit->setText( QString::number( settingList.at( 0 ).maxScaleDenominator ) );
|
||||
mScaleDependentDiagramVisibilityCheckBox->setChecked( settingList.at( 0 ).minScaleDenominator != -1 &&
|
||||
settingList.at( 0 ).maxScaleDenominator != -1 );
|
||||
if ( settingList.at( 0 ).sizeType == QgsDiagramSettings::MM )
|
||||
{
|
||||
mDiagramUnitComboBox->setCurrentIndex( 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
mDiagramUnitComboBox->setCurrentIndex( 1 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
QList< QColor > categoryColors = settingList.at( 0 ).categoryColors;
|
||||
QList< int > categoryIndices = settingList.at( 0 ).categoryIndices;
|
||||
QList< int >::const_iterator catIt = categoryIndices.constBegin();
|
||||
QList< QColor >::const_iterator coIt = categoryColors.constBegin();
|
||||
for ( ;catIt != categoryIndices.constEnd(); ++catIt, ++coIt )
|
||||
{
|
||||
QTreeWidgetItem *newItem = new QTreeWidgetItem( mDiagramAttributesTreeWidget );
|
||||
newItem->setText( 0, layer->pendingFields()[*catIt].name() );
|
||||
newItem->setData( 0, Qt::UserRole, *catIt );
|
||||
newItem->setBackground( 1, QBrush( *coIt ) );
|
||||
}
|
||||
}
|
||||
|
||||
if ( dr->rendererName() == "LinearlyInterpolated" )
|
||||
{
|
||||
const QgsLinearlyInterpolatedDiagramRenderer* lidr = dynamic_cast<const QgsLinearlyInterpolatedDiagramRenderer*>( dr );
|
||||
if ( lidr )
|
||||
{
|
||||
mDiagramSizeSpinBox->setEnabled( false );
|
||||
mValueLineEdit->setText( QString::number( lidr->upperValue() ) );
|
||||
mSizeSpinBox->setValue(( lidr->upperSize().width() + lidr->upperSize().height() ) / 2 );
|
||||
mSizeAttributeComboBox->setCurrentIndex( mSizeAttributeComboBox->findData( lidr->classificationAttribute() ) );
|
||||
}
|
||||
}
|
||||
|
||||
QgsDiagramLayerSettings dls = layer->diagramLayerSettings();
|
||||
mDiagramDistanceSpinBox->setValue( dls.dist );
|
||||
mPrioritySlider->setValue( dls.priority );
|
||||
mDataDefinedXComboBox->setCurrentIndex( mDataDefinedXComboBox->findData( dls.xPosColumn ) );
|
||||
mDataDefinedYComboBox->setCurrentIndex( mDataDefinedYComboBox->findData( dls.yPosColumn ) );
|
||||
mPlacementComboBox->setCurrentIndex( mPlacementComboBox->findData( dls.placement ) );
|
||||
mLineOptionsComboBox->setCurrentIndex( mLineOptionsComboBox->findData( dls.placementFlags ) );
|
||||
|
||||
if ( dr->diagram() )
|
||||
{
|
||||
QString diagramName = dr->diagram()->diagramName();
|
||||
if ( diagramName == "Text" )
|
||||
{
|
||||
mDiagramTypeComboBox->setCurrentIndex( mDiagramTypeComboBox->findText( tr( "Text diagram" ) ) );
|
||||
}
|
||||
else if ( diagramName == "Pie" )
|
||||
{
|
||||
mDiagramTypeComboBox->setCurrentIndex( mDiagramTypeComboBox->findText( tr( "Pie chart" ) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
QObject::connect( mDiagramAttributesTreeWidget, SIGNAL( itemDoubleClicked( QTreeWidgetItem*, int ) ), this, SLOT( handleDiagramItemDoubleClick( QTreeWidgetItem*, int ) ) );
|
||||
}
|
||||
|
@ -106,6 +106,14 @@ class QgsVectorLayerProperties : public QDialog, private Ui::QgsVectorLayerPrope
|
||||
void on_pbnSelectEditForm_clicked();
|
||||
void on_tabWidget_currentChanged( int idx );
|
||||
void on_buttonBox_helpRequested() { QgsContextHelp::run( metaObject()->className() ); }
|
||||
void on_mAddCategoryPushButton_clicked();
|
||||
void on_mRemoveCategoryPushButton_clicked();
|
||||
void on_mDiagramFontButton_clicked();
|
||||
void on_mFixedSizeCheckBox_stateChanged( int state );
|
||||
void on_mScaleDependentDiagramVisibilityCheckBox_stateChanged( int state );
|
||||
void on_mFindMaximumValueButton_clicked();
|
||||
void on_mBackgroundColorButton_clicked();
|
||||
void on_mDiagramPenColorButton_clicked();
|
||||
|
||||
void enableLabelOptions( bool theFlag );
|
||||
void addAttribute();
|
||||
@ -120,6 +128,9 @@ class QgsVectorLayerProperties : public QDialog, private Ui::QgsVectorLayerPrope
|
||||
void on_mButtonAddJoin_clicked();
|
||||
void on_mButtonRemoveJoin_clicked();
|
||||
|
||||
/**Set color for diagram category*/
|
||||
void handleDiagramItemDoubleClick( QTreeWidgetItem * item, int column );
|
||||
|
||||
signals:
|
||||
|
||||
/** emitted when changes to layer were saved to update legend */
|
||||
@ -164,10 +175,14 @@ class QgsVectorLayerProperties : public QDialog, private Ui::QgsVectorLayerPrope
|
||||
QMap<int, QgsVectorLayer::RangeData> mRanges;
|
||||
QMap<int, QPair<QString, QString> > mCheckedStates;
|
||||
|
||||
QFont mDiagramFont;
|
||||
|
||||
void updateButtons();
|
||||
void loadRows();
|
||||
void setRow( int row, int idx, const QgsField &field );
|
||||
|
||||
void initDiagramTab();
|
||||
|
||||
/**Requests all overlay plugis from the plugin registry. Useful for inserting their dialogs as new tabs*/
|
||||
QList<QgsVectorOverlayPlugin*> overlayPlugins() const;
|
||||
|
||||
|
@ -46,6 +46,8 @@ SET(QGIS_CORE_SRCS
|
||||
qgscontexthelp.cpp
|
||||
qgscoordinatetransform.cpp
|
||||
qgsdatasourceuri.cpp
|
||||
qgsdiagram.cpp
|
||||
qgsdiagramrendererv2.cpp
|
||||
qgsdistancearea.cpp
|
||||
qgsfeature.cpp
|
||||
qgsfield.cpp
|
||||
|
283
src/core/qgsdiagram.cpp
Normal file
283
src/core/qgsdiagram.cpp
Normal file
@ -0,0 +1,283 @@
|
||||
#include "qgsdiagram.h"
|
||||
#include "qgsdiagramrendererv2.h"
|
||||
#include "qgsrendercontext.h"
|
||||
|
||||
#include <QPainter>
|
||||
|
||||
void QgsDiagram::setPenWidth( QPen& pen, const QgsDiagramSettings& s, const QgsRenderContext& c )
|
||||
{
|
||||
if ( s.sizeType == QgsDiagramSettings::MM )
|
||||
{
|
||||
pen.setWidthF( s.penWidth * c.scaleFactor() );
|
||||
}
|
||||
else
|
||||
{
|
||||
pen.setWidthF( s.penWidth / c.mapToPixel().mapUnitsPerPixel() );
|
||||
}
|
||||
}
|
||||
|
||||
QSizeF QgsDiagram::sizePainterUnits( const QSizeF& size, const QgsDiagramSettings& s, const QgsRenderContext& c )
|
||||
{
|
||||
if ( s.sizeType == QgsDiagramSettings::MM )
|
||||
{
|
||||
return QSizeF( s.size.width() * c.scaleFactor(), s.size.height() * c.scaleFactor() );
|
||||
}
|
||||
else
|
||||
{
|
||||
return QSizeF( s.size.width() / c.mapToPixel().mapUnitsPerPixel(), s.size.height() / c.mapToPixel().mapUnitsPerPixel() );
|
||||
}
|
||||
}
|
||||
|
||||
QFont QgsDiagram::scaledFont( const QgsDiagramSettings& s, const QgsRenderContext& c )
|
||||
{
|
||||
QFont f = s.font;
|
||||
if ( s.sizeType == QgsDiagramSettings::MM )
|
||||
{
|
||||
f.setPixelSize( s.font.pointSizeF() * 0.376 * c.scaleFactor() );
|
||||
}
|
||||
else
|
||||
{
|
||||
f.setPixelSize( s.font.pointSizeF() / c.mapToPixel().mapUnitsPerPixel() );
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
QgsTextDiagram::QgsTextDiagram(): mOrientation( Vertical ), mShape( Circle )
|
||||
{
|
||||
mPen.setWidthF( 2.0 );
|
||||
mPen.setColor( QColor( 0, 0, 0 ) );
|
||||
mPen.setCapStyle( Qt::FlatCap );
|
||||
mBrush.setStyle( Qt::SolidPattern );
|
||||
}
|
||||
|
||||
QgsTextDiagram::~QgsTextDiagram()
|
||||
{
|
||||
}
|
||||
|
||||
void QgsTextDiagram::renderDiagram( const QgsAttributeMap& att, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position )
|
||||
{
|
||||
QPainter* p = c.painter();
|
||||
if ( !p )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
double scaleDenominator = c.rendererScale();
|
||||
if (( s.minScaleDenominator != -1 && scaleDenominator < s.minScaleDenominator )
|
||||
|| ( s.maxScaleDenominator != -1 && scaleDenominator > s.maxScaleDenominator ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//convert from mm / map units to painter units
|
||||
QSizeF spu = sizePainterUnits( s.size, s, c );
|
||||
double w = spu.width();
|
||||
double h = spu.height();
|
||||
|
||||
double baseX = position.x();
|
||||
double baseY = position.y() - h;
|
||||
|
||||
QList<QPointF> textPositions; //midpoints for text placement
|
||||
int nCategories = s.categoryIndices.size();
|
||||
for ( int i = 0; i < nCategories; ++i )
|
||||
{
|
||||
if ( mOrientation == Horizontal )
|
||||
{
|
||||
textPositions.push_back( QPointF( baseX + ( w / nCategories ) * i + w / nCategories / 2.0 , baseY + h / 2.0 ) );
|
||||
}
|
||||
else //vertical
|
||||
{
|
||||
textPositions.push_back( QPointF( baseX + w / 2.0, baseY + h / nCategories * i + w / nCategories / 2.0 ) );
|
||||
}
|
||||
}
|
||||
|
||||
mPen.setColor( s.penColor );
|
||||
setPenWidth( mPen, s, c );
|
||||
p->setPen( mPen );
|
||||
mBrush.setColor( s.backgroundColor );
|
||||
p->setBrush( mBrush );
|
||||
|
||||
//draw shapes and separator lines first
|
||||
if ( mShape == Circle )
|
||||
{
|
||||
p->drawEllipse( baseX, baseY, w, h );
|
||||
|
||||
//draw separator lines
|
||||
QList<QPointF> intersect; //intersections between shape and separation lines
|
||||
QPointF center( baseX + w / 2.0, baseY + h / 2.0 );
|
||||
double r1 = w / 2.0; double r2 = h / 2.0;
|
||||
|
||||
for ( int i = 1; i < nCategories; ++i )
|
||||
{
|
||||
if ( mOrientation == Horizontal )
|
||||
{
|
||||
lineEllipseIntersection( QPointF( baseX + w / nCategories * i, baseY ), QPointF( baseX + w / nCategories * i, baseY + h ), center, r1, r2, intersect );
|
||||
}
|
||||
else //vertical
|
||||
{
|
||||
lineEllipseIntersection( QPointF( baseX, baseY + h / nCategories * i ), QPointF( baseX + w, baseY + h / nCategories * i ), center, r1, r2, intersect );
|
||||
}
|
||||
if ( intersect.size() > 1 )
|
||||
{
|
||||
p->drawLine( intersect.at( 0 ), intersect.at( 1 ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( mShape == Rectangle )
|
||||
{
|
||||
p->drawRect( QRectF( baseX, baseY, w, h ) );
|
||||
for ( int i = 1; i < nCategories; ++i )
|
||||
{
|
||||
if ( mOrientation == Horizontal )
|
||||
{
|
||||
p->drawLine( QPointF( baseX + w / nCategories * i , baseY ), QPointF( baseX + w / nCategories * i, baseY + h ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
p->drawLine( QPointF( baseX, baseY + h / nCategories * i ) , QPointF( baseX + w, baseY + h / nCategories * i ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
else //triangle
|
||||
{
|
||||
QPolygonF triangle;
|
||||
triangle << QPointF( baseX, baseY + h ) << QPointF( baseX + w, baseY + h ) << QPointF( baseX + w / 2.0, baseY );
|
||||
p->drawPolygon( triangle );
|
||||
|
||||
QLineF triangleEdgeLeft( baseX + w / 2.0, baseY, baseX, baseY + h );
|
||||
QLineF triangleEdgeRight( baseX + w, baseY + h, baseX + w / 2.0, baseY );
|
||||
QPointF intersectionPoint1, intersectionPoint2;
|
||||
|
||||
for ( int i = 1; i < nCategories; ++i )
|
||||
{
|
||||
if ( mOrientation == Horizontal )
|
||||
{
|
||||
QLineF verticalLine( baseX + w / nCategories * i, baseY + h, baseX + w / nCategories * i, baseY );
|
||||
if ( baseX + w / nCategories * i < baseX + w / 2.0 )
|
||||
{
|
||||
verticalLine.intersect( triangleEdgeLeft, &intersectionPoint1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
verticalLine.intersect( triangleEdgeRight, &intersectionPoint1 );
|
||||
}
|
||||
p->drawLine( QPointF( baseX + w / nCategories * i, baseY + h ), intersectionPoint1 );
|
||||
}
|
||||
else //vertical
|
||||
{
|
||||
QLineF horizontalLine( baseX, baseY + h / nCategories * i, baseX + w, baseY + h / nCategories * i );
|
||||
horizontalLine.intersect( triangleEdgeLeft, &intersectionPoint1 );
|
||||
horizontalLine.intersect( triangleEdgeRight, &intersectionPoint2 );
|
||||
p->drawLine( intersectionPoint1, intersectionPoint2 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//draw text
|
||||
QFont sFont = scaledFont( s, c );
|
||||
QFontMetricsF fontMetrics( sFont );
|
||||
p->setFont( sFont );
|
||||
|
||||
for ( int i = 0; i < textPositions.size(); ++i )
|
||||
{
|
||||
QString val = att[ s.categoryIndices.at( i )].toString();
|
||||
//find out dimensions
|
||||
double textHeight = fontMetrics.height();
|
||||
double textWidth = fontMetrics.width( val );
|
||||
mPen.setColor( s.categoryColors.at( i ) );
|
||||
p->setPen( mPen );
|
||||
QPointF position = textPositions.at( i );
|
||||
p->drawText( QPointF( position.x() - textWidth / 2.0, position.y() + textHeight / 2.0 ), val );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsTextDiagram::lineEllipseIntersection( const QPointF& lineStart, const QPointF& lineEnd, const QPointF& ellipseMid, double r1, double r2, QList<QPointF>& result ) const
|
||||
{
|
||||
result.clear();
|
||||
|
||||
double rrx = r1 * r1;
|
||||
double rry = r2 * r2;
|
||||
double x21 = lineEnd.x() - lineStart.x();
|
||||
double y21 = lineEnd.y() - lineStart.y();
|
||||
double x10 = lineStart.x() - ellipseMid.x();
|
||||
double y10 = lineStart.y() - ellipseMid.y();
|
||||
double a = x21 * x21 / rrx + y21 * y21 / rry;
|
||||
double b = x21 * x10 / rrx + y21 * y10 / rry;
|
||||
double c = x10 * x10 / rrx + y10 * y10 / rry;
|
||||
double d = b * b - a * ( c - 1 );
|
||||
if ( d > 0 )
|
||||
{
|
||||
double e = sqrt( d );
|
||||
double u1 = ( -b - e ) / a;
|
||||
double u2 = ( -b + e ) / a;
|
||||
//work with a tolerance of 0.00001 because of limited numerical precision
|
||||
if ( -0.00001 <= u1 && u1 < 1.00001 )
|
||||
{
|
||||
result.push_back( QPointF( lineStart.x() + x21 * u1, lineStart.y() + y21 * u1 ) );
|
||||
}
|
||||
if ( -0.00001 <= u2 && u2 <= 1.00001 )
|
||||
{
|
||||
result.push_back( QPointF( lineStart.x() + x21 * u2, lineStart.y() + y21 * u2 ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QgsPieDiagram::QgsPieDiagram()
|
||||
{
|
||||
mCategoryBrush.setStyle( Qt::SolidPattern );
|
||||
mPen.setStyle( Qt::SolidLine );
|
||||
}
|
||||
|
||||
QgsPieDiagram::~QgsPieDiagram()
|
||||
{
|
||||
}
|
||||
|
||||
void QgsPieDiagram::renderDiagram( const QgsAttributeMap& att, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position )
|
||||
{
|
||||
QPainter* p = c.painter();
|
||||
if ( !p )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//get sum of values
|
||||
QList<double> values;
|
||||
double currentVal = 0;
|
||||
double valSum = 0;
|
||||
|
||||
QList<int>::const_iterator catIt = s.categoryIndices.constBegin();
|
||||
for ( ; catIt != s.categoryIndices.constEnd(); ++catIt )
|
||||
{
|
||||
currentVal = att[*catIt].toDouble();
|
||||
values.push_back( currentVal );
|
||||
valSum += currentVal;
|
||||
}
|
||||
|
||||
//draw the slices
|
||||
double totalAngle = 0;
|
||||
double currentAngle;
|
||||
|
||||
//convert from mm / map units to painter units
|
||||
QSizeF spu = sizePainterUnits( s.size, s, c );
|
||||
double w = spu.width();
|
||||
double h = spu.height();
|
||||
|
||||
double baseX = position.x();
|
||||
double baseY = position.y() - h;
|
||||
|
||||
mPen.setColor( s.penColor );
|
||||
setPenWidth( mPen, s, c );
|
||||
p->setPen( mPen );
|
||||
|
||||
QList<double>::const_iterator valIt = values.constBegin();
|
||||
QList< QColor >::const_iterator colIt = s.categoryColors.constBegin();
|
||||
for ( ; valIt != values.constEnd(); ++valIt, ++colIt )
|
||||
{
|
||||
currentAngle = *valIt / valSum * 360 * 16;
|
||||
mCategoryBrush.setColor( *colIt );
|
||||
p->setBrush( mCategoryBrush );
|
||||
p->drawPie( baseX, baseY, w, h, totalAngle, currentAngle );
|
||||
totalAngle += currentAngle;
|
||||
}
|
||||
}
|
74
src/core/qgsdiagram.h
Normal file
74
src/core/qgsdiagram.h
Normal file
@ -0,0 +1,74 @@
|
||||
#ifndef QGSDIAGRAM_H
|
||||
#define QGSDIAGRAM_H
|
||||
|
||||
#include "qgsfeature.h"
|
||||
#include <QPen>
|
||||
|
||||
class QPainter;
|
||||
class QPointF;
|
||||
struct QgsDiagramSettings;
|
||||
|
||||
class QgsRenderContext;
|
||||
|
||||
/**Base class for all diagram types*/
|
||||
class QgsDiagram
|
||||
{
|
||||
public:
|
||||
/**Draws the diagram at the given position (in pixel coordinates)*/
|
||||
virtual void renderDiagram( const QgsAttributeMap& att, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position ) = 0;
|
||||
virtual QString diagramName() const = 0;
|
||||
|
||||
protected:
|
||||
void setPenWidth( QPen& pen, const QgsDiagramSettings& s, const QgsRenderContext& c );
|
||||
QSizeF sizePainterUnits( const QSizeF& size, const QgsDiagramSettings& s, const QgsRenderContext& c );
|
||||
QFont scaledFont( const QgsDiagramSettings& s, const QgsRenderContext& c );
|
||||
};
|
||||
|
||||
class QgsTextDiagram: public QgsDiagram
|
||||
{
|
||||
public:
|
||||
enum Shape
|
||||
{
|
||||
Circle = 0,
|
||||
Rectangle,
|
||||
Triangle
|
||||
};
|
||||
|
||||
enum Orientation
|
||||
{
|
||||
Horizontal = 0,
|
||||
Vertical
|
||||
};
|
||||
|
||||
QgsTextDiagram();
|
||||
~QgsTextDiagram();
|
||||
void renderDiagram( const QgsAttributeMap& att, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position );
|
||||
|
||||
QString diagramName() const { return "Text"; }
|
||||
|
||||
private:
|
||||
Orientation mOrientation;
|
||||
Shape mShape;
|
||||
QBrush mBrush; //transparent brush
|
||||
QPen mPen;
|
||||
|
||||
/**Calculates intersection points between a line and an ellipse
|
||||
@return intersection points*/
|
||||
void lineEllipseIntersection( const QPointF& lineStart, const QPointF& lineEnd, const QPointF& ellipseMid, double r1, double r2, QList<QPointF>& result ) const;
|
||||
};
|
||||
|
||||
class QgsPieDiagram: public QgsDiagram
|
||||
{
|
||||
public:
|
||||
QgsPieDiagram();
|
||||
~QgsPieDiagram();
|
||||
|
||||
void renderDiagram( const QgsAttributeMap& att, QgsRenderContext& c, const QgsDiagramSettings& s, const QPointF& position );
|
||||
QString diagramName() const { return "Pie"; }
|
||||
|
||||
private:
|
||||
QBrush mCategoryBrush;
|
||||
QPen mPen;
|
||||
};
|
||||
|
||||
#endif // QGSDIAGRAM_H
|
342
src/core/qgsdiagramrendererv2.cpp
Normal file
342
src/core/qgsdiagramrendererv2.cpp
Normal file
@ -0,0 +1,342 @@
|
||||
#include "qgsdiagramrendererv2.h"
|
||||
#include "qgsdiagram.h"
|
||||
#include "qgsrendercontext.h"
|
||||
#include <QDomElement>
|
||||
#include <QPainter>
|
||||
|
||||
|
||||
void QgsDiagramLayerSettings::readXML( const QDomElement& elem )
|
||||
{
|
||||
placement = ( Placement )elem.attribute( "placement" ).toInt();
|
||||
placementFlags = ( LinePlacementFlags )elem.attribute( "linePlacementFlags" ).toInt();
|
||||
priority = elem.attribute( "priority" ).toInt();
|
||||
obstacle = elem.attribute( "obstacle" ).toInt();
|
||||
dist = elem.attribute( "dist" ).toDouble();
|
||||
xPosColumn = elem.attribute( "xPosColumn" ).toInt();
|
||||
yPosColumn = elem.attribute( "yPosColumn" ).toInt();
|
||||
}
|
||||
|
||||
void QgsDiagramLayerSettings::writeXML( QDomElement& layerElem, QDomDocument& doc ) const
|
||||
{
|
||||
QDomElement diagramLayerElem = doc.createElement( "DiagramLayerSettings" );
|
||||
diagramLayerElem.setAttribute( "placement", placement );
|
||||
diagramLayerElem.setAttribute( "linePlacementFlags", placementFlags );
|
||||
diagramLayerElem.setAttribute( "priority", priority );
|
||||
diagramLayerElem.setAttribute( "obstacle", obstacle );
|
||||
diagramLayerElem.setAttribute( "dist", dist );
|
||||
diagramLayerElem.setAttribute( "xPosColumn", xPosColumn );
|
||||
diagramLayerElem.setAttribute( "yPosColumn", yPosColumn );
|
||||
layerElem.appendChild( diagramLayerElem );
|
||||
}
|
||||
|
||||
void QgsDiagramSettings::readXML( const QDomElement& elem )
|
||||
{
|
||||
font.fromString( elem.attribute( "font" ) );
|
||||
backgroundColor.setNamedColor( elem.attribute( "backgroundColor" ) );
|
||||
backgroundColor.setAlpha( elem.attribute( "backgroundAlpha" ).toInt() );
|
||||
size.setWidth( elem.attribute( "width" ).toDouble() );
|
||||
size.setHeight( elem.attribute( "height" ).toDouble() );
|
||||
penColor.setNamedColor( elem.attribute( "penColor" ) );
|
||||
penWidth = elem.attribute( "penWidth" ).toDouble();
|
||||
minScaleDenominator = elem.attribute( "minScaleDenominator", "-1" ).toDouble();
|
||||
maxScaleDenominator = elem.attribute( "maxScaleDenominator", "-1" ).toDouble();
|
||||
|
||||
//mm vs map units
|
||||
if ( elem.attribute( "sizeType" ) == "MM" )
|
||||
{
|
||||
sizeType = MM;
|
||||
}
|
||||
else
|
||||
{
|
||||
sizeType = MapUnits;
|
||||
}
|
||||
|
||||
//colors
|
||||
categoryColors.clear();
|
||||
QStringList colorList = elem.attribute( "colors" ).split( "/" );
|
||||
QStringList::const_iterator colorIt = colorList.constBegin();
|
||||
for ( ; colorIt != colorList.constEnd(); ++colorIt )
|
||||
{
|
||||
categoryColors.append( QColor( *colorIt ) );
|
||||
}
|
||||
|
||||
//attribute indices
|
||||
categoryIndices.clear();
|
||||
QStringList catList = elem.attribute( "categories" ).split( "/" );
|
||||
QStringList::const_iterator catIt = catList.constBegin();
|
||||
for ( ; catIt != catList.constEnd(); ++catIt )
|
||||
{
|
||||
categoryIndices.append( catIt->toInt() );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsDiagramSettings::writeXML( QDomElement& rendererElem, QDomDocument& doc ) const
|
||||
{
|
||||
QDomElement categoryElem = doc.createElement( "DiagramCategory" );
|
||||
categoryElem.setAttribute( "font", font.toString() );
|
||||
categoryElem.setAttribute( "backgroundColor", backgroundColor.name() );
|
||||
categoryElem.setAttribute( "backgroundAlpha", backgroundColor.alpha() );
|
||||
categoryElem.setAttribute( "width", size.width() );
|
||||
categoryElem.setAttribute( "height", size.height() );
|
||||
categoryElem.setAttribute( "penColor", penColor.name() );
|
||||
categoryElem.setAttribute( "penWidth", penWidth );
|
||||
categoryElem.setAttribute( "minScaleDenominator", minScaleDenominator );
|
||||
categoryElem.setAttribute( "maxScaleDenominator", maxScaleDenominator );
|
||||
if ( sizeType == MM )
|
||||
{
|
||||
categoryElem.setAttribute( "sizeType", "MM" );
|
||||
}
|
||||
else
|
||||
{
|
||||
categoryElem.setAttribute( "sizeType", "MapUnits" );
|
||||
}
|
||||
|
||||
QString colors;
|
||||
for ( int i = 0; i < categoryColors.size(); ++i )
|
||||
{
|
||||
if ( i > 0 )
|
||||
{
|
||||
colors.append( "/" );
|
||||
}
|
||||
colors.append( categoryColors.at( i ).name() );
|
||||
}
|
||||
categoryElem.setAttribute( "colors", colors );
|
||||
|
||||
QString categories;
|
||||
for ( int i = 0; i < categoryIndices.size(); ++i )
|
||||
{
|
||||
if ( i > 0 )
|
||||
{
|
||||
categories.append( "/" );
|
||||
}
|
||||
categories.append( QString::number( categoryIndices.at( i ) ) );
|
||||
}
|
||||
categoryElem.setAttribute( "categories", categories );
|
||||
|
||||
rendererElem.appendChild( categoryElem );
|
||||
}
|
||||
|
||||
QgsDiagramRendererV2::QgsDiagramRendererV2(): mDiagram( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
QgsDiagramRendererV2::~QgsDiagramRendererV2()
|
||||
{
|
||||
delete mDiagram;
|
||||
}
|
||||
|
||||
void QgsDiagramRendererV2::setDiagram( QgsDiagram* d )
|
||||
{
|
||||
delete mDiagram;
|
||||
mDiagram = d;
|
||||
}
|
||||
|
||||
void QgsDiagramRendererV2::renderDiagram( const QgsAttributeMap& att, QgsRenderContext& c, const QPointF& pos )
|
||||
{
|
||||
if ( !mDiagram )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QgsDiagramSettings s;
|
||||
if ( !diagramSettings( att, c, s ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mDiagram->renderDiagram( att, c, s, pos );
|
||||
}
|
||||
|
||||
QSizeF QgsDiagramRendererV2::sizeMapUnits( const QgsAttributeMap& attributes, const QgsRenderContext& c )
|
||||
{
|
||||
QgsDiagramSettings s;
|
||||
if ( !diagramSettings( attributes, c, s ) )
|
||||
{
|
||||
return QSizeF();
|
||||
}
|
||||
|
||||
QSizeF size = diagramSize( attributes, c );
|
||||
if ( s.sizeType == QgsDiagramSettings::MM )
|
||||
{
|
||||
convertSizeToMapUnits( size, c );
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
void QgsDiagramRendererV2::convertSizeToMapUnits( QSizeF& size, const QgsRenderContext& context ) const
|
||||
{
|
||||
if ( !size.isValid() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int dpi = dpiPaintDevice( context.constPainter() );
|
||||
if ( dpi < 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
double pixelToMap = dpi / 25.4 * context.mapToPixel().mapUnitsPerPixel();
|
||||
size.rwidth() *= pixelToMap;
|
||||
size.rheight() *= pixelToMap;
|
||||
}
|
||||
|
||||
int QgsDiagramRendererV2::dpiPaintDevice( const QPainter* painter )
|
||||
{
|
||||
if ( painter )
|
||||
{
|
||||
QPaintDevice* device = painter->device();
|
||||
if ( device )
|
||||
{
|
||||
return device->logicalDpiX();
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void QgsDiagramRendererV2::_readXML( const QDomElement& elem )
|
||||
{
|
||||
delete mDiagram;
|
||||
QString diagramType = elem.attribute( "diagramType" );
|
||||
if ( diagramType == "Pie" )
|
||||
{
|
||||
mDiagram = new QgsPieDiagram();
|
||||
}
|
||||
else if ( diagramType == "Text" )
|
||||
{
|
||||
mDiagram = new QgsTextDiagram();
|
||||
}
|
||||
else
|
||||
{
|
||||
mDiagram = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void QgsDiagramRendererV2::_writeXML( QDomElement& rendererElem, QDomDocument& doc ) const
|
||||
{
|
||||
if ( mDiagram )
|
||||
{
|
||||
rendererElem.setAttribute( "diagramType", mDiagram->diagramName() );
|
||||
}
|
||||
}
|
||||
|
||||
QgsSingleCategoryDiagramRenderer::QgsSingleCategoryDiagramRenderer(): QgsDiagramRendererV2()
|
||||
{
|
||||
}
|
||||
|
||||
QgsSingleCategoryDiagramRenderer::~QgsSingleCategoryDiagramRenderer()
|
||||
{
|
||||
}
|
||||
|
||||
bool QgsSingleCategoryDiagramRenderer::diagramSettings( const QgsAttributeMap&, const QgsRenderContext& c, QgsDiagramSettings& s )
|
||||
{
|
||||
s = mSettings;
|
||||
return true;
|
||||
}
|
||||
|
||||
QList<QgsDiagramSettings> QgsSingleCategoryDiagramRenderer::diagramSettings() const
|
||||
{
|
||||
QList<QgsDiagramSettings> settingsList;
|
||||
settingsList.push_back( mSettings );
|
||||
return settingsList;
|
||||
}
|
||||
|
||||
void QgsSingleCategoryDiagramRenderer::readXML( const QDomElement& elem )
|
||||
{
|
||||
QDomElement categoryElem = elem.firstChildElement( "DiagramCategory" );
|
||||
if ( categoryElem.isNull() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mSettings.readXML( categoryElem );
|
||||
_readXML( elem );
|
||||
}
|
||||
|
||||
void QgsSingleCategoryDiagramRenderer::writeXML( QDomElement& layerElem, QDomDocument& doc ) const
|
||||
{
|
||||
QDomElement rendererElem = doc.createElement( "SingleCategoryDiagramRenderer" );
|
||||
mSettings.writeXML( rendererElem, doc );
|
||||
_writeXML( rendererElem, doc );
|
||||
layerElem.appendChild( rendererElem );
|
||||
}
|
||||
|
||||
|
||||
QgsLinearlyInterpolatedDiagramRenderer::QgsLinearlyInterpolatedDiagramRenderer(): QgsDiagramRendererV2()
|
||||
{
|
||||
}
|
||||
|
||||
QgsLinearlyInterpolatedDiagramRenderer::~QgsLinearlyInterpolatedDiagramRenderer()
|
||||
{
|
||||
}
|
||||
|
||||
QList<QgsDiagramSettings> QgsLinearlyInterpolatedDiagramRenderer::diagramSettings() const
|
||||
{
|
||||
QList<QgsDiagramSettings> settingsList;
|
||||
settingsList.push_back( mSettings );
|
||||
return settingsList;
|
||||
}
|
||||
|
||||
bool QgsLinearlyInterpolatedDiagramRenderer::diagramSettings( const QgsAttributeMap& attributes, const QgsRenderContext& c, QgsDiagramSettings& s )
|
||||
{
|
||||
s = mSettings;
|
||||
s.size = diagramSize( attributes, c );
|
||||
return true;
|
||||
}
|
||||
|
||||
QList<int> QgsLinearlyInterpolatedDiagramRenderer::diagramAttributes() const
|
||||
{
|
||||
QList<int> attributes = mSettings.categoryIndices;
|
||||
if ( !attributes.contains( mClassificationAttribute ) )
|
||||
{
|
||||
attributes.push_back( mClassificationAttribute );
|
||||
}
|
||||
return attributes;
|
||||
}
|
||||
|
||||
QSizeF QgsLinearlyInterpolatedDiagramRenderer::diagramSize( const QgsAttributeMap& attributes, const QgsRenderContext& c )
|
||||
{
|
||||
QgsAttributeMap::const_iterator attIt = attributes.find( mClassificationAttribute );
|
||||
if ( attIt == attributes.constEnd() )
|
||||
{
|
||||
return QSizeF(); //zero size if attribute is missing
|
||||
}
|
||||
double value = attIt.value().toDouble();
|
||||
|
||||
//interpolate size
|
||||
double ratio = ( value - mLowerValue ) / ( mUpperValue - mLowerValue );
|
||||
return QSizeF( mUpperSize.width() * ratio + mLowerSize.width() * ( 1 - ratio ),
|
||||
mUpperSize.height() * ratio + mLowerSize.height() * ( 1 - ratio ) );
|
||||
}
|
||||
|
||||
void QgsLinearlyInterpolatedDiagramRenderer::readXML( const QDomElement& elem )
|
||||
{
|
||||
mLowerValue = elem.attribute( "lowerValue" ).toDouble();
|
||||
mUpperValue = elem.attribute( "upperValue" ).toDouble();
|
||||
mLowerSize.setWidth( elem.attribute( "lowerWidth" ).toDouble() );
|
||||
mLowerSize.setHeight( elem.attribute( "lowerHeight" ).toDouble() );
|
||||
mUpperSize.setWidth( elem.attribute( "upperWidth" ).toDouble() );
|
||||
mUpperSize.setHeight( elem.attribute( "upperHeight" ).toDouble() );
|
||||
mClassificationAttribute = elem.attribute( "classificationAttribute" ).toInt();
|
||||
QDomElement settingsElem = elem.firstChildElement( "DiagramCategory" );
|
||||
if ( !settingsElem.isNull() )
|
||||
{
|
||||
mSettings.readXML( settingsElem );
|
||||
}
|
||||
_readXML( elem );
|
||||
}
|
||||
|
||||
void QgsLinearlyInterpolatedDiagramRenderer::writeXML( QDomElement& layerElem, QDomDocument& doc ) const
|
||||
{
|
||||
QDomElement rendererElem = doc.createElement( "LinearlyInterpolatedDiagramRenderer" );
|
||||
rendererElem.setAttribute( "lowerValue", mLowerValue );
|
||||
rendererElem.setAttribute( "upperValue", mUpperValue );
|
||||
rendererElem.setAttribute( "lowerWidth", mLowerSize.width() );
|
||||
rendererElem.setAttribute( "lowerHeight", mLowerSize.height() );
|
||||
rendererElem.setAttribute( "upperWidth", mUpperSize.width() );
|
||||
rendererElem.setAttribute( "upperHeight", mUpperSize.height() );
|
||||
rendererElem.setAttribute( "classificationAttribute", mClassificationAttribute );
|
||||
mSettings.writeXML( rendererElem, doc );
|
||||
_writeXML( rendererElem, doc );
|
||||
layerElem.appendChild( rendererElem );
|
||||
}
|
219
src/core/qgsdiagramrendererv2.h
Normal file
219
src/core/qgsdiagramrendererv2.h
Normal file
@ -0,0 +1,219 @@
|
||||
#ifndef QGSDIAGRAMRENDERERV2_H
|
||||
#define QGSDIAGRAMRENDERERV2_H
|
||||
|
||||
#include <QColor>
|
||||
#include <QFont>
|
||||
#include <QList>
|
||||
#include <QPointF>
|
||||
#include <QSizeF>
|
||||
#include "pal/layer.h" //pal::Layer
|
||||
#include "qgsfeature.h"
|
||||
#include "qgspallabeling.h"
|
||||
|
||||
class QgsDiagram;
|
||||
class QgsDiagramRendererV2;
|
||||
class QgsFeature;
|
||||
class QgsRenderContext;
|
||||
class QDomElement;
|
||||
|
||||
struct QgsDiagramLayerSettings
|
||||
{
|
||||
//avoid inclusion of QgsPalLabeling
|
||||
enum Placement
|
||||
{
|
||||
AroundPoint, // Point / Polygon
|
||||
OverPoint, // Point / Polygon
|
||||
Line, // Line / Polygon
|
||||
Curved, // Line
|
||||
Horizontal, // Polygon
|
||||
Free // Polygon
|
||||
};
|
||||
|
||||
enum LinePlacementFlags
|
||||
{
|
||||
OnLine = 1,
|
||||
AboveLine = 2,
|
||||
BelowLine = 4,
|
||||
MapOrientation = 8
|
||||
};
|
||||
|
||||
QgsDiagramLayerSettings(): placement( AroundPoint ), placementFlags( OnLine ), priority( 5 ), obstacle( false ), dist( 0.0 ), renderer( 0 ),
|
||||
palLayer( 0 ), ct( 0 ), xform( 0 ), xPosColumn( -1 ), yPosColumn( -1 )
|
||||
{
|
||||
}
|
||||
|
||||
//pal placement properties
|
||||
Placement placement;
|
||||
LinePlacementFlags placementFlags;
|
||||
int priority; // 0 = low, 10 = high
|
||||
bool obstacle; // whether it's an obstacle
|
||||
double dist; // distance from the feature (in mm)
|
||||
QgsDiagramRendererV2* renderer;
|
||||
|
||||
//assigned when layer gets prepared
|
||||
pal::Layer* palLayer;
|
||||
const QgsCoordinateTransform* ct;
|
||||
const QgsMapToPixel* xform;
|
||||
QList<QgsPalGeometry*> geometries;
|
||||
|
||||
int xPosColumn; //attribute index for x coordinate (or -1 if position not data defined)
|
||||
int yPosColumn;//attribute index for y coordinate (or -1 if position not data defined)
|
||||
|
||||
void readXML( const QDomElement& elem );
|
||||
void writeXML( QDomElement& layerElem, QDomDocument& doc ) const;
|
||||
};
|
||||
|
||||
//diagram settings for rendering
|
||||
struct QgsDiagramSettings
|
||||
{
|
||||
enum SizeType
|
||||
{
|
||||
MM,
|
||||
MapUnits
|
||||
};
|
||||
|
||||
QgsDiagramSettings(): minScaleDenominator( -1 ), maxScaleDenominator( -1 ), sizeType( MM )
|
||||
{}
|
||||
QFont font;
|
||||
QList< QColor > categoryColors;
|
||||
QList< int > categoryIndices;
|
||||
QSizeF size; //size
|
||||
SizeType sizeType; //mm or map units
|
||||
QColor backgroundColor;
|
||||
QColor penColor;
|
||||
double penWidth;
|
||||
|
||||
//scale range (-1 if no lower / upper bound )
|
||||
double minScaleDenominator;
|
||||
double maxScaleDenominator;
|
||||
|
||||
void readXML( const QDomElement& elem );
|
||||
void writeXML( QDomElement& rendererElem, QDomDocument& doc ) const;
|
||||
};
|
||||
|
||||
/**Returns diagram settings for a feature*/
|
||||
class QgsDiagramRendererV2
|
||||
{
|
||||
public:
|
||||
|
||||
QgsDiagramRendererV2();
|
||||
virtual ~QgsDiagramRendererV2();
|
||||
|
||||
/**Returns size of the diagram for feature f in map units. Returns an invalid QSizeF in case of error*/
|
||||
virtual QSizeF sizeMapUnits( const QgsAttributeMap& attributes, const QgsRenderContext& c );
|
||||
|
||||
virtual QString rendererName() const = 0;
|
||||
|
||||
/**Returns attribute indices needed for diagram rendering*/
|
||||
virtual QList<int> diagramAttributes() const = 0;
|
||||
|
||||
void renderDiagram( const QgsAttributeMap& att, QgsRenderContext& c, const QPointF& pos );
|
||||
|
||||
void setDiagram( QgsDiagram* d );
|
||||
const QgsDiagram* diagram() const { return mDiagram; }
|
||||
|
||||
/**Returns list with all diagram settings in the renderer*/
|
||||
virtual QList<QgsDiagramSettings> diagramSettings() const = 0;
|
||||
|
||||
virtual void readXML( const QDomElement& elem ) = 0;
|
||||
virtual void writeXML( QDomElement& layerElem, QDomDocument& doc ) const = 0;
|
||||
|
||||
protected:
|
||||
|
||||
/**Returns diagram settings for a feature (or false if the diagram for the feature is not to be rendered). Used internally within renderDiagram()
|
||||
@param s out: diagram settings for the feature*/
|
||||
virtual bool diagramSettings( const QgsAttributeMap& att, const QgsRenderContext& c, QgsDiagramSettings& s ) = 0;
|
||||
|
||||
/**Returns size of the diagram (in painter units) or an invalid size in case of error*/
|
||||
virtual QSizeF diagramSize( const QgsAttributeMap& attributes, const QgsRenderContext& c ) = 0;
|
||||
|
||||
/**Converts size from mm to map units*/
|
||||
void convertSizeToMapUnits( QSizeF& size, const QgsRenderContext& context ) const;
|
||||
|
||||
/**Returns the paint device dpi (or -1 in case of error*/
|
||||
static int dpiPaintDevice( const QPainter* );
|
||||
|
||||
//read / write diagram
|
||||
void _readXML( const QDomElement& elem );
|
||||
void _writeXML( QDomElement& rendererElem, QDomDocument& doc ) const;
|
||||
|
||||
/**Reference to the object that does the real diagram rendering*/
|
||||
QgsDiagram* mDiagram;
|
||||
};
|
||||
|
||||
/**Renders the diagrams for all features with the same settings*/
|
||||
class QgsSingleCategoryDiagramRenderer: public QgsDiagramRendererV2
|
||||
{
|
||||
public:
|
||||
QgsSingleCategoryDiagramRenderer();
|
||||
~QgsSingleCategoryDiagramRenderer();
|
||||
|
||||
QString rendererName() const { return "SingleCategory"; }
|
||||
|
||||
QList<int> diagramAttributes() const { return mSettings.categoryIndices; }
|
||||
|
||||
void setDiagramSettings( const QgsDiagramSettings& s ) { mSettings = s; }
|
||||
|
||||
QList<QgsDiagramSettings> diagramSettings() const;
|
||||
|
||||
void readXML( const QDomElement& elem );
|
||||
void writeXML( QDomElement& layerElem, QDomDocument& doc ) const;
|
||||
|
||||
protected:
|
||||
bool diagramSettings( const QgsAttributeMap&, const QgsRenderContext& c, QgsDiagramSettings& s );
|
||||
|
||||
QSizeF diagramSize( const QgsAttributeMap& attributes, const QgsRenderContext& c ) { return mSettings.size; }
|
||||
|
||||
private:
|
||||
QgsDiagramSettings mSettings;
|
||||
};
|
||||
|
||||
class QgsLinearlyInterpolatedDiagramRenderer: public QgsDiagramRendererV2
|
||||
{
|
||||
public:
|
||||
QgsLinearlyInterpolatedDiagramRenderer();
|
||||
~QgsLinearlyInterpolatedDiagramRenderer();
|
||||
|
||||
/**Returns list with all diagram settings in the renderer*/
|
||||
QList<QgsDiagramSettings> diagramSettings() const;
|
||||
|
||||
void setDiagramSettings( const QgsDiagramSettings& s ) { mSettings = s; }
|
||||
|
||||
QList<int> diagramAttributes() const;
|
||||
|
||||
QString rendererName() const { return "LinearlyInterpolated"; }
|
||||
|
||||
void setLowerValue( double val ) { mLowerValue = val; }
|
||||
double lowerValue() const { return mLowerValue; }
|
||||
|
||||
void setUpperValue( double val ) { mUpperValue = val; }
|
||||
double upperValue() const { return mUpperValue; }
|
||||
|
||||
void setLowerSize( QSizeF s ) { mLowerSize = s; }
|
||||
QSizeF lowerSize() const { return mLowerSize; }
|
||||
|
||||
void setUpperSize( QSizeF s ) { mUpperSize = s; }
|
||||
QSizeF upperSize() const { return mUpperSize; }
|
||||
|
||||
int classificationAttribute() const { return mClassificationAttribute; }
|
||||
void setClassificationAttribute( int index ) { mClassificationAttribute = index; }
|
||||
|
||||
void readXML( const QDomElement& elem );
|
||||
void writeXML( QDomElement& layerElem, QDomDocument& doc ) const;
|
||||
|
||||
protected:
|
||||
bool diagramSettings( const QgsAttributeMap&, const QgsRenderContext& c, QgsDiagramSettings& s );
|
||||
|
||||
QSizeF diagramSize( const QgsAttributeMap& attributes, const QgsRenderContext& c );
|
||||
|
||||
private:
|
||||
QgsDiagramSettings mSettings;
|
||||
QSizeF mLowerSize;
|
||||
QSizeF mUpperSize;
|
||||
double mLowerValue;
|
||||
double mUpperValue;
|
||||
/**Index of the classification attribute*/
|
||||
int mClassificationAttribute;
|
||||
};
|
||||
|
||||
#endif // QGSDIAGRAMRENDERERV2_H
|
@ -27,7 +27,7 @@ void QgsLabelSearchTree::label( const QgsPoint& p, QList<QgsLabelPosition*>& pos
|
||||
posList = mSearchResults;
|
||||
}
|
||||
|
||||
bool QgsLabelSearchTree::insertLabel( LabelPosition* labelPos, int featureId, const QString& layerName )
|
||||
bool QgsLabelSearchTree::insertLabel( LabelPosition* labelPos, int featureId, const QString& layerName, bool diagram )
|
||||
{
|
||||
if ( !labelPos )
|
||||
{
|
||||
@ -44,7 +44,7 @@ bool QgsLabelSearchTree::insertLabel( LabelPosition* labelPos, int featureId, co
|
||||
cornerPoints.push_back( QgsPoint( labelPos->getX( i ), labelPos->getY( i ) ) );
|
||||
}
|
||||
QgsLabelPosition* newEntry = new QgsLabelPosition( featureId, labelPos->getAlpha(), cornerPoints, QgsRectangle( c_min[0], c_min[1], c_max[0], c_max[1] ),
|
||||
labelPos->getWidth(), labelPos->getHeight(), layerName, labelPos->getUpsideDown() );
|
||||
labelPos->getWidth(), labelPos->getHeight(), layerName, labelPos->getUpsideDown(), diagram );
|
||||
mSpatialIndex.Insert( c_min, c_max, newEntry );
|
||||
return true;
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ class CORE_EXPORT QgsLabelSearchTree
|
||||
|
||||
/**Inserts label position. Does not take ownership of labelPos
|
||||
@return true in case of success*/
|
||||
bool insertLabel( LabelPosition* labelPos, int featureId, const QString& layerName );
|
||||
bool insertLabel( LabelPosition* labelPos, int featureId, const QString& layerName, bool diagram = false );
|
||||
|
||||
private:
|
||||
RTree<QgsLabelPosition*, double, 2, double> mSpatialIndex;
|
||||
|
@ -39,11 +39,13 @@ class QgsOverlayObjectPositionManager;
|
||||
class QgsVectorLayer;
|
||||
class QgsFeature;
|
||||
|
||||
struct QgsDiagramLayerSettings;
|
||||
|
||||
struct CORE_EXPORT QgsLabelPosition
|
||||
{
|
||||
QgsLabelPosition( int id, double r, const QVector< QgsPoint >& corners, const QgsRectangle& rect, double w, double h, const QString& layer, bool upside_down ):
|
||||
featureId( id ), rotation( r ), cornerPoints( corners ), labelRect( rect ), width( w ), height( h ), layerID( layer ), upsideDown( upside_down ) {}
|
||||
QgsLabelPosition(): featureId( -1 ), rotation( 0 ), labelRect( QgsRectangle() ), width( 0 ), height( 0 ), layerID( "" ), upsideDown( false ) {}
|
||||
QgsLabelPosition( int id, double r, const QVector< QgsPoint >& corners, const QgsRectangle& rect, double w, double h, const QString& layer, bool upside_down, bool diagram = false ):
|
||||
featureId( id ), rotation( r ), cornerPoints( corners ), labelRect( rect ), width( w ), height( h ), layerID( layer ), upsideDown( upside_down ), isDiagram( diagram ) {}
|
||||
QgsLabelPosition(): featureId( -1 ), rotation( 0 ), labelRect( QgsRectangle() ), width( 0 ), height( 0 ), layerID( "" ), upsideDown( false ), isDiagram( false ) {}
|
||||
int featureId;
|
||||
double rotation;
|
||||
QVector< QgsPoint > cornerPoints;
|
||||
@ -52,6 +54,7 @@ struct CORE_EXPORT QgsLabelPosition
|
||||
double height;
|
||||
QString layerID;
|
||||
bool upsideDown;
|
||||
bool isDiagram;
|
||||
};
|
||||
|
||||
/** Labeling engine interface.
|
||||
@ -70,8 +73,12 @@ class QgsLabelingEngineInterface
|
||||
//! called when starting rendering of a layer
|
||||
//! @note: this method was added in version 1.6
|
||||
virtual int prepareLayer( QgsVectorLayer* layer, QSet<int>& attrIndices, QgsRenderContext& ctx ) = 0;
|
||||
//! adds a diagram layer to the labeling engine
|
||||
virtual int addDiagramLayer( QgsVectorLayer* layer, QgsDiagramLayerSettings& s ) {};
|
||||
//! called for every feature
|
||||
virtual void registerFeature( QgsVectorLayer* layer, QgsFeature& feat, const QgsRenderContext& context = QgsRenderContext() ) = 0;
|
||||
//! called for every diagram feature
|
||||
virtual void registerDiagramFeature( QgsVectorLayer* layer, QgsFeature& feat, const QgsRenderContext& context = QgsRenderContext() ) {};
|
||||
//! called when the map is drawn and labels should be placed
|
||||
virtual void drawLabeling( QgsRenderContext& context ) = 0;
|
||||
//! called when we're done with rendering
|
||||
|
@ -38,6 +38,8 @@
|
||||
#include <QTime>
|
||||
#include <QPainter>
|
||||
|
||||
#include "qgsdiagram.h"
|
||||
#include "qgsdiagramrendererv2.h"
|
||||
#include "qgslabelsearchtree.h"
|
||||
#include <qgslogger.h>
|
||||
#include <qgsvectorlayer.h>
|
||||
@ -53,7 +55,7 @@ using namespace pal;
|
||||
class QgsPalGeometry : public PalGeometry
|
||||
{
|
||||
public:
|
||||
QgsPalGeometry( int id, QString text, GEOSGeometry* g ): mG( g ), mText( text ), mId( id ), mInfo( NULL )
|
||||
QgsPalGeometry( int id, QString text, GEOSGeometry* g ): mG( g ), mText( text ), mId( id ), mInfo( NULL ), mIsDiagram( false )
|
||||
{
|
||||
mStrId = QByteArray::number( id );
|
||||
}
|
||||
@ -99,14 +101,24 @@ class QgsPalGeometry : public PalGeometry
|
||||
const QMap< QgsPalLayerSettings::DataDefinedProperties, QVariant >& dataDefinedValues() const { return mDataDefinedValues; }
|
||||
void addDataDefinedValue( QgsPalLayerSettings::DataDefinedProperties p, QVariant v ) { mDataDefinedValues.insert( p, v ); }
|
||||
|
||||
void setIsDiagram( bool d ) { mIsDiagram = d; }
|
||||
bool isDiagram() const { return mIsDiagram; }
|
||||
|
||||
void addDiagramAttribute( int index, QVariant value ) { mDiagramAttributes.insert( index, value ); }
|
||||
const QgsAttributeMap& diagramAttributes() { return mDiagramAttributes; }
|
||||
|
||||
protected:
|
||||
GEOSGeometry* mG;
|
||||
QString mText;
|
||||
QByteArray mStrId;
|
||||
int mId;
|
||||
LabelInfo* mInfo;
|
||||
bool mIsDiagram;
|
||||
/**Stores attribute values for data defined properties*/
|
||||
QMap< QgsPalLayerSettings::DataDefinedProperties, QVariant > mDataDefinedValues;
|
||||
|
||||
/**Stores attribute values for diagram rendering*/
|
||||
QgsAttributeMap mDiagramAttributes;
|
||||
};
|
||||
|
||||
// -------------
|
||||
@ -413,7 +425,6 @@ void QgsPalLayerSettings::calculateLabelSize( const QFontMetricsF* fm, QString t
|
||||
labelY = qAbs( ptSize.y() - ptZero.y() );
|
||||
}
|
||||
|
||||
|
||||
void QgsPalLayerSettings::registerFeature( QgsFeature& f, const QgsRenderContext& context )
|
||||
{
|
||||
QString labelText = f.attributeMap()[fieldIndex].toString();
|
||||
@ -742,6 +753,20 @@ int QgsPalLabeling::prepareLayer( QgsVectorLayer* layer, QSet<int>& attrIndices,
|
||||
return 1; // init successful
|
||||
}
|
||||
|
||||
int QgsPalLabeling::addDiagramLayer( QgsVectorLayer* layer, QgsDiagramLayerSettings& s )
|
||||
{
|
||||
Layer* l = mPal->addLayer( layer->id().append( "d" ).toLocal8Bit().data(), -1, -1, pal::Arrangement( s.placement ), METER, s.priority, s.obstacle, true, true );
|
||||
l->setArrangementFlags( s.placementFlags );
|
||||
|
||||
s.palLayer = l;
|
||||
if ( mMapRenderer->hasCrsTransformEnabled() )
|
||||
s.ct = new QgsCoordinateTransform( layer->srs(), mMapRenderer->destinationSrs() );
|
||||
else
|
||||
s.ct = NULL;
|
||||
s.xform = mMapRenderer->coordinateTransform();
|
||||
mActiveDiagramLayers.insert( layer, s );
|
||||
return 1;
|
||||
}
|
||||
|
||||
void QgsPalLabeling::registerFeature( QgsVectorLayer* layer, QgsFeature& f, const QgsRenderContext& context )
|
||||
{
|
||||
@ -749,6 +774,94 @@ void QgsPalLabeling::registerFeature( QgsVectorLayer* layer, QgsFeature& f, cons
|
||||
lyr.registerFeature( f, context );
|
||||
}
|
||||
|
||||
void QgsPalLabeling::registerDiagramFeature( QgsVectorLayer* layer, QgsFeature& feat, const QgsRenderContext& context )
|
||||
{
|
||||
//get diagram layer settings, diagram renderer
|
||||
QHash<QgsVectorLayer*, QgsDiagramLayerSettings>::iterator layerIt = mActiveDiagramLayers.find( layer );
|
||||
if ( layerIt == mActiveDiagramLayers.constEnd() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//convert geom to geos
|
||||
QgsGeometry* geom = feat.geometry();
|
||||
|
||||
if ( layerIt.value().ct ) // reproject the geometry if necessary
|
||||
{
|
||||
geom->transform( *( layerIt.value().ct ) );
|
||||
}
|
||||
|
||||
GEOSGeometry* geos_geom = geom->asGeos();
|
||||
if ( geos_geom == 0 )
|
||||
{
|
||||
return; // invalid geometry
|
||||
}
|
||||
|
||||
//create PALGeometry with diagram = true
|
||||
QgsPalGeometry* lbl = new QgsPalGeometry( feat.id(), "", GEOSGeom_clone( geos_geom ) );
|
||||
lbl->setIsDiagram( true );
|
||||
|
||||
// record the created geometry - it will be deleted at the end.
|
||||
layerIt.value().geometries.append( lbl );
|
||||
|
||||
double diagramWidth = 0;
|
||||
double diagramHeight = 0;
|
||||
QgsDiagramRendererV2* dr = layerIt.value().renderer;
|
||||
if ( dr )
|
||||
{
|
||||
QSizeF diagSize = dr->sizeMapUnits( feat.attributeMap(), context );
|
||||
if ( diagSize.isValid() )
|
||||
{
|
||||
diagramWidth = diagSize.width();
|
||||
diagramHeight = diagSize.height();
|
||||
}
|
||||
|
||||
//append the diagram attributes to lbl
|
||||
QList<int> diagramAttrib = dr->diagramAttributes();
|
||||
QList<int>::const_iterator diagAttIt = diagramAttrib.constBegin();
|
||||
for ( ; diagAttIt != diagramAttrib.constEnd(); ++diagAttIt )
|
||||
{
|
||||
lbl->addDiagramAttribute( *diagAttIt, feat.attributeMap()[*diagAttIt] );
|
||||
}
|
||||
}
|
||||
|
||||
// register feature to the layer
|
||||
int ddColX = layerIt.value().xPosColumn;
|
||||
int ddColY = layerIt.value().yPosColumn;
|
||||
double ddPosX = 0.0;
|
||||
double ddPosY = 0.0;
|
||||
bool ddPos = ( ddColX >= 0 && ddColY >= 0 );
|
||||
if ( ddPos )
|
||||
{
|
||||
bool posXOk, posYOk;
|
||||
//data defined diagram position is always centered
|
||||
ddPosX = feat.attributeMap()[ddColX].toDouble( &posXOk ) - diagramWidth / 2.0;
|
||||
ddPosY = feat.attributeMap()[ddColY].toDouble( &posYOk ) - diagramHeight / 2.0;
|
||||
if ( !posXOk || !posYOk )
|
||||
{
|
||||
ddPos = false;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if ( !layerIt.value().palLayer->registerFeature( lbl->strId(), lbl, diagramWidth, diagramHeight, "", ddPosX, ddPosY, ddPos ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch ( std::exception* e )
|
||||
{
|
||||
QgsDebugMsg( QString( "Ignoring feature %1 due PAL exception: " ).arg( feat.id() ) + QString::fromLatin1( e->what() ) );
|
||||
return;
|
||||
}
|
||||
|
||||
pal::Feature* palFeat = layerIt.value().palLayer->getFeature( lbl->strId() );
|
||||
QgsPoint ptZero = layerIt.value().xform->toMapCoordinates( 0, 0 );
|
||||
QgsPoint ptOne = layerIt.value().xform->toMapCoordinates( 1, 0 );
|
||||
palFeat->setDistLabel( qAbs( ptOne.x() - ptZero.x() ) * layerIt.value().dist );
|
||||
}
|
||||
|
||||
|
||||
void QgsPalLabeling::init( QgsMapRenderer* mr )
|
||||
{
|
||||
@ -778,6 +891,7 @@ void QgsPalLabeling::init( QgsMapRenderer* mr )
|
||||
mPal->setPolyP( mCandPolygon );
|
||||
|
||||
mActiveLayers.clear();
|
||||
mActiveDiagramLayers.clear();
|
||||
}
|
||||
|
||||
void QgsPalLabeling::exit()
|
||||
@ -866,18 +980,42 @@ void QgsPalLabeling::drawLabeling( QgsRenderContext& context )
|
||||
std::list<LabelPosition*>::iterator it = labels->begin();
|
||||
for ( ; it != labels->end(); ++it )
|
||||
{
|
||||
const QgsPalLayerSettings& lyr = layer(( *it )->getLayerName() );
|
||||
QFont fontForLabel = lyr.textFont;
|
||||
QColor fontColor = lyr.textColor;
|
||||
double bufferSize = lyr.bufferSize;
|
||||
QColor bufferColor = lyr.bufferColor;
|
||||
|
||||
QgsPalGeometry* palGeometry = dynamic_cast< QgsPalGeometry* >(( *it )->getFeaturePart()->getUserGeometry() );
|
||||
if ( !palGeometry )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( palGeometry->isDiagram() )
|
||||
{
|
||||
//render diagram
|
||||
QHash<QgsVectorLayer*, QgsDiagramLayerSettings>::iterator dit = mActiveDiagramLayers.begin();
|
||||
for ( dit = mActiveDiagramLayers.begin(); dit != mActiveDiagramLayers.end(); ++dit )
|
||||
{
|
||||
if ( dit.key() && dit.key()->id().append( "d" ) == ( *it )->getLayerName() )
|
||||
{
|
||||
QgsPoint outPt = xform->transform(( *it )->getX(), ( *it )->getY() );
|
||||
dit.value().renderer->renderDiagram( palGeometry->diagramAttributes(), context, QPointF( outPt.x(), outPt.y() ) );
|
||||
}
|
||||
}
|
||||
|
||||
//insert into label search tree to manipulate position interactively
|
||||
if ( mLabelSearchTree )
|
||||
{
|
||||
//for diagrams, remove the additional 'd' at the end of the layer id
|
||||
QString layerId = ( *it )->getLayerName();
|
||||
layerId.chop( 1 );
|
||||
mLabelSearchTree->insertLabel( *it, QString( palGeometry->strId() ).toInt(), layerId, true );
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
const QgsPalLayerSettings& lyr = layer(( *it )->getLayerName() );
|
||||
QFont fontForLabel = lyr.textFont;
|
||||
QColor fontColor = lyr.textColor;
|
||||
double bufferSize = lyr.bufferSize;
|
||||
QColor bufferColor = lyr.bufferColor;
|
||||
|
||||
//apply data defined settings for the label
|
||||
//font size
|
||||
QVariant dataDefinedSize = palGeometry->dataDefinedValues().value( QgsPalLayerSettings::Size );
|
||||
@ -968,9 +1106,18 @@ void QgsPalLabeling::drawLabeling( QgsRenderContext& context )
|
||||
delete *git;
|
||||
lyr.geometries.clear();
|
||||
}
|
||||
// labeling is done: clear the active layers hashtable
|
||||
// mActiveLayers.clear();
|
||||
|
||||
//delete all allocated geometries for diagrams
|
||||
QHash<QgsVectorLayer*, QgsDiagramLayerSettings>::iterator dIt = mActiveDiagramLayers.begin();
|
||||
for ( ; dIt != mActiveDiagramLayers.end(); ++dIt )
|
||||
{
|
||||
QgsDiagramLayerSettings& dls = dIt.value();
|
||||
for ( QList<QgsPalGeometry*>::iterator git = dls.geometries.begin(); git != dls.geometries.end(); ++git )
|
||||
{
|
||||
delete *git;
|
||||
}
|
||||
dls.geometries.clear();
|
||||
}
|
||||
}
|
||||
|
||||
QList<QgsLabelPosition> QgsPalLabeling::labelsAtPosition( const QgsPoint& p )
|
||||
|
@ -23,14 +23,17 @@
|
||||
|
||||
class QFontMetricsF;
|
||||
class QPainter;
|
||||
class QgsGeometry;
|
||||
class QgsMapRenderer;
|
||||
class QgsRectangle;
|
||||
class QgsCoordinateTransform;
|
||||
class QgsLabelSearchTree;
|
||||
struct QgsDiagramLayerSettings;
|
||||
|
||||
#include <QString>
|
||||
#include <QFont>
|
||||
#include <QColor>
|
||||
#include <QHash>
|
||||
#include <QList>
|
||||
#include <QRectF>
|
||||
|
||||
@ -45,9 +48,10 @@ class QgsMapToPixel;
|
||||
class QgsFeature;
|
||||
#include "qgspoint.h"
|
||||
|
||||
#include "qgsvectorlayer.h" // definition of QgsLabelingEngineInterface
|
||||
#include "qgsmaprenderer.h" // definition of QgsLabelingEngineInterface
|
||||
|
||||
class QgsPalGeometry;
|
||||
class QgsVectorLayer;
|
||||
|
||||
class CORE_EXPORT QgsPalLayerSettings
|
||||
{
|
||||
@ -195,8 +199,11 @@ class CORE_EXPORT QgsPalLabeling : public QgsLabelingEngineInterface
|
||||
virtual bool willUseLayer( QgsVectorLayer* layer );
|
||||
//! hook called when drawing layer before issuing select()
|
||||
virtual int prepareLayer( QgsVectorLayer* layer, QSet<int>& attrIndices, QgsRenderContext& ctx );
|
||||
//! adds a diagram layer to the labeling engine
|
||||
virtual int addDiagramLayer( QgsVectorLayer* layer, QgsDiagramLayerSettings& s );
|
||||
//! hook called when drawing for every feature in a layer
|
||||
virtual void registerFeature( QgsVectorLayer* layer, QgsFeature& feat, const QgsRenderContext& context = QgsRenderContext() );
|
||||
virtual void registerDiagramFeature( QgsVectorLayer* layer, QgsFeature& feat, const QgsRenderContext& context = QgsRenderContext() );
|
||||
//! called when the map is drawn and labels should be placed
|
||||
virtual void drawLabeling( QgsRenderContext& context );
|
||||
//! called when we're done with rendering
|
||||
@ -220,6 +227,8 @@ class CORE_EXPORT QgsPalLabeling : public QgsLabelingEngineInterface
|
||||
protected:
|
||||
// hashtable of layer settings, being filled during labeling
|
||||
QHash<QgsVectorLayer*, QgsPalLayerSettings> mActiveLayers;
|
||||
// hashtable of active diagram layers
|
||||
QHash<QgsVectorLayer*, QgsDiagramLayerSettings> mActiveDiagramLayers;
|
||||
QgsPalLayerSettings mInvalidLayerSettings;
|
||||
|
||||
QgsMapRenderer* mMapRenderer;
|
||||
|
@ -41,6 +41,7 @@ class CORE_EXPORT QgsRenderContext
|
||||
//getters
|
||||
|
||||
QPainter* painter() {return mPainter;}
|
||||
const QPainter* constPainter() const { return mPainter; }
|
||||
|
||||
const QgsCoordinateTransform* coordinateTransform() const {return mCoordTransform;}
|
||||
|
||||
|
@ -25,8 +25,13 @@ class QTextCodec;
|
||||
//QGIS Includes
|
||||
#include "qgis.h"
|
||||
#include "qgsdataprovider.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
#include "qgsfeature.h"
|
||||
#include "qgsfield.h"
|
||||
#include "qgsrectangle.h"
|
||||
|
||||
typedef QList<int> QgsAttributeList;
|
||||
typedef QSet<int> QgsFeatureIds;
|
||||
typedef QSet<int> QgsAttributeIds;
|
||||
|
||||
/** \ingroup core
|
||||
* This is the base class for vector data providers.
|
||||
|
@ -111,7 +111,8 @@ QgsVectorLayer::QgsVectorLayer( QString vectorLayerPath,
|
||||
mLabelOn( false ),
|
||||
mVertexMarkerOnlyForSelection( false ),
|
||||
mFetching( false ),
|
||||
mJoinBuffer( 0 )
|
||||
mJoinBuffer( 0 ),
|
||||
mDiagramRenderer( 0 )
|
||||
{
|
||||
mActions = new QgsAttributeAction( this );
|
||||
|
||||
@ -754,8 +755,17 @@ void QgsVectorLayer::drawRendererV2( QgsRenderContext& rendererContext, bool lab
|
||||
mRendererV2->renderFeature( fet, rendererContext, -1, sel, drawMarker );
|
||||
|
||||
// labeling - register feature
|
||||
if ( labeling && mRendererV2->symbolForFeature( fet ) != NULL )
|
||||
rendererContext.labelingEngine()->registerFeature( this, fet, rendererContext );
|
||||
if ( mRendererV2->symbolForFeature( fet ) != NULL )
|
||||
{
|
||||
if ( labeling )
|
||||
{
|
||||
rendererContext.labelingEngine()->registerFeature( this, fet, rendererContext );
|
||||
}
|
||||
if ( mDiagramRenderer )
|
||||
{
|
||||
rendererContext.labelingEngine()->registerDiagramFeature( this, fet, rendererContext );
|
||||
}
|
||||
}
|
||||
|
||||
if ( mEditable )
|
||||
{
|
||||
@ -821,8 +831,17 @@ void QgsVectorLayer::drawRendererV2Levels( QgsRenderContext& rendererContext, bo
|
||||
}
|
||||
features[sym].append( fet );
|
||||
|
||||
if ( labeling && mRendererV2->symbolForFeature( fet ) != NULL )
|
||||
rendererContext.labelingEngine()->registerFeature( this, fet, rendererContext );
|
||||
if ( mRendererV2->symbolForFeature( fet ) != NULL )
|
||||
{
|
||||
if ( labeling )
|
||||
{
|
||||
rendererContext.labelingEngine()->registerFeature( this, fet, rendererContext );
|
||||
}
|
||||
if ( mDiagramRenderer )
|
||||
{
|
||||
rendererContext.labelingEngine()->registerDiagramFeature( this, fet, rendererContext );
|
||||
}
|
||||
}
|
||||
|
||||
if ( mEditable )
|
||||
{
|
||||
@ -949,22 +968,8 @@ bool QgsVectorLayer::draw( QgsRenderContext& rendererContext )
|
||||
}
|
||||
|
||||
bool labeling = false;
|
||||
if ( rendererContext.labelingEngine() )
|
||||
{
|
||||
QSet<int> attrIndex;
|
||||
if ( rendererContext.labelingEngine()->prepareLayer( this, attrIndex, rendererContext ) )
|
||||
{
|
||||
QSet<int>::const_iterator attIt = attrIndex.constBegin();
|
||||
for ( ; attIt != attrIndex.constEnd(); ++attIt )
|
||||
{
|
||||
if ( !attributes.contains( *attIt ) )
|
||||
{
|
||||
attributes << *attIt;
|
||||
}
|
||||
}
|
||||
labeling = true;
|
||||
}
|
||||
}
|
||||
//register label and diagram layer to the labeling engine
|
||||
prepareLabelingAndDiagrams( rendererContext, attributes, labeling );
|
||||
|
||||
select( attributes, rendererContext.extent() );
|
||||
|
||||
@ -1011,22 +1016,7 @@ bool QgsVectorLayer::draw( QgsRenderContext& rendererContext )
|
||||
QgsAttributeList attributes = mRenderer->classificationAttributes();
|
||||
|
||||
bool labeling = false;
|
||||
if ( rendererContext.labelingEngine() )
|
||||
{
|
||||
QSet<int> attrIndex;
|
||||
if ( rendererContext.labelingEngine()->prepareLayer( this, attrIndex, rendererContext ) )
|
||||
{
|
||||
QSet<int>::const_iterator attIt = attrIndex.constBegin();
|
||||
for ( ; attIt != attrIndex.constEnd(); ++attIt )
|
||||
{
|
||||
if ( !attributes.contains( *attIt ) )
|
||||
{
|
||||
attributes << *attIt;
|
||||
}
|
||||
}
|
||||
labeling = true;
|
||||
}
|
||||
}
|
||||
prepareLabelingAndDiagrams( rendererContext, attributes, labeling );
|
||||
|
||||
select( attributes, rendererContext.extent() );
|
||||
|
||||
@ -1092,11 +1082,17 @@ bool QgsVectorLayer::draw( QgsRenderContext& rendererContext )
|
||||
//double scale = rendererContext.scaleFactor() / markerScaleFactor;
|
||||
drawFeature( rendererContext, fet, &marker );
|
||||
|
||||
if ( labeling && mRenderer->willRenderFeature( &fet ) )
|
||||
if ( mRenderer->willRenderFeature( &fet ) )
|
||||
{
|
||||
rendererContext.labelingEngine()->registerFeature( this, fet, rendererContext );
|
||||
if ( labeling )
|
||||
{
|
||||
rendererContext.labelingEngine()->registerFeature( this, fet, rendererContext );
|
||||
}
|
||||
if ( mDiagramRenderer )
|
||||
{
|
||||
rendererContext.labelingEngine()->registerDiagramFeature( this, fet, rendererContext );
|
||||
}
|
||||
}
|
||||
|
||||
++featureCount;
|
||||
}
|
||||
}
|
||||
@ -1303,6 +1299,12 @@ void QgsVectorLayer::setRenderer( QgsRenderer * r )
|
||||
}
|
||||
}
|
||||
|
||||
void QgsVectorLayer::setDiagramRenderer( QgsDiagramRendererV2* r )
|
||||
{
|
||||
delete mDiagramRenderer;
|
||||
mDiagramRenderer = r;
|
||||
}
|
||||
|
||||
QGis::GeometryType QgsVectorLayer::geometryType() const
|
||||
{
|
||||
if ( mDataProvider )
|
||||
@ -2937,6 +2939,30 @@ bool QgsVectorLayer::readSymbology( const QDomNode& node, QString& errorMessage
|
||||
QgsDebugMsg( "calling readXML" );
|
||||
mLabel->readXML( labelattributesnode );
|
||||
}
|
||||
|
||||
//diagram renderer and diagram layer settings
|
||||
delete mDiagramRenderer; mDiagramRenderer = 0;
|
||||
QDomElement singleCatDiagramElem = node.firstChildElement( "SingleCategoryDiagramRenderer" );
|
||||
if ( !singleCatDiagramElem.isNull() )
|
||||
{
|
||||
mDiagramRenderer = new QgsSingleCategoryDiagramRenderer();
|
||||
mDiagramRenderer->readXML( singleCatDiagramElem );
|
||||
}
|
||||
QDomElement linearDiagramElem = node.firstChildElement( "LinearlyInterpolatedDiagramRenderer" );
|
||||
if ( !linearDiagramElem.isNull() )
|
||||
{
|
||||
mDiagramRenderer = new QgsLinearlyInterpolatedDiagramRenderer();
|
||||
mDiagramRenderer->readXML( linearDiagramElem );
|
||||
}
|
||||
|
||||
if ( mDiagramRenderer )
|
||||
{
|
||||
QDomElement diagramSettingsElem = node.firstChildElement( "DiagramLayerSettings" );
|
||||
if ( !diagramSettingsElem.isNull() )
|
||||
{
|
||||
mDiagramLayerSettings.readXML( diagramSettingsElem );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// process the attribute actions
|
||||
@ -3109,6 +3135,12 @@ bool QgsVectorLayer::writeSymbology( QDomNode& node, QDomDocument& doc, QString&
|
||||
}
|
||||
|
||||
mLabel->writeXML( node, doc );
|
||||
|
||||
if ( mDiagramRenderer )
|
||||
{
|
||||
mDiagramRenderer->writeXML( mapLayerNode, doc );
|
||||
mDiagramLayerSettings.writeXML( mapLayerNode, doc );
|
||||
}
|
||||
}
|
||||
|
||||
//edit types
|
||||
@ -5131,3 +5163,49 @@ void QgsVectorLayer::updateAttributeMapIndex( QgsAttributeMap& map, int oldIndex
|
||||
map.insert( newIndex, it.value() );
|
||||
map.remove( oldIndex );
|
||||
}
|
||||
|
||||
void QgsVectorLayer::prepareLabelingAndDiagrams( QgsRenderContext& rendererContext, QgsAttributeList& attributes, bool& labeling )
|
||||
{
|
||||
if ( rendererContext.labelingEngine() )
|
||||
{
|
||||
QSet<int> attrIndex;
|
||||
if ( rendererContext.labelingEngine()->prepareLayer( this, attrIndex, rendererContext ) )
|
||||
{
|
||||
QSet<int>::const_iterator attIt = attrIndex.constBegin();
|
||||
for ( ; attIt != attrIndex.constEnd(); ++attIt )
|
||||
{
|
||||
if ( !attributes.contains( *attIt ) )
|
||||
{
|
||||
attributes << *attIt;
|
||||
}
|
||||
}
|
||||
labeling = true;
|
||||
}
|
||||
|
||||
//register diagram layers
|
||||
if ( mDiagramRenderer )
|
||||
{
|
||||
mDiagramLayerSettings.renderer = mDiagramRenderer;
|
||||
rendererContext.labelingEngine()->addDiagramLayer( this, mDiagramLayerSettings );
|
||||
//add attributes needed by the diagram renderer
|
||||
QList<int> att = mDiagramRenderer->diagramAttributes();
|
||||
QList<int>::const_iterator attIt = att.constBegin();
|
||||
for ( ; attIt != att.constEnd(); ++attIt )
|
||||
{
|
||||
if ( !attributes.contains( *attIt ) )
|
||||
{
|
||||
attributes << *attIt;
|
||||
}
|
||||
}
|
||||
//and the ones needed for data defined diagram positions
|
||||
if ( mDiagramLayerSettings.xPosColumn >= 0 && !attributes.contains( mDiagramLayerSettings.xPosColumn ) )
|
||||
{
|
||||
attributes << mDiagramLayerSettings.xPosColumn;
|
||||
}
|
||||
if ( mDiagramLayerSettings.yPosColumn >= 0 && !attributes.contains( mDiagramLayerSettings.yPosColumn ) )
|
||||
{
|
||||
attributes << mDiagramLayerSettings.yPosColumn;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,10 @@
|
||||
#include <QList>
|
||||
#include <QStringList>
|
||||
|
||||
|
||||
|
||||
#include "qgis.h"
|
||||
#include "qgsdiagramrendererv2.h"
|
||||
#include "qgsmaplayer.h"
|
||||
#include "qgsfeature.h"
|
||||
#include "qgssnapper.h"
|
||||
@ -48,7 +51,6 @@ class QgsVectorOverlay;
|
||||
class QgsSingleSymbolRendererV2;
|
||||
class QgsRectangle;
|
||||
class QgsVectorLayerJoinBuffer;
|
||||
|
||||
class QgsFeatureRendererV2;
|
||||
|
||||
typedef QList<int> QgsAttributeList;
|
||||
@ -208,6 +210,13 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
|
||||
/** Sets the renderer. If a renderer is already present, it is deleted */
|
||||
void setRenderer( QgsRenderer * r );
|
||||
|
||||
/** Sets diagram rendering object (takes ownership) */
|
||||
void setDiagramRenderer( QgsDiagramRendererV2* r );
|
||||
const QgsDiagramRendererV2* diagramRenderer() const { return mDiagramRenderer; }
|
||||
|
||||
void setDiagramLayerSettings( const QgsDiagramLayerSettings& s ) { mDiagramLayerSettings = s; }
|
||||
QgsDiagramLayerSettings diagramLayerSettings() const { return mDiagramLayerSettings; }
|
||||
|
||||
/** Return renderer V2.
|
||||
* @note added in 1.4 */
|
||||
QgsFeatureRendererV2* rendererV2();
|
||||
@ -804,6 +813,11 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
|
||||
/**Updates an index in an attribute map to a new value (usually necessary because of a join operation)*/
|
||||
void updateAttributeMapIndex( QgsAttributeMap& map, int oldIndex, int newIndex ) const;
|
||||
|
||||
/**Registers label and diagram layer
|
||||
@param attList attributes needed for labeling and diagrams will be added to the list
|
||||
@param labeling out: true if there will be labeling (ng) for this layer*/
|
||||
void prepareLabelingAndDiagrams( QgsRenderContext& rendererContext, QgsAttributeList& attributes, bool& labeling );
|
||||
|
||||
private: // Private attributes
|
||||
|
||||
/** Update threshold for drawing features as they are read. A value of zero indicates
|
||||
@ -931,6 +945,12 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
|
||||
|
||||
//stores information about joined layers
|
||||
QgsVectorLayerJoinBuffer* mJoinBuffer;
|
||||
|
||||
//diagram rendering object. 0 if diagram drawing is disabled
|
||||
QgsDiagramRendererV2* mDiagramRenderer;
|
||||
|
||||
//stores infos about diagram placement (placement type, priority, position distance)
|
||||
QgsDiagramLayerSettings mDiagramLayerSettings;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <qgsmapcanvas.h>
|
||||
#include <qgsmaplayer.h>
|
||||
#include <qgsvectordataprovider.h>
|
||||
#include <qgsvectorlayer.h>
|
||||
#include <qgsfield.h>
|
||||
|
||||
// Qt includes
|
||||
|
@ -1,5 +1,6 @@
|
||||
SUBDIRS (copyright_label
|
||||
delimited_text
|
||||
delimited_text
|
||||
diagram_overlay
|
||||
interpolation
|
||||
north_arrow
|
||||
scale_bar
|
||||
@ -7,7 +8,6 @@ SUBDIRS (copyright_label
|
||||
raster_terrain_analysis
|
||||
coordinate_capture
|
||||
dxf2shp_converter
|
||||
diagram_overlay
|
||||
evis
|
||||
point_displacement_renderer
|
||||
spatialquery
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "qgisinterface.h"
|
||||
#include "qgslogger.h"
|
||||
#include "qgsmapcanvas.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
#include "qgsvertexmarker.h"
|
||||
|
||||
#include <QMouseEvent>
|
||||
|
@ -37,7 +37,6 @@
|
||||
#include "qgslogger.h"
|
||||
#include "qgsmessageoutput.h"
|
||||
#include "qgsrectangle.h"
|
||||
#include "qgscoordinatereferencesystem.h"
|
||||
#include "qgis.h"
|
||||
|
||||
static const QString TEXT_PROVIDER_KEY = "delimitedtext";
|
||||
|
@ -18,6 +18,7 @@
|
||||
/* $Id$ */
|
||||
|
||||
#include "qgsvectordataprovider.h"
|
||||
#include "qgscoordinatereferencesystem.h"
|
||||
|
||||
#include <QStringList>
|
||||
|
||||
|
@ -21,6 +21,7 @@ class QgsField;
|
||||
|
||||
#include <QDateTime>
|
||||
#include "qgsvectordataprovider.h"
|
||||
#include <vector>
|
||||
|
||||
/* Update.
|
||||
* Vectors are updated (reloaded) if:
|
||||
|
@ -14,6 +14,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include "qgsvectordataprovider.h"
|
||||
#include "qgscoordinatereferencesystem.h"
|
||||
|
||||
|
||||
typedef QMap<int, QgsFeature> QgsFeatureMap;
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "qgsgeometry.h"
|
||||
#include "qgslogger.h"
|
||||
#include "qgsvectordataprovider.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
#include "qgsapplication.h"
|
||||
|
||||
#include <QFileInfo>
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <sqlite3.h>
|
||||
#include <QFile>
|
||||
|
||||
class QgsVectorLayer;
|
||||
|
||||
/**
|
||||
* Quantum GIS provider for OpenStreetMap data.
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include "qgslogger.h"
|
||||
|
||||
#include "qgscredentials.h"
|
||||
#include <cassert>
|
||||
|
||||
const QString POSTGRES_KEY = "postgres";
|
||||
const QString POSTGRES_DESCRIPTION = "PostgreSQL/PostGIS data provider";
|
||||
|
@ -19,6 +19,7 @@
|
||||
#ifndef QGSSQLANYWHEREPROVIDER_H
|
||||
#define QGSSQLANYWHEREPROVIDER_H
|
||||
|
||||
#include "qgscoordinatereferencesystem.h"
|
||||
#include "qgsdatasourceuri.h"
|
||||
#include "qgsvectordataprovider.h"
|
||||
#include "qgsrectangle.h"
|
||||
|
@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>591</width>
|
||||
<height>426</height>
|
||||
<width>670</width>
|
||||
<height>625</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -21,7 +21,7 @@
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="0" colspan="2">
|
||||
<item row="1" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbnLoadDefaultStyle">
|
||||
@ -53,7 +53,7 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<item row="2" column="0">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
@ -63,7 +63,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<item row="0" column="0">
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
@ -372,8 +372,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>432</width>
|
||||
<height>419</height>
|
||||
<width>648</width>
|
||||
<height>501</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
@ -679,11 +679,522 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="mDiagramPage">
|
||||
<attribute name="icon">
|
||||
<iconset resource="../../images/images.qrc">
|
||||
<normaloff>:/images/themes/default/propertyicons/diagram.png</normaloff>:/images/themes/default/propertyicons/diagram.png</iconset>
|
||||
</attribute>
|
||||
<attribute name="title">
|
||||
<string>Diagrams</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_14">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="mDisplayDiagramsCheckBox">
|
||||
<property name="text">
|
||||
<string>Display diagrams</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<layout class="QHBoxLayout" name="_2">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="mTypeLabel">
|
||||
<property name="text">
|
||||
<string>Diagram type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="mDiagramTypeComboBox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="3" colspan="3">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QLabel" name="mPriorityLabel">
|
||||
<property name="text">
|
||||
<string>Priority:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="mPriorityLowLabel">
|
||||
<property name="text">
|
||||
<string>Low</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="mPrioritySlider">
|
||||
<property name="maximum">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="invertedAppearance">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="invertedControls">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::TicksBelow</enum>
|
||||
</property>
|
||||
<property name="tickInterval">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="mPriorityHighLabel">
|
||||
<property name="text">
|
||||
<string>High</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="6">
|
||||
<widget class="QGroupBox" name="mAppearanceGroupBox">
|
||||
<property name="title">
|
||||
<string>Appearance</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_13">
|
||||
<item row="0" column="0" colspan="4">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_13">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="mScaleDependentDiagramVisibilityCheckBox">
|
||||
<property name="text">
|
||||
<string>Scale dependent visibility</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="mMinimumDiagramScaleLabel">
|
||||
<property name="text">
|
||||
<string>Minimum</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="mMinimumDiagramScaleLineEdit"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="mMaximumDiagramScaleLabel">
|
||||
<property name="text">
|
||||
<string>Maximum</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="mMaximumDiagramScaleLineEdit"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_8">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_10">
|
||||
<item>
|
||||
<widget class="QLabel" name="mBackgroundColorLabel">
|
||||
<property name="text">
|
||||
<string>Background color</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QgsColorButton" name="mBackgroundColorButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>25</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_11">
|
||||
<item>
|
||||
<widget class="QLabel" name="mPenColorLabel">
|
||||
<property name="text">
|
||||
<string>Pen color</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QgsColorButton" name="mDiagramPenColorButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>25</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_16">
|
||||
<item>
|
||||
<widget class="QLabel" name="mPenWidthLabel">
|
||||
<property name="text">
|
||||
<string>Pen width</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="mPenWidthSpinBox">
|
||||
<property name="maximum">
|
||||
<double>99999.990000000005239</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<widget class="QPushButton" name="mDiagramFontButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Font...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<zorder></zorder>
|
||||
<zorder></zorder>
|
||||
<zorder>mDiagramFontButton</zorder>
|
||||
<zorder></zorder>
|
||||
<zorder>mPenWidthSpinBox</zorder>
|
||||
<zorder>mPenWidthLabel</zorder>
|
||||
<zorder>mPenWidthLabel</zorder>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="6">
|
||||
<widget class="QGroupBox" name="mSizeGroupBox">
|
||||
<property name="title">
|
||||
<string>Size</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_12">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="mFixedSizeCheckBox">
|
||||
<property name="text">
|
||||
<string>Fixed size</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QDoubleSpinBox" name="mDiagramSizeSpinBox">
|
||||
<property name="maximum">
|
||||
<double>9999999.990000000223517</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>335</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="4">
|
||||
<widget class="QLabel" name="mLinearlyScalingLabel">
|
||||
<property name="text">
|
||||
<string>Scale linearly between 0 and the following attribute value / diagram size:</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="4">
|
||||
<layout class="QHBoxLayout" name="mLinearlyScalingLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="mSizeAttributeLabel">
|
||||
<property name="text">
|
||||
<string>Attribute</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="mSizeAttributeComboBox"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="mFindMaximumValueButton">
|
||||
<property name="text">
|
||||
<string>Find maximum value</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="mValueLineEdit"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="mSizeLabel">
|
||||
<property name="text">
|
||||
<string>Size</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="mSizeSpinBox">
|
||||
<property name="maximum">
|
||||
<number>10000000</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_12">
|
||||
<item>
|
||||
<widget class="QLabel" name="mDiagramUnitsLabel">
|
||||
<property name="text">
|
||||
<string>Size units</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="mDiagramUnitComboBox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="6">
|
||||
<widget class="QGroupBox" name="mPlacementGroupBox">
|
||||
<property name="title">
|
||||
<string>Position</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_11">
|
||||
<item row="0" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||
<item>
|
||||
<widget class="QLabel" name="mPlacementLabel">
|
||||
<property name="text">
|
||||
<string>Placement</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="mPlacementComboBox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_9">
|
||||
<item>
|
||||
<widget class="QLabel" name="mLineOptionsLabel">
|
||||
<property name="text">
|
||||
<string>Line Options</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="mLineOptionsComboBox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="mDiagramDistanceLabel">
|
||||
<property name="text">
|
||||
<string>Distance</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="mDiagramDistanceSpinBox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="mDataDefinedPositionLabel">
|
||||
<property name="text">
|
||||
<string>Date defined position</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<widget class="QLabel" name="mXPosColLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>x</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="mDataDefinedXComboBox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||
<item>
|
||||
<widget class="QLabel" name="mYPosColLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>y</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="mDataDefinedYComboBox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="mAttributesLabel">
|
||||
<property name="text">
|
||||
<string>Attributes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1" colspan="2">
|
||||
<widget class="QComboBox" name="mDiagramAttributesComboBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="3">
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>241</width>
|
||||
<height>23</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="4" column="4">
|
||||
<widget class="QPushButton" name="mRemoveCategoryPushButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../images/images.qrc">
|
||||
<normaloff>:/images/themes/default/symbologyRemove.png</normaloff>:/images/themes/default/symbologyRemove.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="5">
|
||||
<widget class="QPushButton" name="mAddCategoryPushButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../images/images.qrc">
|
||||
<normaloff>:/images/themes/default/symbologyAdd.png</normaloff>:/images/themes/default/symbologyAdd.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="6">
|
||||
<widget class="QTreeWidget" name="mDiagramAttributesTreeWidget">
|
||||
<property name="columnCount">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Attribute</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Color</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>QgsColorButton</class>
|
||||
<extends>QToolButton</extends>
|
||||
<header>qgscolorbutton.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>txtDisplayName</tabstop>
|
||||
<tabstop>displayFieldComboBox</tabstop>
|
||||
|
Loading…
x
Reference in New Issue
Block a user