Skip to content
Permalink
Browse files
[FEATURE] Port composer config widgets to QgsPanelWidgets
Brings the inline (ie, no modal dialogs!) color modification
and symbol editing from the layer styling panel to
composer item configuration.
  • Loading branch information
nyalldawson committed Oct 6, 2016
1 parent c6436f8 commit 028db7e54182a82c4e64e955dfe4971210b21f5b
@@ -67,6 +67,7 @@
#include "qgsvectorlayer.h"
#include "qgscomposerimageexportoptionsdialog.h"
#include "ui_qgssvgexportoptions.h"
#include "qgspanelwidgetstack.h"

#include <QCloseEvent>
#include <QCheckBox>
@@ -578,6 +579,8 @@ QgsComposer::QgsComposer( QgisApp *qgis, const QString& title )
mItemDock = new QgsDockWidget( tr( "Item properties" ), this );
mItemDock->setObjectName( "ItemDock" );
mItemDock->setMinimumWidth( minDockWidth );
mItemPropertiesStack = new QgsPanelWidgetStack();
mItemDock->setWidget( mItemPropertiesStack );
mPanelMenu->addAction( mItemDock->toggleViewAction() );
mUndoDock = new QgsDockWidget( tr( "Command history" ), this );
mUndoDock->setObjectName( "CommandDock" );
@@ -996,28 +999,27 @@ void QgsComposer::updateStatusAtlasMsg( const QString& message )

void QgsComposer::showItemOptions( QgsComposerItem* item )
{
QWidget* currentWidget = mItemDock->widget();

if ( !item )
{
mItemDock->setWidget( nullptr );
mItemPropertiesStack->takeMainPanel();
return;
}

QMap<QgsComposerItem*, QWidget*>::const_iterator it = mItemWidgetMap.constFind( item );
QMap<QgsComposerItem*, QgsPanelWidget*>::const_iterator it = mItemWidgetMap.constFind( item );
if ( it == mItemWidgetMap.constEnd() )
{
return;
}

QWidget* newWidget = it.value();

if ( !newWidget || newWidget == currentWidget ) //bail out if new widget does not exist or is already there
QgsPanelWidget* newWidget = it.value();
if ( !newWidget || newWidget == mItemPropertiesStack->mainPanel() ) //bail out if new widget does not exist or is already there
{
return;
}

mItemDock->setWidget( newWidget );
( void ) mItemPropertiesStack->takeMainPanel();
newWidget->setDockMode( true );
mItemPropertiesStack->setMainPanel( newWidget );
}

void QgsComposer::on_mActionOptions_triggered()
@@ -3774,7 +3776,7 @@ void QgsComposer::addComposerHtmlFrame( QgsComposerHtml* html, QgsComposerFrame*

void QgsComposer::deleteItem( QgsComposerItem* item )
{
QMap<QgsComposerItem*, QWidget*>::const_iterator it = mItemWidgetMap.constFind( item );
QMap<QgsComposerItem*, QgsPanelWidget*>::const_iterator it = mItemWidgetMap.constFind( item );

if ( it == mItemWidgetMap.constEnd() )
{
@@ -3800,7 +3802,7 @@ void QgsComposer::setSelectionTool()

bool QgsComposer::containsWmsLayer() const
{
QMap<QgsComposerItem*, QWidget*>::const_iterator item_it = mItemWidgetMap.constBegin();
QMap<QgsComposerItem*, QgsPanelWidget*>::const_iterator item_it = mItemWidgetMap.constBegin();
QgsComposerItem* currentItem = nullptr;
QgsComposerMap* currentMap = nullptr;

@@ -3822,7 +3824,7 @@ bool QgsComposer::containsWmsLayer() const
bool QgsComposer::containsAdvancedEffects() const
{
// Check if composer contains any blend modes or flattened layers for transparency
QMap<QgsComposerItem*, QWidget*>::const_iterator item_it = mItemWidgetMap.constBegin();
QMap<QgsComposerItem*, QgsPanelWidget*>::const_iterator item_it = mItemWidgetMap.constBegin();
QgsComposerItem* currentItem = nullptr;
QgsComposerMap* currentMap = nullptr;

@@ -3893,7 +3895,7 @@ void QgsComposer::showAdvancedEffectsWarning()

void QgsComposer::cleanupAfterTemplateRead()
{
QMap<QgsComposerItem*, QWidget*>::const_iterator itemIt = mItemWidgetMap.constBegin();
QMap<QgsComposerItem*, QgsPanelWidget*>::const_iterator itemIt = mItemWidgetMap.constBegin();
for ( ; itemIt != mItemWidgetMap.constEnd(); ++itemIt )
{
//update all legends completely
@@ -18,6 +18,7 @@
#define QGSCOMPOSER_H
#include "ui_qgscomposerbase.h"

#include "qgspanelwidget.h"
class QgisApp;
class QgsComposerArrow;
class QgsComposerPolygon;
@@ -44,6 +45,7 @@ class QgsDockWidget;
class QgsMapLayer;
class QgsFeature;
class QgsVectorLayer;
class QgsPanelWidgetStack;

class QGridLayout;
class QDomNode;
@@ -568,7 +570,7 @@ class QgsComposer: public QMainWindow, private Ui::QgsComposerBase
QSizeGrip *mSizeGrip;

//! To know which item to show if selection changes
QMap<QgsComposerItem*, QWidget*> mItemWidgetMap;
QMap<QgsComposerItem*, QgsPanelWidget*> mItemWidgetMap;

//! Window menu action to select this window
QAction *mWindowAction;
@@ -597,6 +599,7 @@ class QgsComposer: public QMainWindow, private Ui::QgsComposerBase
QMap< QgsComposerMap*, int > mMapsToRestore;

QgsDockWidget* mItemDock;
QgsPanelWidgetStack* mItemPropertiesStack;
QgsDockWidget* mUndoDock;
QgsDockWidget* mGeneralDock;
QgsDockWidget* mAtlasDock;
@@ -28,6 +28,7 @@
QgsComposerArrowWidget::QgsComposerArrowWidget( QgsComposerArrow* arrow ): QgsComposerItemBaseWidget( nullptr, arrow ), mArrow( arrow )
{
setupUi( this );
setPanelTitle( tr( "Arrow properties" ) );
mRadioButtonGroup = new QButtonGroup( this );
mRadioButtonGroup->addButton( mDefaultMarkerRadioButton );
mRadioButtonGroup->addButton( mNoMarkerRadioButton );
@@ -39,6 +39,7 @@ QgsComposerAttributeTableWidget::QgsComposerAttributeTableWidget( QgsComposerAtt
, mFrame( frame )
{
setupUi( this );
setPanelTitle( tr( "Table properties" ) );

blockAllSignals( true );

@@ -31,6 +31,7 @@ QgsComposerHtmlWidget::QgsComposerHtmlWidget( QgsComposerHtml* html, QgsComposer
, mFrame( frame )
{
setupUi( this );
setPanelTitle( tr( "HTML properties" ) );

//setup html editor
mHtmlEditor = new QgsCodeEditorHTML( this );
@@ -30,18 +30,20 @@

//QgsComposerItemBaseWidget

QgsComposerItemBaseWidget::QgsComposerItemBaseWidget( QWidget* parent, QgsComposerObject *composerObject ): QWidget( parent ), mComposerObject( composerObject )
QgsComposerConfigObject::QgsComposerConfigObject( QWidget* parent, QgsComposerObject *composerObject )
: QObject( parent )
, mComposerObject( composerObject )
{
connect( atlasComposition(), SIGNAL( coverageLayerChanged( QgsVectorLayer* ) ),
this, SLOT( updateDataDefinedButtons() ) );
connect( atlasComposition(), SIGNAL( toggled( bool ) ), this, SLOT( updateDataDefinedButtons() ) );
}

QgsComposerItemBaseWidget::~QgsComposerItemBaseWidget()
QgsComposerConfigObject::~QgsComposerConfigObject()
{
}

void QgsComposerItemBaseWidget::updateDataDefinedProperty()
void QgsComposerConfigObject::updateDataDefinedProperty()
{
//match data defined button to item's data defined property
QgsDataDefinedButton* ddButton = dynamic_cast<QgsDataDefinedButton*>( sender() );
@@ -64,15 +66,15 @@ void QgsComposerItemBaseWidget::updateDataDefinedProperty()
mComposerObject->refreshDataDefinedProperty( property );
}

void QgsComposerItemBaseWidget::updateDataDefinedButtons()
void QgsComposerConfigObject::updateDataDefinedButtons()
{
Q_FOREACH ( QgsDataDefinedButton* button, findChildren< QgsDataDefinedButton* >() )
{
button->setVectorLayer( atlasCoverageLayer() );
}
}

void QgsComposerItemBaseWidget::setDataDefinedProperty( const QgsDataDefinedButton *ddBtn, QgsComposerObject::DataDefinedProperty p )
void QgsComposerConfigObject::setDataDefinedProperty( const QgsDataDefinedButton *ddBtn, QgsComposerObject::DataDefinedProperty p )
{
if ( !mComposerObject )
{
@@ -83,7 +85,7 @@ void QgsComposerItemBaseWidget::setDataDefinedProperty( const QgsDataDefinedButt
mComposerObject->setDataDefinedProperty( p, map.value( "active" ).toInt(), map.value( "useexpr" ).toInt(), map.value( "expression" ), map.value( "field" ) );
}

void QgsComposerItemBaseWidget::registerDataDefinedButton( QgsDataDefinedButton* button, QgsComposerObject::DataDefinedProperty property,
void QgsComposerConfigObject::registerDataDefinedButton( QgsDataDefinedButton* button, QgsComposerObject::DataDefinedProperty property,
QgsDataDefinedButton::DataType type, const QString& description )
{
button->blockSignals( true );
@@ -98,7 +100,7 @@ void QgsComposerItemBaseWidget::registerDataDefinedButton( QgsDataDefinedButton*
button->blockSignals( false );
}

QgsAtlasComposition* QgsComposerItemBaseWidget::atlasComposition() const
QgsAtlasComposition* QgsComposerConfigObject::atlasComposition() const
{
if ( !mComposerObject )
{
@@ -115,7 +117,7 @@ QgsAtlasComposition* QgsComposerItemBaseWidget::atlasComposition() const
return &composition->atlasComposition();
}

QgsVectorLayer* QgsComposerItemBaseWidget::atlasCoverageLayer() const
QgsVectorLayer* QgsComposerConfigObject::atlasCoverageLayer() const
{
QgsAtlasComposition* atlasMap = atlasComposition();

@@ -140,8 +142,9 @@ void QgsComposerItemWidget::updateVariables()
}

QgsComposerItemWidget::QgsComposerItemWidget( QWidget* parent, QgsComposerItem* item )
: QgsComposerItemBaseWidget( parent, item )
: QWidget( parent )
, mItem( item )
, mConfigObject( new QgsComposerConfigObject( this, item ) )
, mFreezeXPosSpin( false )
, mFreezeYPosSpin( false )
, mFreezeWidthSpin( false )
@@ -184,18 +187,6 @@ QgsComposerItemWidget::QgsComposerItemWidget( QWidget* parent, QgsComposerItem*
connect( mItem->composition(), SIGNAL( variablesChanged() ), this, SLOT( updateVariables() ) );
}

QgsComposerItemWidget::QgsComposerItemWidget()
: QgsComposerItemBaseWidget( nullptr, nullptr )
, mItem( nullptr )
, mFreezeXPosSpin( false )
, mFreezeYPosSpin( false )
, mFreezeWidthSpin( false )
, mFreezeHeightSpin( false )
, mFreezePageSpin( false )
{

}

QgsComposerItemWidget::~QgsComposerItemWidget()
{

@@ -552,22 +543,22 @@ void QgsComposerItemWidget::setValuesForGuiNonPositionElements()

void QgsComposerItemWidget::populateDataDefinedButtons()
{
registerDataDefinedButton( mXPositionDDBtn, QgsComposerObject::PositionX,
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::doubleDesc() );
registerDataDefinedButton( mYPositionDDBtn, QgsComposerObject::PositionY,
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::doubleDesc() );
registerDataDefinedButton( mWidthDDBtn, QgsComposerObject::ItemWidth,
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::doubleDesc() );
registerDataDefinedButton( mHeightDDBtn, QgsComposerObject::ItemHeight,
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::doubleDesc() );
registerDataDefinedButton( mItemRotationDDBtn, QgsComposerObject::ItemRotation,
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::double180RotDesc() );
registerDataDefinedButton( mTransparencyDDBtn, QgsComposerObject::Transparency,
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::intTranspDesc() );
registerDataDefinedButton( mBlendModeDDBtn, QgsComposerObject::BlendMode,
QgsDataDefinedButton::String, QgsDataDefinedButton::blendModesDesc() );
registerDataDefinedButton( mExcludePrintsDDBtn, QgsComposerObject::ExcludeFromExports,
QgsDataDefinedButton::String, QgsDataDefinedButton::boolDesc() );
mConfigObject->registerDataDefinedButton( mXPositionDDBtn, QgsComposerObject::PositionX,
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::doubleDesc() );
mConfigObject->registerDataDefinedButton( mYPositionDDBtn, QgsComposerObject::PositionY,
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::doubleDesc() );
mConfigObject->registerDataDefinedButton( mWidthDDBtn, QgsComposerObject::ItemWidth,
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::doubleDesc() );
mConfigObject->registerDataDefinedButton( mHeightDDBtn, QgsComposerObject::ItemHeight,
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::doubleDesc() );
mConfigObject->registerDataDefinedButton( mItemRotationDDBtn, QgsComposerObject::ItemRotation,
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::double180RotDesc() );
mConfigObject->registerDataDefinedButton( mTransparencyDDBtn, QgsComposerObject::Transparency,
QgsDataDefinedButton::AnyType, QgsDataDefinedButton::intTranspDesc() );
mConfigObject->registerDataDefinedButton( mBlendModeDDBtn, QgsComposerObject::BlendMode,
QgsDataDefinedButton::String, QgsDataDefinedButton::blendModesDesc() );
mConfigObject->registerDataDefinedButton( mExcludePrintsDDBtn, QgsComposerObject::ExcludeFromExports,
QgsDataDefinedButton::String, QgsDataDefinedButton::boolDesc() );
}

void QgsComposerItemWidget::setValuesForGuiElements()
@@ -786,3 +777,25 @@ void QgsComposerItemWidget::on_mExcludeFromPrintsCheckBox_toggled( bool checked
mItem->endCommand();
}
}

QgsComposerItemBaseWidget::QgsComposerItemBaseWidget( QWidget* parent, QgsComposerObject* composerObject )
: QgsPanelWidget( parent )
, mConfigObject( new QgsComposerConfigObject( this, composerObject ) )
{

}

void QgsComposerItemBaseWidget::registerDataDefinedButton( QgsDataDefinedButton* button, QgsComposerObject::DataDefinedProperty property, QgsDataDefinedButton::DataType type, const QString& description )
{
mConfigObject->registerDataDefinedButton( button, property, type, description );
}

QgsVectorLayer* QgsComposerItemBaseWidget::atlasCoverageLayer() const
{
return mConfigObject->atlasCoverageLayer();
}

QgsAtlasComposition* QgsComposerItemBaseWidget::atlasComposition() const
{
return mConfigObject->atlasComposition();
}

2 comments on commit 028db7e

@nirvn

This comment has been minimized.

Copy link
Contributor

@nirvn nirvn replied Oct 7, 2016

@nyalldawson , the composition's page background symbology widget still shows as a pop-up dialog, can it be transformed into a QgsPanelWidgets?

@nyalldawson

This comment has been minimized.

Copy link
Collaborator Author

@nyalldawson nyalldawson replied Oct 7, 2016

There's still lots of symbol widgets which pop up here - they each need to be manually ported. I'll work on it slowly.

Please sign in to comment.