Проект C ++ / QML, совместимый как с Qt 4 (QtQuick 1.x), так и с Qt 5 (QtQuick 2.x)

При написании приложения Qt, которое не использует QML и не зависит от новых возможностей Qt 5, мы можем скомпилировать его как с Qt 4, так и с Qt 5 (за исключением нескольких несовместимостей исходного кода).

Когда мы хотим использовать функцию Qt 5, но хотим вернуться к эквивалентному, но менее эффективному решению Qt 4, мы можем просто использовать #if для проверки версии Qt, например. использовать новый QStringLiteral, но вернуться к QString::fromUtf8 при компиляции с Qt 4.

Как мы можем сделать то же самое с QtQuick? Обратите внимание, что можно использовать QDeclarativeView с QtQuick 1.x в Qt 5, но при этом не будет использоваться новый граф сцены из Qt 5. Только 1.x поддерживается в QDeclarativeView и только 2.x поддерживается в QQuickView, даже если я не использую представленные функции в Quick 2.0.

Я хочу:

  • При компиляции с Qt 4 используйте QDeclarativeView и друзей; в QML: import QtQuick 1.x
  • При компиляции с Qt 5 используйте новый QQuickView и друзей; в QML: import QtQuick 2.x
  • Имейте только один набор файлов QML, но нет одного для QtQuick 1.x, а другого для QtQuick 2.x

Что касается части C ++, это кажется простым. В Qt 4 мы можем просто добавить:

#include <QApplication>
#include <QDeclarativeView>
#include <QDeclarativeEngine>
typedef QApplication QGuiApplication;
typedef QDeclarativeView QQuickView;

а затем используйте QGuiApplication, QQuickView и так далее как в Qt 4, так и в Qt 5. Но когда файл QML содержит декларативный импорт для QtQuick, я не могу добавить #if, чтобы выбрать между 1.x и 2.x. Есть ли официальный способ, скажем, добавить псевдоним, чтобы QtQuick 1.x работал в QQuickView (чтобы он фактически анализировался как QtQuick 2.0)?


person leemes    schedule 28.01.2014    source источник


Ответы (1)


Я заменил строку QtQuick x.y во всех файлах QML при их развертывании. Если у вас есть папка qml в исходном дереве и вы хотите иметь ту же папку qml в дереве сборки, вы можете развернуть папку, но замените строку, чтобы она соответствовала нужной версии QtQuick.

Следующее решение работает в системах POSIX, поскольку для него требуются некоторые инструменты командной строки; протестировано на Linux (Ubuntu). Может быть, кто-нибудь, имеющий опыт работы с командной строкой Windows, сможет добавить версию для Windows.

Добавьте в свой .pro: (в следующем коде предполагается, что из папки сборки исходная папка доступна с помощью ../src/; если это не так, измените путь, в котором находится комментарий ***)

// Define QT5 macro for use in C++, and select the correct module for QML:
greaterThan(QT_MAJOR_VERSION, 4) {
    DEFINES += QT5
    QT += quick
} else {
    QT += declarative
}

// Define qmake variables for QtQuick version, and if you want, QtQuick Controls:
equals(QT_MAJOR_VERSION, 4) {
    equals(QT_MINOR_VERSION, 7) {
        QT_QUICK_VERSION = 1.0
    }
    equals(QT_MINOR_VERSION, 8) {
        QT_QUICK_VERSION = 1.1
    }
}
equals(QT_MAJOR_VERSION, 5) {
    QT_QUICK_VERSION = 2.$${QT_MINOR_VERSION}
    equals(QT_MINOR_VERSION, 1): QT_QUICKCONTROLS_VERSION = 1.0
    equals(QT_MINOR_VERSION, 2): QT_QUICKCONTROLS_VERSION = 1.1
    equals(QT_MINOR_VERSION, 3): QT_QUICKCONTROLS_VERSION = 1.2
}

// Add a pre-build step which copies your qml folder
QtQuickVersion.target = FORCE
QtQuickVersion.commands = "rm -rf qml/;"
QtQuickVersion.commands += "cp -r ../src/qml/ .;"  // <-- *** Here is the source path
!isEmpty(QT_QUICK_VERSION) {
    QtQuickVersion.commands += "grep -rl 'QtQuick [0-9]\\.[0-9]' qml/ | xargs -r sed -i 's/QtQuick [0-9]\\.[0-9]/QtQuick $${QT_QUICK_VERSION}/g';"
}
!isEmpty(QT_QUICKCONTROLS_VERSION) {
    QtQuickVersion.commands += "grep -rl 'QtQuick.Controls [0-9]\\.[0-9]' qml/ | xargs -r sed -i 's/QtQuick.Controls [0-9]\\.[0-9]/QtQuick.Controls $${QT_QUICKCONTROLS_VERSION}/g';"
}

// Give the Makefile target *any* name which will *not* be created
// as a file, so the step is always executed
PRE_TARGETDEPS += FORCE
QMAKE_EXTRA_TARGETS += QtQuickVersion

В C ++ (main.cpp) вы можете затем создать QQuickView, который возвращается к QDeclarativeView для Qt 4:

#ifdef QT5

#include <QGuiApplication>
#include <QQuickView>
#include <QQmlEngine>

#else

#include <QApplication>
#include <QDeclarativeView>
#include <QDeclarativeEngine>
typedef QApplication QGuiApplication;
typedef QDeclarativeView QQuickView;
// The following is the official fallback for QStringLiteral,
// see qstring.h in Qt 5 after #ifndef QStringLiteral */
#define QStringLiteral(str) QString::fromUtf8("" str "", sizeof(str) - 1)
#endif


int main(int argc, char *argv[])
{
    QGuiApplication a(argc, argv);

    // (add qmlRegisterType etc.)

    // Open the QML view with the main QML document:
    QQuickView view;
    view.setSource(QUrl::fromLocalFile(QStringLiteral("qml/main.qml")));
    view.show();

    // Needed for "Qt.quit()" within QML:
    QObject::connect(view.engine(), SIGNAL(quit()), &a, SLOT(quit()));

    // I normally use this sizing behavior:
    view.setResizeMode(QQuickView::SizeRootObjectToView);

    return a.exec();
}

Файл QML qml/main.qml, открытый указанным выше кодом, может выглядеть следующим образом:

// This import will replaced with the largest supported QtQuick version:
import QtQuick 1.0

Rectangle {
    width: 450
    height: 200

    Text {
        anchors.centerIn: parent
        horizontalAlignment: Text.AlignHCenter
        font.pointSize: Math.min(parent.width / 10, parent.height / 5)

        // This text will also be replaced to show the correct QtQuick version:
        text: "Hello from\nQtQuick 1.0!"

        // Some fancy animations...
        SequentialAnimation on scale {
            running: true; loops: Animation.Infinite
            NumberAnimation { from: 1; to: .6; easing.type: Easing.InOutQuad; duration: 600 }
            NumberAnimation { from: .6; to: 1; easing.type: Easing.InOutQuad; duration: 600 }
        }
        SequentialAnimation on rotation {
            running: true; loops: Animation.Infinite
            NumberAnimation { from: -10; to: 10; easing.type: Easing.InOutQuad; duration: 2000 }
            NumberAnimation { from: 10; to: -10; easing.type: Easing.InOutQuad; duration: 2000 }
        }
    }

    MouseArea {
        anchors.fill: parent
        onClicked: Qt.quit()
    }
}

Файл QML содержит директиву импорта, которая выберет правильную версию QtQuick (вы можете проверить это в папке сборки). Строка в элементе Text также заменяется, поэтому вы легко увидите версию в этой демонстрации.

person leemes    schedule 28.01.2014