mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-13 00:03:09 -04:00
[FEATURE]: move/rotate/change label edit tools to interactively change data defined label properties
git-svn-id: http://svn.osgeo.org/qgis/trunk@14697 c8812cc2-4d05-0410-92ff-de0c093fc19c
This commit is contained in:
parent
2fd7c32a37
commit
ac51927071
@ -123,6 +123,7 @@
|
||||
<file>themes/default/mActionCaptureLine.png</file>
|
||||
<file>themes/default/mActionCapturePoint.png</file>
|
||||
<file>themes/default/mActionCapturePolygon.png</file>
|
||||
<file>themes/default/mActionChangeLabelProperties.png</file>
|
||||
<file>themes/default/mActionCheckQgisVersion.png</file>
|
||||
<file>themes/default/mActionCollapseTree.png</file>
|
||||
<file>themes/default/mActionComposerManager.png</file>
|
||||
@ -168,6 +169,7 @@
|
||||
<file>themes/default/mActionMergeFeatures.png</file>
|
||||
<file>themes/default/mActionMergeFeatureAttributes.png</file>
|
||||
<file>themes/default/mActionMoveFeature.png</file>
|
||||
<file>themes/default/mActionMoveLabel.png</file>
|
||||
<file>themes/default/mActionMoveItemContent.png</file>
|
||||
<file>themes/default/mActionMoveItemsToBottom.png</file>
|
||||
<file>themes/default/mActionMoveItemsToTop.png</file>
|
||||
@ -191,6 +193,7 @@
|
||||
<file>themes/default/mActionRemoveLayer.png</file>
|
||||
<file>themes/default/mActionRemoveSelectedFeature.png</file>
|
||||
<file>themes/default/mActionReshape.png</file>
|
||||
<file>themes/default/mActionRotateLabel.png</file>
|
||||
<file>themes/default/mActionRotatePointSymbols.png</file>
|
||||
<file>themes/default/mActionSaveAsPDF.png</file>
|
||||
<file>themes/default/mActionSaveAsSVG.png</file>
|
||||
|
BIN
images/themes/default/mActionChangeLabelProperties.png
Normal file
BIN
images/themes/default/mActionChangeLabelProperties.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
BIN
images/themes/default/mActionMoveLabel.png
Normal file
BIN
images/themes/default/mActionMoveLabel.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.0 KiB |
BIN
images/themes/default/mActionRotateLabel.png
Normal file
BIN
images/themes/default/mActionRotateLabel.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
@ -25,11 +25,32 @@ public:
|
||||
virtual void drawLabeling( QgsRenderContext& context ) = 0;
|
||||
//! called when we're done with rendering
|
||||
virtual void exit() = 0;
|
||||
//! return infos about labels at a given (map) position
|
||||
//! @note: this method was added in version 1.7
|
||||
virtual QList<QgsLabelPosition> labelsAtPosition( const QgsPoint& p )= 0;
|
||||
|
||||
|
||||
//! called when passing engine among map renderers
|
||||
virtual QgsLabelingEngineInterface* clone() = 0;
|
||||
};
|
||||
|
||||
struct QgsLabelPosition
|
||||
{
|
||||
%TypeHeaderCode
|
||||
#include <qgsmaprenderer.h>
|
||||
%End
|
||||
QgsLabelPosition( int id, double r, const QVector< QgsPoint >& corners, const QgsRectangle& rect, double w, double h, const QString& layer, bool upside_down );
|
||||
QgsLabelPosition();
|
||||
int featureId;
|
||||
double rotation;
|
||||
QVector< QgsPoint > cornerPoints;
|
||||
QgsRectangle labelRect;
|
||||
double width;
|
||||
double height;
|
||||
QString layerID;
|
||||
bool upsideDown;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \class QgsMapRenderer
|
||||
|
@ -77,6 +77,10 @@ public:
|
||||
@note added in QGIS 1.5*/
|
||||
double sqrDistToSegment( double x1, double y1, double x2, double y2, QgsPoint& minDistPoint /Out/) const;
|
||||
|
||||
/**Calculates azimut between this point and other one (clockwise in degree, starting from north)
|
||||
@note: this function has been added in version 1.7*/
|
||||
double azimuth( const QgsPoint& other );
|
||||
|
||||
//! equality operator
|
||||
bool operator==(const QgsPoint &other);
|
||||
|
||||
|
@ -28,6 +28,7 @@ SET(QGIS_APP_SRCS
|
||||
qgsidentifyresults.cpp
|
||||
qgsfeatureaction.cpp
|
||||
qgslabeldialog.cpp
|
||||
qgslabelpropertydialog.cpp
|
||||
qgslabelengineconfigdialog.cpp
|
||||
qgslabelinggui.cpp
|
||||
qgslabelpreview.cpp
|
||||
@ -37,17 +38,21 @@ SET(QGIS_APP_SRCS
|
||||
qgsmaptooladdring.cpp
|
||||
qgsmaptoolannotation.cpp
|
||||
qgsmaptoolcapture.cpp
|
||||
qgsmaptoolchangelabelproperties.cpp
|
||||
qgsmaptooldeletering.cpp
|
||||
qgsmaptooldeletepart.cpp
|
||||
qgsmaptooldeletevertex.cpp
|
||||
qgsmaptooledit.cpp
|
||||
qgsmaptoolformannotation.cpp
|
||||
qgsmaptoolidentify.cpp
|
||||
qgsmaptoollabel.cpp
|
||||
qgsmaptoolmeasureangle.cpp
|
||||
qgsmaptoolmovefeature.cpp
|
||||
qgsmaptoolmovelabel.cpp
|
||||
qgsmaptoolmovevertex.cpp
|
||||
qgsmaptoolnodetool.cpp
|
||||
qgsmaptoolreshape.cpp
|
||||
qgsmaptoolrotatelabel.cpp
|
||||
qgsmaptoolrotatepointsymbols.cpp
|
||||
qgsmaptoolselect.cpp
|
||||
qgsmaptoolselectrectangle.cpp
|
||||
@ -175,6 +180,7 @@ SET (QGIS_APP_MOC_HDRS
|
||||
qgsidentifyresults.h
|
||||
qgsfeatureaction.h
|
||||
qgslabeldialog.h
|
||||
qgslabelpropertydialog.h
|
||||
qgsmanageconnectionsdialog.h
|
||||
qgsmaptoolidentify.h
|
||||
qgsmaptoolsplitfeatures.h
|
||||
|
@ -212,6 +212,9 @@
|
||||
#include "qgsmaptoolzoom.h"
|
||||
#include "qgsmaptoolsimplify.h"
|
||||
#include "qgsmeasuretool.h"
|
||||
#include "qgsmaptoolmovelabel.h"
|
||||
#include "qgsmaptoolrotatelabel.h"
|
||||
#include "qgsmaptoolchangelabelproperties.h"
|
||||
|
||||
//
|
||||
// Conditional Includes
|
||||
@ -580,6 +583,8 @@ QgisApp::~QgisApp()
|
||||
delete mMapTools.mDeletePart;
|
||||
delete mMapTools.mAddIsland;
|
||||
delete mMapTools.mNodeTool;
|
||||
delete mMapTools.mMoveLabel;
|
||||
delete mMapTools.mChangeLabelProperties;
|
||||
|
||||
delete mPythonUtils;
|
||||
|
||||
@ -1229,6 +1234,18 @@ void QgisApp::createActions()
|
||||
mActionAbout->setMenuRole( QAction::AboutRole ); // put in application menu on Mac OS X
|
||||
connect( mActionAbout, SIGNAL( triggered() ), this, SLOT( about() ) );
|
||||
|
||||
mActionMoveLabel = new QAction( getThemeIcon( "mActionMoveLabel.png" ), tr( "Move Label" ), this );
|
||||
mActionMoveLabel->setStatusTip( tr( "Move labels interactively" ) );
|
||||
connect( mActionMoveLabel, SIGNAL( triggered() ), this, SLOT( moveLabel() ) );
|
||||
|
||||
mActionRotateLabel = new QAction( getThemeIcon( "mActionRotateLabel.png" ), tr( "Rotate Label" ), this );
|
||||
mActionRotateLabel->setStatusTip( tr( "Rotate labels interactively" ) );
|
||||
connect( mActionRotateLabel, SIGNAL( triggered() ), this, SLOT( rotateLabel() ) );
|
||||
|
||||
mActionChangeLabelProperties = new QAction( getThemeIcon( "mActionChangeLabelProperties.png" ), tr( "Change label" ), this );
|
||||
mActionChangeLabelProperties->setStatusTip( tr( "Change label properties" ) );
|
||||
connect( mActionChangeLabelProperties, SIGNAL( triggered() ), this, SLOT( changeLabelProperties() ) );
|
||||
|
||||
mActionStyleManagerV2 = new QAction( tr( "Style manager..." ), this );
|
||||
shortcuts->registerAction( mActionStyleManagerV2 );
|
||||
mActionStyleManagerV2->setStatusTip( tr( "Show style manager V2" ) );
|
||||
@ -1349,6 +1366,12 @@ void QgisApp::createActionGroups()
|
||||
mMapToolGroup->addAction( mActionNodeTool );
|
||||
mActionRotatePointSymbols->setCheckable( true );
|
||||
mMapToolGroup->addAction( mActionRotatePointSymbols );
|
||||
mActionMoveLabel->setCheckable( true );
|
||||
mMapToolGroup->addAction( mActionMoveLabel );
|
||||
mActionRotateLabel->setCheckable( true );
|
||||
mMapToolGroup->addAction( mActionRotateLabel );
|
||||
mActionChangeLabelProperties->setCheckable( true );
|
||||
mMapToolGroup->addAction( mActionChangeLabelProperties );
|
||||
}
|
||||
|
||||
void QgisApp::createMenus()
|
||||
@ -1606,7 +1629,7 @@ void QgisApp::createMenus()
|
||||
// don't add it yet, wait for a plugin
|
||||
mDatabaseMenu = new QMenu( tr( "&Database" ) );
|
||||
|
||||
|
||||
|
||||
// Raster Menu
|
||||
|
||||
mRasterMenu = menuBar()->addMenu( tr( "&Raster" ) );
|
||||
@ -1843,6 +1866,15 @@ void QgisApp::createToolBars()
|
||||
mHelpToolBar->addAction( mActionHelpContents );
|
||||
mHelpToolBar->addAction( QWhatsThis::createAction() );
|
||||
mToolbarMenu->addAction( mHelpToolBar->toggleViewAction() );
|
||||
|
||||
//Label Toolbar
|
||||
mLabelToolBar = addToolBar( tr( "Label" ) );
|
||||
mLabelToolBar->setIconSize( myIconSize );
|
||||
mLabelToolBar->setObjectName( "Label" );
|
||||
mLabelToolBar->addAction( mActionMoveLabel );
|
||||
mLabelToolBar->addAction( mActionRotateLabel );
|
||||
mLabelToolBar->addAction( mActionChangeLabelProperties );
|
||||
mToolbarMenu->addAction( mLabelToolBar->toggleViewAction() );
|
||||
}
|
||||
|
||||
void QgisApp::createStatusBar()
|
||||
@ -2245,6 +2277,12 @@ void QgisApp::createCanvasTools()
|
||||
mMapTools.mNodeTool->setAction( mActionNodeTool );
|
||||
mMapTools.mRotatePointSymbolsTool = new QgsMapToolRotatePointSymbols( mMapCanvas );
|
||||
mMapTools.mRotatePointSymbolsTool->setAction( mActionRotatePointSymbols );
|
||||
mMapTools.mMoveLabel = new QgsMapToolMoveLabel( mMapCanvas );
|
||||
mMapTools.mMoveLabel->setAction( mActionMoveLabel );
|
||||
mMapTools.mRotateLabel = new QgsMapToolRotateLabel( mMapCanvas );
|
||||
mMapTools.mRotateLabel->setAction( mActionRotateLabel );
|
||||
mMapTools.mChangeLabelProperties = new QgsMapToolChangeLabelProperties( mMapCanvas );
|
||||
mMapTools.mChangeLabelProperties->setAction( mActionChangeLabelProperties );
|
||||
//ensure that non edit tool is initialised or we will get crashes in some situations
|
||||
mNonEditMapTool = mMapTools.mPan;
|
||||
}
|
||||
@ -4250,6 +4288,21 @@ bool QgisApp::loadAnnotationItemsFromProject( const QDomDocument& doc )
|
||||
return true;
|
||||
}
|
||||
|
||||
void QgisApp::moveLabel()
|
||||
{
|
||||
mMapCanvas->setMapTool( mMapTools.mMoveLabel );
|
||||
}
|
||||
|
||||
void QgisApp::rotateLabel()
|
||||
{
|
||||
mMapCanvas->setMapTool( mMapTools.mRotateLabel );
|
||||
}
|
||||
|
||||
void QgisApp::changeLabelProperties()
|
||||
{
|
||||
mMapCanvas->setMapTool( mMapTools.mChangeLabelProperties );
|
||||
}
|
||||
|
||||
QList<QgsAnnotationItem*> QgisApp::annotationItems()
|
||||
{
|
||||
QList<QgsAnnotationItem*> itemList;
|
||||
|
@ -757,6 +757,13 @@ class QgisApp : public QMainWindow
|
||||
|
||||
bool loadAnnotationItemsFromProject( const QDomDocument& doc );
|
||||
|
||||
//! Activates the move label tool
|
||||
void moveLabel();
|
||||
//! Activates rotate label tool
|
||||
void rotateLabel();
|
||||
//! Activates label property tool
|
||||
void changeLabelProperties();
|
||||
|
||||
signals:
|
||||
/** emitted when a key is pressed and we want non widget sublasses to be able
|
||||
to pick up on this (e.g. maplayer) */
|
||||
@ -866,6 +873,7 @@ class QgisApp : public QMainWindow
|
||||
QToolBar *mAttributesToolBar;
|
||||
QToolBar *mPluginToolBar;
|
||||
QToolBar *mHelpToolBar;
|
||||
QToolBar *mLabelToolBar;
|
||||
|
||||
// actions for menus and toolbars -----------------
|
||||
|
||||
@ -1002,6 +1010,10 @@ class QgisApp : public QMainWindow
|
||||
QAction *mActionHelpSeparator2;
|
||||
QAction *mActionAbout;
|
||||
|
||||
QAction *mActionMoveLabel;
|
||||
QAction *mActionRotateLabel;
|
||||
QAction *mActionChangeLabelProperties;
|
||||
|
||||
QAction *mActionUseRendererV2;
|
||||
QAction *mActionStyleManagerV2;
|
||||
|
||||
@ -1069,6 +1081,9 @@ class QgisApp : public QMainWindow
|
||||
QgsMapTool* mAnnotation;
|
||||
QgsMapTool* mFormAnnotation;
|
||||
QgsMapTool* mTextAnnotation;
|
||||
QgsMapTool* mMoveLabel;
|
||||
QgsMapTool* mRotateLabel;
|
||||
QgsMapTool* mChangeLabelProperties;
|
||||
} mMapTools;
|
||||
|
||||
QgsMapTool *mNonEditMapTool;
|
||||
|
76
src/app/qgsmaptoolchangelabelproperties.cpp
Normal file
76
src/app/qgsmaptoolchangelabelproperties.cpp
Normal file
@ -0,0 +1,76 @@
|
||||
/***************************************************************************
|
||||
qgsmaptoolchangelabelproperties.cpp
|
||||
---------------------------------
|
||||
begin : 2010-11-11
|
||||
copyright : (C) 2010 by Marco Hugentobler
|
||||
email : marco dot hugentobler at sourcepole dot ch
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "qgsmaptoolchangelabelproperties.h"
|
||||
#include "qgslabelpropertydialog.h"
|
||||
#include "qgsmapcanvas.h"
|
||||
#include "qgsrubberband.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
|
||||
QgsMapToolChangeLabelProperties::QgsMapToolChangeLabelProperties( QgsMapCanvas* canvas ): QgsMapToolLabel( canvas )
|
||||
{
|
||||
}
|
||||
|
||||
QgsMapToolChangeLabelProperties::~QgsMapToolChangeLabelProperties()
|
||||
{
|
||||
}
|
||||
|
||||
void QgsMapToolChangeLabelProperties::canvasPressEvent( QMouseEvent * e )
|
||||
{
|
||||
deleteRubberBands();
|
||||
|
||||
if ( !labelAtPosition( e, mCurrentLabelPos ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QgsVectorLayer* vlayer = currentLayer();
|
||||
if ( !vlayer || !vlayer->isEditable() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
createRubberBands();
|
||||
}
|
||||
|
||||
void QgsMapToolChangeLabelProperties::canvasReleaseEvent( QMouseEvent * e )
|
||||
{
|
||||
QgsVectorLayer* vlayer = currentLayer();
|
||||
if ( mLabelRubberBand && mCanvas && vlayer )
|
||||
{
|
||||
QgsLabelPropertyDialog d( mCurrentLabelPos.layerID, mCurrentLabelPos.featureId, mCanvas->mapRenderer() );
|
||||
if ( d.exec() == QDialog::Accepted )
|
||||
{
|
||||
const QgsAttributeMap& changes = d.changedProperties();
|
||||
if ( changes.size() > 0 )
|
||||
{
|
||||
vlayer->beginEditCommand( tr( "Label properties changed" ) );
|
||||
|
||||
QgsAttributeMap::const_iterator changeIt = changes.constBegin();
|
||||
for ( ; changeIt != changes.constEnd(); ++changeIt )
|
||||
{
|
||||
vlayer->changeAttributeValue( mCurrentLabelPos.featureId, changeIt.key(), changeIt.value(), false );
|
||||
}
|
||||
|
||||
vlayer->endEditCommand();
|
||||
mCanvas->refresh();
|
||||
}
|
||||
}
|
||||
deleteRubberBands();
|
||||
}
|
||||
}
|
||||
|
34
src/app/qgsmaptoolchangelabelproperties.h
Normal file
34
src/app/qgsmaptoolchangelabelproperties.h
Normal file
@ -0,0 +1,34 @@
|
||||
/***************************************************************************
|
||||
qgsmaptoolchangelabelproperties.h
|
||||
---------------------------------
|
||||
begin : 2010-11-11
|
||||
copyright : (C) 2010 by Marco Hugentobler
|
||||
email : marco dot hugentobler at sourcepole dot ch
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef QGSMAPTOOLCHANGELABELPROPERTIES_H
|
||||
#define QGSMAPTOOLCHANGELABELPROPERTIES_H
|
||||
|
||||
#include "qgsmaptoollabel.h"
|
||||
|
||||
class QgsMapToolChangeLabelProperties: public QgsMapToolLabel
|
||||
{
|
||||
public:
|
||||
QgsMapToolChangeLabelProperties( QgsMapCanvas* canvas );
|
||||
~QgsMapToolChangeLabelProperties();
|
||||
|
||||
virtual void canvasPressEvent( QMouseEvent * e );
|
||||
virtual void canvasReleaseEvent( QMouseEvent * e );
|
||||
|
||||
};
|
||||
|
||||
#endif // QGSMAPTOOLCHANGELABEL_H
|
347
src/app/qgsmaptoollabel.cpp
Normal file
347
src/app/qgsmaptoollabel.cpp
Normal file
@ -0,0 +1,347 @@
|
||||
/***************************************************************************
|
||||
qgsmaptoollabel.cpp
|
||||
--------------------
|
||||
begin : 2010-11-03
|
||||
copyright : (C) 2010 by Marco Hugentobler
|
||||
email : marco dot hugentobler at sourcepole dot ch
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "qgsmaptoollabel.h"
|
||||
#include "qgsmapcanvas.h"
|
||||
#include "qgsmaplayerregistry.h"
|
||||
#include "qgsrubberband.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
#include <QMouseEvent>
|
||||
|
||||
QgsMapToolLabel::QgsMapToolLabel( QgsMapCanvas* canvas ): QgsMapTool( canvas ), mLabelRubberBand( 0 ), mFeatureRubberBand( 0 ), mFixPointRubberBand( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
QgsMapToolLabel::~QgsMapToolLabel()
|
||||
{
|
||||
delete mLabelRubberBand;
|
||||
delete mFeatureRubberBand;
|
||||
delete mFixPointRubberBand;
|
||||
}
|
||||
|
||||
bool QgsMapToolLabel::labelAtPosition( QMouseEvent* e, QgsLabelPosition& p )
|
||||
{
|
||||
QgsPoint pt = toMapCoordinates( e->pos() );
|
||||
QgsLabelingEngineInterface* labelingEngine = mCanvas->mapRenderer()->labelingEngine();
|
||||
if ( labelingEngine )
|
||||
{
|
||||
QList<QgsLabelPosition> labelPosList = labelingEngine->labelsAtPosition( pt );
|
||||
QList<QgsLabelPosition>::const_iterator posIt = labelPosList.constBegin();
|
||||
if ( posIt != labelPosList.constEnd() )
|
||||
{
|
||||
p = *posIt;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void QgsMapToolLabel::createRubberBands( )
|
||||
{
|
||||
delete mLabelRubberBand;
|
||||
delete mFeatureRubberBand;
|
||||
|
||||
//label rubber band
|
||||
QgsRectangle rect = mCurrentLabelPos.labelRect;
|
||||
mLabelRubberBand = new QgsRubberBand( mCanvas, false );
|
||||
mLabelRubberBand->addPoint( QgsPoint( rect.xMinimum(), rect.yMinimum() ) );
|
||||
mLabelRubberBand->addPoint( QgsPoint( rect.xMinimum(), rect.yMaximum() ) );
|
||||
mLabelRubberBand->addPoint( QgsPoint( rect.xMaximum(), rect.yMaximum() ) );
|
||||
mLabelRubberBand->addPoint( QgsPoint( rect.xMaximum(), rect.yMinimum() ) );
|
||||
mLabelRubberBand->addPoint( QgsPoint( rect.xMinimum(), rect.yMinimum() ) );
|
||||
mLabelRubberBand->setColor( Qt::green );
|
||||
mLabelRubberBand->setWidth( 3 );
|
||||
mLabelRubberBand->show();
|
||||
|
||||
//feature rubber band
|
||||
QgsVectorLayer* vlayer = currentLayer();
|
||||
if ( vlayer )
|
||||
{
|
||||
QgsFeature f;
|
||||
if ( currentFeature( f, true ) )
|
||||
{
|
||||
QgsGeometry* geom = f.geometry();
|
||||
if ( geom )
|
||||
{
|
||||
mFeatureRubberBand = new QgsRubberBand( mCanvas, geom->type() == QGis::Polygon );
|
||||
mFeatureRubberBand->setColor( Qt::red );
|
||||
mFeatureRubberBand->setToGeometry( geom, vlayer );
|
||||
mFeatureRubberBand->show();
|
||||
}
|
||||
}
|
||||
|
||||
//fixpoint rubber band
|
||||
QgsPoint fixPoint;
|
||||
if ( rotationPoint( fixPoint ) )
|
||||
{
|
||||
QgsGeometry* pointGeom = QgsGeometry::fromPoint( fixPoint );
|
||||
mFixPointRubberBand = new QgsRubberBand( mCanvas, false );
|
||||
mFixPointRubberBand->setColor( Qt::blue );
|
||||
mFixPointRubberBand->setToGeometry( pointGeom, vlayer );
|
||||
mFixPointRubberBand->show();
|
||||
delete pointGeom;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QgsMapToolLabel::deleteRubberBands()
|
||||
{
|
||||
delete mLabelRubberBand; mLabelRubberBand = 0;
|
||||
delete mFeatureRubberBand; mFeatureRubberBand = 0;
|
||||
delete mFixPointRubberBand; mFixPointRubberBand = 0;
|
||||
}
|
||||
|
||||
QgsVectorLayer* QgsMapToolLabel::currentLayer()
|
||||
{
|
||||
QgsVectorLayer* vlayer = dynamic_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( mCurrentLabelPos.layerID ) );
|
||||
return vlayer;
|
||||
}
|
||||
|
||||
QgsPalLayerSettings& QgsMapToolLabel::currentLabelSettings( bool* ok )
|
||||
{
|
||||
QgsVectorLayer* vlayer = currentLayer();
|
||||
if ( vlayer )
|
||||
{
|
||||
QgsPalLabeling* labelEngine = dynamic_cast<QgsPalLabeling*>( mCanvas->mapRenderer()->labelingEngine() );
|
||||
if ( labelEngine )
|
||||
{
|
||||
if ( ok )
|
||||
{
|
||||
*ok = true;
|
||||
}
|
||||
return labelEngine->layer( mCurrentLabelPos.layerID );
|
||||
}
|
||||
}
|
||||
|
||||
if ( ok )
|
||||
{
|
||||
*ok = false;
|
||||
}
|
||||
return mInvalidLabelSettings;
|
||||
}
|
||||
|
||||
QString QgsMapToolLabel::currentLabelText()
|
||||
{
|
||||
QgsVectorLayer* vlayer = currentLayer();
|
||||
if ( !vlayer )
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
QString labelField = vlayer->customProperty( "labeling/fieldName" ).toString();
|
||||
if ( !labelField.isEmpty() )
|
||||
{
|
||||
int labelFieldId = vlayer->fieldNameIndex( labelField );
|
||||
QgsFeature f;
|
||||
if ( vlayer->featureAtId( mCurrentLabelPos.featureId, f, false, true ) )
|
||||
{
|
||||
return f.attributeMap()[labelFieldId].toString();
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void QgsMapToolLabel::currentAlignment( QString& hali, QString& vali )
|
||||
{
|
||||
hali = "Left";
|
||||
vali = "Bottom";
|
||||
|
||||
QgsFeature f;
|
||||
if ( !currentFeature( f ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
const QgsAttributeMap& featureAttributes = f.attributeMap();
|
||||
|
||||
bool settingsOk;
|
||||
QgsPalLayerSettings& labelSettings = currentLabelSettings( &settingsOk );
|
||||
if ( settingsOk )
|
||||
{
|
||||
QMap< QgsPalLayerSettings::DataDefinedProperties, int > ddProperties = labelSettings.dataDefinedProperties;
|
||||
|
||||
QMap< QgsPalLayerSettings::DataDefinedProperties, int >::const_iterator haliIter = ddProperties.find( QgsPalLayerSettings::Hali );
|
||||
if ( haliIter != ddProperties.constEnd() )
|
||||
{
|
||||
hali = featureAttributes[*haliIter].toString();
|
||||
}
|
||||
|
||||
QMap< QgsPalLayerSettings::DataDefinedProperties, int >::const_iterator valiIter = ddProperties.find( QgsPalLayerSettings::Vali );
|
||||
if ( valiIter != ddProperties.constEnd() )
|
||||
{
|
||||
vali = featureAttributes[*valiIter].toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool QgsMapToolLabel::currentFeature( QgsFeature& f, bool fetchGeom )
|
||||
{
|
||||
QgsVectorLayer* vlayer = currentLayer();
|
||||
if ( !vlayer )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return vlayer->featureAtId( mCurrentLabelPos.featureId, f, fetchGeom, true );
|
||||
}
|
||||
|
||||
QFont QgsMapToolLabel::labelFontCurrentFeature()
|
||||
{
|
||||
QFont font;
|
||||
QgsVectorLayer* vlayer = currentLayer();
|
||||
|
||||
bool labelSettingsOk;
|
||||
QgsPalLayerSettings& layerSettings = currentLabelSettings( &labelSettingsOk );
|
||||
|
||||
if ( labelSettingsOk && vlayer )
|
||||
{
|
||||
font = layerSettings.textFont;
|
||||
|
||||
QgsFeature f;
|
||||
if ( vlayer->featureAtId( mCurrentLabelPos.featureId, f, false, true ) )
|
||||
{
|
||||
const QgsAttributeMap& attributes = f.attributeMap();
|
||||
QMap< QgsPalLayerSettings::DataDefinedProperties, int > ddProperties = layerSettings.dataDefinedProperties;
|
||||
|
||||
//size
|
||||
QMap< QgsPalLayerSettings::DataDefinedProperties, int >::const_iterator sizeIt = ddProperties.find( QgsPalLayerSettings::Size );
|
||||
if ( sizeIt != ddProperties.constEnd() )
|
||||
{
|
||||
font.setPointSizeF( attributes[*sizeIt].toDouble() );
|
||||
}
|
||||
|
||||
//family
|
||||
QMap< QgsPalLayerSettings::DataDefinedProperties, int >::const_iterator familyIt = ddProperties.find( QgsPalLayerSettings::Family );
|
||||
if ( familyIt != ddProperties.constEnd() )
|
||||
{
|
||||
font.setFamily( attributes[*sizeIt].toString() );
|
||||
}
|
||||
|
||||
//underline
|
||||
QMap< QgsPalLayerSettings::DataDefinedProperties, int >::const_iterator underlineIt = ddProperties.find( QgsPalLayerSettings::Underline );
|
||||
if ( familyIt != ddProperties.constEnd() )
|
||||
{
|
||||
font.setUnderline( attributes[*underlineIt].toBool() );
|
||||
}
|
||||
|
||||
//strikeout
|
||||
QMap< QgsPalLayerSettings::DataDefinedProperties, int >::const_iterator strikeoutIt = ddProperties.find( QgsPalLayerSettings::Strikeout );
|
||||
if ( strikeoutIt != ddProperties.constEnd() )
|
||||
{
|
||||
font.setStrikeOut( attributes[*strikeoutIt].toBool() );
|
||||
}
|
||||
|
||||
//bold
|
||||
QMap< QgsPalLayerSettings::DataDefinedProperties, int >::const_iterator boldIt = ddProperties.find( QgsPalLayerSettings::Bold );
|
||||
if ( boldIt != ddProperties.constEnd() )
|
||||
{
|
||||
font.setBold( attributes[*boldIt].toBool() );
|
||||
}
|
||||
|
||||
//italic
|
||||
QMap< QgsPalLayerSettings::DataDefinedProperties, int >::const_iterator italicIt = ddProperties.find( QgsPalLayerSettings::Italic );
|
||||
if ( italicIt != ddProperties.constEnd() )
|
||||
{
|
||||
font.setItalic( attributes[*italicIt].toBool() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
bool QgsMapToolLabel::rotationPoint( QgsPoint& pos )
|
||||
{
|
||||
QVector<QgsPoint> cornerPoints = mCurrentLabelPos.cornerPoints;
|
||||
if ( cornerPoints.size() < 4 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( mCurrentLabelPos.upsideDown )
|
||||
{
|
||||
pos = mCurrentLabelPos.cornerPoints.at( 2 );
|
||||
}
|
||||
else
|
||||
{
|
||||
pos = mCurrentLabelPos.cornerPoints.at( 0 );
|
||||
}
|
||||
|
||||
//adapt pos depending on data defined alignment
|
||||
QString haliString, valiString;
|
||||
currentAlignment( haliString, valiString );
|
||||
|
||||
QFont labelFont = labelFontCurrentFeature();
|
||||
QFontMetricsF labelFontMetrics( labelFont );
|
||||
|
||||
//label text?
|
||||
QString labelText = currentLabelText();
|
||||
|
||||
bool labelSettingsOk;
|
||||
QgsPalLayerSettings& labelSettings = currentLabelSettings( &labelSettingsOk );
|
||||
if ( !labelSettingsOk )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
double labelSizeX, labelSizeY;
|
||||
labelSettings.calculateLabelSize( &labelFontMetrics, labelText, labelSizeX, labelSizeY );
|
||||
|
||||
double xdiff = 0;
|
||||
double ydiff = 0;
|
||||
|
||||
if ( haliString.compare( "Center", Qt::CaseInsensitive ) == 0 )
|
||||
{
|
||||
xdiff = labelSizeX / 2.0;
|
||||
}
|
||||
else if ( haliString.compare( "Right", Qt::CaseInsensitive ) == 0 )
|
||||
{
|
||||
xdiff = labelSizeX;
|
||||
}
|
||||
|
||||
if ( valiString.compare( "Top", Qt::CaseInsensitive ) == 0 || valiString.compare( "Cap", Qt::CaseInsensitive ) == 0 )
|
||||
{
|
||||
ydiff = labelSizeY;
|
||||
}
|
||||
else
|
||||
{
|
||||
double descentRatio = labelFontMetrics.descent() / labelFontMetrics.height();
|
||||
if ( valiString.compare( "Base", Qt::CaseInsensitive ) == 0 )
|
||||
{
|
||||
ydiff = labelSizeY * descentRatio;
|
||||
}
|
||||
else if ( valiString.compare( "Half", Qt::CaseInsensitive ) == 0 )
|
||||
{
|
||||
ydiff = labelSizeY * descentRatio;
|
||||
ydiff = labelSizeY * 0.5 * ( 1 - descentRatio );
|
||||
}
|
||||
}
|
||||
|
||||
double angle = mCurrentLabelPos.rotation;
|
||||
double xd = xdiff * cos( angle ) - ydiff * sin( angle );
|
||||
double yd = xdiff * sin( angle ) + ydiff * cos( angle );
|
||||
if ( mCurrentLabelPos.upsideDown )
|
||||
{
|
||||
pos.setX( pos.x() - xd );
|
||||
pos.setY( pos.y() - yd );
|
||||
}
|
||||
else
|
||||
{
|
||||
pos.setX( pos.x() + xd );
|
||||
pos.setY( pos.y() + yd );
|
||||
}
|
||||
return true;
|
||||
}
|
80
src/app/qgsmaptoollabel.h
Normal file
80
src/app/qgsmaptoollabel.h
Normal file
@ -0,0 +1,80 @@
|
||||
/***************************************************************************
|
||||
qgsmaptoollabel.h
|
||||
--------------------
|
||||
begin : 2010-11-03
|
||||
copyright : (C) 2010 by Marco Hugentobler
|
||||
email : marco dot hugentobler at sourcepole dot ch
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef QGSMAPTOOLLABEL_H
|
||||
#define QGSMAPTOOLLABEL_H
|
||||
|
||||
#include "qgsmaptool.h"
|
||||
#include "qgsmaprenderer.h"
|
||||
#include "qgspallabeling.h"
|
||||
#include "qgspoint.h"
|
||||
class QgsRubberBand;
|
||||
|
||||
/**Base class for map tools that modify label properties*/
|
||||
class QgsMapToolLabel: public QgsMapTool
|
||||
{
|
||||
public:
|
||||
QgsMapToolLabel( QgsMapCanvas* canvas );
|
||||
~QgsMapToolLabel();
|
||||
|
||||
protected:
|
||||
QgsRubberBand* mLabelRubberBand;
|
||||
QgsRubberBand* mFeatureRubberBand;
|
||||
/**Shows label fixpoint (left/bottom by default)*/
|
||||
QgsRubberBand* mFixPointRubberBand;
|
||||
|
||||
/**Currently dragged label position*/
|
||||
QgsLabelPosition mCurrentLabelPos;
|
||||
|
||||
/**Returns label position for mouse click location
|
||||
@param e mouse event
|
||||
@param p out: label position
|
||||
@return true in case of success, false if no label at this location*/
|
||||
bool labelAtPosition( QMouseEvent* e, QgsLabelPosition& p );
|
||||
|
||||
/**Finds out rotation point of current label position
|
||||
@return true in case of success*/
|
||||
bool rotationPoint( QgsPoint& pos );
|
||||
|
||||
/**Creates label / feature / fixpoint rubber bands for the current label position*/
|
||||
void createRubberBands();
|
||||
|
||||
/**Removes label / feature / fixpoint rubber bands*/
|
||||
void deleteRubberBands();
|
||||
|
||||
/**Returns vector layer for current label position*/
|
||||
QgsVectorLayer* currentLayer();
|
||||
|
||||
/**Returns layer settings of current label position*/
|
||||
QgsPalLayerSettings& currentLabelSettings( bool* ok );
|
||||
|
||||
QString currentLabelText();
|
||||
|
||||
void currentAlignment( QString& hali, QString& vali );
|
||||
|
||||
/**Gets vector feature for current label pos
|
||||
@return true in case of success*/
|
||||
bool currentFeature( QgsFeature& f, bool fetchGeom = false );
|
||||
|
||||
/**Returns the font for the current feature (considering default font and data defined properties*/
|
||||
QFont labelFontCurrentFeature();
|
||||
|
||||
private:
|
||||
QgsPalLayerSettings mInvalidLabelSettings;
|
||||
};
|
||||
|
||||
#endif // QGSMAPTOOLLABEL_H
|
200
src/app/qgsmaptoolmovelabel.cpp
Normal file
200
src/app/qgsmaptoolmovelabel.cpp
Normal file
@ -0,0 +1,200 @@
|
||||
/***************************************************************************
|
||||
qgsmaptoolmovelabel.cpp
|
||||
-----------------------
|
||||
begin : 2010-11-03
|
||||
copyright : (C) 2010 by Marco Hugentobler
|
||||
email : marco dot hugentobler at sourcepole dot ch
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "qgsmaptoolmovelabel.h"
|
||||
#include "qgsmapcanvas.h"
|
||||
#include "qgsmaplayerregistry.h"
|
||||
#include "qgsrubberband.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
#include <QMouseEvent>
|
||||
|
||||
QgsMapToolMoveLabel::QgsMapToolMoveLabel( QgsMapCanvas* canvas ): QgsMapToolLabel( canvas )
|
||||
{
|
||||
}
|
||||
|
||||
QgsMapToolMoveLabel::~QgsMapToolMoveLabel()
|
||||
{
|
||||
}
|
||||
|
||||
void QgsMapToolMoveLabel::canvasPressEvent( QMouseEvent * e )
|
||||
{
|
||||
deleteRubberBands();
|
||||
|
||||
if ( !labelAtPosition( e, mCurrentLabelPos ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QgsMapLayer* layer = QgsMapLayerRegistry::instance()->mapLayer( mCurrentLabelPos.layerID );
|
||||
if ( !layer )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int xCol, yCol;
|
||||
if ( layerIsMoveable( layer, xCol, yCol ) )
|
||||
{
|
||||
mStartPointMapCoords = toMapCoordinates( e->pos() );
|
||||
mClickOffsetX = mStartPointMapCoords.x() - mCurrentLabelPos.labelRect.xMinimum();
|
||||
mClickOffsetY = mStartPointMapCoords.y() - mCurrentLabelPos.labelRect.yMinimum();
|
||||
createRubberBands();
|
||||
}
|
||||
}
|
||||
|
||||
void QgsMapToolMoveLabel::canvasMoveEvent( QMouseEvent * e )
|
||||
{
|
||||
if ( mLabelRubberBand )
|
||||
{
|
||||
QgsPoint pointCanvasCoords = toMapCoordinates( e->pos() );
|
||||
double offsetX = pointCanvasCoords.x() - mStartPointMapCoords.x();
|
||||
double offsetY = pointCanvasCoords.y() - mStartPointMapCoords.y();
|
||||
mLabelRubberBand->setTranslationOffset( offsetX, offsetY );
|
||||
mLabelRubberBand->updatePosition();
|
||||
mLabelRubberBand->update();
|
||||
mFixPointRubberBand->setTranslationOffset( offsetX, offsetY );
|
||||
mFixPointRubberBand->updatePosition();
|
||||
mFixPointRubberBand->update();
|
||||
}
|
||||
}
|
||||
|
||||
void QgsMapToolMoveLabel::canvasReleaseEvent( QMouseEvent * e )
|
||||
{
|
||||
if ( !mLabelRubberBand )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
deleteRubberBands();
|
||||
|
||||
QgsMapLayer* layer = QgsMapLayerRegistry::instance()->mapLayer( mCurrentLabelPos.layerID );
|
||||
if ( !layer )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QgsVectorLayer* vlayer = dynamic_cast<QgsVectorLayer*>( layer );
|
||||
if ( !vlayer )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !vlayer->isEditable() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QgsPoint releaseCoords = toMapCoordinates( e->pos() );
|
||||
double xdiff = releaseCoords.x() - mStartPointMapCoords.x();
|
||||
double ydiff = releaseCoords.y() - mStartPointMapCoords.y();
|
||||
|
||||
int xCol, yCol;
|
||||
double xPosOrig, yPosOrig;
|
||||
bool xSuccess, ySuccess;
|
||||
|
||||
if ( !dataDefinedPosition( vlayer, mCurrentLabelPos.featureId, xPosOrig, xSuccess, yPosOrig, ySuccess, xCol, yCol ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
double xPosNew, yPosNew;
|
||||
|
||||
if ( !xSuccess || !ySuccess )
|
||||
{
|
||||
xPosNew = releaseCoords.x() - mClickOffsetX;
|
||||
yPosNew = releaseCoords.y() - mClickOffsetY;
|
||||
|
||||
//todo: consider hali/vali if there
|
||||
}
|
||||
else
|
||||
{
|
||||
xPosNew = xPosOrig + xdiff;
|
||||
yPosNew = yPosOrig + ydiff;
|
||||
}
|
||||
|
||||
vlayer->beginEditCommand( tr( "Label moved" ) );
|
||||
vlayer->changeAttributeValue( mCurrentLabelPos.featureId, xCol, xPosNew, false );
|
||||
vlayer->changeAttributeValue( mCurrentLabelPos.featureId, yCol, yPosNew, false );
|
||||
vlayer->endEditCommand();
|
||||
|
||||
mCanvas->refresh();
|
||||
}
|
||||
|
||||
bool QgsMapToolMoveLabel::dataDefinedPosition( QgsVectorLayer* vlayer, int featureId, double& x, bool& xSuccess, double& y, bool& ySuccess, int& xCol, int& yCol ) const
|
||||
{
|
||||
xSuccess = false;
|
||||
ySuccess = false;
|
||||
|
||||
if ( !vlayer )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !layerIsMoveable( vlayer, xCol, yCol ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QgsFeature f;
|
||||
if ( !vlayer->featureAtId( featureId, f, false, true ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QgsAttributeMap attributes = f.attributeMap();
|
||||
x = attributes[xCol].toDouble( &xSuccess );
|
||||
y = attributes[yCol].toDouble( &ySuccess );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QgsMapToolMoveLabel::layerIsMoveable( const QgsMapLayer* ml, int& xCol, int& yCol ) const
|
||||
{
|
||||
const QgsVectorLayer* vlayer = dynamic_cast<const QgsVectorLayer*>( ml );
|
||||
if ( !vlayer || !vlayer->isEditable() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool xColOk, yColOk;
|
||||
|
||||
QVariant xColumn = ml->customProperty( "labeling/dataDefinedProperty9" );
|
||||
if ( !xColumn.isValid() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
xCol = xColumn.toInt( &xColOk );
|
||||
if ( !xColOk )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QVariant yColumn = ml->customProperty( "labeling/dataDefinedProperty10" );
|
||||
if ( !yColumn.isValid() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
yCol = yColumn.toInt( &yColOk );
|
||||
if ( !yColOk )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
61
src/app/qgsmaptoolmovelabel.h
Normal file
61
src/app/qgsmaptoolmovelabel.h
Normal file
@ -0,0 +1,61 @@
|
||||
/***************************************************************************
|
||||
qgsmaptoolmovelabel.h
|
||||
--------------------
|
||||
begin : 2010-11-03
|
||||
copyright : (C) 2010 by Marco Hugentobler
|
||||
email : marco dot hugentobler at sourcepole dot ch
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef QGSMAPTOOLMOVELABEL_H
|
||||
#define QGSMAPTOOLMOVELABEL_H
|
||||
|
||||
#include "qgsmaptoollabel.h"
|
||||
|
||||
/**A map tool for dragging label positions*/
|
||||
class QgsMapToolMoveLabel: public QgsMapToolLabel
|
||||
{
|
||||
public:
|
||||
QgsMapToolMoveLabel( QgsMapCanvas* canvas );
|
||||
~QgsMapToolMoveLabel();
|
||||
|
||||
virtual void canvasPressEvent( QMouseEvent * e );
|
||||
|
||||
virtual void canvasMoveEvent( QMouseEvent * e );
|
||||
|
||||
virtual void canvasReleaseEvent( QMouseEvent * e );
|
||||
|
||||
protected:
|
||||
/**Get data defined position of a feature
|
||||
@param layerId layer identification string
|
||||
@param x out: data defined x-coordinate
|
||||
@param xSuccess out: false if attribute value is NULL
|
||||
@param y out: data defined y-coordinate
|
||||
@param ySuccess out: false if attribute value is NULL
|
||||
@param xCol out: index of the x position column
|
||||
@param yCol out: index of the y position column
|
||||
@return false if layer does not have data defined label position enabled*/
|
||||
bool dataDefinedPosition( QgsVectorLayer* vlayer, int featureId, double& x, bool& xSuccess, double& y, bool& ySuccess, int& xCol, int& yCol ) const;
|
||||
|
||||
/**Returns true if layer 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;
|
||||
|
||||
/**Start point of the move in map coordinates*/
|
||||
QgsPoint mStartPointMapCoords;
|
||||
|
||||
double mClickOffsetX;
|
||||
double mClickOffsetY;
|
||||
};
|
||||
|
||||
#endif // QGSMAPTOOLMOVELABEL_H
|
207
src/app/qgsmaptoolrotatelabel.cpp
Normal file
207
src/app/qgsmaptoolrotatelabel.cpp
Normal file
@ -0,0 +1,207 @@
|
||||
/***************************************************************************
|
||||
qgsmaptoolrotatelabel.cpp
|
||||
-------------------------
|
||||
begin : 2010-11-09
|
||||
copyright : (C) 2010 by Marco Hugentobler
|
||||
email : marco dot hugentobler at sourcepole dot ch
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "qgsmaptoolrotatelabel.h"
|
||||
#include "qgsmapcanvas.h"
|
||||
#include "qgsmaplayerregistry.h"
|
||||
#include "qgspallabeling.h"
|
||||
#include "qgspointrotationitem.h"
|
||||
#include "qgsrubberband.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
#include <QMouseEvent>
|
||||
|
||||
#include "qgisapp.h"
|
||||
|
||||
QgsMapToolRotateLabel::QgsMapToolRotateLabel( QgsMapCanvas* canvas ): QgsMapToolLabel( canvas ), mRotationItem( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
QgsMapToolRotateLabel::~QgsMapToolRotateLabel()
|
||||
{
|
||||
delete mRotationItem;
|
||||
}
|
||||
|
||||
void QgsMapToolRotateLabel::canvasPressEvent( QMouseEvent * e )
|
||||
{
|
||||
deleteRubberBands();
|
||||
|
||||
if ( !labelAtPosition( e, mCurrentLabelPos ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QgsVectorLayer* vlayer = dynamic_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( mCurrentLabelPos.layerID ) );
|
||||
if ( !vlayer )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !rotationPoint( mRotationPoint ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int rotationCol;
|
||||
if ( layerIsRotatable( vlayer, rotationCol ) )
|
||||
{
|
||||
mCurrentMouseAzimuth = azimuthToCCW( mRotationPoint.azimuth( toMapCoordinates( e->pos() ) ) );
|
||||
|
||||
|
||||
bool hasRotationValue;
|
||||
if ( dataDefinedRotation( vlayer, mCurrentLabelPos.featureId, mCurrentRotation, hasRotationValue ) )
|
||||
{
|
||||
if ( !hasRotationValue )
|
||||
{
|
||||
mCurrentRotation = 0;
|
||||
}
|
||||
createRubberBands();
|
||||
|
||||
mRotationItem = new QgsPointRotationItem( mCanvas );
|
||||
mRotationItem->setOrientation( QgsPointRotationItem::Counterclockwise );
|
||||
mRotationItem->setSymbol( QgisApp::instance()->getThemePixmap( "mActionRotatePointSymbols.png" ).toImage() );
|
||||
mRotationItem->setPointLocation( mRotationPoint );
|
||||
mRotationItem->setSymbolRotation( mCurrentRotation );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QgsMapToolRotateLabel::canvasMoveEvent( QMouseEvent * e )
|
||||
{
|
||||
if ( mLabelRubberBand )
|
||||
{
|
||||
QgsPoint currentPoint = toMapCoordinates( e->pos() );
|
||||
double azimuth = azimuthToCCW( mRotationPoint.azimuth( currentPoint ) );
|
||||
double azimuthDiff = azimuth - mCurrentMouseAzimuth;
|
||||
azimuthDiff = azimuthDiff > 180 ? azimuthDiff - 360 : azimuthDiff;
|
||||
|
||||
mCurrentRotation += azimuthDiff;
|
||||
mCurrentRotation = mCurrentRotation - static_cast<float>( static_cast<int>( mCurrentRotation / 360 ) ) * 360; //mCurrentRotation % 360;
|
||||
mCurrentRotation = mCurrentRotation < 0 ? 360 - mCurrentRotation : mCurrentRotation;
|
||||
|
||||
mCurrentMouseAzimuth = azimuth - static_cast<float>( static_cast<int>( azimuth / 360 ) ) * 360;
|
||||
|
||||
//if shift-modifier is pressed, round to 15 degrees
|
||||
int displayValue;
|
||||
if ( e->modifiers() & Qt::ControlModifier )
|
||||
{
|
||||
displayValue = roundTo15Degrees( mCurrentRotation );
|
||||
mCtrlPressed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
displayValue = ( int )( mCurrentRotation );
|
||||
mCtrlPressed = false;
|
||||
}
|
||||
|
||||
if ( mRotationItem )
|
||||
{
|
||||
mRotationItem->setSymbolRotation( displayValue );
|
||||
mRotationItem->update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QgsMapToolRotateLabel::canvasReleaseEvent( QMouseEvent * e )
|
||||
{
|
||||
deleteRubberBands();
|
||||
delete mRotationItem;
|
||||
mRotationItem = 0;
|
||||
|
||||
QgsMapLayer* layer = QgsMapLayerRegistry::instance()->mapLayer( mCurrentLabelPos.layerID );
|
||||
if ( !layer )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QgsVectorLayer* vlayer = dynamic_cast<QgsVectorLayer*>( layer );
|
||||
if ( !vlayer )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int rotationCol;
|
||||
if ( !layerIsRotatable( vlayer, rotationCol ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
double rotation = mCtrlPressed ? roundTo15Degrees( mCurrentRotation ) : mCurrentRotation;
|
||||
|
||||
vlayer->beginEditCommand( tr( "Label rotated" ) );
|
||||
vlayer->changeAttributeValue( mCurrentLabelPos.featureId, rotationCol, mCurrentRotation, false );
|
||||
vlayer->endEditCommand();
|
||||
mCanvas->refresh();
|
||||
}
|
||||
|
||||
bool QgsMapToolRotateLabel::layerIsRotatable( const QgsMapLayer* layer, int& rotationCol ) const
|
||||
{
|
||||
const QgsVectorLayer* vlayer = dynamic_cast<const QgsVectorLayer*>( layer );
|
||||
if ( !vlayer || !vlayer->isEditable() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QVariant rotation = layer->customProperty( "labeling/dataDefinedProperty14" );
|
||||
if ( !rotation.isValid() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool rotationOk;
|
||||
rotationCol = rotation.toInt( &rotationOk );
|
||||
if ( !rotationOk )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QgsMapToolRotateLabel::dataDefinedRotation( QgsVectorLayer* vlayer, int featureId, double& rotation, bool& rotationSuccess )
|
||||
{
|
||||
rotationSuccess = false;
|
||||
if ( !vlayer )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int rotationCol;
|
||||
if ( !layerIsRotatable( vlayer, rotationCol ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QgsFeature f;
|
||||
if ( !vlayer->featureAtId( featureId, f, false, true ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QgsAttributeMap attributes = f.attributeMap();
|
||||
rotation = attributes[rotationCol].toDouble( &rotationSuccess );
|
||||
return true;
|
||||
}
|
||||
|
||||
int QgsMapToolRotateLabel::roundTo15Degrees( double n )
|
||||
{
|
||||
int m = ( int )( n / 15.0 + 0.5 );
|
||||
return ( m * 15 );
|
||||
}
|
||||
|
||||
double QgsMapToolRotateLabel::azimuthToCCW( double a )
|
||||
{
|
||||
return ( a > 0 ? 360 - a : -a );
|
||||
}
|
59
src/app/qgsmaptoolrotatelabel.h
Normal file
59
src/app/qgsmaptoolrotatelabel.h
Normal file
@ -0,0 +1,59 @@
|
||||
/***************************************************************************
|
||||
qgsmaptoolrotatelabel.h
|
||||
-----------------------
|
||||
begin : 2010-11-09
|
||||
copyright : (C) 2010 by Marco Hugentobler
|
||||
email : marco dot hugentobler at sourcepole dot ch
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef QGSMAPTOOLROTATELABEL_H
|
||||
#define QGSMAPTOOLROTATELABEL_H
|
||||
|
||||
#include "qgsmaptoollabel.h"
|
||||
class QgsPointRotationItem;
|
||||
|
||||
class QgsMapToolRotateLabel: public QgsMapToolLabel
|
||||
{
|
||||
public:
|
||||
QgsMapToolRotateLabel( QgsMapCanvas* canvas );
|
||||
~QgsMapToolRotateLabel();
|
||||
|
||||
virtual void canvasPressEvent( QMouseEvent * e );
|
||||
virtual void canvasMoveEvent( QMouseEvent * e );
|
||||
virtual void canvasReleaseEvent( QMouseEvent * e );
|
||||
|
||||
protected:
|
||||
/**Checks if labels in a layer can be rotated
|
||||
@param rotationCol out: attribute column for data defined label rotation*/
|
||||
bool layerIsRotatable( const QgsMapLayer* layer, int& rotationCol ) const;
|
||||
/**Returns data defined rotation of a feature.
|
||||
@param rotation out: rotation value
|
||||
@param rotationSuccess out: false if rotation value is NULL
|
||||
@return true if data defined rotation is enabled on the layer
|
||||
*/
|
||||
bool dataDefinedRotation( QgsVectorLayer* vlayer, int featureId, double& rotation, bool& rotationSuccess );
|
||||
|
||||
static int roundTo15Degrees( double n );
|
||||
/**Converts azimuth value to counterclockwise 0 - 360*/
|
||||
static double azimuthToCCW( double a );
|
||||
|
||||
|
||||
double mCurrentRotation;
|
||||
double mCurrentMouseAzimuth;
|
||||
QgsPoint mRotationPoint;
|
||||
QgsPointRotationItem* mRotationItem;
|
||||
|
||||
/**True if ctrl was pressed during the last mouse move event*/
|
||||
bool mCtrlPressed;
|
||||
};
|
||||
|
||||
#endif // QGSMAPTOOLROTATELABEL_H
|
@ -22,7 +22,7 @@
|
||||
#include <math.h>
|
||||
#endif
|
||||
|
||||
QgsPointRotationItem::QgsPointRotationItem( QgsMapCanvas* canvas ): QgsMapCanvasItem( canvas ), mRotation( 0.0 )
|
||||
QgsPointRotationItem::QgsPointRotationItem( QgsMapCanvas* canvas ): QgsMapCanvasItem( canvas ), mOrientation( Clockwise ), mRotation( 0.0 )
|
||||
{
|
||||
//setup font
|
||||
mFont.setPointSize( 12 );
|
||||
@ -55,12 +55,11 @@ void QgsPointRotationItem::paint( QPainter * painter )
|
||||
{
|
||||
h = sqrt(( double ) mPixmap.width() * mPixmap.width() + mPixmap.height() * mPixmap.height() ) / 2; //the half of the item diagonal
|
||||
dAngel = acos( mPixmap.width() / ( h * 2 ) ) * 180 / M_PI; //the diagonal angel of the original rect
|
||||
x = h * cos(( mRotation - dAngel ) * M_PI / 180 );
|
||||
y = h * sin(( mRotation - dAngel ) * M_PI / 180 );
|
||||
x = h * cos(( painterRotation( mRotation ) - dAngel ) * M_PI / 180 );
|
||||
y = h * sin(( painterRotation( mRotation ) - dAngel ) * M_PI / 180 );
|
||||
}
|
||||
|
||||
//painter->translate(-mPixmap.width() / 2.0, -mPixmap.width() / 2.0);
|
||||
painter->rotate( mRotation );
|
||||
painter->rotate( painterRotation( mRotation ) );
|
||||
painter->translate( x - mPixmap.width() / 2.0, -y - mPixmap.height() / 2.0 );
|
||||
painter->drawPixmap( 0, 0, mPixmap );
|
||||
|
||||
@ -109,3 +108,13 @@ void QgsPointRotationItem::setSymbol( const QImage& symbolImage )
|
||||
}
|
||||
}
|
||||
|
||||
int QgsPointRotationItem::painterRotation( int rotation ) const
|
||||
{
|
||||
if ( mOrientation == Clockwise )
|
||||
{
|
||||
return rotation;
|
||||
}
|
||||
|
||||
return 360 - ( rotation % 360 );
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,13 @@
|
||||
class QgsPointRotationItem: public QgsMapCanvasItem
|
||||
{
|
||||
public:
|
||||
|
||||
enum Orientation
|
||||
{
|
||||
Clockwise = 0,
|
||||
Counterclockwise
|
||||
};
|
||||
|
||||
QgsPointRotationItem( QgsMapCanvas* canvas );
|
||||
~QgsPointRotationItem();
|
||||
|
||||
@ -39,8 +46,15 @@ class QgsPointRotationItem: public QgsMapCanvasItem
|
||||
/**Sets rotation symbol from image (takes ownership)*/
|
||||
void setSymbol( const QImage& symbolImage );
|
||||
|
||||
void setOrientation( Orientation o ) { mOrientation = o; }
|
||||
Orientation orientation() const { return mOrientation; }
|
||||
|
||||
private:
|
||||
QgsPointRotationItem();
|
||||
/**Converts rotation into QPainter rotation considering mOrientation*/
|
||||
int painterRotation( int rotation ) const;
|
||||
/**Clockwise (default) or counterclockwise*/
|
||||
Orientation mOrientation;
|
||||
/**Font to display the numerical rotation values*/
|
||||
QFont mFont;
|
||||
/**Symboll pixmap*/
|
||||
|
@ -53,6 +53,7 @@ SET(QGIS_CORE_SRCS
|
||||
qgshttptransaction.cpp
|
||||
qgslabel.cpp
|
||||
qgslabelattributes.cpp
|
||||
qgslabelsearchtree.cpp
|
||||
qgslogger.cpp
|
||||
qgsmaplayer.cpp
|
||||
qgsmaplayerregistry.cpp
|
||||
|
@ -55,7 +55,7 @@
|
||||
namespace pal
|
||||
{
|
||||
LabelPosition::LabelPosition( int id, double x1, double y1, double w, double h, double alpha, double cost, FeaturePart *feature, bool isReversed )
|
||||
: id( id ), cost( cost ), feature( feature ), nbOverlap( 0 ), alpha( alpha ), w( w ), h( h ), nextPart( NULL ), partId( -1 ), reversed( isReversed )
|
||||
: id( id ), cost( cost ), feature( feature ), nbOverlap( 0 ), alpha( alpha ), w( w ), h( h ), nextPart( NULL ), partId( -1 ), reversed( isReversed ), upsideDown( false )
|
||||
{
|
||||
|
||||
// alpha take his value bw 0 and 2*pi rad
|
||||
@ -111,6 +111,8 @@ namespace pal
|
||||
x[3] = tx;
|
||||
y[3] = ty;
|
||||
|
||||
upsideDown = true;
|
||||
|
||||
if ( this->alpha < M_PI )
|
||||
this->alpha += M_PI;
|
||||
else
|
||||
@ -137,6 +139,7 @@ namespace pal
|
||||
else
|
||||
nextPart = NULL;
|
||||
partId = other.partId;
|
||||
upsideDown = other.upsideDown;
|
||||
}
|
||||
|
||||
bool LabelPosition::isIn( double *bbox )
|
||||
|
@ -79,6 +79,8 @@ namespace pal
|
||||
//if the layer arrangement is P_LINE
|
||||
bool reversed;
|
||||
|
||||
bool upsideDown;
|
||||
|
||||
bool isInConflictSinglePart( LabelPosition* lp );
|
||||
bool isInConflictMultiPart( LabelPosition* lp );
|
||||
|
||||
@ -196,6 +198,7 @@ namespace pal
|
||||
*/
|
||||
double getAlpha() const;
|
||||
bool getReversed() const { return reversed; }
|
||||
bool getUpsideDown() const { return upsideDown; }
|
||||
|
||||
void print();
|
||||
|
||||
|
62
src/core/qgslabelsearchtree.cpp
Normal file
62
src/core/qgslabelsearchtree.cpp
Normal file
@ -0,0 +1,62 @@
|
||||
#include "qgslabelsearchtree.h"
|
||||
#include "labelposition.h"
|
||||
|
||||
bool searchCallback( QgsLabelPosition* pos, void* context )
|
||||
{
|
||||
QList<QgsLabelPosition*>* list = static_cast< QList<QgsLabelPosition*>* >( context );
|
||||
list->push_back( pos );
|
||||
return true;
|
||||
}
|
||||
|
||||
QgsLabelSearchTree::QgsLabelSearchTree()
|
||||
{
|
||||
}
|
||||
|
||||
QgsLabelSearchTree::~QgsLabelSearchTree()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void QgsLabelSearchTree::label( const QgsPoint& p, QList<QgsLabelPosition*>& posList )
|
||||
{
|
||||
double c_min[2]; c_min[0] = p.x() - 1; c_min[1] = p.y() - 1;
|
||||
double c_max[2]; c_max[0] = p.x() + 1; c_max[1] = p.y() + 1;
|
||||
|
||||
mSearchResults.clear();
|
||||
mSpatialIndex.Search( c_min, c_max, searchCallback, &mSearchResults );
|
||||
posList = mSearchResults;
|
||||
}
|
||||
|
||||
bool QgsLabelSearchTree::insertLabel( LabelPosition* labelPos, int featureId, const QString& layerName )
|
||||
{
|
||||
if ( !labelPos )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
double c_min[2];
|
||||
double c_max[2];
|
||||
labelPos->getBoundingBox( c_min, c_max );
|
||||
|
||||
QVector<QgsPoint> cornerPoints;
|
||||
for ( int i = 0; i < 4; ++i )
|
||||
{
|
||||
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() );
|
||||
mSpatialIndex.Insert( c_min, c_max, newEntry );
|
||||
return true;
|
||||
}
|
||||
|
||||
void QgsLabelSearchTree::clear()
|
||||
{
|
||||
RTree<QgsLabelPosition*, double, 2, double>::Iterator indexIt;
|
||||
mSpatialIndex.GetFirst( indexIt );
|
||||
while ( !mSpatialIndex.IsNull( indexIt ) )
|
||||
{
|
||||
delete mSpatialIndex.GetAt( indexIt );
|
||||
mSpatialIndex.GetNext( indexIt );
|
||||
}
|
||||
mSpatialIndex.RemoveAll();
|
||||
}
|
54
src/core/qgslabelsearchtree.h
Normal file
54
src/core/qgslabelsearchtree.h
Normal file
@ -0,0 +1,54 @@
|
||||
/***************************************************************************
|
||||
qgslabelsearchtree.h
|
||||
Node for raster calculator tree
|
||||
--------------------
|
||||
begin : 2010-11-02
|
||||
copyright : (C) 2010 by Marco Hugentobler
|
||||
email : marco dot hugentobler at sourcepole dot ch
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef QGSLABELSEARCHTREE_H
|
||||
#define QGSLABELSEARCHTREE_H
|
||||
|
||||
#include "qgspoint.h"
|
||||
#include "qgsmaprenderer.h"
|
||||
#include <QList>
|
||||
#include <QVector>
|
||||
#include <pointset.h>
|
||||
#include <labelposition.h>
|
||||
#include "qgsrectangle.h"
|
||||
|
||||
using namespace pal;
|
||||
|
||||
/**A class to query the labeling structure at a given point (small wraper around pal RTree class)*/
|
||||
class QgsLabelSearchTree
|
||||
{
|
||||
public:
|
||||
QgsLabelSearchTree();
|
||||
~QgsLabelSearchTree();
|
||||
|
||||
/**Removes and deletes all the entries*/
|
||||
void clear();
|
||||
|
||||
/**Returns label position(s) at a given point. QgsLabelSearchTree keeps ownership, don't delete the LabelPositions*/
|
||||
void label( const QgsPoint& p, QList<QgsLabelPosition*>& posList );
|
||||
|
||||
/**Inserts label position. Does not take ownership of labelPos
|
||||
@return true in case of success*/
|
||||
bool insertLabel( LabelPosition* labelPos, int featureId, const QString& layerName );
|
||||
|
||||
private:
|
||||
RTree<QgsLabelPosition*, double, 2, double> mSpatialIndex;
|
||||
QList<QgsLabelPosition*> mSearchResults;
|
||||
};
|
||||
|
||||
#endif // QGSLABELTREE_H
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include <QSize>
|
||||
#include <QStringList>
|
||||
#include <QVector>
|
||||
|
||||
#include "qgis.h"
|
||||
#include "qgsrectangle.h"
|
||||
@ -38,12 +39,28 @@ class QgsOverlayObjectPositionManager;
|
||||
class QgsVectorLayer;
|
||||
class QgsFeature;
|
||||
|
||||
struct 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 ) {}
|
||||
int featureId;
|
||||
double rotation;
|
||||
QVector< QgsPoint > cornerPoints;
|
||||
QgsRectangle labelRect;
|
||||
double width;
|
||||
double height;
|
||||
QString layerID;
|
||||
bool upsideDown;
|
||||
};
|
||||
|
||||
/** Labeling engine interface.
|
||||
* \note Added in QGIS v1.4
|
||||
*/
|
||||
class QgsLabelingEngineInterface
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~QgsLabelingEngineInterface() {}
|
||||
|
||||
//! called when we're going to start with rendering
|
||||
@ -59,6 +76,9 @@ class QgsLabelingEngineInterface
|
||||
virtual void drawLabeling( QgsRenderContext& context ) = 0;
|
||||
//! called when we're done with rendering
|
||||
virtual void exit() = 0;
|
||||
//! return infos about labels at a given (map) position
|
||||
//! @note: this method was added in version 1.7
|
||||
virtual QList<QgsLabelPosition> labelsAtPosition( const QgsPoint& p ) = 0;
|
||||
|
||||
//! called when passing engine among map renderers
|
||||
virtual QgsLabelingEngineInterface* clone() = 0;
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include <QTime>
|
||||
#include <QPainter>
|
||||
|
||||
#include "qgslabelsearchtree.h"
|
||||
#include <qgslogger.h>
|
||||
#include <qgsvectorlayer.h>
|
||||
#include <qgsmaplayerregistry.h>
|
||||
@ -453,6 +454,7 @@ void QgsPalLayerSettings::registerFeature( QgsFeature& f, const QgsRenderContext
|
||||
bool dataDefinedPosition = false;
|
||||
bool dataDefinedRotation = false;
|
||||
double xPos, yPos, angle;
|
||||
bool ddXPos, ddYPos;
|
||||
|
||||
QMap< DataDefinedProperties, int >::const_iterator dPosXIt = dataDefinedProperties.find( QgsPalLayerSettings::PositionX );
|
||||
if ( dPosXIt != dataDefinedProperties.constEnd() )
|
||||
@ -460,74 +462,77 @@ void QgsPalLayerSettings::registerFeature( QgsFeature& f, const QgsRenderContext
|
||||
QMap< DataDefinedProperties, int >::const_iterator dPosYIt = dataDefinedProperties.find( QgsPalLayerSettings::PositionY );
|
||||
if ( dPosYIt != dataDefinedProperties.constEnd() )
|
||||
{
|
||||
//data defined position
|
||||
dataDefinedPosition = true;
|
||||
xPos = f.attributeMap().value( *dPosXIt ).toDouble();
|
||||
yPos = f.attributeMap().value( *dPosYIt ).toDouble();
|
||||
//data defined position. But field values could be NULL -> positions will be generated by PAL
|
||||
xPos = f.attributeMap().value( *dPosXIt ).toDouble( &ddXPos );
|
||||
yPos = f.attributeMap().value( *dPosYIt ).toDouble( &ddYPos );
|
||||
|
||||
//x/y shift in case of alignment
|
||||
double xdiff = 0;
|
||||
double ydiff = 0;
|
||||
|
||||
//horizontal alignment
|
||||
QMap< DataDefinedProperties, int >::const_iterator haliIt = dataDefinedProperties.find( QgsPalLayerSettings::Hali );
|
||||
if ( haliIt != dataDefinedProperties.end() )
|
||||
if ( ddXPos && ddYPos )
|
||||
{
|
||||
QString haliString = f.attributeMap().value( *haliIt ).toString();
|
||||
if ( haliString.compare( "Center", Qt::CaseInsensitive ) == 0 )
|
||||
{
|
||||
xdiff -= labelX / 2.0;
|
||||
}
|
||||
else if ( haliString.compare( "Right", Qt::CaseInsensitive ) == 0 )
|
||||
{
|
||||
xdiff -= labelX;
|
||||
}
|
||||
}
|
||||
dataDefinedPosition = true;
|
||||
//x/y shift in case of alignment
|
||||
double xdiff = 0;
|
||||
double ydiff = 0;
|
||||
|
||||
//vertical alignment
|
||||
QMap< DataDefinedProperties, int >::const_iterator valiIt = dataDefinedProperties.find( QgsPalLayerSettings::Vali );
|
||||
if ( valiIt != dataDefinedProperties.constEnd() )
|
||||
{
|
||||
QString valiString = f.attributeMap().value( *valiIt ).toString();
|
||||
if ( valiString.compare( "Bottom", Qt::CaseInsensitive ) != 0 )
|
||||
//horizontal alignment
|
||||
QMap< DataDefinedProperties, int >::const_iterator haliIt = dataDefinedProperties.find( QgsPalLayerSettings::Hali );
|
||||
if ( haliIt != dataDefinedProperties.end() )
|
||||
{
|
||||
if ( valiString.compare( "Top", Qt::CaseInsensitive ) == 0 || valiString.compare( "Cap", Qt::CaseInsensitive ) == 0 )
|
||||
QString haliString = f.attributeMap().value( *haliIt ).toString();
|
||||
if ( haliString.compare( "Center", Qt::CaseInsensitive ) == 0 )
|
||||
{
|
||||
ydiff -= labelY;
|
||||
xdiff -= labelX / 2.0;
|
||||
}
|
||||
else
|
||||
else if ( haliString.compare( "Right", Qt::CaseInsensitive ) == 0 )
|
||||
{
|
||||
QFontMetrics labelFontMetrics( labelFont );
|
||||
double descentRatio = labelFontMetrics.descent() / labelFontMetrics.height();
|
||||
xdiff -= labelX;
|
||||
}
|
||||
}
|
||||
|
||||
if ( valiString.compare( "Base", Qt::CaseInsensitive ) == 0 )
|
||||
//vertical alignment
|
||||
QMap< DataDefinedProperties, int >::const_iterator valiIt = dataDefinedProperties.find( QgsPalLayerSettings::Vali );
|
||||
if ( valiIt != dataDefinedProperties.constEnd() )
|
||||
{
|
||||
QString valiString = f.attributeMap().value( *valiIt ).toString();
|
||||
if ( valiString.compare( "Bottom", Qt::CaseInsensitive ) != 0 )
|
||||
{
|
||||
if ( valiString.compare( "Top", Qt::CaseInsensitive ) == 0 || valiString.compare( "Cap", Qt::CaseInsensitive ) == 0 )
|
||||
{
|
||||
ydiff -= labelY * descentRatio;
|
||||
ydiff -= labelY;
|
||||
}
|
||||
else if ( valiString.compare( "Half", Qt::CaseInsensitive ) == 0 )
|
||||
else
|
||||
{
|
||||
ydiff -= labelY * descentRatio;
|
||||
ydiff -= labelY * 0.5 * ( 1 - descentRatio );
|
||||
QFontMetrics labelFontMetrics( labelFont );
|
||||
double descentRatio = labelFontMetrics.descent() / labelFontMetrics.height();
|
||||
|
||||
if ( valiString.compare( "Base", Qt::CaseInsensitive ) == 0 )
|
||||
{
|
||||
ydiff -= labelY * descentRatio;
|
||||
}
|
||||
else if ( valiString.compare( "Half", Qt::CaseInsensitive ) == 0 )
|
||||
{
|
||||
ydiff -= labelY * descentRatio;
|
||||
ydiff -= labelY * 0.5 * ( 1 - descentRatio );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//data defined rotation?
|
||||
QMap< DataDefinedProperties, int >::const_iterator rotIt = dataDefinedProperties.find( QgsPalLayerSettings::Rotation );
|
||||
if ( rotIt != dataDefinedProperties.constEnd() )
|
||||
{
|
||||
dataDefinedRotation = true;
|
||||
angle = f.attributeMap().value( *rotIt ).toDouble() * M_PI / 180;
|
||||
//adjust xdiff and ydiff because the hali/vali point needs to be the rotation center
|
||||
double xd = xdiff * cos( angle ) - ydiff * sin( angle );
|
||||
double yd = xdiff * sin( angle ) + ydiff * cos( angle );
|
||||
xdiff = xd;
|
||||
ydiff = yd;
|
||||
}
|
||||
//data defined rotation?
|
||||
QMap< DataDefinedProperties, int >::const_iterator rotIt = dataDefinedProperties.find( QgsPalLayerSettings::Rotation );
|
||||
if ( rotIt != dataDefinedProperties.constEnd() )
|
||||
{
|
||||
dataDefinedRotation = true;
|
||||
angle = f.attributeMap().value( *rotIt ).toDouble() * M_PI / 180;
|
||||
//adjust xdiff and ydiff because the hali/vali point needs to be the rotation center
|
||||
double xd = xdiff * cos( angle ) - ydiff * sin( angle );
|
||||
double yd = xdiff * sin( angle ) + ydiff * cos( angle );
|
||||
xdiff = xd;
|
||||
ydiff = yd;
|
||||
}
|
||||
|
||||
yPos += ydiff;
|
||||
xPos += xdiff;
|
||||
yPos += ydiff;
|
||||
xPos += xdiff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -615,6 +620,8 @@ QgsPalLabeling::QgsPalLabeling()
|
||||
|
||||
mShowingCandidates = false;
|
||||
mShowingAllLabels = false;
|
||||
|
||||
mLabelSearchTree = new QgsLabelSearchTree();
|
||||
}
|
||||
|
||||
|
||||
@ -622,6 +629,8 @@ QgsPalLabeling::~QgsPalLabeling()
|
||||
{
|
||||
// make sure we've freed everything
|
||||
exit();
|
||||
delete mLabelSearchTree;
|
||||
mLabelSearchTree = NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -752,6 +761,8 @@ void QgsPalLabeling::init( QgsMapRenderer* mr )
|
||||
mPal->setPointP( mCandPoint );
|
||||
mPal->setLineP( mCandLine );
|
||||
mPal->setPolyP( mCandPolygon );
|
||||
|
||||
mActiveLayers.clear();
|
||||
}
|
||||
|
||||
void QgsPalLabeling::exit()
|
||||
@ -761,14 +772,15 @@ void QgsPalLabeling::exit()
|
||||
mMapRenderer = NULL;
|
||||
}
|
||||
|
||||
QgsPalLayerSettings& QgsPalLabeling::layer( const char* layerName )
|
||||
QgsPalLayerSettings& QgsPalLabeling::layer( const QString& layerName )
|
||||
{
|
||||
QHash<QgsVectorLayer*, QgsPalLayerSettings>::iterator lit;
|
||||
for ( lit = mActiveLayers.begin(); lit != mActiveLayers.end(); ++lit )
|
||||
{
|
||||
QgsPalLayerSettings& lyr = lit.value();
|
||||
if ( lyr.palLayer->getName() == layerName )
|
||||
return lyr;
|
||||
if ( lit.key() && lit.key()->getLayerID() == layerName )
|
||||
{
|
||||
return lit.value();
|
||||
}
|
||||
}
|
||||
return mInvalidLayerSettings;
|
||||
}
|
||||
@ -780,6 +792,11 @@ void QgsPalLabeling::drawLabeling( QgsRenderContext& context )
|
||||
QPainter* painter = context.painter();
|
||||
QgsRectangle extent = context.extent();
|
||||
|
||||
if ( mLabelSearchTree )
|
||||
{
|
||||
mLabelSearchTree->clear();
|
||||
}
|
||||
|
||||
QTime t;
|
||||
t.start();
|
||||
|
||||
@ -797,7 +814,7 @@ void QgsPalLabeling::drawLabeling( QgsRenderContext& context )
|
||||
catch ( std::exception& e )
|
||||
{
|
||||
QgsDebugMsg( "PAL EXCEPTION :-( " + QString::fromLatin1( e.what() ) );
|
||||
mActiveLayers.clear(); // clean up
|
||||
//mActiveLayers.clear(); // clean up
|
||||
return;
|
||||
}
|
||||
|
||||
@ -915,6 +932,11 @@ void QgsPalLabeling::drawLabeling( QgsRenderContext& context )
|
||||
drawLabel( *it, painter, fontForLabel, fontColor, xform, bufferSize, bufferColor, true );
|
||||
|
||||
drawLabel( *it, painter, fontForLabel, fontColor, xform );
|
||||
|
||||
if ( mLabelSearchTree )
|
||||
{
|
||||
mLabelSearchTree->insertLabel( *it, QString( palGeometry->strId() ).toInt(), ( *it )->getLayerName() );
|
||||
}
|
||||
}
|
||||
|
||||
QgsDebugMsg( QString( "LABELING draw: %1 ms" ).arg( t.elapsed() ) );
|
||||
@ -932,10 +954,28 @@ void QgsPalLabeling::drawLabeling( QgsRenderContext& context )
|
||||
lyr.geometries.clear();
|
||||
}
|
||||
// labeling is done: clear the active layers hashtable
|
||||
mActiveLayers.clear();
|
||||
// mActiveLayers.clear();
|
||||
|
||||
}
|
||||
|
||||
QList<QgsLabelPosition> QgsPalLabeling::labelsAtPosition( const QgsPoint& p )
|
||||
{
|
||||
QList<QgsLabelPosition> positions;
|
||||
|
||||
QList<QgsLabelPosition*> positionPointers;
|
||||
if ( mLabelSearchTree )
|
||||
{
|
||||
mLabelSearchTree->label( p, positionPointers );
|
||||
QList<QgsLabelPosition*>::const_iterator pointerIt = positionPointers.constBegin();
|
||||
for ( ; pointerIt != positionPointers.constEnd(); ++pointerIt )
|
||||
{
|
||||
positions.push_back( QgsLabelPosition( **pointerIt ) );
|
||||
}
|
||||
}
|
||||
|
||||
return positions;
|
||||
}
|
||||
|
||||
void QgsPalLabeling::numCandidatePositions( int& candPoint, int& candLine, int& candPolygon )
|
||||
{
|
||||
candPoint = mCandPoint;
|
||||
@ -1055,14 +1095,6 @@ void QgsPalLabeling::drawLabel( pal::LabelPosition* label, QPainter* painter, co
|
||||
|
||||
void QgsPalLabeling::drawLabelBuffer( QPainter* p, QString text, const QFont& font, double size, QColor color )
|
||||
{
|
||||
/*
|
||||
p->setFont( font );
|
||||
p->setPen( color );
|
||||
for (int x = -size; x <= size; x++)
|
||||
for (int y = -size; y <= size; y++)
|
||||
p->drawText(x,y, text);
|
||||
*/
|
||||
|
||||
QPainterPath path;
|
||||
path.addText( 0, 0, font, text );
|
||||
QPen pen( color );
|
||||
|
@ -26,6 +26,7 @@ class QPainter;
|
||||
class QgsMapRenderer;
|
||||
class QgsRectangle;
|
||||
class QgsCoordinateTransform;
|
||||
class QgsLabelSearchTree;
|
||||
|
||||
#include <QString>
|
||||
#include <QFont>
|
||||
@ -168,7 +169,7 @@ class CORE_EXPORT QgsPalLabeling : public QgsLabelingEngineInterface
|
||||
QgsPalLabeling();
|
||||
~QgsPalLabeling();
|
||||
|
||||
QgsPalLayerSettings& layer( const char* layerName );
|
||||
QgsPalLayerSettings& layer( const QString& layerName );
|
||||
|
||||
void numCandidatePositions( int& candPoint, int& candLine, int& candPolygon );
|
||||
void setNumCandidatePositions( int candPoint, int candLine, int candPolygon );
|
||||
@ -199,6 +200,8 @@ class CORE_EXPORT QgsPalLabeling : public QgsLabelingEngineInterface
|
||||
virtual void drawLabeling( QgsRenderContext& context );
|
||||
//! called when we're done with rendering
|
||||
virtual void exit();
|
||||
//! return infos about labels at a given (map) position
|
||||
virtual QList<QgsLabelPosition> labelsAtPosition( const QgsPoint& p );
|
||||
|
||||
//! called when passing engine among map renderers
|
||||
virtual QgsLabelingEngineInterface* clone();
|
||||
@ -214,7 +217,7 @@ class CORE_EXPORT QgsPalLabeling : public QgsLabelingEngineInterface
|
||||
void initPal();
|
||||
|
||||
protected:
|
||||
// temporary hashtable of layer settings, being filled during labeling, cleared once labeling's done
|
||||
// hashtable of layer settings, being filled during labeling
|
||||
QHash<QgsVectorLayer*, QgsPalLayerSettings> mActiveLayers;
|
||||
QgsPalLayerSettings mInvalidLayerSettings;
|
||||
|
||||
@ -229,6 +232,8 @@ class CORE_EXPORT QgsPalLabeling : public QgsLabelingEngineInterface
|
||||
bool mShowingCandidates;
|
||||
|
||||
bool mShowingAllLabels; // whether to avoid collisions or not
|
||||
|
||||
QgsLabelSearchTree* mLabelSearchTree;
|
||||
};
|
||||
|
||||
#endif // QGSPALLABELING_H
|
||||
|
@ -43,7 +43,7 @@ QgsVector QgsVector::operator-( void ) const
|
||||
|
||||
QgsVector QgsVector::operator*( double scalar ) const
|
||||
{
|
||||
return QgsVector( m_x*scalar, m_y*scalar );
|
||||
return QgsVector( m_x * scalar, m_y * scalar );
|
||||
}
|
||||
|
||||
QgsVector QgsVector::operator/( double scalar ) const
|
||||
@ -53,12 +53,12 @@ QgsVector QgsVector::operator/( double scalar ) const
|
||||
|
||||
double QgsVector::operator*( QgsVector v ) const
|
||||
{
|
||||
return m_x*v.m_x + m_y*v.m_y;
|
||||
return m_x * v.m_x + m_y * v.m_y;
|
||||
}
|
||||
|
||||
double QgsVector::length() const
|
||||
{
|
||||
return sqrt( m_x*m_x + m_y*m_y );
|
||||
return sqrt( m_x * m_x + m_y * m_y );
|
||||
}
|
||||
|
||||
double QgsVector::x() const
|
||||
@ -80,7 +80,7 @@ QgsVector QgsVector::perpVector() const
|
||||
double QgsVector::angle( void ) const
|
||||
{
|
||||
double ang = atan2( m_y, m_x );
|
||||
return ang < 0.0 ? ang + 2.0*M_PI : ang;
|
||||
return ang < 0.0 ? ang + 2.0 * M_PI : ang;
|
||||
}
|
||||
|
||||
double QgsVector::angle( QgsVector v ) const
|
||||
@ -92,7 +92,7 @@ QgsVector QgsVector::rotateBy( double rot ) const
|
||||
{
|
||||
double ang = atan2( m_y, m_x ) + rot;
|
||||
double len = length();
|
||||
return QgsVector( len*cos( ang ), len*sin( ang ) );
|
||||
return QgsVector( len * cos( ang ), len * sin( ang ) );
|
||||
}
|
||||
|
||||
QgsVector QgsVector::normal() const
|
||||
@ -167,7 +167,7 @@ QString QgsPoint::wellKnownText() const
|
||||
|
||||
double QgsPoint::sqrDist( double x, double y ) const
|
||||
{
|
||||
return ( m_x - x )*( m_x - x ) + ( m_y - y )*( m_y - y );
|
||||
return ( m_x - x ) * ( m_x - x ) + ( m_y - y ) * ( m_y - y );
|
||||
}
|
||||
|
||||
double QgsPoint::sqrDist( const QgsPoint& other ) const
|
||||
@ -175,6 +175,13 @@ double QgsPoint::sqrDist( const QgsPoint& other ) const
|
||||
return sqrDist( other.x(), other.y() );
|
||||
}
|
||||
|
||||
double QgsPoint::azimuth( const QgsPoint& other )
|
||||
{
|
||||
double dx = other.x() - m_x;
|
||||
double dy = other.y() - m_y;
|
||||
return ( atan2( dx, dy ) * 180.0 / M_PI );
|
||||
}
|
||||
|
||||
// operators
|
||||
bool QgsPoint::operator==( const QgsPoint & other )
|
||||
{
|
||||
|
@ -148,6 +148,10 @@ class CORE_EXPORT QgsPoint
|
||||
@note added in QGIS 1.5*/
|
||||
double sqrDistToSegment( double x1, double y1, double x2, double y2, QgsPoint& minDistPoint ) const;
|
||||
|
||||
/**Calculates azimut between this point and other one (clockwise in degree, starting from north)
|
||||
@note: this function has been added in version 1.7*/
|
||||
double azimuth( const QgsPoint& other );
|
||||
|
||||
//! equality operator
|
||||
bool operator==( const QgsPoint &other );
|
||||
|
||||
|
259
src/ui/qgslabelpropertydialogbase.ui
Normal file
259
src/ui/qgslabelpropertydialogbase.ui
Normal file
@ -0,0 +1,259 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>QgsLabelPropertyDialogBase</class>
|
||||
<widget class="QDialog" name="QgsLabelPropertyDialogBase">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>284</width>
|
||||
<height>411</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Label properties</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="0" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="mLabelTextLabel">
|
||||
<property name="text">
|
||||
<string>Text</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="mLabelTextLineEdit"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QGroupBox" name="mFontGroupBox">
|
||||
<property name="title">
|
||||
<string>Font</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="mFontSizeLabel">
|
||||
<property name="text">
|
||||
<string>Size</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="mFontSizeSpinBox">
|
||||
<property name="maximum">
|
||||
<double>999999.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QPushButton" name="mFontPushButton">
|
||||
<property name="text">
|
||||
<string>Font</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QgsColorButton" name="mFontColorButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QGroupBox" name="mBufferGroupBox">
|
||||
<property name="title">
|
||||
<string>Buffer</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="mBufferSizeLabel">
|
||||
<property name="text">
|
||||
<string>Size</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="mBufferSizeSpinBox">
|
||||
<property name="maximum">
|
||||
<double>999999.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QgsColorButton" name="mBufferColorButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QGroupBox" name="mPositionGroupBlox">
|
||||
<property name="title">
|
||||
<string>Position</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="mLabelDistanceLabel">
|
||||
<property name="text">
|
||||
<string>Label distance</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QDoubleSpinBox" name="mLabelDistanceSpinBox"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="mXCoordLabel">
|
||||
<property name="text">
|
||||
<string>X Coordinate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QDoubleSpinBox" name="mXCoordSpinBox">
|
||||
<property name="minimum">
|
||||
<double>-999999999.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>999999999.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="mYCoordLabel">
|
||||
<property name="text">
|
||||
<string>Y Coordinate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QDoubleSpinBox" name="mYCoordSpinBox">
|
||||
<property name="minimum">
|
||||
<double>-999999999.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>999999999.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="mHaliLabel">
|
||||
<property name="text">
|
||||
<string>Horizontal alignment</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="mHaliComboBox"/>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="mValiLabel">
|
||||
<property name="text">
|
||||
<string>Vertical alignment</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QComboBox" name="mValiComboBox"/>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="mRotationLabel">
|
||||
<property name="text">
|
||||
<string>Rotation</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QDoubleSpinBox" name="mRotationSpinBox">
|
||||
<property name="maximum">
|
||||
<double>360.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>QgsColorButton</class>
|
||||
<extends>QToolButton</extends>
|
||||
<header>qgscolorbutton.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>QgsLabelPropertyDialogBase</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>QgsLabelPropertyDialogBase</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
Loading…
x
Reference in New Issue
Block a user