Create QgsHistoryEntryNode class

Used for representing information about of QgsHistoryEntry
in a hierarchical tree structure
This commit is contained in:
Nyall Dawson 2023-04-19 10:52:52 +10:00
parent aa7535ffab
commit dd25f39479
6 changed files with 447 additions and 1 deletions

View File

@ -0,0 +1,115 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/history/qgshistoryentrynode.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
class QgsHistoryEntryNode
{
%Docstring(signature="appended")
Base class for nodes representing a :py:class:`QgsHistoryEntry`.
.. versionadded:: 3.32
%End
%TypeHeaderCode
#include "qgshistoryentrynode.h"
%End
public:
QgsHistoryEntryNode();
virtual ~QgsHistoryEntryNode();
QgsHistoryEntryGroup *parent();
%Docstring
Returns the node's parent node.
If parent is ``None``, the node is a root node
%End
virtual QVariant data( int role = Qt::DisplayRole ) const = 0;
%Docstring
Returns the node's data for the specified model ``role``.
%End
virtual int childCount() const;
%Docstring
Returns the number of child nodes owned by this node.
%End
private:
QgsHistoryEntryNode( const QgsHistoryEntryNode &other );
};
class QgsHistoryEntryGroup : QgsHistoryEntryNode
{
%Docstring(signature="appended")
Base class for history entry "group" nodes, which contain children of their own.
.. versionadded:: 3.32
%End
%TypeHeaderCode
#include "qgshistoryentrynode.h"
%End
public:
QgsHistoryEntryGroup();
~QgsHistoryEntryGroup();
void addChild( QgsHistoryEntryNode *child /Transfer/ );
%Docstring
Adds a ``child`` node to this node.
Ownership is transferred to the group.
%End
int indexOf( QgsHistoryEntryNode *child ) const;
%Docstring
Returns the index of the specified ``child`` node.
.. warning::
``child`` must be a valid child of this node.
%End
QgsHistoryEntryNode *childAt( int index );
%Docstring
Returns the child at the specified ``index``.
%End
void removeChildAt( int index );
%Docstring
Removes the child at the specified ``index``.
%End
void clear();
%Docstring
Clears the group, removing all its children.
%End
virtual int childCount() const ${SIP_FINAL};
private:
QgsHistoryEntryGroup( const QgsHistoryEntryGroup &other );
};
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/history/qgshistoryentrynode.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/

View File

@ -342,6 +342,7 @@
%Include auto_generated/effects/qgspainteffectwidget.sip
%Include auto_generated/elevation/qgselevationprofilecanvas.sip
%Include auto_generated/history/qgshistoryentry.sip
%Include auto_generated/history/qgshistoryentrynode.sip
%Include auto_generated/history/qgshistoryprovider.sip
%Include auto_generated/history/qgshistoryproviderregistry.sip
%Include auto_generated/labeling/qgslabellineanchorwidget.sip

View File

@ -237,6 +237,7 @@ set(QGIS_GUI_SRCS
elevation/qgselevationprofilelayertreeview.cpp
history/qgshistoryentry.cpp
history/qgshistoryentrynode.cpp
history/qgshistoryprovider.cpp
history/qgshistoryproviderregistry.cpp
@ -1144,6 +1145,7 @@ set(QGIS_GUI_HDRS
elevation/qgselevationprofilelayertreeview.h
history/qgshistoryentry.h
history/qgshistoryentrynode.h
history/qgshistoryprovider.h
history/qgshistoryproviderregistry.h

View File

@ -0,0 +1,107 @@
/***************************************************************************
qgshistoryentrynode.cpp
--------------------------
begin : Aprial 2023
copyright : (C) 2023 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgshistoryentrynode.h"
//
// QgsHistoryEntryNode
//
QgsHistoryEntryNode::~QgsHistoryEntryNode() = default;
int QgsHistoryEntryNode::childCount() const
{
return 0;
}
#if 0
QString QgsHistoryEntryNode::html() const
{
return QString();
}
QWidget *QgsHistoryEntryNode::createWidget()
{
return nullptr;
}
QList<QAction *> QgsHistoryEntryNode::actions( QWidget * )
{
return {};
}
bool QgsHistoryEntryNode::matchesString( const QString & )
{
return false;
}
#endif
//
// QgsHistoryEntryGroup
//
QgsHistoryEntryGroup::~QgsHistoryEntryGroup() = default;
void QgsHistoryEntryGroup::addChild( QgsHistoryEntryNode *child )
{
if ( !child )
return;
Q_ASSERT( !child->mParent );
child->mParent = this;
mChildren.emplace_back( child );
}
int QgsHistoryEntryGroup::indexOf( QgsHistoryEntryNode *child ) const
{
if ( child->mParent != this )
return -1;
auto it = std::find_if( mChildren.begin(), mChildren.end(), [&]( const std::unique_ptr<QgsHistoryEntryNode> &p )
{
return p.get() == child;
} );
if ( it != mChildren.end() )
return std::distance( mChildren.begin(), it );
return -1;
}
QgsHistoryEntryNode *QgsHistoryEntryGroup::childAt( int index )
{
if ( static_cast< std::size_t >( index ) >= mChildren.size() )
return nullptr;
return mChildren[ index ].get();
}
void QgsHistoryEntryGroup::removeChildAt( int index )
{
if ( static_cast< std::size_t >( index ) >= mChildren.size() )
return;
mChildren.erase( mChildren.begin() + index );
}
void QgsHistoryEntryGroup::clear()
{
mChildren.clear();
}
int QgsHistoryEntryGroup::childCount() const
{
return mChildren.size();
}

View File

@ -0,0 +1,176 @@
/***************************************************************************
qgshistoryentrynode.h
--------------------------
begin : Aprial 2023
copyright : (C) 2023 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSHISTORYENTRYNODE_H
#define QGSHISTORYENTRYNODE_H
#include "qgis_gui.h"
#include "qgis_sip.h"
#include "qgis.h"
#include <QString>
#include <QVariantMap>
#include <memory>
#include <deque>
class QWidget;
class QAction;
class QgsHistoryEntryGroup;
/**
* Base class for nodes representing a QgsHistoryEntry.
*
* \ingroup gui
* \since QGIS 3.32
*/
class GUI_EXPORT QgsHistoryEntryNode
{
public:
/**
* Constructor for QgsHistoryEntryNode.
*/
QgsHistoryEntryNode() = default;
virtual ~QgsHistoryEntryNode();
//! QgsHistoryEntryNode cannot be copied
QgsHistoryEntryNode( const QgsHistoryEntryNode &other ) = delete;
//! QgsHistoryEntryNode cannot be copied
QgsHistoryEntryNode &operator=( const QgsHistoryEntryNode &other ) = delete;
/**
* Returns the node's parent node.
*
* If parent is NULLPTR, the node is a root node.
*/
QgsHistoryEntryGroup *parent() { return mParent; }
/**
* Returns the node's data for the specified model \a role.
*/
virtual QVariant data( int role = Qt::DisplayRole ) const = 0;
/**
* Returns the number of child nodes owned by this node.
*/
virtual int childCount() const;
#if 0 // currently unused
/**
* Returns a HTML formatted text string which should be shown to a user when
* selecting the node.
*
* Subclasses should implement this method or createWidget(), but not both.
*/
virtual QString html() const;
/**
* Returns a new widget which should be shown to users when selecting the node.
*
* If a NULLPTR is returned, the node's html() method will be called instead to
* create the node's content.
*/
virtual QWidget *createWidget() SIP_FACTORY;
/**
* Returns a list of actions which users can trigger to interact with the history
* entry. Buttons corresponding to each action will be automatically created and
* shown to users.
*
* Actions should be parented to the specified \a parent widget.
*/
virtual QList< QAction * > actions( QWidget *parent );
/**
* Returns true if the node matches the specified \a searchString, and
* should be shown in filtered results with that search string.
*/
virtual bool matchesString( const QString &searchString );
#endif
private:
#ifdef SIP_RUN
QgsHistoryEntryNode( const QgsHistoryEntryNode &other );
#endif
QgsHistoryEntryGroup *mParent = nullptr;
friend class QgsHistoryEntryGroup;
};
/**
* \ingroup gui
* \class QgsHistoryEntryGroup
* \brief Base class for history entry "group" nodes, which contain children of their own.
* \since QGIS 3.32
*/
class GUI_EXPORT QgsHistoryEntryGroup : public QgsHistoryEntryNode
{
public:
//! Constructor for QgsHistoryEntryGroup
QgsHistoryEntryGroup() = default;
~QgsHistoryEntryGroup() override;
//! QgsHistoryEntryGroup cannot be copied
QgsHistoryEntryGroup( const QgsHistoryEntryGroup &other ) = delete;
//! QgsHistoryEntryGroup cannot be copied
QgsHistoryEntryGroup &operator=( const QgsHistoryEntryGroup &other ) = delete;
/**
* Adds a \a child node to this node.
*
* Ownership is transferred to the group.
*/
void addChild( QgsHistoryEntryNode *child SIP_TRANSFER );
/**
* Returns the index of the specified \a child node.
*
* \warning \a child must be a valid child of this node.
*/
int indexOf( QgsHistoryEntryNode *child ) const;
/**
* Returns the child at the specified \a index.
*/
QgsHistoryEntryNode *childAt( int index );
/**
* Removes the child at the specified \a index.
*/
void removeChildAt( int index );
/**
* Clears the group, removing all its children.
*/
void clear();
int childCount() const FINAL;
private:
#ifdef SIP_RUN
QgsHistoryEntryGroup( const QgsHistoryEntryGroup &other );
#endif
std::deque< std::unique_ptr< QgsHistoryEntryNode > > mChildren SIP_SKIP;
};
#endif // QGSHISTORYENTRYNODE_H

View File

@ -19,7 +19,9 @@ from qgis.gui import (
QgsAbstractHistoryProvider,
QgsHistoryEntry,
QgsHistoryProviderRegistry,
QgsGui
QgsGui,
QgsHistoryEntryNode,
QgsHistoryEntryGroup
)
from qgis.testing import start_app, unittest
@ -38,6 +40,18 @@ class TestHistoryProvider2(QgsAbstractHistoryProvider):
return 'test_provider2'
class TestNode(QgsHistoryEntryNode):
def data(self, role):
return 'test'
class TestGroup(QgsHistoryEntryGroup):
def data(self, role):
return 'test'
class TestQgsHistoryProviderRegistry(unittest.TestCase):
@classmethod
@ -240,6 +254,37 @@ class TestQgsHistoryProviderRegistry(unittest.TestCase):
self.assertEqual(reg.queryEntries()[1].id, 2)
self.assertEqual(reg.queryEntries()[1].entry, {'var': 8})
def test_nodes(self):
node = TestNode()
self.assertEqual(node.childCount(), 0)
self.assertFalse(node.parent())
group = TestGroup()
self.assertEqual(group.childCount(), 0)
self.assertFalse(group.parent())
self.assertFalse(group.childAt(0))
self.assertEqual(group.indexOf(node), -1)
group.addChild(node)
self.assertEqual(group.childCount(), 1)
self.assertFalse(group.parent())
self.assertEqual(node.parent(), group)
self.assertEqual(group.childAt(0), node)
self.assertEqual(group.indexOf(node), 0)
node2 = TestNode()
group.addChild(node2)
self.assertEqual(group.childCount(), 2)
self.assertFalse(group.parent())
self.assertEqual(node2.parent(), group)
self.assertEqual(group.childAt(0), node)
self.assertEqual(group.childAt(1), node2)
self.assertEqual(group.indexOf(node), 0)
self.assertEqual(group.indexOf(node2), 1)
group.clear()
self.assertEqual(group.childCount(), 0)
if __name__ == '__main__':
unittest.main()