Skip to content

Commit dd25f39

Browse files
committedApr 22, 2023
Create QgsHistoryEntryNode class
Used for representing information about of QgsHistoryEntry in a hierarchical tree structure
1 parent aa7535f commit dd25f39

File tree

6 files changed

+447
-1
lines changed

6 files changed

+447
-1
lines changed
 
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/************************************************************************
2+
* This file has been generated automatically from *
3+
* *
4+
* src/gui/history/qgshistoryentrynode.h *
5+
* *
6+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
7+
************************************************************************/
8+
9+
10+
11+
12+
class QgsHistoryEntryNode
13+
{
14+
%Docstring(signature="appended")
15+
Base class for nodes representing a :py:class:`QgsHistoryEntry`.
16+
17+
.. versionadded:: 3.32
18+
%End
19+
20+
%TypeHeaderCode
21+
#include "qgshistoryentrynode.h"
22+
%End
23+
public:
24+
25+
QgsHistoryEntryNode();
26+
virtual ~QgsHistoryEntryNode();
27+
28+
29+
QgsHistoryEntryGroup *parent();
30+
%Docstring
31+
Returns the node's parent node.
32+
33+
If parent is ``None``, the node is a root node
34+
%End
35+
36+
virtual QVariant data( int role = Qt::DisplayRole ) const = 0;
37+
%Docstring
38+
Returns the node's data for the specified model ``role``.
39+
%End
40+
41+
virtual int childCount() const;
42+
%Docstring
43+
Returns the number of child nodes owned by this node.
44+
%End
45+
46+
47+
private:
48+
QgsHistoryEntryNode( const QgsHistoryEntryNode &other );
49+
};
50+
51+
52+
class QgsHistoryEntryGroup : QgsHistoryEntryNode
53+
{
54+
%Docstring(signature="appended")
55+
Base class for history entry "group" nodes, which contain children of their own.
56+
57+
.. versionadded:: 3.32
58+
%End
59+
60+
%TypeHeaderCode
61+
#include "qgshistoryentrynode.h"
62+
%End
63+
public:
64+
65+
QgsHistoryEntryGroup();
66+
~QgsHistoryEntryGroup();
67+
68+
void addChild( QgsHistoryEntryNode *child /Transfer/ );
69+
%Docstring
70+
Adds a ``child`` node to this node.
71+
72+
Ownership is transferred to the group.
73+
%End
74+
75+
int indexOf( QgsHistoryEntryNode *child ) const;
76+
%Docstring
77+
Returns the index of the specified ``child`` node.
78+
79+
.. warning::
80+
81+
``child`` must be a valid child of this node.
82+
%End
83+
84+
QgsHistoryEntryNode *childAt( int index );
85+
%Docstring
86+
Returns the child at the specified ``index``.
87+
%End
88+
89+
void removeChildAt( int index );
90+
%Docstring
91+
Removes the child at the specified ``index``.
92+
%End
93+
94+
void clear();
95+
%Docstring
96+
Clears the group, removing all its children.
97+
%End
98+
99+
virtual int childCount() const ${SIP_FINAL};
100+
101+
102+
private:
103+
QgsHistoryEntryGroup( const QgsHistoryEntryGroup &other );
104+
};
105+
106+
107+
108+
109+
/************************************************************************
110+
* This file has been generated automatically from *
111+
* *
112+
* src/gui/history/qgshistoryentrynode.h *
113+
* *
114+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
115+
************************************************************************/

‎python/gui/gui_auto.sip

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,7 @@
342342
%Include auto_generated/effects/qgspainteffectwidget.sip
343343
%Include auto_generated/elevation/qgselevationprofilecanvas.sip
344344
%Include auto_generated/history/qgshistoryentry.sip
345+
%Include auto_generated/history/qgshistoryentrynode.sip
345346
%Include auto_generated/history/qgshistoryprovider.sip
346347
%Include auto_generated/history/qgshistoryproviderregistry.sip
347348
%Include auto_generated/labeling/qgslabellineanchorwidget.sip

‎src/gui/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ set(QGIS_GUI_SRCS
237237
elevation/qgselevationprofilelayertreeview.cpp
238238

239239
history/qgshistoryentry.cpp
240+
history/qgshistoryentrynode.cpp
240241
history/qgshistoryprovider.cpp
241242
history/qgshistoryproviderregistry.cpp
242243

@@ -1144,6 +1145,7 @@ set(QGIS_GUI_HDRS
11441145
elevation/qgselevationprofilelayertreeview.h
11451146

11461147
history/qgshistoryentry.h
1148+
history/qgshistoryentrynode.h
11471149
history/qgshistoryprovider.h
11481150
history/qgshistoryproviderregistry.h
11491151

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/***************************************************************************
2+
qgshistoryentrynode.cpp
3+
--------------------------
4+
begin : Aprial 2023
5+
copyright : (C) 2023 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+
#include "qgshistoryentrynode.h"
17+
18+
//
19+
// QgsHistoryEntryNode
20+
//
21+
22+
QgsHistoryEntryNode::~QgsHistoryEntryNode() = default;
23+
24+
int QgsHistoryEntryNode::childCount() const
25+
{
26+
return 0;
27+
}
28+
29+
#if 0
30+
QString QgsHistoryEntryNode::html() const
31+
{
32+
return QString();
33+
}
34+
35+
QWidget *QgsHistoryEntryNode::createWidget()
36+
{
37+
return nullptr;
38+
}
39+
40+
QList<QAction *> QgsHistoryEntryNode::actions( QWidget * )
41+
{
42+
return {};
43+
}
44+
45+
bool QgsHistoryEntryNode::matchesString( const QString & )
46+
{
47+
return false;
48+
}
49+
#endif
50+
51+
//
52+
// QgsHistoryEntryGroup
53+
//
54+
55+
QgsHistoryEntryGroup::~QgsHistoryEntryGroup() = default;
56+
57+
void QgsHistoryEntryGroup::addChild( QgsHistoryEntryNode *child )
58+
{
59+
if ( !child )
60+
return;
61+
62+
Q_ASSERT( !child->mParent );
63+
child->mParent = this;
64+
65+
mChildren.emplace_back( child );
66+
}
67+
68+
int QgsHistoryEntryGroup::indexOf( QgsHistoryEntryNode *child ) const
69+
{
70+
if ( child->mParent != this )
71+
return -1;
72+
73+
auto it = std::find_if( mChildren.begin(), mChildren.end(), [&]( const std::unique_ptr<QgsHistoryEntryNode> &p )
74+
{
75+
return p.get() == child;
76+
} );
77+
if ( it != mChildren.end() )
78+
return std::distance( mChildren.begin(), it );
79+
return -1;
80+
}
81+
82+
QgsHistoryEntryNode *QgsHistoryEntryGroup::childAt( int index )
83+
{
84+
if ( static_cast< std::size_t >( index ) >= mChildren.size() )
85+
return nullptr;
86+
87+
return mChildren[ index ].get();
88+
89+
}
90+
91+
void QgsHistoryEntryGroup::removeChildAt( int index )
92+
{
93+
if ( static_cast< std::size_t >( index ) >= mChildren.size() )
94+
return;
95+
96+
mChildren.erase( mChildren.begin() + index );
97+
}
98+
99+
void QgsHistoryEntryGroup::clear()
100+
{
101+
mChildren.clear();
102+
}
103+
104+
int QgsHistoryEntryGroup::childCount() const
105+
{
106+
return mChildren.size();
107+
}

‎src/gui/history/qgshistoryentrynode.h

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
/***************************************************************************
2+
qgshistoryentrynode.h
3+
--------------------------
4+
begin : Aprial 2023
5+
copyright : (C) 2023 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 QGSHISTORYENTRYNODE_H
17+
#define QGSHISTORYENTRYNODE_H
18+
19+
#include "qgis_gui.h"
20+
#include "qgis_sip.h"
21+
#include "qgis.h"
22+
#include <QString>
23+
#include <QVariantMap>
24+
#include <memory>
25+
#include <deque>
26+
27+
class QWidget;
28+
class QAction;
29+
class QgsHistoryEntryGroup;
30+
31+
/**
32+
* Base class for nodes representing a QgsHistoryEntry.
33+
*
34+
* \ingroup gui
35+
* \since QGIS 3.32
36+
*/
37+
class GUI_EXPORT QgsHistoryEntryNode
38+
{
39+
public:
40+
41+
/**
42+
* Constructor for QgsHistoryEntryNode.
43+
*/
44+
QgsHistoryEntryNode() = default;
45+
virtual ~QgsHistoryEntryNode();
46+
47+
//! QgsHistoryEntryNode cannot be copied
48+
QgsHistoryEntryNode( const QgsHistoryEntryNode &other ) = delete;
49+
//! QgsHistoryEntryNode cannot be copied
50+
QgsHistoryEntryNode &operator=( const QgsHistoryEntryNode &other ) = delete;
51+
52+
/**
53+
* Returns the node's parent node.
54+
*
55+
* If parent is NULLPTR, the node is a root node.
56+
*/
57+
QgsHistoryEntryGroup *parent() { return mParent; }
58+
59+
/**
60+
* Returns the node's data for the specified model \a role.
61+
*/
62+
virtual QVariant data( int role = Qt::DisplayRole ) const = 0;
63+
64+
/**
65+
* Returns the number of child nodes owned by this node.
66+
*/
67+
virtual int childCount() const;
68+
69+
#if 0 // currently unused
70+
/**
71+
* Returns a HTML formatted text string which should be shown to a user when
72+
* selecting the node.
73+
*
74+
* Subclasses should implement this method or createWidget(), but not both.
75+
*/
76+
virtual QString html() const;
77+
78+
/**
79+
* Returns a new widget which should be shown to users when selecting the node.
80+
*
81+
* If a NULLPTR is returned, the node's html() method will be called instead to
82+
* create the node's content.
83+
*/
84+
virtual QWidget *createWidget() SIP_FACTORY;
85+
86+
/**
87+
* Returns a list of actions which users can trigger to interact with the history
88+
* entry. Buttons corresponding to each action will be automatically created and
89+
* shown to users.
90+
*
91+
* Actions should be parented to the specified \a parent widget.
92+
*/
93+
virtual QList< QAction * > actions( QWidget *parent );
94+
95+
/**
96+
* Returns true if the node matches the specified \a searchString, and
97+
* should be shown in filtered results with that search string.
98+
*/
99+
virtual bool matchesString( const QString &searchString );
100+
#endif
101+
102+
private:
103+
#ifdef SIP_RUN
104+
QgsHistoryEntryNode( const QgsHistoryEntryNode &other );
105+
#endif
106+
107+
QgsHistoryEntryGroup *mParent = nullptr;
108+
109+
friend class QgsHistoryEntryGroup;
110+
111+
};
112+
113+
114+
/**
115+
* \ingroup gui
116+
* \class QgsHistoryEntryGroup
117+
* \brief Base class for history entry "group" nodes, which contain children of their own.
118+
* \since QGIS 3.32
119+
*/
120+
class GUI_EXPORT QgsHistoryEntryGroup : public QgsHistoryEntryNode
121+
{
122+
public:
123+
124+
//! Constructor for QgsHistoryEntryGroup
125+
QgsHistoryEntryGroup() = default;
126+
~QgsHistoryEntryGroup() override;
127+
128+
//! QgsHistoryEntryGroup cannot be copied
129+
QgsHistoryEntryGroup( const QgsHistoryEntryGroup &other ) = delete;
130+
//! QgsHistoryEntryGroup cannot be copied
131+
QgsHistoryEntryGroup &operator=( const QgsHistoryEntryGroup &other ) = delete;
132+
133+
/**
134+
* Adds a \a child node to this node.
135+
*
136+
* Ownership is transferred to the group.
137+
*/
138+
void addChild( QgsHistoryEntryNode *child SIP_TRANSFER );
139+
140+
/**
141+
* Returns the index of the specified \a child node.
142+
*
143+
* \warning \a child must be a valid child of this node.
144+
*/
145+
int indexOf( QgsHistoryEntryNode *child ) const;
146+
147+
/**
148+
* Returns the child at the specified \a index.
149+
*/
150+
QgsHistoryEntryNode *childAt( int index );
151+
152+
/**
153+
* Removes the child at the specified \a index.
154+
*/
155+
void removeChildAt( int index );
156+
157+
/**
158+
* Clears the group, removing all its children.
159+
*/
160+
void clear();
161+
162+
int childCount() const FINAL;
163+
164+
private:
165+
#ifdef SIP_RUN
166+
QgsHistoryEntryGroup( const QgsHistoryEntryGroup &other );
167+
#endif
168+
169+
std::deque< std::unique_ptr< QgsHistoryEntryNode > > mChildren SIP_SKIP;
170+
171+
};
172+
173+
#endif // QGSHISTORYENTRYNODE_H
174+
175+
176+

‎tests/src/python/test_qgshistoryproviderregistry.py

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919
QgsAbstractHistoryProvider,
2020
QgsHistoryEntry,
2121
QgsHistoryProviderRegistry,
22-
QgsGui
22+
QgsGui,
23+
QgsHistoryEntryNode,
24+
QgsHistoryEntryGroup
2325
)
2426
from qgis.testing import start_app, unittest
2527

@@ -38,6 +40,18 @@ def id(self) -> str:
3840
return 'test_provider2'
3941

4042

43+
class TestNode(QgsHistoryEntryNode):
44+
45+
def data(self, role):
46+
return 'test'
47+
48+
49+
class TestGroup(QgsHistoryEntryGroup):
50+
51+
def data(self, role):
52+
return 'test'
53+
54+
4155
class TestQgsHistoryProviderRegistry(unittest.TestCase):
4256

4357
@classmethod
@@ -240,6 +254,37 @@ def test_registry_entries(self):
240254
self.assertEqual(reg.queryEntries()[1].id, 2)
241255
self.assertEqual(reg.queryEntries()[1].entry, {'var': 8})
242256

257+
def test_nodes(self):
258+
node = TestNode()
259+
self.assertEqual(node.childCount(), 0)
260+
self.assertFalse(node.parent())
261+
262+
group = TestGroup()
263+
self.assertEqual(group.childCount(), 0)
264+
self.assertFalse(group.parent())
265+
self.assertFalse(group.childAt(0))
266+
self.assertEqual(group.indexOf(node), -1)
267+
268+
group.addChild(node)
269+
self.assertEqual(group.childCount(), 1)
270+
self.assertFalse(group.parent())
271+
self.assertEqual(node.parent(), group)
272+
self.assertEqual(group.childAt(0), node)
273+
self.assertEqual(group.indexOf(node), 0)
274+
275+
node2 = TestNode()
276+
group.addChild(node2)
277+
self.assertEqual(group.childCount(), 2)
278+
self.assertFalse(group.parent())
279+
self.assertEqual(node2.parent(), group)
280+
self.assertEqual(group.childAt(0), node)
281+
self.assertEqual(group.childAt(1), node2)
282+
self.assertEqual(group.indexOf(node), 0)
283+
self.assertEqual(group.indexOf(node2), 1)
284+
285+
group.clear()
286+
self.assertEqual(group.childCount(), 0)
287+
243288

244289
if __name__ == '__main__':
245290
unittest.main()

0 commit comments

Comments
 (0)
Please sign in to comment.