mirror of
				https://github.com/qgis/QGIS.git
				synced 2025-11-04 00:04:25 -05:00 
			
		
		
		
	Merge pull request #4943 from nyalldawson/exp_layer_rel
Add items for project map layers and relations to expression builder
This commit is contained in:
		
						commit
						0328b7af48
					
				@ -236,6 +236,30 @@ Sets the expression string for the widget
 | 
			
		||||
 Update the list of function files found at the given path
 | 
			
		||||
%End
 | 
			
		||||
 | 
			
		||||
    QStandardItemModel *model();
 | 
			
		||||
%Docstring
 | 
			
		||||
 Returns a pointer to the dialog's function item model.
 | 
			
		||||
 This method is exposed for testing purposes only - it should not be used to modify the model.
 | 
			
		||||
.. versionadded:: 3.0
 | 
			
		||||
 :rtype: QStandardItemModel
 | 
			
		||||
%End
 | 
			
		||||
 | 
			
		||||
    QgsProject *project();
 | 
			
		||||
%Docstring
 | 
			
		||||
 Returns the project currently associated with the widget.
 | 
			
		||||
.. seealso:: setProject()
 | 
			
		||||
.. versionadded:: 3.0
 | 
			
		||||
 :rtype: QgsProject
 | 
			
		||||
%End
 | 
			
		||||
 | 
			
		||||
    void setProject( QgsProject *project );
 | 
			
		||||
%Docstring
 | 
			
		||||
 Sets the ``project`` currently associated with the widget. This
 | 
			
		||||
 controls which layers and relations and other project-specific items are shown in the widget.
 | 
			
		||||
.. seealso:: project()
 | 
			
		||||
.. versionadded:: 3.0
 | 
			
		||||
%End
 | 
			
		||||
 | 
			
		||||
  public slots:
 | 
			
		||||
 | 
			
		||||
    void loadSampleValues();
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										5
									
								
								resources/function_help/json/Map Layers
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								resources/function_help/json/Map Layers
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "Map Layers",
 | 
			
		||||
  "type": "group",
 | 
			
		||||
  "description": "Contains a list of map layers available in the current project."
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										5
									
								
								resources/function_help/json/Relations
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								resources/function_help/json/Relations
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "Relations",
 | 
			
		||||
  "type": "group",
 | 
			
		||||
  "description": "Contains a list of relations available in the current project."
 | 
			
		||||
}
 | 
			
		||||
@ -25,6 +25,9 @@
 | 
			
		||||
#include "qgsfeatureiterator.h"
 | 
			
		||||
#include "qgsvectorlayer.h"
 | 
			
		||||
#include "qgssettings.h"
 | 
			
		||||
#include "qgsproject.h"
 | 
			
		||||
#include "qgsrelationmanager.h"
 | 
			
		||||
#include "qgsrelation.h"
 | 
			
		||||
 | 
			
		||||
#include <QMenu>
 | 
			
		||||
#include <QFile>
 | 
			
		||||
@ -42,6 +45,7 @@ QgsExpressionBuilderWidget::QgsExpressionBuilderWidget( QWidget *parent )
 | 
			
		||||
  , mLayer( nullptr )
 | 
			
		||||
  , highlighter( nullptr )
 | 
			
		||||
  , mExpressionValid( false )
 | 
			
		||||
  , mProject( QgsProject::instance() )
 | 
			
		||||
{
 | 
			
		||||
  setupUi( this );
 | 
			
		||||
 | 
			
		||||
@ -440,6 +444,32 @@ void QgsExpressionBuilderWidget::loadRecent( const QString &collection )
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void QgsExpressionBuilderWidget::loadLayers()
 | 
			
		||||
{
 | 
			
		||||
  if ( !mProject )
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  QMap<QString, QgsMapLayer *> layers = mProject->mapLayers();
 | 
			
		||||
  QMap<QString, QgsMapLayer *>::const_iterator layerIt = layers.constBegin();
 | 
			
		||||
  for ( ; layerIt != layers.constEnd(); ++layerIt )
 | 
			
		||||
  {
 | 
			
		||||
    registerItemForAllGroups( QStringList() << tr( "Map Layers" ), layerIt.value()->name(), QStringLiteral( "'%1'" ).arg( layerIt.key() ), formatLayerHelp( layerIt.value() ) );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void QgsExpressionBuilderWidget::loadRelations()
 | 
			
		||||
{
 | 
			
		||||
  if ( !mProject )
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  QMap<QString, QgsRelation> relations = mProject->relationManager()->relations();
 | 
			
		||||
  QMap<QString, QgsRelation>::const_iterator relIt = relations.constBegin();
 | 
			
		||||
  for ( ; relIt != relations.constEnd(); ++relIt )
 | 
			
		||||
  {
 | 
			
		||||
    registerItemForAllGroups( QStringList() << tr( "Relations" ), relIt->name(), QStringLiteral( "'%1'" ).arg( relIt->id() ), formatRelationHelp( relIt.value() ) );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void QgsExpressionBuilderWidget::updateFunctionTree()
 | 
			
		||||
{
 | 
			
		||||
  mModel->clear();
 | 
			
		||||
@ -495,6 +525,12 @@ void QgsExpressionBuilderWidget::updateFunctionTree()
 | 
			
		||||
    registerItemForAllGroups( func->groups(), func->name(), ' ' + name + ' ', func->helpText() );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // load relation names
 | 
			
		||||
  loadRelations();
 | 
			
		||||
 | 
			
		||||
  // load layer IDs
 | 
			
		||||
  loadLayers();
 | 
			
		||||
 | 
			
		||||
  loadExpressionContext();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -614,6 +650,36 @@ void QgsExpressionBuilderWidget::registerItemForAllGroups( const QStringList &gr
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString QgsExpressionBuilderWidget::formatRelationHelp( const QgsRelation &relation ) const
 | 
			
		||||
{
 | 
			
		||||
  QString text = QStringLiteral( "<p>%1</p>" ).arg( tr( "Inserts the relation ID for the relation named '%1'." ).arg( relation.name() ) );
 | 
			
		||||
  text.append( QStringLiteral( "<p>%1</p>" ).arg( tr( "Current value: '%1'" ).arg( relation.id() ) ) );
 | 
			
		||||
  return text;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString QgsExpressionBuilderWidget::formatLayerHelp( const QgsMapLayer *layer ) const
 | 
			
		||||
{
 | 
			
		||||
  QString text = QStringLiteral( "<p>%1</p>" ).arg( tr( "Inserts the layer ID for the layer named '%1'." ).arg( layer->name() ) );
 | 
			
		||||
  text.append( QStringLiteral( "<p>%1</p>" ).arg( tr( "Current value: '%1'" ).arg( layer->id() ) ) );
 | 
			
		||||
  return text;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QStandardItemModel *QgsExpressionBuilderWidget::model()
 | 
			
		||||
{
 | 
			
		||||
  return mModel;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QgsProject *QgsExpressionBuilderWidget::project()
 | 
			
		||||
{
 | 
			
		||||
  return mProject;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void QgsExpressionBuilderWidget::setProject( QgsProject *project )
 | 
			
		||||
{
 | 
			
		||||
  mProject = project;
 | 
			
		||||
  updateFunctionTree();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void QgsExpressionBuilderWidget::showEvent( QShowEvent *e )
 | 
			
		||||
{
 | 
			
		||||
  QWidget::showEvent( e );
 | 
			
		||||
 | 
			
		||||
@ -31,6 +31,7 @@
 | 
			
		||||
 | 
			
		||||
class QgsFields;
 | 
			
		||||
class QgsExpressionHighlighter;
 | 
			
		||||
class QgsRelation;
 | 
			
		||||
 | 
			
		||||
/** \ingroup gui
 | 
			
		||||
 * An expression item that can be used in the QgsExpressionBuilderWidget tree.
 | 
			
		||||
@ -225,6 +226,28 @@ class GUI_EXPORT QgsExpressionBuilderWidget : public QWidget, private Ui::QgsExp
 | 
			
		||||
     */
 | 
			
		||||
    void updateFunctionFileList( const QString &path );
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns a pointer to the dialog's function item model.
 | 
			
		||||
     * This method is exposed for testing purposes only - it should not be used to modify the model.
 | 
			
		||||
     * \since QGIS 3.0
 | 
			
		||||
     */
 | 
			
		||||
    QStandardItemModel *model();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the project currently associated with the widget.
 | 
			
		||||
     * \see setProject()
 | 
			
		||||
     * \since QGIS 3.0
 | 
			
		||||
     */
 | 
			
		||||
    QgsProject *project();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the \a project currently associated with the widget. This
 | 
			
		||||
     * controls which layers and relations and other project-specific items are shown in the widget.
 | 
			
		||||
     * \see project()
 | 
			
		||||
     * \since QGIS 3.0
 | 
			
		||||
     */
 | 
			
		||||
    void setProject( QgsProject *project );
 | 
			
		||||
 | 
			
		||||
  public slots:
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@ -286,6 +309,12 @@ class GUI_EXPORT QgsExpressionBuilderWidget : public QWidget, private Ui::QgsExp
 | 
			
		||||
 | 
			
		||||
    void loadExpressionContext();
 | 
			
		||||
 | 
			
		||||
    //! Loads current project relations names/id into the expression help tree
 | 
			
		||||
    void loadRelations();
 | 
			
		||||
 | 
			
		||||
    //! Loads current project layer names/ids into the expression help tree
 | 
			
		||||
    void loadLayers();
 | 
			
		||||
 | 
			
		||||
    /** Registers a node item for the expression builder, adding multiple items when the function exists in multiple groups
 | 
			
		||||
      * \param groups The groups the item will be show in the tree view.  If a group doesn't exist it will be created.
 | 
			
		||||
      * \param label The label that is show to the user for the item in the tree.
 | 
			
		||||
@ -300,6 +329,16 @@ class GUI_EXPORT QgsExpressionBuilderWidget : public QWidget, private Ui::QgsExp
 | 
			
		||||
                                   QgsExpressionItem::ItemType type = QgsExpressionItem::ExpressionNode,
 | 
			
		||||
                                   bool highlightedItem = false, int sortOrder = 1 );
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns a HTML formatted string for use as a \a relation item help.
 | 
			
		||||
     */
 | 
			
		||||
    QString formatRelationHelp( const QgsRelation &relation ) const;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns a HTML formatted string for use as a \a layer item help.
 | 
			
		||||
     */
 | 
			
		||||
    QString formatLayerHelp( const QgsMapLayer *layer ) const;
 | 
			
		||||
 | 
			
		||||
    bool mAutoSave;
 | 
			
		||||
    QString mFunctionsPath;
 | 
			
		||||
    QgsVectorLayer *mLayer = nullptr;
 | 
			
		||||
@ -314,6 +353,7 @@ class GUI_EXPORT QgsExpressionBuilderWidget : public QWidget, private Ui::QgsExp
 | 
			
		||||
    QString mRecentKey;
 | 
			
		||||
    QMap<QString, QStringList> mFieldValues;
 | 
			
		||||
    QgsExpressionContext mExpressionContext;
 | 
			
		||||
    QPointer< QgsProject > mProject;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // QGSEXPRESSIONBUILDER_H
 | 
			
		||||
 | 
			
		||||
@ -47,6 +47,7 @@ ADD_PYTHON_TEST(PyQgsDistanceArea test_qgsdistancearea.py)
 | 
			
		||||
ADD_PYTHON_TEST(PyQgsEditWidgets test_qgseditwidgets.py)
 | 
			
		||||
ADD_PYTHON_TEST(PyQgsEllipsoidUtils test_qgsellipsoidutils.py)
 | 
			
		||||
ADD_PYTHON_TEST(PyQgsExpression test_qgsexpression.py)
 | 
			
		||||
ADD_PYTHON_TEST(PyQgsExpressionBuilderWidget test_qgsexpressionbuilderwidget.py)
 | 
			
		||||
ADD_PYTHON_TEST(PyQgsExpressionLineEdit test_qgsexpressionlineedit.py)
 | 
			
		||||
ADD_PYTHON_TEST(PyQgsExtentGroupBox test_qgsextentgroupbox.py)
 | 
			
		||||
ADD_PYTHON_TEST(PyQgsFeature test_qgsfeature.py)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										171
									
								
								tests/src/python/test_qgsexpressionbuilderwidget.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										171
									
								
								tests/src/python/test_qgsexpressionbuilderwidget.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,171 @@
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
"""QGIS Unit tests for QgsExpressionBuilderWidget
 | 
			
		||||
 | 
			
		||||
.. note:: 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.
 | 
			
		||||
"""
 | 
			
		||||
__author__ = 'Nyall Dawson'
 | 
			
		||||
__date__ = '30/07/2017'
 | 
			
		||||
__copyright__ = 'Copyright 2017, The QGIS Project'
 | 
			
		||||
# This will get replaced with a git SHA1 when you do a git archive
 | 
			
		||||
__revision__ = '$Format:%H$'
 | 
			
		||||
 | 
			
		||||
import qgis  # NOQA
 | 
			
		||||
 | 
			
		||||
from qgis.PyQt.QtCore import Qt
 | 
			
		||||
from qgis.testing import start_app, unittest
 | 
			
		||||
from qgis.gui import QgsExpressionBuilderWidget
 | 
			
		||||
from qgis.core import (QgsExpressionContext,
 | 
			
		||||
                       QgsExpressionContextScope,
 | 
			
		||||
                       QgsProject,
 | 
			
		||||
                       QgsVectorLayer,
 | 
			
		||||
                       QgsRelation,
 | 
			
		||||
                       QgsFeature,
 | 
			
		||||
                       QgsGeometry)
 | 
			
		||||
start_app()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def createReferencingLayer():
 | 
			
		||||
    layer = QgsVectorLayer("Point?field=fldtxt:string&field=foreignkey:integer",
 | 
			
		||||
                           "referencinglayer", "memory")
 | 
			
		||||
    pr = layer.dataProvider()
 | 
			
		||||
    f1 = QgsFeature()
 | 
			
		||||
    f1.setFields(layer.pendingFields())
 | 
			
		||||
    f1.setAttributes(["test1", 123])
 | 
			
		||||
    f2 = QgsFeature()
 | 
			
		||||
    f2.setFields(layer.pendingFields())
 | 
			
		||||
    f2.setAttributes(["test2", 123])
 | 
			
		||||
    f3 = QgsFeature()
 | 
			
		||||
    f3.setFields(layer.pendingFields())
 | 
			
		||||
    f3.setAttributes(["foobar'bar", 124])
 | 
			
		||||
    assert pr.addFeatures([f1, f2, f3])
 | 
			
		||||
    return layer
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def createReferencedLayer():
 | 
			
		||||
    layer = QgsVectorLayer(
 | 
			
		||||
        "Point?field=x:string&field=y:integer&field=z:integer",
 | 
			
		||||
        "referencedlayer", "memory")
 | 
			
		||||
    pr = layer.dataProvider()
 | 
			
		||||
    f1 = QgsFeature()
 | 
			
		||||
    f1.setFields(layer.pendingFields())
 | 
			
		||||
    f1.setAttributes(["foo", 123, 321])
 | 
			
		||||
    f2 = QgsFeature()
 | 
			
		||||
    f2.setFields(layer.pendingFields())
 | 
			
		||||
    f2.setAttributes(["bar", 456, 654])
 | 
			
		||||
    f3 = QgsFeature()
 | 
			
		||||
    f3.setFields(layer.pendingFields())
 | 
			
		||||
    f3.setAttributes(["foobar'bar", 789, 554])
 | 
			
		||||
    assert pr.addFeatures([f1, f2, f3])
 | 
			
		||||
    return layer
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestQgsExpressionBuilderWidget(unittest.TestCase):
 | 
			
		||||
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        self.referencedLayer = createReferencedLayer()
 | 
			
		||||
        self.referencingLayer = createReferencingLayer()
 | 
			
		||||
        QgsProject.instance().addMapLayers([self.referencedLayer, self.referencingLayer])
 | 
			
		||||
 | 
			
		||||
    def testFunctionPresent(self):
 | 
			
		||||
        """ check through widget model to ensure it is initially populated with functions """
 | 
			
		||||
        w = QgsExpressionBuilderWidget()
 | 
			
		||||
        m = w.model()
 | 
			
		||||
        # check that some standard expression functions are shown
 | 
			
		||||
        items = m.findItems('lower', Qt.MatchRecursive)
 | 
			
		||||
        self.assertEqual(len(items), 1)
 | 
			
		||||
        items = m.findItems('upper', Qt.MatchRecursive)
 | 
			
		||||
        self.assertEqual(len(items), 1)
 | 
			
		||||
        items = m.findItems('asdasdasda#$@#$', Qt.MatchRecursive)
 | 
			
		||||
        self.assertEqual(len(items), 0)
 | 
			
		||||
 | 
			
		||||
    def testVariables(self):
 | 
			
		||||
        """ check through widget model to ensure it is populated with variables """
 | 
			
		||||
        w = QgsExpressionBuilderWidget()
 | 
			
		||||
        m = w.model()
 | 
			
		||||
 | 
			
		||||
        s = QgsExpressionContextScope()
 | 
			
		||||
        s.setVariable('my_var1', 'x')
 | 
			
		||||
        s.setVariable('my_var2', 'y')
 | 
			
		||||
        c = QgsExpressionContext()
 | 
			
		||||
        c.appendScope(s)
 | 
			
		||||
 | 
			
		||||
        # check that variables are added when setting context
 | 
			
		||||
        w.setExpressionContext(c)
 | 
			
		||||
        items = m.findItems('my_var1', Qt.MatchRecursive)
 | 
			
		||||
        self.assertEqual(len(items), 1)
 | 
			
		||||
        items = m.findItems('my_var2', Qt.MatchRecursive)
 | 
			
		||||
        self.assertEqual(len(items), 1)
 | 
			
		||||
        items = m.findItems('not_my_var', Qt.MatchRecursive)
 | 
			
		||||
        self.assertEqual(len(items), 0)
 | 
			
		||||
        # double check that functions are still only there once
 | 
			
		||||
        items = m.findItems('lower', Qt.MatchRecursive)
 | 
			
		||||
        self.assertEqual(len(items), 1)
 | 
			
		||||
        items = m.findItems('upper', Qt.MatchRecursive)
 | 
			
		||||
        self.assertEqual(len(items), 1)
 | 
			
		||||
 | 
			
		||||
    def testLayers(self):
 | 
			
		||||
        """ check that layers are shown in widget model"""
 | 
			
		||||
        p = QgsProject.instance()
 | 
			
		||||
        layer = QgsVectorLayer("Point", "layer1", "memory")
 | 
			
		||||
        layer2 = QgsVectorLayer("Point", "layer2", "memory")
 | 
			
		||||
        p.addMapLayers([layer, layer2])
 | 
			
		||||
 | 
			
		||||
        w = QgsExpressionBuilderWidget()
 | 
			
		||||
        m = w.model()
 | 
			
		||||
 | 
			
		||||
        # check that layers are shown
 | 
			
		||||
        items = m.findItems('layer1', Qt.MatchRecursive)
 | 
			
		||||
        self.assertEqual(len(items), 1)
 | 
			
		||||
        items = m.findItems('layer2', Qt.MatchRecursive)
 | 
			
		||||
        self.assertEqual(len(items), 1)
 | 
			
		||||
 | 
			
		||||
        # change project
 | 
			
		||||
        p2 = QgsProject()
 | 
			
		||||
        layer3 = QgsVectorLayer("Point", "layer3", "memory")
 | 
			
		||||
        p2.addMapLayers([layer3])
 | 
			
		||||
        w.setProject(p2)
 | 
			
		||||
        m = w.model()
 | 
			
		||||
        items = m.findItems('layer1', Qt.MatchRecursive)
 | 
			
		||||
        self.assertEqual(len(items), 0)
 | 
			
		||||
        items = m.findItems('layer2', Qt.MatchRecursive)
 | 
			
		||||
        self.assertEqual(len(items), 0)
 | 
			
		||||
        items = m.findItems('layer3', Qt.MatchRecursive)
 | 
			
		||||
        self.assertEqual(len(items), 1)
 | 
			
		||||
 | 
			
		||||
    def testRelations(self):
 | 
			
		||||
        """ check that layers are shown in widget model"""
 | 
			
		||||
        p = QgsProject.instance()
 | 
			
		||||
 | 
			
		||||
        # not valid, but doesn't matter for test....
 | 
			
		||||
        rel = QgsRelation()
 | 
			
		||||
        rel.setId('rel1')
 | 
			
		||||
        rel.setName('Relation Number One')
 | 
			
		||||
        rel.setReferencingLayer(self.referencingLayer.id())
 | 
			
		||||
        rel.setReferencedLayer(self.referencedLayer.id())
 | 
			
		||||
        rel.addFieldPair('foreignkey', 'y')
 | 
			
		||||
 | 
			
		||||
        rel2 = QgsRelation()
 | 
			
		||||
        rel2.setId('rel2')
 | 
			
		||||
        rel2.setName('Relation Number Two')
 | 
			
		||||
        rel2.setReferencingLayer(self.referencingLayer.id())
 | 
			
		||||
        rel2.setReferencedLayer(self.referencedLayer.id())
 | 
			
		||||
        rel2.addFieldPair('foreignkey', 'y')
 | 
			
		||||
 | 
			
		||||
        p.relationManager().addRelation(rel)
 | 
			
		||||
        p.relationManager().addRelation(rel2)
 | 
			
		||||
 | 
			
		||||
        w = QgsExpressionBuilderWidget()
 | 
			
		||||
        m = w.model()
 | 
			
		||||
 | 
			
		||||
        # check that relations are shown
 | 
			
		||||
        items = m.findItems('Relation Number One', Qt.MatchRecursive)
 | 
			
		||||
        self.assertEqual(len(items), 1)
 | 
			
		||||
        items = m.findItems('Relation Number Two', Qt.MatchRecursive)
 | 
			
		||||
        self.assertEqual(len(items), 1)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    unittest.main()
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user