Skip to content

Commit cf488d3

Browse files
committedJul 11, 2017
Split layout item registry into two separate registries
Instead of relying on forward declared c++ classes from gui in QgsLayoutItemRegistry, instead create a QgsLayoutItemGuiRegistry which handles registration of all the GUI specific behavior relating to layout items. Remove all GUI related code from QgsLayoutItemRegistry. This creates a cleaner split between core/gui code, and given that there'll be a lot of gui specific behavior which needs to be handled by a registry it makes sense to keep this isolated in gui. It also plays nicer with the sip bindings, which can't handle forward declared gui classes in core.
1 parent 0307cac commit cf488d3

18 files changed

+580
-229
lines changed
 

‎python/core/layout/qgslayoutitemregistry.sip

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,13 @@ class QgsLayoutItemAbstractMetadata
1313
{
1414
%Docstring
1515
Stores metadata about one layout item class.
16+
17+
A companion class, QgsLayoutItemAbstractGuiMetadata, handles the
18+
GUI behavior of QgsLayoutItems.
19+
1620
.. note::
1721

18-
In C++ you can use QgsSymbolLayerMetadata convenience class.
22+
In C++ you can use QgsLayoutItemMetadata convenience class.
1923
.. versionadded:: 3.0
2024
%End
2125

@@ -56,13 +60,6 @@ class QgsLayoutItemAbstractMetadata
5660
:rtype: QgsLayoutItem
5761
%End
5862

59-
virtual QWidget *createItemWidget() /Factory/;
60-
%Docstring
61-
Creates a configuration widget for layout items of this type. Can return None if no configuration GUI is required.
62-
:rtype: QWidget
63-
%End
64-
65-
6663
virtual void resolvePaths( QVariantMap &properties, const QgsPathResolver &pathResolver, bool saving );
6764
%Docstring
6865
Resolve paths in the item's ``properties`` (if there are any paths).
@@ -79,8 +76,6 @@ class QgsLayoutItemAbstractMetadata
7976

8077

8178

82-
83-
8479
class QgsLayoutItemRegistry : QObject
8580
{
8681
%Docstring
@@ -89,6 +84,9 @@ class QgsLayoutItemRegistry : QObject
8984
QgsLayoutItemRegistry is not usually directly created, but rather accessed through
9085
QgsApplication.layoutItemRegistry().
9186

87+
A companion class, QgsLayoutItemGuiRegistry, handles the GUI behavior
88+
of layout items.
89+
9290
.. versionadded:: 3.0
9391
%End
9492

@@ -147,13 +145,6 @@ class QgsLayoutItemRegistry : QObject
147145
:rtype: QgsLayoutItem
148146
%End
149147

150-
QWidget *createItemWidget( int type ) const /Factory/;
151-
%Docstring
152-
Creates a new instance of a layout item configuration widget for the specified item ``type``.
153-
:rtype: QWidget
154-
%End
155-
156-
157148
void resolvePaths( int type, QVariantMap &properties, const QgsPathResolver &pathResolver, bool saving ) const;
158149
%Docstring
159150
Resolve paths in properties of a particular symbol layer.

‎python/gui/gui_auto.sip

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242
%Include editorwidgets/core/qgseditorwidgetautoconf.sip
4343
%Include layertree/qgslayertreeembeddedconfigwidget.sip
4444
%Include layertree/qgslayertreeembeddedwidgetregistry.sip
45-
%Include layout/qgslayoutitemregistryguiutils.sip
4645
%Include layout/qgslayoutviewmouseevent.sip
4746
%Include layout/qgslayoutviewrubberband.sip
4847
%Include locator/qgslocatorcontext.sip
@@ -278,6 +277,7 @@
278277
%Include layertree/qgslayertreeview.sip
279278
%Include layertree/qgslayertreeviewdefaultactions.sip
280279
%Include layout/qgslayoutdesignerinterface.sip
280+
%Include layout/qgslayoutitemguiregistry.sip
281281
%Include layout/qgslayoutview.sip
282282
%Include layout/qgslayoutviewtool.sip
283283
%Include layout/qgslayoutviewtooladditem.sip
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
/************************************************************************
2+
* This file has been generated automatically from *
3+
* *
4+
* src/gui/layout/qgslayoutitemguiregistry.h *
5+
* *
6+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
7+
************************************************************************/
8+
9+
10+
11+
12+
class QgsLayoutItemAbstractGuiMetadata
13+
{
14+
%Docstring
15+
Stores GUI metadata about one layout item class.
16+
17+
This is a companion to QgsLayoutItemAbstractMetadata, storing only
18+
the components related to the GUI behavior of a layout item.
19+
20+
.. note::
21+
22+
In C++ you can use QgsLayoutItemGuiMetadata convenience class.
23+
.. versionadded:: 3.0
24+
%End
25+
26+
%TypeHeaderCode
27+
#include "qgslayoutitemguiregistry.h"
28+
%End
29+
public:
30+
31+
QgsLayoutItemAbstractGuiMetadata( int type );
32+
%Docstring
33+
Constructor for QgsLayoutItemAbstractGuiMetadata with the specified class ``type``.
34+
%End
35+
36+
virtual ~QgsLayoutItemAbstractGuiMetadata();
37+
38+
int type() const;
39+
%Docstring
40+
Returns the unique item type code for the layout item class.
41+
:rtype: int
42+
%End
43+
44+
virtual QIcon creationIcon() const;
45+
%Docstring
46+
Returns an icon representing creation of the layout item type.
47+
:rtype: QIcon
48+
%End
49+
50+
virtual QWidget *createItemWidget() /Factory/;
51+
%Docstring
52+
Creates a configuration widget for layout items of this type. Can return None if no configuration GUI is required.
53+
:rtype: QWidget
54+
%End
55+
56+
virtual QgsLayoutViewRubberBand *createRubberBand( QgsLayoutView *view ) /Factory/;
57+
%Docstring
58+
Creates a rubber band for use when creating layout items of this type. Can return None if no rubber band
59+
should be created. The default behavior is to create a rectangular rubber band.
60+
:rtype: QgsLayoutViewRubberBand
61+
%End
62+
63+
};
64+
65+
66+
67+
68+
class QgsLayoutItemGuiRegistry : QObject
69+
{
70+
%Docstring
71+
Registry of available layout item GUI behavior.
72+
73+
QgsLayoutItemGuiRegistry is not usually directly created, but rather accessed through
74+
QgsGui.layoutItemGuiRegistry().
75+
76+
This acts as a companion to QgsLayoutItemRegistry, handling only
77+
the components related to the GUI behavior of layout items.
78+
79+
.. versionadded:: 3.0
80+
%End
81+
82+
%TypeHeaderCode
83+
#include "qgslayoutitemguiregistry.h"
84+
%End
85+
public:
86+
87+
QgsLayoutItemGuiRegistry( QObject *parent = 0 );
88+
%Docstring
89+
Creates a new empty item GUI registry.
90+
91+
QgsLayoutItemGuiRegistry is not usually directly created, but rather accessed through
92+
QgsGui.layoutItemGuiRegistry().
93+
94+
.. seealso:: populate()
95+
%End
96+
97+
~QgsLayoutItemGuiRegistry();
98+
99+
bool populate();
100+
%Docstring
101+
Populates the registry with standard item types. If called on a non-empty registry
102+
then this will have no effect and will return false.
103+
:rtype: bool
104+
%End
105+
106+
107+
QgsLayoutItemAbstractGuiMetadata *itemMetadata( int type ) const;
108+
%Docstring
109+
Returns the metadata for the specified item ``type``. Returns None if
110+
a corresponding type was not found in the registry.
111+
:rtype: QgsLayoutItemAbstractGuiMetadata
112+
%End
113+
114+
bool addLayoutItemGuiMetadata( QgsLayoutItemAbstractGuiMetadata *metadata /Transfer/ );
115+
%Docstring
116+
Registers the gui metadata for a new layout item type. Takes ownership of the metadata instance.
117+
:rtype: bool
118+
%End
119+
120+
QWidget *createItemWidget( int type ) const /Factory/;
121+
%Docstring
122+
Creates a new instance of a layout item configuration widget for the specified item ``type``.
123+
:rtype: QWidget
124+
%End
125+
126+
127+
QList< int > itemTypes() const;
128+
%Docstring
129+
Returns a list of available item types handled by the registry.
130+
:rtype: list of int
131+
%End
132+
133+
signals:
134+
135+
void typeAdded( int type );
136+
%Docstring
137+
Emitted whenever a new item type is added to the registry, with the specified
138+
``type``.
139+
%End
140+
141+
private:
142+
QgsLayoutItemGuiRegistry( const QgsLayoutItemGuiRegistry &rh );
143+
};
144+
145+
146+
147+
148+
/************************************************************************
149+
* This file has been generated automatically from *
150+
* *
151+
* src/gui/layout/qgslayoutitemguiregistry.h *
152+
* *
153+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
154+
************************************************************************/

‎python/gui/qgsgui.sip

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,12 @@ class QgsGui
5656
:rtype: QgsMapLayerActionRegistry
5757
%End
5858

59+
static QgsLayoutItemGuiRegistry *layoutItemGuiRegistry();
60+
%Docstring
61+
Returns the global layout item GUI registry, used for registering the GUI behavior of layout items.
62+
:rtype: QgsLayoutItemGuiRegistry
63+
%End
64+
5965
~QgsGui();
6066

6167
private:

‎src/app/layout/qgslayoutdesignerdialog.cpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
#include "qgslayoutviewtoolpan.h"
2727
#include "qgslayoutviewtoolzoom.h"
2828
#include "qgslayoutviewtoolselect.h"
29+
#include "qgsgui.h"
30+
#include "qgslayoutitemguiregistry.h"
2931

3032
QgsAppLayoutDesignerInterface::QgsAppLayoutDesignerInterface( QgsLayoutDesignerDialog *dialog )
3133
: QgsLayoutDesignerInterface( dialog )
@@ -89,14 +91,12 @@ QgsLayoutDesignerDialog::QgsLayoutDesignerDialog( QWidget *parent, Qt::WindowFla
8991
connect( mActionClose, &QAction::triggered, this, &QWidget::close );
9092

9193
// populate with initial items...
92-
QMap< int, QString> types = QgsApplication::layoutItemRegistry()->itemTypes();
93-
QMap< int, QString>::const_iterator typeIt = types.constBegin();
94-
for ( ; typeIt != types.constEnd(); ++typeIt )
94+
Q_FOREACH ( int type, QgsGui::layoutItemGuiRegistry()->itemTypes() )
9595
{
96-
itemTypeAdded( typeIt.key(), typeIt.value() );
96+
itemTypeAdded( type );
9797
}
9898
//..and listen out for new item types
99-
connect( QgsApplication::layoutItemRegistry(), &QgsLayoutItemRegistry::typeAdded, this, &QgsLayoutDesignerDialog::itemTypeAdded );
99+
connect( QgsGui::layoutItemGuiRegistry(), &QgsLayoutItemGuiRegistry::typeAdded, this, &QgsLayoutDesignerDialog::itemTypeAdded );
100100

101101
mAddItemTool = new QgsLayoutViewToolAddItem( mView );
102102
mPanTool = new QgsLayoutViewToolPan( mView );
@@ -192,14 +192,15 @@ void QgsLayoutDesignerDialog::closeEvent( QCloseEvent * )
192192
saveWindowState();
193193
}
194194

195-
void QgsLayoutDesignerDialog::itemTypeAdded( int type, const QString &name )
195+
void QgsLayoutDesignerDialog::itemTypeAdded( int type )
196196
{
197+
QString name = QgsApplication::layoutItemRegistry()->itemMetadata( type )->visibleName();
197198
// update UI for new item type
198199
QAction *action = new QAction( tr( "Add %1" ).arg( name ), this );
199200
action->setToolTip( tr( "Adds a new %1 to the layout" ).arg( name ) );
200201
action->setCheckable( true );
201202
action->setData( type );
202-
action->setIcon( QgsApplication::layoutItemRegistry()->itemMetadata( type )->icon() );
203+
action->setIcon( QgsGui::layoutItemGuiRegistry()->itemMetadata( type )->creationIcon() );
203204
mToolsActionGroup->addAction( action );
204205
mItemMenu->addAction( action );
205206
mToolsToolbar->addAction( action );

‎src/app/layout/qgslayoutdesignerdialog.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ class QgsLayoutDesignerDialog: public QMainWindow, private Ui::QgsLayoutDesigner
115115

116116
private slots:
117117

118-
void itemTypeAdded( int type, const QString &name );
118+
void itemTypeAdded( int type );
119119

120120
private:
121121

‎src/core/layout/qgslayoutitemregistry.cpp

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -65,25 +65,6 @@ QgsLayoutItem *QgsLayoutItemRegistry::createItem( int type, QgsLayout *layout, c
6565
return mMetadata[type]->createItem( layout, properties );
6666
}
6767

68-
QWidget *QgsLayoutItemRegistry::createItemWidget( int type ) const
69-
{
70-
if ( !mMetadata.contains( type ) )
71-
return nullptr;
72-
73-
return mMetadata[type]->createItemWidget();
74-
}
75-
76-
QgsLayoutViewRubberBand *QgsLayoutItemRegistry::createItemRubberBand( int type, QgsLayoutView *view ) const
77-
{
78-
if ( mRubberBandFunctions.contains( type ) )
79-
return mRubberBandFunctions.value( type )( view );
80-
81-
if ( !mMetadata.contains( type ) )
82-
return nullptr;
83-
84-
return mMetadata[type]->createRubberBand( view );
85-
}
86-
8768
void QgsLayoutItemRegistry::resolvePaths( int type, QVariantMap &properties, const QgsPathResolver &pathResolver, bool saving ) const
8869
{
8970
if ( !mMetadata.contains( type ) )

‎src/core/layout/qgslayoutitemregistry.h

Lines changed: 11 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,15 @@
2929
class QgsLayout;
3030
class QgsLayoutView;
3131
class QgsLayoutItem;
32-
class QgsLayoutViewRubberBand;
3332

3433
/**
3534
* \ingroup core
3635
* \brief Stores metadata about one layout item class.
37-
* \note In C++ you can use QgsSymbolLayerMetadata convenience class.
36+
*
37+
* A companion class, QgsLayoutItemAbstractGuiMetadata, handles the
38+
* GUI behavior of QgsLayoutItems.
39+
*
40+
* \note In C++ you can use QgsLayoutItemMetadata convenience class.
3841
* \since QGIS 3.0
3942
*/
4043
class CORE_EXPORT QgsLayoutItemAbstractMetadata
@@ -72,19 +75,6 @@ class CORE_EXPORT QgsLayoutItemAbstractMetadata
7275
*/
7376
virtual QgsLayoutItem *createItem( QgsLayout *layout, const QVariantMap &properties ) = 0 SIP_FACTORY;
7477

75-
/**
76-
* Creates a configuration widget for layout items of this type. Can return nullptr if no configuration GUI is required.
77-
*/
78-
virtual QWidget *createItemWidget() SIP_FACTORY { return nullptr; }
79-
80-
/**
81-
* Creates a rubber band for use when creating layout items of this type. Can return nullptr if no rubber band
82-
* should be created.
83-
* \note not available in Python bindings. Python item subclasses must use QgsLayoutItemRegistryGuiUtils
84-
* to override the default rubber band creation function.
85-
*/
86-
virtual QgsLayoutViewRubberBand *createRubberBand( QgsLayoutView *view ) SIP_SKIP { Q_UNUSED( view ); return nullptr; }
87-
8878
/**
8979
* Resolve paths in the item's \a properties (if there are any paths).
9080
* When \a saving is true, paths are converted from absolute to relative,
@@ -108,12 +98,6 @@ class CORE_EXPORT QgsLayoutItemAbstractMetadata
10898
//! Layout item creation function
10999
typedef std::function<QgsLayoutItem *( QgsLayout *, const QVariantMap & )> QgsLayoutItemCreateFunc SIP_SKIP;
110100

111-
//! Layout item configuration widget creation function
112-
typedef std::function<QWidget *()> QgsLayoutItemWidgetFunc SIP_SKIP;
113-
114-
//! Layout rubber band creation function
115-
typedef std::function<QgsLayoutViewRubberBand *( QgsLayoutView * )> QgsLayoutItemRubberBandFunc SIP_SKIP;
116-
117101
//! Layout item path resolver function
118102
typedef std::function<void( QVariantMap &, const QgsPathResolver &, bool )> QgsLayoutItemPathResolverFunc SIP_SKIP;
119103

@@ -131,17 +115,14 @@ class CORE_EXPORT QgsLayoutItemMetadata : public QgsLayoutItemAbstractMetadata
131115

132116
/**
133117
* Constructor for QgsLayoutItemMetadata with the specified class \a type
134-
* and \a visibleName, and function pointers for the various item and
135-
* configuration widget creation functions.
118+
* and \a visibleName, and function pointers for the various item creation functions.
136119
*/
137120
QgsLayoutItemMetadata( int type, const QString &visibleName, const QIcon &icon,
138121
QgsLayoutItemCreateFunc pfCreate,
139-
QgsLayoutItemPathResolverFunc pfPathResolver = nullptr,
140-
QgsLayoutItemWidgetFunc pfWidget = nullptr )
122+
QgsLayoutItemPathResolverFunc pfPathResolver = nullptr )
141123
: QgsLayoutItemAbstractMetadata( type, visibleName )
142124
, mIcon( icon )
143125
, mCreateFunc( pfCreate )
144-
, mWidgetFunc( pfWidget )
145126
, mPathResolverFunc( pfPathResolver )
146127
{}
147128

@@ -150,39 +131,13 @@ class CORE_EXPORT QgsLayoutItemMetadata : public QgsLayoutItemAbstractMetadata
150131
*/
151132
QgsLayoutItemCreateFunc createFunction() const { return mCreateFunc; }
152133

153-
/**
154-
* Returns the classes' configuration widget creation function.
155-
* \see setWidgetFunction()
156-
*/
157-
QgsLayoutItemWidgetFunc widgetFunction() const { return mWidgetFunc; }
158-
159134
/**
160135
* Returns the classes' path resolver function.
161136
*/
162137
QgsLayoutItemPathResolverFunc pathResolverFunction() const { return mPathResolverFunc; }
163138

164-
/**
165-
* Sets the classes' configuration widget creation \a function.
166-
* \see widgetFunction()
167-
*/
168-
void setWidgetFunction( QgsLayoutItemWidgetFunc function ) { mWidgetFunc = function; }
169-
170-
/**
171-
* Returns the classes' rubber band creation function.
172-
* \see setRubberBandCreationFunction()
173-
*/
174-
QgsLayoutItemRubberBandFunc rubberBandCreationFunction() const { return mRubberBandFunc; }
175-
176-
/**
177-
* Sets the classes' rubber band creation \a function.
178-
* \see rubberBandCreationFunction()
179-
*/
180-
void setRubberBandCreationFunction( QgsLayoutItemRubberBandFunc function ) { mRubberBandFunc = function; }
181-
182139
QIcon icon() const override { return mIcon.isNull() ? QgsLayoutItemAbstractMetadata::icon() : mIcon; }
183140
QgsLayoutItem *createItem( QgsLayout *layout, const QVariantMap &properties ) override { return mCreateFunc ? mCreateFunc( layout, properties ) : nullptr; }
184-
QWidget *createItemWidget() override { return mWidgetFunc ? mWidgetFunc() : nullptr; }
185-
QgsLayoutViewRubberBand *createRubberBand( QgsLayoutView *view ) override { return mRubberBandFunc ? mRubberBandFunc( view ) : nullptr; }
186141

187142
void resolvePaths( QVariantMap &properties, const QgsPathResolver &pathResolver, bool saving ) override
188143
{
@@ -193,8 +148,6 @@ class CORE_EXPORT QgsLayoutItemMetadata : public QgsLayoutItemAbstractMetadata
193148
protected:
194149
QIcon mIcon;
195150
QgsLayoutItemCreateFunc mCreateFunc = nullptr;
196-
QgsLayoutItemWidgetFunc mWidgetFunc = nullptr;
197-
QgsLayoutItemRubberBandFunc mRubberBandFunc = nullptr;
198151
QgsLayoutItemPathResolverFunc mPathResolverFunc = nullptr;
199152

200153
};
@@ -211,6 +164,9 @@ class CORE_EXPORT QgsLayoutItemMetadata : public QgsLayoutItemAbstractMetadata
211164
* QgsLayoutItemRegistry is not usually directly created, but rather accessed through
212165
* QgsApplication::layoutItemRegistry().
213166
*
167+
* A companion class, QgsLayoutItemGuiRegistry, handles the GUI behavior
168+
* of layout items.
169+
*
214170
* \since QGIS 3.0
215171
*/
216172
class CORE_EXPORT QgsLayoutItemRegistry : public QObject
@@ -251,7 +207,7 @@ class CORE_EXPORT QgsLayoutItemRegistry : public QObject
251207

252208
//! QgsLayoutItemRegistry cannot be copied.
253209
QgsLayoutItemRegistry( const QgsLayoutItemRegistry &rh ) = delete;
254-
//! QgsLayoutItemRegistryQgsLayoutItemRegistry cannot be copied.
210+
//! QgsLayoutItemRegistry cannot be copied.
255211
QgsLayoutItemRegistry &operator=( const QgsLayoutItemRegistry &rh ) = delete;
256212

257213
/**
@@ -270,17 +226,6 @@ class CORE_EXPORT QgsLayoutItemRegistry : public QObject
270226
*/
271227
QgsLayoutItem *createItem( int type, QgsLayout *layout, const QVariantMap &properties = QVariantMap() ) const SIP_FACTORY;
272228

273-
/**
274-
* Creates a new instance of a layout item configuration widget for the specified item \a type.
275-
*/
276-
QWidget *createItemWidget( int type ) const SIP_FACTORY;
277-
278-
/**
279-
* Creates a new rubber band item for the specified item \a type and destination \a view.
280-
* \note not available from Python bindings
281-
*/
282-
QgsLayoutViewRubberBand *createItemRubberBand( int type, QgsLayoutView *view ) const SIP_SKIP;
283-
284229
/**
285230
* Resolve paths in properties of a particular symbol layer.
286231
* This normally means converting relative paths to absolute paths when loading
@@ -308,10 +253,6 @@ class CORE_EXPORT QgsLayoutItemRegistry : public QObject
308253

309254
QMap<int, QgsLayoutItemAbstractMetadata *> mMetadata;
310255

311-
QMap<int, QgsLayoutItemRubberBandFunc > mRubberBandFunctions;
312-
313-
friend class QgsLayoutItemRegistryGuiUtils;
314-
315256
};
316257

317258
#ifndef SIP_RUN

‎src/gui/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ SET(QGIS_GUI_SRCS
158158
layertree/qgslayertreeview.cpp
159159
layertree/qgslayertreeviewdefaultactions.cpp
160160

161-
layout/qgslayoutitemregistryguiutils.cpp
161+
layout/qgslayoutitemguiregistry.cpp
162162
layout/qgslayoutview.cpp
163163
layout/qgslayoutviewmouseevent.cpp
164164
layout/qgslayoutviewrubberband.cpp
@@ -633,6 +633,7 @@ SET(QGIS_GUI_MOC_HDRS
633633
layertree/qgslayertreeviewdefaultactions.h
634634

635635
layout/qgslayoutdesignerinterface.h
636+
layout/qgslayoutitemguiregistry.h
636637
layout/qgslayoutview.h
637638
layout/qgslayoutviewtool.h
638639
layout/qgslayoutviewtooladditem.h
@@ -735,7 +736,6 @@ SET(QGIS_GUI_HDRS
735736
layertree/qgslayertreeembeddedconfigwidget.h
736737
layertree/qgslayertreeembeddedwidgetregistry.h
737738

738-
layout/qgslayoutitemregistryguiutils.h
739739
layout/qgslayoutviewmouseevent.h
740740
layout/qgslayoutviewrubberband.h
741741

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/***************************************************************************
2+
qgslayoutitemregistry.cpp
3+
-------------------------
4+
begin : June 2017
5+
copyright : (C) 2017 by Nyall Dawson
6+
email : nyall dot dawson at gmail dot com
7+
***************************************************************************/
8+
/***************************************************************************
9+
* *
10+
* This program is free software; you can redistribute it and/or modify *
11+
* it under the terms of the GNU General Public License as published by *
12+
* the Free Software Foundation; either version 2 of the License, or *
13+
* (at your option) any later version. *
14+
* *
15+
***************************************************************************/
16+
17+
#include "qgslayoutitemguiregistry.h"
18+
#include "qgslayoutviewrubberband.h"
19+
#include <QPainter>
20+
21+
22+
QgsLayoutViewRubberBand *QgsLayoutItemAbstractGuiMetadata::createRubberBand( QgsLayoutView *view )
23+
{
24+
return new QgsLayoutViewRectangularRubberBand( view );
25+
}
26+
27+
28+
QgsLayoutItemGuiRegistry::QgsLayoutItemGuiRegistry( QObject *parent )
29+
: QObject( parent )
30+
{
31+
}
32+
33+
QgsLayoutItemGuiRegistry::~QgsLayoutItemGuiRegistry()
34+
{
35+
qDeleteAll( mMetadata );
36+
}
37+
38+
bool QgsLayoutItemGuiRegistry::populate()
39+
{
40+
if ( !mMetadata.isEmpty() )
41+
return false;
42+
43+
// add temporary item to register
44+
auto createRubberBand = ( []( QgsLayoutView * view )->QgsLayoutViewRubberBand *
45+
{
46+
return new QgsLayoutViewRectangularRubberBand( view );
47+
} );
48+
49+
addLayoutItemGuiMetadata( new QgsLayoutItemGuiMetadata( 101, QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddLabel.svg" ) ), nullptr, createRubberBand ) );
50+
return true;
51+
}
52+
53+
QgsLayoutItemAbstractGuiMetadata *QgsLayoutItemGuiRegistry::itemMetadata( int type ) const
54+
{
55+
return mMetadata.value( type );
56+
}
57+
58+
bool QgsLayoutItemGuiRegistry::addLayoutItemGuiMetadata( QgsLayoutItemAbstractGuiMetadata *metadata )
59+
{
60+
if ( !metadata || mMetadata.contains( metadata->type() ) )
61+
return false;
62+
63+
mMetadata[metadata->type()] = metadata;
64+
emit typeAdded( metadata->type() );
65+
return true;
66+
}
67+
68+
QWidget *QgsLayoutItemGuiRegistry::createItemWidget( int type ) const
69+
{
70+
if ( !mMetadata.contains( type ) )
71+
return nullptr;
72+
73+
return mMetadata[type]->createItemWidget();
74+
}
75+
76+
QgsLayoutViewRubberBand *QgsLayoutItemGuiRegistry::createItemRubberBand( int type, QgsLayoutView *view ) const
77+
{
78+
if ( !mMetadata.contains( type ) )
79+
return nullptr;
80+
81+
return mMetadata[type]->createRubberBand( view );
82+
}
83+
84+
QList<int> QgsLayoutItemGuiRegistry::itemTypes() const
85+
{
86+
return mMetadata.keys();
87+
}
Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
/***************************************************************************
2+
qgslayoutitemguiregistry.h
3+
--------------------------
4+
begin : June 2017
5+
copyright : (C) 2017 by Nyall Dawson
6+
email : nyall dot dawson at gmail dot com
7+
***************************************************************************/
8+
/***************************************************************************
9+
* *
10+
* This program is free software; you can redistribute it and/or modify *
11+
* it under the terms of the GNU General Public License as published by *
12+
* the Free Software Foundation; either version 2 of the License, or *
13+
* (at your option) any later version. *
14+
* *
15+
***************************************************************************/
16+
#ifndef QGSLAYOUTITEMGUIREGISTRY_H
17+
#define QGSLAYOUTITEMGUIREGISTRY_H
18+
19+
#include "qgis_gui.h"
20+
#include "qgis_sip.h"
21+
#include "qgsapplication.h"
22+
#include "qgspathresolver.h"
23+
#include <QGraphicsItem> //for QGraphicsItem::UserType
24+
#include <QIcon>
25+
#include <functional>
26+
27+
#include "qgslayoutitem.h" // temporary
28+
29+
class QgsLayout;
30+
class QgsLayoutView;
31+
class QgsLayoutItem;
32+
class QgsLayoutViewRubberBand;
33+
34+
/**
35+
* \ingroup gui
36+
* \brief Stores GUI metadata about one layout item class.
37+
*
38+
* This is a companion to QgsLayoutItemAbstractMetadata, storing only
39+
* the components related to the GUI behavior of a layout item.
40+
*
41+
* \note In C++ you can use QgsLayoutItemGuiMetadata convenience class.
42+
* \since QGIS 3.0
43+
*/
44+
class GUI_EXPORT QgsLayoutItemAbstractGuiMetadata
45+
{
46+
public:
47+
48+
/**
49+
* Constructor for QgsLayoutItemAbstractGuiMetadata with the specified class \a type.
50+
*/
51+
QgsLayoutItemAbstractGuiMetadata( int type )
52+
: mType( type )
53+
{}
54+
55+
virtual ~QgsLayoutItemAbstractGuiMetadata() = default;
56+
57+
/**
58+
* Returns the unique item type code for the layout item class.
59+
*/
60+
int type() const { return mType; }
61+
62+
/**
63+
* Returns an icon representing creation of the layout item type.
64+
*/
65+
virtual QIcon creationIcon() const { return QgsApplication::getThemeIcon( QStringLiteral( "/mActionAddBasicRectangle.svg" ) ); }
66+
67+
/**
68+
* Creates a configuration widget for layout items of this type. Can return nullptr if no configuration GUI is required.
69+
*/
70+
virtual QWidget *createItemWidget() SIP_FACTORY { return nullptr; }
71+
72+
/**
73+
* Creates a rubber band for use when creating layout items of this type. Can return nullptr if no rubber band
74+
* should be created. The default behavior is to create a rectangular rubber band.
75+
*/
76+
virtual QgsLayoutViewRubberBand *createRubberBand( QgsLayoutView *view ) SIP_FACTORY;
77+
78+
private:
79+
80+
int mType = -1;
81+
};
82+
83+
//! Layout item configuration widget creation function
84+
typedef std::function<QWidget *()> QgsLayoutItemWidgetFunc SIP_SKIP;
85+
86+
//! Layout rubber band creation function
87+
typedef std::function<QgsLayoutViewRubberBand *( QgsLayoutView * )> QgsLayoutItemRubberBandFunc SIP_SKIP;
88+
89+
#ifndef SIP_RUN
90+
91+
/**
92+
* \ingroup gui
93+
* Convenience metadata class that uses static functions to handle layout item GUI behavior.
94+
* \since QGIS 3.0
95+
* \note not available in Python bindings
96+
*/
97+
class CORE_EXPORT QgsLayoutItemGuiMetadata : public QgsLayoutItemAbstractGuiMetadata
98+
{
99+
public:
100+
101+
/**
102+
* Constructor for QgsLayoutItemGuiMetadata with the specified class \a type
103+
* and \a creationIcon, and function pointers for the various
104+
* configuration widget creation functions.
105+
*/
106+
QgsLayoutItemGuiMetadata( int type, const QIcon &creationIcon,
107+
QgsLayoutItemWidgetFunc pfWidget = nullptr,
108+
QgsLayoutItemRubberBandFunc pfRubberBand = nullptr )
109+
: QgsLayoutItemAbstractGuiMetadata( type )
110+
, mIcon( creationIcon )
111+
, mWidgetFunc( pfWidget )
112+
, mRubberBandFunc( pfRubberBand )
113+
{}
114+
115+
/**
116+
* Returns the classes' configuration widget creation function.
117+
* \see setWidgetFunction()
118+
*/
119+
QgsLayoutItemWidgetFunc widgetFunction() const { return mWidgetFunc; }
120+
121+
/**
122+
* Sets the classes' configuration widget creation \a function.
123+
* \see widgetFunction()
124+
*/
125+
void setWidgetFunction( QgsLayoutItemWidgetFunc function ) { mWidgetFunc = function; }
126+
127+
/**
128+
* Returns the classes' rubber band creation function.
129+
* \see setRubberBandCreationFunction()
130+
*/
131+
QgsLayoutItemRubberBandFunc rubberBandCreationFunction() const { return mRubberBandFunc; }
132+
133+
/**
134+
* Sets the classes' rubber band creation \a function.
135+
* \see rubberBandCreationFunction()
136+
*/
137+
void setRubberBandCreationFunction( QgsLayoutItemRubberBandFunc function ) { mRubberBandFunc = function; }
138+
139+
QIcon creationIcon() const override { return mIcon.isNull() ? QgsLayoutItemAbstractGuiMetadata::creationIcon() : mIcon; }
140+
QWidget *createItemWidget() override { return mWidgetFunc ? mWidgetFunc() : nullptr; }
141+
QgsLayoutViewRubberBand *createRubberBand( QgsLayoutView *view ) override { return mRubberBandFunc ? mRubberBandFunc( view ) : nullptr; }
142+
143+
protected:
144+
QIcon mIcon;
145+
QgsLayoutItemWidgetFunc mWidgetFunc = nullptr;
146+
QgsLayoutItemRubberBandFunc mRubberBandFunc = nullptr;
147+
148+
};
149+
150+
#endif
151+
152+
/**
153+
* \ingroup core
154+
* \class QgsLayoutItemGuiRegistry
155+
* \brief Registry of available layout item GUI behavior.
156+
*
157+
* QgsLayoutItemGuiRegistry is not usually directly created, but rather accessed through
158+
* QgsGui::layoutItemGuiRegistry().
159+
*
160+
* This acts as a companion to QgsLayoutItemRegistry, handling only
161+
* the components related to the GUI behavior of layout items.
162+
*
163+
* \since QGIS 3.0
164+
*/
165+
class CORE_EXPORT QgsLayoutItemGuiRegistry : public QObject
166+
{
167+
Q_OBJECT
168+
169+
public:
170+
171+
/**
172+
* Creates a new empty item GUI registry.
173+
*
174+
* QgsLayoutItemGuiRegistry is not usually directly created, but rather accessed through
175+
* QgsGui::layoutItemGuiRegistry().
176+
*
177+
* \see populate()
178+
*/
179+
QgsLayoutItemGuiRegistry( QObject *parent = nullptr );
180+
181+
~QgsLayoutItemGuiRegistry();
182+
183+
/**
184+
* Populates the registry with standard item types. If called on a non-empty registry
185+
* then this will have no effect and will return false.
186+
*/
187+
bool populate();
188+
189+
//! QgsLayoutItemGuiRegistry cannot be copied.
190+
QgsLayoutItemGuiRegistry( const QgsLayoutItemGuiRegistry &rh ) = delete;
191+
//! QgsLayoutItemGuiRegistry cannot be copied.
192+
QgsLayoutItemGuiRegistry &operator=( const QgsLayoutItemGuiRegistry &rh ) = delete;
193+
194+
/**
195+
* Returns the metadata for the specified item \a type. Returns nullptr if
196+
* a corresponding type was not found in the registry.
197+
*/
198+
QgsLayoutItemAbstractGuiMetadata *itemMetadata( int type ) const;
199+
200+
/**
201+
* Registers the gui metadata for a new layout item type. Takes ownership of the metadata instance.
202+
*/
203+
bool addLayoutItemGuiMetadata( QgsLayoutItemAbstractGuiMetadata *metadata SIP_TRANSFER );
204+
205+
/**
206+
* Creates a new instance of a layout item configuration widget for the specified item \a type.
207+
*/
208+
QWidget *createItemWidget( int type ) const SIP_FACTORY;
209+
210+
/**
211+
* Creates a new rubber band item for the specified item \a type and destination \a view.
212+
* \note not available from Python bindings
213+
*/
214+
QgsLayoutViewRubberBand *createItemRubberBand( int type, QgsLayoutView *view ) const SIP_SKIP;
215+
216+
/**
217+
* Returns a list of available item types handled by the registry.
218+
*/
219+
QList< int > itemTypes() const;
220+
221+
signals:
222+
223+
/**
224+
* Emitted whenever a new item type is added to the registry, with the specified
225+
* \a type.
226+
*/
227+
void typeAdded( int type );
228+
229+
private:
230+
#ifdef SIP_RUN
231+
QgsLayoutItemGuiRegistry( const QgsLayoutItemGuiRegistry &rh );
232+
#endif
233+
234+
QMap<int, QgsLayoutItemAbstractGuiMetadata *> mMetadata;
235+
236+
};
237+
238+
#endif //QGSLAYOUTITEMGUIREGISTRY_H
239+
240+
241+

‎src/gui/layout/qgslayoutitemregistryguiutils.cpp

Lines changed: 0 additions & 27 deletions
This file was deleted.

‎src/gui/layout/qgslayoutitemregistryguiutils.h

Lines changed: 0 additions & 50 deletions
This file was deleted.

‎src/gui/layout/qgslayoutviewtooladditem.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#include "qgslayoutviewmouseevent.h"
2323
#include "qgslogger.h"
2424
#include "qgslayoutviewrubberband.h"
25+
#include "qgsgui.h"
26+
#include "qgslayoutitemguiregistry.h"
2527
#include <QGraphicsRectItem>
2628
#include <QPen>
2729
#include <QBrush>
@@ -49,7 +51,7 @@ void QgsLayoutViewToolAddItem::layoutPressEvent( QgsLayoutViewMouseEvent *event
4951

5052
mDrawing = true;
5153
mMousePressStartPos = event->pos();
52-
mRubberBand.reset( QgsApplication::layoutItemRegistry()->createItemRubberBand( mItemType, view() ) );
54+
mRubberBand.reset( QgsGui::layoutItemGuiRegistry()->createItemRubberBand( mItemType, view() ) );
5355
if ( mRubberBand )
5456
{
5557
mRubberBand->start( event->layoutPoint(), event->modifiers() );

‎src/gui/qgsgui.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "qgslayertreeembeddedwidgetregistry.h"
2121
#include "qgsmaplayeractionregistry.h"
2222
#include "qgslayoutitemregistry.h"
23+
#include "qgslayoutitemguiregistry.h"
2324
#include "qgslayoutviewrubberband.h"
2425
#ifdef Q_OS_MACX
2526
#include "qgsmacnative.h"
@@ -59,8 +60,14 @@ QgsMapLayerActionRegistry *QgsGui::mapLayerActionRegistry()
5960
return instance()->mMapLayerActionRegistry;
6061
}
6162

63+
QgsLayoutItemGuiRegistry *QgsGui::layoutItemGuiRegistry()
64+
{
65+
return instance()->mLayoutItemGuiRegistry;
66+
}
67+
6268
QgsGui::~QgsGui()
6369
{
70+
delete mLayoutItemGuiRegistry;
6471
delete mLayerTreeEmbeddedWidgetRegistry;
6572
delete mEditorWidgetRegistry;
6673
delete mMapLayerActionRegistry;
@@ -80,13 +87,6 @@ QgsGui::QgsGui()
8087
mShortcutsManager = new QgsShortcutsManager();
8188
mLayerTreeEmbeddedWidgetRegistry = new QgsLayerTreeEmbeddedWidgetRegistry();
8289
mMapLayerActionRegistry = new QgsMapLayerActionRegistry();
83-
84-
85-
QgsLayoutItemAbstractMetadata *abstractMetadata = QgsApplication::layoutItemRegistry()->itemMetadata( 101 );
86-
QgsLayoutItemMetadata *metadata = dynamic_cast<QgsLayoutItemMetadata *>( abstractMetadata );
87-
metadata->setRubberBandCreationFunction( []( QgsLayoutView * view )->QgsLayoutViewRubberBand *
88-
{
89-
return new QgsLayoutViewRectangularRubberBand( view );
90-
} );
91-
90+
mLayoutItemGuiRegistry = new QgsLayoutItemGuiRegistry();
91+
mLayoutItemGuiRegistry->populate();
9292
}

‎src/gui/qgsgui.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class QgsShortcutsManager;
2626
class QgsLayerTreeEmbeddedWidgetRegistry;
2727
class QgsMapLayerActionRegistry;
2828
class QgsNative;
29+
class QgsLayoutItemGuiRegistry;
2930

3031
/**
3132
* \ingroup gui
@@ -75,6 +76,11 @@ class GUI_EXPORT QgsGui
7576
*/
7677
static QgsMapLayerActionRegistry *mapLayerActionRegistry();
7778

79+
/**
80+
* Returns the global layout item GUI registry, used for registering the GUI behavior of layout items.
81+
*/
82+
static QgsLayoutItemGuiRegistry *layoutItemGuiRegistry();
83+
7884
~QgsGui();
7985

8086
private:
@@ -86,6 +92,7 @@ class GUI_EXPORT QgsGui
8692
QgsShortcutsManager *mShortcutsManager = nullptr;
8793
QgsLayerTreeEmbeddedWidgetRegistry *mLayerTreeEmbeddedWidgetRegistry = nullptr;
8894
QgsMapLayerActionRegistry *mMapLayerActionRegistry = nullptr;
95+
QgsLayoutItemGuiRegistry *mLayoutItemGuiRegistry = nullptr;
8996

9097
#ifdef SIP_RUN
9198
QgsGui( const QgsGui &other );

‎tests/src/core/testqgslayoutitem.cpp

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -115,24 +115,19 @@ void TestQgsLayoutItem::registry()
115115
QVERIFY( !registry.itemMetadata( -1 ) );
116116
QVERIFY( registry.itemTypes().isEmpty() );
117117
QVERIFY( !registry.createItem( 1, nullptr ) );
118-
QVERIFY( !registry.createItemWidget( 1 ) );
119118

120119
auto create = []( QgsLayout * layout, const QVariantMap & )->QgsLayoutItem*
121120
{
122121
return new TestItem( layout );
123122
};
124-
auto createWidget = []()->QWidget*
125-
{
126-
return new QWidget();
127-
};
128123
auto resolve = []( QVariantMap & props, const QgsPathResolver &, bool )
129124
{
130125
props.clear();
131126
};
132127

133128
QSignalSpy spyTypeAdded( &registry, &QgsLayoutItemRegistry::typeAdded );
134129

135-
QgsLayoutItemMetadata *metadata = new QgsLayoutItemMetadata( 2, QStringLiteral( "my type" ), QIcon(), create, resolve, createWidget );
130+
QgsLayoutItemMetadata *metadata = new QgsLayoutItemMetadata( 2, QStringLiteral( "my type" ), QIcon(), create, resolve );
136131
QVERIFY( registry.addLayoutItemType( metadata ) );
137132
QCOMPARE( spyTypeAdded.count(), 1 );
138133
QCOMPARE( spyTypeAdded.value( 0 ).at( 0 ).toInt(), 2 );
@@ -150,9 +145,6 @@ void TestQgsLayoutItem::registry()
150145
QVERIFY( item );
151146
QVERIFY( dynamic_cast< TestItem *>( item ) );
152147
delete item;
153-
QWidget *config = registry.createItemWidget( 2 );
154-
QVERIFY( config );
155-
delete config;
156148
QVariantMap props;
157149
props.insert( QStringLiteral( "a" ), 5 );
158150
registry.resolvePaths( 1, props, QgsPathResolver(), true );

‎tests/src/gui/testqgslayoutview.cpp

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@
2020
#include "qgslayoutviewmouseevent.h"
2121
#include "qgslayoutitem.h"
2222
#include "qgslayoutviewrubberband.h"
23-
#include "qgslayoutitemregistryguiutils.h"
23+
#include "qgslayoutitemregistry.h"
24+
#include "qgslayoutitemguiregistry.h"
2425
#include "qgstestutils.h"
26+
#include "qgsgui.h"
2527
#include <QtTest/QSignalSpy>
2628

2729
class TestQgsLayoutView: public QObject
@@ -35,7 +37,7 @@ class TestQgsLayoutView: public QObject
3537
void basic();
3638
void tool();
3739
void events();
38-
void registryUtils();
40+
void guiRegistry();
3941
void rubberBand();
4042

4143
private:
@@ -246,38 +248,61 @@ QString mReport;
246248

247249
bool renderCheck( QString testName, QImage &image, int mismatchCount );
248250

249-
void TestQgsLayoutView::registryUtils()
251+
void TestQgsLayoutView::guiRegistry()
250252
{
253+
// test QgsLayoutItemGuiRegistry
254+
QgsLayoutItemGuiRegistry registry;
255+
256+
// empty registry
257+
QVERIFY( !registry.itemMetadata( -1 ) );
258+
QVERIFY( registry.itemTypes().isEmpty() );
259+
QVERIFY( !registry.createItemWidget( 1 ) );
260+
261+
QSignalSpy spyTypeAdded( &registry, &QgsLayoutItemGuiRegistry::typeAdded );
262+
251263
// add a dummy item to registry
252-
auto create = []( QgsLayout * layout, const QVariantMap & )->QgsLayoutItem*
264+
auto createWidget = []()->QWidget*
253265
{
254-
return new TestItem( layout );
266+
return new QWidget();
255267
};
256268

257269
auto createRubberBand = []( QgsLayoutView * view )->QgsLayoutViewRubberBand *
258270
{
259271
return new QgsLayoutViewRectangularRubberBand( view );
260272
};
261273

262-
QgsLayoutItemMetadata *metadata = new QgsLayoutItemMetadata( 2, QStringLiteral( "my type" ), QIcon(), create );
263-
metadata->setRubberBandCreationFunction( createRubberBand );
264-
QVERIFY( QgsApplication::layoutItemRegistry()->addLayoutItemType( metadata ) );
274+
QgsLayoutItemGuiMetadata *metadata = new QgsLayoutItemGuiMetadata( 2, QIcon(), createWidget, createRubberBand );
275+
QVERIFY( registry.addLayoutItemGuiMetadata( metadata ) );
276+
QCOMPARE( spyTypeAdded.count(), 1 );
277+
QCOMPARE( spyTypeAdded.value( 0 ).at( 0 ).toInt(), 2 );
278+
// duplicate type id
279+
QVERIFY( !registry.addLayoutItemGuiMetadata( metadata ) );
280+
QCOMPARE( spyTypeAdded.count(), 1 );
281+
282+
//retrieve metadata
283+
QVERIFY( !registry.itemMetadata( -1 ) );
284+
QVERIFY( registry.itemMetadata( 2 ) );
285+
QCOMPARE( registry.itemTypes().count(), 1 );
286+
QCOMPARE( registry.itemTypes().value( 0 ), 2 );
287+
288+
QWidget *widget = registry.createItemWidget( 2 );
289+
QVERIFY( widget );
290+
delete widget;
265291

266292
QgsLayoutView *view = new QgsLayoutView();
267293
//should use metadata's method
268-
QgsLayoutViewRubberBand *band = QgsApplication::layoutItemRegistry()->createItemRubberBand( 2, view );
294+
QgsLayoutViewRubberBand *band = registry.createItemRubberBand( 2, view );
269295
QVERIFY( band );
270296
QVERIFY( dynamic_cast< QgsLayoutViewRectangularRubberBand * >( band ) );
271297
QCOMPARE( band->view(), view );
272298
delete band;
273299

274-
//manually register a prototype
275-
QgsLayoutItemRegistryGuiUtils::setItemRubberBandPrototype( 2, new QgsLayoutViewEllipticalRubberBand() );
276-
band = QgsApplication::layoutItemRegistry()->createItemRubberBand( 2, view );
277-
QVERIFY( band );
278-
QVERIFY( dynamic_cast< QgsLayoutViewEllipticalRubberBand * >( band ) );
279-
QCOMPARE( band->view(), view );
280-
300+
//test populate
301+
QgsLayoutItemGuiRegistry reg2;
302+
QVERIFY( reg2.itemTypes().isEmpty() );
303+
QVERIFY( reg2.populate() );
304+
QVERIFY( !reg2.itemTypes().isEmpty() );
305+
QVERIFY( !reg2.populate() );
281306
}
282307

283308
void TestQgsLayoutView::rubberBand()

0 commit comments

Comments
 (0)
Please sign in to comment.