diff --git a/src/modules/locale/LocaleViewStep.cpp b/src/modules/locale/LocaleViewStep.cpp index c2781f9b4..24719b1be 100644 --- a/src/modules/locale/LocaleViewStep.cpp +++ b/src/modules/locale/LocaleViewStep.cpp @@ -1,6 +1,6 @@ /* === This file is part of Calamares - === * - * Copyright 2014-2015, Teo Mrnjavac + * Copyright 2014-2016, Teo Mrnjavac * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,11 +26,16 @@ #include "utils/CalamaresUtilsGui.h" #include "utils/Logger.h" +#include "utils/YamlUtils.h" #include #include +#include +#include #include +#include + CALAMARES_PLUGIN_FACTORY_DEFINITION( LocaleViewStepFactory, registerPlugin(); ) @@ -44,25 +49,37 @@ LocaleViewStep::LocaleViewStep( QObject* parent ) m_widget->setLayout( mainLayout ); CalamaresUtils::unmarginLayout( mainLayout ); - WaitingWidget* waitingWidget = - new WaitingWidget( tr( "Loading location data..." ) ); - - mainLayout->addWidget( waitingWidget ); + m_waitingWidget = new WaitingWidget( tr( "Loading location data..." ) ); + mainLayout->addWidget( m_waitingWidget ); connect( &m_initWatcher, &QFutureWatcher< void >::finished, - [=] + this, [=] { - m_actualWidget->init( m_startingTimezone.first, - m_startingTimezone.second, - m_localeGenPath ); - m_widget->layout()->removeWidget( waitingWidget ); - waitingWidget->deleteLater(); - m_widget->layout()->addWidget( m_actualWidget ); - m_nextEnabled = true; - emit nextStatusChanged( m_nextEnabled ); + bool hasInternet = Calamares::JobQueue::instance()->globalStorage() + ->value( "hasInternet" ).toBool(); + if ( m_geoipUrl.isEmpty() || !hasInternet ) + setUpPage(); + else + fetchGeoIpTimezone(); }); - QFuture< void > initFuture = QtConcurrent::run( LocaleGlobal::init ); + QFuture< void > initFuture = QtConcurrent::run( [=] + { + LocaleGlobal::init(); + if ( m_geoipUrl.isEmpty() ) + return; + + Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); + + // Max 10sec wait for RequirementsChecker to finish, assuming the welcome + // module is used. + // If welcome is not used, either "hasInternet" should be set by other means, + // or the GeoIP feature should be disabled. + for ( int i = 0; i < 10; ++i ) + if ( !gs->contains( "hasInternet" ) ) + QThread::sleep( 1 ); + } ); + m_initWatcher.setFuture( initFuture ); emit nextStatusChanged( m_nextEnabled ); @@ -76,6 +93,67 @@ LocaleViewStep::~LocaleViewStep() } +void +LocaleViewStep::setUpPage() +{ + m_actualWidget->init( m_startingTimezone.first, + m_startingTimezone.second, + m_localeGenPath ); + m_widget->layout()->removeWidget( m_waitingWidget ); + m_waitingWidget->deleteLater(); + m_widget->layout()->addWidget( m_actualWidget ); + m_nextEnabled = true; + emit nextStatusChanged( m_nextEnabled ); +} + + +void +LocaleViewStep::fetchGeoIpTimezone() +{ + QNetworkAccessManager *manager = new QNetworkAccessManager( this ); + connect( manager, &QNetworkAccessManager::finished, + [=]( QNetworkReply* reply ) + { + if ( reply->error() == QNetworkReply::NoError ) + { + YAML::Node doc = YAML::Load( reply->readAll() ); + + QVariant var = CalamaresUtils::yamlToVariant( doc ); + if ( !var.isNull() && + var.isValid() && + var.type() == QVariant::Map ) + { + QVariantMap map = var.toMap(); + if ( map.contains( "time_zone" ) && + !map.value( "time_zone" ).toString().isEmpty() ) + { + QString timezoneString = map.value( "time_zone" ).toString(); + QStringList timezone = timezoneString.split( '/', QString::SkipEmptyParts ); + if ( timezone.size() >= 2 ) + { + cDebug() << "GeoIP reporting" << timezoneString; + QString region = timezone.takeFirst(); + QString zone = timezone.join( '/' ); + m_startingTimezone = qMakePair( region, zone ); + } + } + } + } + + reply->deleteLater(); + manager->deleteLater(); + setUpPage(); + } ); + + QNetworkRequest request; + QString requestUrl = QString( "%1/json" ) + .arg( QUrl::fromUserInput( m_geoipUrl ).toString() ); + request.setUrl( QUrl( requestUrl ) ); + request.setAttribute( QNetworkRequest::FollowRedirectsAttribute, true ); + manager->get( request ); +} + + QString LocaleViewStep::prettyName() const { @@ -198,4 +276,12 @@ LocaleViewStep::setConfigurationMap( const QVariantMap& configurationMap ) { m_localeGenPath = QStringLiteral( "/etc/locale.gen" ); } + + // Optional + if ( configurationMap.contains( "geoipUrl" ) && + configurationMap.value( "geoipUrl" ).type() == QVariant::String && + !configurationMap.value( "geoipUrl" ).toString().isEmpty() ) + { + m_geoipUrl = configurationMap.value( "geoipUrl" ).toString(); + } } diff --git a/src/modules/locale/LocaleViewStep.h b/src/modules/locale/LocaleViewStep.h index 1ab9c451e..2785f3d4a 100644 --- a/src/modules/locale/LocaleViewStep.h +++ b/src/modules/locale/LocaleViewStep.h @@ -1,6 +1,6 @@ /* === This file is part of Calamares - === * - * Copyright 2014-2015, Teo Mrnjavac + * Copyright 2014-2016, Teo Mrnjavac * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,6 +29,7 @@ #include class LocalePage; +class WaitingWidget; class PLUGINDLLEXPORT LocaleViewStep : public Calamares::ViewStep { @@ -59,9 +60,14 @@ public: void setConfigurationMap( const QVariantMap& configurationMap ) override; +private slots: + void setUpPage(); + private: + void fetchGeoIpTimezone(); QWidget* m_widget; QFutureWatcher< void > m_initWatcher; + WaitingWidget* m_waitingWidget; LocalePage* m_actualWidget; bool m_nextEnabled; @@ -69,6 +75,7 @@ private: QPair< QString, QString > m_startingTimezone; QString m_localeGenPath; + QString m_geoipUrl; QList< Calamares::job_ptr > m_jobs; };