Запускать системные команды из приложения QML

16

Я хочу запустить системную команду из моего приложения. Предполагается выполнить команду на удаленном сервере, используя SSH. Но дело не в этом. Дело в том, что я не знаю, как запустить какую-либо команду из приложения. Я спросил в списке рассылки, и они направили меня на создание расширения QML с использованием C ++. Но я не знаю C ++, и мне кажется, что мне нужно многому научиться, только чтобы выполнить простую команду.

В Python (как в PHP) легко запустить системную команду. Есть ли другой способ сделать это в моем приложении Touch, или есть кто-то, кто может помочь мне еще больше? Или, может быть, есть лучшее решение моей проблемы?

Даниэль Холм
источник
1
Можете ли вы удалить весь контент, не имеющий отношения к сути вашего вопроса, такой как «Сервер Minecraft», Как вы изучаете этот «Просто для удовольствия» и т. Д.? Причина, по которой я спрашиваю, заключается в том, что эти детали не относятся к вопросу и довольно отвлекают, с уважением.
Акива

Ответы:

13

Это не то, что поддерживает QML, типичный ответ - написать плагин C ++ для обработки подобных вещей.

Однако команда SDK планирует различные расширения, чтобы предоставить разработчикам приложений QML, и это может быть то, что они реализуют в универсальном плагине, который вы можете использовать.

mhall119
источник
2
Это будет высоко ценится! Вместо этого я начал искать способ вызова скрипта Python, но я могу найти только скрипт Python, который запускает QML, а не наоборот.
Даниэль Холм
В конце концов я сделал некоторые изменения в своем веб-интерфейсе для той же функции, что и в новом приложении, и извлек необходимую информацию из него с помощью XML. Довольно аккуратно.
Даниэль Холм
1
Я попробовал концепцию QProcess Launcher в 14.04, и она отлично работает: askubuntu.com/a/446736/20275
int_ua
@ mhall119 Пожалуйста, исправьте меня, если я ошибаюсь, но вы не можете сделать это с помощью QML на телефоне из-за AppArmor. Это помешает вам сделать это.
Акива
10

Обновление: для 14.04 см. Намного упрощенный ответ от int_ua.

Первоначальный текст:

На http://talk.maemo.org/showthread.php?t=87580 приведен общий обзор того, как добавить расширение в QML. Я решил попробовать, используя вместо этого ubuntu-sdk, который немного отличается. Я документирую ниже.

Для этого проекта я выбрал Ubuntu Touch / Simple UI с C ++ Backend в QtCreator. Это создает проект с двумя отдельными частями, бэкендом и внешним интерфейсом touchui, написанным на QML. К бэкэнду мы добавим два файла для класса 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;
}

Этот класс просто использует QProcess для выполнения программы, ожидает ее завершения, читает ее стандартный вывод и возвращает ее в виде строки.

Далее нам нужно изменить backend / backend.cpp, чтобы включить класс. Это требует двух строк. Добавить включение:

#include "launcher.h"

и в BackendPlugin :: registerTypes добавьте строку:

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

Там уже должна быть строка для MyType, который является включенным примером. После этого мы сможем построить бэкэнд. Остается только использовать его в файле main.qml. Для этого я добавил строку:

Launcher { id: myLauncher }

и для обработчика кнопки onClick установите:

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

На данный момент все, что остается, это запустить его и проверить. Здесь я столкнулся с проблемой, так как QtCreator, похоже, не все правильно настроил по умолчанию. В качестве обходного пути, в терминале перейдите в каталог вашего проекта QtCreator и:

mkdir -p Ubuntu/Example

Затем скопируйте файл libUbuntuExample.so из ProjectBuildDir / backend в Ubuntu / Example и файл qmldir из ProjectName / backend / qmldir. Тогда вы можете запустить:

qmlscene -I . ProjectName/touchui/main.qml

Я уверен, что, возможно, есть простой способ настроить все это, поэтому Build / Run просто работает.

Джейсон Конти
источник
Это теперь просто работает в 14.04: askubuntu.com/a/446736/20275
int_ua
6

Ubuntu 14.04

Концепция типа QProcess Launcher теперь работает без проблем в Trusty с ubuntu-sdk-teamPPA. Просто создайте QML Extension Library + Tabbed UIпроект ( пока не используйте дефисы в имени проекта ), замените содержимое

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

}

и изменения qmlRegisterTypeв backend.cppTo

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

Далее просто очистите все MyTypeостатки от файлов QML и добавьте

        Rectangle {

          Launcher {
             id: qprocess
          }

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

где угодно и

import projectname 1.0

в начале.

Необязательный

Я также использую эту обертку:

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

Если вам нужен root-доступ, добавьте pkexec.

int_ua
источник
1
Я просто хотел бы подтвердить, что это решение отлично сработало для меня. Какие бы команды вы ни вводили, их вывод отображается в прямоугольнике.
Акива
2

Вам действительно не нужно много знать о c ++, чтобы получить доступ к командам терминала. Просто поместите следующее в любой файл, заканчивающийся на .cpp, например runPython.cpp.

#include <stdlib.h>

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

Все, что вам нужно выяснить сейчас, - это как запустить код на C ++ в QML, но я уверен, что это очень хорошо задокументировано.

Обратите внимание, что вы можете добавить любую понравившуюся вам команду linux, следуя тому же синтаксису system("linux command");.

Надеюсь это поможет!

user93692
источник