diff --git a/src/libcalamaresui/CMakeLists.txt b/src/libcalamaresui/CMakeLists.txt index 061a401bb..c603ca22d 100644 --- a/src/libcalamaresui/CMakeLists.txt +++ b/src/libcalamaresui/CMakeLists.txt @@ -16,6 +16,7 @@ set( calamaresui_SOURCES utils/CalamaresUtilsGui.cpp utils/ImageRegistry.cpp utils/Paste.cpp + utils/Qml.cpp viewpages/BlankViewStep.cpp viewpages/ExecutionViewStep.cpp diff --git a/src/libcalamaresui/utils/Qml.cpp b/src/libcalamaresui/utils/Qml.cpp new file mode 100644 index 000000000..1ea72e674 --- /dev/null +++ b/src/libcalamaresui/utils/Qml.cpp @@ -0,0 +1,52 @@ +/* === This file is part of Calamares - === + * + * Copyright 2020, Adriaan de Groot + * + * Calamares is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Calamares is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Calamares. If not, see . + */ + +#include "Qml.h" + +#include "utils/Logger.h" + +#include +#include +#include +#include + +namespace CalamaresUtils +{ + +void +callQMLFunction( QQuickItem* qmlObject, const char* method ) +{ + QByteArray methodSignature( method ); + methodSignature.append( "()" ); + + if ( qmlObject && qmlObject->metaObject()->indexOfMethod( methodSignature ) >= 0 ) + { + QVariant returnValue; + QMetaObject::invokeMethod( qmlObject, method, Q_RETURN_ARG( QVariant, returnValue ) ); + if ( !returnValue.isNull() ) + { + cDebug() << "QML" << methodSignature << "returned" << returnValue; + } + } + else if ( qmlObject ) + { + cDebug() << "QML" << methodSignature << "is missing."; + } +} + +} // namespace CalamaresUtils diff --git a/src/libcalamaresui/utils/Qml.h b/src/libcalamaresui/utils/Qml.h new file mode 100644 index 000000000..70f59e7ec --- /dev/null +++ b/src/libcalamaresui/utils/Qml.h @@ -0,0 +1,42 @@ +/* === This file is part of Calamares - === + * + * Copyright 2020, Adriaan de Groot + * + * Calamares is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Calamares is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Calamares. If not, see . + */ + +#ifndef UTILS_QML_H +#define UTILS_QML_H + +#include "DllMacro.h" + +class QQuickItem; + +namespace CalamaresUtils +{ + +/** @brief Calls the QML method @p method on @p qmlObject + * + * Pass in only the name of the method (e.g. onActivate). This function + * checks if the method exists (with no arguments) before trying to + * call it, so that no warnings are printed due to missing methods. + * + * If there is a return value from the QML method, it is logged (but not otherwise used). + */ +DLLEXPORT void +callQMLFunction( QQuickItem* qmlObject, const char* method ); + +} // namespace CalamaresUtils + +#endif diff --git a/src/libcalamaresui/viewpages/ExecutionViewStep.cpp b/src/libcalamaresui/viewpages/ExecutionViewStep.cpp index e0921910d..8ea918690 100644 --- a/src/libcalamaresui/viewpages/ExecutionViewStep.cpp +++ b/src/libcalamaresui/viewpages/ExecutionViewStep.cpp @@ -31,6 +31,7 @@ #include "utils/CalamaresUtilsGui.h" #include "utils/Dirs.h" #include "utils/Logger.h" +#include "utils/Qml.h" #include "utils/Retranslator.h" #include @@ -42,35 +43,6 @@ #include #include -/** @brief Calls the QML method @p method() - * - * Pass in only the name of the method (e.g. onActivate). This function - * checks if the method exists (with no arguments) before trying to - * call it, so that no warnings are printed due to missing methods. - * - * If there is a return value from the QML method, it is logged (but not otherwise used). - */ -static void -callQMLFunction( QQuickItem* qmlObject, const char* method ) -{ - QByteArray methodSignature( method ); - methodSignature.append( "()" ); - - if ( qmlObject && qmlObject->metaObject()->indexOfMethod( methodSignature ) >= 0 ) - { - QVariant returnValue; - QMetaObject::invokeMethod( qmlObject, method, Q_RETURN_ARG( QVariant, returnValue ) ); - if ( !returnValue.isNull() ) - { - cDebug() << "QML" << methodSignature << "returned" << returnValue; - } - } - else if ( qmlObject ) - { - cDebug() << "QML" << methodSignature << "is missing."; - } -} - namespace Calamares { @@ -205,7 +177,7 @@ changeSlideShowState( Slideshow state, QQuickItem* slideshow, QQuickWidget* widg if ( Branding::instance()->slideshowAPI() == 2 ) { // The QML was already loaded in the constructor, need to start it - callQMLFunction( slideshow, activate ? "onActivate" : "onLeave" ); + CalamaresUtils::callQMLFunction( slideshow, activate ? "onActivate" : "onLeave" ); } else if ( !Calamares::Branding::instance()->slideshowPath().isEmpty() ) { diff --git a/src/libcalamaresui/viewpages/QmlViewStep.cpp b/src/libcalamaresui/viewpages/QmlViewStep.cpp index b009d1626..2bfc72757 100644 --- a/src/libcalamaresui/viewpages/QmlViewStep.cpp +++ b/src/libcalamaresui/viewpages/QmlViewStep.cpp @@ -19,10 +19,12 @@ #include "QmlViewStep.h" #include "Branding.h" +#include "ViewManager.h" #include "utils/Dirs.h" #include "utils/Logger.h" #include "utils/NamedEnum.h" +#include "utils/Qml.h" #include "utils/Variant.h" #include "widgets/WaitingWidget.h" @@ -50,6 +52,36 @@ searchNames() return names; } +/// @brief State-change of the QML, for changeQMLState() +enum class QMLAction +{ + Start, + Stop +}; + +/** @brief Tells the QML we activated or left it. + * + * If @p action is @c QMLAction::Start, calls onActivate in the QML. + * If @p action is @c QMLAction::Stop, calls onLeave in the QML. + * + * Sets *activatedInCalamares* property on the QML as well (to true + * if @p action is @c QMLAction::Start, false otherwise). + */ +static void +changeQMLState( QMLAction action, QQuickItem* item ) +{ + static const char propertyName[] = "activatedInCalamares"; + + bool activate = action == QMLAction::Start; + CalamaresUtils::callQMLFunction( item, activate ? "onActivate" : "onLeave" ); + + auto property = item->property( propertyName ); + if ( property.isValid() && ( property.type() == QVariant::Bool ) && ( property.toBool() != activate ) ) + { + item->setProperty( propertyName, activate ); + } +} + namespace Calamares { @@ -80,57 +112,61 @@ QmlViewStep::prettyName() const } -} // namespace Calamares - bool -Calamares::QmlViewStep::isAtBeginning() const +QmlViewStep::isAtBeginning() const { return true; } bool -Calamares::QmlViewStep::isAtEnd() const +QmlViewStep::isAtEnd() const { return true; } bool -Calamares::QmlViewStep::isBackEnabled() const +QmlViewStep::isBackEnabled() const { return true; } bool -Calamares::QmlViewStep::isNextEnabled() const +QmlViewStep::isNextEnabled() const { return true; } Calamares::JobList -Calamares::QmlViewStep::jobs() const +QmlViewStep::jobs() const { return JobList(); } void -Calamares::QmlViewStep::onActivate() +QmlViewStep::onActivate() { - // TODO: call into QML + if ( m_qmlObject ) + { + changeQMLState( QMLAction::Start, m_qmlObject ); + } } void -Calamares::QmlViewStep::onLeave() +QmlViewStep::onLeave() { - // TODO: call into QML + if ( m_qmlObject ) + { + changeQMLState( QMLAction::Stop, m_qmlObject ); + } } QWidget* -Calamares::QmlViewStep::widget() +QmlViewStep::widget() { return m_widget; } void -Calamares::QmlViewStep::loadComplete() +QmlViewStep::loadComplete() { cDebug() << "QML component" << m_qmlFileName << m_qmlComponent->status(); if ( m_qmlComponent->status() == QQmlComponent::Error ) @@ -163,7 +199,7 @@ Calamares::QmlViewStep::loadComplete() } void -Calamares::QmlViewStep::showQml() +QmlViewStep::showQml() { if ( !m_qmlWidget || !m_qmlObject ) { @@ -181,6 +217,13 @@ Calamares::QmlViewStep::showQml() { cDebug() << "showQml() called twice"; } + + if ( ViewManager::instance()->currentStep() == this ) + { + // We're alreay visible! Must have been slow QML loading, and we + // passed onActivate already. + changeQMLState( QMLAction::Start, m_qmlObject ); + } } @@ -190,7 +233,7 @@ Calamares::QmlViewStep::showQml() * is badly configured). */ QString -searchQmlFile( Calamares::QmlViewStep::QmlSearch method, const QString& configuredName, const QString& moduleName ) +searchQmlFile( QmlViewStep::QmlSearch method, const QString& configuredName, const QString& moduleName ) { using QmlSearch = Calamares::QmlViewStep::QmlSearch; @@ -235,7 +278,7 @@ searchQmlFile( Calamares::QmlViewStep::QmlSearch method, const QString& configur } void -Calamares::QmlViewStep::setConfigurationMap( const QVariantMap& configurationMap ) +QmlViewStep::setConfigurationMap( const QVariantMap& configurationMap ) { bool ok = false; m_searchMethod = searchNames().find( CalamaresUtils::getString( configurationMap, "search" ), ok ); @@ -270,8 +313,10 @@ Calamares::QmlViewStep::setConfigurationMap( const QVariantMap& configurationMap } void -Calamares::QmlViewStep::showFailedQml() +QmlViewStep::showFailedQml() { cWarning() << "QmlViewStep" << moduleInstanceKey() << "loading failed."; m_spinner->setText( prettyName() + ' ' + tr( "Loading failed." ) ); } + +} // namespace Calamares