Esegui i comandi di sistema dall'app QML


16

Voglio eseguire un comando di sistema dall'interno della mia applicazione. Si supponga di eseguire un comando su un server remoto utilizzando SSH. Ma non è questo il punto. Il punto è che non so come eseguire alcun tipo di comando dall'app. Ho chiesto nella mailing list e mi hanno indirizzato a creare un'estensione QML usando C ++. Ma non conosco C ++ e sembra che devo 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?


1
Riesci a rimuovere tutto il contenuto che non ha a che fare con il nocciolo della tua domanda, come il "Minecraft Server", come stai imparando questo "Solo per divertimento", ecc.? Il motivo per cui lo chiedo è perché questi dettagli sono a parte il problema e abbastanza distraenti, rispettosamente.
Akiva,

Risposte:


13

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

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


2
Sarebbe molto apprezzato! Ho invece iniziato a cercare un modo per chiamare uno script Python, ma riesco a trovare solo uno script Python che esegue QML e non viceversa.
Daniel Holm,

Quello che finalmente ho fatto è stato apportare alcune modifiche al mio webui per la stessa funzione della nuova app e ottenere le informazioni di cui ho bisogno usando XML. Piuttosto pulito.
Daniel Holm,

1
Ho provato il concetto di QProcess Launcher nel 14.04 e funziona perfettamente: askubuntu.com/a/446736/20275
int_ua

@ mhall119 Per favore, correggimi se sbaglio, ma non puoi effettivamente farlo con QML sul telefono a causa di AppArmor. Ti impedirà di farlo.
Akiva,

10

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

Testo originale:

A http://talk.maemo.org/showthread.php?t=87580 c'è una panoramica di base su come aggiungere l'estensione a QML. Ho deciso di fare un tentativo usando Ubuntu-SDK, che è leggermente diverso. Documenterò di seguito.

Per questo progetto ho selezionato Ubuntu Touch / Simple UI con C ++ Backend in QtCreator. Questo crea un progetto con due parti separate, il backend e il frontend touchui scritti 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.

Successivamente è necessario modificare backend / backend.cpp per includere la classe. Ciò richiede due righe. Aggiungi un'inclusione:

#include "launcher.h"

e in BackendPlugin :: registerTypes aggiungi una riga:

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

Dovrebbe esserci già una riga per MyType, che è l'esempio incluso. Dopo questo dovremmo essere in grado di costruire il backend. L'unica cosa che rimane è usarlo nel file main.qml. Per questo ho aggiunto una riga:

Launcher { id: myLauncher }

e al gestore onClick di Button, impostare:

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

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

mkdir -p Ubuntu/Example

Quindi copiare il file libUbuntuExample.so da ProjectBuildDir / backend su Ubuntu / Esempio 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.


Ora funziona solo nel 14.04: askubuntu.com/a/446736/20275
int_ua

6

Ubuntu 14.04

Il concetto di tipo QProcess Launcher ora funziona senza problemi in Trusty con ubuntu-sdk-teamPPA. Basta creare un QML Extension Library + Tabbed UIprogetto ( non usare ancora trattini nel nome del progetto ), sostituire 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 cambia qmlRegisterTypein backend.cppa

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

Quindi, basta pulire tutto ciò che MyTyperimane dai file QML e aggiungere

        Rectangle {

          Launcher {
             id: qprocess
          }

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

dove vuoi e

import projectname 1.0

all'inizio.

Opzionale

Uso anche questo wrapper:

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

Se è necessario l'accesso root, aggiungere pkexec.


1
Vorrei solo confermare che questa soluzione ha funzionato in modo eccellente per me. Qualunque sia il comando che inserisci, il suo output viene visualizzato nel rettangolo.
Akiva,

2

Non hai davvero bisogno di sapere molto su c ++ per ottenere l'accesso ai comandi del terminale. Inserisci semplicemente 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 far funzionare il codice c ++ in QML ma sono sicuro che è ben documentato.

Nota che puoi aggiungere qualsiasi comando linux che ti piace seguendo la stessa sintassi system("linux command");.

Spero che sia di aiuto!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.