Re: [PATCH] phonesim: fix exporting of child widgets to javascript engine

Andres Salomon <[email protected]> Fri, 27 Feb 2026 16:27:21 -0500
Newsgroups dev.linux.lists.ofono
Message-ID <[email protected]>
BTW Marcel, I noticed in the latest phonesim release (2.1) that the 
tarball dropped the doc/scriptable.txt file. Was this unintentional, or 
is the javascript interface being deprecated?

If it's not being deprecated, I'd love some feedback on this patch. :)

On 12/29/25 03:10, Andres Salomon wrote:
> Using the example sms.js script in doc/scriptable.txt, the following
> error occurs with phonesim built using Qt5.15:
> 
> Error org.ofono.phonesim.Error.ScriptExecError: /tmp/sms.js, line 1, TypeError: Cannot read property 'leMessageSender' of undefined
> 
> This is due to phonesim creating javascript objects for all the gui
> tab widgets, but none of the child widgets inside of those tabs. So
> in the javascript engine, 'tabSMS' is available, but its child widget
> 'gbMessage1' is undefined.
> 
> I'm not sure if this is related to behavior changes in current versions
> of QJSEngine/UIC or what, but we can manually add all those widgets
> to the javascript engine to fix this.
> ---
>   src/control.cpp | 25 +++++++++++++++++++++++++
>   src/control.h   |  2 ++
>   2 files changed, 27 insertions(+)
> 
> diff --git a/src/control.cpp b/src/control.cpp
> index 817a0b2..b85e9ad 100644
> --- a/src/control.cpp
> +++ b/src/control.cpp
> @@ -637,32 +637,57 @@ void ControlWidget::modemSilentReset()
>       emit unsolicitedCommand("+CRST:");
>   }
>   
> +/*
> + * Recursively add all widgets in a controlbase.ui tab to the javascript
> + * engine so that scripts can reference them. Because the widgets
> + * aren't local to this function, they should remain in scope while the
> + * script executes.
> + */
> +void Script::AddChildren(const QWidget *parentW, QJSValue &parentJS)
> +{
> +    QList<QWidget*> kids = parentW->findChildren<QWidget*>(QString(),
> +            Qt::FindDirectChildrenOnly);
> +    foreach (QWidget *w, kids) {
> +        QJSValue obj = engine.newQObject(w);
> +        parentJS.setProperty(w->objectName(), obj);
> +        AddChildren(w, obj);
> +    }
> +}
> +
>   Script::Script(QObject *obj, Ui_ControlBase *ui) : QDBusAbstractAdaptor(obj)
>   {
>       /* Export tabs to be accessed by script */
>       QJSValue qsTab = engine.newQObject(ui->tab);
>       engine.globalObject().setProperty("tabRegistration", qsTab);
> +    AddChildren(ui->tab, qsTab);
>   
>       QJSValue qsTab2 = engine.newQObject(ui->tab_2);
>       engine.globalObject().setProperty("tabCBM", qsTab2);
> +    AddChildren(ui->tab_2, qsTab2);
>   
>       QJSValue qsTab3 = engine.newQObject(ui->tab_3);
>       engine.globalObject().setProperty("tabSMS", qsTab3);
> +    AddChildren(ui->tab_3, qsTab3);
>   
>       QJSValue qsTab4 = engine.newQObject(ui->tab_4);
>       engine.globalObject().setProperty("tabVoiceMail", qsTab4);
> +    AddChildren(ui->tab_4, qsTab4);
>   
>       QJSValue qsTab5 = engine.newQObject(ui->tab_5);
>       engine.globalObject().setProperty("tabUSSD", qsTab5);
> +    AddChildren(ui->tab_5, qsTab5);
>   
>       QJSValue qsTab6 = engine.newQObject(ui->tab_6);
>       engine.globalObject().setProperty("tabSIM", qsTab6);
> +    AddChildren(ui->tab_6, qsTab6);
>   
>       QJSValue qsTab8 = engine.newQObject(ui->tab_8);
>       engine.globalObject().setProperty("tabPosition", qsTab8);
> +    AddChildren(ui->tab_8, qsTab8);
>   
>       QJSValue qsTab9 = engine.newQObject(ui->tab_9);
>       engine.globalObject().setProperty("tabCall", qsTab9);
> +    AddChildren(ui->tab_9, qsTab9);
>   }
>   
>   void Script::SetPath(const QString &path, const QDBusMessage &msg)
> diff --git a/src/control.h b/src/control.h
> index be4a366..c160d61 100644
> --- a/src/control.h
> +++ b/src/control.h
> @@ -57,6 +57,8 @@ public slots:
>       QString Run(const QString &name, const QDBusMessage &msg);
>   
>   private:
> +    void AddChildren(const QWidget *parentW, QJSValue &parentJS);
> +
>       QString dirPath;
>       QJSEngine engine;
>   };