问题描述
我想从应用程序内部运行系统命令。它应该使用 SSH 在远程服务器上运行命令。但这不是重点。重点是我不知道如何从应用程序运行任何类型的命令。我在邮件列表中询问,他们建议我使用 C++ 构建 QML 扩展。但我不懂 C++,似乎我必须学习这么多才能运行一个简单的命令。
在 Python(与 PHP 一样)中,运行系统命令很容易。在我的 Touch 应用中还有其他方法可以执行此操作吗?或者有人能为我提供更多帮助吗?或者也许有更好的解决方案来解决我的问题?
最佳回答
这不是 QML 所支持的东西,典型的答案是编写一个 C++ 插件来处理这类事情。
但是,SDK 团队正在计划向 QML 应用程序开发人员提供各种扩展,这可能是他们在您可以使用的通用插件中实现的内容。
次佳回答
更新:对于 14.04,请参见 int_ua 提供的简化版答案。
原文:
在 http://talk.maemo.org/showthread.php?t=87580 中有一个关于如何将扩展添加到 QML 的基本概述。我决定尝试使用 ubuntu-sdk,它略有不同。我将在下面记录。
对于这个项目,我在 QtCreator 中选择了 Ubuntu Touch/Simple UI 和 C++ Backend。这将创建一个包含两个独立部分的项目,即后端和用 QML 编写的 touchui 前端。我们将在后端为 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
启动器.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 复制到 Ubuntu/Example。然后您可以运行:
qmlscene -I . ProjectName/touchui/main.qml
我确信可能存在一种简单的方法来完成这一切,以便 Build/Run 能够正常工作。
第三种回答
Ubuntu 14.04
QProcess Launcher 类型的概念现在在 Trusty 中使用 ubuntu-sdk-team
PPA 时没有问题。只需创建 QML Extension Library + Tabbed UI
项目 ( don’t use hyphens in project name yet ),替换
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() {
}
并将 backend.cpp
中的 qmlRegisterType
更改为
qmlRegisterType<Launcher>(uri, 1, 0, "Launcher");
接下来,只需清除 QML 文件中的所有 MyType
残留,然后添加
Rectangle {
Launcher {
id: qprocess
}
Text {
anchors.centerIn: parent
text: qprocess.launch("which bash")
}
}
你喜欢的任何地方
import projectname 1.0
在一开始的时候。
Optional
我也使用这个包装器:
function exec(command) {
return qprocess.launch("sh -c \"" + command + " < /dev/null \"")
}
如果需要 root 访问权限,请添加 pkexec
。