Merge branch 'software-chooser' of https://github.com/calamares/calamares into development
This commit is contained in:
commit
e7e25a11e7
@ -26,17 +26,22 @@
|
|||||||
#include "utils/Logger.h"
|
#include "utils/Logger.h"
|
||||||
#include "utils/Yaml.h"
|
#include "utils/Yaml.h"
|
||||||
|
|
||||||
|
#include "Branding.h"
|
||||||
#include "GlobalStorage.h"
|
#include "GlobalStorage.h"
|
||||||
#include "Job.h"
|
#include "Job.h"
|
||||||
#include "JobQueue.h"
|
#include "JobQueue.h"
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
#include "ViewManager.h"
|
#include "ViewManager.h"
|
||||||
|
|
||||||
|
#include "modulesystem/ModuleManager.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QCommandLineOption>
|
#include <QCommandLineOption>
|
||||||
#include <QCommandLineParser>
|
#include <QCommandLineParser>
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QMainWindow>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
@ -51,13 +56,15 @@ struct ModuleConfig
|
|||||||
QString m_jobConfig;
|
QString m_jobConfig;
|
||||||
QString m_globalConfig;
|
QString m_globalConfig;
|
||||||
QString m_language;
|
QString m_language;
|
||||||
|
QString m_branding;
|
||||||
|
bool m_ui;
|
||||||
};
|
};
|
||||||
|
|
||||||
static ModuleConfig
|
static ModuleConfig
|
||||||
handle_args( QCoreApplication& a )
|
handle_args( QCoreApplication& a )
|
||||||
{
|
{
|
||||||
QCommandLineOption debugLevelOption(
|
QCommandLineOption debugLevelOption(
|
||||||
QStringLiteral( "D" ), "Verbose output for debugging purposes (0-8).", "level" );
|
QStringLiteral( "D" ), "Verbose output for debugging purposes (0-8), ignored.", "level" );
|
||||||
QCommandLineOption globalOption( QStringList() << QStringLiteral( "g" ) << QStringLiteral( "global " ),
|
QCommandLineOption globalOption( QStringList() << QStringLiteral( "g" ) << QStringLiteral( "global " ),
|
||||||
QStringLiteral( "Global settings document" ),
|
QStringLiteral( "Global settings document" ),
|
||||||
"global.yaml" );
|
"global.yaml" );
|
||||||
@ -67,6 +74,12 @@ handle_args( QCoreApplication& a )
|
|||||||
QCommandLineOption langOption( QStringList() << QStringLiteral( "l" ) << QStringLiteral( "language" ),
|
QCommandLineOption langOption( QStringList() << QStringLiteral( "l" ) << QStringLiteral( "language" ),
|
||||||
QStringLiteral( "Language (global)" ),
|
QStringLiteral( "Language (global)" ),
|
||||||
"languagecode" );
|
"languagecode" );
|
||||||
|
QCommandLineOption brandOption( QStringList() << QStringLiteral( "b" ) << QStringLiteral( "branding" ),
|
||||||
|
QStringLiteral( "Branding directory" ),
|
||||||
|
"path/to/branding.desc",
|
||||||
|
"src/branding/default/branding.desc" );
|
||||||
|
QCommandLineOption uiOption( QStringList() << QStringLiteral( "U" ) << QStringLiteral( "ui" ),
|
||||||
|
QStringLiteral( "Enable UI" ) );
|
||||||
|
|
||||||
QCommandLineParser parser;
|
QCommandLineParser parser;
|
||||||
parser.setApplicationDescription( "Calamares module tester" );
|
parser.setApplicationDescription( "Calamares module tester" );
|
||||||
@ -77,27 +90,13 @@ handle_args( QCoreApplication& a )
|
|||||||
parser.addOption( globalOption );
|
parser.addOption( globalOption );
|
||||||
parser.addOption( jobOption );
|
parser.addOption( jobOption );
|
||||||
parser.addOption( langOption );
|
parser.addOption( langOption );
|
||||||
|
parser.addOption( brandOption );
|
||||||
|
parser.addOption( uiOption );
|
||||||
parser.addPositionalArgument( "module", "Path or name of module to run." );
|
parser.addPositionalArgument( "module", "Path or name of module to run." );
|
||||||
parser.addPositionalArgument( "job.yaml", "Path of job settings document to use.", "[job.yaml]" );
|
parser.addPositionalArgument( "job.yaml", "Path of job settings document to use.", "[job.yaml]" );
|
||||||
|
|
||||||
parser.process( a );
|
parser.process( a );
|
||||||
|
|
||||||
if ( parser.isSet( debugLevelOption ) )
|
|
||||||
{
|
|
||||||
bool ok = true;
|
|
||||||
unsigned int l = parser.value( debugLevelOption ).toUInt( &ok );
|
|
||||||
unsigned int dlevel = 0;
|
|
||||||
if ( !ok )
|
|
||||||
{
|
|
||||||
dlevel = Logger::LOGVERBOSE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dlevel = l;
|
|
||||||
}
|
|
||||||
Logger::setupLogLevel( dlevel );
|
|
||||||
}
|
|
||||||
|
|
||||||
const QStringList args = parser.positionalArguments();
|
const QStringList args = parser.positionalArguments();
|
||||||
if ( args.isEmpty() )
|
if ( args.isEmpty() )
|
||||||
{
|
{
|
||||||
@ -117,7 +116,12 @@ handle_args( QCoreApplication& a )
|
|||||||
jobSettings = args.at( 1 );
|
jobSettings = args.at( 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
return ModuleConfig { args.first(), jobSettings, parser.value( globalOption ), parser.value( langOption ) };
|
return ModuleConfig { args.first(),
|
||||||
|
jobSettings,
|
||||||
|
parser.value( globalOption ),
|
||||||
|
parser.value( langOption ),
|
||||||
|
parser.value( brandOption ),
|
||||||
|
parser.isSet( uiOption ) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,13 +188,38 @@ load_module( const ModuleConfig& moduleConfig )
|
|||||||
return module;
|
return module;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @brief Create the right kind of QApplication
|
||||||
|
*
|
||||||
|
* Does primitive parsing of argv[] to find the --ui option and returns
|
||||||
|
* a UI-enabled application if it does.
|
||||||
|
*
|
||||||
|
* @p argc must be a reference (to main's argc) because the QCoreApplication
|
||||||
|
* constructors take a reference as well, and that would otherwise be a
|
||||||
|
* reference to a temporary.
|
||||||
|
*/
|
||||||
|
QCoreApplication*
|
||||||
|
createApplication( int& argc, char* argv[] )
|
||||||
|
{
|
||||||
|
for ( int i = 1; i < argc; ++i )
|
||||||
|
{
|
||||||
|
if ( !qstrcmp( argv[ i ], "--ui" ) || !qstrcmp( argv[ i ], "-U" ) )
|
||||||
|
{
|
||||||
|
auto* aw = new QApplication( argc, argv );
|
||||||
|
aw->setQuitOnLastWindowClosed( true );
|
||||||
|
return aw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new QCoreApplication( argc, argv );
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main( int argc, char* argv[] )
|
main( int argc, char* argv[] )
|
||||||
{
|
{
|
||||||
QCoreApplication a( argc, argv );
|
QCoreApplication* aw = createApplication( argc, argv );
|
||||||
QApplication* aw = nullptr;
|
|
||||||
|
|
||||||
ModuleConfig module = handle_args( a );
|
Logger::setupLogLevel( Logger::LOGVERBOSE );
|
||||||
|
|
||||||
|
ModuleConfig module = handle_args( *aw );
|
||||||
if ( module.moduleName().isEmpty() )
|
if ( module.moduleName().isEmpty() )
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
@ -198,6 +227,7 @@ main( int argc, char* argv[] )
|
|||||||
|
|
||||||
std::unique_ptr< Calamares::Settings > settings_p( new Calamares::Settings( QString(), true ) );
|
std::unique_ptr< Calamares::Settings > settings_p( new Calamares::Settings( QString(), true ) );
|
||||||
std::unique_ptr< Calamares::JobQueue > jobqueue_p( new Calamares::JobQueue( nullptr ) );
|
std::unique_ptr< Calamares::JobQueue > jobqueue_p( new Calamares::JobQueue( nullptr ) );
|
||||||
|
QMainWindow* mw = nullptr;
|
||||||
|
|
||||||
auto gs = jobqueue_p->globalStorage();
|
auto gs = jobqueue_p->globalStorage();
|
||||||
if ( !module.globalConfigFile().isEmpty() )
|
if ( !module.globalConfigFile().isEmpty() )
|
||||||
@ -223,8 +253,11 @@ main( int argc, char* argv[] )
|
|||||||
cDebug() << " .. got" << m->name() << m->typeString() << m->interfaceString();
|
cDebug() << " .. got" << m->name() << m->typeString() << m->interfaceString();
|
||||||
if ( m->type() == Calamares::Module::Type::View )
|
if ( m->type() == Calamares::Module::Type::View )
|
||||||
{
|
{
|
||||||
aw = new QApplication( argc, argv );
|
mw = module.m_ui ? new QMainWindow() : nullptr;
|
||||||
(void)Calamares::ViewManager::instance( nullptr );
|
|
||||||
|
(void)new Calamares::Branding( module.m_branding );
|
||||||
|
(void)new Calamares::ModuleManager( QStringList(), nullptr );
|
||||||
|
(void)Calamares::ViewManager::instance( mw );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !m->isLoaded() )
|
if ( !m->isLoaded() )
|
||||||
@ -238,6 +271,16 @@ main( int argc, char* argv[] )
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( mw )
|
||||||
|
{
|
||||||
|
QWidget* w = Calamares::ViewManager::instance()->currentStep()->widget();
|
||||||
|
w->setParent( mw );
|
||||||
|
mw->setCentralWidget( w );
|
||||||
|
w->show();
|
||||||
|
mw->show();
|
||||||
|
return aw->exec();
|
||||||
|
}
|
||||||
|
|
||||||
using TR = Logger::DebugRow< const char*, const QString >;
|
using TR = Logger::DebugRow< const char*, const QString >;
|
||||||
|
|
||||||
cDebug() << "Module metadata" << TR( "name", m->name() ) << TR( "type", m->typeString() )
|
cDebug() << "Module metadata" << TR( "name", m->name() ) << TR( "type", m->typeString() )
|
||||||
|
@ -21,11 +21,11 @@
|
|||||||
|
|
||||||
#include "LicensePage.h"
|
#include "LicensePage.h"
|
||||||
|
|
||||||
#include "ui_LicensePage.h"
|
|
||||||
#include "LicenseWidget.h"
|
#include "LicenseWidget.h"
|
||||||
|
#include "ui_LicensePage.h"
|
||||||
|
|
||||||
#include "JobQueue.h"
|
|
||||||
#include "GlobalStorage.h"
|
#include "GlobalStorage.h"
|
||||||
|
#include "JobQueue.h"
|
||||||
#include "ViewManager.h"
|
#include "ViewManager.h"
|
||||||
|
|
||||||
#include "utils/CalamaresUtilsGui.h"
|
#include "utils/CalamaresUtilsGui.h"
|
||||||
@ -36,10 +36,10 @@
|
|||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QBoxLayout>
|
#include <QBoxLayout>
|
||||||
|
#include <QComboBox>
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
#include <QFocusEvent>
|
#include <QFocusEvent>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QComboBox>
|
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@ -62,7 +62,9 @@ LicenseEntry::typeNames()
|
|||||||
LicenseEntry::LicenseEntry( const QVariantMap& conf )
|
LicenseEntry::LicenseEntry( const QVariantMap& conf )
|
||||||
{
|
{
|
||||||
if ( !conf.contains( "id" ) || !conf.contains( "name" ) || !conf.contains( "url" ) )
|
if ( !conf.contains( "id" ) || !conf.contains( "name" ) || !conf.contains( "url" ) )
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_id = conf[ "id" ].toString();
|
m_id = conf[ "id" ].toString();
|
||||||
m_prettyName = conf[ "name" ].toString();
|
m_prettyName = conf[ "name" ].toString();
|
||||||
@ -75,8 +77,10 @@ LicenseEntry::LicenseEntry(const QVariantMap& conf)
|
|||||||
QString typeString = conf.value( "type", "software" ).toString();
|
QString typeString = conf.value( "type", "software" ).toString();
|
||||||
m_type = typeNames().find( typeString, ok );
|
m_type = typeNames().find( typeString, ok );
|
||||||
if ( !ok )
|
if ( !ok )
|
||||||
|
{
|
||||||
cWarning() << "License entry" << m_id << "has unknown type" << typeString << "(using 'software')";
|
cWarning() << "License entry" << m_id << "has unknown type" << typeString << "(using 'software')";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
LicenseEntry::isLocal() const
|
LicenseEntry::isLocal() const
|
||||||
@ -119,9 +123,7 @@ LicensePage::LicensePage(QWidget *parent)
|
|||||||
|
|
||||||
connect( ui->acceptCheckBox, &QCheckBox::toggled, this, &LicensePage::checkAcceptance );
|
connect( ui->acceptCheckBox, &QCheckBox::toggled, this, &LicensePage::checkAcceptance );
|
||||||
|
|
||||||
CALAMARES_RETRANSLATE(
|
CALAMARES_RETRANSLATE( ui->acceptCheckBox->setText( tr( "I accept the terms and conditions above." ) ); )
|
||||||
ui->acceptCheckBox->setText( tr( "I accept the terms and conditions above." ) );
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -132,26 +134,27 @@ LicensePage::setEntries( const QList< LicenseEntry >& entriesList )
|
|||||||
m_entries.clear();
|
m_entries.clear();
|
||||||
m_entries.reserve( entriesList.count() );
|
m_entries.reserve( entriesList.count() );
|
||||||
|
|
||||||
const bool required = std::any_of( entriesList.cbegin(), entriesList.cend(), []( const LicenseEntry& e ){ return e.m_required; });
|
const bool required
|
||||||
|
= std::any_of( entriesList.cbegin(), entriesList.cend(), []( const LicenseEntry& e ) { return e.m_required; } );
|
||||||
if ( entriesList.isEmpty() )
|
if ( entriesList.isEmpty() )
|
||||||
|
{
|
||||||
m_allLicensesOptional = true;
|
m_allLicensesOptional = true;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
m_allLicensesOptional = !required;
|
m_allLicensesOptional = !required;
|
||||||
|
}
|
||||||
|
|
||||||
checkAcceptance( false );
|
checkAcceptance( false );
|
||||||
|
|
||||||
CALAMARES_RETRANSLATE(
|
CALAMARES_RETRANSLATE( if ( required ) {
|
||||||
if ( required )
|
|
||||||
{
|
|
||||||
ui->mainText->setText( tr( "<h1>License Agreement</h1>"
|
ui->mainText->setText( tr( "<h1>License Agreement</h1>"
|
||||||
"This setup procedure will install proprietary "
|
"This setup procedure will install proprietary "
|
||||||
"software that is subject to licensing terms." ) );
|
"software that is subject to licensing terms." ) );
|
||||||
ui->additionalText->setText( tr( "Please review the End User License "
|
ui->additionalText->setText( tr( "Please review the End User License "
|
||||||
"Agreements (EULAs) above.<br/>"
|
"Agreements (EULAs) above.<br/>"
|
||||||
"If you do not agree with the terms, the setup procedure cannot continue." ) );
|
"If you do not agree with the terms, the setup procedure cannot continue." ) );
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
ui->mainText->setText( tr( "<h1>License Agreement</h1>"
|
ui->mainText->setText( tr( "<h1>License Agreement</h1>"
|
||||||
"This setup procedure can install proprietary "
|
"This setup procedure can install proprietary "
|
||||||
"software that is subject to licensing terms "
|
"software that is subject to licensing terms "
|
||||||
@ -161,12 +164,10 @@ LicensePage::setEntries( const QList< LicenseEntry >& entriesList )
|
|||||||
"Agreements (EULAs) above.<br/>"
|
"Agreements (EULAs) above.<br/>"
|
||||||
"If you do not agree with the terms, proprietary software will not "
|
"If you do not agree with the terms, proprietary software will not "
|
||||||
"be installed, and open source alternatives will be used instead." ) );
|
"be installed, and open source alternatives will be used instead." ) );
|
||||||
}
|
} ui->retranslateUi( this );
|
||||||
ui->retranslateUi( this );
|
|
||||||
|
|
||||||
for ( const auto& w : m_entries )
|
for ( const auto& w
|
||||||
w->retranslateUi();
|
: m_entries ) w->retranslateUi(); )
|
||||||
)
|
|
||||||
|
|
||||||
for ( const LicenseEntry& entry : entriesList )
|
for ( const LicenseEntry& entry : entriesList )
|
||||||
{
|
{
|
||||||
@ -190,7 +191,8 @@ LicensePage::updateGlobalStorage( bool v )
|
|||||||
Calamares::JobQueue::instance()->globalStorage()->insert( "licenseAgree", v );
|
Calamares::JobQueue::instance()->globalStorage()->insert( "licenseAgree", v );
|
||||||
}
|
}
|
||||||
|
|
||||||
void LicensePage::checkAcceptance( bool checked )
|
void
|
||||||
|
LicensePage::checkAcceptance( bool checked )
|
||||||
{
|
{
|
||||||
updateGlobalStorage( checked );
|
updateGlobalStorage( checked );
|
||||||
|
|
||||||
|
@ -24,8 +24,8 @@
|
|||||||
|
|
||||||
#include "utils/NamedEnum.h"
|
#include "utils/NamedEnum.h"
|
||||||
|
|
||||||
#include <QWidget>
|
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
namespace Ui
|
namespace Ui
|
||||||
{
|
{
|
||||||
|
@ -19,9 +19,9 @@
|
|||||||
|
|
||||||
#include "LicenseViewStep.h"
|
#include "LicenseViewStep.h"
|
||||||
|
|
||||||
#include "LicensePage.h"
|
|
||||||
#include "JobQueue.h"
|
|
||||||
#include "GlobalStorage.h"
|
#include "GlobalStorage.h"
|
||||||
|
#include "JobQueue.h"
|
||||||
|
#include "LicensePage.h"
|
||||||
#include "utils/Logger.h"
|
#include "utils/Logger.h"
|
||||||
|
|
||||||
#include <QVariantMap>
|
#include <QVariantMap>
|
||||||
@ -33,16 +33,17 @@ LicenseViewStep::LicenseViewStep( QObject* parent )
|
|||||||
, m_widget( new LicensePage )
|
, m_widget( new LicensePage )
|
||||||
{
|
{
|
||||||
emit nextStatusChanged( false );
|
emit nextStatusChanged( false );
|
||||||
connect( m_widget, &LicensePage::nextStatusChanged,
|
connect( m_widget, &LicensePage::nextStatusChanged, this, &LicenseViewStep::nextStatusChanged );
|
||||||
this, &LicenseViewStep::nextStatusChanged );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LicenseViewStep::~LicenseViewStep()
|
LicenseViewStep::~LicenseViewStep()
|
||||||
{
|
{
|
||||||
if ( m_widget && m_widget->parent() == nullptr )
|
if ( m_widget && m_widget->parent() == nullptr )
|
||||||
|
{
|
||||||
m_widget->deleteLater();
|
m_widget->deleteLater();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
QString
|
QString
|
||||||
@ -97,20 +98,23 @@ void
|
|||||||
LicenseViewStep::setConfigurationMap( const QVariantMap& configurationMap )
|
LicenseViewStep::setConfigurationMap( const QVariantMap& configurationMap )
|
||||||
{
|
{
|
||||||
QList< LicenseEntry > entriesList;
|
QList< LicenseEntry > entriesList;
|
||||||
if ( configurationMap.contains( "entries" ) &&
|
if ( configurationMap.contains( "entries" ) && configurationMap.value( "entries" ).type() == QVariant::List )
|
||||||
configurationMap.value( "entries" ).type() == QVariant::List )
|
|
||||||
{
|
{
|
||||||
const auto entries = configurationMap.value( "entries" ).toList();
|
const auto entries = configurationMap.value( "entries" ).toList();
|
||||||
for ( const QVariant& entryV : entries )
|
for ( const QVariant& entryV : entries )
|
||||||
{
|
{
|
||||||
if ( entryV.type() != QVariant::Map )
|
if ( entryV.type() != QVariant::Map )
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
LicenseEntry entry( entryV.toMap() );
|
LicenseEntry entry( entryV.toMap() );
|
||||||
if ( entry.isValid() )
|
if ( entry.isValid() )
|
||||||
|
{
|
||||||
entriesList.append( entry );
|
entriesList.append( entry );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_widget->setEntries( entriesList );
|
m_widget->setEntries( entriesList );
|
||||||
}
|
}
|
||||||
|
@ -20,9 +20,9 @@
|
|||||||
#ifndef LICENSEPAGEPLUGIN_H
|
#ifndef LICENSEPAGEPLUGIN_H
|
||||||
#define LICENSEPAGEPLUGIN_H
|
#define LICENSEPAGEPLUGIN_H
|
||||||
|
|
||||||
|
#include <PluginDllMacro.h>
|
||||||
#include <utils/PluginFactory.h>
|
#include <utils/PluginFactory.h>
|
||||||
#include <viewpages/ViewStep.h>
|
#include <viewpages/ViewStep.h>
|
||||||
#include <PluginDllMacro.h>
|
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
@ -34,7 +34,9 @@ static QString
|
|||||||
loadLocalFile( const QUrl& u )
|
loadLocalFile( const QUrl& u )
|
||||||
{
|
{
|
||||||
if ( !u.isLocalFile() )
|
if ( !u.isLocalFile() )
|
||||||
|
{
|
||||||
return QString();
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
QFile file( u.path() );
|
QFile file( u.path() );
|
||||||
if ( !file.open( QIODevice::ReadOnly | QIODevice::Text ) )
|
if ( !file.open( QIODevice::ReadOnly | QIODevice::Text ) )
|
||||||
@ -108,11 +110,10 @@ LicenseWidget::LicenseWidget( LicenseEntry entry, QWidget* parent )
|
|||||||
retranslateUi();
|
retranslateUi();
|
||||||
}
|
}
|
||||||
|
|
||||||
LicenseWidget::~LicenseWidget()
|
LicenseWidget::~LicenseWidget() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void LicenseWidget::retranslateUi()
|
void
|
||||||
|
LicenseWidget::retranslateUi()
|
||||||
{
|
{
|
||||||
QString productDescription;
|
QString productDescription;
|
||||||
switch ( m_entry.m_type )
|
switch ( m_entry.m_type )
|
||||||
@ -173,7 +174,9 @@ LicenseWidget::expandClicked()
|
|||||||
|
|
||||||
// Show/hide based on the new arrow direction.
|
// Show/hide based on the new arrow direction.
|
||||||
if ( m_fullText )
|
if ( m_fullText )
|
||||||
|
{
|
||||||
m_fullText->setHidden( m_expandLicenseButton->arrowType() == Qt::UpArrow );
|
m_fullText->setHidden( m_expandLicenseButton->arrowType() == Qt::UpArrow );
|
||||||
|
}
|
||||||
|
|
||||||
updateExpandToolTip();
|
updateExpandToolTip();
|
||||||
}
|
}
|
||||||
@ -186,21 +189,15 @@ LicenseWidget::updateExpandToolTip()
|
|||||||
{
|
{
|
||||||
const bool isNowCollapsed = m_expandLicenseButton->arrowType() == Qt::UpArrow;
|
const bool isNowCollapsed = m_expandLicenseButton->arrowType() == Qt::UpArrow;
|
||||||
|
|
||||||
m_expandLicenseButton->setToolTip(
|
m_expandLicenseButton->setToolTip( isNowCollapsed ? tr( "Shows the complete license text" )
|
||||||
isNowCollapsed
|
: tr( "Hide license text" ) );
|
||||||
? tr( "Shows the complete license text" )
|
m_viewLicenseLabel->setText( isNowCollapsed ? tr( "Show license agreement" ) : tr( "Hide license agreement" ) );
|
||||||
: tr( "Hide license text" )
|
|
||||||
) ;
|
|
||||||
m_viewLicenseLabel->setText(
|
|
||||||
isNowCollapsed
|
|
||||||
? tr( "Show license agreement" )
|
|
||||||
: tr( "Hide license agreement" ) );
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_expandLicenseButton->setToolTip( tr( "Opens the license agreement in a browser window." ) );
|
m_expandLicenseButton->setToolTip( tr( "Opens the license agreement in a browser window." ) );
|
||||||
m_viewLicenseLabel->setText( tr( "<a href=\"%1\">View license agreement</a>" )
|
m_viewLicenseLabel->setText(
|
||||||
.arg( m_entry.m_url.toString() ) );
|
tr( "<a href=\"%1\">View license agreement</a>" ).arg( m_entry.m_url.toString() ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +34,6 @@ PackageChooserPage::PackageChooserPage( PackageChooserMode mode, QWidget* parent
|
|||||||
tr( "Please pick a product from the list. The selected product will be installed." ) )
|
tr( "Please pick a product from the list. The selected product will be installed." ) )
|
||||||
{
|
{
|
||||||
m_introduction.screenshot = QPixmap( QStringLiteral( ":/images/no-selection.png" ) );
|
m_introduction.screenshot = QPixmap( QStringLiteral( ":/images/no-selection.png" ) );
|
||||||
cDebug() << m_introduction.screenshot;
|
|
||||||
|
|
||||||
ui->setupUi( this );
|
ui->setupUi( this );
|
||||||
CALAMARES_RETRANSLATE( updateLabels(); )
|
CALAMARES_RETRANSLATE( updateLabels(); )
|
||||||
@ -42,9 +41,9 @@ PackageChooserPage::PackageChooserPage( PackageChooserMode mode, QWidget* parent
|
|||||||
switch ( mode )
|
switch ( mode )
|
||||||
{
|
{
|
||||||
case PackageChooserMode::Optional:
|
case PackageChooserMode::Optional:
|
||||||
case PackageChooserMode::Exclusive:
|
case PackageChooserMode::Required:
|
||||||
ui->products->setSelectionMode( QAbstractItemView::SingleSelection );
|
ui->products->setSelectionMode( QAbstractItemView::SingleSelection );
|
||||||
case PackageChooserMode::Multiple:
|
case PackageChooserMode::OptionalMultiple:
|
||||||
case PackageChooserMode::RequiredMultiple:
|
case PackageChooserMode::RequiredMultiple:
|
||||||
ui->products->setSelectionMode( QAbstractItemView::ExtendedSelection );
|
ui->products->setSelectionMode( QAbstractItemView::ExtendedSelection );
|
||||||
}
|
}
|
||||||
@ -87,6 +86,26 @@ void
|
|||||||
PackageChooserPage::setModel( QAbstractItemModel* model )
|
PackageChooserPage::setModel( QAbstractItemModel* model )
|
||||||
{
|
{
|
||||||
ui->products->setModel( model );
|
ui->products->setModel( model );
|
||||||
|
|
||||||
|
// Check if any of the items in the model is the "none" option.
|
||||||
|
// If so, copy its values into the introduction / none item.
|
||||||
|
for ( int r = 0; r < model->rowCount(); ++r )
|
||||||
|
{
|
||||||
|
auto index = model->index( r, 0 );
|
||||||
|
if ( index.isValid() )
|
||||||
|
{
|
||||||
|
QVariant v = model->data( index, PackageListModel::IdRole );
|
||||||
|
if ( v.isValid() && v.toString().isEmpty() )
|
||||||
|
{
|
||||||
|
m_introduction.name = model->data( index, PackageListModel::NameRole ).toString();
|
||||||
|
m_introduction.description = model->data( index, PackageListModel::DescriptionRole ).toString();
|
||||||
|
m_introduction.screenshot = model->data( index, PackageListModel::ScreenshotRole ).value< QPixmap >();
|
||||||
|
currentChanged( QModelIndex() );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
connect( ui->products->selectionModel(),
|
connect( ui->products->selectionModel(),
|
||||||
&QItemSelectionModel::selectionChanged,
|
&QItemSelectionModel::selectionChanged,
|
||||||
this,
|
this,
|
||||||
@ -98,3 +117,24 @@ PackageChooserPage::hasSelection() const
|
|||||||
{
|
{
|
||||||
return ui && ui->products && ui->products->selectionModel() && ui->products->selectionModel()->hasSelection();
|
return ui && ui->products && ui->products->selectionModel() && ui->products->selectionModel()->hasSelection();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList
|
||||||
|
PackageChooserPage::selectedPackageIds() const
|
||||||
|
{
|
||||||
|
if ( !( ui && ui->products && ui->products->selectionModel() ) )
|
||||||
|
{
|
||||||
|
return QStringList();
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto* model = ui->products->model();
|
||||||
|
QStringList ids;
|
||||||
|
for ( const auto& index : ui->products->selectionModel()->selectedIndexes() )
|
||||||
|
{
|
||||||
|
QString pid = model->data( index, PackageListModel::IdRole ).toString();
|
||||||
|
if ( !pid.isEmpty() )
|
||||||
|
{
|
||||||
|
ids.append( pid );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ids;
|
||||||
|
}
|
||||||
|
@ -37,7 +37,13 @@ public:
|
|||||||
|
|
||||||
void setModel( QAbstractItemModel* model );
|
void setModel( QAbstractItemModel* model );
|
||||||
|
|
||||||
|
/// @brief Is anything selected?
|
||||||
bool hasSelection() const;
|
bool hasSelection() const;
|
||||||
|
/** @brief Get the list of selected ids
|
||||||
|
*
|
||||||
|
* This list may be empty (if none is selected).
|
||||||
|
*/
|
||||||
|
QStringList selectedPackageIds() const;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void currentChanged( const QModelIndex& index );
|
void currentChanged( const QModelIndex& index );
|
||||||
|
@ -37,7 +37,7 @@ PackageChooserViewStep::PackageChooserViewStep( QObject* parent )
|
|||||||
: Calamares::ViewStep( parent )
|
: Calamares::ViewStep( parent )
|
||||||
, m_widget( nullptr )
|
, m_widget( nullptr )
|
||||||
, m_model( nullptr )
|
, m_model( nullptr )
|
||||||
, m_mode( PackageChooserMode::Exclusive )
|
, m_mode( PackageChooserMode::Required )
|
||||||
{
|
{
|
||||||
emit nextStatusChanged( false );
|
emit nextStatusChanged( false );
|
||||||
}
|
}
|
||||||
@ -100,10 +100,10 @@ PackageChooserViewStep::isNextEnabled() const
|
|||||||
switch ( m_mode )
|
switch ( m_mode )
|
||||||
{
|
{
|
||||||
case PackageChooserMode::Optional:
|
case PackageChooserMode::Optional:
|
||||||
case PackageChooserMode::Multiple:
|
case PackageChooserMode::OptionalMultiple:
|
||||||
// zero or one OR zero or more
|
// zero or one OR zero or more
|
||||||
return true;
|
return true;
|
||||||
case PackageChooserMode::Exclusive:
|
case PackageChooserMode::Required:
|
||||||
case PackageChooserMode::RequiredMultiple:
|
case PackageChooserMode::RequiredMultiple:
|
||||||
// exactly one OR one or more
|
// exactly one OR one or more
|
||||||
return m_widget->hasSelection();
|
return m_widget->hasSelection();
|
||||||
@ -137,6 +137,15 @@ PackageChooserViewStep::isAtEnd() const
|
|||||||
void
|
void
|
||||||
PackageChooserViewStep::onLeave()
|
PackageChooserViewStep::onLeave()
|
||||||
{
|
{
|
||||||
|
QString key = QStringLiteral( "packagechooser_%1" ).arg( m_id );
|
||||||
|
QString value;
|
||||||
|
if ( m_widget->hasSelection() )
|
||||||
|
{
|
||||||
|
value = m_widget->selectedPackageIds().join( ',' );
|
||||||
|
}
|
||||||
|
Calamares::JobQueue::instance()->globalStorage()->insert( key, value );
|
||||||
|
|
||||||
|
cDebug() << "PackageChooser" << key << "selected" << value;
|
||||||
}
|
}
|
||||||
|
|
||||||
Calamares::JobList
|
Calamares::JobList
|
||||||
@ -149,15 +158,40 @@ PackageChooserViewStep::jobs() const
|
|||||||
void
|
void
|
||||||
PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap )
|
PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap )
|
||||||
{
|
{
|
||||||
// TODO: use the configurationMap
|
QString mode = CalamaresUtils::getString( configurationMap, "mode" );
|
||||||
|
bool ok = false;
|
||||||
|
if ( !mode.isEmpty() )
|
||||||
|
{
|
||||||
|
m_mode = roleNames().find( mode, ok );
|
||||||
|
}
|
||||||
|
if ( !ok )
|
||||||
|
{
|
||||||
|
m_mode = PackageChooserMode::Required;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_id = CalamaresUtils::getString( configurationMap, "id" );
|
||||||
|
if ( m_id.isEmpty() )
|
||||||
|
{
|
||||||
|
// Not set, so use the instance id
|
||||||
|
// TODO: use a stronger type than QString for structured IDs
|
||||||
|
m_id = moduleInstanceKey().split( '@' ).last();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: replace this hard-coded model
|
||||||
if ( !m_model )
|
if ( !m_model )
|
||||||
{
|
{
|
||||||
|
|
||||||
m_model = new PackageListModel( nullptr );
|
m_model = new PackageListModel( nullptr );
|
||||||
|
m_model->addPackage( PackageItem { QString(),
|
||||||
|
QString(),
|
||||||
|
"No Desktop",
|
||||||
|
"Please pick a desktop environment from the list. "
|
||||||
|
"If you don't want to install a desktop, that's fine, "
|
||||||
|
"your system will start up in text-only mode and you can "
|
||||||
|
"install a desktop environment later.",
|
||||||
|
":/images/no-selection.png" } );
|
||||||
m_model->addPackage( PackageItem { "kde", "kde", "Plasma", "Plasma Desktop", ":/images/kde.png" } );
|
m_model->addPackage( PackageItem { "kde", "kde", "Plasma", "Plasma Desktop", ":/images/kde.png" } );
|
||||||
m_model->addPackage(
|
m_model->addPackage( PackageItem {
|
||||||
PackageItem { "gnome", "gnome", "GNOME", "GNU Networked Object Modeling Environment Desktop", ":/images/gnome.png" } );
|
"gnome", "gnome", "GNOME", "GNU Networked Object Modeling Environment Desktop", ":/images/gnome.png" } );
|
||||||
|
|
||||||
|
|
||||||
if ( m_widget )
|
if ( m_widget )
|
||||||
|
@ -30,7 +30,6 @@
|
|||||||
#include <QVariantMap>
|
#include <QVariantMap>
|
||||||
|
|
||||||
class PackageChooserPage;
|
class PackageChooserPage;
|
||||||
class PackageListModel;
|
|
||||||
|
|
||||||
class PLUGINDLLEXPORT PackageChooserViewStep : public Calamares::ViewStep
|
class PLUGINDLLEXPORT PackageChooserViewStep : public Calamares::ViewStep
|
||||||
{
|
{
|
||||||
@ -61,7 +60,10 @@ private:
|
|||||||
|
|
||||||
PackageChooserPage* m_widget;
|
PackageChooserPage* m_widget;
|
||||||
PackageListModel* m_model;
|
PackageListModel* m_model;
|
||||||
|
|
||||||
|
// Configuration
|
||||||
PackageChooserMode m_mode;
|
PackageChooserMode m_mode;
|
||||||
|
QString m_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
CALAMARES_PLUGIN_FACTORY_DECLARATION( PackageChooserViewStepFactory )
|
CALAMARES_PLUGIN_FACTORY_DECLARATION( PackageChooserViewStepFactory )
|
||||||
|
@ -20,6 +20,26 @@
|
|||||||
|
|
||||||
#include "utils/Logger.h"
|
#include "utils/Logger.h"
|
||||||
|
|
||||||
|
const NamedEnumTable< PackageChooserMode >&
|
||||||
|
roleNames()
|
||||||
|
{
|
||||||
|
static const NamedEnumTable< PackageChooserMode > names {
|
||||||
|
{ "optional", PackageChooserMode::Optional },
|
||||||
|
{ "required", PackageChooserMode::Required },
|
||||||
|
{ "optionalmultiple", PackageChooserMode::OptionalMultiple },
|
||||||
|
{ "requiredmultiple", PackageChooserMode::RequiredMultiple },
|
||||||
|
// and a bunch of aliases
|
||||||
|
{ "zero-or-one", PackageChooserMode::Optional },
|
||||||
|
{ "radio", PackageChooserMode::Required },
|
||||||
|
{ "one", PackageChooserMode::Required },
|
||||||
|
{ "set", PackageChooserMode::OptionalMultiple },
|
||||||
|
{ "zero-or-more", PackageChooserMode::OptionalMultiple },
|
||||||
|
{ "multiple", PackageChooserMode::RequiredMultiple },
|
||||||
|
{ "one-or-more", PackageChooserMode::RequiredMultiple }
|
||||||
|
};
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
PackageItem
|
PackageItem
|
||||||
PackageItem::fromAppStream( const QString& filename )
|
PackageItem::fromAppStream( const QString& filename )
|
||||||
{
|
{
|
||||||
@ -108,6 +128,10 @@ PackageListModel::data( const QModelIndex& index, int role ) const
|
|||||||
{
|
{
|
||||||
return m_packages[ row ].screenshot;
|
return m_packages[ row ].screenshot;
|
||||||
}
|
}
|
||||||
|
else if ( role == IdRole )
|
||||||
|
{
|
||||||
|
return m_packages[ row ].id;
|
||||||
|
}
|
||||||
|
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
#ifndef PACKAGEMODEL_H
|
#ifndef PACKAGEMODEL_H
|
||||||
#define PACKAGEMODEL_H
|
#define PACKAGEMODEL_H
|
||||||
|
|
||||||
|
#include "utils/NamedEnum.h"
|
||||||
|
|
||||||
#include <QAbstractListModel>
|
#include <QAbstractListModel>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QPixmap>
|
#include <QPixmap>
|
||||||
@ -27,11 +29,13 @@
|
|||||||
enum class PackageChooserMode
|
enum class PackageChooserMode
|
||||||
{
|
{
|
||||||
Optional, // zero or one
|
Optional, // zero or one
|
||||||
Exclusive, // exactly one
|
Required, // exactly one
|
||||||
Multiple, // zero or more
|
OptionalMultiple, // zero or more
|
||||||
RequiredMultiple // one or more
|
RequiredMultiple // one or more
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const NamedEnumTable< PackageChooserMode >& roleNames();
|
||||||
|
|
||||||
struct PackageItem
|
struct PackageItem
|
||||||
{
|
{
|
||||||
QString id;
|
QString id;
|
||||||
@ -69,7 +73,7 @@ class PackageListModel : public QAbstractListModel
|
|||||||
public:
|
public:
|
||||||
PackageListModel( PackageList&& items, QObject* parent );
|
PackageListModel( PackageList&& items, QObject* parent );
|
||||||
PackageListModel( QObject* parent );
|
PackageListModel( QObject* parent );
|
||||||
virtual ~PackageListModel();
|
virtual ~PackageListModel() override;
|
||||||
|
|
||||||
void addPackage( PackageItem&& p );
|
void addPackage( PackageItem&& p );
|
||||||
|
|
||||||
@ -80,7 +84,8 @@ public:
|
|||||||
{
|
{
|
||||||
NameRole = Qt::DisplayRole,
|
NameRole = Qt::DisplayRole,
|
||||||
DescriptionRole = Qt::UserRole,
|
DescriptionRole = Qt::UserRole,
|
||||||
ScreenshotRole
|
ScreenshotRole,
|
||||||
|
IdRole
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
21
src/modules/packagechooser/packagechooser.conf
Normal file
21
src/modules/packagechooser/packagechooser.conf
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# Configuration for the low-density software chooser
|
||||||
|
---
|
||||||
|
# The packagechooser writes a GlobalStorage value for the choice that
|
||||||
|
# has been made. The key is *packagechooser_<id>*. If *id* is set here,
|
||||||
|
# it is substituted into the key name. If it is not set, the module's
|
||||||
|
# instance name is used; see the *instances* section of `settings.conf`.
|
||||||
|
# If there is just one packagechooser module, and no *id* is set,
|
||||||
|
# resulting GS key is probably *packagechooser_packagechooser*.
|
||||||
|
#
|
||||||
|
# The GS value is a comma-separated list of the IDs of the selected
|
||||||
|
# packages, or an empty string if none is selected.
|
||||||
|
#
|
||||||
|
# id: ""
|
||||||
|
|
||||||
|
# Software selection mode, to set whether the software packages
|
||||||
|
# can be chosen singly, or multiply.
|
||||||
|
#
|
||||||
|
# Possible modes are "optional", "required" (for zero or one)
|
||||||
|
# or "optionalmultiple", "requiredmultiple" (for zero-or-more
|
||||||
|
# or one-or-more).
|
||||||
|
mode: required
|
@ -53,6 +53,12 @@
|
|||||||
<property name="text">
|
<property name="text">
|
||||||
<string>TextLabel</string>
|
<string>TextLabel</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="openExternalLinks">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
Loading…
Reference in New Issue
Block a user