[officechooser] merge with upstream

This commit is contained in:
Philip Müller 2019-08-07 07:38:12 +02:00
parent ac5c2a041d
commit 51ec85fdd5
14 changed files with 502 additions and 83 deletions

View File

@ -1,4 +1,15 @@
find_package( Qt5 COMPONENTS Core Gui Widgets REQUIRED ) find_package( Qt5 COMPONENTS Core Gui Widgets REQUIRED )
set( _extra_libraries "" )
### OPTIONAL AppData XML support in PackageModel
#
#
find_package(Qt5 COMPONENTS Xml)
if ( Qt5Xml_FOUND )
add_definitions( -DHAVE_XML )
list( APPEND _extra_libraries Qt5::Xml )
endif()
calamares_add_plugin( officechooser calamares_add_plugin( officechooser
TYPE viewmodule TYPE viewmodule
@ -13,6 +24,7 @@ calamares_add_plugin( officechooser
page_package.ui page_package.ui
LINK_PRIVATE_LIBRARIES LINK_PRIVATE_LIBRARIES
calamaresui calamaresui
${_extra_libraries}
SHARED_LIB SHARED_LIB
) )
@ -20,11 +32,14 @@ if( ECM_FOUND AND BUILD_TESTING )
ecm_add_test( ecm_add_test(
Tests.cpp Tests.cpp
TEST_NAME TEST_NAME
packagechooosertest packagechoosertest
LINK_LIBRARIES LINK_LIBRARIES
${CALAMARES_LIBRARIES} ${CALAMARES_LIBRARIES}
calamares_viewmodule_packagechooser
Qt5::Core Qt5::Core
Qt5::Test Qt5::Test
Qt5::Gui
${_extra_libraries}
) )
calamares_automoc( packagechooosertest) calamares_automoc( packagechoosertest)
endif() endif()

View File

@ -1,7 +1,6 @@
/* === This file is part of Calamares - <https://github.com/calamares> === /* === This file is part of Calamares - <https://github.com/calamares> ===
* *
* Copyright 2019, Adriaan de Groot <groot@kde.org> * Copyright 2019, Adriaan de Groot <groot@kde.org>
* Copyright 2019, Philip MÜller <philm@manjaro.org>
* *
* Calamares is free software: you can redistribute it and/or modify * Calamares is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -31,10 +30,10 @@ PackageChooserPage::PackageChooserPage( PackageChooserMode mode, QWidget* parent
, ui( new Ui::PackageChooserPage ) , ui( new Ui::PackageChooserPage )
, m_introduction( QString(), , m_introduction( QString(),
QString(), QString(),
tr( "Office Suite" ), tr( "Package Selection" ),
tr( "Please pick an office suite 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/choose-office.jpg" ) ); m_introduction.screenshot = QPixmap( QStringLiteral( ":/images/no-selection.png" ) );
ui->setupUi( this ); ui->setupUi( this );
CALAMARES_RETRANSLATE( updateLabels(); ) CALAMARES_RETRANSLATE( updateLabels(); )
@ -42,9 +41,12 @@ PackageChooserPage::PackageChooserPage( PackageChooserMode mode, QWidget* parent
switch ( mode ) switch ( mode )
{ {
case PackageChooserMode::Optional: case PackageChooserMode::Optional:
FALLTHRU;
case PackageChooserMode::Required: case PackageChooserMode::Required:
ui->products->setSelectionMode( QAbstractItemView::SingleSelection ); ui->products->setSelectionMode( QAbstractItemView::SingleSelection );
break;
case PackageChooserMode::OptionalMultiple: case PackageChooserMode::OptionalMultiple:
FALLTHRU;
case PackageChooserMode::RequiredMultiple: case PackageChooserMode::RequiredMultiple:
ui->products->setSelectionMode( QAbstractItemView::ExtendedSelection ); ui->products->setSelectionMode( QAbstractItemView::ExtendedSelection );
} }
@ -55,9 +57,9 @@ PackageChooserPage::currentChanged( const QModelIndex& index )
{ {
if ( !index.isValid() || !ui->products->selectionModel()->hasSelection() ) if ( !index.isValid() || !ui->products->selectionModel()->hasSelection() )
{ {
ui->productName->setText( m_introduction.name ); ui->productName->setText( m_introduction.name.get() );
ui->productScreenshot->setPixmap( m_introduction.screenshot ); ui->productScreenshot->setPixmap( m_introduction.screenshot );
ui->productDescription->setText( m_introduction.description ); ui->productDescription->setText( m_introduction.description.get() );
} }
else else
{ {

View File

@ -1,7 +1,6 @@
/* === This file is part of Calamares - <https://github.com/calamares> === /* === This file is part of Calamares - <https://github.com/calamares> ===
* *
* Copyright 2019, Adriaan de Groot <groot@kde.org> * Copyright 2019, Adriaan de Groot <groot@kde.org>
* Copyright 2019, Philip MÜller <philm@manjaro.org>
* *
* Calamares is free software: you can redistribute it and/or modify * Calamares is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -57,7 +56,7 @@ PackageChooserViewStep::~PackageChooserViewStep()
QString QString
PackageChooserViewStep::prettyName() const PackageChooserViewStep::prettyName() const
{ {
return tr( "Office Suite" ); return tr( "Packages" );
} }
@ -77,7 +76,7 @@ PackageChooserViewStep::widget()
} }
else else
{ {
cWarning() << "OfficeChooser Widget created before model."; cWarning() << "PackageChooser Widget created before model.";
} }
} }
return m_widget; return m_widget;
@ -146,7 +145,7 @@ PackageChooserViewStep::onLeave()
} }
Calamares::JobQueue::instance()->globalStorage()->insert( key, value ); Calamares::JobQueue::instance()->globalStorage()->insert( key, value );
cDebug() << "OfficeChooser" << key << "selected" << value; cDebug() << "PackageChooser" << key << "selected" << value;
} }
Calamares::JobList Calamares::JobList
@ -178,35 +177,68 @@ PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap
m_id = moduleInstanceKey().split( '@' ).last(); m_id = moduleInstanceKey().split( '@' ).last();
} }
bool first_time = !m_model;
if ( configurationMap.contains( "items" ) )
{
fillModel( configurationMap.value( "items" ).toList() );
}
// TODO: replace this hard-coded model // 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(), m_model->addPackage( PackageItem { QString(),
QString(), QString(),
"No Office Suite", "No Desktop",
"Please pick an office suite from the list. " "Please pick a desktop environment from the list. "
"If you don't want to install an office suite, that's fine, " "If you don't want to install a desktop, that's fine, "
"you can install one later as needed.", "your system will start up in text-only mode and you can "
":/images/choose-office.jpg" } ); "install a desktop environment later.",
m_model->addPackage( PackageItem { "libreoffice-still", ":/images/no-selection.png" } );
"libreoffice-still", m_model->addPackage( PackageItem { "kde", "kde", "Plasma", "Plasma Desktop", ":/images/kde.png" } );
"LibreOffice", m_model->addPackage( PackageItem {
"LibreOffice is a powerful and free office suite, used by millions of people around the world. " "gnome", "gnome", "GNOME", "GNU Networked Object Modeling Environment Desktop", ":/images/gnome.png" } );
"Its clean interface and feature-rich tools help you unleash your creativity and enhance your productivity.", }
":/images/LibreOffice.jpg" } );
m_model->addPackage( PackageItem { "freeoffice", if ( first_time && m_widget && m_model )
"freeoffice", {
"FreeOffice", hookupModel();
"FreeOffice 2018 is a full-featured Office suite with word processing, " }
"spreadsheet and presentation software. It is seamlessly compatible with Microsoft Office. " }
"(Note: You need to register the product for free longterm usage)",
":/images/FreeOffice.jpg" } );
if ( m_widget ) void
PackageChooserViewStep::fillModel( const QVariantList& items )
{
if ( !m_model )
{
m_model = new PackageListModel( nullptr );
}
if ( items.isEmpty() )
{
cWarning() << "No *items* for PackageChooser module.";
return;
}
cDebug() << "Loading PackageChooser model items from config";
int item_index = 0;
for ( const auto& item_it : items )
{
++item_index;
QVariantMap item_map = item_it.toMap();
if ( item_map.isEmpty() )
{ {
hookupModel(); cWarning() << "PackageChooser entry" << item_index << "is not valid.";
continue;
}
if ( item_map.contains( "appdata" ) )
{
m_model->addPackage( PackageItem::fromAppData( item_map ) );
}
else
{
m_model->addPackage( PackageItem( item_map ) );
} }
} }
} }

View File

@ -56,6 +56,7 @@ public:
void setConfigurationMap( const QVariantMap& configurationMap ) override; void setConfigurationMap( const QVariantMap& configurationMap ) override;
private: private:
void fillModel( const QVariantList& items );
void hookupModel(); void hookupModel();
PackageChooserPage* m_widget; PackageChooserPage* m_widget;

View File

@ -19,6 +19,13 @@
#include "PackageModel.h" #include "PackageModel.h"
#include "utils/Logger.h" #include "utils/Logger.h"
#include "utils/Variant.h"
#ifdef HAVE_XML
#include <QDomDocument>
#include <QDomNodeList>
#include <QFile>
#endif
const NamedEnumTable< PackageChooserMode >& const NamedEnumTable< PackageChooserMode >&
roleNames() roleNames()
@ -40,13 +47,6 @@ roleNames()
return names; return names;
} }
PackageItem
PackageItem::fromAppStream( const QString& filename )
{
// TODO: implement this
return PackageItem {};
}
PackageItem::PackageItem() {} PackageItem::PackageItem() {}
PackageItem::PackageItem( const QString& a_id, PackageItem::PackageItem( const QString& a_id,
@ -73,6 +73,239 @@ PackageItem::PackageItem( const QString& a_id,
{ {
} }
PackageItem::PackageItem::PackageItem( const QVariantMap& item_map )
: id( CalamaresUtils::getString( item_map, "id" ) )
, package( CalamaresUtils::getString( item_map, "package" ) )
, name( CalamaresUtils::Locale::TranslatedString( item_map, "name" ) )
, description( CalamaresUtils::Locale::TranslatedString( item_map, "description" ) )
, screenshot( CalamaresUtils::getString( item_map, "screenshot" ) )
{
if ( name.isEmpty() && id.isEmpty() )
{
name = QObject::tr( "No product" );
}
else if ( name.isEmpty() )
{
cWarning() << "PackageChooser item" << id << "has an empty name.";
}
if ( description.isEmpty() )
{
description = QObject::tr( "No description provided." );
}
}
#ifdef HAVE_XML
/** @brief try to load the given @p fileName XML document
*
* Returns a QDomDocument, which will be valid iff the file can
* be read and contains valid XML data.
*/
static inline QDomDocument
loadAppData( const QString& fileName )
{
QFile file( fileName );
if ( !file.open( QIODevice::ReadOnly ) )
{
return QDomDocument();
}
QDomDocument doc( "AppData" );
if ( !doc.setContent( &file ) )
{
file.close();
return QDomDocument();
}
file.close();
return doc;
}
/** @brief gets the text of child element @p tagName
*/
static inline QString
getChildText( const QDomNode& n, const QString& tagName )
{
QDomElement e = n.firstChildElement( tagName );
return e.isNull() ? QString() : e.text();
}
/** @brief Gets a suitable screenshot path
*
* The <screenshots> element contains zero or more <screenshot>
* elements, which can have a *type* associated with them.
* Scan the screenshot elements, return the <image> path
* for the one labeled with type=default or, if there is no
* default, the first element.
*/
static inline QString
getScreenshotPath( const QDomNode& n )
{
QDomElement shotsNode = n.firstChildElement( "screenshots" );
if ( shotsNode.isNull() )
{
return QString();
}
const QDomNodeList shotList = shotsNode.childNodes();
int firstScreenshot = -1; // Use which screenshot node?
for ( int i = 0; i < shotList.count(); ++i )
{
if ( !shotList.at( i ).isElement() )
{
continue;
}
QDomElement e = shotList.at( i ).toElement();
if ( e.tagName() != "screenshot" )
{
continue;
}
// If none has the "type=default" attribute, use the first one
if ( firstScreenshot < 0 )
{
firstScreenshot = i;
}
// But type=default takes precedence.
if ( e.hasAttribute( "type" ) && e.attribute( "type" ) == "default" )
{
firstScreenshot = i;
break;
}
}
if ( firstScreenshot >= 0 )
{
return shotList.at( firstScreenshot ).firstChildElement( "image" ).text();
}
return QString();
}
/** @brief Returns language of the given element @p e
*
* Transforms the attribute value for xml:lang to something
* suitable for TranslatedString (e.g. [lang]).
*/
static inline QString
getLanguage( const QDomElement& e )
{
QString language = e.attribute( "xml:lang" );
if ( !language.isEmpty() )
{
language.replace( '-', '_' );
language.prepend( '[' );
language.append( ']' );
}
return language;
}
/** @brief Scan the list of @p children for @p tagname elements and add them to the map
*
* Uses @p mapname instead of @p tagname for the entries in map @p m
* to allow renaming from XML to map keys (in particular for
* TranslatedString). Also transforms xml:lang attributes to suitable
* key-decorations on @p mapname.
*/
static inline void
fillMap( QVariantMap& m, const QDomNodeList& children, const QString& tagname, const QString& mapname )
{
for ( int i = 0; i < children.count(); ++i )
{
if ( !children.at( i ).isElement() )
{
continue;
}
QDomElement e = children.at( i ).toElement();
if ( e.tagName() != tagname )
{
continue;
}
m[ mapname + getLanguage( e ) ] = e.text();
}
}
/** @brief gets the <name> and <description> elements
*
* Builds up a map of the <name> elements (which may have a *lang*
* attribute to indicate translations and paragraphs of the
* <description> element (also with lang). Uses the <summary>
* elements to supplement the description if no description
* is available for a given language.
*
* Returns a map with keys suitable for use by TranslatedString.
*/
static inline QVariantMap
getNameAndSummary( const QDomNode& n )
{
QVariantMap m;
const QDomNodeList children = n.childNodes();
fillMap( m, children, "name", "name" );
fillMap( m, children, "summary", "description" );
const QDomElement description = n.firstChildElement( "description" );
if ( !description.isNull() )
{
fillMap( m, description.childNodes(), "p", "description" );
}
return m;
}
#endif
PackageItem
PackageItem::fromAppData( const QVariantMap& item_map )
{
#ifdef HAVE_XML
QString fileName = CalamaresUtils::getString( item_map, "appdata" );
if ( fileName.isEmpty() )
{
cWarning() << "Can't load AppData without a suitable key.";
return PackageItem();
}
cDebug() << "Loading AppData XML from" << fileName;
QDomDocument doc = loadAppData( fileName );
if ( doc.isNull() )
{
return PackageItem();
}
QDomElement componentNode = doc.documentElement();
if ( !componentNode.isNull() && componentNode.tagName() == "component" )
{
// An "id" entry in the Calamares config overrides ID in the AppData
QString id = CalamaresUtils::getString( item_map, "id" );
if ( id.isEmpty() )
{
id = getChildText( componentNode, "id" );
}
if ( id.isEmpty() )
{
return PackageItem();
}
// A "screenshot" entry in the Calamares config overrides AppData
QString screenshotPath = CalamaresUtils::getString( item_map, "screenshot" );
if ( screenshotPath.isEmpty() )
{
screenshotPath = getScreenshotPath( componentNode );
}
QVariantMap map = getNameAndSummary( componentNode );
map.insert( "id", id );
map.insert( "screenshot", screenshotPath );
return PackageItem( map );
}
return PackageItem();
#else
cWarning() << "Loading AppData XML is not supported.";
return PackageItem();
#endif
}
PackageListModel::PackageListModel( QObject* parent ) PackageListModel::PackageListModel( QObject* parent )
: QAbstractListModel( parent ) : QAbstractListModel( parent )
@ -90,10 +323,14 @@ PackageListModel::~PackageListModel() {}
void void
PackageListModel::addPackage( PackageItem&& p ) PackageListModel::addPackage( PackageItem&& p )
{ {
int c = m_packages.count(); // Only add valid packages
beginInsertRows( QModelIndex(), c, c ); if ( p.isValid() )
m_packages.append( p ); {
endInsertRows(); int c = m_packages.count();
beginInsertRows( QModelIndex(), c, c );
m_packages.append( p );
endInsertRows();
}
} }
int int
@ -118,11 +355,11 @@ PackageListModel::data( const QModelIndex& index, int role ) const
if ( role == Qt::DisplayRole /* Also PackageNameRole */ ) if ( role == Qt::DisplayRole /* Also PackageNameRole */ )
{ {
return m_packages[ row ].name; return m_packages[ row ].name.get();
} }
else if ( role == DescriptionRole ) else if ( role == DescriptionRole )
{ {
return m_packages[ row ].description; return m_packages[ row ].description.get();
} }
else if ( role == ScreenshotRole ) else if ( role == ScreenshotRole )
{ {

View File

@ -19,6 +19,7 @@
#ifndef PACKAGEMODEL_H #ifndef PACKAGEMODEL_H
#define PACKAGEMODEL_H #define PACKAGEMODEL_H
#include "locale/TranslatableConfiguration.h"
#include "utils/NamedEnum.h" #include "utils/NamedEnum.h"
#include <QAbstractListModel> #include <QAbstractListModel>
@ -39,12 +40,10 @@ const NamedEnumTable< PackageChooserMode >& roleNames();
struct PackageItem struct PackageItem
{ {
QString id; QString id;
// TODO: may need more than one // FIXME: unused
QString package; QString package;
// TODO: name and description are localized CalamaresUtils::Locale::TranslatedString name;
QString name; CalamaresUtils::Locale::TranslatedString description;
QString description;
// TODO: may be more than one
QPixmap screenshot; QPixmap screenshot;
/// @brief Create blank PackageItem /// @brief Create blank PackageItem
@ -56,14 +55,44 @@ struct PackageItem
*/ */
PackageItem( const QString& id, const QString& package, const QString& name, const QString& description ); PackageItem( const QString& id, const QString& package, const QString& name, const QString& description );
/** @brief Creates a PackageItem from given strings.
*
* Set all the text members and load the screenshot from the given
* @p screenshotPath, which may be a QRC path (:/path/in/qrc) or
* a filesystem path, whatever QPixmap understands.
*/
PackageItem( const QString& id, PackageItem( const QString& id,
const QString& package, const QString& package,
const QString& name, const QString& name,
const QString& description, const QString& description,
const QString& screenshotPath ); const QString& screenshotPath );
// TODO: implement this /** @brief Creates a PackageItem from a QVariantMap
PackageItem fromAppStream( const QString& filename ); *
* This is intended for use when loading PackageItems from a
* configuration map. It will look up the various keys in the map
* and handle translation strings as well.
*/
PackageItem( const QVariantMap& map );
/** @brief Is this item valid?
*
* A valid item has an untranslated name available.
*/
bool isValid() const { return !name.isEmpty(); }
/** @brief Loads an AppData XML file and returns a PackageItem
*
* The @p map must have a key *appdata*. That is used as the
* primary source of information, but keys *id* and *screenshotPath*
* may be used to override parts of the AppData -- so that the
* ID is under the control of Calamares, and the screenshot can be
* forced to a local path available on the installation medium.
*
* Requires XML support in libcalamares, if not present will
* return invalid PackageItems.
*/
static PackageItem fromAppData( const QVariantMap& map );
}; };
using PackageList = QVector< PackageItem >; using PackageList = QVector< PackageItem >;
@ -75,6 +104,10 @@ public:
PackageListModel( QObject* parent ); PackageListModel( QObject* parent );
virtual ~PackageListModel() override; virtual ~PackageListModel() override;
/** @brief Add a package @p to the model
*
* Only valid packages are added -- that is, they must have a name.
*/
void addPackage( PackageItem&& p ); void addPackage( PackageItem&& p );
int rowCount( const QModelIndex& index ) const override; int rowCount( const QModelIndex& index ) const override;

View File

@ -18,9 +18,13 @@
#include "Tests.h" #include "Tests.h"
#include "PackageModel.h"
#include "utils/Logger.h"
#include <QtTest/QtTest> #include <QtTest/QtTest>
QTEST_GUILESS_MAIN( PackageChooserTests ) QTEST_MAIN( PackageChooserTests )
PackageChooserTests::PackageChooserTests() {} PackageChooserTests::PackageChooserTests() {}
@ -29,6 +33,7 @@ PackageChooserTests::~PackageChooserTests() {}
void void
PackageChooserTests::initTestCase() PackageChooserTests::initTestCase()
{ {
Logger::setupLogLevel( Logger::LOGDEBUG );
} }
void void
@ -36,3 +41,37 @@ PackageChooserTests::testBogus()
{ {
QVERIFY( true ); QVERIFY( true );
} }
void
PackageChooserTests::testAppData()
{
// Path from the build-dir
QString appdataName( "../io.calamares.calamares.appdata.xml" );
QVERIFY( QFile::exists( appdataName ) );
QVariantMap m;
m.insert( "appdata", appdataName );
PackageItem p1 = PackageItem::fromAppData( m );
#ifdef HAVE_XML
QVERIFY( p1.isValid() );
QCOMPARE( p1.id, "io.calamares.calamares.desktop" );
QCOMPARE( p1.name.get(), "Calamares" );
// The <description> entry has precedence
QCOMPARE( p1.description.get(), "Calamares is an installer program for Linux distributions." );
// .. but en_GB doesn't have an entry in description, so uses <summary>
QCOMPARE( p1.description.get( QLocale( "en_GB" ) ), "Calamares Linux Installer" );
QCOMPARE( p1.description.get( QLocale( "nl" ) ), "Calamares is een installatieprogramma voor Linux distributies." );
QVERIFY( p1.screenshot.isNull() );
m.insert( "id", "calamares" );
m.insert( "screenshot", ":/images/calamares.png" );
PackageItem p2= PackageItem::fromAppData( m );
QVERIFY( p2.isValid() );
QCOMPARE( p2.id, "calamares" );
QCOMPARE( p2.description.get( QLocale( "nl" ) ), "Calamares is een installatieprogramma voor Linux distributies." );
QVERIFY( !p2.screenshot.isNull() );
#else
QVERIFY( !p1.isValid() );
#endif
}

View File

@ -31,6 +31,7 @@ public:
private Q_SLOTS: private Q_SLOTS:
void initTestCase(); void initTestCase();
void testBogus(); void testBogus();
void testAppData();
}; };
#endif #endif

View File

@ -19,3 +19,61 @@
# or "optionalmultiple", "requiredmultiple" (for zero-or-more # or "optionalmultiple", "requiredmultiple" (for zero-or-more
# or one-or-more). # or one-or-more).
mode: required mode: required
# Items to display in the chooser. In general, this should be a
# pretty short list to avoid overwhelming the UI. This is a list
# of objects, and the items are displayed in list order.
#
# Either provide the data for an item in the list (using the keys
# below), or use existing AppData XML files as a source for the data.
#
# For data provided by the list: the item has an id, which is used in
# setting the value of *packagechooser_<module-id>*). The following fields
# are mandatory:
#
# - *id* ID for the product. The ID "" is special, and is used for
# "no package selected". Only include this if the mode allows
# selecting none.
# - *package* Package name for the product. While mandatory, this is
# not actually used anywhere.
# - *name* Human-readable name of the product. To provide translations,
# add a *[lang]* decoration as part of the key name, e.g. `name[nl]`
# for Dutch. The list of usable languages can be found in
# `CMakeLists.txt` or as part of the debug output of Calamares.
# - *description* Human-readable description. These can be translated
# as well.
# - *screenshot* Path to a single screenshot of the product. May be
# a filesystem path or a QRC path (e.g. ":/images/no-selection.png").
#
# Use the empty string "" as ID / key for the "no selection" item if
# you want to customize the display of that item as well.
#
# For data provided by AppData XML: the item has an *appdata*
# key which points to an AppData XML file in the local filesystem.
# This file is parsed to provide the id (from AppData id), name
# (from AppData name), description (from AppData description paragraphs
# or the summary entries), and a screenshot (the defautl screenshot
# from AppData). No package is set (but that is unused anyway).
#
# AppData may contain IDs that are not useful inside Calamares,
# and the screenshot URL may be remote -- a remote URL will not
# be loaded and the screenshot will be missing. An item with *appdata*
# **may** specify an ID or screenshot path, as above. This will override
# the settings from AppData.
items:
- id: ""
package: ""
name: "No Office Suite"
description: "Please pick an office suite from the list. If you don't want to install an office suite, that's fine, you can install one later as needed."
screenshot: ":/images/choose-office.jpg"
- id: libreoffice-still
package: libreoffice-still
name: LibreOffice
description: "LibreOffice is a powerful and free office suite, used by millions of people around the world. Its clean interface and feature-rich tools help you unleash your creativity and enhance your productivity."
screenshot: ":/images/LibreOffice.jpg"
- id: freeoffice
package: freeoffice
name: FreeOffice
description: "FreeOffice 2018 is a full-featured Office suite with word processing, spreadsheet and presentation software. It is seamlessly compatible with Microsoft Office. (Note: You need to register the product for free longterm usage)
screenshot: ":/images/FreeOffice.jpg"

View File

@ -1,7 +1,8 @@
<RCC> <RCC>
<qresource prefix="/"> <qresource prefix="/">
<file>images/choose-office.jpg</file> <file>images/no-selection.png</file>
<file>images/LibreOffice.jpg</file> <file>images/kde.png</file>
<file>images/FreeOffice.jpg</file> <file>images/gnome.png</file>
<file>images/calamares.png</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@ -39,9 +39,6 @@
<property name="text"> <property name="text">
<string>TextLabel</string> <string>TextLabel</string>
</property> </property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget> </widget>
</item> </item>
<item> <item>
@ -49,9 +46,6 @@
<property name="text"> <property name="text">
<string>TextLabel</string> <string>TextLabel</string>
</property> </property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget> </widget>
</item> </item>
<item> <item>
@ -59,9 +53,6 @@
<property name="text"> <property name="text">
<string>TextLabel</string> <string>TextLabel</string>
</property> </property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap"> <property name="wordWrap">
<bool>true</bool> <bool>true</bool>
</property> </property>

View File

@ -1,6 +1,7 @@
/* === This file is part of Calamares - <https://github.com/calamares> === /* === This file is part of Calamares - <https://github.com/calamares> ===
* *
* Copyright 2019, Adriaan de Groot <groot@kde.org> * Copyright 2019, Adriaan de Groot <groot@kde.org>
* Copyright 2019, Philip MÜller <philm@manjaro.org>
* *
* Calamares is free software: you can redistribute it and/or modify * Calamares is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -30,10 +31,10 @@ PackageChooserPage::PackageChooserPage( PackageChooserMode mode, QWidget* parent
, ui( new Ui::PackageChooserPage ) , ui( new Ui::PackageChooserPage )
, m_introduction( QString(), , m_introduction( QString(),
QString(), QString(),
tr( "Package Selection" ), tr( "Office Suite" ),
tr( "Please pick a product from the list. The selected product will be installed." ) ) tr( "Please pick an office suite from the list. The selected product will be installed." ) )
{ {
m_introduction.screenshot = QPixmap( QStringLiteral( ":/images/no-selection.png" ) ); m_introduction.screenshot = QPixmap( QStringLiteral( ":/images/choose-office.jpg" ) );
ui->setupUi( this ); ui->setupUi( this );
CALAMARES_RETRANSLATE( updateLabels(); ) CALAMARES_RETRANSLATE( updateLabels(); )

View File

@ -1,6 +1,7 @@
/* === This file is part of Calamares - <https://github.com/calamares> === /* === This file is part of Calamares - <https://github.com/calamares> ===
* *
* Copyright 2019, Adriaan de Groot <groot@kde.org> * Copyright 2019, Adriaan de Groot <groot@kde.org>
* Copyright 2019, Philip MÜller <philm@manjaro.org>
* *
* Calamares is free software: you can redistribute it and/or modify * Calamares is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -76,7 +77,7 @@ PackageChooserViewStep::widget()
} }
else else
{ {
cWarning() << "PackageChooser Widget created before model."; cWarning() << "OfficeChooser Widget created before model.";
} }
} }
return m_widget; return m_widget;
@ -189,16 +190,24 @@ PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap
m_model = new PackageListModel( nullptr ); m_model = new PackageListModel( nullptr );
m_model->addPackage( PackageItem { QString(), m_model->addPackage( PackageItem { QString(),
QString(), QString(),
"No Desktop", "No Office Suite",
"Please pick a desktop environment from the list. " "Please pick an office suite from the list. "
"If you don't want to install a desktop, that's fine, " "If you don't want to install an office suite, that's fine, "
"your system will start up in text-only mode and you can " "you can install one later as needed.",
"install a desktop environment later.", ":/images/choose-office.jpg" } );
":/images/no-selection.png" } ); m_model->addPackage( PackageItem { "libreoffice-still",
m_model->addPackage( PackageItem { "kde", "kde", "Plasma", "Plasma Desktop", ":/images/kde.png" } ); "libreoffice-still",
m_model->addPackage( PackageItem { "LibreOffice",
"gnome", "gnome", "GNOME", "GNU Networked Object Modeling Environment Desktop", ":/images/gnome.png" } ); "LibreOffice is a powerful and free office suite, used by millions of people around the world. "
} "Its clean interface and feature-rich tools help you unleash your creativity and enhance your productivity.",
":/images/LibreOffice.jpg" } );
m_model->addPackage( PackageItem { "freeoffice",
"freeoffice",
"FreeOffice",
"FreeOffice 2018 is a full-featured Office suite with word processing, "
"spreadsheet and presentation software. It is seamlessly compatible with Microsoft Office. "
"(Note: You need to register the product for free longterm usage)",
":/images/FreeOffice.jpg" } );
if ( first_time && m_widget && m_model ) if ( first_time && m_widget && m_model )
{ {

View File

@ -1,8 +1,7 @@
<RCC> <RCC>
<qresource prefix="/"> <qresource prefix="/">
<file>images/no-selection.png</file> <file>images/choose-office.jpg</file>
<file>images/kde.png</file> <file>images/LibreOffice.jpg</file>
<file>images/gnome.png</file> <file>images/FreeOffice.jpg</file>
<file>images/calamares.png</file>
</qresource> </qresource>
</RCC> </RCC>