add the localq module and config to locale
This commit is contained in:
parent
1eec1a9fe7
commit
8ff1996e12
@ -13,6 +13,7 @@ calamares_add_plugin( locale
|
||||
EXPORT_MACRO PLUGINDLLEXPORT_PRO
|
||||
SOURCES
|
||||
${geoip_src}
|
||||
Config.cpp
|
||||
LCLocaleDialog.cpp
|
||||
LocaleConfiguration.cpp
|
||||
LocalePage.cpp
|
||||
|
314
src/modules/locale/Config.cpp
Normal file
314
src/modules/locale/Config.cpp
Normal file
@ -0,0 +1,314 @@
|
||||
/* === This file is part of Calamares - <https://github.com/calamares> ===
|
||||
*
|
||||
* Copyright 2019-2020, Adriaan de Groot <groot@kde.org>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QProcess>
|
||||
|
||||
#include "SetTimezoneJob.h"
|
||||
#include "timezonewidget/timezonewidget.h"
|
||||
|
||||
#include "GlobalStorage.h"
|
||||
#include "JobQueue.h"
|
||||
#include "LCLocaleDialog.h"
|
||||
#include "Settings.h"
|
||||
|
||||
#include "locale/Label.h"
|
||||
#include "locale/TimeZone.h"
|
||||
#include "utils/CalamaresUtilsGui.h"
|
||||
#include "utils/Logger.h"
|
||||
#include "utils/Retranslator.h"
|
||||
|
||||
Config::Config(QObject *parent) : QObject(parent)
|
||||
, m_regionList( CalamaresUtils::Locale::TZRegion::fromZoneTab() )
|
||||
, m_regionModel( new CalamaresUtils::Locale::CStringListModel ( m_regionList ) )
|
||||
, m_zonesModel( new CalamaresUtils::Locale::CStringListModel ( ) )
|
||||
, m_blockTzWidgetSet( false )
|
||||
{
|
||||
connect(m_regionModel, &CalamaresUtils::Locale::CStringListModel::currentIndexChanged, [&]()
|
||||
{
|
||||
m_zonesModel->setList(static_cast<const CalamaresUtils::Locale::TZRegion*>(m_regionModel->item(m_regionModel->currentIndex()))->zones());
|
||||
updateLocaleLabels();
|
||||
});
|
||||
|
||||
connect(m_zonesModel, &CalamaresUtils::Locale::CStringListModel::currentIndexChanged, [&]()
|
||||
{
|
||||
updateLocaleLabels();
|
||||
});
|
||||
}
|
||||
|
||||
Config::~Config()
|
||||
{
|
||||
qDeleteAll( m_regionList );
|
||||
}
|
||||
|
||||
CalamaresUtils::Locale::CStringListModel *
|
||||
Config::zonesModel() const
|
||||
{
|
||||
return m_zonesModel;
|
||||
}
|
||||
|
||||
CalamaresUtils::Locale::CStringListModel *
|
||||
Config::regionModel() const
|
||||
{
|
||||
return m_regionModel;
|
||||
}
|
||||
|
||||
void
|
||||
Config::setLocaleInfo(const QString& initialRegion, const QString& initialZone, const QString& localeGenPath)
|
||||
{
|
||||
using namespace CalamaresUtils::Locale;
|
||||
|
||||
cDebug()<< "REGION MODEL SIZE" << initialRegion << initialZone;
|
||||
auto* region = m_regionList.find< TZRegion >( initialRegion );
|
||||
if ( region && region->zones().find< TZZone >( initialZone ) )
|
||||
{
|
||||
this->m_regionModel->setCurrentIndex(m_regionModel->indexOf(initialRegion));
|
||||
m_zonesModel->setList(region->zones());
|
||||
this->m_zonesModel->setCurrentIndex(m_zonesModel->indexOf(initialZone));
|
||||
}
|
||||
else
|
||||
{
|
||||
this->m_regionModel->setCurrentIndex(m_regionModel->indexOf("America"));
|
||||
m_zonesModel->setList(static_cast<const TZRegion*>(m_regionModel->item(m_regionModel->currentIndex()))->zones());
|
||||
this->m_zonesModel->setCurrentIndex(m_zonesModel->indexOf("New_York"));
|
||||
|
||||
}
|
||||
|
||||
// Some distros come with a meaningfully commented and easy to parse locale.gen,
|
||||
// and others ship a separate file /usr/share/i18n/SUPPORTED with a clean list of
|
||||
// supported locales. We first try that one, and if it doesn't exist, we fall back
|
||||
// to parsing the lines from locale.gen
|
||||
m_localeGenLines.clear();
|
||||
QFile supported( "/usr/share/i18n/SUPPORTED" );
|
||||
QByteArray ba;
|
||||
|
||||
if ( supported.exists() && supported.open( QIODevice::ReadOnly | QIODevice::Text ) )
|
||||
{
|
||||
ba = supported.readAll();
|
||||
supported.close();
|
||||
|
||||
const auto lines = ba.split( '\n' );
|
||||
for ( const QByteArray& line : lines )
|
||||
{
|
||||
m_localeGenLines.append( QString::fromLatin1( line.simplified() ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QFile localeGen( localeGenPath );
|
||||
if ( localeGen.open( QIODevice::ReadOnly | QIODevice::Text ) )
|
||||
{
|
||||
ba = localeGen.readAll();
|
||||
localeGen.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
cWarning() << "Cannot open file" << localeGenPath
|
||||
<< ". Assuming the supported languages are already built into "
|
||||
"the locale archive.";
|
||||
QProcess localeA;
|
||||
localeA.start( "locale", QStringList() << "-a" );
|
||||
localeA.waitForFinished();
|
||||
ba = localeA.readAllStandardOutput();
|
||||
}
|
||||
const auto lines = ba.split( '\n' );
|
||||
for ( const QByteArray& line : lines )
|
||||
{
|
||||
if ( line.startsWith( "## " ) || line.startsWith( "# " ) || line.simplified() == "#" )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
QString lineString = QString::fromLatin1( line.simplified() );
|
||||
if ( lineString.startsWith( "#" ) )
|
||||
{
|
||||
lineString.remove( '#' );
|
||||
}
|
||||
lineString = lineString.simplified();
|
||||
|
||||
if ( lineString.isEmpty() )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
m_localeGenLines.append( lineString );
|
||||
}
|
||||
}
|
||||
|
||||
if ( m_localeGenLines.isEmpty() )
|
||||
{
|
||||
cWarning() << "cannot acquire a list of available locales."
|
||||
<< "The locale and localecfg modules will be broken as long as this "
|
||||
"system does not provide"
|
||||
<< "\n\t "
|
||||
<< "* a well-formed" << supported.fileName() << "\n\tOR"
|
||||
<< "* a well-formed"
|
||||
<< ( localeGenPath.isEmpty() ? QLatin1String( "/etc/locale.gen" ) : localeGenPath ) << "\n\tOR"
|
||||
<< "* a complete pre-compiled locale-gen database which allows complete locale -a output.";
|
||||
return; // something went wrong and there's nothing we can do about it.
|
||||
}
|
||||
|
||||
// Assuming we have a list of supported locales, we usually only want UTF-8 ones
|
||||
// because it's not 1995.
|
||||
for ( auto it = m_localeGenLines.begin(); it != m_localeGenLines.end(); )
|
||||
{
|
||||
if ( !it->contains( "UTF-8", Qt::CaseInsensitive ) && !it->contains( "utf8", Qt::CaseInsensitive ) )
|
||||
{
|
||||
it = m_localeGenLines.erase( it );
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
// We strip " UTF-8" from "en_US.UTF-8 UTF-8" because it's redundant redundant.
|
||||
for ( auto it = m_localeGenLines.begin(); it != m_localeGenLines.end(); ++it )
|
||||
{
|
||||
if ( it->endsWith( " UTF-8" ) )
|
||||
{
|
||||
it->chop( 6 );
|
||||
}
|
||||
*it = it->simplified();
|
||||
}
|
||||
updateGlobalStorage();
|
||||
updateLocaleLabels();
|
||||
}
|
||||
|
||||
void Config::updateGlobalLocale()
|
||||
{
|
||||
auto* gs = Calamares::JobQueue::instance()->globalStorage();
|
||||
const QString bcp47 = m_selectedLocaleConfiguration.toBcp47();
|
||||
gs->insert( "locale", bcp47 );
|
||||
}
|
||||
|
||||
void Config::updateGlobalStorage()
|
||||
{
|
||||
auto* gs = Calamares::JobQueue::instance()->globalStorage();
|
||||
|
||||
const auto* location = currentLocation();
|
||||
bool locationChanged = ( location->region() != gs->value( "locationRegion" ) )
|
||||
|| ( location->zone() != gs->value( "locationZone" ) );
|
||||
|
||||
gs->insert( "locationRegion", location->region() );
|
||||
gs->insert( "locationZone", location->zone() );
|
||||
|
||||
updateGlobalLocale();
|
||||
|
||||
// If we're in chroot mode (normal install mode), then we immediately set the
|
||||
// timezone on the live system. When debugging timezones, don't bother.
|
||||
#ifndef DEBUG_TIMEZONES
|
||||
if ( locationChanged && Calamares::Settings::instance()->doChroot() )
|
||||
{
|
||||
QProcess::execute( "timedatectl", // depends on systemd
|
||||
{ "set-timezone", location->region() + '/' + location->zone() } );
|
||||
}
|
||||
#endif
|
||||
|
||||
// Preserve those settings that have been made explicit.
|
||||
auto newLocale = guessLocaleConfiguration();
|
||||
if ( !m_selectedLocaleConfiguration.isEmpty() && m_selectedLocaleConfiguration.explicit_lang )
|
||||
{
|
||||
newLocale.setLanguage( m_selectedLocaleConfiguration.language() );
|
||||
}
|
||||
if ( !m_selectedLocaleConfiguration.isEmpty() && m_selectedLocaleConfiguration.explicit_lc )
|
||||
{
|
||||
newLocale.lc_numeric = m_selectedLocaleConfiguration.lc_numeric;
|
||||
newLocale.lc_time = m_selectedLocaleConfiguration.lc_time;
|
||||
newLocale.lc_monetary = m_selectedLocaleConfiguration.lc_monetary;
|
||||
newLocale.lc_paper = m_selectedLocaleConfiguration.lc_paper;
|
||||
newLocale.lc_name = m_selectedLocaleConfiguration.lc_name;
|
||||
newLocale.lc_address = m_selectedLocaleConfiguration.lc_address;
|
||||
newLocale.lc_telephone = m_selectedLocaleConfiguration.lc_telephone;
|
||||
newLocale.lc_measurement = m_selectedLocaleConfiguration.lc_measurement;
|
||||
newLocale.lc_identification = m_selectedLocaleConfiguration.lc_identification;
|
||||
}
|
||||
newLocale.explicit_lang = m_selectedLocaleConfiguration.explicit_lang;
|
||||
newLocale.explicit_lc = m_selectedLocaleConfiguration.explicit_lc;
|
||||
|
||||
m_selectedLocaleConfiguration = newLocale;
|
||||
updateLocaleLabels();
|
||||
}
|
||||
|
||||
void
|
||||
Config::updateLocaleLabels()
|
||||
{
|
||||
LocaleConfiguration lc
|
||||
= m_selectedLocaleConfiguration.isEmpty() ? guessLocaleConfiguration() : m_selectedLocaleConfiguration;
|
||||
auto labels = prettyLocaleStatus( lc );
|
||||
emit prettyStatusChanged();
|
||||
}
|
||||
|
||||
|
||||
std::pair<QString, QString>
|
||||
Config::prettyLocaleStatus(const LocaleConfiguration& lc) const
|
||||
{
|
||||
using CalamaresUtils::Locale::Label;
|
||||
|
||||
Label lang( lc.language(), Label::LabelFormat::AlwaysWithCountry );
|
||||
Label num( lc.lc_numeric, Label::LabelFormat::AlwaysWithCountry );
|
||||
|
||||
return std::make_pair< QString, QString >(
|
||||
tr( "The system language will be set to %1." ).arg( lang.label() ),
|
||||
tr( "The numbers and dates locale will be set to %1." ).arg( num.label() ) );
|
||||
}
|
||||
|
||||
Calamares::JobList Config::createJobs()
|
||||
{
|
||||
QList< Calamares::job_ptr > list;
|
||||
const CalamaresUtils::Locale::TZZone* location = currentLocation();
|
||||
|
||||
Calamares::Job* j = new SetTimezoneJob( location->region(), location->zone() );
|
||||
list.append( Calamares::job_ptr( j ) );
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
LocaleConfiguration Config::guessLocaleConfiguration() const
|
||||
{
|
||||
return LocaleConfiguration::fromLanguageAndLocation(
|
||||
QLocale().name(), m_localeGenLines, currentLocation() ? currentLocation()->country() : "" );
|
||||
}
|
||||
|
||||
QMap<QString, QString> Config::localesMap()
|
||||
{
|
||||
return m_selectedLocaleConfiguration.isEmpty() ? guessLocaleConfiguration().toMap()
|
||||
: m_selectedLocaleConfiguration.toMap();
|
||||
}
|
||||
|
||||
QString Config::prettyStatus() const
|
||||
{
|
||||
QString status;
|
||||
status += tr( "Set timezone to %1/%2.<br/>" ).arg( m_regionModel->item(m_regionModel->currentIndex())->tr() ).arg( m_zonesModel->item(m_zonesModel->currentIndex())->tr() );
|
||||
|
||||
LocaleConfiguration lc
|
||||
= m_selectedLocaleConfiguration.isEmpty() ? guessLocaleConfiguration() : m_selectedLocaleConfiguration;
|
||||
auto labels = prettyLocaleStatus( lc );
|
||||
status += labels.first + "<br/>";
|
||||
status += labels.second + "<br/>";
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
const CalamaresUtils::Locale::TZZone * Config::currentLocation() const
|
||||
{
|
||||
return static_cast<const CalamaresUtils::Locale::TZZone*>(m_zonesModel->item(m_zonesModel->currentIndex()));
|
||||
}
|
84
src/modules/locale/Config.h
Normal file
84
src/modules/locale/Config.h
Normal file
@ -0,0 +1,84 @@
|
||||
/* === This file is part of Calamares - <https://github.com/calamares> ===
|
||||
*
|
||||
* Copyright 2019-2020, Adriaan de Groot <groot@kde.org>
|
||||
*
|
||||
* 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 <QObject>
|
||||
#include <QUrl>
|
||||
#include <QAbstractListModel>
|
||||
#include "Job.h"
|
||||
#include "locale/TimeZone.h"
|
||||
#include "LocaleConfiguration.h"
|
||||
#include "timezonewidget/localeglobal.h"
|
||||
#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;
|
||||
|
||||
void setLocaleInfo(const QString& initialRegion, const QString& initialZone, const QString& localeGenPath);
|
||||
|
||||
Calamares::JobList createJobs();
|
||||
QMap< QString, QString > localesMap();
|
||||
QString prettyStatus() const;
|
||||
|
||||
private:
|
||||
CalamaresUtils::Locale::CStringPairList m_regionList;
|
||||
CalamaresUtils::Locale::CStringListModel * m_regionModel;
|
||||
CalamaresUtils::Locale::CStringListModel * m_zonesModel;
|
||||
|
||||
LocaleConfiguration m_selectedLocaleConfiguration;
|
||||
|
||||
QStringList m_localeGenLines;
|
||||
int m_currentRegion = -1;
|
||||
|
||||
bool m_blockTzWidgetSet;
|
||||
|
||||
LocaleConfiguration guessLocaleConfiguration() const;
|
||||
|
||||
// For the given locale config, return two strings describing
|
||||
// the settings for language and numbers.
|
||||
std::pair< QString, QString > prettyLocaleStatus( const LocaleConfiguration& ) const;
|
||||
|
||||
/** @brief Update the GS *locale* key with the selected system language.
|
||||
*
|
||||
* This uses whatever is set in m_selectedLocaleConfiguration as the language,
|
||||
* and writes it to GS *locale* key (as a string, in BCP47 format).
|
||||
*/
|
||||
void updateGlobalLocale();
|
||||
void updateGlobalStorage();
|
||||
void updateLocaleLabels();
|
||||
|
||||
const CalamaresUtils::Locale::TZZone* currentLocation() const;
|
||||
|
||||
signals:
|
||||
void prettyStatusChanged();
|
||||
};
|
||||
|
||||
|
||||
#endif
|
42
src/modules/localeq/CMakeLists.txt
Normal file
42
src/modules/localeq/CMakeLists.txt
Normal file
@ -0,0 +1,42 @@
|
||||
# When debugging the timezone widget, add this debugging definition
|
||||
# to have a debugging-friendly timezone widget, debug logging,
|
||||
# and no intrusive timezone-setting while clicking around.
|
||||
option( DEBUG_TIMEZONES "Debug-friendly timezone widget." OFF )
|
||||
if( DEBUG_TIMEZONES )
|
||||
add_definitions( -DDEBUG_TIMEZONES )
|
||||
endif()
|
||||
|
||||
set( _locale ${CMAKE_CURRENT_SOURCE_DIR}/../locale )
|
||||
|
||||
include_directories( ${PROJECT_BINARY_DIR}/src/libcalamaresui ${CMAKE_CURRENT_SOURCE_DIR}/../../libcalamares ${_locale} )
|
||||
|
||||
calamares_add_plugin( localeq
|
||||
TYPE viewmodule
|
||||
EXPORT_MACRO PLUGINDLLEXPORT_PRO
|
||||
SOURCES
|
||||
${geoip_src}
|
||||
LocaleQmlViewStep.cpp
|
||||
${_locale}/LocaleConfiguration.cpp
|
||||
${_locale}/Config.cpp
|
||||
${_locale}/SetTimezoneJob.cpp
|
||||
${_locale}/timezonewidget/localeglobal.cpp
|
||||
RESOURCES
|
||||
${_locale}/locale.qrc
|
||||
LINK_PRIVATE_LIBRARIES
|
||||
calamaresui
|
||||
Qt5::Network
|
||||
${geoip_libs}
|
||||
${YAMLCPP_LIBRARY}
|
||||
SHARED_LIB
|
||||
)
|
||||
|
||||
# add_executable( localeqmltest qmlmain.cpp Config.cpp LocaleQmlViewStep.cpp LocaleConfiguration.cpp timezonewidget/localeglobal.cpp SetTimezoneJob.cpp ${geoip_src} )
|
||||
# target_link_libraries( localeqmltest PRIVATE calamaresui Qt5::Core Qt5::Network Qt5::DBus ${geoip_libs})
|
||||
# set_target_properties( localeqmltest
|
||||
# PROPERTIES
|
||||
# ENABLE_EXPORTS TRUE
|
||||
# RUNTIME_OUTPUT_NAME localeqmltest
|
||||
# )
|
||||
# calamares_automoc( localeqmltest )
|
||||
# calamares_autouic( localeqmltest )
|
||||
|
203
src/modules/localeq/LocaleQmlViewStep.cpp
Normal file
203
src/modules/localeq/LocaleQmlViewStep.cpp
Normal file
@ -0,0 +1,203 @@
|
||||
/* === This file is part of Calamares - <https://github.com/calamares> ===
|
||||
*
|
||||
* Copyright 2014-2015, Teo Mrnjavac <teo@kde.org>
|
||||
* Copyright 2018,2020 Adriaan de Groot <groot@kde.org>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#include "LocaleQmlViewStep.h"
|
||||
|
||||
#include "GlobalStorage.h"
|
||||
#include "JobQueue.h"
|
||||
|
||||
#include "geoip/Handler.h"
|
||||
#include "network/Manager.h"
|
||||
#include "utils/CalamaresUtilsGui.h"
|
||||
#include "utils/Logger.h"
|
||||
#include "utils/Variant.h"
|
||||
#include "utils/Yaml.h"
|
||||
|
||||
#include "timezonewidget/localeglobal.h"
|
||||
|
||||
#include "Branding.h"
|
||||
#include "modulesystem/ModuleManager.h"
|
||||
#include <QQmlEngine>
|
||||
#include <QFutureWatcher>
|
||||
#include <QPixmap>
|
||||
#include <QVariant>
|
||||
|
||||
CALAMARES_PLUGIN_FACTORY_DEFINITION( LocaleQmlViewStepFactory, registerPlugin< LocaleQmlViewStep >(); )
|
||||
|
||||
LocaleQmlViewStep::LocaleQmlViewStep( QObject* parent )
|
||||
: Calamares::QmlViewStep( parent )
|
||||
, m_config( new Config( this ) )
|
||||
, m_nextEnabled( false )
|
||||
, m_geoip( nullptr )
|
||||
{
|
||||
emit nextStatusChanged( m_nextEnabled );
|
||||
}
|
||||
|
||||
QObject*
|
||||
LocaleQmlViewStep::getConfig()
|
||||
{
|
||||
return m_config;
|
||||
}
|
||||
|
||||
void
|
||||
LocaleQmlViewStep::fetchGeoIpTimezone()
|
||||
{
|
||||
if ( m_geoip && m_geoip->isValid() )
|
||||
{
|
||||
m_startingTimezone = m_geoip->get();
|
||||
if ( !m_startingTimezone.isValid() )
|
||||
{
|
||||
cWarning() << "GeoIP lookup at" << m_geoip->url() << "failed.";
|
||||
}
|
||||
}
|
||||
|
||||
m_config->setLocaleInfo(m_startingTimezone.first, m_startingTimezone.second, m_localeGenPath);
|
||||
}
|
||||
|
||||
Calamares::RequirementsList LocaleQmlViewStep::checkRequirements()
|
||||
{
|
||||
LocaleGlobal::init();
|
||||
if ( m_geoip && m_geoip->isValid() )
|
||||
{
|
||||
auto& network = CalamaresUtils::Network::Manager::instance();
|
||||
if ( network.hasInternet() )
|
||||
{
|
||||
fetchGeoIpTimezone();
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( network.synchronousPing( m_geoip->url() ) )
|
||||
{
|
||||
fetchGeoIpTimezone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Calamares::RequirementsList();
|
||||
}
|
||||
|
||||
QString
|
||||
LocaleQmlViewStep::prettyName() const
|
||||
{
|
||||
return tr( "Location" );
|
||||
}
|
||||
|
||||
bool
|
||||
LocaleQmlViewStep::isNextEnabled() const
|
||||
{
|
||||
// TODO: should return true
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
LocaleQmlViewStep::isBackEnabled() const
|
||||
{
|
||||
// TODO: should return true (it's weird that you are not allowed to have welcome *after* anything
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
LocaleQmlViewStep::isAtBeginning() const
|
||||
{
|
||||
// TODO: adjust to "pages" in the QML
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
LocaleQmlViewStep::isAtEnd() const
|
||||
{
|
||||
// TODO: adjust to "pages" in the QML
|
||||
return true;
|
||||
}
|
||||
|
||||
Calamares::JobList
|
||||
LocaleQmlViewStep::jobs() const
|
||||
{
|
||||
return m_jobs;
|
||||
}
|
||||
|
||||
void LocaleQmlViewStep::onActivate()
|
||||
{
|
||||
// TODO no sure if it is needed at all or for the abstract class to start something
|
||||
}
|
||||
|
||||
void LocaleQmlViewStep::onLeave()
|
||||
{
|
||||
if ( true )
|
||||
{
|
||||
m_jobs = m_config->createJobs();
|
||||
// m_prettyStatus = m_actualWidget->prettyStatus();
|
||||
|
||||
auto map = m_config->localesMap();
|
||||
QVariantMap vm;
|
||||
for ( auto it = map.constBegin(); it != map.constEnd(); ++it )
|
||||
{
|
||||
vm.insert( it.key(), it.value() );
|
||||
}
|
||||
|
||||
Calamares::JobQueue::instance()->globalStorage()->insert( "localeConf", vm );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_jobs.clear();
|
||||
Calamares::JobQueue::instance()->globalStorage()->remove( "localeConf" );
|
||||
}
|
||||
}
|
||||
|
||||
void LocaleQmlViewStep::setConfigurationMap(const QVariantMap& configurationMap)
|
||||
{
|
||||
QString region = CalamaresUtils::getString( configurationMap, "region" );
|
||||
QString zone = CalamaresUtils::getString( configurationMap, "zone" );
|
||||
if ( !region.isEmpty() && !zone.isEmpty() )
|
||||
{
|
||||
m_startingTimezone = CalamaresUtils::GeoIP::RegionZonePair( region, zone );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_startingTimezone
|
||||
= CalamaresUtils::GeoIP::RegionZonePair( QStringLiteral( "America" ), QStringLiteral( "New_York" ) );
|
||||
}
|
||||
|
||||
m_localeGenPath = CalamaresUtils::getString( configurationMap, "localeGenPath" );
|
||||
if ( m_localeGenPath.isEmpty() )
|
||||
{
|
||||
m_localeGenPath = QStringLiteral( "/etc/locale.gen" );
|
||||
}
|
||||
|
||||
bool ok = false;
|
||||
QVariantMap geoip = CalamaresUtils::getSubMap( configurationMap, "geoip", ok );
|
||||
if ( ok )
|
||||
{
|
||||
QString url = CalamaresUtils::getString( geoip, "url" );
|
||||
QString style = CalamaresUtils::getString( geoip, "style" );
|
||||
QString selector = CalamaresUtils::getString( geoip, "selector" );
|
||||
|
||||
m_geoip = std::make_unique< CalamaresUtils::GeoIP::Handler >( style, url, selector );
|
||||
if ( !m_geoip->isValid() )
|
||||
{
|
||||
cWarning() << "GeoIP Style" << style << "is not recognized.";
|
||||
}
|
||||
}
|
||||
|
||||
checkRequirements();
|
||||
Calamares::QmlViewStep::setConfigurationMap( configurationMap ); // call parent implementation last
|
||||
setContextProperty( "Localeq", m_config );
|
||||
}
|
76
src/modules/localeq/LocaleQmlViewStep.h
Normal file
76
src/modules/localeq/LocaleQmlViewStep.h
Normal file
@ -0,0 +1,76 @@
|
||||
/* === This file is part of Calamares - <https://github.com/calamares> ===
|
||||
*
|
||||
* Copyright 2019-2020 Adriaan de Groot <groot@kde.org>
|
||||
*
|
||||
* 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_QMLVIEWSTEP_H
|
||||
#define LOCALE_QMLVIEWSTEP_H
|
||||
|
||||
#include "Config.h"
|
||||
#include "geoip/Handler.h"
|
||||
#include "geoip/Interface.h"
|
||||
#include "utils/PluginFactory.h"
|
||||
#include "viewpages/QmlViewStep.h"
|
||||
#include <DllMacro.h>
|
||||
|
||||
#include <QFutureWatcher>
|
||||
#include <QObject>
|
||||
|
||||
#include <memory>
|
||||
|
||||
class PLUGINDLLEXPORT LocaleQmlViewStep : public Calamares::QmlViewStep
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LocaleQmlViewStep( QObject* parent = nullptr );
|
||||
|
||||
QString prettyName() const override;
|
||||
|
||||
bool isNextEnabled() const override;
|
||||
bool isBackEnabled() const override;
|
||||
|
||||
bool isAtBeginning() const override;
|
||||
bool isAtEnd() const override;
|
||||
|
||||
Calamares::JobList jobs() const override;
|
||||
void onActivate() override;
|
||||
void onLeave() override;
|
||||
|
||||
void setConfigurationMap( const QVariantMap& configurationMap ) override;
|
||||
QObject* getConfig() override;
|
||||
|
||||
virtual Calamares::RequirementsList checkRequirements() override;
|
||||
|
||||
private:
|
||||
// TODO: a generic QML viewstep should return a config object from a method
|
||||
Config *m_config;
|
||||
|
||||
bool m_nextEnabled;
|
||||
QString m_prettyStatus;
|
||||
|
||||
CalamaresUtils::GeoIP::RegionZonePair m_startingTimezone;
|
||||
QString m_localeGenPath;
|
||||
|
||||
Calamares::JobList m_jobs;
|
||||
std::unique_ptr< CalamaresUtils::GeoIP::Handler > m_geoip;
|
||||
|
||||
void fetchGeoIpTimezone();
|
||||
};
|
||||
|
||||
CALAMARES_PLUGIN_FACTORY_DECLARATION( LocaleQmlViewStepFactory )
|
||||
|
||||
#endif
|
97
src/modules/localeq/localeq.conf
Normal file
97
src/modules/localeq/localeq.conf
Normal file
@ -0,0 +1,97 @@
|
||||
---
|
||||
# This settings are used to set your default system time zone.
|
||||
# Time zones are usually located under /usr/share/zoneinfo and
|
||||
# provided by the 'tzdata' package of your Distribution.
|
||||
#
|
||||
# Distributions using systemd can list available
|
||||
# time zones by using the timedatectl command.
|
||||
# timedatectl list-timezones
|
||||
#
|
||||
# The starting timezone (e.g. the pin-on-the-map) when entering
|
||||
# the locale page can be set through keys *region* and *zone*.
|
||||
# If either is not set, defaults to America/New_York.
|
||||
#
|
||||
region: "America"
|
||||
zone: "New_York"
|
||||
|
||||
|
||||
# System locales are detected in the following order:
|
||||
#
|
||||
# - /usr/share/i18n/SUPPORTED
|
||||
# - localeGenPath (defaults to /etc/locale.gen if not set)
|
||||
# - 'locale -a' output
|
||||
#
|
||||
# Enable only when your Distribution is using an
|
||||
# custom path for locale.gen
|
||||
#
|
||||
#localeGenPath: "PATH_TO/locale.gen"
|
||||
|
||||
# GeoIP based Language settings: Leave commented out to disable GeoIP.
|
||||
#
|
||||
# GeoIP needs a working Internet connection.
|
||||
# This can be managed from `welcome.conf` by adding
|
||||
# internet to the list of required conditions.
|
||||
#
|
||||
# The configuration
|
||||
# is in three parts: a *style*, which can be "json" or "xml"
|
||||
# depending on the kind of data returned by the service, and
|
||||
# a *url* where the data is retrieved, and an optional *selector*
|
||||
# to pick the right field out of the returned data (e.g. field
|
||||
# name in JSON or element name in XML).
|
||||
#
|
||||
# The default selector (when the setting is blank) is picked to
|
||||
# work with existing JSON providers (which use "time_zone") and
|
||||
# Ubiquity's XML providers (which use "TimeZone").
|
||||
#
|
||||
# If the service configured via *url* uses
|
||||
# a different attribute name (e.g. "timezone") in JSON or a
|
||||
# different element tag (e.g. "<Time_Zone>") in XML, set this
|
||||
# string to the name or tag to be used.
|
||||
#
|
||||
# In JSON:
|
||||
# - if the string contains "." characters, this is used as a
|
||||
# multi-level selector, e.g. "a.b" will select the timezone
|
||||
# from data "{a: {b: "Europe/Amsterdam" } }".
|
||||
# - each part of the string split by "." characters is used as
|
||||
# a key into the JSON data.
|
||||
# In XML:
|
||||
# - all elements with the named tag (e.g. all TimeZone) elements
|
||||
# from the document are checked; the first one with non-empty
|
||||
# text value is used.
|
||||
#
|
||||
#
|
||||
# An HTTP(S) request is made to *url*. The request should return
|
||||
# valid data in a suitable format, depending on *style*;
|
||||
# generally this includes a string value with the timezone
|
||||
# in <region>/<zone> format. For services that return data which
|
||||
# does not follow the conventions of "suitable data" described
|
||||
# below, *selector* may be used to pick different data.
|
||||
#
|
||||
# Note that this example URL works, but the service is shutting
|
||||
# down in June 2018.
|
||||
#
|
||||
# Suitable JSON data looks like
|
||||
# ```
|
||||
# {"time_zone":"America/New_York"}
|
||||
# ```
|
||||
# Suitable XML data looks like
|
||||
# ```
|
||||
# <Response><TimeZone>Europe/Brussels</TimeZone></Response>
|
||||
# ```
|
||||
#
|
||||
# To accommodate providers of GeoIP timezone data with peculiar timezone
|
||||
# naming conventions, the following cleanups are performed automatically:
|
||||
# - backslashes are removed
|
||||
# - spaces are replaced with _
|
||||
#
|
||||
# Legacy settings "geoipStyle", "geoipUrl" and "geoipSelector"
|
||||
# in the top-level are still supported, but I'd advise against.
|
||||
#
|
||||
# To disable GeoIP checking, either comment-out the entire geoip section,
|
||||
# or set the *style* key to an unsupported format (e.g. `none`).
|
||||
# Also, note the analogous feature in src/modules/welcome/welcome.conf.
|
||||
#
|
||||
geoip:
|
||||
style: "json"
|
||||
url: "https://geoip.kde.org/v1/calamares"
|
||||
selector: "" # leave blank for the default
|
113
src/modules/localeq/localeq.qml
Normal file
113
src/modules/localeq/localeq.qml
Normal file
@ -0,0 +1,113 @@
|
||||
import io.calamares.modules 1.0 as Modules
|
||||
import io.calamares.ui 1.0
|
||||
|
||||
import QtQuick 2.10
|
||||
import QtQuick.Controls 2.10
|
||||
import QtQuick.Layouts 1.3
|
||||
import org.kde.kirigami 2.7 as Kirigami
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
ResponsiveBase
|
||||
{
|
||||
id: control
|
||||
|
||||
Modules.Locale //locale handler
|
||||
{
|
||||
id: _locale
|
||||
}
|
||||
|
||||
title: stackView.currentItem.title
|
||||
subtitle: stackView.currentItem.subtitle
|
||||
message: stackView.currentItem.message
|
||||
|
||||
stackView.initialItem: Item
|
||||
{
|
||||
id: _regionsListComponent
|
||||
|
||||
property string title: qsTr("Region")
|
||||
property string subtitle: qsTr("Pick your preferred region or use the default one based on your current location")
|
||||
property string message: qsTr("Select your preferred zone within your location to continue with the installation")
|
||||
|
||||
ListViewTemplate
|
||||
{
|
||||
id: _regionListView
|
||||
anchors.centerIn: parent
|
||||
implicitWidth: Math.min(parent.width, 500)
|
||||
implicitHeight: Math.min(contentHeight, 500)
|
||||
currentIndex: model.currentIndex
|
||||
model: _locale.Config.regionModel
|
||||
|
||||
delegate: ListItemDelegate
|
||||
{
|
||||
id: _delegate
|
||||
label1.text: model.label
|
||||
onClicked:
|
||||
{
|
||||
_regionListView.model.currentIndex = index
|
||||
_stackView.push(_zonesListComponent)
|
||||
}
|
||||
}
|
||||
|
||||
footer: RowLayout
|
||||
{
|
||||
width: parent.width
|
||||
z: 99999
|
||||
Button
|
||||
{
|
||||
Layout.fillWidth: true
|
||||
text: qsTr("Timezones")
|
||||
icon.name: "go-previous"
|
||||
onClicked: control.stackView.push(_zonesListComponent)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Component
|
||||
{
|
||||
id: _zonesListComponent
|
||||
|
||||
Item
|
||||
{
|
||||
property string title: qsTr("Timezone")
|
||||
property string subtitle: _locale.Config.prettyStatus
|
||||
property string message: ""
|
||||
ListViewTemplate
|
||||
{
|
||||
id: _zonesListView
|
||||
anchors.centerIn: parent
|
||||
implicitWidth: Math.min(parent.width, 500)
|
||||
implicitHeight: Math.min(contentHeight, 500)
|
||||
currentIndex: model.currentIndex
|
||||
model: _locale.Config.zonesModel
|
||||
|
||||
delegate: ListItemDelegate
|
||||
{
|
||||
id: _delegate
|
||||
label1.text: model.label
|
||||
onClicked:
|
||||
{
|
||||
_zonesListView.model.currentIndex = index
|
||||
positionViewAtIndex(index, ListView.Center)
|
||||
}
|
||||
}
|
||||
|
||||
footer: RowLayout
|
||||
{
|
||||
width: parent.width
|
||||
z: 99999
|
||||
|
||||
Button
|
||||
{
|
||||
Layout.fillWidth: true
|
||||
icon.name: "go-previous"
|
||||
text: qsTr("Regions")
|
||||
onClicked: control.stackView.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user