Merge branch 'master' of https://github.com/calamares/calamares into development

This commit is contained in:
Philip Müller 2019-08-27 12:20:54 -04:00
commit a9732a71ae
7 changed files with 109 additions and 27 deletions

View File

@ -20,6 +20,9 @@ This release contains contributions from (alphabetically by first name):
(maintained!) upstream version instead. It also gives us KMacroExpander
everywhere, which will simplify code for handling substitutions
in configuration files.
- *Slideshows* now have a new property *activatedInCalamares* which
controls the keyboard shortcuts (and can control timers and other
properties of the slideshow, too).
## Modules ##

View File

@ -66,6 +66,16 @@ The setting *slideshowAPI* in `branding.desc` indicates which one to use
for a given branding slideshow. Which API to use is really a function of
the QML. Expect the version 1 API to be deprecated in the course of Calamares 3.3.
In Calamares 3.2.13 support for activation notification to the QML
parts is improved:
- If the root object has a property *activatedInCalamares* (the examples do),
then that property is set to *true* when the slideshow becomes visible
(activated) and is set to *false* when the slideshow is hidden (e.g.
when the installation phase is done).
- The *actvatedInCalamares* property can be used to set up timers also in V1.
- The keyboard shortcuts in the example slideshow are enabled only while
the slideshow is visible.
## Translations

View File

@ -25,14 +25,14 @@ Presentation
id: presentation
function nextSlide() {
console.log("Next slide");
console.log("QML Component (default slideshow) Next slide");
presentation.goToNextSlide();
}
Timer {
id: advanceTimer
interval: 1000
running: false
running: presentation.activatedInCalamares
repeat: true
onTriggered: nextSlide()
}
@ -68,9 +68,19 @@ Presentation
centeredText: qsTr("This is a third Slide element.")
}
// When this slideshow is loaded as a V1 slideshow, only
// activatedInCalamares is set, which starts the timer (see above).
//
// In V2, also the onActivate() and onLeave() methods are called.
// These example functions log a message (and re-start the slides
// from the first).
function onActivate() {
presentation.currentSlide = 0;
advanceTimer.running = true
console.log("QML Component (default slideshow) activated");
presentation.currentSlide = 0;
}
function onLeave() {
console.log("QML Component (default slideshow) deactivated");
}
}

View File

@ -226,7 +226,9 @@ Branding::Branding( const QString& brandingFilePath, QObject* parent )
QString pathString = slideShowPictures[ i ];
QFileInfo imageFi( componentDir.absoluteFilePath( pathString ) );
if ( !imageFi.exists() )
{
bail( QString( "Slideshow file %1 does not exist." ).arg( imageFi.absoluteFilePath() ) );
}
slideShowPictures[ i ] = imageFi.absoluteFilePath();
}

View File

@ -179,12 +179,63 @@ ExecutionViewStep::loadQmlV2()
}
}
/// @brief State-change of the slideshow, for changeSlideShowState()
enum class Slideshow
{
Start,
Stop
};
/** @brief Tells the slideshow we activated or left the show.
*
* If @p state is @c Slideshow::Start, calls suitable activation procedures.
* If @p state is @c Slideshow::Stop, calls deactivation procedures.
*
* Applies V1 and V2 QML activation / deactivation:
* - V1 loads the QML in @p widget on activation. Sets root object property
* *activatedInCalamares* as appropriate.
* - V2 calls onActivate() or onLeave() in the QML as appropriate. Also
* sets the *activatedInCalamares* property.
*/
static void
changeSlideShowState( Slideshow state, QQuickItem* slideshow, QQuickWidget* widget )
{
bool activate = state == Slideshow::Start;
if ( Branding::instance()->slideshowAPI() == 2 )
{
// The QML was already loaded in the constructor, need to start it
callQMLFunction( slideshow, activate ? "onActivate" : "onLeave" );
}
else if ( !Calamares::Branding::instance()->slideshowPath().isEmpty() )
{
// API version 1 assumes onCompleted is the trigger
if ( activate )
{
widget->setSource( QUrl::fromLocalFile( Calamares::Branding::instance()->slideshowPath() ) );
}
// needs the root object for property setting, below
slideshow = widget->rootObject();
}
// V1 API has picked up the root object for use, V2 passed it in.
if ( slideshow )
{
static const char propertyName[] = "activatedInCalamares";
auto property = slideshow->property( propertyName );
if ( property.isValid() && ( property.type() == QVariant::Bool ) && ( property.toBool() != activate ) )
{
slideshow->setProperty( propertyName, activate );
}
}
}
void
ExecutionViewStep::loadQmlV2Complete()
{
if ( m_qmlComponent && m_qmlComponent->isReady() && !m_qmlObject )
{
cDebug() << "QML loading complete, API 2";
cDebug() << "QML component complete, API 2";
// Don't do this again
disconnect( m_qmlComponent, &QQmlComponent::statusChanged, this, &ExecutionViewStep::loadQmlV2Complete );
@ -196,6 +247,8 @@ ExecutionViewStep::loadQmlV2Complete()
}
else
{
cDebug() << Logger::SubEntry << "Loading" << Calamares::Branding::instance()->slideshowPath();
// setContent() is public API, but not documented publicly.
// It is marked \internal in the Qt sources, but does exactly
// what is needed: sets up visual parent by replacing the root
@ -206,7 +259,7 @@ ExecutionViewStep::loadQmlV2Complete()
{
// We're alreay visible! Must have been slow QML loading, and we
// passed onActivate already.
callQMLFunction( m_qmlObject, "onActivate" );
changeSlideShowState( Slideshow::Start, m_qmlObject, m_qmlShow );
}
}
}
@ -215,16 +268,7 @@ ExecutionViewStep::loadQmlV2Complete()
void
ExecutionViewStep::onActivate()
{
if ( Branding::instance()->slideshowAPI() == 2 )
{
// The QML was already loaded in the constructor, need to start it
callQMLFunction( m_qmlObject, "onActivate" );
}
else if ( !Calamares::Branding::instance()->slideshowPath().isEmpty() )
{
// API version 1 assumes onCompleted is the trigger
m_qmlShow->setSource( QUrl::fromLocalFile( Calamares::Branding::instance()->slideshowPath() ) );
}
changeSlideShowState( Slideshow::Start, m_qmlObject, m_qmlShow );
JobQueue* queue = JobQueue::instance();
foreach ( const QString& instanceKey, m_jobInstanceKeys )
@ -272,10 +316,10 @@ ExecutionViewStep::updateFromJobQueue( qreal percent, const QString& message )
void
ExecutionViewStep::onLeave()
{
changeSlideShowState( Slideshow::Stop, m_qmlObject, m_qmlShow );
// API version 2 is explicitly stopped; version 1 keeps running
if ( Branding::instance()->slideshowAPI() == 2 )
{
callQMLFunction( m_qmlObject, "onLeave" );
delete m_qmlObject;
m_qmlObject = nullptr;
}

View File

@ -28,6 +28,7 @@
#include "GlobalStorage.h"
#include "JobQueue.h"
#include "utils/CalamaresUtilsSystem.h"
#include "utils/Logger.h"
DummyCppJob::DummyCppJob( QObject* parent )
@ -113,9 +114,10 @@ Calamares::JobResult
DummyCppJob::exec()
{
// Ported from dummypython
QProcess::execute( "/bin/sh",
QStringList() << "-c"
<< "touch ~/calamares-dummycpp" );
CalamaresUtils::System::runCommand( CalamaresUtils::System::RunLocation::RunInHost,
QStringList() << "/bin/sh"
<< "-c"
<< "touch ~/calamares-dummycpp" );
QString accumulator = QDateTime::currentDateTimeUtc().toString( Qt::ISODate ) + '\n';
accumulator += QStringLiteral( "Calamares version: " ) + CALAMARES_VERSION_SHORT + '\n';
accumulator += QStringLiteral( "This job's name: " ) + prettyName() + '\n';

View File

@ -8,6 +8,9 @@
* (this and the 'c' key make sense in a *presentation*
* slideshow, not in a passive slideshow like Calamares)
* - remove quit key
* Copyright 2019, Adriaan de Groot <groot@kde.org>
* - Support "V2" loading
* - Disable shortcuts until the content is visible in Calamares
*
* SPDX-License-Identifier: LGPL-2.1
* License-Filename: LICENSES/LGPLv2.1-Presentation
@ -77,6 +80,14 @@ Item {
property string fontFamily: "Helvetica"
property string codeFontFamily: "Courier New"
// This is set by the C++ part of Calamares when the slideshow
// becomes visible. You can connect it to a timer, or whatever
// else needs to start only when the slideshow becomes visible.
//
// It is used in this example also to keep the keyboard shortcuts
// enabled only while the slideshow is active.
property bool activatedInCalamares: false
// Private API
property int _lastShownSlide: 0
@ -136,17 +147,17 @@ Item {
Keys.onLeftPressed: goToPreviousSlide()
// navigate with arrow keys
Shortcut { sequence: StandardKey.MoveToNextLine; enabled: root.arrowNavigation; onActivated: goToNextSlide() }
Shortcut { sequence: StandardKey.MoveToPreviousLine; enabled: root.arrowNavigation; onActivated: goToPreviousSlide() }
Shortcut { sequence: StandardKey.MoveToNextChar; enabled: root.arrowNavigation; onActivated: goToNextSlide() }
Shortcut { sequence: StandardKey.MoveToPreviousChar; enabled: root.arrowNavigation; onActivated: goToPreviousSlide() }
Shortcut { sequence: StandardKey.MoveToNextLine; enabled: root.activatedInCalamares && root .arrowNavigation; onActivated: goToNextSlide() }
Shortcut { sequence: StandardKey.MoveToPreviousLine; enabled: root.activatedInCalamares && root.arrowNavigation; onActivated: goToPreviousSlide() }
Shortcut { sequence: StandardKey.MoveToNextChar; enabled: root.activatedInCalamares && root.arrowNavigation; onActivated: goToNextSlide() }
Shortcut { sequence: StandardKey.MoveToPreviousChar; enabled: root.activatedInCalamares && root.arrowNavigation; onActivated: goToPreviousSlide() }
// presentation-specific single-key shortcuts (which interfere with normal typing)
Shortcut { sequence: " "; enabled: root.keyShortcutsEnabled; onActivated: goToNextSlide() }
Shortcut { sequence: " "; enabled: root.activatedInCalamares && root.keyShortcutsEnabled; onActivated: goToNextSlide() }
// standard shortcuts
Shortcut { sequence: StandardKey.MoveToNextPage; onActivated: goToNextSlide() }
Shortcut { sequence: StandardKey.MoveToPreviousPage; onActivated: goToPreviousSlide() }
Shortcut { sequence: StandardKey.MoveToNextPage; enabled: root.activatedInCalamares; onActivated: goToNextSlide() }
Shortcut { sequence: StandardKey.MoveToPreviousPage; enabled: root.activatedInCalamares; onActivated: goToPreviousSlide() }
MouseArea {
id: mouseArea