How can I run a command from a qml script? [duplicate]

Solution 1:

This isn't something that QML supports, the typical answer is to write a C++ plugin to handle that kind of thing.

However, the SDK team is planning out various extensions to provide to QML app developers, and this may be something that they implement in a generic plugin that you can use.

Solution 2:

Update: For 14.04 see the much simplified answer by int_ua.

Original Text:

At http://talk.maemo.org/showthread.php?t=87580 there is a basic overview of how to add the extension to QML. I decided to give it a shot using the ubuntu-sdk instead, which is slightly different. I'll document below.

For this project I selected Ubuntu Touch/Simple UI with C++ Backend in QtCreator. This creates a project with two separate parts, the backend and the touchui frontend written in QML. To the backend we are going to add two files for the Launcher class.

launcher.h:

#ifndef LAUNCHER_H
#define LAUNCHER_H

#include <QObject>
#include <QProcess>

class Launcher : public QObject
{
    Q_OBJECT
public:
    explicit Launcher(QObject *parent = 0);
    Q_INVOKABLE QString launch(const QString &program);

private:
    QProcess *m_process;
};

#endif // LAUNCHER_H

launcher.cpp:

#include "launcher.h"

Launcher::Launcher(QObject *parent) :
    QObject(parent),
    m_process(new QProcess(this))
{
}

QString Launcher::launch(const QString &program)
{
    m_process->start(program);
    m_process->waitForFinished(-1);
    QByteArray bytes = m_process->readAllStandardOutput();
    QString output = QString::fromLocal8Bit(bytes);
    return output;
}

This class simply uses QProcess to execute a program, waits for it to finish, reads its stdout, and returns it as a string.

Next we need to modify backend/backend.cpp to include the class. This requires two lines. Append an include:

#include "launcher.h"

and in BackendPlugin::registerTypes add a line:

qmlRegisterType<Launcher>(uri, 1, 0, "Launcher");

There should already be a line for MyType, which is the included example. After this we should be able to build the backend. The only thing that remains is to use it in the main.qml file. For this I added a line:

Launcher { id: myLauncher }

and to the Button's onClick handler, set:

myType.helloWorld = myLauncher.launch("date");

At this point all that remains is to start it up and test it out. Here is where I ran into a problem, since QtCreator doesn't seem to set everything up properly by default. As I workaround, in the terminal navigate to your QtCreator project directory and:

mkdir -p Ubuntu/Example

Then copy the libUbuntuExample.so file from ProjectBuildDir/backend to Ubuntu/Example, and the qmldir file from ProjectName/backend/qmldir. Then you can run:

qmlscene -I . ProjectName/touchui/main.qml

I'm sure there is probably a simple way to rig this all up so Build/Run just works.