Esegui i comandi di sistema dall'app QML

16

Voglio eseguire un comando di sistema dalla mia applicazione. Si supponga di eseguire un comando su un server remoto usando SSH. Ma non è proprio questo il punto. Il punto è che non so come eseguire alcun tipo di comando dall'app. Ho chiesto nella mail list e mi hanno riferito di creare un'estensione QML usando C ++. Ma non conosco il C ++ e sembra che io debba imparare così tanto solo per eseguire un semplice comando.

In Python (come in PHP) è facile eseguire un comando di sistema. C'è un altro modo di farlo nella mia app Touch o c'è qualcuno che potrebbe aiutarmi ancora di più? O forse hai una soluzione migliore al mio problema?

    
posta Daniel Holm 30.04.2013 - 15:18

4 risposte

13

Questo non è qualcosa che supporta QML, la risposta tipica è scrivere un plugin C ++ per gestire questo tipo di cose.

Tuttavia, il team SDK sta pianificando varie estensioni da fornire agli sviluppatori di app QML e potrebbe essere qualcosa che implementano in un plug-in generico che puoi utilizzare.

    
risposta data mhall119 30.04.2013 - 16:35
10

Aggiornamento: per 14.04 vedere la risposta molto semplificata di int_ua.

Testo originale:

Al link c'è una panoramica di base su come aggiungere l'estensione a QML. Ho deciso di dargli una possibilità usando invece ubuntu-sdk, che è leggermente diverso. Documenterò qui di seguito.

Per questo progetto ho selezionato Ubuntu Touch / Simple UI con Backend C ++ in QtCreator. Questo crea un progetto con due parti separate, il back-end e il front-end touchui scritto in QML. Al backend aggiungeremo due file per la classe Launcher.

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

Questa classe usa semplicemente QProcess per eseguire un programma, aspetta che finisca, legge il suo stdout e lo restituisce come una stringa.

Quindi dobbiamo modificare backend / backend.cpp per includere la classe. Questo richiede due linee. Aggiungi un include:

#include "launcher.h"

e in BackendPlugin :: registerTypes aggiungi una riga:

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

Ci dovrebbe già essere una linea per MyType, che è l'esempio incluso. Dopodiché dovremmo essere in grado di costruire il back-end. L'unica cosa che rimane è usarla nel file main.qml. Per questo ho aggiunto una riga:

Launcher { id: myLauncher }

e al gestore onClick del pulsante, impostare:

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

A questo punto non resta che avviarlo e testarlo. Qui è dove ho incontrato un problema, dal momento che QtCreator non sembra impostare tutto correttamente per impostazione predefinita. Mentre sto cercando, nel terminale accedi alla directory del tuo progetto QtCreator e:

mkdir -p Ubuntu/Example

Quindi copia il file libUbuntuExample.so da ProjectBuildDir / backend in Ubuntu / Example e il file qmldir da ProjectName / backend / qmldir. Quindi puoi eseguire:

qmlscene -I . ProjectName/touchui/main.qml

Sono sicuro che probabilmente c'è un modo semplice per sistemare tutto così Build / Run funziona.

    
risposta data Jason Conti 29.06.2013 - 01:05
6

Ubuntu 14.04

Il concetto di tipo Launcher QProcess ora funziona senza problemi in Trusty con ubuntu-sdk-team PPA. Crea semplicemente QML Extension Library + Tabbed UI project ( non usare i trattini nel nome del progetto ancora ), sostituisce il contenuto di

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() {

}

e modifica qmlRegisterType in backend.cpp in

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

Successivamente, pulisci tutto MyType rimane dai file QML e aggiungi

        Rectangle {

          Launcher {
             id: qprocess
          }

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

dove preferisci e

import projectname 1.0

all'inizio.

opzionale

Uso anche questo wrapper:

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

Se hai bisogno dell'accesso root, aggiungi pkexec .

    
risposta data int_ua 12.04.2014 - 06:30
2

Non hai davvero bisogno di sapere molto su c ++ per avere accesso ai comandi del terminale. Basta inserire quanto segue in qualsiasi file che termina con .cpp, ad esempio runPython.cpp.

#include <stdlib.h>

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

Tutto quello che devi scoprire ora è come ottenere il codice c ++ in esecuzione in QML, ma sono sicuro che è molto ben documentato.

Tieni presente che puoi aggiungere qualsiasi comando di Linux che ti piace seguendo la stessa sintassi system("linux command"); .

Spero che questo aiuti!

    
risposta data user93692 16.08.2013 - 00:53

Leggi altre domande sui tag