1 /***************************************************************************
2     testqgsannotationitemguiregistry.cpp
3      --------------------
4     Date                 : September 2021
5     Copyright            : (C) 2021 Nyall Dawson
6     Email                : nyall dot dawson at gmail dot com
7  ***************************************************************************
8  *                                                                         *
9  *   This program is free software; you can redistribute it and/or modify  *
10  *   it under the terms of the GNU General Public License as published by  *
11  *   the Free Software Foundation; either version 2 of the License, or     *
12  *   (at your option) any later version.                                   *
13  *                                                                         *
14  ***************************************************************************/
15 
16 #include "qgstest.h"
17 #include "qgsannotationitem.h"
18 #include "qgsannotationitemguiregistry.h"
19 #include "qgsannotationitemwidget.h"
20 #include "qgsapplication.h"
21 #include "qgsannotationitemregistry.h"
22 #include <QSignalSpy>
23 
24 class TestQgsAnnotationItemGuiRegistry: public QObject
25 {
26     Q_OBJECT
27   private slots:
28     void initTestCase(); // will be called before the first testfunction is executed.
29     void cleanupTestCase(); // will be called after the last testfunction was executed.
30     void init(); // will be called before each testfunction is executed.
31     void cleanup(); // will be called after every testfunction.
32     void guiRegistry();
33 
34   private:
35 
36 };
37 
initTestCase()38 void TestQgsAnnotationItemGuiRegistry::initTestCase()
39 {
40 
41 }
42 
cleanupTestCase()43 void TestQgsAnnotationItemGuiRegistry::cleanupTestCase()
44 {
45 }
46 
init()47 void TestQgsAnnotationItemGuiRegistry::init()
48 {
49 }
50 
cleanup()51 void TestQgsAnnotationItemGuiRegistry::cleanup()
52 {
53 }
54 
55 //simple item for testing, since some methods in QgsAnnotationItem are pure virtual
56 class TestItem : public QgsAnnotationItem // clazy:exclude=missing-qobject-macro
57 {
58   public:
59 
TestItem()60     TestItem() : QgsAnnotationItem() {}
61 
62     int mFlag = 0;
63 
64     //implement pure virtual methods
type() const65     QString type() const override { return QStringLiteral( "mytype" ); }
clone()66     TestItem *clone() override { return new TestItem(); }
boundingBox() const67     QgsRectangle boundingBox() const override { return QgsRectangle();}
render(QgsRenderContext &,QgsFeedback *)68     void render( QgsRenderContext &, QgsFeedback * ) override {}
writeXml(QDomElement &,QDomDocument &,const QgsReadWriteContext &) const69     bool writeXml( QDomElement &, QDomDocument &, const QgsReadWriteContext & ) const override { return true; }
readXml(const QDomElement &,const QgsReadWriteContext &)70     bool readXml( const QDomElement &, const QgsReadWriteContext & ) override { return true; }
71 };
72 
73 class TestItemWidget: public QgsAnnotationItemBaseWidget
74 {
75   public:
76 
TestItemWidget(QWidget * parent)77     TestItemWidget( QWidget *parent )
78       : QgsAnnotationItemBaseWidget( parent )
79     {}
80 
createItem()81     QgsAnnotationItem *createItem() override { return nullptr; }
updateItem(QgsAnnotationItem *)82     void updateItem( QgsAnnotationItem * ) override {}
83 
84 };
85 
guiRegistry()86 void TestQgsAnnotationItemGuiRegistry::guiRegistry()
87 {
88   // test QgsAnnotationItemGuiRegistry
89   QgsAnnotationItemGuiRegistry registry;
90 
91   // empty registry
92   QVERIFY( !registry.itemMetadata( -1 ) );
93   QVERIFY( registry.itemMetadataIds().isEmpty() );
94   QCOMPARE( registry.metadataIdForItemType( QString() ), -1 );
95   QVERIFY( !registry.createItemWidget( nullptr ) );
96   QVERIFY( !registry.createItemWidget( nullptr ) );
97   const std::unique_ptr< TestItem > testItem = std::make_unique< TestItem >();
98   QVERIFY( !registry.createItemWidget( testItem.get() ) ); // not in registry
99 
100   const QSignalSpy spyTypeAdded( &registry, &QgsAnnotationItemGuiRegistry::typeAdded );
101 
102   // add a dummy item to registry
103   auto createWidget = []( QgsAnnotationItem * )->QgsAnnotationItemBaseWidget *
104   {
105     return new TestItemWidget( nullptr );
106   };
107 
108   QgsAnnotationItemGuiMetadata *metadata = new QgsAnnotationItemGuiMetadata( QStringLiteral( "mytype" ), QStringLiteral( "My Type" ), QIcon(), createWidget );
109   QVERIFY( registry.addAnnotationItemGuiMetadata( metadata ) );
110   QCOMPARE( spyTypeAdded.count(), 1 );
111   int uuid = registry.itemMetadataIds().value( 0 );
112   QCOMPARE( spyTypeAdded.value( 0 ).at( 0 ).toInt(), uuid );
113   QCOMPARE( registry.metadataIdForItemType( QStringLiteral( "mytype" ) ), uuid );
114 
115   // duplicate type id is allowed
116   metadata = new QgsAnnotationItemGuiMetadata( QStringLiteral( "mytype" ), QStringLiteral( "My Type" ), QIcon(), createWidget );
117   QVERIFY( registry.addAnnotationItemGuiMetadata( metadata ) );
118   QCOMPARE( spyTypeAdded.count(), 2 );
119   //retrieve metadata
120   QVERIFY( !registry.itemMetadata( -1 ) );
121   QCOMPARE( registry.itemMetadataIds().count(), 2 );
122   QCOMPARE( registry.metadataIdForItemType( QStringLiteral( "mytype" ) ), uuid );
123 
124   QVERIFY( registry.itemMetadata( uuid ) );
125   QCOMPARE( registry.itemMetadata( uuid )->visibleName(), QStringLiteral( "My Type" ) );
126 
127   QWidget *widget = registry.createItemWidget( testItem.get() );
128   QVERIFY( widget );
129   delete widget;
130 
131   // groups
132   QVERIFY( registry.addItemGroup( QgsAnnotationItemGuiGroup( QStringLiteral( "g1" ) ) ) );
133   QCOMPARE( registry.itemGroup( QStringLiteral( "g1" ) ).id, QStringLiteral( "g1" ) );
134   // can't add duplicate group
135   QVERIFY( !registry.addItemGroup( QgsAnnotationItemGuiGroup( QStringLiteral( "g1" ) ) ) );
136 
137   //creating item
138   QgsAnnotationItem *item = registry.createItem( uuid );
139   QVERIFY( !item );
140   QgsApplication::annotationItemRegistry()->addItemType( new QgsAnnotationItemMetadata( QStringLiteral( "mytype" ), QStringLiteral( "My Type" ), QStringLiteral( "My Types" ), []( )->QgsAnnotationItem*
141   {
142     return new TestItem();
143   } ) );
144 
145   item = registry.createItem( uuid );
146   QVERIFY( item );
147   QCOMPARE( item->type(), QStringLiteral( "mytype" ) );
148   QCOMPARE( static_cast< TestItem * >( item )->mFlag, 0 );
149   delete item;
150 
151   // override create func
152   metadata = new QgsAnnotationItemGuiMetadata( QStringLiteral( "mytype" ), QStringLiteral( "mytype" ), QIcon(), createWidget );
153   metadata->setItemCreationFunction( []()->QgsAnnotationItem*
154   {
155     TestItem *item = new TestItem();
156     item->mFlag = 2;
157     return item;
158   } );
159   QVERIFY( registry.addAnnotationItemGuiMetadata( metadata ) );
160   uuid = spyTypeAdded.at( spyTypeAdded.count() - 1 ).at( 0 ).toInt();
161   item = registry.createItem( uuid );
162   QVERIFY( item );
163   QCOMPARE( item->type(), QStringLiteral( "mytype" ) );
164   QCOMPARE( static_cast< TestItem * >( item )->mFlag, 2 );
165   delete item;
166 }
167 
168 
169 QGSTEST_MAIN( TestQgsAnnotationItemGuiRegistry )
170 #include "testqgsannotationitemguiregistry.moc"
171