mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-26 00:02:08 -05:00
Merge pull request #3438 from nyalldawson/replace
[FEATURE] Substitution list support for labeling
This commit is contained in:
commit
891370fd68
@ -464,6 +464,11 @@ class QgsPalLayerSettings
|
||||
QPainter::CompositionMode blendMode;
|
||||
QColor previewBkgrdColor;
|
||||
|
||||
//! Substitution collection for automatic text substitution with labels
|
||||
QgsStringReplacementCollection substitutions;
|
||||
//! True if substitutions should be applied
|
||||
bool useSubstitutions;
|
||||
|
||||
//-- text formatting
|
||||
|
||||
QString wrapChar;
|
||||
|
@ -1,3 +1,115 @@
|
||||
|
||||
|
||||
/** \ingroup core
|
||||
* \class QgsStringReplacement
|
||||
* \brief A representation of a single string replacement.
|
||||
* \note Added in version 3.0
|
||||
*/
|
||||
|
||||
class QgsStringReplacement
|
||||
{
|
||||
%TypeHeaderCode
|
||||
#include <qgsstringutils.h>
|
||||
%End
|
||||
public:
|
||||
|
||||
/** Constructor for QgsStringReplacement.
|
||||
* @param match string to match
|
||||
* @param replacement string to replace match with
|
||||
* @param caseSensitive set to true for a case sensitive match
|
||||
* @param wholeWordOnly set to true to match complete words only, or false to allow partial word matches
|
||||
*/
|
||||
QgsStringReplacement( const QString& match,
|
||||
const QString& replacement,
|
||||
bool caseSensitive = false,
|
||||
bool wholeWordOnly = false );
|
||||
|
||||
//! Returns the string matched by this object
|
||||
QString match() const;
|
||||
|
||||
//! Returns the string to replace matches with
|
||||
QString replacement() const;
|
||||
|
||||
//! Returns true if match is case sensitive
|
||||
bool caseSensitive() const;
|
||||
|
||||
//! Returns true if match only applies to whole words, or false if partial word matches are permitted
|
||||
bool wholeWordOnly() const;
|
||||
|
||||
/** Processes a given input string, applying any valid replacements which should be made.
|
||||
* @param input input string
|
||||
* @returns input string with any matches replaced by replacement string
|
||||
*/
|
||||
QString process( const QString& input ) const;
|
||||
|
||||
bool operator==( const QgsStringReplacement& other );
|
||||
|
||||
/** Returns a map of the replacement properties.
|
||||
* @see fromProperties()
|
||||
*/
|
||||
QgsStringMap properties() const;
|
||||
|
||||
/** Creates a new QgsStringReplacement from an encoded properties map.
|
||||
* @see properties()
|
||||
*/
|
||||
static QgsStringReplacement fromProperties( const QgsStringMap& properties );
|
||||
|
||||
};
|
||||
|
||||
|
||||
/** \ingroup core
|
||||
* \class QgsStringReplacementCollection
|
||||
* \brief A collection of string replacements (specified using QgsStringReplacement objects).
|
||||
* \note Added in version 3.0
|
||||
*/
|
||||
|
||||
class QgsStringReplacementCollection
|
||||
{
|
||||
%TypeHeaderCode
|
||||
#include <qgsstringutils.h>
|
||||
%End
|
||||
public:
|
||||
|
||||
/** Constructor for QgsStringReplacementCollection
|
||||
* @param replacements initial list of string replacements
|
||||
*/
|
||||
QgsStringReplacementCollection( const QList< QgsStringReplacement >& replacements = QList< QgsStringReplacement >() );
|
||||
|
||||
/** Returns the list of string replacements in this collection.
|
||||
* @see setReplacements()
|
||||
*/
|
||||
QList< QgsStringReplacement > replacements() const;
|
||||
|
||||
/** Sets the list of string replacements in this collection.
|
||||
* @param replacements list of string replacements to apply. Replacements are applied in the
|
||||
* order they are specified here.
|
||||
* @see replacements()
|
||||
*/
|
||||
void setReplacements( const QList< QgsStringReplacement >& replacements );
|
||||
|
||||
/** Processes a given input string, applying any valid replacements which should be made
|
||||
* using QgsStringReplacement objects contained by this collection. Replacements
|
||||
* are made in order of the QgsStringReplacement objects contained in the collection.
|
||||
* @param input input string
|
||||
* @returns input string with any matches replaced by replacement string
|
||||
*/
|
||||
QString process( const QString& input ) const;
|
||||
|
||||
/** Writes the collection state to an XML element.
|
||||
* @param elem target DOM element
|
||||
* @param doc DOM document
|
||||
* @see readXml()
|
||||
*/
|
||||
void writeXml( QDomElement& elem, QDomDocument& doc ) const;
|
||||
|
||||
/** Reads the collection state from an XML element.
|
||||
* @param elem DOM element
|
||||
* @see writeXml()
|
||||
*/
|
||||
void readXml( const QDomElement& elem );
|
||||
};
|
||||
|
||||
|
||||
/** \ingroup core
|
||||
* \class QgsStringUtils
|
||||
* \brief Utility functions for working with strings.
|
||||
|
@ -114,6 +114,7 @@ SET(QGIS_APP_SRCS
|
||||
qgsrelationadddlg.cpp
|
||||
qgsselectbyformdialog.cpp
|
||||
qgsstatisticalsummarydockwidget.cpp
|
||||
qgssubstitutionlistwidget.cpp
|
||||
qgstextannotationdialog.cpp
|
||||
qgssnappingdialog.cpp
|
||||
qgssvgannotationdialog.cpp
|
||||
@ -290,6 +291,7 @@ SET (QGIS_APP_MOC_HDRS
|
||||
qgssnappingdialog.h
|
||||
qgssponsors.h
|
||||
qgsstatisticalsummarydockwidget.h
|
||||
qgssubstitutionlistwidget.h
|
||||
qgssvgannotationdialog.h
|
||||
qgstextannotationdialog.h
|
||||
qgstipgui.h
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "qgssvgselectorwidget.h"
|
||||
#include "qgsvectorlayerlabeling.h"
|
||||
#include "qgslogger.h"
|
||||
#include "qgssubstitutionlistwidget.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QSettings>
|
||||
@ -137,6 +138,7 @@ QgsLabelingGui::QgsLabelingGui( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas,
|
||||
connect( mShadowTranspSlider, SIGNAL( valueChanged( int ) ), mShadowTranspSpnBx, SLOT( setValue( int ) ) );
|
||||
connect( mShadowTranspSpnBx, SIGNAL( valueChanged( int ) ), mShadowTranspSlider, SLOT( setValue( int ) ) );
|
||||
connect( mLimitLabelChkBox, SIGNAL( toggled( bool ) ), mLimitLabelSpinBox, SLOT( setEnabled( bool ) ) );
|
||||
connect( mCheckBoxSubstituteText, SIGNAL( toggled( bool ) ), mToolButtonConfigureSubstitutes, SLOT( setEnabled( bool ) ) );
|
||||
|
||||
//connections to prevent users removing all line placement positions
|
||||
connect( chkLineAbove, SIGNAL( toggled( bool ) ), this, SLOT( updateLinePlacementOptions() ) );
|
||||
@ -466,7 +468,8 @@ QgsLabelingGui::QgsLabelingGui( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas,
|
||||
<< radPolygonPerimeter
|
||||
<< radPolygonPerimeterCurved
|
||||
<< radPredefinedOrder
|
||||
<< mFieldExpressionWidget;
|
||||
<< mFieldExpressionWidget
|
||||
<< mCheckBoxSubstituteText;
|
||||
connectValueChanged( widgets, SLOT( updatePreview() ) );
|
||||
|
||||
connect( mQuadrantBtnGrp, SIGNAL( buttonClicked( int ) ), this, SLOT( updatePreview() ) );
|
||||
@ -623,6 +626,8 @@ void QgsLabelingGui::init()
|
||||
// set the current field or add the current expression to the bottom of the list
|
||||
mFieldExpressionWidget->setRow( -1 );
|
||||
mFieldExpressionWidget->setField( lyr.fieldName );
|
||||
mCheckBoxSubstituteText->setChecked( lyr.useSubstitutions );
|
||||
mSubstitutions = lyr.substitutions;
|
||||
|
||||
// populate placement options
|
||||
mCentroidRadioWhole->setChecked( lyr.centroidWhole );
|
||||
@ -1013,6 +1018,8 @@ QgsPalLayerSettings QgsLabelingGui::layerSettings()
|
||||
lyr.scaleVisibility = mScaleBasedVisibilityChkBx->isChecked();
|
||||
lyr.scaleMin = mScaleBasedVisibilityMinSpnBx->value();
|
||||
lyr.scaleMax = mScaleBasedVisibilityMaxSpnBx->value();
|
||||
lyr.useSubstitutions = mCheckBoxSubstituteText->isChecked();
|
||||
lyr.substitutions = mSubstitutions;
|
||||
|
||||
// buffer
|
||||
lyr.bufferDraw = mBufferDrawChkBx->isChecked();
|
||||
@ -1973,6 +1980,12 @@ void QgsLabelingGui::updateLinePlacementOptions()
|
||||
}
|
||||
}
|
||||
|
||||
void QgsLabelingGui::onSubstitutionsChanged( const QgsStringReplacementCollection& substitutions )
|
||||
{
|
||||
mSubstitutions = substitutions;
|
||||
emit widgetChanged();
|
||||
}
|
||||
|
||||
void QgsLabelingGui::updateSvgWidgets( const QString& svgPath )
|
||||
{
|
||||
if ( mShapeSVGPathLineEdit->text() != svgPath )
|
||||
@ -2099,6 +2112,28 @@ void QgsLabelingGui::on_mChkNoObstacle_toggled( bool active )
|
||||
mObstaclePriorityFrame->setEnabled( active );
|
||||
}
|
||||
|
||||
void QgsLabelingGui::on_mToolButtonConfigureSubstitutes_clicked()
|
||||
{
|
||||
QgsPanelWidget* panel = QgsPanelWidget::findParentPanel( this );
|
||||
if ( panel && panel->dockMode() )
|
||||
{
|
||||
QgsSubstitutionListWidget* widget = new QgsSubstitutionListWidget( panel );
|
||||
widget->setPanelTitle( tr( "Substitutions" ) );
|
||||
widget->setSubstitutions( mSubstitutions );
|
||||
connect( widget, SIGNAL( substitutionsChanged( QgsStringReplacementCollection ) ), this, SLOT( onSubstitutionsChanged( QgsStringReplacementCollection ) ) );
|
||||
panel->openPanel( widget );
|
||||
return;
|
||||
}
|
||||
|
||||
QgsSubstitutionListDialog dlg( this );
|
||||
dlg.setSubstitutions( mSubstitutions );
|
||||
if ( dlg.exec() == QDialog::Accepted )
|
||||
{
|
||||
mSubstitutions = dlg.substitutions();
|
||||
emit widgetChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void QgsLabelingGui::showBackgroundRadius( bool show )
|
||||
{
|
||||
mShapeRadiusLabel->setVisible( show );
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <QDialog>
|
||||
#include <QFontDatabase>
|
||||
#include <ui_qgslabelingguibase.h>
|
||||
#include "qgsstringutils.h"
|
||||
|
||||
class QgsVectorLayer;
|
||||
class QgsMapCanvas;
|
||||
@ -94,6 +95,8 @@ class APP_EXPORT QgsLabelingGui : public QWidget, private Ui::QgsLabelingGuiBase
|
||||
void on_mDirectSymbRightToolBtn_clicked();
|
||||
void on_mChkNoObstacle_toggled( bool active );
|
||||
|
||||
void on_mToolButtonConfigureSubstitutes_clicked();
|
||||
|
||||
protected:
|
||||
void blockInitSignals( bool block );
|
||||
void blockFontChangeSignals( bool blk );
|
||||
@ -133,6 +136,8 @@ class APP_EXPORT QgsLabelingGui : public QWidget, private Ui::QgsLabelingGuiBase
|
||||
|
||||
bool mLoadSvgParams;
|
||||
|
||||
QgsStringReplacementCollection mSubstitutions;
|
||||
|
||||
void enableDataDefinedAlignment( bool enable );
|
||||
|
||||
QgsExpressionContext createExpressionContext() const override;
|
||||
@ -143,6 +148,7 @@ class APP_EXPORT QgsLabelingGui : public QWidget, private Ui::QgsLabelingGuiBase
|
||||
void showBackgroundPenStyle( bool show );
|
||||
void on_mShapeSVGPathLineEdit_textChanged( const QString& text );
|
||||
void updateLinePlacementOptions();
|
||||
void onSubstitutionsChanged( const QgsStringReplacementCollection& substitutions );
|
||||
};
|
||||
|
||||
#endif
|
||||
|
230
src/app/qgssubstitutionlistwidget.cpp
Normal file
230
src/app/qgssubstitutionlistwidget.cpp
Normal file
@ -0,0 +1,230 @@
|
||||
/***************************************************************************
|
||||
qgssubstitutionlistwidget.cpp
|
||||
-----------------------------
|
||||
begin : August 2016
|
||||
copyright : (C) 2016 Nyall Dawson
|
||||
email : nyall dot dawson at gmail dot com
|
||||
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "qgssubstitutionlistwidget.h"
|
||||
#include <QDialogButtonBox>
|
||||
#include <QCheckBox>
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QTextStream>
|
||||
|
||||
QgsSubstitutionListWidget::QgsSubstitutionListWidget( QWidget* parent )
|
||||
: QgsPanelWidget( parent )
|
||||
{
|
||||
setupUi( this );
|
||||
connect( mTableSubstitutions, SIGNAL( cellChanged( int, int ) ), this, SLOT( tableChanged() ) );
|
||||
}
|
||||
|
||||
void QgsSubstitutionListWidget::setSubstitutions( const QgsStringReplacementCollection& substitutions )
|
||||
{
|
||||
mTableSubstitutions->blockSignals( true );
|
||||
mTableSubstitutions->clearContents();
|
||||
Q_FOREACH ( const QgsStringReplacement& replacement, substitutions.replacements() )
|
||||
{
|
||||
addSubstitution( replacement );
|
||||
}
|
||||
mTableSubstitutions->blockSignals( false );
|
||||
}
|
||||
|
||||
QgsStringReplacementCollection QgsSubstitutionListWidget::substitutions() const
|
||||
{
|
||||
QList< QgsStringReplacement > result;
|
||||
for ( int i = 0; i < mTableSubstitutions->rowCount(); ++i )
|
||||
{
|
||||
if ( !mTableSubstitutions->item( i, 0 ) )
|
||||
continue;
|
||||
|
||||
if ( mTableSubstitutions->item( i, 0 )->text().isEmpty() )
|
||||
continue;
|
||||
|
||||
QCheckBox* chkCaseSensitive = qobject_cast<QCheckBox*>( mTableSubstitutions->cellWidget( i, 2 ) );
|
||||
QCheckBox* chkWholeWord = qobject_cast<QCheckBox*>( mTableSubstitutions->cellWidget( i, 3 ) );
|
||||
|
||||
QgsStringReplacement replacement( mTableSubstitutions->item( i, 0 )->text(),
|
||||
mTableSubstitutions->item( i, 1 )->text(),
|
||||
chkCaseSensitive->isChecked(),
|
||||
chkWholeWord->isChecked() );
|
||||
result << replacement;
|
||||
}
|
||||
return QgsStringReplacementCollection( result );
|
||||
}
|
||||
|
||||
void QgsSubstitutionListWidget::on_mButtonAdd_clicked()
|
||||
{
|
||||
addSubstitution( QgsStringReplacement( QString(), QString(), false, true ) );
|
||||
mTableSubstitutions->setFocus();
|
||||
mTableSubstitutions->setCurrentCell( mTableSubstitutions->rowCount() - 1, 0 );
|
||||
}
|
||||
|
||||
void QgsSubstitutionListWidget::on_mButtonRemove_clicked()
|
||||
{
|
||||
int currentRow = mTableSubstitutions->currentRow();
|
||||
mTableSubstitutions->removeRow( currentRow );
|
||||
tableChanged();
|
||||
}
|
||||
|
||||
void QgsSubstitutionListWidget::tableChanged()
|
||||
{
|
||||
emit substitutionsChanged( substitutions() );
|
||||
}
|
||||
|
||||
void QgsSubstitutionListWidget::on_mButtonExport_clicked()
|
||||
{
|
||||
QString fileName = QFileDialog::getSaveFileName( this, tr( "Save substitutions" ), QDir::homePath(),
|
||||
tr( "XML files (*.xml *.XML)" ) );
|
||||
if ( fileName.isEmpty() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// ensure the user never ommited the extension from the file name
|
||||
if ( !fileName.endsWith( ".xml", Qt::CaseInsensitive ) )
|
||||
{
|
||||
fileName += ".xml";
|
||||
}
|
||||
|
||||
QDomDocument doc;
|
||||
QDomElement root = doc.createElement( "substitutions" );
|
||||
root.setAttribute( "version", "1.0" );
|
||||
QgsStringReplacementCollection collection = substitutions();
|
||||
collection.writeXml( root, doc );
|
||||
doc.appendChild( root );
|
||||
|
||||
QFile file( fileName );
|
||||
if ( !file.open( QIODevice::WriteOnly | QIODevice::Text ) )
|
||||
{
|
||||
QMessageBox::warning( nullptr, tr( "Export substitutions" ),
|
||||
tr( "Cannot write file %1:\n%2." ).arg( fileName, file.errorString() ),
|
||||
QMessageBox::Ok,
|
||||
QMessageBox::Ok );
|
||||
return;
|
||||
}
|
||||
|
||||
QTextStream out( &file );
|
||||
doc.save( out, 4 );
|
||||
}
|
||||
|
||||
void QgsSubstitutionListWidget::on_mButtonImport_clicked()
|
||||
{
|
||||
QString fileName = QFileDialog::getOpenFileName( this, tr( "Load substitutions" ), QDir::homePath(),
|
||||
tr( "XML files (*.xml *.XML)" ) );
|
||||
if ( fileName.isEmpty() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QFile file( fileName );
|
||||
if ( !file.open( QIODevice::ReadOnly | QIODevice::Text ) )
|
||||
{
|
||||
QMessageBox::warning( nullptr, tr( "Import substitutions" ),
|
||||
tr( "Cannot read file %1:\n%2." ).arg( fileName, file.errorString() ),
|
||||
QMessageBox::Ok,
|
||||
QMessageBox::Ok );
|
||||
return;
|
||||
}
|
||||
|
||||
QDomDocument doc;
|
||||
QString errorStr;
|
||||
int errorLine;
|
||||
int errorColumn;
|
||||
|
||||
if ( !doc.setContent( &file, true, &errorStr, &errorLine, &errorColumn ) )
|
||||
{
|
||||
QMessageBox::warning( nullptr, tr( "Import substitutions" ),
|
||||
tr( "Parse error at line %1, column %2:\n%3" )
|
||||
.arg( errorLine )
|
||||
.arg( errorColumn )
|
||||
.arg( errorStr ),
|
||||
QMessageBox::Ok,
|
||||
QMessageBox::Ok );
|
||||
return;
|
||||
}
|
||||
|
||||
QDomElement root = doc.documentElement();
|
||||
if ( root.tagName() != "substitutions" )
|
||||
{
|
||||
QMessageBox::warning( nullptr, tr( "Import substitutions" ),
|
||||
tr( "The selected file in not an substitutions list." ),
|
||||
QMessageBox::Ok,
|
||||
QMessageBox::Ok );
|
||||
return;
|
||||
}
|
||||
|
||||
QgsStringReplacementCollection collection;
|
||||
collection.readXml( root );
|
||||
setSubstitutions( collection );
|
||||
tableChanged();
|
||||
}
|
||||
|
||||
void QgsSubstitutionListWidget::addSubstitution( const QgsStringReplacement& substitution )
|
||||
{
|
||||
int row = mTableSubstitutions->rowCount();
|
||||
mTableSubstitutions->insertRow( row );
|
||||
|
||||
Qt::ItemFlags itemFlags = Qt::ItemIsEnabled | Qt::ItemIsSelectable
|
||||
| Qt::ItemIsEditable;
|
||||
|
||||
QTableWidgetItem* matchItem = new QTableWidgetItem( substitution.match() );
|
||||
matchItem->setFlags( itemFlags );
|
||||
mTableSubstitutions->setItem( row, 0, matchItem );
|
||||
QTableWidgetItem* replaceItem = new QTableWidgetItem( substitution.replacement() );
|
||||
replaceItem->setFlags( itemFlags );
|
||||
mTableSubstitutions->setItem( row, 1, replaceItem );
|
||||
|
||||
QCheckBox* caseSensitiveChk = new QCheckBox( this );
|
||||
caseSensitiveChk->setChecked( substitution.caseSensitive() );
|
||||
mTableSubstitutions->setCellWidget( row, 2, caseSensitiveChk );
|
||||
connect( caseSensitiveChk, SIGNAL( toggled( bool ) ), this, SLOT( tableChanged() ) );
|
||||
|
||||
QCheckBox* wholeWordChk = new QCheckBox( this );
|
||||
wholeWordChk->setChecked( substitution.wholeWordOnly() );
|
||||
mTableSubstitutions->setCellWidget( row, 3, wholeWordChk );
|
||||
connect( wholeWordChk, SIGNAL( toggled( bool ) ), this, SLOT( tableChanged() ) );
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// QgsSubstitutionListDialog
|
||||
//
|
||||
|
||||
|
||||
QgsSubstitutionListDialog::QgsSubstitutionListDialog( QWidget* parent )
|
||||
: QDialog( parent )
|
||||
, mWidget( nullptr )
|
||||
{
|
||||
setWindowTitle( tr( "Substitutions" ) );
|
||||
QVBoxLayout* vLayout = new QVBoxLayout();
|
||||
mWidget = new QgsSubstitutionListWidget();
|
||||
vLayout->addWidget( mWidget );
|
||||
QDialogButtonBox* bbox = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal );
|
||||
connect( bbox, SIGNAL( accepted() ), this, SLOT( accept() ) );
|
||||
connect( bbox, SIGNAL( rejected() ), this, SLOT( reject() ) );
|
||||
vLayout->addWidget( bbox );
|
||||
setLayout( vLayout );
|
||||
}
|
||||
|
||||
void QgsSubstitutionListDialog::setSubstitutions( const QgsStringReplacementCollection& substitutions )
|
||||
{
|
||||
mWidget->setSubstitutions( substitutions );
|
||||
}
|
||||
|
||||
QgsStringReplacementCollection QgsSubstitutionListDialog::substitutions() const
|
||||
{
|
||||
return mWidget->substitutions();
|
||||
}
|
111
src/app/qgssubstitutionlistwidget.h
Normal file
111
src/app/qgssubstitutionlistwidget.h
Normal file
@ -0,0 +1,111 @@
|
||||
/***************************************************************************
|
||||
qgssubstitutionlistwidget.h
|
||||
---------------------------
|
||||
begin : August 2016
|
||||
copyright : (C) 2016 Nyall Dawson
|
||||
email : nyall dot dawson at gmail dot com
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
#ifndef QGSSUBSTITUTIONLISTWIDGET_H
|
||||
#define QGSSUBSTITUTIONLISTWIDGET_H
|
||||
|
||||
#include <QDialog>
|
||||
#include "qgspanelwidget.h"
|
||||
#include "ui_qgssubstitutionlistwidgetbase.h"
|
||||
#include "qgsstringutils.h"
|
||||
|
||||
/** \class QgsSubstitutionListWidget
|
||||
* \ingroup app
|
||||
* A widget which allows users to specify a list of substitutions to apply to a string, with
|
||||
* options for exporting and importing substitution lists.
|
||||
* \note added in QGIS 3.0
|
||||
* \see QgsSubstitutionListDialog
|
||||
*/
|
||||
class APP_EXPORT QgsSubstitutionListWidget : public QgsPanelWidget, private Ui::QgsSubstitutionListWidgetBase
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY( QgsStringReplacementCollection substitutions READ substitutions WRITE setSubstitutions NOTIFY substitutionsChanged )
|
||||
|
||||
public:
|
||||
|
||||
/** Constructor for QgsSubstitutionListWidget.
|
||||
* @param parent parent widget
|
||||
*/
|
||||
QgsSubstitutionListWidget( QWidget* parent = nullptr );
|
||||
|
||||
/** Sets the list of substitutions to show in the widget.
|
||||
* @param substitutions substitution list
|
||||
* @see substitutions()
|
||||
*/
|
||||
void setSubstitutions( const QgsStringReplacementCollection& substitutions );
|
||||
|
||||
/** Returns the list of substitutions currently defined by the widget.
|
||||
* @see setSubstitutions()
|
||||
*/
|
||||
QgsStringReplacementCollection substitutions() const;
|
||||
|
||||
signals:
|
||||
|
||||
//! Emitted when the substitution definitions change.
|
||||
void substitutionsChanged( const QgsStringReplacementCollection& substitutions );
|
||||
|
||||
private slots:
|
||||
|
||||
void on_mButtonAdd_clicked();
|
||||
void on_mButtonRemove_clicked();
|
||||
void tableChanged();
|
||||
void on_mButtonExport_clicked();
|
||||
void on_mButtonImport_clicked();
|
||||
|
||||
private:
|
||||
|
||||
void addSubstitution( const QgsStringReplacement& substitution );
|
||||
|
||||
};
|
||||
|
||||
/** \class QgsSubstitutionListDialog
|
||||
* \ingroup app
|
||||
* A dialog which allows users to specify a list of substitutions to apply to a string, with
|
||||
* options for exporting and importing substitution lists.
|
||||
* \see QgsSubstitutionListWidget
|
||||
*/
|
||||
class APP_EXPORT QgsSubstitutionListDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY( QgsStringReplacementCollection substitutions READ substitutions WRITE setSubstitutions )
|
||||
|
||||
public:
|
||||
|
||||
/** Constructor for QgsSubstitutionListDialog.
|
||||
* @param parent parent widget
|
||||
*/
|
||||
QgsSubstitutionListDialog( QWidget* parent = nullptr );
|
||||
|
||||
/** Sets the list of substitutions to show in the dialog.
|
||||
* @param substitutions substitution list
|
||||
* @see substitutions()
|
||||
*/
|
||||
void setSubstitutions( const QgsStringReplacementCollection& substitutions );
|
||||
|
||||
/** Returns the list of substitutions currently defined by the dialog.
|
||||
* @see setSubstitutions()
|
||||
*/
|
||||
QgsStringReplacementCollection substitutions() const;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
QgsSubstitutionListWidget* mWidget;
|
||||
|
||||
};
|
||||
|
||||
#endif // QGSSUBSTITUTIONLISTWIDGET_H
|
@ -128,6 +128,7 @@ QgsPalLayerSettings::QgsPalLayerSettings()
|
||||
// font processing info
|
||||
mTextFontFound = true;
|
||||
mTextFontFamily = QApplication::font().family();
|
||||
useSubstitutions = false;
|
||||
|
||||
// text formatting
|
||||
wrapChar = "";
|
||||
@ -387,6 +388,8 @@ QgsPalLayerSettings& QgsPalLayerSettings::operator=( const QgsPalLayerSettings &
|
||||
// font processing info
|
||||
mTextFontFound = s.mTextFontFound;
|
||||
mTextFontFamily = s.mTextFontFamily;
|
||||
substitutions = s.substitutions;
|
||||
useSubstitutions = s.useSubstitutions;
|
||||
|
||||
// text formatting
|
||||
wrapChar = s.wrapChar;
|
||||
@ -847,7 +850,11 @@ void QgsPalLayerSettings::readFromLayer( QgsVectorLayer* layer )
|
||||
blendMode = QgsPainting::getCompositionMode(
|
||||
static_cast< QgsPainting::BlendMode >( layer->customProperty( "labeling/blendMode", QVariant( QgsPainting::BlendNormal ) ).toUInt() ) );
|
||||
previewBkgrdColor = QColor( layer->customProperty( "labeling/previewBkgrdColor", QVariant( "#ffffff" ) ).toString() );
|
||||
|
||||
QDomDocument doc( "substitutions" );
|
||||
doc.setContent( layer->customProperty( "labeling/substitutions" ).toString() );
|
||||
QDomElement replacementElem = doc.firstChildElement( "substitutions" );
|
||||
substitutions.readXml( replacementElem );
|
||||
useSubstitutions = layer->customProperty( "labeling/useSubstitutions" ).toBool();
|
||||
|
||||
// text formatting
|
||||
wrapChar = layer->customProperty( "labeling/wrapChar" ).toString();
|
||||
@ -1127,6 +1134,14 @@ void QgsPalLayerSettings::writeToLayer( QgsVectorLayer* layer )
|
||||
layer->setCustomProperty( "labeling/textTransp", textTransp );
|
||||
layer->setCustomProperty( "labeling/blendMode", QgsPainting::getBlendModeEnum( blendMode ) );
|
||||
layer->setCustomProperty( "labeling/previewBkgrdColor", previewBkgrdColor.name() );
|
||||
QDomDocument doc( "substitutions" );
|
||||
QDomElement replacementElem = doc.createElement( "substitutions" );
|
||||
substitutions.writeXml( replacementElem, doc );
|
||||
QString replacementProps;
|
||||
QTextStream stream( &replacementProps );
|
||||
replacementElem.save( stream, -1 );
|
||||
layer->setCustomProperty( "labeling/substitutions", replacementProps );
|
||||
layer->setCustomProperty( "labeling/useSubstitutions", useSubstitutions );
|
||||
|
||||
// text formatting
|
||||
layer->setCustomProperty( "labeling/wrapChar", wrapChar );
|
||||
@ -1298,7 +1313,8 @@ void QgsPalLayerSettings::readXml( QDomElement& elem )
|
||||
blendMode = QgsPainting::getCompositionMode(
|
||||
static_cast< QgsPainting::BlendMode >( textStyleElem.attribute( "blendMode", QString::number( QgsPainting::BlendNormal ) ).toUInt() ) );
|
||||
previewBkgrdColor = QColor( textStyleElem.attribute( "previewBkgrdColor", "#ffffff" ) );
|
||||
|
||||
substitutions.readXml( textStyleElem.firstChildElement( "substitutions" ) );
|
||||
useSubstitutions = textStyleElem.attribute( "useSubstitutions" ).toInt();
|
||||
|
||||
// text formatting
|
||||
QDomElement textFormatElem = elem.firstChildElement( "text-format" );
|
||||
@ -1564,6 +1580,10 @@ QDomElement QgsPalLayerSettings::writeXml( QDomDocument& doc )
|
||||
textStyleElem.setAttribute( "textTransp", textTransp );
|
||||
textStyleElem.setAttribute( "blendMode", QgsPainting::getBlendModeEnum( blendMode ) );
|
||||
textStyleElem.setAttribute( "previewBkgrdColor", previewBkgrdColor.name() );
|
||||
QDomElement replacementElem = doc.createElement( "substitutions" );
|
||||
substitutions.writeXml( replacementElem, doc );
|
||||
textStyleElem.appendChild( replacementElem );
|
||||
textStyleElem.setAttribute( "useSubstitutions", useSubstitutions );
|
||||
|
||||
// text formatting
|
||||
QDomElement textFormatElem = doc.createElement( "text-format" );
|
||||
@ -2314,6 +2334,12 @@ void QgsPalLayerSettings::registerFeature( QgsFeature& f, QgsRenderContext &cont
|
||||
labelText = v.isNull() ? "" : v.toString();
|
||||
}
|
||||
|
||||
// apply text replacements
|
||||
if ( useSubstitutions )
|
||||
{
|
||||
labelText = substitutions.process( labelText );
|
||||
}
|
||||
|
||||
// data defined format numbers?
|
||||
bool formatnum = formatNumbers;
|
||||
if ( dataDefinedEvaluate( QgsPalLayerSettings::NumFormat, exprVal, &context.expressionContext(), formatNumbers ) )
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "qgsfield.h"
|
||||
#include "qgspoint.h"
|
||||
#include "qgsmapunitscale.h"
|
||||
#include "qgsstringutils.h"
|
||||
|
||||
namespace pal
|
||||
{
|
||||
@ -480,6 +481,11 @@ class CORE_EXPORT QgsPalLayerSettings
|
||||
QPainter::CompositionMode blendMode;
|
||||
QColor previewBkgrdColor;
|
||||
|
||||
//! Substitution collection for automatic text substitution with labels
|
||||
QgsStringReplacementCollection substitutions;
|
||||
//! True if substitutions should be applied
|
||||
bool useSubstitutions;
|
||||
|
||||
//-- text formatting
|
||||
|
||||
QString wrapChar;
|
||||
|
@ -337,3 +337,89 @@ QString QgsStringUtils::insertLinks( const QString& string, bool *foundLinks )
|
||||
|
||||
return converted;
|
||||
}
|
||||
|
||||
QgsStringReplacement::QgsStringReplacement( const QString& match, const QString& replacement, bool caseSensitive, bool wholeWordOnly )
|
||||
: mMatch( match )
|
||||
, mReplacement( replacement )
|
||||
, mCaseSensitive( caseSensitive )
|
||||
, mWholeWordOnly( wholeWordOnly )
|
||||
{
|
||||
if ( mWholeWordOnly )
|
||||
mRx = QRegExp( QString( "\\b%1\\b" ).arg( mMatch ),
|
||||
mCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive );
|
||||
}
|
||||
|
||||
QString QgsStringReplacement::process( const QString& input ) const
|
||||
{
|
||||
QString result = input;
|
||||
if ( !mWholeWordOnly )
|
||||
{
|
||||
return result.replace( mMatch, mReplacement, mCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive );
|
||||
}
|
||||
else
|
||||
{
|
||||
return result.replace( mRx, mReplacement );
|
||||
}
|
||||
}
|
||||
|
||||
QgsStringMap QgsStringReplacement::properties() const
|
||||
{
|
||||
QgsStringMap map;
|
||||
map.insert( "match", mMatch );
|
||||
map.insert( "replace", mReplacement );
|
||||
map.insert( "caseSensitive", mCaseSensitive ? "1" : "0" );
|
||||
map.insert( "wholeWord", mWholeWordOnly ? "1" : "0" );
|
||||
return map;
|
||||
}
|
||||
|
||||
QgsStringReplacement QgsStringReplacement::fromProperties( const QgsStringMap& properties )
|
||||
{
|
||||
return QgsStringReplacement( properties.value( "match" ),
|
||||
properties.value( "replace" ),
|
||||
properties.value( "caseSensitive", "0" ) == "1",
|
||||
properties.value( "wholeWord", "0" ) == "1" );
|
||||
}
|
||||
|
||||
QString QgsStringReplacementCollection::process( const QString& input ) const
|
||||
{
|
||||
QString result = input;
|
||||
Q_FOREACH ( const QgsStringReplacement& r, mReplacements )
|
||||
{
|
||||
result = r.process( result );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void QgsStringReplacementCollection::writeXml( QDomElement& elem, QDomDocument& doc ) const
|
||||
{
|
||||
Q_FOREACH ( const QgsStringReplacement& r, mReplacements )
|
||||
{
|
||||
QgsStringMap props = r.properties();
|
||||
QDomElement propEl = doc.createElement( "replacement" );
|
||||
QgsStringMap::const_iterator it = props.constBegin();
|
||||
for ( ; it != props.constEnd(); ++it )
|
||||
{
|
||||
propEl.setAttribute( it.key(), it.value() );
|
||||
}
|
||||
elem.appendChild( propEl );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsStringReplacementCollection::readXml( const QDomElement& elem )
|
||||
{
|
||||
mReplacements.clear();
|
||||
QDomNodeList nodelist = elem.elementsByTagName( "replacement" );
|
||||
for ( int i = 0;i < nodelist.count(); i++ )
|
||||
{
|
||||
QDomElement replacementElem = nodelist.at( i ).toElement();
|
||||
QDomNamedNodeMap nodeMap = replacementElem.attributes();
|
||||
|
||||
QgsStringMap props;
|
||||
for ( int j = 0; j < nodeMap.count(); ++j )
|
||||
{
|
||||
props.insert( nodeMap.item( j ).nodeName(), nodeMap.item( j ).nodeValue() );
|
||||
}
|
||||
mReplacements << QgsStringReplacement::fromProperties( props );
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -14,10 +14,148 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include <QString>
|
||||
#include <QRegExp>
|
||||
#include <QList>
|
||||
#include <QDomDocument>
|
||||
#include "qgis.h"
|
||||
|
||||
#ifndef QGSSTRINGUTILS_H
|
||||
#define QGSSTRINGUTILS_H
|
||||
|
||||
|
||||
/** \ingroup core
|
||||
* \class QgsStringReplacement
|
||||
* \brief A representation of a single string replacement.
|
||||
* \note Added in version 3.0
|
||||
*/
|
||||
|
||||
class CORE_EXPORT QgsStringReplacement
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
/** Constructor for QgsStringReplacement.
|
||||
* @param match string to match
|
||||
* @param replacement string to replace match with
|
||||
* @param caseSensitive set to true for a case sensitive match
|
||||
* @param wholeWordOnly set to true to match complete words only, or false to allow partial word matches
|
||||
*/
|
||||
QgsStringReplacement( const QString& match,
|
||||
const QString& replacement,
|
||||
bool caseSensitive = false,
|
||||
bool wholeWordOnly = false );
|
||||
|
||||
//! Returns the string matched by this object
|
||||
QString match() const { return mMatch; }
|
||||
|
||||
//! Returns the string to replace matches with
|
||||
QString replacement() const { return mReplacement; }
|
||||
|
||||
//! Returns true if match is case sensitive
|
||||
bool caseSensitive() const { return mCaseSensitive; }
|
||||
|
||||
//! Returns true if match only applies to whole words, or false if partial word matches are permitted
|
||||
bool wholeWordOnly() const { return mWholeWordOnly; }
|
||||
|
||||
/** Processes a given input string, applying any valid replacements which should be made.
|
||||
* @param input input string
|
||||
* @returns input string with any matches replaced by replacement string
|
||||
*/
|
||||
QString process( const QString& input ) const;
|
||||
|
||||
bool operator==( const QgsStringReplacement& other )
|
||||
{
|
||||
return mMatch == other.mMatch
|
||||
&& mReplacement == other.mReplacement
|
||||
&& mCaseSensitive == other.mCaseSensitive
|
||||
&& mWholeWordOnly == other.mWholeWordOnly;
|
||||
}
|
||||
|
||||
/** Returns a map of the replacement properties.
|
||||
* @see fromProperties()
|
||||
*/
|
||||
QgsStringMap properties() const;
|
||||
|
||||
/** Creates a new QgsStringReplacement from an encoded properties map.
|
||||
* @see properties()
|
||||
*/
|
||||
static QgsStringReplacement fromProperties( const QgsStringMap& properties );
|
||||
|
||||
private:
|
||||
|
||||
QString mMatch;
|
||||
|
||||
QString mReplacement;
|
||||
|
||||
bool mCaseSensitive;
|
||||
|
||||
bool mWholeWordOnly;
|
||||
|
||||
QRegExp mRx;
|
||||
};
|
||||
|
||||
|
||||
/** \ingroup core
|
||||
* \class QgsStringReplacementCollection
|
||||
* \brief A collection of string replacements (specified using QgsStringReplacement objects).
|
||||
* \note Added in version 3.0
|
||||
*/
|
||||
|
||||
class CORE_EXPORT QgsStringReplacementCollection
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
/** Constructor for QgsStringReplacementCollection
|
||||
* @param replacements initial list of string replacements
|
||||
*/
|
||||
QgsStringReplacementCollection( const QList< QgsStringReplacement >& replacements = QList< QgsStringReplacement >() )
|
||||
: mReplacements( replacements )
|
||||
{}
|
||||
|
||||
/** Returns the list of string replacements in this collection.
|
||||
* @see setReplacements()
|
||||
*/
|
||||
QList< QgsStringReplacement > replacements() const { return mReplacements; }
|
||||
|
||||
/** Sets the list of string replacements in this collection.
|
||||
* @param replacements list of string replacements to apply. Replacements are applied in the
|
||||
* order they are specified here.
|
||||
* @see replacements()
|
||||
*/
|
||||
void setReplacements( const QList< QgsStringReplacement >& replacements )
|
||||
{
|
||||
mReplacements = replacements;
|
||||
}
|
||||
|
||||
/** Processes a given input string, applying any valid replacements which should be made
|
||||
* using QgsStringReplacement objects contained by this collection. Replacements
|
||||
* are made in order of the QgsStringReplacement objects contained in the collection.
|
||||
* @param input input string
|
||||
* @returns input string with any matches replaced by replacement string
|
||||
*/
|
||||
QString process( const QString& input ) const;
|
||||
|
||||
/** Writes the collection state to an XML element.
|
||||
* @param elem target DOM element
|
||||
* @param doc DOM document
|
||||
* @see readXml()
|
||||
*/
|
||||
void writeXml( QDomElement& elem, QDomDocument& doc ) const;
|
||||
|
||||
/** Reads the collection state from an XML element.
|
||||
* @param elem DOM element
|
||||
* @see writeXml()
|
||||
*/
|
||||
void readXml( const QDomElement& elem );
|
||||
|
||||
private:
|
||||
|
||||
QList< QgsStringReplacement > mReplacements;
|
||||
|
||||
|
||||
};
|
||||
|
||||
/** \ingroup core
|
||||
* \class QgsStringUtils
|
||||
* \brief Utility functions for working with strings.
|
||||
|
@ -118,6 +118,8 @@ class CORE_EXPORT QgsVectorLayerLabelProvider : public QgsAbstractLabelProvider
|
||||
|
||||
//! List of generated
|
||||
QList<QgsLabelFeature*> mLabels;
|
||||
|
||||
friend class TestQgsLabelingEngine;
|
||||
};
|
||||
|
||||
#endif // QGSVECTORLAYERLABELPROVIDER_H
|
||||
|
@ -618,7 +618,7 @@
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="mLabelStackedWidget">
|
||||
<property name="currentIndex">
|
||||
<number>5</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="mLabelPage_Text">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
@ -646,9 +646,9 @@
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<y>-78</y>
|
||||
<width>448</width>
|
||||
<height>411</height>
|
||||
<height>442</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
@ -691,6 +691,91 @@
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="3" column="2">
|
||||
<widget class="QgsDataDefinedButton" name="mFontStyleDDBtn">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="mFontStyleLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Style</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QgsUnitSelectionWidget" name="mFontSizeUnitWidget" native="true"/>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="mFontLabel_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Text</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="mFontTranspLabel">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Transparency</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QgsColorButton" name="btnTextColor">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>120</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>120</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="0">
|
||||
<widget class="QLabel" name="labelBlendMode">
|
||||
<property name="text">
|
||||
<string>Blend mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="2">
|
||||
<widget class="QgsDataDefinedButton" name="mFontColorDDBtn">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1" colspan="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_14">
|
||||
<item>
|
||||
@ -743,73 +828,13 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QgsDoubleSpinBox" name="mFontSizeSpinBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>999999999.000000000000000</double>
|
||||
</property>
|
||||
<property name="showClearButton" stdset="0">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<item row="12" column="1">
|
||||
<widget class="QgsBlendModeComboBox" name="comboBlendMode"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="mFontStyleLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<item row="9" column="2">
|
||||
<widget class="QgsDataDefinedButton" name="mFontCaseDDBtn">
|
||||
<property name="text">
|
||||
<string>Style</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<widget class="QComboBox" name="mFontCapitalsComboBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Capitalization style of text</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="mFontTranspLabel">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Transparency</string>
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -857,38 +882,36 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="2">
|
||||
<widget class="QgsDataDefinedButton" name="mFontCaseDDBtn">
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="mFontCapitalsLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Type case</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="2">
|
||||
<widget class="QgsDataDefinedButton" name="mFontBlendModeDDBtn">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="2">
|
||||
<widget class="QgsDataDefinedButton" name="mFontUnitsDDBtn">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="mFontSizeLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="2">
|
||||
<widget class="QgsDataDefinedButton" name="mFontColorDDBtn">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QgsDataDefinedButton" name="mFontDDBtn">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="2">
|
||||
<widget class="QgsDataDefinedButton" name="mFontTranspDDBtn">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
<string>Size</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -960,46 +983,66 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="mFontCapitalsLabel">
|
||||
<item row="2" column="1">
|
||||
<widget class="QFrame" name="mFontFamilyFrame">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="mFontMissingLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">color: #990000;
|
||||
font-style: italic;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Font is missing.</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QgsDoubleSpinBox" name="mFontSizeSpinBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Type case</string>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="2">
|
||||
<widget class="QgsDataDefinedButton" name="mFontBlendModeDDBtn">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
<property name="decimals">
|
||||
<number>4</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="mFontColorLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
<property name="maximum">
|
||||
<double>999999999.000000000000000</double>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Color</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<widget class="QgsDataDefinedButton" name="mFontSizeDDBtn">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
<property name="showClearButton" stdset="0">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -1010,86 +1053,19 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QgsColorButton" name="btnTextColor">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>120</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>120</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="0">
|
||||
<widget class="QLabel" name="labelBlendMode">
|
||||
<item row="6" column="2">
|
||||
<widget class="QgsDataDefinedButton" name="mFontUnitsDDBtn">
|
||||
<property name="text">
|
||||
<string>Blend mode</string>
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="1" colspan="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_15">
|
||||
<item>
|
||||
<widget class="QLabel" name="mFontWordSpacingLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>word</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QgsDoubleSpinBox" name="mFontWordSpacingSpinBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Space in pixels or map units, relative to size unit choice</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>-1000.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>999999999.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="showClearButton" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QgsDataDefinedButton" name="mFontWordSpacingDDBtn">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<item row="1" column="2">
|
||||
<widget class="QgsDataDefinedButton" name="mFontDDBtn">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1" colspan="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_13">
|
||||
@ -1273,66 +1249,64 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="12" column="1">
|
||||
<widget class="QgsBlendModeComboBox" name="comboBlendMode"/>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QgsDataDefinedButton" name="mFontStyleDDBtn">
|
||||
<item row="8" column="2">
|
||||
<widget class="QgsDataDefinedButton" name="mFontTranspDDBtn">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="mFontSizeLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Size</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QFrame" name="mFontFamilyFrame">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="mFontMissingLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">color: #990000;
|
||||
font-style: italic;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Font is missing.</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<item row="11" column="1" colspan="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_15">
|
||||
<item>
|
||||
<widget class="QLabel" name="mFontWordSpacingLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>word</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QgsDoubleSpinBox" name="mFontWordSpacingSpinBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Space in pixels or map units, relative to size unit choice</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>-1000.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>999999999.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
<property name="showClearButton" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QgsDataDefinedButton" name="mFontWordSpacingDDBtn">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QFontComboBox" name="mFontFamilyCmbBx">
|
||||
@ -1341,22 +1315,71 @@ font-style: italic;</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QgsUnitSelectionWidget" name="mFontSizeUnitWidget" native="true"/>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="mFontLabel_2">
|
||||
<item row="9" column="1">
|
||||
<widget class="QComboBox" name="mFontCapitalsComboBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Capitalization style of text</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="mFontColorLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Text</string>
|
||||
<string>Color</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<widget class="QgsDataDefinedButton" name="mFontSizeDDBtn">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="mCheckBoxSubstituteText">
|
||||
<property name="toolTip">
|
||||
<string>If enabled, the label text will automatically be modified using a preset list of substitutes</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Apply label text substitutes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="2">
|
||||
<widget class="QToolButton" name="mToolButtonConfigureSubstitutes">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Configure substitutes</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -5389,7 +5412,7 @@ font-style: italic;</string>
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>448</width>
|
||||
<width>429</width>
|
||||
<height>799</height>
|
||||
</rect>
|
||||
</property>
|
||||
|
134
src/ui/qgssubstitutionlistwidgetbase.ui
Normal file
134
src/ui/qgssubstitutionlistwidgetbase.ui
Normal file
@ -0,0 +1,134 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>QgsSubstitutionListWidgetBase</class>
|
||||
<widget class="QgsPanelWidget" name="QgsSubstitutionListWidgetBase">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>291</width>
|
||||
<height>416</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTableWidget" name="mTableSubstitutions">
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Text</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Substitution</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Case Sensitive</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Whole Word</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>If checked, only whole word matches are replaced</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QToolButton" name="mButtonAdd">
|
||||
<property name="text">
|
||||
<string>...</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="QToolButton" name="mButtonRemove">
|
||||
<property name="text">
|
||||
<string>...</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>
|
||||
<widget class="QToolButton" name="mButtonImport">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../images/images.qrc">
|
||||
<normaloff>:/images/themes/default/mActionFileOpen.svg</normaloff>:/images/themes/default/mActionFileOpen.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="mButtonExport">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../images/images.qrc">
|
||||
<normaloff>:/images/themes/default/mActionFileSave.svg</normaloff>:/images/themes/default/mActionFileSave.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>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>QgsPanelWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>qgspanelwidget.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../../images/images.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
@ -43,6 +43,7 @@ class TestQgsLabelingEngine : public QObject
|
||||
void testRuleBased();
|
||||
void zOrder(); //test that labels are stacked correctly
|
||||
void testEncodeDecodePositionOrder();
|
||||
void testSubstitutions();
|
||||
|
||||
private:
|
||||
QgsVectorLayer* vl;
|
||||
@ -413,6 +414,46 @@ void TestQgsLabelingEngine::testEncodeDecodePositionOrder()
|
||||
QCOMPARE( decoded, expected );
|
||||
}
|
||||
|
||||
void TestQgsLabelingEngine::testSubstitutions()
|
||||
{
|
||||
QgsPalLayerSettings settings;
|
||||
settings.useSubstitutions = false;
|
||||
QgsStringReplacementCollection collection( QList< QgsStringReplacement >() << QgsStringReplacement( "aa", "bb" ) );
|
||||
settings.substitutions = collection;
|
||||
settings.fieldName = QString( "'aa label'" );
|
||||
settings.isExpression = true;
|
||||
|
||||
QgsVectorLayerLabelProvider* provider = new QgsVectorLayerLabelProvider( vl, "test", true, &settings );
|
||||
QgsFeature f( vl->fields(), 1 );
|
||||
f.setGeometry( QgsGeometry::fromPoint( QgsPoint( 1, 2 ) ) );
|
||||
|
||||
// make a fake render context
|
||||
QSize size( 640, 480 );
|
||||
QgsMapSettings mapSettings;
|
||||
mapSettings.setOutputSize( size );
|
||||
mapSettings.setExtent( vl->extent() );
|
||||
mapSettings.setLayers( QStringList() << vl->id() );
|
||||
mapSettings.setOutputDpi( 96 );
|
||||
QgsRenderContext context = QgsRenderContext::fromMapSettings( mapSettings );
|
||||
QStringList attributes;
|
||||
QgsLabelingEngine engine;
|
||||
engine.setMapSettings( mapSettings );
|
||||
engine.addProvider( provider );
|
||||
provider->prepare( context, attributes );
|
||||
|
||||
provider->registerFeature( f, context );
|
||||
QCOMPARE( provider->mLabels.at( 0 )->labelText(), QString( "aa label" ) );
|
||||
|
||||
//with substitution
|
||||
settings.useSubstitutions = true;
|
||||
QgsVectorLayerLabelProvider* provider2 = new QgsVectorLayerLabelProvider( vl, "test2", true, &settings );
|
||||
engine.addProvider( provider2 );
|
||||
provider2->prepare( context, attributes );
|
||||
|
||||
provider2->registerFeature( f, context );
|
||||
QCOMPARE( provider2->mLabels.at( 0 )->labelText(), QString( "bb label" ) );
|
||||
}
|
||||
|
||||
bool TestQgsLabelingEngine::imageCheck( const QString& testName, QImage &image, int mismatchCount )
|
||||
{
|
||||
//draw background
|
||||
|
@ -92,6 +92,7 @@ ADD_PYTHON_TEST(PyQgsSymbolLayerCreateSld test_qgssymbollayer_createsld.py)
|
||||
ADD_PYTHON_TEST(PyQgsArrowSymbolLayer test_qgsarrowsymbollayer.py)
|
||||
ADD_PYTHON_TEST(PyQgsSymbolExpressionVariables test_qgssymbolexpressionvariables.py)
|
||||
ADD_PYTHON_TEST(PyQgsSyntacticSugar test_syntactic_sugar.py)
|
||||
ADD_PYTHON_TEST(PyQgsStringUtils test_qgsstringutils.py)
|
||||
ADD_PYTHON_TEST(PyQgsSymbol test_qgssymbol.py)
|
||||
ADD_PYTHON_TEST(PyQgsTreeWidgetItem test_qgstreewidgetitem.py)
|
||||
ADD_PYTHON_TEST(PyQgsUnitTypes test_qgsunittypes.py)
|
||||
|
137
tests/src/python/test_qgsstringutils.py
Normal file
137
tests/src/python/test_qgsstringutils.py
Normal file
@ -0,0 +1,137 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""QGIS Unit tests for QgsStringUtils.
|
||||
|
||||
.. note:: 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.
|
||||
"""
|
||||
__author__ = 'Nyall Dawson'
|
||||
__date__ = '30/08/2016'
|
||||
__copyright__ = 'Copyright 2016, The QGIS Project'
|
||||
# This will get replaced with a git SHA1 when you do a git archive
|
||||
__revision__ = '$Format:%H$'
|
||||
|
||||
import qgis # NOQA
|
||||
|
||||
from qgis.PyQt.QtXml import (QDomDocument, QDomElement)
|
||||
|
||||
from qgis.core import (QgsStringUtils,
|
||||
QgsStringReplacement,
|
||||
QgsStringReplacementCollection
|
||||
)
|
||||
from qgis.testing import unittest
|
||||
|
||||
|
||||
class PyQgsStringReplacement(unittest.TestCase):
|
||||
|
||||
def testBasic(self):
|
||||
""" basic tests for QgsStringReplacement"""
|
||||
r = QgsStringReplacement('match', 'replace')
|
||||
self.assertEqual(r.match(), 'match')
|
||||
self.assertEqual(r.replacement(), 'replace')
|
||||
|
||||
r = QgsStringReplacement('match', 'replace', True, True)
|
||||
self.assertTrue(r.wholeWordOnly())
|
||||
self.assertTrue(r.caseSensitive())
|
||||
|
||||
def testReplace(self):
|
||||
""" test applying replacements"""
|
||||
|
||||
# case insensitive
|
||||
r = QgsStringReplacement('match', 'replace', False, False)
|
||||
self.assertEqual(r.process('one MaTch only'), 'one replace only')
|
||||
self.assertEqual(r.process('more then one MaTch here match two'), 'more then one replace here replace two')
|
||||
self.assertEqual(r.process('match start and end MaTch'), 'replace start and end replace')
|
||||
self.assertEqual(r.process('no hits'), 'no hits')
|
||||
self.assertEqual(r.process('some exmatches here'), 'some exreplacees here')
|
||||
self.assertEqual(r.process(''), '')
|
||||
|
||||
# case sensitive
|
||||
r = QgsStringReplacement('match', 'replace', True, False)
|
||||
self.assertEqual(r.process('one MaTch only'), 'one MaTch only')
|
||||
self.assertEqual(r.process('one match only'), 'one replace only')
|
||||
|
||||
# whole word only, case insensitive
|
||||
r = QgsStringReplacement('match', 'replace', False, True)
|
||||
self.assertEqual(r.process('some exmatches here'), 'some exmatches here')
|
||||
self.assertEqual(r.process('some match here'), 'some replace here')
|
||||
self.assertEqual(r.process('some exmatches MaTch here'), 'some exmatches replace here')
|
||||
self.assertEqual(r.process('some match maTCh here'), 'some replace replace here')
|
||||
self.assertEqual(r.process('some -match. here'), 'some -replace. here')
|
||||
self.assertEqual(r.process('match here'), 'replace here')
|
||||
self.assertEqual(r.process('some match'), 'some replace')
|
||||
|
||||
# whole word only, case sensitive
|
||||
r = QgsStringReplacement('match', 'replace', True, True)
|
||||
self.assertEqual(r.process('some exmatches here'), 'some exmatches here')
|
||||
self.assertEqual(r.process('some match here'), 'some replace here')
|
||||
self.assertEqual(r.process('some exmatches MaTch here'), 'some exmatches MaTch here')
|
||||
self.assertEqual(r.process('some match maTCh here'), 'some replace maTCh here')
|
||||
|
||||
def testEquality(self):
|
||||
""" test equality operator"""
|
||||
r1 = QgsStringReplacement('a', 'b', True, True)
|
||||
r2 = QgsStringReplacement('a', 'b', True, True)
|
||||
self.assertEqual(r1, r2)
|
||||
r2 = QgsStringReplacement('c', 'b')
|
||||
self.assertNotEqual(r1, r2)
|
||||
r2 = QgsStringReplacement('a', 'c')
|
||||
self.assertNotEqual(r1, r2)
|
||||
r2 = QgsStringReplacement('a', 'b', False, True)
|
||||
self.assertNotEqual(r1, r2)
|
||||
r2 = QgsStringReplacement('c', 'b', True, False)
|
||||
self.assertNotEqual(r1, r2)
|
||||
|
||||
def testSaveRestore(self):
|
||||
""" test saving/restoring replacement to map"""
|
||||
r1 = QgsStringReplacement('a', 'b', True, True)
|
||||
props = r1.properties()
|
||||
r2 = QgsStringReplacement.fromProperties(props)
|
||||
self.assertEqual(r1, r2)
|
||||
r1 = QgsStringReplacement('a', 'b', False, False)
|
||||
props = r1.properties()
|
||||
r2 = QgsStringReplacement.fromProperties(props)
|
||||
self.assertEqual(r1, r2)
|
||||
|
||||
|
||||
class PyQgsStringReplacementCollection(unittest.TestCase):
|
||||
|
||||
def testBasic(self):
|
||||
""" basic QgsStringReplacementCollection tests"""
|
||||
list = [QgsStringReplacement('aa', '11'),
|
||||
QgsStringReplacement('bb', '22')]
|
||||
c = QgsStringReplacementCollection(list)
|
||||
self.assertEqual(c.replacements(), list)
|
||||
|
||||
def testReplacements(self):
|
||||
""" test replacing using collection of replacements """
|
||||
c = QgsStringReplacementCollection()
|
||||
c.setReplacements([QgsStringReplacement('aa', '11'),
|
||||
QgsStringReplacement('bb', '22')])
|
||||
self.assertEqual(c.process('here aa bb is aa string bb'), 'here 11 22 is 11 string 22')
|
||||
self.assertEqual(c.process('no matches'), 'no matches')
|
||||
self.assertEqual(c.process(''), '')
|
||||
|
||||
# test replacements are done in order
|
||||
c.setReplacements([QgsStringReplacement('aa', '11'),
|
||||
QgsStringReplacement('11', '22')])
|
||||
self.assertEqual(c.process('string aa'), 'string 22')
|
||||
# no replacements
|
||||
c.setReplacements([])
|
||||
self.assertEqual(c.process('string aa'), 'string aa')
|
||||
|
||||
def testSaveRestore(self):
|
||||
""" test saving and restoring collections """
|
||||
c = QgsStringReplacementCollection([QgsStringReplacement('aa', '11', False, False),
|
||||
QgsStringReplacement('bb', '22', True, True)])
|
||||
doc = QDomDocument("testdoc")
|
||||
elem = doc.createElement("replacements")
|
||||
c.writeXml(elem, doc)
|
||||
c2 = QgsStringReplacementCollection()
|
||||
c2.readXml(elem)
|
||||
self.assertEqual(c2.replacements(), c.replacements())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
Loading…
x
Reference in New Issue
Block a user