Skip to content

Commit c228132

Browse files
committed
Layout designers listen out for new item types in registry and
auto create actions for adding new items of the newly registered type This avoids hard-coding in available item types into layout UI classes, and allows designers to handle plugin-supplied item types
1 parent 97e8d9c commit c228132

File tree

6 files changed

+68
-9
lines changed

6 files changed

+68
-9
lines changed

python/core/layout/qgslayoutitemregistry.sip

+6
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ class QgsLayoutItemAbstractMetadata
3737
:rtype: int
3838
%End
3939

40+
virtual QIcon icon() const;
41+
%Docstring
42+
Returns an icon representing the layout item type.
43+
:rtype: QIcon
44+
%End
45+
4046
QString visibleName() const;
4147
%Docstring
4248
Returns a translated, user visible name for the layout item class.

src/app/layout/qgslayoutdesignerdialog.cpp

+34
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
***************************************************************************/
1717

1818
#include "qgslayoutdesignerdialog.h"
19+
#include "qgslayoutitemregistry.h"
1920
#include "qgssettings.h"
2021
#include "qgisapp.h"
2122
#include "qgslogger.h"
@@ -39,6 +40,7 @@ void QgsAppLayoutDesignerInterface::close()
3940
QgsLayoutDesignerDialog::QgsLayoutDesignerDialog( QWidget *parent, Qt::WindowFlags flags )
4041
: QMainWindow( parent, flags )
4142
, mInterface( new QgsAppLayoutDesignerInterface( this ) )
43+
, mToolsActionGroup( new QActionGroup( this ) )
4244
{
4345
QgsSettings settings;
4446
int size = settings.value( QStringLiteral( "IconSize" ), QGIS_ICON_SIZE ).toInt();
@@ -55,6 +57,16 @@ QgsLayoutDesignerDialog::QgsLayoutDesignerDialog( QWidget *parent, Qt::WindowFla
5557

5658
connect( mActionClose, &QAction::triggered, this, &QWidget::close );
5759

60+
// populate with initial items...
61+
QMap< int, QString> types = QgsApplication::layoutItemRegistry()->itemTypes();
62+
QMap< int, QString>::const_iterator typeIt = types.constBegin();
63+
for ( ; typeIt != types.constEnd(); ++typeIt )
64+
{
65+
itemTypeAdded( typeIt.key(), typeIt.value() );
66+
}
67+
//..and listen out for new item types
68+
connect( QgsApplication::layoutItemRegistry(), &QgsLayoutItemRegistry::typeAdded, this, &QgsLayoutDesignerDialog::itemTypeAdded );
69+
5870
restoreWindowState();
5971
}
6072

@@ -122,6 +134,23 @@ void QgsLayoutDesignerDialog::closeEvent( QCloseEvent * )
122134
saveWindowState();
123135
}
124136

137+
void QgsLayoutDesignerDialog::itemTypeAdded( int type, const QString &name )
138+
{
139+
// update UI for new item type
140+
QAction *action = new QAction( tr( "Add %1" ).arg( name ), this );
141+
action->setToolTip( tr( "Adds a new %1 to the layout" ).arg( name ) );
142+
action->setCheckable( true );
143+
action->setData( type );
144+
action->setIcon( QgsApplication::layoutItemRegistry()->itemMetadata( type )->icon() );
145+
mToolsActionGroup->addAction( action );
146+
mItemMenu->addAction( action );
147+
mItemToolbar->addAction( action );
148+
connect( action, &QAction::triggered, this, [this, type]()
149+
{
150+
activateNewItemCreationTool( type );
151+
} );
152+
}
153+
125154
void QgsLayoutDesignerDialog::saveWindowState()
126155
{
127156
QgsSettings settings;
@@ -147,4 +176,9 @@ void QgsLayoutDesignerDialog::restoreWindowState()
147176
}
148177
}
149178

179+
void QgsLayoutDesignerDialog::activateNewItemCreationTool( int type )
180+
{
181+
QgsLogger::debug( QStringLiteral( "creating new %1 item " ).arg( QgsApplication::layoutItemRegistry()->itemMetadata( type )->visibleName() ) );
182+
}
183+
150184

src/app/layout/qgslayoutdesignerdialog.h

+9
Original file line numberDiff line numberDiff line change
@@ -96,18 +96,27 @@ class QgsLayoutDesignerDialog: public QMainWindow, private Ui::QgsLayoutDesigner
9696

9797
virtual void closeEvent( QCloseEvent * ) override;
9898

99+
private slots:
100+
101+
void itemTypeAdded( int type, const QString &name );
102+
99103
private:
100104

101105
QgsAppLayoutDesignerInterface *mInterface = nullptr;
102106

103107
QgsLayout *mLayout = nullptr;
104108

109+
QActionGroup *mToolsActionGroup = nullptr;
110+
111+
105112
//! Save window state
106113
void saveWindowState();
107114

108115
//! Restore the window and toolbar state
109116
void restoreWindowState();
110117

118+
//! Switch to new item creation tool, for a new item of the specified \a type.
119+
void activateNewItemCreationTool( int type );
111120

112121
};
113122

src/core/layout/qgslayoutitemregistry.h

+14-4
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@
1818

1919
#include "qgis_core.h"
2020
#include "qgis_sip.h"
21+
#include "qgsapplication.h"
2122
#include "qgspathresolver.h"
2223
#include <QGraphicsItem> //for QGraphicsItem::UserType
24+
#include <QIcon>
2325
#include <functional>
2426

2527
class QgsLayout;
@@ -51,6 +53,11 @@ class CORE_EXPORT QgsLayoutItemAbstractMetadata
5153
*/
5254
int type() const { return mType; }
5355

56+
/**
57+
* Returns an icon representing the layout item type.
58+
*/
59+
virtual QIcon icon() const { return QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddBasicRectangle.svg" ) ); }
60+
5461
/**
5562
* Returns a translated, user visible name for the layout item class.
5663
*/
@@ -112,11 +119,12 @@ class CORE_EXPORT QgsLayoutItemMetadata : public QgsLayoutItemAbstractMetadata
112119
* and \a visibleName, and function pointers for the various item and
113120
* configuration widget creation functions.
114121
*/
115-
QgsLayoutItemMetadata( int type, const QString &visibleName,
122+
QgsLayoutItemMetadata( int type, const QString &visibleName, const QIcon &icon,
116123
QgsLayoutItemCreateFunc pfCreate,
117124
QgsLayoutItemPathResolverFunc pfPathResolver = nullptr,
118125
QgsLayoutItemWidgetFunc pfWidget = nullptr )
119126
: QgsLayoutItemAbstractMetadata( type, visibleName )
127+
, mIcon( icon )
120128
, mCreateFunc( pfCreate )
121129
, mWidgetFunc( pfWidget )
122130
, mPathResolverFunc( pfPathResolver )
@@ -144,15 +152,17 @@ class CORE_EXPORT QgsLayoutItemMetadata : public QgsLayoutItemAbstractMetadata
144152
*/
145153
void setWidgetFunction( QgsLayoutItemWidgetFunc function ) { mWidgetFunc = function; }
146154

147-
virtual QgsLayoutItem *createItem( QgsLayout *layout, const QVariantMap &properties ) override { return mCreateFunc ? mCreateFunc( layout, properties ) : nullptr; }
148-
virtual QWidget *createItemWidget() override { return mWidgetFunc ? mWidgetFunc() : nullptr; }
149-
virtual void resolvePaths( QVariantMap &properties, const QgsPathResolver &pathResolver, bool saving ) override
155+
QIcon icon() const override { return mIcon.isNull() ? QgsLayoutItemAbstractMetadata::icon() : mIcon; }
156+
QgsLayoutItem *createItem( QgsLayout *layout, const QVariantMap &properties ) override { return mCreateFunc ? mCreateFunc( layout, properties ) : nullptr; }
157+
QWidget *createItemWidget() override { return mWidgetFunc ? mWidgetFunc() : nullptr; }
158+
void resolvePaths( QVariantMap &properties, const QgsPathResolver &pathResolver, bool saving ) override
150159
{
151160
if ( mPathResolverFunc )
152161
mPathResolverFunc( properties, pathResolver, saving );
153162
}
154163

155164
protected:
165+
QIcon mIcon;
156166
QgsLayoutItemCreateFunc mCreateFunc = nullptr;
157167
QgsLayoutItemWidgetFunc mWidgetFunc = nullptr;
158168
QgsLayoutItemPathResolverFunc mPathResolverFunc = nullptr;

src/ui/layout/qgslayoutdesignerbase.ui

+4-4
Original file line numberDiff line numberDiff line change
@@ -80,19 +80,19 @@
8080
<height>25</height>
8181
</rect>
8282
</property>
83-
<widget class="QMenu" name="menuLayout">
83+
<widget class="QMenu" name="mLayoutMenu">
8484
<property name="title">
8585
<string>&amp;Layout</string>
8686
</property>
8787
<addaction name="mActionClose"/>
8888
</widget>
89-
<widget class="QMenu" name="menuItems">
89+
<widget class="QMenu" name="mItemMenu">
9090
<property name="title">
9191
<string>&amp;Items</string>
9292
</property>
9393
</widget>
94-
<addaction name="menuLayout"/>
95-
<addaction name="menuItems"/>
94+
<addaction name="mLayoutMenu"/>
95+
<addaction name="mItemMenu"/>
9696
</widget>
9797
<action name="mActionClose">
9898
<property name="text">

tests/src/core/testqgslayoutitem.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ void TestQgsLayoutItem::registry()
132132

133133
QSignalSpy spyTypeAdded( &registry, &QgsLayoutItemRegistry::typeAdded );
134134

135-
QgsLayoutItemMetadata *metadata = new QgsLayoutItemMetadata( 2, QStringLiteral( "my type" ), create, resolve, createWidget );
135+
QgsLayoutItemMetadata *metadata = new QgsLayoutItemMetadata( 2, QStringLiteral( "my type" ), QIcon(), create, resolve, createWidget );
136136
QVERIFY( registry.addLayoutItemType( metadata ) );
137137
QCOMPARE( spyTypeAdded.count(), 1 );
138138
QCOMPARE( spyTypeAdded.value( 0 ).at( 0 ).toInt(), 2 );

0 commit comments

Comments
 (0)