Commit af4a7086 authored by Philip Müller's avatar Philip Müller

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

parents b88e5589 463435db
......@@ -7,6 +7,16 @@ charset = utf-8
end_of_line = lf
trim_trailing_whitespace = true
[CMakeLists.txt]
indent_style = space
indent_size = 4
insert_final_newline = true
[*.cmake]
indent_style = space
indent_size = 4
insert_final_newline = true
[*.{py,cpp,h}]
indent_style = space
indent_size = 4
......
......@@ -6,6 +6,7 @@ website will have to do for older versions.
# 3.2.21 (unreleased) #
This release contains contributions from (alphabetically by first name):
- Anke Boersma
- Camilo Higuita
- Gabriel Craciunescu
- Gaël PORTAY
......@@ -25,6 +26,11 @@ This release contains contributions from (alphabetically by first name):
more configurable: the branding key *sidebar* controls it. The sidebar
can be shown as a widget (default, as it has been), hidden, or use a
new QML view which is more easily customised.
- A new `settings.conf` key *quit-at-end* will automatically close
Calamares (by clicking on the *Done* button) when the end of the
sequence is reached. If *finished* is the last module in the sequence,
this will run whatever it is configured for; you can also leave out
the finished page and Calamares will close after the exec parts.
## Modules ##
- *packages* now reports more details in the installation progress-bar.
......
......@@ -181,3 +181,11 @@ disable-cancel: false
#
# YAML: boolean.
disable-cancel-during-exec: false
# If this is set to true, then once the end of the sequence has
# been reached, the quit (done) button is clicked automatically
# and Calamares will close. Default is false: the user will see
# that the end of installation has been reached, and that things are ok.
#
#
quit-at-end: false
......@@ -6,26 +6,72 @@ In principle, all parts can be styled through CSS.
Missing parts should be filed as issues.
The IDs are based on the object names in the C++ code.
You can use the Debug Dialog to find out object names:
- Open the debug dialog
- Choose tab *Tools*
- Click *Widget Tree* button
The list of object names is printed in the log.
Documentation for styling Qt Widgets through a stylesheet
can be found at
https://doc.qt.io/qt-5/stylesheet-examples.html
https://doc.qt.io/qt-5/stylesheet-reference.html
In Calamares, styling widget classes is supported (e.g.
using `QComboBox` as a selector). You can also use specific
object names (ids), which you can find through debugging tools.
using `QComboBox` as a selector).
This example stylesheet has all the actual styling commented out.
The examples are not exhaustive.
*/
/* Main application window.
/*** Generic Widgets.
*
* You can style **all** widgets of a given class by selecting
* the class name. Some widgets have specialized sub-selectors.
*/
/*
QPushButton { background-color: green; }
*/
/*** Main application window.
*
* The main application window has the sidebar, which in turn
* contains a logo and a list of items -- note that the list
* can **not** be styled, since it has its own custom C++
* delegate code.
*/
/*
#mainApp { }
#logoApp { }
#sidebarApp { }
#sidebarMenuApp { }
#logoApp { }
*/
/* Partitioning module.
/*** Welcome module.
*
* There are plenty of parts, but the buttons are the most interesting
* ones (donate, release notes, ...). The little icon image can be
* styled through *qproperty-icon*, which is a little obscure.
* URLs can reference the QRC paths of the Calamares application
* or loaded via plugins or within the filesystem. There is no
* comprehensive list of available icons, though.
*/
/*
QPushButton#aboutButton { qproperty-icon: url(:/data/images/release.svg); }
#donateButton,
#supportButton,
#releaseNotesButton,
#knownIssuesButton { qproperty-icon: url(:/data/images/help.svg); }
*/
/*** Partitioning module.
*
* Many moving parts, which you will need to experiment with.
*/
/*
#bootInfoIcon { }
#bootInfoLable { }
#deviceInfoIcon { }
......@@ -34,8 +80,13 @@ object names (ids), which you can find through debugging tools.
#partitionBarView { }
*/
/* Licensing module.
/*** Licensing module.
*
* The licensing module paints individual widgets for each of
* the licenses. The item can be collapsed or expanded.
*/
/*
#licenseItem { }
#licenseItemFullText { }
*/
......@@ -83,7 +83,7 @@ CalamaresApplication::init()
initQmlPath();
initBranding();
CalamaresUtils::installTranslator( QLocale::system(), QString(), this );
CalamaresUtils::installTranslator( QLocale::system(), QString() );
setQuitOnLastWindowClosed( false );
setWindowIcon( QIcon( Calamares::Branding::instance()->imagePath( Calamares::Branding::ProductIcon ) ) );
......
......@@ -69,6 +69,7 @@ public:
if ( anyFailed && !job->isEmergency() )
{
cDebug() << "Skipping non-emergency job" << job->prettyName();
++m_jobIndex;
continue;
}
......@@ -83,10 +84,8 @@ public:
message = result.message();
details = result.details();
}
if ( !anyFailed )
{
++m_jobIndex;
}
emitProgress( 1.0 );
++m_jobIndex;
}
if ( anyFailed )
{
......@@ -141,7 +140,7 @@ private:
m_queue, "failed", Qt::QueuedConnection, Q_ARG( QString, message ), Q_ARG( QString, details ) );
}
void emitFinished() { QMetaObject::invokeMethod( m_queue, "finished", Qt::QueuedConnection ); }
void emitFinished() { QMetaObject::invokeMethod( m_queue, "finish", Qt::QueuedConnection ); }
};
JobThread::~JobThread() {}
......@@ -196,6 +195,7 @@ JobQueue::start()
Q_ASSERT( !m_thread->isRunning() );
m_thread->setJobs( std::move( m_jobs ) );
m_jobs.clear();
m_finished = false;
m_thread->start();
}
......@@ -217,4 +217,11 @@ JobQueue::enqueue( const JobList& jobs )
emit queueChanged( m_jobs );
}
void
JobQueue::finish()
{
m_finished = true;
emit finished();
}
} // namespace Calamares
......@@ -45,6 +45,11 @@ public:
void enqueue( const JobList& jobs );
void start();
bool isRunning() const { return !m_finished; }
public slots:
void finish();
signals:
void queueChanged( const JobList& jobs );
void progress( qreal percent, const QString& prettyName );
......@@ -57,6 +62,7 @@ private:
JobList m_jobs;
JobThread* m_thread;
GlobalStorage* m_storage;
bool m_finished = true; ///< Initially, not running
};
} // namespace Calamares
......
......@@ -232,6 +232,7 @@ Settings::Settings( const QString& settingsFilePath, bool debugMode )
m_isSetupMode = requireBool( config, "oem-setup", !m_doChroot );
m_disableCancel = requireBool( config, "disable-cancel", false );
m_disableCancelDuringExec = requireBool( config, "disable-cancel-during-exec", false );
m_quitAtEnd = requireBool( config, "quit-at-end", false );
}
catch ( YAML::Exception& e )
{
......
......@@ -101,6 +101,9 @@ public:
/** @brief Temporary setting of disable-cancel: can't cancel during exec. */
bool disableCancelDuringExec() const { return m_disableCancelDuringExec; }
/** @brief Is quit-at-end set? (Quit automatically when done) */
bool quitAtEnd() const { return m_quitAtEnd; }
private:
static Settings* s_instance;
......@@ -117,6 +120,7 @@ private:
bool m_promptInstall;
bool m_disableCancel;
bool m_disableCancelDuringExec;
bool m_quitAtEnd;
};
} // namespace Calamares
......
......@@ -33,9 +33,7 @@ Label::Label( const QString& locale, LabelFormat format, QObject* parent )
: QObject( parent )
, m_locale( Label::getLocale( locale ) )
, m_localeId( locale.isEmpty() ? m_locale.name() : locale )
{
//: language[name] (country[name])
QString longFormat = QObject::tr( "%1 (%2)" );
QString languageName = m_locale.nativeLanguageName();
......
......@@ -40,10 +40,6 @@ class Label : public QObject
{
Q_OBJECT
Q_PROPERTY( QString label READ label CONSTANT FINAL )
Q_PROPERTY( QString englishLabel READ englishLabel CONSTANT FINAL )
Q_PROPERTY( QString localeId MEMBER m_localeId CONSTANT FINAL )
public:
/** @brief Formatting option for label -- add (country) to label. */
enum class LabelFormat
......@@ -65,6 +61,7 @@ public:
LabelFormat format = LabelFormat::IfNeededWithCountry,
QObject* parent = nullptr );
/** @brief Define a sorting order.
*
* Locales are sorted by their id, which means the ISO 2-letter code + country.
......
......@@ -239,7 +239,13 @@ CStringListModel::CStringListModel( CStringPairList l )
{
}
CStringListModel::~CStringListModel() {}
void
CStringListModel::setList( CalamaresUtils::Locale::CStringPairList l )
{
beginResetModel();
m_list = l;
endResetModel();
}
int
CStringListModel::rowCount( const QModelIndex& ) const
......@@ -264,6 +270,30 @@ CStringListModel::data( const QModelIndex& index, int role ) const
return item ? ( role == Qt::DisplayRole ? item->tr() : item->key() ) : QVariant();
}
void
CStringListModel::setCurrentIndex( int index )
{
if ( ( index < 0 ) || ( index >= m_list.count() ) )
{
return;
}
m_currentIndex = index;
emit currentIndexChanged();
}
int
CStringListModel::currentIndex() const
{
return m_currentIndex;
}
QHash< int, QByteArray >
CStringListModel::roleNames() const
{
return { { Qt::DisplayRole, "label" }, { Qt::UserRole, "key" } };
}
const CStringPair*
CStringListModel::item( int index ) const
{
......
......@@ -44,8 +44,9 @@ namespace Locale
* QPair<QString, QString> because there is API that needs
* C-style strings.
*/
class CStringPair
class CStringPair : public QObject
{
Q_OBJECT
public:
/// @brief An empty pair
CStringPair() {}
......@@ -86,6 +87,7 @@ public:
/// @brief A pair of strings for timezone regions (e.g. "America")
class TZRegion : public CStringPair
{
Q_OBJECT
public:
using CStringPair::CStringPair;
virtual ~TZRegion() override;
......@@ -117,6 +119,7 @@ private:
/// @brief A pair of strings for specific timezone names (e.g. "New_York")
class TZZone : public CStringPair
{
Q_OBJECT
public:
using CStringPair::CStringPair;
QString tr() const override;
......@@ -137,21 +140,52 @@ protected:
class CStringListModel : public QAbstractListModel
{
Q_OBJECT
Q_PROPERTY( int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged )
public:
/// @brief Create empty model
CStringListModel();
CStringListModel() {}
/// @brief Create model from list (non-owning)
CStringListModel( CStringPairList );
virtual ~CStringListModel() override;
int rowCount( const QModelIndex& parent ) const override;
QVariant data( const QModelIndex& index, int role ) const override;
const CStringPair* item( int index ) const;
QHash< int, QByteArray > roleNames() const override;
void setCurrentIndex( int index );
int currentIndex() const;
void setList( CStringPairList );
inline int indexOf( const QString& key )
{
const auto it = std::find_if(
m_list.constBegin(), m_list.constEnd(), [&]( const CalamaresUtils::Locale::CStringPair* item ) -> bool {
return item->key() == key;
} );
if ( it != m_list.constEnd() )
{
// distance() is usually a long long
return int( std::distance( m_list.constBegin(), it ) );
}
else
{
return -1;
}
}
private:
CStringPairList m_list;
int m_currentIndex = -1;
signals:
void currentIndexChanged();
};
} // namespace Locale
......
......@@ -276,7 +276,7 @@ Manager::synchronousGet( const QUrl& url, const RequestOptions& options )
}
QNetworkReply*
Manager::asynchronouseGet( const QUrl& url, const CalamaresUtils::Network::RequestOptions& options )
Manager::asynchronousGet( const QUrl& url, const CalamaresUtils::Network::RequestOptions& options )
{
return asynchronousRun( d->nam(), url, options );
}
......
......@@ -146,7 +146,7 @@ public:
* This may be a nullptr if an error occurs immediately.
* The caller is responsible for cleaning up the reply (eventually).
*/
QNetworkReply* asynchronouseGet( const QUrl& url, const RequestOptions& options = RequestOptions() );
QNetworkReply* asynchronousGet( const QUrl& url, const RequestOptions& options = RequestOptions() );
private:
class Private;
......
......@@ -197,7 +197,7 @@ static QTranslator* s_tztranslator = nullptr;
static QString s_translatorLocaleName;
void
installTranslator( const QLocale& locale, const QString& brandingTranslationsPrefix, QObject* )
installTranslator( const QLocale& locale, const QString& brandingTranslationsPrefix )
{
loadSingletonTranslator( BrandingLoader( locale, brandingTranslationsPrefix ), s_brandingTranslator );
loadSingletonTranslator( TZLoader( locale ), s_tztranslator );
......
......@@ -36,9 +36,8 @@ namespace CalamaresUtils
* @brief installTranslator changes the application language.
* @param locale the new locale.
* @param brandingTranslationsPrefix the branding path prefix, from Calamares::Branding.
* @param parent the parent QObject.
*/
DLLEXPORT void installTranslator( const QLocale& locale, const QString& brandingTranslationsPrefix, QObject* parent );
DLLEXPORT void installTranslator( const QLocale& locale, const QString& brandingTranslationsPrefix );
DLLEXPORT QString translatorLocaleName();
......
......@@ -29,8 +29,8 @@
#include "utils/Paste.h"
#include "utils/Retranslator.h"
#include "viewpages/BlankViewStep.h"
#include "viewpages/ViewStep.h"
#include "viewpages/ExecutionViewStep.h"
#include "viewpages/ViewStep.h"
#include <QApplication>
#include <QBoxLayout>
......@@ -309,6 +309,13 @@ stepIsExecute( const ViewStepList& steps, int index )
&& ( qobject_cast< ExecutionViewStep* >( steps.at( index ) ) != nullptr );
}
static inline bool
isAtVeryEnd( const ViewStepList& steps, int index )
{
return ( index >= steps.count() ) || ( index == steps.count() - 1 && steps.last()->isAtEnd() );
}
void
ViewManager::next()
{
......@@ -412,13 +419,17 @@ ViewManager::updateButtonLabels()
m_back->setText( tr( "&Back" ) );
// Cancel button changes label at the end
if ( isAtVeryEnd() )
if ( isAtVeryEnd( m_steps, m_currentStep ) )
{
m_quit->setText( tr( "&Done" ) );
m_quit->setToolTip( quitOnCompleteTooltip );
m_quit->setVisible( true ); // At end, always visible and enabled.
setButtonIcon( m_quit, "dialog-ok-apply" );
updateCancelEnabled( true );
if ( settings->quitAtEnd() )
{
m_quit->click();
}
}
else
{
......@@ -473,7 +484,7 @@ ViewManager::confirmCancelInstallation()
const auto* const settings = Calamares::Settings::instance();
// When we're at the very end, then it's always OK to exit.
if ( isAtVeryEnd() )
if ( isAtVeryEnd( m_steps, m_currentStep ) )
{
return true;
}
......
......@@ -132,12 +132,6 @@ private:
void updateButtonLabels();
void updateCancelEnabled( bool enabled );
bool isAtVeryEnd() const
{
return ( m_currentStep >= m_steps.count() )
|| ( m_currentStep == m_steps.count() - 1 && m_steps.last()->isAtEnd() );
}
static ViewManager* s_instance;
ViewStepList m_steps;
......
......@@ -136,7 +136,7 @@ ExecutionViewStep::isAtBeginning() const
bool
ExecutionViewStep::isAtEnd() const
{
return true;
return !JobQueue::instance()->isRunning();
}
void
......
......@@ -102,7 +102,7 @@ def run():
status = _("Dummy python step {}").format(str(c) + ":" + repr(k))
libcalamares.utils.debug(_("Dummy python step {}").format(str(k)))
sleep(1)
libcalamares.job.setprogress(c * 1.0 / len(configlist))
libcalamares.job.setprogress(c * 1.0 / (len(configlist)+1))
c += 1
sleep(3)
......
......@@ -18,12 +18,12 @@
#include "KeyboardViewStep.h"
#include "JobQueue.h"
#include "GlobalStorage.h"
#include "KeyboardPage.h"
CALAMARES_PLUGIN_FACTORY_DEFINITION( KeyboardViewStepFactory, registerPlugin<KeyboardViewStep>(); )
#include "GlobalStorage.h"
#include "JobQueue.h"
CALAMARES_PLUGIN_FACTORY_DEFINITION( KeyboardViewStepFactory, registerPlugin< KeyboardViewStep >(); )
KeyboardViewStep::KeyboardViewStep( QObject* parent )
: Calamares::ViewStep( parent )
......@@ -40,7 +40,9 @@ KeyboardViewStep::KeyboardViewStep( QObject* parent )
KeyboardViewStep::~KeyboardViewStep()
{
if ( m_widget && m_widget->parent() == nullptr )
{
m_widget->deleteLater();
}
}
......@@ -111,9 +113,7 @@ void
KeyboardViewStep::onLeave()
{
m_widget->finalize();
m_jobs = m_widget->createJobs( m_xOrgConfFileName,
m_convertedKeymapPath,
m_writeEtcDefaultKeyboard );
m_jobs = m_widget->createJobs( m_xOrgConfFileName, m_convertedKeymapPath, m_writeEtcDefaultKeyboard );
m_prettyStatus = m_widget->prettyStatus();
}
......@@ -121,29 +121,35 @@ KeyboardViewStep::onLeave()
void
KeyboardViewStep::setConfigurationMap( const QVariantMap& configurationMap )
{
if ( configurationMap.contains( "xOrgConfFileName" ) &&
configurationMap.value( "xOrgConfFileName" ).type() == QVariant::String &&
!configurationMap.value( "xOrgConfFileName" ).toString().isEmpty() )
if ( configurationMap.contains( "xOrgConfFileName" )
&& configurationMap.value( "xOrgConfFileName" ).type() == QVariant::String
&& !configurationMap.value( "xOrgConfFileName" ).toString().isEmpty() )
{
m_xOrgConfFileName = configurationMap.value( "xOrgConfFileName" )
.toString();
m_xOrgConfFileName = configurationMap.value( "xOrgConfFileName" ).toString();
}
else
{
m_xOrgConfFileName = "00-keyboard.conf";
}
if ( configurationMap.contains( "convertedKeymapPath" ) &&
configurationMap.value( "convertedKeymapPath" ).type() == QVariant::String &&
!configurationMap.value( "convertedKeymapPath" ).toString().isEmpty() )
if ( configurationMap.contains( "convertedKeymapPath" )
&& configurationMap.value( "convertedKeymapPath" ).type() == QVariant::String
&& !configurationMap.value( "convertedKeymapPath" ).toString().isEmpty() )
{
m_convertedKeymapPath = configurationMap.value( "convertedKeymapPath" )
.toString();
m_convertedKeymapPath = configurationMap.value( "convertedKeymapPath" ).toString();
}
else
{
m_convertedKeymapPath = QString();
}
if ( configurationMap.contains( "writeEtcDefaultKeyboard" ) &&
configurationMap.value( "writeEtcDefaultKeyboard" ).type() == QVariant::Bool )
if ( configurationMap.contains( "writeEtcDefaultKeyboard" )
&& configurationMap.value( "writeEtcDefaultKeyboard" ).type() == QVariant::Bool )
{
m_writeEtcDefaultKeyboard = configurationMap.value( "writeEtcDefaultKeyboard" ).toBool();
}
else
{
m_writeEtcDefaultKeyboard = true;
}
}
......@@ -20,12 +20,11 @@
#ifndef KEYBOARDVIEWSTEP_H
#define KEYBOARDVIEWSTEP_H
#include <QObject>
#include "DllMacro.h"
#include "utils/PluginFactory.h"
#include "viewpages/ViewStep.h"
#include "DllMacro.h"
#include <QObject>
class KeyboardPage;
......@@ -48,7 +47,7 @@ public:
bool isAtBeginning() const override;
bool isAtEnd() const override;
QList< Calamares::job_ptr > jobs() const override;
Calamares::JobList jobs() const override;
void onActivate() override;
void onLeave() override;
......@@ -64,9 +63,9 @@ private:
QString m_convertedKeymapPath;
bool m_writeEtcDefaultKeyboard;
QList< Calamares::job_ptr > m_jobs;
Calamares::JobList m_jobs;
};
CALAMARES_PLUGIN_FACTORY_DECLARATION( KeyboardViewStepFactory )
#endif // KEYBOARDVIEWSTEP_H
#endif // KEYBOARDVIEWSTEP_H
......@@ -13,6 +13,7 @@ calamares_add_plugin( locale
EXPORT_MACRO PLUGINDLLEXPORT_PRO
SOURCES
${geoip_src}
Config.cpp
LCLocaleDialog.cpp
LocaleConfiguration.cpp
LocalePage.cpp
......
This diff is collapsed.
/* === This file is part of Calamares - <https://github.com/calamares> ===
*
* Copyright 2019-2020, Adriaan de Groot <groot@kde.org>
* Copyright 2020, Camilo Higuita <milo.h@aol.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef LOCALE_CONFIG_H
#define LOCALE_CONFIG_H
#include "LocaleConfiguration.h"
#include "timezonewidget/localeglobal.h"
#include "Job.h"
#include "locale/TimeZone.h"
#include <QAbstractListModel>
#include <QObject>
#include <memory>
class Config : public QObject
{
Q_OBJECT
Q_PROPERTY( CalamaresUtils::Locale::CStringListModel* zonesModel READ zonesModel CONSTANT FINAL )
Q_PROPERTY( CalamaresUtils::Locale::CStringListModel* regionModel READ regionModel CONSTANT FINAL )
Q_PROPERTY( QString prettyStatus READ prettyStatus NOTIFY prettyStatusChanged FINAL )
public:
Config( QObject* parent = nullptr );
~Config();
CalamaresUtils::Locale::CStringListModel* regionModel() const;
CalamaresUtils::Locale::CStringListModel* zonesModel() const;