Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

setContextProperty : why is a method of a contextProperty not recognized ?



  • hi !

    I created two C++ class which instanciates two others as ContextProperties.
    i can call a method of one of the class from the QML and it works fine when I launch it with a button. If I do the same with a method of the other object,
    TypeError: Property 'savePreset' of object VIEW::PresetModel<adress> is not a function. Why ?

    Here are the codes :
    setContextProperties :

    MainModelView* mp_mainModel;
    PresetModel* mp_presetModel;
    QQmlContext::PropertyPair m_mainModelProperty, m_presetModelProperty;
    
    this->engine()->addImportPath(QString(QML_HOME));
    mp_mainModel = new MainModelView(this); 
    mp_presetModel = new PresetModel(this);
    QVector<QQmlContext::PropertyPair> w_properties;
    if (mp_mainModel && mp_mainModel)
    {
    	m_mainModelProperty.name = "MainModel";
    	m_mainModelProperty.value = QVariant::fromValue(mp_mainModel);
    	w_properties.append(m_mainModelProperty);
    	m_presetModelProperty.name = "PresetModel";
    	m_presetModelProperty.value = QVariant::fromValue(mp_presetModel);
    	w_properties.append(m_presetModelProperty);
    				
    	this->engine()->rootContext()->setContextProperties(w_properties);
    	//this->engine()->rootContext()->setContextProperty("MainModel",mp_mainModel);
    	//this->engine()->rootContext()->setContextProperty("PresetModel", mp_presetModel);
    

    (should I use two setContextProperty or one setContextProperties ? the documentation says it's better to set everything at one time but I have to create a vector, two objects, two QVariant casts... is it really more efficient ?)
    Prototype of the methods of MainModelView that is working fine

    Q_INVOKABLE void nameOfTheMethod(void);
    

    QML programm that calls the method that works

     EditPanelButton {
            id: reset_button
            width: position === Qt.LeftEdge || position === Qt.RightEdge ? parent.width/1.5 : parent.height/1.5
            height: width
            x: position === Qt.LeftEdge || position === Qt.RightEdge ? parent.width/2-width/2 : parent.width-width-10
            y: position === Qt.LeftEdge || position === Qt.RightEdge ? parent.height-height-10 : parent.height/2-height/2
            text: "RESET"
            onClicked: {MainModel.resetParameters();console.log("reset_button clicked")}
    }
    

    and this call doesn't work

    EditPanelButton {
            id: save_preset
            x: position === Qt.LeftEdge || position === Qt.RightEdge ? limit3.x : limit3.x + 10
            y: position === Qt.LeftEdge || position === Qt.RightEdge ? limit3.y + 10 : limit3.y
            width: position === Qt.LeftEdge || position === Qt.RightEdge ? parent.width/3 : parent.height/3
            height: width
            image: "../../resources/save-128.png"
    
            onClicked: { PresetModel.savePreset(); preset_view.currentIndex = preset_view.count-1;console.debug("EditPanel savepreset clicked") }
        }
    

    how can I launch savePreset() as I launch resetParameters() ?


  • Qt Champions 2017

    Can you show what is the PresetModel header file ? I suspect the issue with declaration of savePreset().

    Can you try registering the objects using setContextProperty & check it works ?


  • Moderators

    hi @Quentin91

    is your

    Q_INVOKABLE void nameOfTheMethod(void);

    public ?



  • Thank you very much for your answers

    @dheerendra sure, here is the declaration of the class

    class PresetModel : public QAbstractListModel
    		{
    			Q_OBJECT
    		private:
    			QQuickView * mp_view;
    			QList<Preset> m_preset_list;
    			/*!
    			*  \brief constructeur par copie
    			*
    			*	constructeur par copie privé
    			*
    			*	\param [IN] air_presetModel : référence à l'objet à copier.
    			*/
    			PresetModel(const PresetModel& air_presetModel);
    			
    			Preset* mp_preset_base;
    		public:
    			
    			enum t_presetRole
    			{
    				NameRole = Qt::UserRole + 1
    			} mstruct_roles;
    
    			static const int ms_NameRole = Qt::UserRole +1;
    			/*!
    			*  \brief constructeur
    			*
    			*	\param [IN] aip_view : pointeur sur la QQuickView correspondant à la fenêtre principale
    			*	\param [IN] aip_parent : parent QObject de la classe, null par défaut
    			*/
    			PresetModel(QQuickView* aip_view, QObject* aip_parent = nullptr);
    			/*!
    			*  \brief donne le nombre d'éléments du model
    			*/
    			~PresetModel();
    			/*!
    			*  \brief ajoute un modèle Preset à la fin de la QList
    			*
    			*	\param [IN] aip_p : référence const sur le Preset à ajouter
    			*/
    			void addPreset(const Preset& air_p);
    			/*!
    			*  \brief donne le nombre d'éléments du model
    			*
    			*	\param [IN] air_parent : QModelIndex& qui localise les données dans le model de données
    			*	\return int : nombre de lignes du parent
    			*/
    			int rowCount(const QModelIndex& air_parent = QModelIndex())const override;
    			/*!
    			*  \brief donne accès à l'objet enregistré sous un certain index
    			*
    			*	\param [IN] air_index : QModelIndex& qui localise les données dans le model de données
    			*	_param [IN] ai_role : int correspondant au role. Aucune idée de ce que c'est que cette histoire
    			*	\return QVariant : nom de l'Item enregistré à l'index donné si tout va bien. Sinon, un QVariant vide
    			*/
    			QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
    			/*!
    			 *	\brief getter de mstruct_roles
    			 * 
    			 * \return t_presetRole : contenu de la structure. A savoir un integer
    			 */
    			t_presetRole roleName(void);
    			/*!
    			 * \brief initilialise un élément de base dans la liste
    			 * 
    			 */
    			void setPresetBase(void);
    			/*!
    			 * \brief 
    			 * 
    			 * \param ai_index correspond à la configuration à charger
    			 */
    			Q_INVOKABLE void applyPreset(int ai_index);
    			/*!
    			* \brief sauvegarde la configuration actuelle
    			*/
    			Q_INVOKABLE void savePreset(void);
    	
    			/*!
    			 * \brief charge les paramètres des items QML depuis un fichier
    			 * 
    			 */
    			bool loadPresetFromFile(void);
    		public slots:
    		
    		void onPresetChanged();
    
    		};
    

    Can you try registering the objects using setContextProperty & check it works ?

    I tried again, the behaviour of the program is exactly the same. Do you think i should use 2 setContextProperty instead of setContextProperties ?

    @J-Hilk Yes, the methods are public
    Here is the definition of the method savePreset that can't get CALLED. As you can see, it's the simplest I can do.

    void PresetModel::savePreset(void)
    {
    	TRACE_DEBUG("presetModel::savePreset....................CALLED");
            printf("but does nothing yet\n");
    }
    

Log in to reply