From f299b86a3b3f0a16c73276aad59f094afd65ee9e Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 21 Mar 2019 17:46:04 +0100 Subject: [PATCH 01/21] [license] start to document license.conf - document keys and values in a way consistent with other modules - document **intended** use of local URLs. --- src/modules/license/license.conf | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/modules/license/license.conf b/src/modules/license/license.conf index c99b1529d..ac4367f8b 100644 --- a/src/modules/license/license.conf +++ b/src/modules/license/license.conf @@ -1,14 +1,26 @@ # Configuration file for License viewmodule, Calamares # Syntax is YAML 1.2 --- -# YAML: list of maps. +# Define a list of licenses which may / must be accepted before continuing. +# +# Each entry in this list has the following keys: +# - id Entry identifier, must be unique. Not user visible. YAML: string. +# - name Pretty name for the software product, user visible and untranslatable. YAML: string. +# - vendor Pretty name for the software vendor, user visible and untranslatable. YAML: string, optional, default is empty. +# - type Package type identifier for presentation, not user visible but affects user visible strings. YAML: string. +# values: driver, gpudriver, browserplugin, codec, package, software; optional, default is software. +# - required If set to true, the user cannot proceed without accepting this license. YAML: boolean, optional, default is false. +# - url A URL for the license; a remote URL is not shown in Calamares, but a link +# to the URL is provided, which opens in the default web browser. A local +# URL (i.e. file:///) assumes that the contents are HTML or plain text, and +# displays the license in-line. YAML: string, mandatory. entries: -- id: nvidia # Entry identifier, must be unique. Not user visible. YAML: string. - name: Nvidia # Pretty name for the software product, user visible and untranslatable. YAML: string. - vendor: Nvidia Corporation # Pretty name for the software vendor, user visible and untranslatable. YAML: string, optional, default is empty. - type: driver # Package type for presentation, not user visible but affects user visible strings. YAML: string, allowed values: driver, gpudriver, browserplugin, codec, package, software; optional, default is software. - url: http://developer.download.nvidia.com/cg/Cg_3.0/license.pdf # Url of license text to display in a web view. YAML: string. - required: false # If set to true, the user cannot proceed without accepting this license. YAML: boolean, optional, default is false. +- id: nvidia + name: Nvidia + vendor: Nvidia Corporation + type: driver + url: http://developer.download.nvidia.com/cg/Cg_3.0/license.pdf + required: false - id: amd name: Catalyst vendor: "Advanced Micro Devices, Inc." From 81016667ae0a8abd4f2e6979ff348e2ce52652de Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 22 Mar 2019 18:53:00 +0100 Subject: [PATCH 02/21] [license] Change to enum class - non-functional change, just chasing modern C++ --- src/modules/license/LicensePage.cpp | 12 ++++++------ src/modules/license/LicensePage.h | 5 +++-- src/modules/license/LicenseViewStep.cpp | 12 ++++++------ 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/modules/license/LicensePage.cpp b/src/modules/license/LicensePage.cpp index 1fb3de7a8..8fe0a581f 100644 --- a/src/modules/license/LicensePage.cpp +++ b/src/modules/license/LicensePage.cpp @@ -154,39 +154,39 @@ LicensePage::setEntries( const QList< LicenseEntry >& entriesList ) QString productDescription; switch ( entry.type ) { - case LicenseEntry::Driver: + case LicenseEntry::Type::Driver: //: %1 is an untranslatable product name, example: Creative Audigy driver productDescription = tr( "%1 driver
" "by %2" ) .arg( entry.prettyName ) .arg( entry.prettyVendor ); break; - case LicenseEntry::GpuDriver: + case LicenseEntry::Type::GpuDriver: //: %1 is usually a vendor name, example: Nvidia graphics driver productDescription = tr( "%1 graphics driver
" "by %2" ) .arg( entry.prettyName ) .arg( entry.prettyVendor ); break; - case LicenseEntry::BrowserPlugin: + case LicenseEntry::Type::BrowserPlugin: productDescription = tr( "%1 browser plugin
" "by %2" ) .arg( entry.prettyName ) .arg( entry.prettyVendor ); break; - case LicenseEntry::Codec: + case LicenseEntry::Type::Codec: productDescription = tr( "%1 codec
" "by %2" ) .arg( entry.prettyName ) .arg( entry.prettyVendor ); break; - case LicenseEntry::Package: + case LicenseEntry::Type::Package: productDescription = tr( "%1 package
" "by %2" ) .arg( entry.prettyName ) .arg( entry.prettyVendor ); break; - case LicenseEntry::Software: + case LicenseEntry::Type::Software: productDescription = tr( "%1
" "by %2" ) .arg( entry.prettyName ) diff --git a/src/modules/license/LicensePage.h b/src/modules/license/LicensePage.h index 300e9e309..03801467c 100644 --- a/src/modules/license/LicensePage.h +++ b/src/modules/license/LicensePage.h @@ -30,9 +30,10 @@ namespace Ui class LicensePage; } -struct LicenseEntry +class LicenseEntry { - enum Type +public: + enum class Type { Software = 0, Driver, diff --git a/src/modules/license/LicenseViewStep.cpp b/src/modules/license/LicenseViewStep.cpp index 96a7b8660..d7a4c4930 100644 --- a/src/modules/license/LicenseViewStep.cpp +++ b/src/modules/license/LicenseViewStep.cpp @@ -121,17 +121,17 @@ LicenseViewStep::setConfigurationMap( const QVariantMap& configurationMap ) QString entryType = entryMap.value( "type", "software" ).toString(); if ( entryType == "driver" ) - entry.type = LicenseEntry::Driver; + entry.type = LicenseEntry::Type::Driver; else if ( entryType == "gpudriver" ) - entry.type = LicenseEntry::GpuDriver; + entry.type = LicenseEntry::Type::GpuDriver; else if ( entryType == "browserplugin" ) - entry.type = LicenseEntry::BrowserPlugin; + entry.type = LicenseEntry::Type::BrowserPlugin; else if ( entryType == "codec" ) - entry.type = LicenseEntry::Codec; + entry.type = LicenseEntry::Type::Codec; else if ( entryType == "package" ) - entry.type = LicenseEntry::Package; + entry.type = LicenseEntry::Type::Package; else - entry.type = LicenseEntry::Software; + entry.type = LicenseEntry::Type::Software; entriesList.append( entry ); } From 614bd3c6de8dc25c6e890c000a4e2648799b371c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 22 Mar 2019 19:31:39 +0100 Subject: [PATCH 03/21] [license] Move logic to LicenseEntry class --- src/modules/license/LicensePage.cpp | 28 ++++++++++++++++++++++ src/modules/license/LicensePage.h | 5 ++++ src/modules/license/LicenseViewStep.cpp | 31 +++---------------------- 3 files changed, 36 insertions(+), 28 deletions(-) diff --git a/src/modules/license/LicensePage.cpp b/src/modules/license/LicensePage.cpp index 8fe0a581f..acbbd8737 100644 --- a/src/modules/license/LicensePage.cpp +++ b/src/modules/license/LicensePage.cpp @@ -25,6 +25,7 @@ #include "JobQueue.h" #include "GlobalStorage.h" #include "utils/Logger.h" +#include "utils/CalamaresUtils.h" #include "utils/CalamaresUtilsGui.h" #include "utils/Retranslator.h" #include "ViewManager.h" @@ -37,6 +38,33 @@ #include #include +LicenseEntry::LicenseEntry(const QVariantMap& conf) +{ + if ( !conf.contains( "id" ) || !conf.contains( "name" ) || !conf.contains( "url" ) ) + return; + + id = conf[ "id" ].toString(); + prettyName = conf[ "name" ].toString(); + prettyVendor = conf.value( "vendor" ).toString(); + url = QUrl( conf[ "url" ].toString() ); + + required = CalamaresUtils::getBool( conf, "required", false ); + + QString entryType = conf.value( "type", "software" ).toString(); + if ( entryType == "driver" ) + type = LicenseEntry::Type::Driver; + else if ( entryType == "gpudriver" ) + type = LicenseEntry::Type::GpuDriver; + else if ( entryType == "browserplugin" ) + type = LicenseEntry::Type::BrowserPlugin; + else if ( entryType == "codec" ) + type = LicenseEntry::Type::Codec; + else if ( entryType == "package" ) + type = LicenseEntry::Type::Package; + else + type = LicenseEntry::Type::Software; +} + LicensePage::LicensePage(QWidget *parent) : QWidget( parent ) , ui( new Ui::LicensePage ) diff --git a/src/modules/license/LicensePage.h b/src/modules/license/LicensePage.h index 03801467c..f0d490a8b 100644 --- a/src/modules/license/LicensePage.h +++ b/src/modules/license/LicensePage.h @@ -43,6 +43,11 @@ public: Package }; + LicenseEntry( const QVariantMap& conf ); + LicenseEntry( const LicenseEntry& ) = default; + + bool isValid() const { return !id.isEmpty(); } + QString id; QString prettyName; QString prettyVendor; diff --git a/src/modules/license/LicenseViewStep.cpp b/src/modules/license/LicenseViewStep.cpp index d7a4c4930..f5f4b6e2b 100644 --- a/src/modules/license/LicenseViewStep.cpp +++ b/src/modules/license/LicenseViewStep.cpp @@ -106,34 +106,9 @@ LicenseViewStep::setConfigurationMap( const QVariantMap& configurationMap ) if ( entryV.type() != QVariant::Map ) continue; - QVariantMap entryMap = entryV.toMap(); - if ( !entryMap.contains( "id" ) || - !entryMap.contains( "name" ) || - !entryMap.contains( "url" ) ) - continue; - - LicenseEntry entry; - entry.id = entryMap[ "id" ].toString(); - entry.prettyName = entryMap[ "name" ].toString(); - entry.prettyVendor =entryMap.value( "vendor" ).toString(); - entry.url = QUrl( entryMap[ "url" ].toString() ); - entry.required = entryMap.value( "required", QVariant( false ) ).toBool(); - - QString entryType = entryMap.value( "type", "software" ).toString(); - if ( entryType == "driver" ) - entry.type = LicenseEntry::Type::Driver; - else if ( entryType == "gpudriver" ) - entry.type = LicenseEntry::Type::GpuDriver; - else if ( entryType == "browserplugin" ) - entry.type = LicenseEntry::Type::BrowserPlugin; - else if ( entryType == "codec" ) - entry.type = LicenseEntry::Type::Codec; - else if ( entryType == "package" ) - entry.type = LicenseEntry::Type::Package; - else - entry.type = LicenseEntry::Type::Software; - - entriesList.append( entry ); + LicenseEntry entry( entryV.toMap() ); + if ( entry.isValid() ) + entriesList.append( entry ); } } From dc006d58b222ed725494b0ad5a7a875fd8d2a002 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 20 Apr 2019 11:43:19 -0400 Subject: [PATCH 04/21] [license] Use NamedEnum --- src/modules/license/LicensePage.cpp | 37 +++++++++++++++++------------ 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/src/modules/license/LicensePage.cpp b/src/modules/license/LicensePage.cpp index acbbd8737..cf43ba66b 100644 --- a/src/modules/license/LicensePage.cpp +++ b/src/modules/license/LicensePage.cpp @@ -22,13 +22,16 @@ #include "LicensePage.h" #include "ui_LicensePage.h" + #include "JobQueue.h" #include "GlobalStorage.h" -#include "utils/Logger.h" +#include "ViewManager.h" + #include "utils/CalamaresUtils.h" #include "utils/CalamaresUtilsGui.h" +#include "utils/Logger.h" +#include "utils/NamedEnum.h" #include "utils/Retranslator.h" -#include "ViewManager.h" #include #include @@ -38,6 +41,21 @@ #include #include +static const NamedEnumTable< LicenseEntry::Type >& +typeNames() +{ + static const NamedEnumTable< LicenseEntry::Type > names{ + { QStringLiteral( "software" ), LicenseEntry::Type::Software}, + { QStringLiteral( "driver" ), LicenseEntry::Type::Driver }, + { QStringLiteral( "gpudriver" ), LicenseEntry::Type::GpuDriver }, + { QStringLiteral( "browserplugin" ), LicenseEntry::Type::BrowserPlugin}, + { QStringLiteral( "codec" ), LicenseEntry::Type::Codec }, + { QStringLiteral( "package" ), LicenseEntry::Type::Package } + }; + + return names; +} + LicenseEntry::LicenseEntry(const QVariantMap& conf) { if ( !conf.contains( "id" ) || !conf.contains( "name" ) || !conf.contains( "url" ) ) @@ -50,19 +68,8 @@ LicenseEntry::LicenseEntry(const QVariantMap& conf) required = CalamaresUtils::getBool( conf, "required", false ); - QString entryType = conf.value( "type", "software" ).toString(); - if ( entryType == "driver" ) - type = LicenseEntry::Type::Driver; - else if ( entryType == "gpudriver" ) - type = LicenseEntry::Type::GpuDriver; - else if ( entryType == "browserplugin" ) - type = LicenseEntry::Type::BrowserPlugin; - else if ( entryType == "codec" ) - type = LicenseEntry::Type::Codec; - else if ( entryType == "package" ) - type = LicenseEntry::Type::Package; - else - type = LicenseEntry::Type::Software; + bool ok = false; + type = typeNames().find( conf.value( "type", "software" ).toString(), ok ); } LicensePage::LicensePage(QWidget *parent) From 937f33244144f1d834086fe34b064631f0b2cad1 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 20 Apr 2019 11:52:22 -0400 Subject: [PATCH 05/21] [license] Refactor LicenseEntry - Follow Calamares conventions for member naming - Switch to struct since everything is public anyway --- src/modules/license/LicensePage.cpp | 49 +++++++++++++++-------------- src/modules/license/LicensePage.h | 22 +++++++------ 2 files changed, 39 insertions(+), 32 deletions(-) diff --git a/src/modules/license/LicensePage.cpp b/src/modules/license/LicensePage.cpp index cf43ba66b..f21c222a2 100644 --- a/src/modules/license/LicensePage.cpp +++ b/src/modules/license/LicensePage.cpp @@ -41,8 +41,8 @@ #include #include -static const NamedEnumTable< LicenseEntry::Type >& -typeNames() +const NamedEnumTable< LicenseEntry::Type >& +LicenseEntry::typeNames() { static const NamedEnumTable< LicenseEntry::Type > names{ { QStringLiteral( "software" ), LicenseEntry::Type::Software}, @@ -61,15 +61,18 @@ LicenseEntry::LicenseEntry(const QVariantMap& conf) if ( !conf.contains( "id" ) || !conf.contains( "name" ) || !conf.contains( "url" ) ) return; - id = conf[ "id" ].toString(); - prettyName = conf[ "name" ].toString(); - prettyVendor = conf.value( "vendor" ).toString(); - url = QUrl( conf[ "url" ].toString() ); + m_id = conf[ "id" ].toString(); + m_prettyName = conf[ "name" ].toString(); + m_prettyVendor = conf.value( "vendor" ).toString(); + m_url = QUrl( conf[ "url" ].toString() ); - required = CalamaresUtils::getBool( conf, "required", false ); + m_required = CalamaresUtils::getBool( conf, "required", false ); bool ok = false; - type = typeNames().find( conf.value( "type", "software" ).toString(), ok ); + QString typeString = conf.value( "type", "software" ).toString(); + m_type = typeNames().find( typeString, ok ); + if ( !ok ) + cWarning() << "License entry" << m_id << "has unknown type" << typeString << "(using 'software')"; } LicensePage::LicensePage(QWidget *parent) @@ -134,7 +137,7 @@ LicensePage::setEntries( const QList< LicenseEntry >& entriesList ) bool required = false; for ( const LicenseEntry& entry : entriesList ) { - if ( entry.required ) + if ( entry.m_required ) { required = true; break; @@ -187,45 +190,45 @@ LicensePage::setEntries( const QList< LicenseEntry >& entriesList ) label->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Minimum ); QString productDescription; - switch ( entry.type ) + switch ( entry.m_type ) { case LicenseEntry::Type::Driver: //: %1 is an untranslatable product name, example: Creative Audigy driver productDescription = tr( "%1 driver
" "by %2" ) - .arg( entry.prettyName ) - .arg( entry.prettyVendor ); + .arg( entry.m_prettyName ) + .arg( entry.m_prettyVendor ); break; case LicenseEntry::Type::GpuDriver: //: %1 is usually a vendor name, example: Nvidia graphics driver productDescription = tr( "%1 graphics driver
" "by %2" ) - .arg( entry.prettyName ) - .arg( entry.prettyVendor ); + .arg( entry.m_prettyName ) + .arg( entry.m_prettyVendor ); break; case LicenseEntry::Type::BrowserPlugin: productDescription = tr( "%1 browser plugin
" "by %2" ) - .arg( entry.prettyName ) - .arg( entry.prettyVendor ); + .arg( entry.m_prettyName ) + .arg( entry.m_prettyVendor ); break; case LicenseEntry::Type::Codec: productDescription = tr( "%1 codec
" "by %2" ) - .arg( entry.prettyName ) - .arg( entry.prettyVendor ); + .arg( entry.m_prettyName ) + .arg( entry.m_prettyVendor ); break; case LicenseEntry::Type::Package: productDescription = tr( "%1 package
" "by %2" ) - .arg( entry.prettyName ) - .arg( entry.prettyVendor ); + .arg( entry.m_prettyName ) + .arg( entry.m_prettyVendor ); break; case LicenseEntry::Type::Software: productDescription = tr( "%1
" "by %2" ) - .arg( entry.prettyName ) - .arg( entry.prettyVendor ); + .arg( entry.m_prettyName ) + .arg( entry.m_prettyVendor ); } label->setText( productDescription ); @@ -235,7 +238,7 @@ LicensePage::setEntries( const QList< LicenseEntry >& entriesList ) viewLicenseLabel->setOpenExternalLinks( true ); viewLicenseLabel->setAlignment( Qt::AlignVCenter | Qt::AlignRight ); viewLicenseLabel->setText( tr( "view license agreement" ) - .arg( entry.url.toString() ) ); + .arg( entry.m_url.toString() ) ); ui->licenseEntriesLayout->addWidget( widget ); } diff --git a/src/modules/license/LicensePage.h b/src/modules/license/LicensePage.h index f0d490a8b..4fbd163eb 100644 --- a/src/modules/license/LicensePage.h +++ b/src/modules/license/LicensePage.h @@ -22,6 +22,8 @@ #ifndef LICENSEPAGE_H #define LICENSEPAGE_H +#include "utils/NamedEnum.h" + #include #include @@ -30,9 +32,8 @@ namespace Ui class LicensePage; } -class LicenseEntry +struct LicenseEntry { -public: enum class Type { Software = 0, @@ -43,17 +44,20 @@ public: Package }; + /// @brief Lookup table for the enums + const NamedEnumTable< Type >& typeNames(); + LicenseEntry( const QVariantMap& conf ); LicenseEntry( const LicenseEntry& ) = default; - bool isValid() const { return !id.isEmpty(); } + bool isValid() const { return !m_id.isEmpty(); } - QString id; - QString prettyName; - QString prettyVendor; - Type type; - QUrl url; - bool required; + QString m_id; + QString m_prettyName; + QString m_prettyVendor; + Type m_type; + QUrl m_url; + bool m_required; }; class LicensePage : public QWidget From c245238b89a9ec7d979cedfee4b967a99ade80a1 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 20 Apr 2019 11:58:01 -0400 Subject: [PATCH 06/21] [license] Use standard algorithms, simplify code - Introduce isRequired() for readability later - Use std::any_of instead of rolling own loop --- src/modules/license/LicensePage.cpp | 12 +++--------- src/modules/license/LicensePage.h | 1 + 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/modules/license/LicensePage.cpp b/src/modules/license/LicensePage.cpp index f21c222a2..1c1129513 100644 --- a/src/modules/license/LicensePage.cpp +++ b/src/modules/license/LicensePage.cpp @@ -41,6 +41,8 @@ #include #include +#include + const NamedEnumTable< LicenseEntry::Type >& LicenseEntry::typeNames() { @@ -134,15 +136,7 @@ LicensePage::setEntries( const QList< LicenseEntry >& entriesList ) { CalamaresUtils::clearLayout( ui->licenseEntriesLayout ); - bool required = false; - for ( const LicenseEntry& entry : entriesList ) - { - if ( entry.m_required ) - { - required = true; - break; - } - } + const bool required = std::any_of( entriesList.cbegin(), entriesList.cend(), []( const LicenseEntry& e ){ return e.m_required; }); m_isNextEnabled = !required; nextStatusChanged( m_isNextEnabled ); diff --git a/src/modules/license/LicensePage.h b/src/modules/license/LicensePage.h index 4fbd163eb..b2e343602 100644 --- a/src/modules/license/LicensePage.h +++ b/src/modules/license/LicensePage.h @@ -51,6 +51,7 @@ struct LicenseEntry LicenseEntry( const LicenseEntry& ) = default; bool isValid() const { return !m_id.isEmpty(); } + bool isRequired() const { return m_required; } QString m_id; QString m_prettyName; From d2957fbad3ca07ffc6a5a06924e450f26d572fad Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 20 Apr 2019 15:21:15 -0400 Subject: [PATCH 07/21] [license] Handle the case where all the licenses are optional - If all of the licenses are optional, you should be able to continue without accepting. Refactor to a single visible slot to check the conditions. - Always set the globalsettings value; to "false" on entry to make sure it's there. - When setting the list of entries, check the conditions (because if the list is empty, or all of them are optional, then it's ok to continue). FIXES #1124 FIXES #1125 --- src/modules/license/LicensePage.cpp | 53 ++++++++++++++++++----------- src/modules/license/LicensePage.h | 20 ++++++++++- 2 files changed, 52 insertions(+), 21 deletions(-) diff --git a/src/modules/license/LicensePage.cpp b/src/modules/license/LicensePage.cpp index 1c1129513..29ed4d555 100644 --- a/src/modules/license/LicensePage.cpp +++ b/src/modules/license/LicensePage.cpp @@ -106,24 +106,9 @@ LicensePage::LicensePage(QWidget *parent) "padding: 2px; }" ); ui->acceptFrame->layout()->setMargin( CalamaresUtils::defaultFontHeight() / 2 ); - connect( ui->acceptCheckBox, &QCheckBox::toggled, - this, [ this ]( bool checked ) - { - Calamares::JobQueue::instance()->globalStorage()->insert( "licenseAgree", checked ); - m_isNextEnabled = checked; - if ( !checked ) - { - ui->acceptFrame->setStyleSheet( "#acceptFrame { border: 1px solid red;" - "background-color: #fff8f8;" - "border-radius: 4px;" - "padding: 2px; }" ); - } - else - { - ui->acceptFrame->setStyleSheet( "#acceptFrame { padding: 3px }" ); - } - emit nextStatusChanged( checked ); - } ); + updateGlobalStorage( false ); // Have not agreed yet + + connect( ui->acceptCheckBox, &QCheckBox::toggled, this, &LicensePage::checkAcceptance ); CALAMARES_RETRANSLATE( ui->acceptCheckBox->setText( tr( "I accept the terms and conditions above." ) ); @@ -137,9 +122,12 @@ LicensePage::setEntries( const QList< LicenseEntry >& entriesList ) CalamaresUtils::clearLayout( ui->licenseEntriesLayout ); const bool required = std::any_of( entriesList.cbegin(), entriesList.cend(), []( const LicenseEntry& e ){ return e.m_required; }); + if ( entriesList.isEmpty() ) + m_allLicensesOptional = true; + else + m_allLicensesOptional = !required; - m_isNextEnabled = !required; - nextStatusChanged( m_isNextEnabled ); + checkAcceptance( false ); CALAMARES_RETRANSLATE( if ( required ) @@ -245,3 +233,28 @@ LicensePage::isNextEnabled() const { return m_isNextEnabled; } + +void +LicensePage::updateGlobalStorage( bool v ) +{ + Calamares::JobQueue::instance()->globalStorage()->insert( "licenseAgree", v ); +} + +void LicensePage::checkAcceptance( bool checked ) +{ + updateGlobalStorage( checked ); + + m_isNextEnabled = checked || m_allLicensesOptional; + if ( !m_isNextEnabled ) + { + ui->acceptFrame->setStyleSheet( "#acceptFrame { border: 1px solid red;" + "background-color: #fff8f8;" + "border-radius: 4px;" + "padding: 2px; }" ); + } + else + { + ui->acceptFrame->setStyleSheet( "#acceptFrame { padding: 3px }" ); + } + emit nextStatusChanged( checked ); +} diff --git a/src/modules/license/LicensePage.h b/src/modules/license/LicensePage.h index b2e343602..1af83269a 100644 --- a/src/modules/license/LicensePage.h +++ b/src/modules/license/LicensePage.h @@ -70,13 +70,31 @@ public: void setEntries( const QList< LicenseEntry >& entriesList ); bool isNextEnabled() const; + +public slots: + /** @brief Check if the user can continue + * + * The user can continue if + * - none of the licenses are required, or + * - the user has ticked the "OK" box. + * This function calls updateGlobalStorage() as needed, and updates + * the appearance of the page as needed. @p checked indicates whether + * the checkbox has been ticked or not. + */ + void checkAcceptance( bool checked ); + signals: void nextStatusChanged( bool status ); private: - Ui::LicensePage* ui; + /** @brief Update the global storage "licenseAgree" key. */ + void updateGlobalStorage( bool v ); bool m_isNextEnabled; + bool m_allLicensesOptional; //< all the licenses passed to setEntries are not-required + + Ui::LicensePage* ui; + }; #endif //LICENSEPAGE_H From 35f23c86c6827e49b061581c23de3a4da84d237e Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sun, 21 Apr 2019 12:43:04 +0200 Subject: [PATCH 08/21] [license] Add stub LicenseWidget files - Prepare for refactoring - Clean up weirdness in the CMakeLists.txt --- src/modules/license/CMakeLists.txt | 12 +++--------- src/modules/license/LicenseWidget.cpp | 22 ++++++++++++++++++++++ src/modules/license/LicenseWidget.h | 25 +++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 9 deletions(-) create mode 100644 src/modules/license/LicenseWidget.cpp create mode 100644 src/modules/license/LicenseWidget.h diff --git a/src/modules/license/CMakeLists.txt b/src/modules/license/CMakeLists.txt index 54774dede..164233b3b 100644 --- a/src/modules/license/CMakeLists.txt +++ b/src/modules/license/CMakeLists.txt @@ -1,18 +1,12 @@ include_directories( ${PROJECT_BINARY_DIR}/src/libcalamaresui ) + calamares_add_plugin( license - -set_source_files_properties( PROPERTIES LANGUAGE CXX ) - -find_package( Qt5 ${QT_VERSION} CONFIG REQUIRED DBus ) - -set( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} - ${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules ) - TYPE viewmodule EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES - LicenseViewStep.cpp LicensePage.cpp + LicenseViewStep.cpp + LicenseWidget.cpp UI LicensePage.ui LINK_PRIVATE_LIBRARIES diff --git a/src/modules/license/LicenseWidget.cpp b/src/modules/license/LicenseWidget.cpp new file mode 100644 index 000000000..d68a279b5 --- /dev/null +++ b/src/modules/license/LicenseWidget.cpp @@ -0,0 +1,22 @@ +/* === This file is part of Calamares - === + * + * Copyright 2015, Anke Boersma + * Copyright 2015, Alexandre Arnt + * Copyright 2015, Teo Mrnjavac + * Copyright 2018, 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 "LicenseWidget.h" diff --git a/src/modules/license/LicenseWidget.h b/src/modules/license/LicenseWidget.h new file mode 100644 index 000000000..2c2b6526f --- /dev/null +++ b/src/modules/license/LicenseWidget.h @@ -0,0 +1,25 @@ +/* === This file is part of Calamares - === + * + * Copyright 2015, Anke Boersma + * Copyright 2015, Alexandre Arnt + * Copyright 2015, Teo Mrnjavac + * Copyright 2018, 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 LICENSE_LICENSEWIDGET_H +#define LICENSE_LICENSEWIDGET_H + +#endif From 1235207ead95c2df3f633160a1f571fc8dea0ce7 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sun, 21 Apr 2019 13:36:28 +0200 Subject: [PATCH 09/21] [license] Refactor LicenseWidget - Move all the widget code into its own file --- src/modules/license/LicensePage.cpp | 69 +---------------------- src/modules/license/LicenseWidget.cpp | 79 +++++++++++++++++++++++++++ src/modules/license/LicenseWidget.h | 14 +++++ 3 files changed, 95 insertions(+), 67 deletions(-) diff --git a/src/modules/license/LicensePage.cpp b/src/modules/license/LicensePage.cpp index 29ed4d555..97bb9a9ab 100644 --- a/src/modules/license/LicensePage.cpp +++ b/src/modules/license/LicensePage.cpp @@ -22,6 +22,7 @@ #include "LicensePage.h" #include "ui_LicensePage.h" +#include "LicenseWidget.h" #include "JobQueue.h" #include "GlobalStorage.h" @@ -156,73 +157,7 @@ LicensePage::setEntries( const QList< LicenseEntry >& entriesList ) for ( const LicenseEntry& entry : entriesList ) { - QWidget* widget = new QWidget( this ); - QPalette pal( palette() ); - pal.setColor( QPalette::Background, palette().background().color().lighter( 108 ) ); - widget->setAutoFillBackground( true ); - widget->setPalette( pal ); - widget->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum ); - widget->setContentsMargins( 4, 4, 4, 4 ); - - QHBoxLayout* wiLayout = new QHBoxLayout; - widget->setLayout( wiLayout ); - QLabel* label = new QLabel( widget ); - label->setWordWrap( true ); - wiLayout->addWidget( label ); - label->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Minimum ); - - QString productDescription; - switch ( entry.m_type ) - { - case LicenseEntry::Type::Driver: - //: %1 is an untranslatable product name, example: Creative Audigy driver - productDescription = tr( "%1 driver
" - "by %2" ) - .arg( entry.m_prettyName ) - .arg( entry.m_prettyVendor ); - break; - case LicenseEntry::Type::GpuDriver: - //: %1 is usually a vendor name, example: Nvidia graphics driver - productDescription = tr( "%1 graphics driver
" - "by %2" ) - .arg( entry.m_prettyName ) - .arg( entry.m_prettyVendor ); - break; - case LicenseEntry::Type::BrowserPlugin: - productDescription = tr( "%1 browser plugin
" - "by %2" ) - .arg( entry.m_prettyName ) - .arg( entry.m_prettyVendor ); - break; - case LicenseEntry::Type::Codec: - productDescription = tr( "%1 codec
" - "by %2" ) - .arg( entry.m_prettyName ) - .arg( entry.m_prettyVendor ); - break; - case LicenseEntry::Type::Package: - productDescription = tr( "%1 package
" - "by %2" ) - .arg( entry.m_prettyName ) - .arg( entry.m_prettyVendor ); - break; - case LicenseEntry::Type::Software: - productDescription = tr( "%1
" - "by %2" ) - .arg( entry.m_prettyName ) - .arg( entry.m_prettyVendor ); - } - label->setText( productDescription ); - - QLabel* viewLicenseLabel = new QLabel( widget ); - wiLayout->addWidget( viewLicenseLabel ); - viewLicenseLabel->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ); - viewLicenseLabel->setOpenExternalLinks( true ); - viewLicenseLabel->setAlignment( Qt::AlignVCenter | Qt::AlignRight ); - viewLicenseLabel->setText( tr( "view license agreement" ) - .arg( entry.m_url.toString() ) ); - - ui->licenseEntriesLayout->addWidget( widget ); + ui->licenseEntriesLayout->addWidget( new LicenseWidget( entry ) ); } ui->licenseEntriesLayout->addStretch(); } diff --git a/src/modules/license/LicenseWidget.cpp b/src/modules/license/LicenseWidget.cpp index d68a279b5..c944f973b 100644 --- a/src/modules/license/LicenseWidget.cpp +++ b/src/modules/license/LicenseWidget.cpp @@ -20,3 +20,82 @@ */ #include "LicenseWidget.h" + +#include +#include + + +LicenseWidget::LicenseWidget( LicenseEntry entry, QWidget* parent ) + : QWidget( parent ) + , m_entry( std::move( entry ) ) +{ + QPalette pal( palette() ); + pal.setColor( QPalette::Background, palette().background().color().lighter( 108 ) ); + + setAutoFillBackground( true ); + setPalette( pal ); + setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum ); + setContentsMargins( 4, 4, 4, 4 ); + + QHBoxLayout* wiLayout = new QHBoxLayout; + setLayout( wiLayout ); + QLabel* label = new QLabel( this ); + label->setWordWrap( true ); + wiLayout->addWidget( label ); + label->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Minimum ); + + QString productDescription; + switch ( entry.m_type ) + { + case LicenseEntry::Type::Driver: + //: %1 is an untranslatable product name, example: Creative Audigy driver + productDescription = tr( "%1 driver
" + "by %2" ) + .arg( entry.m_prettyName ) + .arg( entry.m_prettyVendor ); + break; + case LicenseEntry::Type::GpuDriver: + //: %1 is usually a vendor name, example: Nvidia graphics driver + productDescription = tr( "%1 graphics driver
" + "by %2" ) + .arg( entry.m_prettyName ) + .arg( entry.m_prettyVendor ); + break; + case LicenseEntry::Type::BrowserPlugin: + productDescription = tr( "%1 browser plugin
" + "by %2" ) + .arg( entry.m_prettyName ) + .arg( entry.m_prettyVendor ); + break; + case LicenseEntry::Type::Codec: + productDescription = tr( "%1 codec
" + "by %2" ) + .arg( entry.m_prettyName ) + .arg( entry.m_prettyVendor ); + break; + case LicenseEntry::Type::Package: + productDescription = tr( "%1 package
" + "by %2" ) + .arg( entry.m_prettyName ) + .arg( entry.m_prettyVendor ); + break; + case LicenseEntry::Type::Software: + productDescription = tr( "%1
" + "by %2" ) + .arg( entry.m_prettyName ) + .arg( entry.m_prettyVendor ); + } + label->setText( productDescription ); + + QLabel* viewLicenseLabel = new QLabel( this ); + wiLayout->addWidget( viewLicenseLabel ); + viewLicenseLabel->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ); + viewLicenseLabel->setOpenExternalLinks( true ); + viewLicenseLabel->setAlignment( Qt::AlignVCenter | Qt::AlignRight ); + viewLicenseLabel->setText( tr( "view license agreement" ) + .arg( entry.m_url.toString() ) ); +} + +LicenseWidget::~LicenseWidget() +{ +} diff --git a/src/modules/license/LicenseWidget.h b/src/modules/license/LicenseWidget.h index 2c2b6526f..861c4ec34 100644 --- a/src/modules/license/LicenseWidget.h +++ b/src/modules/license/LicenseWidget.h @@ -22,4 +22,18 @@ #ifndef LICENSE_LICENSEWIDGET_H #define LICENSE_LICENSEWIDGET_H +#include "LicensePage.h" + +#include +#include + +class LicenseWidget : public QWidget +{ +public: + LicenseWidget( LicenseEntry e, QWidget* parent = nullptr ); + virtual ~LicenseWidget() override; + +private: + LicenseEntry m_entry; +} ; #endif From cb80d476821c4c5edca5dbde1a65412905668bde Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sun, 21 Apr 2019 13:50:06 +0200 Subject: [PATCH 10/21] [license] Move translation / retranslation to LicenseWidget - Language change didn't otherwise apply to the license items --- src/modules/license/LicensePage.cpp | 9 +- src/modules/license/LicensePage.h | 4 +- src/modules/license/LicenseWidget.cpp | 113 ++++++++++++++------------ src/modules/license/LicenseWidget.h | 4 + 4 files changed, 75 insertions(+), 55 deletions(-) diff --git a/src/modules/license/LicensePage.cpp b/src/modules/license/LicensePage.cpp index 97bb9a9ab..3f16a6698 100644 --- a/src/modules/license/LicensePage.cpp +++ b/src/modules/license/LicensePage.cpp @@ -121,6 +121,8 @@ void LicensePage::setEntries( const QList< LicenseEntry >& entriesList ) { CalamaresUtils::clearLayout( ui->licenseEntriesLayout ); + m_entries.clear(); + m_entries.reserve( entriesList.count() ); const bool required = std::any_of( entriesList.cbegin(), entriesList.cend(), []( const LicenseEntry& e ){ return e.m_required; }); if ( entriesList.isEmpty() ) @@ -153,11 +155,16 @@ LicensePage::setEntries( const QList< LicenseEntry >& entriesList ) "be installed, and open source alternatives will be used instead." ) ); } ui->retranslateUi( this ); + + for ( const auto& w : m_entries ) + w->retranslateUi(); ) for ( const LicenseEntry& entry : entriesList ) { - ui->licenseEntriesLayout->addWidget( new LicenseWidget( entry ) ); + LicenseWidget* w = new LicenseWidget( entry ); + ui->licenseEntriesLayout->addWidget( w ); + m_entries.append( w ); } ui->licenseEntriesLayout->addStretch(); } diff --git a/src/modules/license/LicensePage.h b/src/modules/license/LicensePage.h index 1af83269a..e9bd0f696 100644 --- a/src/modules/license/LicensePage.h +++ b/src/modules/license/LicensePage.h @@ -32,6 +32,8 @@ namespace Ui class LicensePage; } +class LicenseWidget; + struct LicenseEntry { enum class Type @@ -94,7 +96,7 @@ private: bool m_allLicensesOptional; //< all the licenses passed to setEntries are not-required Ui::LicensePage* ui; - + QList< LicenseWidget* > m_entries; }; #endif //LICENSEPAGE_H diff --git a/src/modules/license/LicenseWidget.cpp b/src/modules/license/LicenseWidget.cpp index c944f973b..4030cbd6c 100644 --- a/src/modules/license/LicenseWidget.cpp +++ b/src/modules/license/LicenseWidget.cpp @@ -28,6 +28,8 @@ LicenseWidget::LicenseWidget( LicenseEntry entry, QWidget* parent ) : QWidget( parent ) , m_entry( std::move( entry ) ) + , m_label( new QLabel( this ) ) + , m_viewLicenseLabel( new QLabel( this ) ) { QPalette pal( palette() ); pal.setColor( QPalette::Background, palette().background().color().lighter( 108 ) ); @@ -39,63 +41,68 @@ LicenseWidget::LicenseWidget( LicenseEntry entry, QWidget* parent ) QHBoxLayout* wiLayout = new QHBoxLayout; setLayout( wiLayout ); - QLabel* label = new QLabel( this ); - label->setWordWrap( true ); - wiLayout->addWidget( label ); - label->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Minimum ); - QString productDescription; - switch ( entry.m_type ) - { - case LicenseEntry::Type::Driver: - //: %1 is an untranslatable product name, example: Creative Audigy driver - productDescription = tr( "%1 driver
" - "by %2" ) - .arg( entry.m_prettyName ) - .arg( entry.m_prettyVendor ); - break; - case LicenseEntry::Type::GpuDriver: - //: %1 is usually a vendor name, example: Nvidia graphics driver - productDescription = tr( "%1 graphics driver
" - "by %2" ) - .arg( entry.m_prettyName ) - .arg( entry.m_prettyVendor ); - break; - case LicenseEntry::Type::BrowserPlugin: - productDescription = tr( "%1 browser plugin
" - "by %2" ) - .arg( entry.m_prettyName ) - .arg( entry.m_prettyVendor ); - break; - case LicenseEntry::Type::Codec: - productDescription = tr( "%1 codec
" - "by %2" ) - .arg( entry.m_prettyName ) - .arg( entry.m_prettyVendor ); - break; - case LicenseEntry::Type::Package: - productDescription = tr( "%1 package
" - "by %2" ) - .arg( entry.m_prettyName ) - .arg( entry.m_prettyVendor ); - break; - case LicenseEntry::Type::Software: - productDescription = tr( "%1
" - "by %2" ) - .arg( entry.m_prettyName ) - .arg( entry.m_prettyVendor ); - } - label->setText( productDescription ); + m_label->setWordWrap( true ); + m_label->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Minimum ); + wiLayout->addWidget( m_label ); - QLabel* viewLicenseLabel = new QLabel( this ); - wiLayout->addWidget( viewLicenseLabel ); - viewLicenseLabel->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ); - viewLicenseLabel->setOpenExternalLinks( true ); - viewLicenseLabel->setAlignment( Qt::AlignVCenter | Qt::AlignRight ); - viewLicenseLabel->setText( tr( "view license agreement" ) - .arg( entry.m_url.toString() ) ); + m_viewLicenseLabel->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ); + m_viewLicenseLabel->setOpenExternalLinks( true ); + m_viewLicenseLabel->setAlignment( Qt::AlignVCenter | Qt::AlignRight ); + wiLayout->addWidget( m_viewLicenseLabel ); + + retranslateUi(); } LicenseWidget::~LicenseWidget() { } + +void LicenseWidget::retranslateUi() +{ + QString productDescription; + switch ( m_entry.m_type ) + { + case LicenseEntry::Type::Driver: + //: %1 is an untranslatable product name, example: Creative Audigy driver + productDescription = tr( "%1 driver
" + "by %2" ) + .arg( m_entry.m_prettyName ) + .arg( m_entry.m_prettyVendor ); + break; + case LicenseEntry::Type::GpuDriver: + //: %1 is usually a vendor name, example: Nvidia graphics driver + productDescription = tr( "%1 graphics driver
" + "by %2" ) + .arg( m_entry.m_prettyName ) + .arg( m_entry.m_prettyVendor ); + break; + case LicenseEntry::Type::BrowserPlugin: + productDescription = tr( "%1 browser plugin
" + "by %2" ) + .arg( m_entry.m_prettyName ) + .arg( m_entry.m_prettyVendor ); + break; + case LicenseEntry::Type::Codec: + productDescription = tr( "%1 codec
" + "by %2" ) + .arg( m_entry.m_prettyName ) + .arg( m_entry.m_prettyVendor ); + break; + case LicenseEntry::Type::Package: + productDescription = tr( "%1 package
" + "by %2" ) + .arg( m_entry.m_prettyName ) + .arg( m_entry.m_prettyVendor ); + break; + case LicenseEntry::Type::Software: + productDescription = tr( "%1
" + "by %2" ) + .arg( m_entry.m_prettyName ) + .arg( m_entry.m_prettyVendor ); + } + m_label->setText( productDescription ); + + m_viewLicenseLabel->setText( tr( "view license agreement" ) + .arg( m_entry.m_url.toString() ) ); +} diff --git a/src/modules/license/LicenseWidget.h b/src/modules/license/LicenseWidget.h index 861c4ec34..e91ea23c1 100644 --- a/src/modules/license/LicenseWidget.h +++ b/src/modules/license/LicenseWidget.h @@ -33,7 +33,11 @@ public: LicenseWidget( LicenseEntry e, QWidget* parent = nullptr ); virtual ~LicenseWidget() override; + void retranslateUi(); + private: LicenseEntry m_entry; + QLabel *m_label; + QLabel *m_viewLicenseLabel; } ; #endif From 32ed3f6db69e8fbb6b49a6287ccf715ccd61f1a6 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sun, 21 Apr 2019 14:23:56 +0200 Subject: [PATCH 11/21] [license] Add GPLv3 as an example in the license.conf --- src/modules/license/license.conf | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/modules/license/license.conf b/src/modules/license/license.conf index ac4367f8b..bf79a3e97 100644 --- a/src/modules/license/license.conf +++ b/src/modules/license/license.conf @@ -33,3 +33,9 @@ entries: type: browserplugin url: http://www.adobe.com/products/eulas/pdfs/PlatformClients_PC_WWEULA_Combined_20100108_1657.pdf required: true +- id: gpl + name: GNU General Public License v3 + vendor: FSF + type: erp + required: true + url: file:///tmp/COPYING.txt From c696b5c19d47c6f07c4a40b463f748db2b0938ae Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sun, 21 Apr 2019 20:36:11 +0200 Subject: [PATCH 12/21] [license] Add show-license toggle button - Non-functional as yet - Toggles expand / collapse arrow and tooltip --- src/modules/license/LicensePage.cpp | 8 +++++ src/modules/license/LicensePage.h | 1 + src/modules/license/LicenseWidget.cpp | 50 +++++++++++++++++++++++++-- src/modules/license/LicenseWidget.h | 10 ++++-- 4 files changed, 65 insertions(+), 4 deletions(-) diff --git a/src/modules/license/LicensePage.cpp b/src/modules/license/LicensePage.cpp index 3f16a6698..025f77284 100644 --- a/src/modules/license/LicensePage.cpp +++ b/src/modules/license/LicensePage.cpp @@ -78,6 +78,14 @@ LicenseEntry::LicenseEntry(const QVariantMap& conf) cWarning() << "License entry" << m_id << "has unknown type" << typeString << "(using 'software')"; } +bool +LicenseEntry::isLocal() const +{ + return ( m_url.scheme() == "file" ) && + ( []( const QString&& r ){ return r.endsWith( ".html" ) || r.endsWith( ".txt" ); }( m_url.toString() ) ); +} + + LicensePage::LicensePage(QWidget *parent) : QWidget( parent ) , ui( new Ui::LicensePage ) diff --git a/src/modules/license/LicensePage.h b/src/modules/license/LicensePage.h index e9bd0f696..c08676f92 100644 --- a/src/modules/license/LicensePage.h +++ b/src/modules/license/LicensePage.h @@ -54,6 +54,7 @@ struct LicenseEntry bool isValid() const { return !m_id.isEmpty(); } bool isRequired() const { return m_required; } + bool isLocal() const; QString m_id; QString m_prettyName; diff --git a/src/modules/license/LicenseWidget.cpp b/src/modules/license/LicenseWidget.cpp index 4030cbd6c..7a52f4e9e 100644 --- a/src/modules/license/LicenseWidget.cpp +++ b/src/modules/license/LicenseWidget.cpp @@ -23,6 +23,7 @@ #include #include +#include LicenseWidget::LicenseWidget( LicenseEntry entry, QWidget* parent ) @@ -30,6 +31,7 @@ LicenseWidget::LicenseWidget( LicenseEntry entry, QWidget* parent ) , m_entry( std::move( entry ) ) , m_label( new QLabel( this ) ) , m_viewLicenseLabel( new QLabel( this ) ) + , m_expandLicenseButton( nullptr ) { QPalette pal( palette() ); pal.setColor( QPalette::Background, palette().background().color().lighter( 108 ) ); @@ -47,10 +49,21 @@ LicenseWidget::LicenseWidget( LicenseEntry entry, QWidget* parent ) wiLayout->addWidget( m_label ); m_viewLicenseLabel->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ); - m_viewLicenseLabel->setOpenExternalLinks( true ); m_viewLicenseLabel->setAlignment( Qt::AlignVCenter | Qt::AlignRight ); wiLayout->addWidget( m_viewLicenseLabel ); + if ( m_entry.isLocal() ) + { + m_expandLicenseButton = new QToolButton( this ); + m_expandLicenseButton->setArrowType( Qt::DownArrow ); + wiLayout->addWidget( m_expandLicenseButton ); + + connect( m_expandLicenseButton, &QAbstractButton::clicked, this, &LicenseWidget::expandClicked ); + } + else + m_viewLicenseLabel->setOpenExternalLinks( true ); + + retranslateUi(); } @@ -103,6 +116,39 @@ void LicenseWidget::retranslateUi() } m_label->setText( productDescription ); - m_viewLicenseLabel->setText( tr( "view license agreement" ) + if ( m_entry.isLocal() ) + { + m_viewLicenseLabel->setText( tr( "Show license agreement" ) ); + updateExpandToolTip(); + } + else + m_viewLicenseLabel->setText( tr( "view license agreement" ) .arg( m_entry.m_url.toString() ) ); } + +void +LicenseWidget::expandClicked() +{ + if ( m_expandLicenseButton->arrowType() == Qt::DownArrow ) + { + m_expandLicenseButton->setArrowType( Qt::UpArrow ); + } + else + { + m_expandLicenseButton->setArrowType( Qt::DownArrow ); + } + updateExpandToolTip(); +} + +void +LicenseWidget::updateExpandToolTip() +{ + if ( !m_expandLicenseButton ) + return; + + m_expandLicenseButton->setToolTip( + ( m_expandLicenseButton->arrowType() == Qt::DownArrow ) + ? tr( "Show complete license text" ) + : tr( "Hide license text" ) + ) ; +} diff --git a/src/modules/license/LicenseWidget.h b/src/modules/license/LicenseWidget.h index e91ea23c1..ab6a91491 100644 --- a/src/modules/license/LicenseWidget.h +++ b/src/modules/license/LicenseWidget.h @@ -27,6 +27,8 @@ #include #include +class QToolButton; + class LicenseWidget : public QWidget { public: @@ -36,8 +38,12 @@ public: void retranslateUi(); private: + void expandClicked(); + void updateExpandToolTip(); + LicenseEntry m_entry; - QLabel *m_label; - QLabel *m_viewLicenseLabel; + QLabel* m_label; + QLabel* m_viewLicenseLabel; + QToolButton* m_expandLicenseButton; } ; #endif From ddf541774b729f7919693355d78a16bf19bfec37 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 23 Apr 2019 04:10:43 -0400 Subject: [PATCH 13/21] [license] Make local and external links more consistent - Capitalization of message - Add a right-pointing "open" button to external links as well --- src/modules/license/LicenseWidget.cpp | 19 +++++++++++++++++-- src/modules/license/LicenseWidget.h | 3 ++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/modules/license/LicenseWidget.cpp b/src/modules/license/LicenseWidget.cpp index 7a52f4e9e..bf20ffc51 100644 --- a/src/modules/license/LicenseWidget.cpp +++ b/src/modules/license/LicenseWidget.cpp @@ -21,6 +21,7 @@ #include "LicenseWidget.h" +#include #include #include #include @@ -61,8 +62,16 @@ LicenseWidget::LicenseWidget( LicenseEntry entry, QWidget* parent ) connect( m_expandLicenseButton, &QAbstractButton::clicked, this, &LicenseWidget::expandClicked ); } else - m_viewLicenseLabel->setOpenExternalLinks( true ); + { + auto* button = new QToolButton( this ); + button->setArrowType( Qt::RightArrow ); + wiLayout->addWidget( button ); + connect( button, &QAbstractButton::clicked, this, &LicenseWidget::viewClicked ); + // Normally setOpenExternalLinks( true ) would do, but we need the + // open code anyway for the toolbutton, let's share it. + connect( m_viewLicenseLabel, &QLabel::linkActivated, this, &LicenseWidget::viewClicked ); + } retranslateUi(); } @@ -122,7 +131,7 @@ void LicenseWidget::retranslateUi() updateExpandToolTip(); } else - m_viewLicenseLabel->setText( tr( "view license agreement" ) + m_viewLicenseLabel->setText( tr( "View license agreement" ) .arg( m_entry.m_url.toString() ) ); } @@ -152,3 +161,9 @@ LicenseWidget::updateExpandToolTip() : tr( "Hide license text" ) ) ; } + +void +LicenseWidget::viewClicked() +{ + QDesktopServices::openUrl( m_entry.m_url ); +} diff --git a/src/modules/license/LicenseWidget.h b/src/modules/license/LicenseWidget.h index ab6a91491..dcddf7f3c 100644 --- a/src/modules/license/LicenseWidget.h +++ b/src/modules/license/LicenseWidget.h @@ -38,7 +38,8 @@ public: void retranslateUi(); private: - void expandClicked(); + void expandClicked(); // "slot" to toggle show/hide of local license text + void viewClicked(); // "slot" to open link void updateExpandToolTip(); LicenseEntry m_entry; From 92a3666dcecf5326f21a59cf132f6061f3dfa929 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 23 Apr 2019 08:16:54 -0400 Subject: [PATCH 14/21] [license] Simplify isLocal() by using Qt method --- src/modules/license/LicensePage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/license/LicensePage.cpp b/src/modules/license/LicensePage.cpp index 025f77284..a894d35ff 100644 --- a/src/modules/license/LicensePage.cpp +++ b/src/modules/license/LicensePage.cpp @@ -81,7 +81,7 @@ LicenseEntry::LicenseEntry(const QVariantMap& conf) bool LicenseEntry::isLocal() const { - return ( m_url.scheme() == "file" ) && + return m_url.isLocalFile() && ( []( const QString&& r ){ return r.endsWith( ".html" ) || r.endsWith( ".txt" ); }( m_url.toString() ) ); } From 4bdae0cab0bb862ceca94937d6eabb068079b4f3 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 23 Apr 2019 08:29:32 -0400 Subject: [PATCH 15/21] [license] Load full license text if local - Load full text, toggle display - Swap Up and Down arrow semantics on button, to match usual text-editor display (down means it's expanded, displayed) --- src/modules/license/LicenseWidget.cpp | 42 +++++++++++++++++++++++++-- src/modules/license/LicenseWidget.h | 1 + 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/modules/license/LicenseWidget.cpp b/src/modules/license/LicenseWidget.cpp index bf20ffc51..831844d5a 100644 --- a/src/modules/license/LicenseWidget.cpp +++ b/src/modules/license/LicenseWidget.cpp @@ -21,11 +21,30 @@ #include "LicenseWidget.h" +#include "utils/Logger.h" + #include +#include #include #include #include +#include +static QString +loadLocalFile( const QUrl& u ) +{ + if ( !u.isLocalFile() ) + return QString(); + + QFile file( u.path() ); + if ( !file.open(QIODevice::ReadOnly | QIODevice::Text) ) + { + cWarning() << "Could not load license file" << u; + return QString(); + } + + return file.readAll(); +} LicenseWidget::LicenseWidget( LicenseEntry entry, QWidget* parent ) : QWidget( parent ) @@ -33,6 +52,7 @@ LicenseWidget::LicenseWidget( LicenseEntry entry, QWidget* parent ) , m_label( new QLabel( this ) ) , m_viewLicenseLabel( new QLabel( this ) ) , m_expandLicenseButton( nullptr ) + , m_fullText( nullptr ) { QPalette pal( palette() ); pal.setColor( QPalette::Background, palette().background().color().lighter( 108 ) ); @@ -43,7 +63,6 @@ LicenseWidget::LicenseWidget( LicenseEntry entry, QWidget* parent ) setContentsMargins( 4, 4, 4, 4 ); QHBoxLayout* wiLayout = new QHBoxLayout; - setLayout( wiLayout ); m_label->setWordWrap( true ); m_label->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Minimum ); @@ -55,11 +74,21 @@ LicenseWidget::LicenseWidget( LicenseEntry entry, QWidget* parent ) if ( m_entry.isLocal() ) { + QVBoxLayout* vLayout = new QVBoxLayout; + m_expandLicenseButton = new QToolButton( this ); - m_expandLicenseButton->setArrowType( Qt::DownArrow ); + m_expandLicenseButton->setArrowType( Qt::UpArrow ); wiLayout->addWidget( m_expandLicenseButton ); connect( m_expandLicenseButton, &QAbstractButton::clicked, this, &LicenseWidget::expandClicked ); + + vLayout->addLayout( wiLayout ); + m_fullText = new QLabel( this ); + m_fullText->setText( loadLocalFile( m_entry.m_url ) ); + m_fullText->hide(); + + vLayout->addWidget( m_fullText ); + setLayout( vLayout ); } else { @@ -71,6 +100,8 @@ LicenseWidget::LicenseWidget( LicenseEntry entry, QWidget* parent ) // Normally setOpenExternalLinks( true ) would do, but we need the // open code anyway for the toolbutton, let's share it. connect( m_viewLicenseLabel, &QLabel::linkActivated, this, &LicenseWidget::viewClicked ); + + setLayout( wiLayout ); // Only the horizontal layout needed } retranslateUi(); @@ -146,6 +177,11 @@ LicenseWidget::expandClicked() { m_expandLicenseButton->setArrowType( Qt::DownArrow ); } + + // Show/hide based on the new arrow direction. + if ( m_fullText ) + m_fullText->setHidden( m_expandLicenseButton->arrowType() == Qt::UpArrow ); + updateExpandToolTip(); } @@ -156,7 +192,7 @@ LicenseWidget::updateExpandToolTip() return; m_expandLicenseButton->setToolTip( - ( m_expandLicenseButton->arrowType() == Qt::DownArrow ) + ( m_expandLicenseButton->arrowType() == Qt::UpArrow ) ? tr( "Show complete license text" ) : tr( "Hide license text" ) ) ; diff --git a/src/modules/license/LicenseWidget.h b/src/modules/license/LicenseWidget.h index dcddf7f3c..c43233da4 100644 --- a/src/modules/license/LicenseWidget.h +++ b/src/modules/license/LicenseWidget.h @@ -46,5 +46,6 @@ private: QLabel* m_label; QLabel* m_viewLicenseLabel; QToolButton* m_expandLicenseButton; + QLabel* m_fullText; } ; #endif From 982a3fb372f5d00f8bb7462aa364ea502ce4630a Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 23 Apr 2019 08:41:05 -0400 Subject: [PATCH 16/21] [license] Apply stylesheet so displayed text is nicer. --- src/modules/license/LicenseWidget.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/modules/license/LicenseWidget.cpp b/src/modules/license/LicenseWidget.cpp index 831844d5a..de75b0e2d 100644 --- a/src/modules/license/LicenseWidget.cpp +++ b/src/modules/license/LicenseWidget.cpp @@ -43,7 +43,7 @@ loadLocalFile( const QUrl& u ) return QString(); } - return file.readAll(); + return QString( "\n" ) + file.readAll(); } LicenseWidget::LicenseWidget( LicenseEntry entry, QWidget* parent ) @@ -86,6 +86,7 @@ LicenseWidget::LicenseWidget( LicenseEntry entry, QWidget* parent ) m_fullText = new QLabel( this ); m_fullText->setText( loadLocalFile( m_entry.m_url ) ); m_fullText->hide(); + m_fullText->setStyleSheet( "border-top: 1px solid black; margin-top: 1em; padding-top: 1em;" ); vLayout->addWidget( m_fullText ); setLayout( vLayout ); From f0d26a74b7353c711eef89e59fbc9c1965322ba9 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 23 Apr 2019 17:05:44 -0400 Subject: [PATCH 17/21] [license] Set object names - This is prep-work now that the CSS styling branch has merged --- src/modules/license/LicenseWidget.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/modules/license/LicenseWidget.cpp b/src/modules/license/LicenseWidget.cpp index de75b0e2d..fc1e6c5b3 100644 --- a/src/modules/license/LicenseWidget.cpp +++ b/src/modules/license/LicenseWidget.cpp @@ -57,6 +57,8 @@ LicenseWidget::LicenseWidget( LicenseEntry entry, QWidget* parent ) QPalette pal( palette() ); pal.setColor( QPalette::Background, palette().background().color().lighter( 108 ) ); + setObjectName( "licenseItem" ); + setAutoFillBackground( true ); setPalette( pal ); setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum ); @@ -87,6 +89,7 @@ LicenseWidget::LicenseWidget( LicenseEntry entry, QWidget* parent ) m_fullText->setText( loadLocalFile( m_entry.m_url ) ); m_fullText->hide(); m_fullText->setStyleSheet( "border-top: 1px solid black; margin-top: 1em; padding-top: 1em;" ); + m_fullText->setObjectName( "licenseItemFullText" ); vLayout->addWidget( m_fullText ); setLayout( vLayout ); From 4ce6fdbd902a2315697e7d4ba8c297fce53d70b7 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 24 Apr 2019 06:43:00 -0400 Subject: [PATCH 18/21] [license] Make area scrollable - Since the list of license entries may be long (especially if the text is expanded) make it scrollable. --- src/modules/license/LicensePage.ui | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/modules/license/LicensePage.ui b/src/modules/license/LicensePage.ui index 9de62511e..767b392a0 100644 --- a/src/modules/license/LicensePage.ui +++ b/src/modules/license/LicensePage.ui @@ -46,7 +46,31 @@ - + + + QFrame::NoFrame + + + Qt::ScrollBarAlwaysOn + + + Qt::ScrollBarAlwaysOff + + + true + + + + + 0 + 0 + 765 + 94 + + + + + From 3608f62ec09559cf8a27518750320e9cc3402d49 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 24 Apr 2019 06:53:31 -0400 Subject: [PATCH 19/21] [license] Adjust tooltip and button texts - Handle various states of the link and tool buttons, give them appropriate texts and tooltips. --- src/modules/license/LicenseWidget.cpp | 48 ++++++++++++++------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/src/modules/license/LicenseWidget.cpp b/src/modules/license/LicenseWidget.cpp index fc1e6c5b3..c72fa76e0 100644 --- a/src/modules/license/LicenseWidget.cpp +++ b/src/modules/license/LicenseWidget.cpp @@ -74,14 +74,13 @@ LicenseWidget::LicenseWidget( LicenseEntry entry, QWidget* parent ) m_viewLicenseLabel->setAlignment( Qt::AlignVCenter | Qt::AlignRight ); wiLayout->addWidget( m_viewLicenseLabel ); + m_expandLicenseButton = new QToolButton( this ); + wiLayout->addWidget( m_expandLicenseButton ); if ( m_entry.isLocal() ) { QVBoxLayout* vLayout = new QVBoxLayout; - m_expandLicenseButton = new QToolButton( this ); m_expandLicenseButton->setArrowType( Qt::UpArrow ); - wiLayout->addWidget( m_expandLicenseButton ); - connect( m_expandLicenseButton, &QAbstractButton::clicked, this, &LicenseWidget::expandClicked ); vLayout->addLayout( wiLayout ); @@ -96,11 +95,9 @@ LicenseWidget::LicenseWidget( LicenseEntry entry, QWidget* parent ) } else { - auto* button = new QToolButton( this ); - button->setArrowType( Qt::RightArrow ); - wiLayout->addWidget( button ); + m_expandLicenseButton->setArrowType( Qt::RightArrow ); + connect( m_expandLicenseButton, &QAbstractButton::clicked, this, &LicenseWidget::viewClicked ); - connect( button, &QAbstractButton::clicked, this, &LicenseWidget::viewClicked ); // Normally setOpenExternalLinks( true ) would do, but we need the // open code anyway for the toolbutton, let's share it. connect( m_viewLicenseLabel, &QLabel::linkActivated, this, &LicenseWidget::viewClicked ); @@ -159,15 +156,7 @@ void LicenseWidget::retranslateUi() .arg( m_entry.m_prettyVendor ); } m_label->setText( productDescription ); - - if ( m_entry.isLocal() ) - { - m_viewLicenseLabel->setText( tr( "Show license agreement" ) ); - updateExpandToolTip(); - } - else - m_viewLicenseLabel->setText( tr( "View license agreement" ) - .arg( m_entry.m_url.toString() ) ); + updateExpandToolTip(); } void @@ -189,17 +178,30 @@ LicenseWidget::expandClicked() updateExpandToolTip(); } +/** @brief Called on retranslate and when button state changes. */ void LicenseWidget::updateExpandToolTip() { - if ( !m_expandLicenseButton ) - return; + if ( m_entry.isLocal() ) + { + const bool isNowCollapsed = m_expandLicenseButton->arrowType() == Qt::UpArrow; - m_expandLicenseButton->setToolTip( - ( m_expandLicenseButton->arrowType() == Qt::UpArrow ) - ? tr( "Show complete license text" ) - : tr( "Hide license text" ) - ) ; + m_expandLicenseButton->setToolTip( + isNowCollapsed + ? tr( "Shows the complete license text" ) + : tr( "Hide license text" ) + ) ; + m_viewLicenseLabel->setText( + isNowCollapsed + ? tr( "Show license agreement" ) + : tr( "Hide license agreement" ) ); + } + else + { + m_expandLicenseButton->setToolTip( tr( "Opens the license agreement in a browser window." ) ); + m_viewLicenseLabel->setText( tr( "View license agreement" ) + .arg( m_entry.m_url.toString() ) ); + } } void From ca870a6d41292b57ed3e9955d935b7b63fdbb241 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 24 Apr 2019 07:03:57 -0400 Subject: [PATCH 20/21] [license] Update example - Explain that the GPLv3 isn't actually a proprietary license, but is used as convenient text for the license page. - Invent a Calamares, Inc. --- src/modules/license/license.conf | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/modules/license/license.conf b/src/modules/license/license.conf index bf79a3e97..9057f8a51 100644 --- a/src/modules/license/license.conf +++ b/src/modules/license/license.conf @@ -33,9 +33,13 @@ entries: type: browserplugin url: http://www.adobe.com/products/eulas/pdfs/PlatformClients_PC_WWEULA_Combined_20100108_1657.pdf required: true -- id: gpl - name: GNU General Public License v3 - vendor: FSF - type: erp +# This example uses a file: link. This example uses a relative link, which +# is relative to where you run Calamares. Assuming you run it from build/ +# as part of your testing, you'll get the LICENSE text for Calamares +# (which is the text of the GPLv3, not proprietary at all). +- id: mine_mine + name: Calamares Proprietary License + vendor: Calamares, Inc. + type: software required: true - url: file:///tmp/COPYING.txt + url: file:../LICENSE From 58770037f404ccaeb5c5b513ceb6e6338438e04b Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 24 Apr 2019 07:04:38 -0400 Subject: [PATCH 21/21] [license] Allow more things locally - If it says file:, it's local (don't require a specific file extension). - Report actual path loaded. --- src/modules/license/LicensePage.cpp | 3 +-- src/modules/license/LicenseWidget.cpp | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/modules/license/LicensePage.cpp b/src/modules/license/LicensePage.cpp index a894d35ff..0ed5a6a17 100644 --- a/src/modules/license/LicensePage.cpp +++ b/src/modules/license/LicensePage.cpp @@ -81,8 +81,7 @@ LicenseEntry::LicenseEntry(const QVariantMap& conf) bool LicenseEntry::isLocal() const { - return m_url.isLocalFile() && - ( []( const QString&& r ){ return r.endsWith( ".html" ) || r.endsWith( ".txt" ); }( m_url.toString() ) ); + return m_url.isLocalFile(); } diff --git a/src/modules/license/LicenseWidget.cpp b/src/modules/license/LicenseWidget.cpp index c72fa76e0..238d57b07 100644 --- a/src/modules/license/LicenseWidget.cpp +++ b/src/modules/license/LicenseWidget.cpp @@ -39,7 +39,7 @@ loadLocalFile( const QUrl& u ) QFile file( u.path() ); if ( !file.open(QIODevice::ReadOnly | QIODevice::Text) ) { - cWarning() << "Could not load license file" << u; + cWarning() << "Could not load license file" << u.path(); return QString(); }