Qt quick中C++与QML的整合。
出自:
http://www.ics.com/blog/integrating-c-qml
把大象装冰箱里总共分四步:
1. 定义一个类,继承自QObject。
2. 在定义的类中声明Q_OBJECT,这样可以支持signals 和slots和meta-object system。
3. 通过Q_PROPERTY定义一些属性。
4. 在main程序中调用qmlRegisterType() 注册。
keygenerator.h
#ifndef KEYGENERATOR_H
#define KEYGENERATOR_H
#include <QObject>
#include <QString>
#include <QStringList>
// Simple QML object to generate SSH key pairs by calling ssh-keygen.
class KeyGenerator : public QObject { Q_OBJECT Q_PROPERTY(QString type READ type WRITE setType NOTIFY typeChanged) Q_PROPERTY(QStringList types READ types NOTIFY typesChanged) Q_PROPERTY(QString filename READ filename WRITE setFilename NOTIFY filenameChanged) Q_PROPERTY(QString passphrase READ filename WRITE setPassphrase NOTIFY passphraseChanged) public: KeyGenerator(); ~KeyGenerator(); QString type(); void setType(const QString &t); QStringList types(); QString filename(); void setFilename(const QString &f); QString passphrase(); void setPassphrase(const QString &p); public slots: void generateKey(); signals: void typeChanged(); void typesChanged(); void filenameChanged(); void passphraseChanged(); void keyGenerated(bool success); private: QString _type; QString _filename; QString _passphrase; QStringList _types; }; #endif
keygenerator.cpp
#include <QFile>
#include <QProcess>
#include "KeyGenerator.h"
KeyGenerator::KeyGenerator()
: _type("rsa"), _types{"dsa", "ecdsa", "rsa", "rsa1"}
{
}
KeyGenerator::~KeyGenerator()
{
}
QString KeyGenerator::type()
{
return _type;
}
void KeyGenerator::setType(const QString &t)
{
// Check for valid type.
if (!_types.contains(t))
return;
if (t != _type) {
_type = t;
emit typeChanged();
}
}
QStringList KeyGenerator::types()
{
return _types;
}
QString KeyGenerator::filename()
{
return _filename;
}
void KeyGenerator::setFilename(const QString &f)
{
if (f != _filename) {
_filename = f;
emit filenameChanged();
}
}
QString KeyGenerator::passphrase()
{
return _passphrase;
}
void KeyGenerator::setPassphrase(const QString &p)
{
if (p != _passphrase) {
_passphrase = p;
emit passphraseChanged();
}
}
void KeyGenerator::generateKey()
{
// Sanity check on arguments
if (_type.isEmpty() or _filename.isEmpty() or
(_passphrase.length() > 0 and _passphrase.length() < 5)) {
emit keyGenerated(false);
return;
}
// Remove key file if it already exists
if (QFile::exists(_filename)) {
QFile::remove(_filename);
}
// Execute ssh-keygen -t type -N passphrase -f keyfileq
QProcess *proc = new QProcess;
QString prog = "ssh-keygen";
QStringList args{"-t", _type, "-N", _passphrase, "-f", _filename};
proc->start(prog, args);
proc->waitForFinished();
emit keyGenerated(proc->exitCode() == 0);
delete proc;
}
main.cpp
#include <QApplication>
#include <QObject>
#include <QQmlComponent>
#include <QQmlEngine>
#include <QQuickWindow>
#include <QSurfaceFormat>
#include "KeyGenerator.h"
// Main wrapper program.
// Special handling is needed when using Qt Quick Controls for the top window.
// The code here is based on what qmlscene does.
int main(int argc, char ** argv)
{
QApplication app(argc, argv);
// Register our component type with QML.
qmlRegisterType<KeyGenerator>("com.ics.demo", 1, 0, "KeyGenerator");
int rc = 0;
QQmlEngine engine;
QQmlComponent *component = new QQmlComponent(&engine);
QObject::connect(&engine, SIGNAL(quit()), QCoreApplication::instance(), SLOT(quit()));
component->loadUrl(QUrl("qrc:/main.qml"));
if (!component->isReady() ) {
qWarning("%s", qPrintable(component->errorString()));
return -1;
}
QObject *topLevel = component->create();
QQuickWindow *window = qobject_cast<QQuickWindow *>(topLevel);
QSurfaceFormat surfaceFormat = window->requestedFormat();
window->setFormat(surfaceFormat);
window->show();
rc = app.exec();
delete component;
return rc;
}
main.qml
// SSH key generator UI
import QtQuick 2.1
import QtQuick.Controls 1.0
import QtQuick.Layouts 1.0
import QtQuick.Dialogs 1.0
import com.ics.demo 1.0
ApplicationWindow {
title: qsTr("SSH Key Generator")
statusBar: StatusBar {
RowLayout {
Label {
id: status
}
}
}
width: 369
height: 166
ColumnLayout {
x: 10
y: 10
// Key type
RowLayout {
Label {
text: qsTr("Key type:")
}
ComboBox {
id: combobox
Layout.fillWidth: true
model: keygen.types
currentIndex: 2
}
}
// Filename
RowLayout {
Label {
text: qsTr("Filename:")
}
TextField {
id: filename
implicitWidth: 200
onTextChanged: updateStatusBar()
}
Button {
text: qsTr("&Browse...")
onClicked: filedialog.visible = true
}
}
// Passphrase
RowLayout {
Label {
text: qsTr("Pass phrase:")
}
TextField {
id: passphrase
Layout.fillWidth: true
echoMode: TextInput.Password
onTextChanged: updateStatusBar()
}
}
// Confirm Passphrase
RowLayout {
Label {
text: qsTr("Confirm pass phrase:")
}
TextField {
id: confirm
Layout.fillWidth: true
echoMode: TextInput.Password
onTextChanged: updateStatusBar()
}
}
// Buttons: Generate, Quit
RowLayout {
Button {
id: generate
text: qsTr("&Generate")
onClicked: keygen.generateKey()
}
Button {
text: qsTr("&Quit")
onClicked: Qt.quit()
}
}
}
FileDialog {
id: filedialog
title: qsTr("Select a file")
selectMultiple: false
selectFolder: false
nameFilters: [ "All files (*)" ]
selectedNameFilter: "All files (*)"
onAccepted: {
filename.text = fileUrl.toString().replace("file://", "")
}
}
KeyGenerator {
id: keygen
filename: filename.text
passphrase: passphrase.text
type: combobox.currentText
onKeyGenerated: {
if (success) {
status.text = qsTr('<font color="green">Key generation succeeded.</font>')
} else {
status.text = qsTr('<font color="red">Key generation failed</font>')
}
}
}
function updateStatusBar() {
if (passphrase.text != confirm.text) {
status.text = qsTr('<font color="red">Pass phrase does not match.</font>')
generate.enabled = false
} else if (passphrase.text.length > 0 && passphrase.text.length < 5) {
status.text = qsTr('<font color="red">Pass phrase too short.</font>')
generate.enabled = false
} else if (filename.text == "") {
status.text = qsTr('<font color="red">Enter a filename.</font>')
generate.enabled = false
} else {
status.text = ""
generate.enabled = true
}
}
Component.onCompleted: updateStatusBar()
}
.pro文件
TEMPLATE = app
QT += qml quick
CONFIG += c++11
QT += widgets
SOURCES += main.cpp \
keygenerator.cpp
RESOURCES += qml.qrc
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =
# Default rules for deployment.
include(deployment.pri)
HEADERS += \
keygenerator.h