Allow pushing more contextual information to QgsFontButton/QgsTextFormatWidget

e.g. follow the same approach as symbology and allow pushing message
bars, map canvases, and expression contexts to the widgets
This commit is contained in:
Nyall Dawson 2019-07-17 17:48:03 +10:00
parent a57d04fb7f
commit a83953599a
7 changed files with 222 additions and 18 deletions

View File

@ -94,6 +94,25 @@ Sets a map ``canvas`` to associate with the widget. This allows the
widget to fetch current settings from the map canvas, such as current scale.
.. seealso:: :py:func:`mapCanvas`
%End
void setMessageBar( QgsMessageBar *bar );
%Docstring
Sets the message ``bar`` associated with the widget. This allows the widget to push feedback messages
to the appropriate message bar.
.. seealso:: :py:func:`messageBar`
.. versionadded:: 3.10
%End
QgsMessageBar *messageBar() const;
%Docstring
Returns the message bar associated with the widget.
.. seealso:: :py:func:`setMessageBar`
.. versionadded:: 3.10
%End
QgsTextFormat textFormat() const;
@ -112,6 +131,33 @@ This is only used when mode() is ModeQFont.
.. seealso:: :py:func:`setCurrentFont`
%End
QgsVectorLayer *layer() const;
%Docstring
Returns the layer associated with the widget.
.. seealso:: :py:func:`setLayer`
.. versionadded:: 3.10
%End
void setLayer( QgsVectorLayer *layer );
%Docstring
Sets a ``layer`` to associate with the widget. This allows the
widget to setup layer related settings within the text settings dialog,
such as correctly populating data defined override buttons.
.. seealso:: :py:func:`layer`
.. versionadded:: 3.10
%End
void registerExpressionContextGenerator( QgsExpressionContextGenerator *generator );
%Docstring
Register an expression context generator class that will be used to retrieve
an expression context for the button when required.
.. versionadded:: 3.10
%End
public slots:

View File

@ -34,13 +34,15 @@ of Labeling.
%End
public:
QgsTextFormatWidget( const QgsTextFormat &format = QgsTextFormat(), QgsMapCanvas *mapCanvas = 0, QWidget *parent /TransferThis/ = 0 );
QgsTextFormatWidget( const QgsTextFormat &format = QgsTextFormat(), QgsMapCanvas *mapCanvas = 0, QWidget *parent /TransferThis/ = 0,
QgsVectorLayer *layer = 0 );
%Docstring
Constructor for QgsTextFormatWidget.
:param format: initial formatting settings to show in widget
:param mapCanvas: associated map canvas
:param parent: parent widget
:param layer: associated vector layer
%End
~QgsTextFormatWidget();
@ -99,7 +101,7 @@ Emitted when the text format defined by the widget changes
Labeling,
};
QgsTextFormatWidget( QgsMapCanvas *mapCanvas, QWidget *parent /TransferThis/, Mode mode );
QgsTextFormatWidget( QgsMapCanvas *mapCanvas, QWidget *parent /TransferThis/, Mode mode, QgsVectorLayer *layer = 0 );
%Docstring
Constructor for QgsTextFormatWidget.
@ -187,7 +189,7 @@ a :py:class:`QgsTextFormat`, including shadow, background and buffer.
%End
public:
QgsTextFormatDialog( const QgsTextFormat &format, QgsMapCanvas *mapCanvas = 0, QWidget *parent /TransferThis/ = 0, Qt::WindowFlags fl = QgsGuiUtils::ModalDialogFlags );
QgsTextFormatDialog( const QgsTextFormat &format, QgsMapCanvas *mapCanvas = 0, QWidget *parent /TransferThis/ = 0, Qt::WindowFlags fl = QgsGuiUtils::ModalDialogFlags, QgsVectorLayer *layer = 0 );
%Docstring
Constructor for QgsTextFormatDialog.
@ -195,11 +197,21 @@ Constructor for QgsTextFormatDialog.
:param mapCanvas: optional associated map canvas
:param parent: parent widget
:param fl: window flags for dialog
:param layer: associated vector layer
%End
QgsTextFormat format() const;
%Docstring
Returns the current formatting settings defined by the widget.
%End
void setContext( const QgsSymbolWidgetContext &context );
%Docstring
Sets the ``context`` in which the widget is shown, e.g., the associated map canvas and expression contexts.
.. seealso:: :py:func:`context`
.. versionadded:: 3.10
%End
QDialogButtonBox *buttonBox() const;
@ -229,18 +241,28 @@ a :py:class:`QgsTextFormat`, including shadow, background and buffer.
%End
public:
QgsTextFormatPanelWidget( const QgsTextFormat &format, QgsMapCanvas *mapCanvas = 0, QWidget *parent /TransferThis/ = 0 );
QgsTextFormatPanelWidget( const QgsTextFormat &format, QgsMapCanvas *mapCanvas = 0, QWidget *parent /TransferThis/ = 0, QgsVectorLayer *layer = 0 );
%Docstring
Constructor for QgsTextFormatPanelWidget.
:param format: initial format settings to show in dialog
:param mapCanvas: optional associated map canvas
:param parent: parent widget
:param layer: associated layer
%End
QgsTextFormat format() const;
%Docstring
Returns the current formatting settings defined by the widget.
%End
void setContext( const QgsSymbolWidgetContext &context );
%Docstring
Sets the ``context`` in which the widget is shown, e.g., the associated map canvas and expression contexts.
.. seealso:: :py:func:`context`
.. versionadded:: 3.10
%End
virtual void setDockMode( bool dockMode );

View File

@ -26,6 +26,8 @@
#include "qgsmenuheader.h"
#include "qgsfontutils.h"
#include "qgsapplication.h"
#include "qgsexpressioncontextutils.h"
#include "qgsvectorlayer.h"
#include <QMenu>
#include <QClipboard>
#include <QDrag>
@ -71,19 +73,34 @@ void QgsFontButton::showSettingsDialog()
{
case ModeTextRenderer:
{
QgsExpressionContext context;
if ( mExpressionContextGenerator )
context = mExpressionContextGenerator->createExpressionContext();
else
{
context.appendScopes( QgsExpressionContextUtils::globalProjectLayerScopes( mLayer.data() ) );
}
QgsSymbolWidgetContext symbolContext;
symbolContext.setExpressionContext( &context );
symbolContext.setMapCanvas( mMapCanvas );
symbolContext.setMessageBar( mMessageBar );
QgsPanelWidget *panel = QgsPanelWidget::findParentPanel( this );
if ( panel && panel->dockMode() )
{
QgsTextFormatPanelWidget *formatWidget = new QgsTextFormatPanelWidget( mFormat, mMapCanvas, this );
QgsTextFormatPanelWidget *formatWidget = new QgsTextFormatPanelWidget( mFormat, mMapCanvas, this, mLayer.data() );
formatWidget->setPanelTitle( mDialogTitle );
formatWidget->setContext( symbolContext );
connect( formatWidget, &QgsTextFormatPanelWidget::widgetChanged, this, [ this, formatWidget ] { this->setTextFormat( formatWidget->format() ); } );
panel->openPanel( formatWidget );
return;
}
QgsTextFormatDialog dialog( mFormat, mMapCanvas, this );
QgsTextFormatDialog dialog( mFormat, mMapCanvas, this, QgsGuiUtils::ModalDialogFlags, mLayer.data() );
dialog.setWindowTitle( mDialogTitle );
dialog.setContext( symbolContext );
if ( dialog.exec() )
{
setTextFormat( dialog.format() );
@ -120,6 +137,16 @@ void QgsFontButton::setMapCanvas( QgsMapCanvas *mapCanvas )
mMapCanvas = mapCanvas;
}
void QgsFontButton::setMessageBar( QgsMessageBar *bar )
{
mMessageBar = bar;
}
QgsMessageBar *QgsFontButton::messageBar() const
{
return mMessageBar;
}
void QgsFontButton::setTextFormat( const QgsTextFormat &format )
{
mFormat = format;
@ -692,6 +719,21 @@ QFont QgsFontButton::currentFont() const
return mFont;
}
QgsVectorLayer *QgsFontButton::layer() const
{
return mLayer;
}
void QgsFontButton::setLayer( QgsVectorLayer *layer )
{
mLayer = layer;
}
void QgsFontButton::registerExpressionContextGenerator( QgsExpressionContextGenerator *generator )
{
mExpressionContextGenerator = generator;
}
void QgsFontButton::setCurrentFont( const QFont &font )
{
mFont = font;

View File

@ -21,7 +21,9 @@
#include <QToolButton>
class QgsExpressionContextGenerator;
class QgsMapCanvas;
class QgsMessageBar;
/**
* \ingroup gui
@ -109,6 +111,21 @@ class GUI_EXPORT QgsFontButton : public QToolButton
*/
void setMapCanvas( QgsMapCanvas *canvas );
/**
* Sets the message \a bar associated with the widget. This allows the widget to push feedback messages
* to the appropriate message bar.
* \see messageBar()
* \since QGIS 3.10
*/
void setMessageBar( QgsMessageBar *bar );
/**
* Returns the message bar associated with the widget.
* \see setMessageBar()
* \since QGIS 3.10
*/
QgsMessageBar *messageBar() const;
/**
* Returns the current text formatting set by the widget.
* This is only used when mode() is ModeTextRenderer.
@ -123,6 +140,28 @@ class GUI_EXPORT QgsFontButton : public QToolButton
*/
QFont currentFont() const;
/**
* Returns the layer associated with the widget.
* \see setLayer()
* \since QGIS 3.10
*/
QgsVectorLayer *layer() const;
/**
* Sets a \a layer to associate with the widget. This allows the
* widget to setup layer related settings within the text settings dialog,
* such as correctly populating data defined override buttons.
* \see layer()
* \since QGIS 3.10
*/
void setLayer( QgsVectorLayer *layer );
/**
* Register an expression context generator class that will be used to retrieve
* an expression context for the button when required.
* \since QGIS 3.10
*/
void registerExpressionContextGenerator( QgsExpressionContextGenerator *generator );
public slots:
@ -227,13 +266,18 @@ class GUI_EXPORT QgsFontButton : public QToolButton
QFont mFont;
QgsMapCanvas *mMapCanvas = nullptr;
QgsMessageBar *mMessageBar = nullptr;
QPoint mDragStartPosition;
QMenu *mMenu = nullptr;
QPointer< QgsVectorLayer > mLayer;
QSize mIconSize;
QgsExpressionContextGenerator *mExpressionContextGenerator = nullptr;
/**
* Attempts to parse \a mimeData as a text format.
* \returns TRUE if mime data could be intrepreted as a format

View File

@ -135,8 +135,7 @@ void QgsLabelingGui::updateCalloutWidget( QgsCallout *callout )
}
QgsLabelingGui::QgsLabelingGui( QgsVectorLayer *layer, QgsMapCanvas *mapCanvas, const QgsPalLayerSettings &layerSettings, QWidget *parent, QgsWkbTypes::GeometryType geomType )
: QgsTextFormatWidget( mapCanvas, parent, QgsTextFormatWidget::Labeling )
, mLayer( layer )
: QgsTextFormatWidget( mapCanvas, parent, QgsTextFormatWidget::Labeling, layer )
, mGeomType( geomType )
, mSettings( layerSettings )
, mMode( NoLabels )

View File

@ -31,22 +31,25 @@
#include "qgsstylesavedialog.h"
#include "qgsexpressioncontextutils.h"
#include "qgsgui.h"
#include "qgsvectorlayer.h"
#include <QButtonGroup>
#include <QMessageBox>
QgsTextFormatWidget::QgsTextFormatWidget( const QgsTextFormat &format, QgsMapCanvas *mapCanvas, QWidget *parent )
QgsTextFormatWidget::QgsTextFormatWidget( const QgsTextFormat &format, QgsMapCanvas *mapCanvas, QWidget *parent, QgsVectorLayer *layer )
: QWidget( parent )
, mMapCanvas( mapCanvas )
, mLayer( layer )
{
initWidget();
setWidgetMode( Text );
updateWidgetForFormat( format );
}
QgsTextFormatWidget::QgsTextFormatWidget( QgsMapCanvas *mapCanvas, QWidget *parent, Mode mode )
QgsTextFormatWidget::QgsTextFormatWidget( QgsMapCanvas *mapCanvas, QWidget *parent, Mode mode, QgsVectorLayer *layer )
: QWidget( parent )
, mMapCanvas( mapCanvas )
, mLayer( layer )
, mWidgetMode( mode )
{
initWidget();
@ -941,6 +944,14 @@ void QgsTextFormatWidget::optionsStackedWidget_CurrentChanged( int indx )
void QgsTextFormatWidget::setContext( const QgsSymbolWidgetContext &context )
{
mContext = context;
if ( mContext.expressionContext() )
{
mPreviewExpressionContext = *mContext.expressionContext();
if ( mLayer )
mPreviewExpressionContext.appendScope( QgsExpressionContextUtils::layerScope( mLayer ) );
}
const auto symbolButtonWidgets = findChildren<QgsSymbolButton *>();
for ( QgsSymbolButton *symbolWidget : symbolButtonWidgets )
{
@ -1660,6 +1671,9 @@ void QgsTextFormatWidget::enableDataDefinedAlignment( bool enable )
QgsExpressionContext QgsTextFormatWidget::createExpressionContext() const
{
if ( mContext.expressionContext() )
return *mContext.expressionContext();
QgsExpressionContext expContext;
expContext << QgsExpressionContextUtils::globalScope()
<< QgsExpressionContextUtils::projectScope( QgsProject::instance() )
@ -1667,6 +1681,12 @@ QgsExpressionContext QgsTextFormatWidget::createExpressionContext() const
if ( mMapCanvas )
expContext << QgsExpressionContextUtils::mapSettingsScope( mMapCanvas->mapSettings() );
if ( mLayer )
expContext << QgsExpressionContextUtils::layerScope( mLayer );
//TODO - show actual value
expContext.setOriginalValueVariable( QVariant() );
return expContext;
}
@ -1675,12 +1695,12 @@ QgsExpressionContext QgsTextFormatWidget::createExpressionContext() const
// QgsTextFormatDialog
//
QgsTextFormatDialog::QgsTextFormatDialog( const QgsTextFormat &format, QgsMapCanvas *mapCanvas, QWidget *parent, Qt::WindowFlags fl )
QgsTextFormatDialog::QgsTextFormatDialog( const QgsTextFormat &format, QgsMapCanvas *mapCanvas, QWidget *parent, Qt::WindowFlags fl, QgsVectorLayer *layer )
: QDialog( parent, fl )
{
setWindowTitle( tr( "Text Settings" ) );
mFormatWidget = new QgsTextFormatWidget( format, mapCanvas, this );
mFormatWidget = new QgsTextFormatWidget( format, mapCanvas, this, layer );
mFormatWidget->layout()->setContentsMargins( 0, 0, 0, 0 );
QVBoxLayout *layout = new QVBoxLayout( this );
@ -1701,13 +1721,18 @@ QgsTextFormat QgsTextFormatDialog::format() const
return mFormatWidget->format();
}
void QgsTextFormatDialog::setContext( const QgsSymbolWidgetContext &context )
{
mFormatWidget->setContext( context );
}
QDialogButtonBox *QgsTextFormatDialog::buttonBox() const
{
return mButtonBox;
}
QgsTextFormatPanelWidget::QgsTextFormatPanelWidget( const QgsTextFormat &format, QgsMapCanvas *mapCanvas, QWidget *parent )
: QgsPanelWidgetWrapper( new QgsTextFormatWidget( format, mapCanvas ), parent )
QgsTextFormatPanelWidget::QgsTextFormatPanelWidget( const QgsTextFormat &format, QgsMapCanvas *mapCanvas, QWidget *parent, QgsVectorLayer *layer )
: QgsPanelWidgetWrapper( new QgsTextFormatWidget( format, mapCanvas, nullptr, layer ), parent )
{
mFormatWidget = qobject_cast< QgsTextFormatWidget * >( widget() );
connect( mFormatWidget, &QgsTextFormatWidget::widgetChanged, this, &QgsPanelWidget::widgetChanged );
@ -1718,6 +1743,11 @@ QgsTextFormat QgsTextFormatPanelWidget::format() const
return mFormatWidget->format();
}
void QgsTextFormatPanelWidget::setContext( const QgsSymbolWidgetContext &context )
{
mFormatWidget->setContext( context );
}
void QgsTextFormatPanelWidget::setDockMode( bool dockMode )
{
mFormatWidget->setDockMode( dockMode );

View File

@ -59,8 +59,10 @@ class GUI_EXPORT QgsTextFormatWidget : public QWidget, public QgsExpressionConte
* \param format initial formatting settings to show in widget
* \param mapCanvas associated map canvas
* \param parent parent widget
* \param layer associated vector layer
*/
QgsTextFormatWidget( const QgsTextFormat &format = QgsTextFormat(), QgsMapCanvas *mapCanvas = nullptr, QWidget *parent SIP_TRANSFERTHIS = nullptr );
QgsTextFormatWidget( const QgsTextFormat &format = QgsTextFormat(), QgsMapCanvas *mapCanvas = nullptr, QWidget *parent SIP_TRANSFERTHIS = nullptr,
QgsVectorLayer *layer = nullptr );
~QgsTextFormatWidget() override;
@ -117,7 +119,7 @@ class GUI_EXPORT QgsTextFormatWidget : public QWidget, public QgsExpressionConte
* \param parent parent widget
* \param mode widget mode
*/
QgsTextFormatWidget( QgsMapCanvas *mapCanvas, QWidget *parent SIP_TRANSFERTHIS, Mode mode );
QgsTextFormatWidget( QgsMapCanvas *mapCanvas, QWidget *parent SIP_TRANSFERTHIS, Mode mode, QgsVectorLayer *layer = nullptr );
/**
* Updates the widget's state to reflect the settings in a QgsTextFormat.
@ -162,6 +164,8 @@ class GUI_EXPORT QgsTextFormatWidget : public QWidget, public QgsExpressionConte
//! Context in which widget is shown
QgsSymbolWidgetContext mContext;
//! Associated vector layer
QgsVectorLayer *mLayer = nullptr;
protected slots:
//! Updates line placement options to reflect current state of widget
@ -202,6 +206,7 @@ class GUI_EXPORT QgsTextFormatWidget : public QWidget, public QgsExpressionConte
bool mDockMode;
bool mLoadSvgParams = false;
QgsExpressionContext mPreviewExpressionContext;
void initWidget();
void setWidgetMode( Mode mode );
@ -279,14 +284,22 @@ class GUI_EXPORT QgsTextFormatDialog : public QDialog
* \param mapCanvas optional associated map canvas
* \param parent parent widget
* \param fl window flags for dialog
* \param layer associated vector layer
*/
QgsTextFormatDialog( const QgsTextFormat &format, QgsMapCanvas *mapCanvas = nullptr, QWidget *parent SIP_TRANSFERTHIS = nullptr, Qt::WindowFlags fl = QgsGuiUtils::ModalDialogFlags );
QgsTextFormatDialog( const QgsTextFormat &format, QgsMapCanvas *mapCanvas = nullptr, QWidget *parent SIP_TRANSFERTHIS = nullptr, Qt::WindowFlags fl = QgsGuiUtils::ModalDialogFlags, QgsVectorLayer *layer = nullptr );
/**
* Returns the current formatting settings defined by the widget.
*/
QgsTextFormat format() const;
/**
* Sets the \a context in which the widget is shown, e.g., the associated map canvas and expression contexts.
* \see context()
* \since QGIS 3.10
*/
void setContext( const QgsSymbolWidgetContext &context );
/**
* Returns a reference to the dialog's button box.
* \since QGIS 3.10
@ -322,14 +335,22 @@ class GUI_EXPORT QgsTextFormatPanelWidget : public QgsPanelWidgetWrapper
* \param format initial format settings to show in dialog
* \param mapCanvas optional associated map canvas
* \param parent parent widget
* \param layer associated layer
*/
QgsTextFormatPanelWidget( const QgsTextFormat &format, QgsMapCanvas *mapCanvas = nullptr, QWidget *parent SIP_TRANSFERTHIS = nullptr );
QgsTextFormatPanelWidget( const QgsTextFormat &format, QgsMapCanvas *mapCanvas = nullptr, QWidget *parent SIP_TRANSFERTHIS = nullptr, QgsVectorLayer *layer = nullptr );
/**
* Returns the current formatting settings defined by the widget.
*/
QgsTextFormat format() const;
/**
* Sets the \a context in which the widget is shown, e.g., the associated map canvas and expression contexts.
* \see context()
* \since QGIS 3.10
*/
void setContext( const QgsSymbolWidgetContext &context );
void setDockMode( bool dockMode ) override;
private: