Executar comandos do sistema no QML App

16

Eu quero executar um comando do sistema de dentro do meu aplicativo. Supõe-se executar um comando em um servidor remoto usando SSH. Mas esse não é realmente o ponto. O ponto é que não sei como executar nenhum tipo de comando no aplicativo. Eu perguntei na lista de emails e eles me indicaram para criar uma extensão QML usando C ++. Mas eu não conheço C ++ e parece que tenho que aprender muito apenas para executar um comando simples.

No Python (como no PHP), é fácil executar um comando do sistema. Existe alguma outra maneira de fazer isso no meu aplicativo Touch ou há alguém que poderia me ajudar ainda mais? Ou talvez tenha uma solução melhor para o meu problema?

Daniel Holm
fonte
11
Você pode remover todo o conteúdo que não tem a ver com o núcleo da sua pergunta, como o "Minecraft Server", como você está aprendendo isso "Apenas por diversão", etc? A razão pela qual pergunto é porque esses detalhes estão fora do assunto e são bastante perturbadores, respeitosamente.
214 Akiva

Respostas:

13

Isso não é algo compatível com o QML, a resposta típica é escrever um plug-in C ++ para lidar com esse tipo de coisa.

No entanto, a equipe do SDK está planejando várias extensões para fornecer aos desenvolvedores de aplicativos QML, e isso pode ser algo que eles implementam em um plug-in genérico que você pode usar.

mhall119
fonte
2
Isso seria muito apreciado! Em vez disso, comecei a procurar uma maneira de chamar um script Python, mas só consigo encontrar um script Python que execute QML, e não o contrário.
Daniel Holm
O que finalmente fiz foi fazer algumas alterações no meu webui para a mesma função que o novo aplicativo e extrair as informações necessárias usando XML. Muito arrumado.
Daniel Holm
11
Eu tentei o conceito QProcess Launcher em 14,04 e ele funciona muito bem: askubuntu.com/a/446736/20275
int_ua
@ mhall119 Corrija-me se estiver errado, mas na verdade você não pode fazer isso com o QML no telefone por causa do AppArmor. Isso impedirá que você faça isso.
Akiva
10

Atualização: para 14.04, veja a resposta muito simplificada de int_ua.

Texto original:

Em http://talk.maemo.org/showthread.php?t=87580, há uma visão geral básica de como adicionar a extensão ao QML. Decidi tentar usando o ubuntu-sdk, que é um pouco diferente. Vou documentar abaixo.

Para este projeto, selecionei o Ubuntu Touch / UI simples com C ++ Backend no QtCreator. Isso cria um projeto com duas partes separadas, o backend e o touchui frontend, escritos em QML. No back-end, adicionaremos dois arquivos para a 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;
}

Essa classe simplesmente usa QProcess para executar um programa, aguarda o término, lê seu stdout e o retorna como uma string.

Em seguida, precisamos modificar o backend / backend.cpp para incluir a classe. Isso requer duas linhas. Anexe um include:

#include "launcher.h"

e em BackendPlugin :: registerTypes adicione uma linha:

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

Já deve haver uma linha para MyType, que é o exemplo incluído. Depois disso, poderemos criar o back-end. A única coisa que resta é usá-lo no arquivo main.qml. Para isso, adicionei uma linha:

Launcher { id: myLauncher }

e para o manipulador onClick do Button, defina:

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

Neste ponto, tudo o que resta é iniciá-lo e testá-lo. Aqui foi onde encontrei um problema, já que o QtCreator parece não configurar tudo corretamente por padrão. Como solução alternativa, no terminal, navegue até o diretório do projeto QtCreator e:

mkdir -p Ubuntu/Example

Em seguida, copie o arquivo libUbuntuExample.so do ProjectBuildDir / back-end para o Ubuntu / Example e o arquivo qmldir do ProjectName / back-end / qmldir. Então você pode executar:

qmlscene -I . ProjectName/touchui/main.qml

Tenho certeza de que provavelmente existe uma maneira simples de manipular tudo isso, para que o Build / Run funcione.

Jason Conti
fonte
Agora funciona no 14.04: askubuntu.com/a/446736/20275
int_ua 12/04/2014
6

Ubuntu 14.04

O conceito do tipo QProcess Launcher agora está funcionando sem problemas no Trusty with ubuntu-sdk-teamPPA. Basta criar um QML Extension Library + Tabbed UIprojeto ( não use hífens no nome do projeto ainda ), substitua o conteúdo 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() {

}

e mudar qmlRegisterTypeno backend.cpppara

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

Em seguida, basta limpar todos os MyTyperestos dos arquivos QML e adicionar

        Rectangle {

          Launcher {
             id: qprocess
          }

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

onde você quiser e

import projectname 1.0

no início.

Opcional

Eu também uso este wrapper:

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

Se você precisar de acesso root, adicione pkexec.

int_ua
fonte
11
Gostaria apenas de confirmar que esta solução funcionou excelentemente para mim. Quaisquer que sejam os comandos que você digitar, sua saída será exibida no retângulo.
214 Akiva
2

Você realmente não precisa saber muito sobre c ++ para obter acesso aos comandos do terminal. Basta colocar o seguinte em qualquer arquivo que termine com .cpp, por exemplo, runPython.cpp.

#include <stdlib.h>

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

Tudo o que você precisa descobrir agora é como obter o código c ++ em execução na QML, mas tenho certeza de que está muito bem documentado.

Observe que você pode adicionar qualquer comando linux que desejar, seguindo a mesma sintaxe system("linux command");.

Espero que isto ajude!

user93692
fonte