[FEATURE][styles] Add new style dock for interactive styling

This commit is contained in:
Nathan Woodrow 2016-04-19 09:44:12 +10:00
parent b7a43f2cc8
commit 831e7cd236
18 changed files with 1360 additions and 930 deletions

View File

@ -84,6 +84,9 @@ class QgsFieldExpressionWidget : QWidget
//! convenience slot to connect QgsMapLayerComboBox layer signal
void setLayer( QgsMapLayer* layer );
//! sets the current row in the widget
void setRow( int row );
//! sets the current field or expression in the widget
void setField( const QString &fieldName );

View File

@ -94,6 +94,7 @@ SET(QGIS_APP_SRCS
nodetool/qgsvertexentry.cpp
nodetool/qgsnodeeditor.cpp
qgsmapstylingwidget.cpp
qgsmeasuredialog.cpp
qgsmeasuretool.cpp
qgsmergeattributesdialog.cpp
@ -268,6 +269,7 @@ SET (QGIS_APP_MOC_HDRS
nodetool/qgsselectedfeature.h
nodetool/qgsnodeeditor.h
qgsmapstylingwidget.h
qgsmeasuredialog.h
qgsmeasuretool.h
qgsmergeattributesdialog.h

View File

@ -75,6 +75,7 @@
#include <qgsnetworkaccessmanager.h>
#include <qgsapplication.h>
#include <qgscomposition.h>
#include <qgsmapstylingwidget.h>
#include <QNetworkReply>
#include <QNetworkProxy>
@ -716,6 +717,16 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, bool skipVersionCh
addDockWidget( Qt::LeftDockWidgetArea, mUndoWidget );
mUndoWidget->hide();
mMapStylingDock = new QDockWidget( this );
mMapStylingDock->setWindowTitle( tr( "Map Styling" ) );
mMapStyleWidget = new QgsMapStylingWidget( mMapCanvas );
mMapStylingDock->setWidget( mMapStyleWidget );
connect( mMapStyleWidget, SIGNAL( styleChanged( QgsMapLayer* ) ), this, SLOT( updateLabelToolButtons() ) );
addDockWidget( Qt::RightDockWidgetArea, mMapStylingDock );
mMapStylingDock->hide();
mSnappingDialog = new QgsSnappingDialog( this, mMapCanvas );
mSnappingDialog->setObjectName( "SnappingOption" );
@ -2399,6 +2410,9 @@ void QgisApp::setupConnections()
// connect legend signals
connect( mLayerTreeView, SIGNAL( currentLayerChanged( QgsMapLayer * ) ),
this, SLOT( activateDeactivateLayerRelatedActions( QgsMapLayer * ) ) );
connect( mLayerTreeView, SIGNAL( currentLayerChanged( QgsMapLayer * ) ),
this, SLOT( setMapStyleDockLayer( QgsMapLayer* ) ) );
connect( mLayerTreeView->selectionModel(), SIGNAL( selectionChanged( QItemSelection, QItemSelection ) ),
this, SLOT( legendLayerSelectionChanged() ) );
connect( mLayerTreeView->layerTreeModel()->rootGroup(), SIGNAL( addedChildren( QgsLayerTreeNode*, int, int ) ),
@ -2748,6 +2762,11 @@ void QgisApp::initLayerTreeView()
mLegendExpressionFilterButton->setToolTip( tr( "Filter legend by expression" ) );
connect( mLegendExpressionFilterButton, SIGNAL( toggled( bool ) ), this, SLOT( toggleFilterLegendByExpression( bool ) ) );
mActionStyleDock = new QAction( tr( "Map Styling" ), this );
mActionStyleDock->setToolTip( tr( "Open the map styling dock" ) );
mActionStyleDock->setIcon( QgsApplication::getThemeIcon( "propertyicons/symbology.png" ) );
connect( mActionStyleDock, SIGNAL( triggered() ), this, SLOT( mapStyleDock() ) );
// expand / collapse tool buttons
QAction* actionExpandAll = new QAction( tr( "Expand All" ), this );
actionExpandAll->setIcon( QgsApplication::getThemeIcon( "/mActionExpandTree.svg" ) );
@ -2758,6 +2777,9 @@ void QgisApp::initLayerTreeView()
actionCollapseAll->setToolTip( tr( "Collapse All" ) );
connect( actionCollapseAll, SIGNAL( triggered( bool ) ), mLayerTreeView, SLOT( collapseAll() ) );
QWidget* spacer = new QWidget();
spacer->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
QToolBar* toolbar = new QToolBar();
toolbar->setIconSize( QSize( 16, 16 ) );
toolbar->addAction( actionAddGroup );
@ -2767,6 +2789,8 @@ void QgisApp::initLayerTreeView()
toolbar->addAction( actionExpandAll );
toolbar->addAction( actionCollapseAll );
toolbar->addAction( mActionRemoveLayer );
toolbar->addWidget( spacer );
toolbar->addAction( mActionStyleDock );
QVBoxLayout* vboxLayout = new QVBoxLayout;
vboxLayout->setMargin( 0 );
@ -5460,47 +5484,33 @@ void QgisApp::labeling()
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer*>( activeLayer() );
if ( !vlayer )
{
messageBar()->pushMessage( tr( "Labeling Options" ),
tr( "Please select a vector layer first" ),
QgsMessageBar::INFO,
messageTimeout() );
return;
}
mapStyleDock();
}
QDialog dlg;
dlg.setWindowTitle( tr( "Layer labeling settings" ) );
QgsLabelingWidget *labelingGui = new QgsLabelingWidget( vlayer, mMapCanvas, &dlg );
labelingGui->layout()->setContentsMargins( 0, 0, 0, 0 );
QVBoxLayout *layout = new QVBoxLayout( &dlg );
layout->addWidget( labelingGui );
QDialogButtonBox *buttonBox = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Apply, Qt::Horizontal, &dlg );
layout->addWidget( buttonBox );
dlg.setLayout( layout );
QSettings settings;
dlg.restoreGeometry( settings.value( "/Windows/Labeling/geometry" ).toByteArray() );
connect( buttonBox->button( QDialogButtonBox::Ok ), SIGNAL( clicked() ), &dlg, SLOT( accept() ) );
connect( buttonBox->button( QDialogButtonBox::Cancel ), SIGNAL( clicked() ), &dlg, SLOT( reject() ) );
connect( buttonBox->button( QDialogButtonBox::Apply ), SIGNAL( clicked() ), labelingGui, SLOT( apply() ) );
if ( dlg.exec() )
void QgisApp::setMapStyleDockLayer( QgsMapLayer* layer )
{
if ( !layer )
{
labelingGui->writeSettingsToLayer();
settings.setValue( "/Windows/Labeling/geometry", dlg.saveGeometry() );
// trigger refresh
if ( mMapCanvas )
{
mMapCanvas->refresh();
}
mMapStylingDock->setEnabled( false );
return;
}
activateDeactivateLayerRelatedActions( vlayer );
mMapStylingDock->setEnabled( true );
// We don't set the layer if the dock isn't open mainly to save
// the extra work if it's not needed
if ( mMapStylingDock->isVisible() )
mMapStyleWidget->setLayer( layer );
mMapStylingDock->setWindowTitle( tr( "Map Styling - %1" ).arg( layer->name() ) );
}
void QgisApp::mapStyleDock()
{
mMapStylingDock->show();
setMapStyleDockLayer( activeLayer() );
}
void QgisApp::diagramProperties()
@ -9848,7 +9858,7 @@ void QgisApp::layerEditStateChanged()
}
}
void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer* layer )
void QgisApp::updateLabelToolButtons()
{
bool enableMove = false, enableRotate = false, enablePin = false, enableShowHide = false, enableChange = false;
@ -9895,6 +9905,11 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer* layer )
mActionMoveLabel->setEnabled( enableMove );
mActionRotateLabel->setEnabled( enableRotate );
mActionChangeLabelProperties->setEnabled( enableChange );
}
void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer* layer )
{
updateLabelToolButtons();
mMenuPasteAs->setEnabled( clipboard() && !clipboard()->isEmpty() );
mActionPasteAsNewVector->setEnabled( clipboard() && !clipboard()->isEmpty() );

View File

@ -12,8 +12,7 @@
* 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 QGISAPP_H
#define QGISAPP_H
@ -94,6 +93,8 @@ class QgsScaleComboBox;
class QgsDataItem;
class QgsTileScaleWidget;
class QgsLabelingWidget;
class QgsMapStylingWidget;
class QgsDiagramProperties;
#include <QMainWindow>
@ -115,6 +116,7 @@ class QgsDiagramProperties;
#include "qgsbookmarks.h"
#include "qgswelcomepageitemsmodel.h"
#include "ui_qgisapp.h"
#ifdef HAVE_TOUCH
@ -1089,6 +1091,9 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
/** Called when some layer's editing mode was toggled on/off */
void layerEditStateChanged();
/** Update the label toolbar buttons */
void updateLabelToolButtons();
/** Activates or deactivates actions depending on the current maplayer type.
Is called from the legend when the current legend item has changed*/
void activateDeactivateLayerRelatedActions( QgsMapLayer *layer );
@ -1164,6 +1169,9 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
//! shows label settings dialog (for labeling-ng)
void labeling();
//! shows the map styling dock
void mapStyleDock();
//! diagrams properties
void diagramProperties();
@ -1285,6 +1293,9 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
/** Pushes a layer error to the message bar */
void onLayerError( const QString& msg );
/** Set the layer for the map style dock. Doesn't show the style dock */
void setMapStyleDockLayer( QgsMapLayer *layer );
signals:
/** Emitted when a key is pressed and we want non widget sublasses to be able
to pick up on this (e.g. maplayer) */
@ -1682,6 +1693,8 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
QgsSnappingDialog *mSnappingDialog;
QgsPluginManager *mPluginManager;
QDockWidget *mMapStylingDock;
QgsMapStylingWidget* mMapStyleWidget;
QgsComposerManager *mComposerManager;
@ -1720,6 +1733,7 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
QgsMapCanvasTracer* mTracer;
QAction* mActionFilterLegend;
QAction* mActionStyleDock;
QgsLegendFilterButton* mLegendExpressionFilterButton;

View File

@ -76,9 +76,6 @@ QgsLabelingGui::QgsLabelingGui( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas,
, mMinPixelLimit( 0 )
, mLoadSvgParams( false )
{
if ( !layer )
return;
setupUi( this );
mFieldExpressionWidget->registerGetExpressionContextCallback( &_getExpressionContext, mLayer );
@ -124,22 +121,11 @@ QgsLabelingGui::QgsLabelingGui( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas,
connect( mBufferDrawChkBx, SIGNAL( toggled( bool ) ), this, SLOT( updateUi() ) );
connect( mShapeDrawChkBx, SIGNAL( toggled( bool ) ), this, SLOT( updateUi() ) );
connect( mShadowDrawChkBx, SIGNAL( toggled( bool ) ), this, SLOT( updateUi() ) );
connect( mDirectSymbChkBx, SIGNAL( toggled( bool ) ), this, SLOT( updateUi() ) );
connect( mFormatNumChkBx, SIGNAL( toggled( bool ) ), this, SLOT( updateUi() ) );
connect( mScaleBasedVisibilityChkBx, SIGNAL( toggled( bool ) ), this, SLOT( updateUi() ) );
connect( mFontLimitPixelChkBox, SIGNAL( toggled( bool ) ), this, SLOT( updateUi() ) );
// preview and basic option connections
connect( btnTextColor, SIGNAL( colorChanged( const QColor& ) ), this, SLOT( changeTextColor( const QColor& ) ) );
connect( mFontTranspSpinBox, SIGNAL( valueChanged( int ) ), this, SLOT( updatePreview() ) );
connect( mBufferDrawChkBx, SIGNAL( toggled( bool ) ), this, SLOT( updatePreview() ) );
connect( btnBufferColor, SIGNAL( colorChanged( const QColor& ) ), this, SLOT( changeBufferColor( const QColor& ) ) );
connect( spinBufferSize, SIGNAL( valueChanged( double ) ), this, SLOT( updatePreview() ) );
connect( mBufferTranspSpinBox, SIGNAL( valueChanged( int ) ), this, SLOT( updatePreview() ) );
connect( mBufferJoinStyleComboBox, SIGNAL( currentIndexChanged( int ) ), this, SLOT( updatePreview() ) );
connect( mBufferTranspFillChbx, SIGNAL( toggled( bool ) ), this, SLOT( updatePreview() ) );
// internal connections
connect( mFontTranspSlider, SIGNAL( valueChanged( int ) ), mFontTranspSpinBox, SLOT( setValue( int ) ) );
connect( mFontTranspSpinBox, SIGNAL( valueChanged( int ) ), mFontTranspSlider, SLOT( setValue( int ) ) );
@ -158,45 +144,6 @@ QgsLabelingGui::QgsLabelingGui( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas,
connect( chkLineBelow, SIGNAL( toggled( bool ) ), this, SLOT( updateLinePlacementOptions() ) );
connect( chkLineOn, SIGNAL( toggled( bool ) ), this, SLOT( updateLinePlacementOptions() ) );
// set placement methods page based on geometry type
switch ( layer->geometryType() )
{
case QGis::Point:
stackedPlacement->setCurrentWidget( pagePoint );
break;
case QGis::Line:
stackedPlacement->setCurrentWidget( pageLine );
break;
case QGis::Polygon:
stackedPlacement->setCurrentWidget( pagePolygon );
break;
case QGis::NoGeometry:
break;
case QGis::UnknownGeometry:
qFatal( "unknown geometry type unexpected" );
}
if ( layer->geometryType() == QGis::Point )
{
// follow placement alignment is only valid for point layers
mFontMultiLineAlignComboBox->addItem( tr( "Follow label placement" ) );
}
// show/hide options based upon geometry type
chkMergeLines->setVisible( layer->geometryType() == QGis::Line );
mDirectSymbolsFrame->setVisible( layer->geometryType() == QGis::Line );
mMinSizeFrame->setVisible( layer->geometryType() != QGis::Point );
mPolygonObstacleTypeFrame->setVisible( layer->geometryType() == QGis::Polygon );
mPolygonFeatureOptionsFrame->setVisible( layer->geometryType() == QGis::Polygon );
// field combo and expression button
mFieldExpressionWidget->setLayer( mLayer );
QgsDistanceArea myDa;
myDa.setSourceCrs( mLayer->crs().srsid() );
myDa.setEllipsoidalMode( QgisApp::instance()->mapCanvas()->mapSettings().hasCrsTransformEnabled() );
myDa.setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", GEO_NONE ) );
mFieldExpressionWidget->setGeomCalculator( myDa );
populateFontCapitalsComboBox();
// color buttons
@ -315,10 +262,351 @@ QgsLabelingGui::QgsLabelingGui( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas,
mLabelingOptionsSplitter->restoreState( settings.value( QString( "/Windows/Labeling/OptionsSplitState" ) ).toByteArray() );
mLabelingOptionsListWidget->setCurrentRow( settings.value( QString( "/Windows/Labeling/Tab" ), 0 ).toInt() );
setDockMode( false );
QList<QWidget*> widgets;
widgets << btnBufferColor
<< btnTextColor
<< chkLabelPerFeaturePart
<< chkLineAbove
<< chkLineBelow
<< chkLineOn
<< chkLineOrientationDependent
<< chkMergeLines
<< chkPreserveRotation
<< comboBlendMode
<< comboBufferBlendMode
<< mAlwaysShowDDBtn
<< mBufferBlendModeDDBtn
<< mBufferColorDDBtn
<< mBufferDrawChkBx
<< mBufferDrawDDBtn
<< mBufferJoinStyleComboBox
<< mBufferJoinStyleDDBtn
<< mBufferSizeDDBtn
<< mBufferTranspDDBtn
<< mBufferTranspFillChbx
<< mBufferTranspSlider
<< mBufferTranspSpinBox
<< mBufferUnitsDDBtn
<< mCentroidDDBtn
<< mCentroidInsideCheckBox
<< mChkNoObstacle
<< mCoordAlignmentHDDBtn
<< mCoordAlignmentVDDBtn
<< mCoordRotationDDBtn
<< mCoordXDDBtn
<< mCoordYDDBtn
<< mDirectSymbChkBx
<< mDirectSymbDDBtn
<< mDirectSymbLeftDDBtn
<< mDirectSymbLeftLineEdit
<< mDirectSymbLeftToolBtn
<< mDirectSymbPlacementDDBtn
<< mDirectSymbRevChkBx
<< mDirectSymbRevDDBtn
<< mDirectSymbRightDDBtn
<< mDirectSymbRightLineEdit
<< mDirectSymbRightToolBtn
<< mFitInsidePolygonCheckBox
<< mFontBlendModeDDBtn
<< mFontBoldBtn
<< mFontBoldDDBtn
<< mFontCapitalsComboBox
<< mFontCaseDDBtn
<< mFontColorDDBtn
<< mFontDDBtn
<< mFontItalicBtn
<< mFontItalicDDBtn
<< mFontLetterSpacingDDBtn
<< mFontLetterSpacingSpinBox
<< mFontLimitPixelChkBox
<< mFontLimitPixelDDBtn
<< mFontLineHeightDDBtn
<< mFontLineHeightSpinBox
<< mFontMaxPixelDDBtn
<< mFontMaxPixelSpinBox
<< mFontMinPixelDDBtn
<< mFontMinPixelSpinBox
<< mFontMultiLineAlignComboBox
<< mFontMultiLineAlignDDBtn
<< mFontSizeDDBtn
<< mFontSizeSpinBox
<< mFontStrikeoutDDBtn
<< mFontStrikethroughBtn
<< mFontStyleComboBox
<< mFontStyleDDBtn
<< mFontTranspDDBtn
<< mFontTranspSlider
<< mFontTranspSpinBox
<< mFontUnderlineBtn
<< mFontUnderlineDDBtn
<< mFontUnitsDDBtn
<< mFontWordSpacingDDBtn
<< mFontWordSpacingSpinBox
<< mFormatNumChkBx
<< mFormatNumDDBtn
<< mFormatNumDecimalsDDBtn
<< mFormatNumDecimalsSpnBx
<< mFormatNumPlusSignChkBx
<< mFormatNumPlusSignDDBtn
<< mIsObstacleDDBtn
<< mLimitLabelChkBox
<< mLimitLabelSpinBox
<< mLineDistanceDDBtn
<< mLineDistanceSpnBx
<< mLineDistanceUnitDDBtn
<< mMaxCharAngleDDBtn
<< mMaxCharAngleInDSpinBox
<< mMaxCharAngleOutDSpinBox
<< mMinSizeSpinBox
<< mObstacleFactorDDBtn
<< mObstacleFactorSlider
<< mObstacleTypeComboBox
<< mOffsetTypeComboBox
<< mPalShowAllLabelsForLayerChkBx
<< mPointAngleDDBtn
<< mPointAngleSpinBox
<< mPointOffsetAbove
<< mPointOffsetAboveLeft
<< mPointOffsetAboveRight
<< mPointOffsetBelow
<< mPointOffsetBelowLeft
<< mPointOffsetBelowRight
<< mPointOffsetDDBtn
<< mPointOffsetLeft
<< mPointOffsetOver
<< mPointOffsetRight
<< mPointOffsetUnitsDDBtn
<< mPointOffsetXSpinBox
<< mPointOffsetYSpinBox
<< mPointPositionOrderDDBtn
<< mPointQuadOffsetDDBtn
<< mPreviewBackgroundBtn
<< mPreviewSizeSlider
<< mPreviewTextBtn
<< mPreviewTextEdit
<< mPriorityDDBtn
<< mPrioritySlider
<< mRepeatDistanceDDBtn
<< mRepeatDistanceSpinBox
<< mRepeatDistanceUnitDDBtn
<< mScaleBasedVisibilityChkBx
<< mScaleBasedVisibilityDDBtn
<< mScaleBasedVisibilityMaxDDBtn
<< mScaleBasedVisibilityMaxSpnBx
<< mScaleBasedVisibilityMinDDBtn
<< mScaleBasedVisibilityMinSpnBx
<< mShadowBlendCmbBx
<< mShadowBlendDDBtn
<< mShadowColorBtn
<< mShadowColorDDBtn
<< mShadowDrawChkBx
<< mShadowDrawDDBtn
<< mShadowOffsetAngleDDBtn
<< mShadowOffsetAngleSpnBx
<< mShadowOffsetDDBtn
<< mShadowOffsetGlobalChkBx
<< mShadowOffsetSpnBx
<< mShadowOffsetUnitsDDBtn
<< mShadowRadiusAlphaChkBx
<< mShadowRadiusDDBtn
<< mShadowRadiusDblSpnBx
<< mShadowRadiusUnitsDDBtn
<< mShadowScaleDDBtn
<< mShadowScaleSpnBx
<< mShadowTranspDDBtn
<< mShadowTranspSlider
<< mShadowTranspSpnBx
<< mShadowUnderCmbBx
<< mShadowUnderDDBtn
<< mShapeBlendCmbBx
<< mShapeBlendModeDDBtn
<< mShapeBorderColorBtn
<< mShapeBorderColorDDBtn
<< mShapeBorderUnitsDDBtn
<< mShapeBorderWidthDDBtn
<< mShapeBorderWidthSpnBx
<< mShapeDrawChkBx
<< mShapeDrawDDBtn
<< mShapeFillColorBtn
<< mShapeFillColorDDBtn
<< mShapeOffsetDDBtn
<< mShapeOffsetUnitsDDBtn
<< mShapeOffsetXSpnBx
<< mShapeOffsetYSpnBx
<< mShapePenStyleCmbBx
<< mShapePenStyleDDBtn
<< mShapeRadiusDDBtn
<< mShapeRadiusUnitsDDBtn
<< mShapeRadiusXDbSpnBx
<< mShapeRadiusYDbSpnBx
<< mShapeRotationCmbBx
<< mShapeRotationDDBtn
<< mShapeRotationDblSpnBx
<< mShapeRotationTypeDDBtn
<< mShapeSVGParamsBtn
<< mShapeSVGPathDDBtn
<< mShapeSVGPathLineEdit
<< mShapeSVGSelectorBtn
<< mShapeSizeCmbBx
<< mShapeSizeTypeDDBtn
<< mShapeSizeUnitsDDBtn
<< mShapeSizeXDDBtn
<< mShapeSizeXSpnBx
<< mShapeSizeYDDBtn
<< mShapeSizeYSpnBx
<< mShapeTranspDDBtn
<< mShapeTranspSlider
<< mShapeTranspSpinBox
<< mShapeTypeCmbBx
<< mShapeTypeDDBtn
<< mShowLabelDDBtn
<< mWrapCharDDBtn
<< mZIndexDDBtn
<< mZIndexSpinBox
<< spinBufferSize
<< wrapCharacterEdit
<< stackedPlacement
<< mCentroidRadioVisible
<< mCentroidRadioWhole
<< mDirectSymbRadioBtnAbove
<< mDirectSymbRadioBtnBelow
<< mDirectSymbRadioBtnLR
<< mUpsidedownRadioAll
<< mUpsidedownRadioDefined
<< mUpsidedownRadioOff
<< radAroundCentroid
<< radAroundPoint
<< radLineCurved
<< radLineHorizontal
<< radLineParallel
<< radOverCentroid
<< radOverPoint
<< radPolygonFree
<< radPolygonHorizontal
<< radPolygonPerimeter
<< radPredefinedOrder
<< mFieldExpressionWidget;
connectValueChanged( widgets, SLOT( updatePreview() ) );
connect( mQuadrantBtnGrp, SIGNAL( buttonClicked( int ) ), this, SLOT( updatePreview() ) );
mOptionsTab->setCurrentIndex( 0 );
}
void QgsLabelingGui::setDockMode( bool enabled )
{
mOptionsTab->setVisible( enabled );
mLabelingOptionsListFrame->setVisible( !enabled );
groupBox_mPreview->setVisible( !enabled );
mDockMode = enabled;
}
void QgsLabelingGui::connectValueChanged( QList<QWidget *> widgets, const char *slot )
{
Q_FOREACH ( QWidget* widget, widgets )
{
if ( QgsDataDefinedButton* w = qobject_cast<QgsDataDefinedButton*>( widget ) )
{
connect( w, SIGNAL( dataDefinedActivated( bool ) ), this, slot );
connect( w, SIGNAL( dataDefinedChanged( QString ) ), this, slot );
}
else if ( QgsFieldExpressionWidget* w = qobject_cast<QgsFieldExpressionWidget*>( widget ) )
{
connect( w, SIGNAL( fieldChanged( QString ) ), this, slot );
}
else if ( QComboBox* w = qobject_cast<QComboBox*>( widget ) )
{
connect( w, SIGNAL( currentIndexChanged( int ) ), this, slot );
}
else if ( QSpinBox* w = qobject_cast<QSpinBox*>( widget ) )
{
connect( w, SIGNAL( valueChanged( int ) ), this, slot );
}
else if ( QDoubleSpinBox* w = qobject_cast<QDoubleSpinBox*>( widget ) )
{
connect( w , SIGNAL( valueChanged( double ) ), this, slot );
}
else if ( QgsColorButtonV2* w = qobject_cast<QgsColorButtonV2*>( widget ) )
{
connect( w, SIGNAL( colorChanged( QColor ) ), this, slot );
}
else if ( QCheckBox* w = qobject_cast<QCheckBox*>( widget ) )
{
connect( w, SIGNAL( toggled( bool ) ), this, slot );
}
else if ( QRadioButton* w = qobject_cast<QRadioButton*>( widget ) )
{
connect( w, SIGNAL( toggled( bool ) ), this, slot );
}
else if ( QLineEdit* w = qobject_cast<QLineEdit*>( widget ) )
{
connect( w, SIGNAL( textEdited( QString ) ), this, slot );
}
}
}
void QgsLabelingGui::setLayer( QgsMapLayer* mapLayer )
{
if ( !mapLayer || mapLayer->type() != QgsMapLayer::VectorLayer )
{
setEnabled( false );
return;
}
else
{
setEnabled( true );
}
QgsVectorLayer *layer = qobject_cast<QgsVectorLayer*>( mapLayer );
mLayer = layer ;
init();
}
void QgsLabelingGui::init()
{
// show/hide options based upon geometry type
chkMergeLines->setVisible( mLayer->geometryType() == QGis::Line );
mDirectSymbolsFrame->setVisible( mLayer->geometryType() == QGis::Line );
mMinSizeFrame->setVisible( mLayer->geometryType() != QGis::Point );
mPolygonObstacleTypeFrame->setVisible( mLayer->geometryType() == QGis::Polygon );
mPolygonFeatureOptionsFrame->setVisible( mLayer->geometryType() == QGis::Polygon );
// field combo and expression button
mFieldExpressionWidget->setLayer( mLayer );
QgsDistanceArea myDa;
myDa.setSourceCrs( mLayer->crs().srsid() );
myDa.setEllipsoidalMode( QgisApp::instance()->mapCanvas()->mapSettings().hasCrsTransformEnabled() );
myDa.setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", GEO_NONE ) );
mFieldExpressionWidget->setGeomCalculator( myDa );
// set placement methods page based on geometry type
switch ( mLayer->geometryType() )
{
case QGis::Point:
stackedPlacement->setCurrentWidget( pagePoint );
break;
case QGis::Line:
stackedPlacement->setCurrentWidget( pageLine );
break;
case QGis::Polygon:
stackedPlacement->setCurrentWidget( pagePolygon );
break;
case QGis::NoGeometry:
break;
case QGis::UnknownGeometry:
qFatal( "unknown geometry type unexpected" );
}
if ( mLayer->geometryType() == QGis::Point )
{
// follow placement alignment is only valid for point layers
mFontMultiLineAlignComboBox->addItem( tr( "Follow label placement" ) );
}
// load labeling settings from layer
QgsPalLayerSettings lyr;
if ( mSettings )
@ -332,6 +620,7 @@ void QgsLabelingGui::init()
mLabelingFrame->setEnabled( mMode == Labels );
// set the current field or add the current expression to the bottom of the list
mFieldExpressionWidget->setRow( -1 );
mFieldExpressionWidget->setField( lyr.fieldName );
// populate placement options
@ -555,7 +844,6 @@ void QgsLabelingGui::init()
updateUi(); // should come after data defined button setup
}
QgsLabelingGui::~QgsLabelingGui()
{
QSettings settings;
@ -573,6 +861,7 @@ void QgsLabelingGui::blockInitSignals( bool block )
mPlacePolygonBtnGrp->blockSignals( block );
}
void QgsLabelingGui::optionsStackedWidget_CurrentChanged( int indx )
{
mLabelingOptionsListWidget->blockSignals( true );
@ -1251,6 +1540,15 @@ void QgsLabelingGui::blockFontChangeSignals( bool blk )
void QgsLabelingGui::updatePreview()
{
// In dock mode we don't have a preview we
// just let stuff know we have changed because
// there might be live updates connected.
if ( mLayer && mDockMode )
{
emit widgetChanged();
return;
}
scrollPreview();
lblFontPreview->setFont( mRefFont );
QFont previewFont = lblFontPreview->font();

View File

@ -48,7 +48,14 @@ class APP_EXPORT QgsLabelingGui : public QWidget, private Ui::QgsLabelingGuiBase
void setLabelMode( LabelMode mode );
signals:
void widgetChanged();
public slots:
void setLayer( QgsMapLayer* layer );
void setDockMode( bool enabled );
void connectValueChanged( QList<QWidget*> widgets, const char* slot );
void init();
void collapseSample( bool collapse );
void apply();
@ -121,6 +128,7 @@ class APP_EXPORT QgsLabelingGui : public QWidget, private Ui::QgsLabelingGuiBase
// background reference font
QFont mRefFont;
bool mDockMode;
int mPreviewSize;
int mMinPixelLimit;

View File

@ -12,6 +12,10 @@
* (at your option) any later version. *
* *
***************************************************************************/
#include <QDialogButtonBox>
#include <QDomElement>
#include "qgslabelingwidget.h"
#include "qgslabelengineconfigdialog.h"
@ -31,14 +35,68 @@ QgsLabelingWidget::QgsLabelingWidget( QgsVectorLayer* layer, QgsMapCanvas* canva
connect( mEngineSettingsButton, SIGNAL( clicked() ), this, SLOT( showEngineConfigDialog() ) );
mLabelModeComboBox->setCurrentIndex( -1 );
mLabelGui = new QgsLabelingGui( nullptr, mCanvas, nullptr, this );
mStackedWidget->addWidget( mLabelGui );
connect( mLabelModeComboBox, SIGNAL( currentIndexChanged( int ) ), this, SLOT( labelModeChanged( int ) ) );
connect( mLabelGui, SIGNAL( widgetChanged() ), this, SIGNAL( widgetChanged() ) );
setLayer( layer );
}
void QgsLabelingWidget::resetSettings()
{
if ( mOldSettings )
{
mLayer->setLabeling( mOldSettings );
if ( mOldSettings->type() == "simple" )
{
mOldPalSettings.writeToLayer( mLayer );
}
}
setLayer( mLayer );
}
void QgsLabelingWidget::setLayer( QgsMapLayer* mapLayer )
{
if ( !mapLayer || mapLayer->type() != QgsMapLayer::VectorLayer )
{
setEnabled( false );
return;
}
else
{
setEnabled( true );
}
QgsVectorLayer *layer = qobject_cast<QgsVectorLayer*>( mapLayer );
mLayer = layer;
if ( mLayer->labeling() )
{
QDomDocument doc;
QDomElement oldSettings = mLayer->labeling()->save( doc );
mOldSettings = QgsAbstractVectorLayerLabeling::create( oldSettings );
mOldPalSettings.readFromLayer( mLayer );
}
else
mOldSettings = nullptr;
adaptToLayer();
}
void QgsLabelingWidget::setDockMode( bool enabled )
{
mDockMode = enabled;
mLabelGui->setDockMode( mDockMode );
}
void QgsLabelingWidget::adaptToLayer()
{
if ( !mLayer )
return;
QgsDebugMsg( QString( "Setting up for layer %1" ).arg( mLayer->name() ) );
mLabelModeComboBox->setCurrentIndex( -1 );
// pick the right mode of the layer
@ -72,7 +130,7 @@ void QgsLabelingWidget::writeSettingsToLayer()
}
else
{
qobject_cast<QgsLabelingGui*>( mWidget )->writeSettingsToLayer();
mLabelGui->writeSettingsToLayer();
}
}
@ -92,46 +150,32 @@ void QgsLabelingWidget::labelModeChanged( int index )
if ( index < 0 )
return;
if ( index != 2 )
{
if ( QgsLabelingGui* widgetSimple = qobject_cast<QgsLabelingGui*>( mWidget ) )
{
// lighter variant - just change the mode of existing widget
if ( index == 3 )
widgetSimple->setLabelMode( QgsLabelingGui::ObstaclesOnly );
else
widgetSimple->setLabelMode( static_cast< QgsLabelingGui::LabelMode >( index ) );
return;
}
}
// in general case we need to recreate the widget
if ( mWidget )
mStackedWidget->removeWidget( mWidget );
delete mWidget;
mWidget = nullptr;
if ( index == 2 )
{
mWidget = new QgsRuleBasedLabelingWidget( mLayer, mCanvas, this );
if ( mWidget )
mStackedWidget->removeWidget( mWidget );
delete mWidget;
mWidget = nullptr;
QgsRuleBasedLabelingWidget* ruleWidget = new QgsRuleBasedLabelingWidget( mLayer, mCanvas, this, mDockMode );
connect( ruleWidget, SIGNAL( widgetChanged() ), this, SIGNAL( widgetChanged() ) );
mWidget = ruleWidget;
mStackedWidget->addWidget( mWidget );
mStackedWidget->setCurrentWidget( mWidget );
}
else
{
QgsLabelingGui* w = new QgsLabelingGui( mLayer, mCanvas, nullptr, this );
if ( index == 3 )
w->setLabelMode( QgsLabelingGui::ObstaclesOnly );
mLabelGui->setLabelMode( QgsLabelingGui::ObstaclesOnly );
else
w->setLabelMode( static_cast< QgsLabelingGui::LabelMode >( index ) );
mLabelGui->setLabelMode( static_cast< QgsLabelingGui::LabelMode >( index ) );
w->init();
mWidget = w;
mLabelGui->setLayer( mLayer );
mStackedWidget->setCurrentWidget( mLabelGui );
}
mStackedWidget->addWidget( mWidget );
mStackedWidget->setCurrentWidget( mWidget );
emit widgetChanged();
}
void QgsLabelingWidget::showEngineConfigDialog()

View File

@ -4,11 +4,14 @@
#include <QWidget>
#include <ui_qgslabelingwidget.h>
#include <qgspallabeling.h>
class QgsLabelingGui;
class QgsMapCanvas;
class QgsRuleBasedLabelingWidget;
class QgsAbstractVectorLayerLabeling;
class QgsVectorLayer;
class QgsMapLayer;
/**
* Master widget for configuration of labeling of a vector layer
@ -20,6 +23,8 @@ class QgsLabelingWidget : public QWidget, private Ui::QgsLabelingWidget
QgsLabelingWidget( QgsVectorLayer* layer, QgsMapCanvas* canvas, QWidget* parent = nullptr );
public slots:
void setLayer( QgsMapLayer *layer );
void setDockMode( bool enabled );
//! save config to layer
void writeSettingsToLayer();
@ -29,6 +34,11 @@ class QgsLabelingWidget : public QWidget, private Ui::QgsLabelingWidget
//! reload the settings shown in the dialog from the current layer
void adaptToLayer();
void resetSettings();
signals:
void widgetChanged();
protected slots:
void labelModeChanged( int index );
void showEngineConfigDialog();
@ -37,7 +47,12 @@ class QgsLabelingWidget : public QWidget, private Ui::QgsLabelingWidget
QgsVectorLayer* mLayer;
QgsMapCanvas* mCanvas;
bool mDockMode;
QWidget* mWidget;
QgsLabelingGui* mLabelGui;
QgsAbstractVectorLayerLabeling* mOldSettings;
QgsPalLayerSettings mOldPalSettings;
};
#endif // QGSLABELINGWIDGET_H

View File

@ -0,0 +1,113 @@
#include <QLabel>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QWidget>
#include <QSizePolicy>
#include "qgsapplication.h"
#include "qgslabelingwidget.h"
#include "qgsmapstylingwidget.h"
#include "qgsmapcanvas.h"
#include "qgsmaplayer.h"
QgsMapStylingWidget::QgsMapStylingWidget( QgsMapCanvas* canvas, QWidget *parent ) :
QWidget( parent ), mMapCanvas( canvas ), mBlockAutoApply( false ), mCurrentLayer( nullptr )
{
QBoxLayout* layout = new QVBoxLayout();
layout->setContentsMargins( 0, 0, 0, 0 );
this->setLayout( layout );
mStackedWidget = new QStackedWidget( this );
mMapStyleTabs = new QTabWidget( this );
mMapStyleTabs->setDocumentMode( true );
mNotSupportedPage = mStackedWidget->addWidget( new QLabel( "Not supported currently" ) );
mVectorPage = mStackedWidget->addWidget( mMapStyleTabs );
layout->addWidget( mStackedWidget );
mButtonBox = new QDialogButtonBox( QDialogButtonBox::Reset | QDialogButtonBox::Apply );
mLiveApplyCheck = new QCheckBox( "Live update" );
mLiveApplyCheck->setChecked( true );
QHBoxLayout* bottomLayout = new QHBoxLayout( );
bottomLayout->addWidget( mButtonBox );
bottomLayout->addWidget( mLiveApplyCheck );
layout->addLayout( bottomLayout );
mLabelingWidget = new QgsLabelingWidget( 0, mMapCanvas, this );
mLabelingWidget->setDockMode( true );
connect( mLabelingWidget, SIGNAL( widgetChanged() ), this, SLOT( autoApply() ) );
// Only labels for now but styles and diagrams will come later
// int styleTabIndex = mMapStyleTabs->addTab( new QWidget(), QgsApplication::getThemeIcon( "propertyicons/symbology.png" ), "Styles" );
mLabelTabIndex = mMapStyleTabs->addTab( mLabelingWidget, QgsApplication::getThemeIcon( "labelingSingle.svg" ), "Labeling" );
// int diagramTabIndex = mMapStyleTabs->addTab( new QWidget(), QgsApplication::getThemeIcon( "propertyicons/diagram.png" ), "Diagrams" );
// mMapStyleTabs->setTabEnabled( styleTabIndex, false );
// mMapStyleTabs->setTabEnabled( diagramTabIndex, false );
mMapStyleTabs->setCurrentIndex( mLabelTabIndex );
connect( mLiveApplyCheck, SIGNAL( toggled( bool ) ), mButtonBox->button( QDialogButtonBox::Apply ), SLOT( setDisabled( bool ) ) );
connect( mButtonBox->button( QDialogButtonBox::Apply ), SIGNAL( clicked() ), this, SLOT( apply() ) );
connect( mButtonBox->button( QDialogButtonBox::Reset ), SIGNAL( clicked() ), this, SLOT( resetSettings() ) );
mButtonBox->button( QDialogButtonBox::Apply )->setEnabled( false );
mButtonBox->button( QDialogButtonBox::Reset )->setEnabled( false );
}
void QgsMapStylingWidget::setLayer( QgsMapLayer *layer )
{
if ( !layer )
return;
mBlockAutoApply = true;
mCurrentLayer = layer;
if ( layer->type() == QgsMapLayer::VectorLayer )
{
mStackedWidget->setCurrentIndex( mVectorPage );
// TODO Once there is support for more then just labels
// we need to add a check for the just the current tab
mMapStyleTabs->setCurrentIndex( mLabelTabIndex );
mLabelingWidget->setLayer( layer );
}
else if ( layer->type() == QgsMapLayer::RasterLayer )
{
mStackedWidget->setCurrentIndex( mNotSupportedPage );
}
else if ( layer->type() == QgsMapLayer::PluginLayer )
{
mStackedWidget->setCurrentIndex( mNotSupportedPage );
}
mBlockAutoApply = false;
mButtonBox->button( QDialogButtonBox::Reset )->setEnabled( false );
}
void QgsMapStylingWidget::apply()
{
if ( mStackedWidget->currentIndex() == mVectorPage &&
mMapStyleTabs->currentIndex() == mLabelTabIndex )
{
mLabelingWidget->apply();
mButtonBox->button( QDialogButtonBox::Reset )->setEnabled( true );
emit styleChanged( mCurrentLayer );
}
}
void QgsMapStylingWidget::autoApply()
{
if ( mLiveApplyCheck->isChecked() && !mBlockAutoApply )
apply();
}
void QgsMapStylingWidget::resetSettings()
{
if ( mStackedWidget->currentIndex() == mVectorPage &&
mMapStyleTabs->currentIndex() == mLabelTabIndex )
{
mLabelingWidget->resetSettings();
}
}

View File

@ -0,0 +1,46 @@
#ifndef QGSMAPSTYLESDOCK_H
#define QGSMAPSTYLESDOCK_H
#include <QWidget>
#include <QTabWidget>
#include <QStackedWidget>
#include <QDialogButtonBox>
#include <QCheckBox>
class QgsLabelingWidget;
class QgsMapLayer;
class QgsMapCanvas;
class APP_EXPORT QgsMapStylingWidget : public QWidget
{
Q_OBJECT
public:
explicit QgsMapStylingWidget( QgsMapCanvas *canvas, QWidget *parent = 0 );
QgsMapLayer* layer() { return mCurrentLayer; }
signals:
void styleChanged( QgsMapLayer* layer );
public slots:
void setLayer( QgsMapLayer* layer );
void apply();
void autoApply();
void resetSettings();
private:
int mNotSupportedPage;
int mVectorPage;
int mLabelTabIndex;
QgsMapCanvas* mMapCanvas;
bool mBlockAutoApply;
QgsMapLayer* mCurrentLayer;
QStackedWidget* mStackedWidget;
QTabWidget *mMapStyleTabs;
QgsLabelingWidget *mLabelingWidget;
QDialogButtonBox* mButtonBox;
QCheckBox* mLiveApplyCheck;
};
#endif // QGSMAPSTYLESDOCK_H

View File

@ -24,12 +24,14 @@
#include <QClipboard>
#include <QMessageBox>
QgsRuleBasedLabelingWidget::QgsRuleBasedLabelingWidget( QgsVectorLayer* layer, QgsMapCanvas* canvas, QWidget* parent )
QgsRuleBasedLabelingWidget::QgsRuleBasedLabelingWidget( QgsVectorLayer* layer, QgsMapCanvas* canvas, QWidget* parent, bool dockMode )
: QWidget( parent )
, mLayer( layer )
, mCanvas( canvas )
, mRootRule( nullptr )
, mModel( nullptr )
, mRuleProps( nullptr )
, mDockMode( dockMode )
{
setupUi( this );
@ -76,6 +78,11 @@ QgsRuleBasedLabelingWidget::~QgsRuleBasedLabelingWidget()
delete mRootRule;
}
void QgsRuleBasedLabelingWidget::setDockMode( bool enabled )
{
mDockMode = enabled;
}
void QgsRuleBasedLabelingWidget::writeSettingsToLayer()
{
// also clear old-style labeling config
@ -86,31 +93,83 @@ void QgsRuleBasedLabelingWidget::writeSettingsToLayer()
void QgsRuleBasedLabelingWidget::addRule()
{
QgsRuleBasedLabeling::Rule* newrule = new QgsRuleBasedLabeling::Rule( new QgsPalLayerSettings );
if ( mRuleProps )
mStackedWidget->removeWidget( mRuleProps );
QgsLabelingRulePropsDialog dlg( newrule, mLayer, this, mCanvas );
if ( dlg.exec() )
delete mRuleProps;
mRuleProps = nullptr;
// TODO Delete rule
QgsRuleBasedLabeling::Rule* newrule = new QgsRuleBasedLabeling::Rule( new QgsPalLayerSettings );
mRuleProps = new QgsLabelingRulePropsDialog( newrule, mLayer, this, mCanvas, mDockMode );
mRuleProps->setCurrentMode( QgsLabelingRulePropsDialog::Adding );
mStackedWidget->addWidget( mRuleProps );
mStackedWidget->setCurrentWidget( mRuleProps );
connect( mRuleProps, SIGNAL( widgetChanged() ), this, SIGNAL( widgetChanged() ) );
connect( mRuleProps, SIGNAL( accepted() ), this, SLOT( saveRule() ) );
connect( mRuleProps, SIGNAL( rejected() ), this, SLOT( rejectRule() ) );
addNewRule( newrule );
}
void QgsRuleBasedLabelingWidget::saveRuleEdit()
{
QModelIndex index = viewRules->selectionModel()->currentIndex();
mModel->updateRule( index.parent(), index.row() );
if ( mRuleProps )
mStackedWidget->removeWidget( mRuleProps );
delete mRuleProps;
mRuleProps = nullptr;
mStackedWidget->setCurrentIndex( 0 );
emit widgetChanged();
}
void QgsRuleBasedLabelingWidget::saveRule()
{
if ( mRuleProps )
mStackedWidget->removeWidget( mRuleProps );
delete mRuleProps;
mRuleProps = nullptr;
mStackedWidget->setCurrentIndex( 0 );
emit widgetChanged();
}
void QgsRuleBasedLabelingWidget::addNewRule( QgsRuleBasedLabeling::Rule* newrule )
{
if ( currentRule() )
{
QgsRuleBasedLabeling::Rule* current = currentRule();
if ( current )
{
// add after this rule
QModelIndex currentIndex = viewRules->selectionModel()->currentIndex();
mModel->insertRule( currentIndex.parent(), currentIndex.row() + 1, newrule );
}
else
{
// append to root rule
int rows = mModel->rowCount();
mModel->insertRule( QModelIndex(), rows, newrule );
}
// add after this rule
QModelIndex currentIndex = viewRules->selectionModel()->currentIndex();
mModel->insertRule( currentIndex.parent(), currentIndex.row() + 1, newrule );
viewRules->selectionModel()->select( mModel->index( currentIndex.row() + 1, 0 ), QItemSelectionModel::ClearAndSelect );
}
else
{
delete newrule;
// append to root rule
int rows = mModel->rowCount();
mModel->insertRule( QModelIndex(), rows, newrule );
viewRules->selectionModel()->select( mModel->index( rows, 0 ), QItemSelectionModel::ClearAndSelect );
}
}
void QgsRuleBasedLabelingWidget::rejectRule()
{
if ( mRuleProps->currentMode() == QgsLabelingRulePropsDialog::Adding )
removeRule();
mStackedWidget->setCurrentIndex( 0 );
if ( mRuleProps )
mStackedWidget->removeWidget( mRuleProps );
delete mRuleProps;
mRuleProps = nullptr;
emit widgetChanged();
}
void QgsRuleBasedLabelingWidget::editRule()
{
editRule( viewRules->selectionModel()->currentIndex() );
@ -120,14 +179,24 @@ void QgsRuleBasedLabelingWidget::editRule( const QModelIndex& index )
{
if ( !index.isValid() )
return;
QgsRuleBasedLabeling::Rule* rule = mModel->ruleForIndex( index );
QgsLabelingRulePropsDialog dlg( rule, mLayer, this, mCanvas );
if ( dlg.exec() )
{
// model should know about the change and emit dataChanged signal for the view
mModel->updateRule( index.parent(), index.row() );
}
if ( mRuleProps )
mStackedWidget->removeWidget( mRuleProps );
delete mRuleProps;
mRuleProps = nullptr;
QgsRuleBasedLabeling::Rule* rule = mModel->ruleForIndex( index );
mRuleProps = new QgsLabelingRulePropsDialog( rule, mLayer, this, mCanvas, mDockMode );
mRuleProps->setCurrentMode( QgsLabelingRulePropsDialog::Editing );
connect( mRuleProps, SIGNAL( widgetChanged() ), this, SIGNAL( widgetChanged() ) );
mStackedWidget->addWidget( mRuleProps );
mStackedWidget->setCurrentWidget( mRuleProps );
connect( mRuleProps, SIGNAL( accepted() ), this, SLOT( saveRuleEdit() ) );
connect( mRuleProps, SIGNAL( rejected() ), this, SLOT( rejectRule() ) );
}
void QgsRuleBasedLabelingWidget::removeRule()
@ -142,6 +211,7 @@ void QgsRuleBasedLabelingWidget::removeRule()
}
// make sure that the selection is gone
viewRules->selectionModel()->clear();
emit widgetChanged();
}
void QgsRuleBasedLabelingWidget::copy()
@ -154,6 +224,7 @@ void QgsRuleBasedLabelingWidget::copy()
QMimeData* mime = mModel->mimeData( indexlist );
QApplication::clipboard()->setMimeData( mime );
emit widgetChanged();
}
void QgsRuleBasedLabelingWidget::paste()
@ -166,6 +237,7 @@ void QgsRuleBasedLabelingWidget::paste()
else
index = indexlist.first();
mModel->dropMimeData( mime, Qt::CopyAction, index.row(), index.column(), index.parent() );
emit widgetChanged();
}
QgsRuleBasedLabeling::Rule* QgsRuleBasedLabelingWidget::currentRule()
@ -550,8 +622,8 @@ void QgsRuleBasedLabelingModel::updateRule( const QModelIndex& parent, int row )
/////////
QgsLabelingRulePropsDialog::QgsLabelingRulePropsDialog( QgsRuleBasedLabeling::Rule* rule, QgsVectorLayer* layer, QWidget* parent, QgsMapCanvas* mapCanvas )
: QDialog( parent ), mRule( rule ), mLayer( layer ), mLabelingGui( nullptr ), mSettings( nullptr ), mMapCanvas( mapCanvas )
QgsLabelingRulePropsDialog::QgsLabelingRulePropsDialog( QgsRuleBasedLabeling::Rule* rule, QgsVectorLayer* layer, QWidget* parent, QgsMapCanvas* mapCanvas, bool dockMode )
: QDialog( parent ), mRule( rule ), mLayer( layer ), mLabelingGui( nullptr ), mSettings( nullptr ), mMapCanvas( mapCanvas ), mDockMode( dockMode )
{
setupUi( this );
#ifdef Q_OS_MAC
@ -588,17 +660,21 @@ QgsLabelingRulePropsDialog::QgsLabelingRulePropsDialog( QgsRuleBasedLabeling::Ru
mSettings = new QgsPalLayerSettings;
}
mLabelingGui = new QgsLabelingGui( mLayer, mMapCanvas, mSettings, this );
mLabelingGui = new QgsLabelingGui( nullptr, mMapCanvas, mSettings, this );
mLabelingGui->setDockMode( mDockMode );
mLabelingGui->layout()->setContentsMargins( 0, 0, 0, 0 );
QVBoxLayout* l = new QVBoxLayout;
l->addWidget( mLabelingGui );
groupSettings->setLayout( l );
mLabelingGui->setLabelMode( QgsLabelingGui::Labels );
mLabelingGui->init();
mLabelingGui->setLayer( mLayer );
connect( btnExpressionBuilder, SIGNAL( clicked() ), this, SLOT( buildExpression() ) );
connect( btnTestFilter, SIGNAL( clicked() ), this, SLOT( testFilter() ) );
connect( editFilter, SIGNAL( textEdited( QString ) ), this, SIGNAL( widgetChanged() ) );
connect( mLabelingGui, SIGNAL( widgetChanged() ), this, SIGNAL( widgetChanged() ) );
connect( this, SIGNAL( widgetChanged() ), this, SLOT( updateRule() ) );
QSettings settings;
restoreGeometry( settings.value( "/Windows/QgsLabelingRulePropsDialog/geometry" ).toByteArray() );
@ -686,7 +762,7 @@ void QgsLabelingRulePropsDialog::buildExpression()
editFilter->setText( dlg.expressionText() );
}
void QgsLabelingRulePropsDialog::accept()
void QgsLabelingRulePropsDialog::updateRule()
{
mRule->setFilterExpression( editFilter->text() );
mRule->setDescription( editDescription->text() );
@ -694,6 +770,10 @@ void QgsLabelingRulePropsDialog::accept()
mRule->setScaleMinDenom( groupScale->isChecked() ? mScaleRangeWidget->minimumScaleDenom() : 0 );
mRule->setScaleMaxDenom( groupScale->isChecked() ? mScaleRangeWidget->maximumScaleDenom() : 0 );
mRule->setSettings( groupSettings->isChecked() ? new QgsPalLayerSettings( mLabelingGui->layerSettings() ) : nullptr );
}
void QgsLabelingRulePropsDialog::accept()
{
updateRule();
QDialog::accept();
}

View File

@ -72,27 +72,37 @@ class APP_EXPORT QgsRuleBasedLabelingModel : public QAbstractItemModel
};
class QgsLabelingRulePropsDialog;
class QgsRuleBasedLabelingWidget : public QWidget, private Ui::QgsRuleBasedLabelingWidget
{
Q_OBJECT
public:
QgsRuleBasedLabelingWidget( QgsVectorLayer* layer, QgsMapCanvas* canvas, QWidget* parent = nullptr );
QgsRuleBasedLabelingWidget( QgsVectorLayer* layer, QgsMapCanvas* canvas, QWidget* parent = nullptr, bool dockMode = false );
~QgsRuleBasedLabelingWidget();
//! save config to layer
void writeSettingsToLayer();
void setDockMode( bool enabled );
signals:
void widgetChanged();
protected slots:
void saveRuleEdit();
void addRule();
void saveRule();
void rejectRule();
void editRule();
void editRule( const QModelIndex& index );
void removeRule();
void copy();
void paste();
private:
void addNewRule( QgsRuleBasedLabeling::Rule* newrule );
protected:
QgsRuleBasedLabeling::Rule* currentRule();
@ -102,10 +112,12 @@ class QgsRuleBasedLabelingWidget : public QWidget, private Ui::QgsRuleBasedLabel
QgsRuleBasedLabeling::Rule* mRootRule;
QgsRuleBasedLabelingModel* mModel;
QgsLabelingRulePropsDialog* mRuleProps;
QAction* mCopyAction;
QAction* mPasteAction;
QAction* mDeleteAction;
bool mDockMode;
};
@ -120,14 +132,29 @@ class APP_EXPORT QgsLabelingRulePropsDialog : public QDialog, private Ui::QgsLab
Q_OBJECT
public:
QgsLabelingRulePropsDialog( QgsRuleBasedLabeling::Rule* rule, QgsVectorLayer* layer, QWidget* parent = nullptr, QgsMapCanvas* mapCanvas = nullptr );
enum Mode
{
Adding,
Editing
};
QgsLabelingRulePropsDialog( QgsRuleBasedLabeling::Rule* rule, QgsVectorLayer* layer,
QWidget* parent = nullptr, QgsMapCanvas* mapCanvas = nullptr,
bool dockMode = false );
~QgsLabelingRulePropsDialog();
QgsRuleBasedLabeling::Rule* rule() { return mRule; }
Mode currentMode() { return mCurrentMode; }
void setCurrentMode( Mode currentMode ) { mCurrentMode = currentMode; }
signals:
void widgetChanged();
public slots:
void testFilter();
void buildExpression();
void updateRule();
void accept() override;
protected:
@ -138,6 +165,8 @@ class APP_EXPORT QgsLabelingRulePropsDialog : public QDialog, private Ui::QgsLab
QgsPalLayerSettings* mSettings; // a clone of original settings
QgsMapCanvas* mMapCanvas;
bool mDockMode;
Mode mCurrentMode;
};

View File

@ -200,5 +200,4 @@ namespace QgisGui
return QFontDialog::getFont( &ok, initial, nullptr, title );
#endif
}
} // end of QgisGui namespace

View File

@ -127,6 +127,9 @@ class GUI_EXPORT QgsFieldExpressionWidget : public QWidget
//! convenience slot to connect QgsMapLayerComboBox layer signal
void setLayer( QgsMapLayer* layer );
//! sets the current row in the widget
void setRow( int row ) { mCombo->setCurrentIndex( row ); }
//! sets the current field or expression in the widget
void setField( const QString &fieldName );

File diff suppressed because it is too large Load Diff

View File

@ -14,96 +14,124 @@
<string>Rule properties</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="margin">
<number>0</number>
</property>
<item>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
<widget class="QScrollArea" name="scrollArea">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_1">
<property name="text">
<string>Description</string>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>666</width>
<height>540</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="margin">
<number>0</number>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="editDescription"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Filter</string>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLineEdit" name="editFilter"/>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_1">
<property name="text">
<string>Description</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="editDescription"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Filter</string>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLineEdit" name="editFilter"/>
</item>
<item>
<widget class="QPushButton" name="btnExpressionBuilder">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnTestFilter">
<property name="text">
<string>Test</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="QPushButton" name="btnExpressionBuilder">
<widget class="QGroupBox" name="groupScale">
<property name="title">
<string>Scale range</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QgsScaleRangeWidget" name="mScaleRangeWidget">
<property name="toolTip">
<string/>
</property>
<property name="whatsThis">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupSettings">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>...</string>
<property name="title">
<string>Labels</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnTestFilter">
<property name="text">
<string>Test</string>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="groupScale">
<property name="title">
<string>Scale range</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QgsScaleRangeWidget" name="mScaleRangeWidget" native="true">
<property name="toolTip">
<string/>
</property>
<property name="whatsThis">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupSettings">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Labels</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</widget>
</item>
<item>
@ -112,7 +140,7 @@
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Save</set>
</property>
</widget>
</item>
@ -130,8 +158,6 @@
<tabstop>editFilter</tabstop>
<tabstop>btnExpressionBuilder</tabstop>
<tabstop>btnTestFilter</tabstop>
<tabstop>groupScale</tabstop>
<tabstop>groupSettings</tabstop>
<tabstop>buttonBox</tabstop>
</tabstops>
<resources/>

View File

@ -97,6 +97,16 @@
<item>
<widget class="QStackedWidget" name="mStackedWidget"/>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="spacing">
<number>12</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
</layout>
</item>
</layout>
</widget>
<resources>

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
<width>457</width>
<height>372</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
@ -15,92 +15,106 @@
<number>0</number>
</property>
<item>
<widget class="QTreeView" name="viewRules">
<property name="contextMenuPolicy">
<enum>Qt::ActionsContextMenu</enum>
<widget class="QStackedWidget" name="mStackedWidget">
<property name="currentIndex">
<number>0</number>
</property>
<property name="acceptDrops">
<bool>true</bool>
</property>
<property name="editTriggers">
<set>QAbstractItemView::EditKeyPressed|QAbstractItemView::SelectedClicked</set>
</property>
<property name="dragEnabled">
<bool>true</bool>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::InternalMove</enum>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
<property name="allColumnsShowFocus">
<bool>true</bool>
</property>
<attribute name="headerMinimumSectionSize">
<number>100</number>
</attribute>
<widget class="QWidget" name="rulesPage">
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QTreeView" name="viewRules">
<property name="contextMenuPolicy">
<enum>Qt::ActionsContextMenu</enum>
</property>
<property name="acceptDrops">
<bool>true</bool>
</property>
<property name="editTriggers">
<set>QAbstractItemView::EditKeyPressed|QAbstractItemView::SelectedClicked</set>
</property>
<property name="dragEnabled">
<bool>true</bool>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::InternalMove</enum>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
<property name="allColumnsShowFocus">
<bool>true</bool>
</property>
<attribute name="headerMinimumSectionSize">
<number>100</number>
</attribute>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="btnAddRule">
<property name="toolTip">
<string>Add rule</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/symbologyAdd.svg</normaloff>:/images/themes/default/symbologyAdd.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnEditRule">
<property name="toolTip">
<string>Edit rule</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/symbologyEdit.png</normaloff>:/images/themes/default/symbologyEdit.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnRemoveRule">
<property name="toolTip">
<string>Remove rule</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/symbologyRemove.svg</normaloff>:/images/themes/default/symbologyRemove.svg</iconset>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="btnAddRule">
<property name="toolTip">
<string>Add rule</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/symbologyAdd.svg</normaloff>:/images/themes/default/symbologyAdd.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnEditRule">
<property name="toolTip">
<string>Edit rule</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/symbologyEdit.png</normaloff>:/images/themes/default/symbologyEdit.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnRemoveRule">
<property name="toolTip">
<string>Remove rule</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/symbologyRemove.svg</normaloff>:/images/themes/default/symbologyRemove.svg</iconset>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
<resources>