web-dev-qa-db-fra.com

Exécuter des commandes système à partir de l'application QML

Je souhaite exécuter une commande système à l'intérieur de mon application. Il est supposé exécuter une commande sur un serveur distant utilisant SSH. Mais ce n'est pas vraiment le point. Le fait est que je ne sais pas comment exécuter un type de commande depuis l'application. J'ai demandé dans la liste de messagerie et ils m'ont demandé de construire une extension QML en utilisant C++. Mais je ne connais pas le C++ et il semble que je doive apprendre beaucoup pour pouvoir exécuter une simple commande.

En Python (comme en PHP), il est facile d'exécuter une commande système. Existe-t-il un autre moyen de le faire dans mon application Touch ou y a-t-il quelqu'un qui pourrait m'aider encore plus? Ou peut-être une meilleure solution à mon problème?

16
Daniel Holm

Ce n’est pas quelque chose que QML prend en charge, la réponse typique est d’écrire un plugin C++ pour gérer ce genre de choses.

Toutefois, l’équipe du SDK prévoit diverses extensions à fournir aux développeurs d’applications QML. C’est peut-être quelque chose qu’elles implémentent dans un plug-in générique que vous pouvez utiliser.

13
mhall119

Mise à jour: Pour 14.04 voir la réponse très simplifiée de int_ua.

Texte original:

À la page http://talk.maemo.org/showthread.php?t=8758 , un aperçu de base explique comment ajouter l'extension à QML. J'ai décidé de tenter l'expérience avec ubuntu-sdk, qui est légèrement différent. Je vais documenter ci-dessous.

Pour ce projet, j'ai sélectionné Ubuntu Touch/Interface utilisateur simple avec C++ Backend dans QtCreator. Cela crée un projet avec deux parties distinctes, le backend et le touchui frontend écrit en QML. Au backend, nous allons ajouter deux fichiers pour la classe Launcher.

lanceur.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;
}

Cette classe utilise simplement QProcess pour exécuter un programme, attend sa fin, lit son stdout et le renvoie sous forme de chaîne.

Ensuite, nous devons modifier backend/backend.cpp pour inclure la classe. Cela nécessite deux lignes. Ajouter un inclure:

#include "launcher.h"

et dans BackendPlugin :: registerTypes ajoutez une ligne:

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

Il devrait déjà y avoir une ligne pour MyType, qui est l'exemple inclus. Après cela, nous devrions pouvoir construire le backend. La seule chose qui reste à faire est de l’utiliser dans le fichier main.qml. Pour cela j'ai ajouté une ligne:

Launcher { id: myLauncher }

et au gestionnaire onClick de Button, définissez:

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

À ce stade, tout ce qui reste à faire est de le démarrer et de le tester. C'est là que j'ai rencontré un problème, car QtCreator ne semble pas tout configurer correctement par défaut. Pour résoudre ce problème, dans le terminal, accédez au répertoire de votre projet QtCreator et:

mkdir -p Ubuntu/Example

Copiez ensuite le fichier libUbuntuExample.so de ProjectBuildDir/backend vers Ubuntu/Example et le fichier qmldir de ProjectName/backend/qmldir. Ensuite, vous pouvez exécuter:

qmlscene -I . ProjectName/touchui/main.qml

Je suis sûr qu'il existe probablement un moyen simple de configurer tout cela, donc Build/Run fonctionne parfaitement.

10
Jason Conti

Ubuntu 14.04

Le concept de type QProcess Launcher fonctionne désormais sans problème dans Trusty avec ubuntu-sdk-team PPA. Créez simplement le projet QML Extension Library + Tabbed UI ( n'utilisez pas encore de trait d'union dans le nom du projet ), remplacez le contenu de

mytype.h

#ifndef LAUNCHER_H
#define LAUNCHER_H

#include <QObject>
#include <QProcess>

class Launcher : public QObject
{
    Q_OBJECT

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

protected:
    QProcess *m_process;
};

#endif // LAUNCHER_H

mytype.cpp

#include "mytype.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;
}

Launcher::~Launcher() {

}

et remplacez qmlRegisterType dans backend.cpp par

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

Ensuite, nettoyez tout ce qui reste de MyType à partir des fichiers QML et ajoutez

        Rectangle {

          Launcher {
             id: qprocess
          }

          Text {
            anchors.centerIn: parent
            text: qprocess.launch("which bash")
          }
        }

où tu veux et

import projectname 1.0

au début.

Optionnel

J'utilise aussi ce wrapper:

function exec(command) {
    return qprocess.launch("sh -c \"" + command + " < /dev/null \"")
}

Si vous avez besoin d'un accès root, ajoutez pkexec.

6
int_ua

Vous n'avez vraiment pas besoin d'en savoir beaucoup sur c ++ pour avoir accès aux commandes de terminal. Il suffit de mettre ce qui suit dans n'importe quel fichier se terminant par .cpp, par exemple runPython.cpp.

#include <stdlib.h>

int main ()
{
    system("cd /home/user/path/to/script");
    system("python3 myScript.py");
    return 0;
}

Tout ce que vous devez savoir maintenant, c'est comment faire fonctionner le code c ++ dans QML, mais je suis sûr que c'est très bien documenté.

Notez que vous pouvez ajouter n'importe quelle commande linux en suivant la même syntaxe que system("linux command");.

J'espère que cela t'aides!

2
user93692