如何重新加载主qml文件?

时间:2019-04-16 02:48:32

标签: qt qml

我正在尝试捕获应用程序崩溃,并向用户显示一个屏幕以确认崩溃报告。这个想法是:当发生崩溃时,我将加载带有崩溃描述和发送按钮的特殊情况的QML。但是我无法重新加载已经存在的main.qml文件,QApplication::exit()函数只是不退出主事件循环,因此'crash.qml'屏幕永远不会显示给用户。

这是重现我的问题的最小工作示例:

/// main.cpp
#include <QDebug>
#include <QObject>
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <setjmp.h>
#include <signal.h>
#include "cpp.h"

CPP cpp_obj;
sigjmp_buf main_entry;
void signal_handler(int signum) {
    signal(SIGSEGV, SIG_DFL);   // clear signal handler as we don't need it anymore
    qDebug() << "got crash";
    qGuiApp->exit(1);
    longjmp(main_entry, 1);
}
int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QGuiApplication app(argc, argv);
    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));    

    QQmlContext* ctext = engine.rootContext();
    ctext->setContextProperty("cpp_obj", &cpp_obj);
    if (engine.rootObjects().isEmpty())
        return -1;

    signal(SIGSEGV, signal_handler);
    int retcode;
    if (setjmp(main_entry) == 0) {
        qDebug() << "app starting normal";
        retcode=app.exec();
        qDebug() << "app returned from normal call, retcode=" << retcode;
    } else {
        qDebug() << "loading crash qml file";
        engine.load(QUrl(QStringLiteral("qrc:/crash.qml")));
        qDebug() << "entering crash's main event loop";
        retcode=app.exec();
    }
    qDebug() << "exiting app at the end of the main(), retcode=" << retcode;
    return retcode;
}

//cpp.h
#ifndef CPP_H
#define CPP_H
#include <QObject>
class CPP : public QObject
{
    Q_OBJECT
public:
    explicit CPP(QObject *parent = nullptr);
     Q_INVOKABLE void crash_app();
signals:
    void app_crashed(QString failure_description);
};
#endif // CPP_H

/// cpp.cpp
#include "cpp.h"

CPP::CPP(QObject *parent) : QObject(parent)
{

}
void CPP::crash_app() {
    char *ptr=nullptr;
    *ptr='A';
}

///main.qml
import QtQuick 2.11
import QtQuick.Controls 2.4

ApplicationWindow {
    id: window
    visible: true
    width: 640
    height: 480
    title: qsTr("The App runs fine")

    Button {
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.verticalCenter: parent.verticalCenter
        text: "Simulate Crash"
        onClicked: cpp_obj.crash_app()
    }
}


///crash.qml
import QtQuick 2.11
import QtQuick.Controls 2.4

ApplicationWindow {
    id: window
    visible: true
    width: 640
    height: 480
    title: qsTr("Crash Report")

    Label {
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.verticalCenter: parent.verticalCenter
        text: "The app has failed"
    }
    Button {
        text: "Submit Crash Report"
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.bottom: parent.bottom
        onClicked: {
            // TODO: send crash report via UDP
        }

    }
}

当我运行它时,这就是我在控制台上看到的内容:

QML debugging is enabled. Only use this in a safe environment.
app starting normal
got crash
loading crash qml file
entering crash's main event loop
QCoreApplication::exec: The event loop is already running
exiting app at the end of the main(), retcode= -1

如果还有其他方法可以满足我的需求,我将不胜感激

0 个答案:

没有答案