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

This commit is contained in:
Philip Müller 2019-12-12 19:53:47 +01:00
commit 14aba17cc3
28 changed files with 6817 additions and 513 deletions

View File

@ -7,6 +7,12 @@ source_file = lang/calamares_en.ts
source_lang = en
type = QT
[calamares.tz]
file_filter = lang/tz_<lang>.ts
source_file = lang/tz_en.ts
source_lang = en
type = QT
[calamares.dummypythonqt]
file_filter = src/modules/dummypythonqt/lang/<lang>/LC_MESSAGES/dummypythonqt.po
source_file = src/modules/dummypythonqt/lang/dummypythonqt.pot

11
CHANGES
View File

@ -9,10 +9,17 @@ This release contains contributions from (alphabetically by first name):
- No other contributors this time around.
## Core ##
- No changes to core functionality.
- Timezone support code has migrated into the core of Calamares. This
means that modules now have easier access to timezone information.
Translations for timezones have also been enabled, so it is **possible**
at least to translate the displayed zones in the *welcome* module.
## Modules ##
- No changes to modules.
- The *license* module has seen a significant change to its looks.
Actions are now labeled more clearly, and the URL (or filename)
for each license is displayed.
- The *welcome* module now supports translations for timezone and
location names (e.g. "Berlin" is "Berlijn" in Dutch).
# 3.2.17.1 (2019-12-02) #

View File

@ -67,8 +67,12 @@ macro(add_calamares_translations language)
# calamares and qt language files
set( calamares_i18n_qrc_content "${calamares_i18n_qrc_content}<qresource prefix=\"/lang\">\n" )
foreach( lang ${CALAMARES_LANGUAGES} )
set( calamares_i18n_qrc_content "${calamares_i18n_qrc_content}<file>calamares_${lang}.qm</file>\n" )
list( APPEND TS_FILES "${CMAKE_SOURCE_DIR}/lang/calamares_${lang}.ts" )
foreach( tlsource "calamares_${lang}" "tz_${lang}" )
if( EXISTS "${CMAKE_SOURCE_DIR}/lang/${tlsource}.ts" )
set( calamares_i18n_qrc_content "${calamares_i18n_qrc_content}<file>${tlsource}.qm</file>\n" )
list( APPEND TS_FILES "${CMAKE_SOURCE_DIR}/lang/${tlsource}.ts" )
endif()
endforeach()
endforeach()
set( calamares_i18n_qrc_content "${calamares_i18n_qrc_content}</qresource>\n" )

View File

@ -50,12 +50,17 @@ fi
# sources, then push to Transifex
export QT_SELECT=5
lupdate -version > /dev/null 2>&1 || export QT_SELECT=qt5
lupdate -version > /dev/null 2>&1 || { echo "! No working lupdate" ; lupdate -version ; exit 1 ; }
# Don't pull branding translations in,
# those are done separately.
_srcdirs="src/calamares src/libcalamares src/libcalamaresui src/modules src/qml"
lupdate $_srcdirs -ts -no-obsolete lang/calamares_en.ts
lupdate -no-obsolete $_srcdirs -ts lang/calamares_en.ts
lupdate -no-obsolete -extensions cxxtr src/libcalamares/locale -ts lang/tz_en.ts
tx push --source --no-interactive -r calamares.calamares-master
tx push --source --no-interactive -r calamares.tz
tx push --source --no-interactive -r calamares.fdo
### PYTHON MODULES

2617
lang/tz_en.ts Normal file

File diff suppressed because it is too large Load Diff

2617
lang/tz_nl.ts Normal file

File diff suppressed because it is too large Load Diff

View File

@ -34,6 +34,7 @@ set( libSources
locale/Label.cpp
locale/LabelModel.cpp
locale/Lookup.cpp
locale/TimeZone.cpp
locale/TranslatableConfiguration.cpp
# Network service

View File

@ -15,6 +15,13 @@
* Conditions herein.
*/
/* MODIFICATIONS
*
* Edited anyway:
* 20191211 India changed to AnyLanguage, since Hindi doesn't make sense. #1284
*
*/
// BEGIN Generated from CLDR data
// *INDENT-OFF*
// clang-format off
@ -115,7 +122,7 @@ static const CountryData country_data_table[] = {
{ QLocale::Language::Spanish, QLocale::Country::CanaryIslands, 'I', 'C' },
{ QLocale::Language::Indonesian, QLocale::Country::Indonesia, 'I', 'D' },
{ QLocale::Language::Hebrew, QLocale::Country::Israel, 'I', 'L' },
{ QLocale::Language::Hindi, QLocale::Country::India, 'I', 'N' },
{ QLocale::Language::AnyLanguage, QLocale::Country::India, 'I', 'N' },
{ QLocale::Language::Arabic, QLocale::Country::Iraq, 'I', 'Q' },
{ QLocale::Language::Persian, QLocale::Country::Iran, 'I', 'R' },
{ QLocale::Language::Icelandic, QLocale::Country::Iceland, 'I', 'S' },

View File

@ -19,6 +19,7 @@
#include "Tests.h"
#include "locale/LabelModel.h"
#include "locale/TimeZone.h"
#include "locale/TranslatableConfiguration.h"
#include "CalamaresVersion.h"
@ -199,3 +200,55 @@ LocaleTests::testTranslatableConfig2()
QVERIFY( ts3.isEmpty() );
QCOMPARE( ts3.count(), 1 ); // The empty string
}
void
LocaleTests::testSimpleZones()
{
using namespace CalamaresUtils::Locale;
{
TZRegion r;
QVERIFY( r.tr().isEmpty() );
}
{
TZZone n;
QVERIFY( n.tr().isEmpty() );
}
{
TZRegion r0( "xAmsterdam" );
QCOMPARE( r0.tr(), QStringLiteral( "xAmsterdam" ) );
TZRegion r1( r0 );
QCOMPARE( r0.tr(), QStringLiteral( "xAmsterdam" ) );
QCOMPARE( r1.tr(), QStringLiteral( "xAmsterdam" ) );
TZRegion r2( std::move( r0 ) );
QCOMPARE( r2.tr(), QStringLiteral( "xAmsterdam" ) );
QCOMPARE( r0.tr(), QString() );
}
{
TZZone r0( nullptr );
QVERIFY( r0.tr().isEmpty() );
TZZone r1( r0 );
QVERIFY( r1.tr().isEmpty() );
TZZone r2( std::move( r0 ) );
QVERIFY( r2.tr().isEmpty() );
}
}
void
LocaleTests::testComplexZones()
{
using namespace CalamaresUtils::Locale;
{
TZZone r0( "America/New_York" );
TZZone r1( "America/New York" );
QCOMPARE( r0.tr(), r1.tr() );
QCOMPARE( r0.tr(), QStringLiteral( "America/New York" ) );
}
{
TZZone r( "zxc,;*_vm" );
QVERIFY( !r.tr().isEmpty() );
QCOMPARE( r.tr(), QStringLiteral( "zxc,;* vm" ) ); // Only _ is special
}
}

View File

@ -36,6 +36,10 @@ private Q_SLOTS:
void testTranslatableLanguages();
void testTranslatableConfig1();
void testTranslatableConfig2();
// TimeZone testing
void testSimpleZones();
void testComplexZones();
};
#endif

View File

@ -0,0 +1,279 @@
/* === This file is part of Calamares - <https://github.com/calamares> ===
*
* Copyright 2019, 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 "TimeZone.h"
#include "utils/Logger.h"
#include <QFile>
#include <QStringList>
#include <QTextStream>
#include <cstring>
static const char TZ_DATA_FILE[] = "/usr/share/zoneinfo/zone.tab";
static double
getRightGeoLocation( QString str )
{
double sign = 1, num = 0.00;
// Determine sign
if ( str.startsWith( '-' ) )
{
sign = -1;
str.remove( 0, 1 );
}
else if ( str.startsWith( '+' ) )
{
str.remove( 0, 1 );
}
if ( str.length() == 4 || str.length() == 6 )
{
num = str.mid( 0, 2 ).toDouble() + str.mid( 2, 2 ).toDouble() / 60.0;
}
else if ( str.length() == 5 || str.length() == 7 )
{
num = str.mid( 0, 3 ).toDouble() + str.mid( 3, 2 ).toDouble() / 60.0;
}
return sign * num;
}
namespace CalamaresUtils
{
namespace Locale
{
CStringPair::CStringPair( CStringPair&& t )
: m_human( nullptr )
, m_key()
{
// My pointers are initialized to nullptr
std::swap( m_human, t.m_human );
std::swap( m_key, t.m_key );
}
CStringPair::CStringPair( const CStringPair& t )
: m_human( t.m_human ? strdup( t.m_human ) : nullptr )
, m_key( t.m_key )
{
}
/** @brief Massage an identifier into a human-readable form
*
* Makes a copy of @p s, caller must free() it.
*/
static char*
munge( const char* s )
{
char* t = strdup( s );
if ( !t )
{
return nullptr;
}
// replace("_"," ") in the Python script
char* p = t;
while ( *p )
{
if ( ( *p ) == '_' )
{
*p = ' ';
}
++p;
}
return t;
}
CStringPair::CStringPair( const char* s1 )
: m_human( s1 ? munge( s1 ) : nullptr )
, m_key( s1 ? QString( s1 ) : QString() )
{
}
CStringPair::~CStringPair()
{
free( m_human );
}
QString
TZRegion::tr() const
{
// NOTE: context name must match what's used in zone-extractor.py
return QObject::tr( m_human, "tz_regions" );
}
TZRegion::~TZRegion()
{
qDeleteAll( m_zones );
}
const CStringPairList&
TZRegion::fromZoneTab()
{
static CStringPairList zoneTab = TZRegion::fromFile( TZ_DATA_FILE );
return zoneTab;
}
CStringPairList
TZRegion::fromFile( const char* fileName )
{
CStringPairList model;
QFile file( fileName );
if ( !file.open( QIODevice::ReadOnly | QIODevice::Text ) )
{
return model;
}
TZRegion* thisRegion = nullptr;
QTextStream in( &file );
while ( !in.atEnd() )
{
QString line = in.readLine().trimmed().split( '#', QString::KeepEmptyParts ).first().trimmed();
if ( line.isEmpty() )
{
continue;
}
QStringList list = line.split( QRegExp( "[\t ]" ), QString::SkipEmptyParts );
if ( list.size() < 3 )
{
continue;
}
QStringList timezoneParts = list.at( 2 ).split( '/', QString::SkipEmptyParts );
if ( timezoneParts.size() < 2 )
{
continue;
}
QString region = timezoneParts.first().trimmed();
;
if ( region.isEmpty() )
{
continue;
}
auto keyMatch = [&region]( const CStringPair* r ) { return r->key() == region; };
auto it = std::find_if( model.begin(), model.end(), keyMatch );
if ( it != model.end() )
{
thisRegion = dynamic_cast< TZRegion* >( *it );
}
else
{
thisRegion = new TZRegion( region.toUtf8().data() );
model.append( thisRegion );
}
QString countryCode = list.at( 0 ).trimmed();
if ( countryCode.size() != 2 )
{
continue;
}
timezoneParts.removeFirst();
thisRegion->m_zones.append(
new TZZone( region, timezoneParts.join( '/' ).toUtf8().constData(), countryCode, list.at( 1 ) ) );
}
auto sorter = []( const CStringPair* l, const CStringPair* r ) { return *l < *r; };
std::sort( model.begin(), model.end(), sorter );
for ( auto& it : model )
{
TZRegion* r = dynamic_cast< TZRegion* >( it );
if ( r )
{
std::sort( r->m_zones.begin(), r->m_zones.end(), sorter );
}
}
return model;
}
TZZone::TZZone( const QString& region, const char* zoneName, const QString& country, QString position )
: CStringPair( zoneName )
, m_region( region )
, m_country( country )
{
int cooSplitPos = position.indexOf( QRegExp( "[-+]" ), 1 );
if ( cooSplitPos > 0 )
{
m_latitude = getRightGeoLocation( position.mid( 0, cooSplitPos ) );
m_longitude = getRightGeoLocation( position.mid( cooSplitPos ) );
}
}
QString
TZZone::tr() const
{
// NOTE: context name must match what's used in zone-extractor.py
return QObject::tr( m_human, "tz_names" );
}
CStringListModel::CStringListModel( CStringPairList l )
: m_list( l )
{
}
CStringListModel::~CStringListModel() {}
int
CStringListModel::rowCount( const QModelIndex& parent ) const
{
return m_list.count();
}
QVariant
CStringListModel::data( const QModelIndex& index, int role ) const
{
if ( ( role != Qt::DisplayRole ) && ( role != Qt::UserRole ) )
{
return QVariant();
}
if ( !index.isValid() )
{
return QVariant();
}
const auto* item = m_list.at( index.row() );
return item ? ( role == Qt::DisplayRole ? item->tr() : item->key() ) : QVariant();
}
const CStringPair*
CStringListModel::item( int index ) const
{
if ( ( index < 0 ) || ( index >= m_list.count() ) )
{
return nullptr;
}
return m_list[ index ];
}
} // namespace Locale
} // namespace CalamaresUtils

View File

@ -0,0 +1,159 @@
/* === This file is part of Calamares - <https://github.com/calamares> ===
*
* Copyright 2019, 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_TIMEZONE_H
#define LOCALE_TIMEZONE_H
#include "DllMacro.h"
#include "utils/Logger.h"
#include <QAbstractListModel>
#include <QObject>
#include <QString>
#include <memory>
namespace CalamaresUtils
{
namespace Locale
{
/** @brief A pair of strings, one human-readable, one a key
*
* Given an identifier-like string (e.g. "New_York"), makes
* a human-readable version of that and keeps a copy of the
* identifier itself.
*
* This explicitly uses const char* instead of just being
* QPair<QString, QString> because there is API that needs
* C-style strings.
*/
class CStringPair
{
public:
/// @brief An empty pair
CStringPair() {};
/// @brief Given an identifier, create the pair
explicit CStringPair( const char* s1 );
CStringPair( CStringPair&& t );
CStringPair( const CStringPair& );
virtual ~CStringPair();
/// @brief Give the localized human-readable form
virtual QString tr() const = 0;
QString key() const { return m_key; }
bool operator<( const CStringPair& other ) const { return m_key < other.m_key; }
protected:
char* m_human = nullptr;
QString m_key;
};
class CStringPairList : public QList< CStringPair* >
{
public:
template < typename T >
T* find( const QString& key ) const
{
for ( auto* p : *this )
{
if ( p->key() == key )
{
return dynamic_cast< T* >( p );
}
}
return nullptr;
}
};
/// @brief A pair of strings for timezone regions (e.g. "America")
class TZRegion : public CStringPair
{
public:
using CStringPair::CStringPair;
virtual ~TZRegion();
QString tr() const override;
QString region() const { return key(); }
/** @brief Create list from a zone.tab-like file
*
* Returns a list of all the regions; each region has a list
* of zones within that region. Dyamically, the items in the
* returned list are TZRegions; their zones dynamically are
* TZZones even though all those lists have type CStringPairList.
*
* The list owns the regions, and the regions own their own list of zones.
* When getting rid of the list, remember to qDeleteAll() on it.
*/
static CStringPairList fromFile( const char* fileName );
/// @brief Calls fromFile with the standard zone.tab name
static const CStringPairList& fromZoneTab();
const CStringPairList& zones() const { return m_zones; }
private:
CStringPairList m_zones;
};
/// @brief A pair of strings for specific timezone names (e.g. "New_York")
class TZZone : public CStringPair
{
public:
using CStringPair::CStringPair;
QString tr() const override;
TZZone( const QString& region, const char* zoneName, const QString& country, QString position );
QString region() const { return m_region; }
QString zone() const { return key(); }
QString country() const { return m_country; }
double latitude() const { return m_latitude; }
double longitude() const { return m_longitude; }
protected:
QString m_region;
QString m_country;
double m_latitude = 0.0, m_longitude = 0.0;
};
class CStringListModel : public QAbstractListModel
{
public:
/// @brief Create empty model
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;
private:
CStringPairList m_list;
};
} // namespace Locale
} // namespace CalamaresUtils
#endif // LOCALE_TIMEZONE_H

View File

@ -0,0 +1,478 @@
/* GENERATED FILE DO NOT EDIT
*
* === This file is part of Calamares - <https://github.com/calamares> ===
*
* This file is derived from zone.tab, which has its own copyright statement:
*
* This file is in the public domain, so clarified as of
* 2009-05-17 by Arthur David Olson.
*
* From Paul Eggert (2018-06-27):
* This file is intended as a backward-compatibility aid for older programs.
* New programs should use zone1970.tab. This file is like zone1970.tab (see
* zone1970.tab's comments), but with the following additional restrictions:
*
* 1. This file contains only ASCII characters.
* 2. The first data column contains exactly one country code.
*
*/
/** THIS FILE EXISTS ONLY FOR TRANSLATIONS PURPOSES **/
// *INDENT-OFF*
// clang-format off
/* This returns a reference to local, which is a terrible idea.
* Good thing it's not meant to be compiled.
*/
static const QStringList& tz_regions_table()
{
return QStringList {
QObject::tr("Africa", "tz_regions"),
QObject::tr("America", "tz_regions"),
QObject::tr("Antarctica", "tz_regions"),
QObject::tr("Arctic", "tz_regions"),
QObject::tr("Asia", "tz_regions"),
QObject::tr("Atlantic", "tz_regions"),
QObject::tr("Australia", "tz_regions"),
QObject::tr("Europe", "tz_regions"),
QObject::tr("Indian", "tz_regions"),
QObject::tr("Pacific", "tz_regions"),
QString()
};
}
/* This returns a reference to local, which is a terrible idea.
* Good thing it's not meant to be compiled.
*/
static const QStringList& tz_names_table()
{
return QStringList {
QObject::tr("Abidjan", "tz_names"),
QObject::tr("Accra", "tz_names"),
QObject::tr("Adak", "tz_names"),
QObject::tr("Addis Ababa", "tz_names"),
QObject::tr("Adelaide", "tz_names"),
QObject::tr("Aden", "tz_names"),
QObject::tr("Algiers", "tz_names"),
QObject::tr("Almaty", "tz_names"),
QObject::tr("Amman", "tz_names"),
QObject::tr("Amsterdam", "tz_names"),
QObject::tr("Anadyr", "tz_names"),
QObject::tr("Anchorage", "tz_names"),
QObject::tr("Andorra", "tz_names"),
QObject::tr("Anguilla", "tz_names"),
QObject::tr("Antananarivo", "tz_names"),
QObject::tr("Antigua", "tz_names"),
QObject::tr("Apia", "tz_names"),
QObject::tr("Aqtau", "tz_names"),
QObject::tr("Aqtobe", "tz_names"),
QObject::tr("Araguaina", "tz_names"),
QObject::tr("Argentina/Buenos Aires", "tz_names"),
QObject::tr("Argentina/Catamarca", "tz_names"),
QObject::tr("Argentina/Cordoba", "tz_names"),
QObject::tr("Argentina/Jujuy", "tz_names"),
QObject::tr("Argentina/La Rioja", "tz_names"),
QObject::tr("Argentina/Mendoza", "tz_names"),
QObject::tr("Argentina/Rio Gallegos", "tz_names"),
QObject::tr("Argentina/Salta", "tz_names"),
QObject::tr("Argentina/San Juan", "tz_names"),
QObject::tr("Argentina/San Luis", "tz_names"),
QObject::tr("Argentina/Tucuman", "tz_names"),
QObject::tr("Argentina/Ushuaia", "tz_names"),
QObject::tr("Aruba", "tz_names"),
QObject::tr("Ashgabat", "tz_names"),
QObject::tr("Asmara", "tz_names"),
QObject::tr("Astrakhan", "tz_names"),
QObject::tr("Asuncion", "tz_names"),
QObject::tr("Athens", "tz_names"),
QObject::tr("Atikokan", "tz_names"),
QObject::tr("Atyrau", "tz_names"),
QObject::tr("Auckland", "tz_names"),
QObject::tr("Azores", "tz_names"),
QObject::tr("Baghdad", "tz_names"),
QObject::tr("Bahia", "tz_names"),
QObject::tr("Bahia Banderas", "tz_names"),
QObject::tr("Bahrain", "tz_names"),
QObject::tr("Baku", "tz_names"),
QObject::tr("Bamako", "tz_names"),
QObject::tr("Bangkok", "tz_names"),
QObject::tr("Bangui", "tz_names"),
QObject::tr("Banjul", "tz_names"),
QObject::tr("Barbados", "tz_names"),
QObject::tr("Barnaul", "tz_names"),
QObject::tr("Beirut", "tz_names"),
QObject::tr("Belem", "tz_names"),
QObject::tr("Belgrade", "tz_names"),
QObject::tr("Belize", "tz_names"),
QObject::tr("Berlin", "tz_names"),
QObject::tr("Bermuda", "tz_names"),
QObject::tr("Bishkek", "tz_names"),
QObject::tr("Bissau", "tz_names"),
QObject::tr("Blanc-Sablon", "tz_names"),
QObject::tr("Blantyre", "tz_names"),
QObject::tr("Boa Vista", "tz_names"),
QObject::tr("Bogota", "tz_names"),
QObject::tr("Boise", "tz_names"),
QObject::tr("Bougainville", "tz_names"),
QObject::tr("Bratislava", "tz_names"),
QObject::tr("Brazzaville", "tz_names"),
QObject::tr("Brisbane", "tz_names"),
QObject::tr("Broken Hill", "tz_names"),
QObject::tr("Brunei", "tz_names"),
QObject::tr("Brussels", "tz_names"),
QObject::tr("Bucharest", "tz_names"),
QObject::tr("Budapest", "tz_names"),
QObject::tr("Bujumbura", "tz_names"),
QObject::tr("Busingen", "tz_names"),
QObject::tr("Cairo", "tz_names"),
QObject::tr("Cambridge Bay", "tz_names"),
QObject::tr("Campo Grande", "tz_names"),
QObject::tr("Canary", "tz_names"),
QObject::tr("Cancun", "tz_names"),
QObject::tr("Cape Verde", "tz_names"),
QObject::tr("Caracas", "tz_names"),
QObject::tr("Casablanca", "tz_names"),
QObject::tr("Casey", "tz_names"),
QObject::tr("Cayenne", "tz_names"),
QObject::tr("Cayman", "tz_names"),
QObject::tr("Ceuta", "tz_names"),
QObject::tr("Chagos", "tz_names"),
QObject::tr("Chatham", "tz_names"),
QObject::tr("Chicago", "tz_names"),
QObject::tr("Chihuahua", "tz_names"),
QObject::tr("Chisinau", "tz_names"),
QObject::tr("Chita", "tz_names"),
QObject::tr("Choibalsan", "tz_names"),
QObject::tr("Christmas", "tz_names"),
QObject::tr("Chuuk", "tz_names"),
QObject::tr("Cocos", "tz_names"),
QObject::tr("Colombo", "tz_names"),
QObject::tr("Comoro", "tz_names"),
QObject::tr("Conakry", "tz_names"),
QObject::tr("Copenhagen", "tz_names"),
QObject::tr("Costa Rica", "tz_names"),
QObject::tr("Creston", "tz_names"),
QObject::tr("Cuiaba", "tz_names"),
QObject::tr("Curacao", "tz_names"),
QObject::tr("Currie", "tz_names"),
QObject::tr("Dakar", "tz_names"),
QObject::tr("Damascus", "tz_names"),
QObject::tr("Danmarkshavn", "tz_names"),
QObject::tr("Dar es Salaam", "tz_names"),
QObject::tr("Darwin", "tz_names"),
QObject::tr("Davis", "tz_names"),
QObject::tr("Dawson", "tz_names"),
QObject::tr("Dawson Creek", "tz_names"),
QObject::tr("Denver", "tz_names"),
QObject::tr("Detroit", "tz_names"),
QObject::tr("Dhaka", "tz_names"),
QObject::tr("Dili", "tz_names"),
QObject::tr("Djibouti", "tz_names"),
QObject::tr("Dominica", "tz_names"),
QObject::tr("Douala", "tz_names"),
QObject::tr("Dubai", "tz_names"),
QObject::tr("Dublin", "tz_names"),
QObject::tr("DumontDUrville", "tz_names"),
QObject::tr("Dushanbe", "tz_names"),
QObject::tr("Easter", "tz_names"),
QObject::tr("Edmonton", "tz_names"),
QObject::tr("Efate", "tz_names"),
QObject::tr("Eirunepe", "tz_names"),
QObject::tr("El Aaiun", "tz_names"),
QObject::tr("El Salvador", "tz_names"),
QObject::tr("Enderbury", "tz_names"),
QObject::tr("Eucla", "tz_names"),
QObject::tr("Fakaofo", "tz_names"),
QObject::tr("Famagusta", "tz_names"),
QObject::tr("Faroe", "tz_names"),
QObject::tr("Fiji", "tz_names"),
QObject::tr("Fort Nelson", "tz_names"),
QObject::tr("Fortaleza", "tz_names"),
QObject::tr("Freetown", "tz_names"),
QObject::tr("Funafuti", "tz_names"),
QObject::tr("Gaborone", "tz_names"),
QObject::tr("Galapagos", "tz_names"),
QObject::tr("Gambier", "tz_names"),
QObject::tr("Gaza", "tz_names"),
QObject::tr("Gibraltar", "tz_names"),
QObject::tr("Glace Bay", "tz_names"),
QObject::tr("Godthab", "tz_names"),
QObject::tr("Goose Bay", "tz_names"),
QObject::tr("Grand Turk", "tz_names"),
QObject::tr("Grenada", "tz_names"),
QObject::tr("Guadalcanal", "tz_names"),
QObject::tr("Guadeloupe", "tz_names"),
QObject::tr("Guam", "tz_names"),
QObject::tr("Guatemala", "tz_names"),
QObject::tr("Guayaquil", "tz_names"),
QObject::tr("Guernsey", "tz_names"),
QObject::tr("Guyana", "tz_names"),
QObject::tr("Halifax", "tz_names"),
QObject::tr("Harare", "tz_names"),
QObject::tr("Havana", "tz_names"),
QObject::tr("Hebron", "tz_names"),
QObject::tr("Helsinki", "tz_names"),
QObject::tr("Hermosillo", "tz_names"),
QObject::tr("Ho Chi Minh", "tz_names"),
QObject::tr("Hobart", "tz_names"),
QObject::tr("Hong Kong", "tz_names"),
QObject::tr("Honolulu", "tz_names"),
QObject::tr("Hovd", "tz_names"),
QObject::tr("Indiana/Indianapolis", "tz_names"),
QObject::tr("Indiana/Knox", "tz_names"),
QObject::tr("Indiana/Marengo", "tz_names"),
QObject::tr("Indiana/Petersburg", "tz_names"),
QObject::tr("Indiana/Tell City", "tz_names"),
QObject::tr("Indiana/Vevay", "tz_names"),
QObject::tr("Indiana/Vincennes", "tz_names"),
QObject::tr("Indiana/Winamac", "tz_names"),
QObject::tr("Inuvik", "tz_names"),
QObject::tr("Iqaluit", "tz_names"),
QObject::tr("Irkutsk", "tz_names"),
QObject::tr("Isle of Man", "tz_names"),
QObject::tr("Istanbul", "tz_names"),
QObject::tr("Jakarta", "tz_names"),
QObject::tr("Jamaica", "tz_names"),
QObject::tr("Jayapura", "tz_names"),
QObject::tr("Jersey", "tz_names"),
QObject::tr("Jerusalem", "tz_names"),
QObject::tr("Johannesburg", "tz_names"),
QObject::tr("Juba", "tz_names"),
QObject::tr("Juneau", "tz_names"),
QObject::tr("Kabul", "tz_names"),
QObject::tr("Kaliningrad", "tz_names"),
QObject::tr("Kamchatka", "tz_names"),
QObject::tr("Kampala", "tz_names"),
QObject::tr("Karachi", "tz_names"),
QObject::tr("Kathmandu", "tz_names"),
QObject::tr("Kentucky/Louisville", "tz_names"),
QObject::tr("Kentucky/Monticello", "tz_names"),
QObject::tr("Kerguelen", "tz_names"),
QObject::tr("Khandyga", "tz_names"),
QObject::tr("Khartoum", "tz_names"),
QObject::tr("Kiev", "tz_names"),
QObject::tr("Kigali", "tz_names"),
QObject::tr("Kinshasa", "tz_names"),
QObject::tr("Kiritimati", "tz_names"),
QObject::tr("Kirov", "tz_names"),
QObject::tr("Kolkata", "tz_names"),
QObject::tr("Kosrae", "tz_names"),
QObject::tr("Kralendijk", "tz_names"),
QObject::tr("Krasnoyarsk", "tz_names"),
QObject::tr("Kuala Lumpur", "tz_names"),
QObject::tr("Kuching", "tz_names"),
QObject::tr("Kuwait", "tz_names"),
QObject::tr("Kwajalein", "tz_names"),
QObject::tr("La Paz", "tz_names"),
QObject::tr("Lagos", "tz_names"),
QObject::tr("Libreville", "tz_names"),
QObject::tr("Lima", "tz_names"),
QObject::tr("Lindeman", "tz_names"),
QObject::tr("Lisbon", "tz_names"),
QObject::tr("Ljubljana", "tz_names"),
QObject::tr("Lome", "tz_names"),
QObject::tr("London", "tz_names"),
QObject::tr("Longyearbyen", "tz_names"),
QObject::tr("Lord Howe", "tz_names"),
QObject::tr("Los Angeles", "tz_names"),
QObject::tr("Lower Princes", "tz_names"),
QObject::tr("Luanda", "tz_names"),
QObject::tr("Lubumbashi", "tz_names"),
QObject::tr("Lusaka", "tz_names"),
QObject::tr("Luxembourg", "tz_names"),
QObject::tr("Macau", "tz_names"),
QObject::tr("Maceio", "tz_names"),
QObject::tr("Macquarie", "tz_names"),
QObject::tr("Madeira", "tz_names"),
QObject::tr("Madrid", "tz_names"),
QObject::tr("Magadan", "tz_names"),
QObject::tr("Mahe", "tz_names"),
QObject::tr("Majuro", "tz_names"),
QObject::tr("Makassar", "tz_names"),
QObject::tr("Malabo", "tz_names"),
QObject::tr("Maldives", "tz_names"),
QObject::tr("Malta", "tz_names"),
QObject::tr("Managua", "tz_names"),
QObject::tr("Manaus", "tz_names"),
QObject::tr("Manila", "tz_names"),
QObject::tr("Maputo", "tz_names"),
QObject::tr("Mariehamn", "tz_names"),
QObject::tr("Marigot", "tz_names"),
QObject::tr("Marquesas", "tz_names"),
QObject::tr("Martinique", "tz_names"),
QObject::tr("Maseru", "tz_names"),
QObject::tr("Matamoros", "tz_names"),
QObject::tr("Mauritius", "tz_names"),
QObject::tr("Mawson", "tz_names"),
QObject::tr("Mayotte", "tz_names"),
QObject::tr("Mazatlan", "tz_names"),
QObject::tr("Mbabane", "tz_names"),
QObject::tr("McMurdo", "tz_names"),
QObject::tr("Melbourne", "tz_names"),
QObject::tr("Menominee", "tz_names"),
QObject::tr("Merida", "tz_names"),
QObject::tr("Metlakatla", "tz_names"),
QObject::tr("Mexico City", "tz_names"),
QObject::tr("Midway", "tz_names"),
QObject::tr("Minsk", "tz_names"),
QObject::tr("Miquelon", "tz_names"),
QObject::tr("Mogadishu", "tz_names"),
QObject::tr("Monaco", "tz_names"),
QObject::tr("Moncton", "tz_names"),
QObject::tr("Monrovia", "tz_names"),
QObject::tr("Monterrey", "tz_names"),
QObject::tr("Montevideo", "tz_names"),
QObject::tr("Montserrat", "tz_names"),
QObject::tr("Moscow", "tz_names"),
QObject::tr("Muscat", "tz_names"),
QObject::tr("Nairobi", "tz_names"),
QObject::tr("Nassau", "tz_names"),
QObject::tr("Nauru", "tz_names"),
QObject::tr("Ndjamena", "tz_names"),
QObject::tr("New York", "tz_names"),
QObject::tr("Niamey", "tz_names"),
QObject::tr("Nicosia", "tz_names"),
QObject::tr("Nipigon", "tz_names"),
QObject::tr("Niue", "tz_names"),
QObject::tr("Nome", "tz_names"),
QObject::tr("Norfolk", "tz_names"),
QObject::tr("Noronha", "tz_names"),
QObject::tr("North Dakota/Beulah", "tz_names"),
QObject::tr("North Dakota/Center", "tz_names"),
QObject::tr("North Dakota/New Salem", "tz_names"),
QObject::tr("Nouakchott", "tz_names"),
QObject::tr("Noumea", "tz_names"),
QObject::tr("Novokuznetsk", "tz_names"),
QObject::tr("Novosibirsk", "tz_names"),
QObject::tr("Ojinaga", "tz_names"),
QObject::tr("Omsk", "tz_names"),
QObject::tr("Oral", "tz_names"),
QObject::tr("Oslo", "tz_names"),
QObject::tr("Ouagadougou", "tz_names"),
QObject::tr("Pago Pago", "tz_names"),
QObject::tr("Palau", "tz_names"),
QObject::tr("Palmer", "tz_names"),
QObject::tr("Panama", "tz_names"),
QObject::tr("Pangnirtung", "tz_names"),
QObject::tr("Paramaribo", "tz_names"),
QObject::tr("Paris", "tz_names"),
QObject::tr("Perth", "tz_names"),
QObject::tr("Phnom Penh", "tz_names"),
QObject::tr("Phoenix", "tz_names"),
QObject::tr("Pitcairn", "tz_names"),
QObject::tr("Podgorica", "tz_names"),
QObject::tr("Pohnpei", "tz_names"),
QObject::tr("Pontianak", "tz_names"),
QObject::tr("Port Moresby", "tz_names"),
QObject::tr("Port of Spain", "tz_names"),
QObject::tr("Port-au-Prince", "tz_names"),
QObject::tr("Porto Velho", "tz_names"),
QObject::tr("Porto-Novo", "tz_names"),
QObject::tr("Prague", "tz_names"),
QObject::tr("Puerto Rico", "tz_names"),
QObject::tr("Punta Arenas", "tz_names"),
QObject::tr("Pyongyang", "tz_names"),
QObject::tr("Qatar", "tz_names"),
QObject::tr("Qostanay", "tz_names"),
QObject::tr("Qyzylorda", "tz_names"),
QObject::tr("Rainy River", "tz_names"),
QObject::tr("Rankin Inlet", "tz_names"),
QObject::tr("Rarotonga", "tz_names"),
QObject::tr("Recife", "tz_names"),
QObject::tr("Regina", "tz_names"),
QObject::tr("Resolute", "tz_names"),
QObject::tr("Reunion", "tz_names"),
QObject::tr("Reykjavik", "tz_names"),
QObject::tr("Riga", "tz_names"),
QObject::tr("Rio Branco", "tz_names"),
QObject::tr("Riyadh", "tz_names"),
QObject::tr("Rome", "tz_names"),
QObject::tr("Rothera", "tz_names"),
QObject::tr("Saipan", "tz_names"),
QObject::tr("Sakhalin", "tz_names"),
QObject::tr("Samara", "tz_names"),
QObject::tr("Samarkand", "tz_names"),
QObject::tr("San Marino", "tz_names"),
QObject::tr("Santarem", "tz_names"),
QObject::tr("Santiago", "tz_names"),
QObject::tr("Santo Domingo", "tz_names"),
QObject::tr("Sao Paulo", "tz_names"),
QObject::tr("Sao Tome", "tz_names"),
QObject::tr("Sarajevo", "tz_names"),
QObject::tr("Saratov", "tz_names"),
QObject::tr("Scoresbysund", "tz_names"),
QObject::tr("Seoul", "tz_names"),
QObject::tr("Shanghai", "tz_names"),
QObject::tr("Simferopol", "tz_names"),
QObject::tr("Singapore", "tz_names"),
QObject::tr("Sitka", "tz_names"),
QObject::tr("Skopje", "tz_names"),
QObject::tr("Sofia", "tz_names"),
QObject::tr("South Georgia", "tz_names"),
QObject::tr("Srednekolymsk", "tz_names"),
QObject::tr("St Barthelemy", "tz_names"),
QObject::tr("St Helena", "tz_names"),
QObject::tr("St Johns", "tz_names"),
QObject::tr("St Kitts", "tz_names"),
QObject::tr("St Lucia", "tz_names"),
QObject::tr("St Thomas", "tz_names"),
QObject::tr("St Vincent", "tz_names"),
QObject::tr("Stanley", "tz_names"),
QObject::tr("Stockholm", "tz_names"),
QObject::tr("Swift Current", "tz_names"),
QObject::tr("Sydney", "tz_names"),
QObject::tr("Syowa", "tz_names"),
QObject::tr("Tahiti", "tz_names"),
QObject::tr("Taipei", "tz_names"),
QObject::tr("Tallinn", "tz_names"),
QObject::tr("Tarawa", "tz_names"),
QObject::tr("Tashkent", "tz_names"),
QObject::tr("Tbilisi", "tz_names"),
QObject::tr("Tegucigalpa", "tz_names"),
QObject::tr("Tehran", "tz_names"),
QObject::tr("Thimphu", "tz_names"),
QObject::tr("Thule", "tz_names"),
QObject::tr("Thunder Bay", "tz_names"),
QObject::tr("Tijuana", "tz_names"),
QObject::tr("Tirane", "tz_names"),
QObject::tr("Tokyo", "tz_names"),
QObject::tr("Tomsk", "tz_names"),
QObject::tr("Tongatapu", "tz_names"),
QObject::tr("Toronto", "tz_names"),
QObject::tr("Tortola", "tz_names"),
QObject::tr("Tripoli", "tz_names"),
QObject::tr("Troll", "tz_names"),
QObject::tr("Tunis", "tz_names"),
QObject::tr("Ulaanbaatar", "tz_names"),
QObject::tr("Ulyanovsk", "tz_names"),
QObject::tr("Urumqi", "tz_names"),
QObject::tr("Ust-Nera", "tz_names"),
QObject::tr("Uzhgorod", "tz_names"),
QObject::tr("Vaduz", "tz_names"),
QObject::tr("Vancouver", "tz_names"),
QObject::tr("Vatican", "tz_names"),
QObject::tr("Vienna", "tz_names"),
QObject::tr("Vientiane", "tz_names"),
QObject::tr("Vilnius", "tz_names"),
QObject::tr("Vladivostok", "tz_names"),
QObject::tr("Volgograd", "tz_names"),
QObject::tr("Vostok", "tz_names"),
QObject::tr("Wake", "tz_names"),
QObject::tr("Wallis", "tz_names"),
QObject::tr("Warsaw", "tz_names"),
QObject::tr("Whitehorse", "tz_names"),
QObject::tr("Windhoek", "tz_names"),
QObject::tr("Winnipeg", "tz_names"),
QObject::tr("Yakutat", "tz_names"),
QObject::tr("Yakutsk", "tz_names"),
QObject::tr("Yangon", "tz_names"),
QObject::tr("Yekaterinburg", "tz_names"),
QObject::tr("Yellowknife", "tz_names"),
QObject::tr("Yerevan", "tz_names"),
QObject::tr("Zagreb", "tz_names"),
QObject::tr("Zaporozhye", "tz_names"),
QObject::tr("Zurich", "tz_names"),
QString()
};
}

View File

@ -0,0 +1,108 @@
#! /usr/bin/env python3
#
# === This file is part of Calamares - <https://github.com/calamares> ===
#
# Python3 script to scrape some data out of zoneinfo/zone.tab.
#
### BEGIN LICENSES
#
# Copyright 2019 Adriaan de Groot <groot@kde.org>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
### END LICENSES
### BEGIN USAGE
#
"""
Python3 script to scrape some data out of zoneinfo/zone.tab.
To use this script, you must have a zone.tab in a standard location,
/usr/share/zoneinfo/zone.tab (this is usual on FreeBSD and Linux).
Prints out a few tables of zone names for use in translations.
"""
def scrape_file(file, regionset, zoneset):
for line in file.readlines():
if line.startswith("#"):
continue
parts = line.split("\t")
if len(parts) < 3:
continue
zoneid = parts[2]
if not "/" in zoneid:
continue
region, zone = zoneid.split("/", 1)
zone = zone.strip().replace("_", " ")
regionset.add(region)
assert(zone not in zoneset)
zoneset.add(zone)
def write_set(file, label, set):
file.write("/* This returns a reference to local, which is a terrible idea.\n * Good thing it's not meant to be compiled.\n */\n")
# Note {{ is an escaped { for Python string formatting
file.write("static const QStringList& {!s}_table()\n{{\n\treturn QStringList {{\n".format(label))
for x in sorted(set):
file.write("""\t\tQObject::tr("{!s}", "{!s}"),\n""".format(x, label))
file.write("\t\tQString()\n\t};\n}\n\n")
cpp_header_comment = """/* GENERATED FILE DO NOT EDIT
*
* === This file is part of Calamares - <https://github.com/calamares> ===
*
* This file is derived from zone.tab, which has its own copyright statement:
*
* This file is in the public domain, so clarified as of
* 2009-05-17 by Arthur David Olson.
*
* From Paul Eggert (2018-06-27):
* This file is intended as a backward-compatibility aid for older programs.
* New programs should use zone1970.tab. This file is like zone1970.tab (see
* zone1970.tab's comments), but with the following additional restrictions:
*
* 1. This file contains only ASCII characters.
* 2. The first data column contains exactly one country code.
*
*/
/** THIS FILE EXISTS ONLY FOR TRANSLATIONS PURPOSES **/
// *INDENT-OFF*
// clang-format off
"""
if __name__ == "__main__":
regions=set()
zones=set()
with open("/usr/share/zoneinfo/zone.tab", "r") as f:
scrape_file(f, regions, zones)
with open("ZoneData_p.cpp", "w") as f:
f.write(cpp_header_comment)
write_set(f, "tz_regions", regions)
write_set(f, "tz_names", zones)

View File

@ -25,15 +25,14 @@
#include <QEvent>
#include <QTranslator>
namespace CalamaresUtils
/** @brief Helper class for loading translations
*
* This is used by the loadSingletonTranslator() function to hand off
* work to translation-type specific code.
*/
struct TranslationLoader
{
static QTranslator* s_brandingTranslator = nullptr;
static QTranslator* s_translator = nullptr;
static QString s_translatorLocaleName;
void
installTranslator( const QLocale& locale, const QString& brandingTranslationsPrefix, QObject* parent )
static QString mungeLocaleName( const QLocale& locale )
{
QString localeName = locale.name();
localeName.replace( "-", "_" );
@ -50,65 +49,132 @@ installTranslator( const QLocale& locale, const QString& brandingTranslationsPre
{
localeName = QStringLiteral( "sr@latin" );
}
return localeName;
}
cDebug() << "Looking for translations for" << localeName;
QTranslator* translator = nullptr;
// Branding translations
if ( !brandingTranslationsPrefix.isEmpty() )
TranslationLoader( const QLocale& locale )
: m_locale( locale )
, m_localeName( mungeLocaleName( locale ) )
{
QString brandingTranslationsDirPath( brandingTranslationsPrefix );
brandingTranslationsDirPath.truncate( brandingTranslationsPrefix.lastIndexOf( QDir::separator() ) );
}
virtual ~TranslationLoader() {};
/// @brief Loads @p translator with the specific translations of this type
virtual bool tryLoad( QTranslator* translator ) = 0;
const QLocale& m_locale;
QString m_localeName;
};
struct BrandingLoader : public TranslationLoader
{
BrandingLoader( const QLocale& locale, const QString& prefix )
: TranslationLoader( locale )
, m_prefix( prefix )
{
}
bool tryLoad( QTranslator* translator ) override
{
if ( m_prefix.isEmpty() )
{
return false;
}
QString brandingTranslationsDirPath( m_prefix );
brandingTranslationsDirPath.truncate( m_prefix.lastIndexOf( QDir::separator() ) );
QDir brandingTranslationsDir( brandingTranslationsDirPath );
if ( brandingTranslationsDir.exists() )
{
QString filenameBase( brandingTranslationsPrefix );
filenameBase.remove( 0, brandingTranslationsPrefix.lastIndexOf( QDir::separator() ) + 1 );
translator = new QTranslator( parent );
if ( translator->load( locale, filenameBase, "_", brandingTranslationsDir.absolutePath() ) )
QString filenameBase( m_prefix );
filenameBase.remove( 0, m_prefix.lastIndexOf( QDir::separator() ) + 1 );
if ( translator->load( m_locale, filenameBase, "_", brandingTranslationsDir.absolutePath() ) )
{
cDebug() << Logger::SubEntry << "Branding using locale:" << localeName;
cDebug() << Logger::SubEntry << "Branding using locale:" << m_localeName;
return true;
}
else
{
cDebug() << Logger::SubEntry << "Branding using default, system locale not found:" << localeName;
translator->load( brandingTranslationsPrefix + "en" );
cDebug() << Logger::SubEntry << "Branding using default, system locale not found:" << m_localeName;
// TODO: this loads something completely different
return translator->load( m_prefix + "en" );
}
}
return false;
}
if ( s_brandingTranslator )
QString m_prefix;
};
struct CalamaresLoader : public TranslationLoader
{
QCoreApplication::removeTranslator( s_brandingTranslator );
delete s_brandingTranslator;
}
using TranslationLoader::TranslationLoader;
QCoreApplication::installTranslator( translator );
s_brandingTranslator = translator;
}
}
// Calamares translations
translator = new QTranslator( parent );
if ( translator->load( QString( ":/lang/calamares_" ) + localeName ) )
bool tryLoad( QTranslator* translator ) override
{
cDebug() << Logger::SubEntry << "Calamares using locale:" << localeName;
if ( translator->load( QString( ":/lang/calamares_" ) + m_localeName ) )
{
cDebug() << Logger::SubEntry << "Calamares using locale:" << m_localeName;
return true;
}
else
{
cDebug() << Logger::SubEntry << "Calamares using default, system locale not found:" << localeName;
translator->load( QString( ":/lang/calamares_en" ) );
cDebug() << Logger::SubEntry << "Calamares using default, system locale not found:" << m_localeName;
return translator->load( QString( ":/lang/calamares_en" ) );
}
}
};
if ( s_translator )
struct TZLoader : public TranslationLoader
{
QCoreApplication::removeTranslator( s_translator );
delete s_translator;
using TranslationLoader::TranslationLoader;
bool tryLoad( QTranslator* translator ) override
{
if ( translator->load( QString( ":/lang/tz_" ) + m_localeName ) )
{
cDebug() << Logger::SubEntry << "Calamares Timezones using locale:" << m_localeName;
return true;
}
else
{
cDebug() << Logger::SubEntry
<< "Calamares Timezones using default, system locale not found:" << m_localeName;
return translator->load( QString( ":/lang/tz_en" ) );
}
}
};
static void
loadSingletonTranslator( TranslationLoader&& loader, QTranslator*& translator_p )
{
QTranslator* translator = new QTranslator();
loader.tryLoad( translator );
if ( translator_p )
{
QCoreApplication::removeTranslator( translator_p );
delete translator_p;
}
QCoreApplication::installTranslator( translator );
s_translator = translator;
translator_p = translator;
}
s_translatorLocaleName = localeName;
namespace CalamaresUtils
{
static QTranslator* s_brandingTranslator = nullptr;
static QTranslator* s_translator = nullptr;
static QTranslator* s_tztranslator = nullptr;
static QString s_translatorLocaleName;
void
installTranslator( const QLocale& locale, const QString& brandingTranslationsPrefix, QObject* parent )
{
loadSingletonTranslator( BrandingLoader( locale, brandingTranslationsPrefix ), s_brandingTranslator );
loadSingletonTranslator( TZLoader( locale ), s_tztranslator );
CalamaresLoader l( locale ); // because we want the extracted localeName
loadSingletonTranslator( std::move( l ), s_translator );
s_translatorLocaleName = l.m_localeName;
}

View File

@ -44,6 +44,12 @@
#include <algorithm>
static const char mustAccept[] = "#acceptFrame { border: 1px solid red;"
"background-color: #fff6f6;"
"border-radius: 4px;"
"padding: 2px; }";
static const char okAccept[] = "#acceptFrame { padding: 3px }";
const NamedEnumTable< LicenseEntry::Type >&
LicenseEntry::typeNames()
{
@ -104,13 +110,8 @@ LicensePage::LicensePage( QWidget* parent )
ui->mainText->setWordWrap( true );
ui->mainText->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum );
ui->additionalText->setWordWrap( true );
ui->acceptFrame->setFrameStyle( QFrame::NoFrame | QFrame::Plain );
ui->acceptFrame->setStyleSheet( "#acceptFrame { border: 1px solid red;"
"background-color: #fff6f6;"
"border-radius: 4px;"
"padding: 2px; }" );
ui->acceptFrame->setStyleSheet( mustAccept );
ui->acceptFrame->layout()->setMargin( CalamaresUtils::defaultFontHeight() / 2 );
updateGlobalStorage( false ); // Have not agreed yet
@ -136,6 +137,7 @@ LicensePage::setEntries( const QList< LicenseEntry >& entriesList )
m_entries.append( w );
m_allLicensesOptional &= !entry.isRequired();
}
ui->licenseEntriesLayout->addSpacerItem( new QSpacerItem( 10, 10, QSizePolicy::Minimum, QSizePolicy::Expanding ) );
ui->acceptCheckBox->setChecked( false );
checkAcceptance( false );
@ -154,7 +156,8 @@ LicensePage::retranslate()
ui->mainText->setText( tr( "This setup procedure will install proprietary "
"software that is subject to licensing terms." )
+ br + review );
ui->additionalText->setText( tr( "If you do not agree with the terms, the setup procedure cannot continue." ) );
QString mustAcceptText( tr( "If you do not agree with the terms, the setup procedure cannot continue." ) );
ui->acceptCheckBox->setToolTip( mustAcceptText );
}
else
{
@ -163,8 +166,9 @@ LicensePage::retranslate()
"in order to provide additional features and enhance the user "
"experience." )
+ br + review );
ui->additionalText->setText( tr( "If you do not agree with the terms, proprietary software will not "
QString okAcceptText( tr( "If you do not agree with the terms, proprietary software will not "
"be installed, and open source alternatives will be used instead." ) );
ui->acceptCheckBox->setToolTip( okAcceptText );
}
ui->retranslateUi( this );
@ -195,14 +199,11 @@ LicensePage::checkAcceptance( bool checked )
m_isNextEnabled = checked || m_allLicensesOptional;
if ( !m_isNextEnabled )
{
ui->acceptFrame->setStyleSheet( "#acceptFrame { border: 1px solid red;"
"background-color: #fff8f8;"
"border-radius: 4px;"
"padding: 2px; }" );
ui->acceptFrame->setStyleSheet( mustAccept );
}
else
{
ui->acceptFrame->setStyleSheet( "#acceptFrame { padding: 3px }" );
ui->acceptFrame->setStyleSheet( okAccept );
}
emit nextStatusChanged( m_isNextEnabled );
}

View File

@ -15,7 +15,7 @@
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,0,0,0,0,0,0">
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,0,0,0,0,0">
<item>
<widget class="QLabel" name="titleLabel">
<property name="text">
@ -87,7 +87,7 @@
<x>0</x>
<y>0</y>
<width>765</width>
<height>81</height>
<height>89</height>
</rect>
</property>
<layout class="QVBoxLayout" name="licenseEntriesLayout"/>
@ -107,22 +107,6 @@
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="additionalText">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string notr="true"/>
</property>
<property name="text">
<string notr="true">&lt;additionalText&gt;</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="spacing">

View File

@ -27,13 +27,9 @@
#include <QFile>
#include <QHBoxLayout>
#include <QLabel>
#include <QToolButton>
#include <QPushButton>
#include <QVBoxLayout>
static constexpr const auto ArrowOpenExternalLink = Qt::RightArrow;
static constexpr const auto ArrowLocalLicenseIsCollapsed = Qt::UpArrow;
static constexpr const auto ArrowLocalLicenseIsExpanded = Qt::DownArrow;
static QString
loadLocalFile( const QUrl& u )
{
@ -56,9 +52,9 @@ LicenseWidget::LicenseWidget( LicenseEntry entry, QWidget* parent )
: QWidget( parent )
, m_entry( std::move( entry ) )
, m_label( new QLabel( this ) )
, m_viewLicenseLabel( new QLabel( this ) )
, m_expandLicenseButton( nullptr )
, m_fullText( nullptr )
, m_viewLicenseButton( new QPushButton( this ) )
, m_licenceTextLabel( new QLabel( this ) )
, m_isExpanded( m_entry.expandByDefault() )
{
QPalette pal( palette() );
pal.setColor( QPalette::Background, palette().window().color().lighter( 108 ) );
@ -70,53 +66,40 @@ LicenseWidget::LicenseWidget( LicenseEntry entry, QWidget* parent )
setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum );
setContentsMargins( 4, 4, 4, 4 );
QVBoxLayout* vLayout = new QVBoxLayout;
QWidget* topPart = new QWidget( this );
topPart->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
vLayout->addWidget( topPart );
QHBoxLayout* wiLayout = new QHBoxLayout;
topPart->setLayout( wiLayout );
m_label->setWordWrap( true );
m_label->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Minimum );
m_label->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
wiLayout->addWidget( m_label );
m_viewLicenseLabel->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred );
m_viewLicenseLabel->setAlignment( Qt::AlignVCenter | Qt::AlignRight );
wiLayout->addWidget( m_viewLicenseLabel );
wiLayout->addSpacing( 10 );
m_viewLicenseButton->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed );
wiLayout->addWidget( m_viewLicenseButton );
m_licenceTextLabel->setStyleSheet( "border-top: 1px solid black; margin-top: 0px; padding-top: 1em;" );
m_licenceTextLabel->setObjectName( "licenseItemFullText" );
m_expandLicenseButton = new QToolButton( this );
wiLayout->addWidget( m_expandLicenseButton );
if ( m_entry.isLocal() )
{
QVBoxLayout* vLayout = new QVBoxLayout;
m_expandLicenseButton->setArrowType( ArrowLocalLicenseIsCollapsed );
connect( m_expandLicenseButton, &QAbstractButton::clicked, this, &LicenseWidget::expandClicked );
vLayout->addLayout( wiLayout );
m_fullText = new QLabel( this );
m_fullText->setText( loadLocalFile( m_entry.m_url ) );
m_fullText->hide();
m_fullText->setStyleSheet( "border-top: 1px solid black; margin-top: 1em; padding-top: 1em;" );
m_fullText->setObjectName( "licenseItemFullText" );
vLayout->addWidget( m_fullText );
setLayout( vLayout );
if ( m_entry.expandByDefault() )
{
// Since we started in a collapsed state, toggle it to expand.
// This can only be done once the full text has been added.
expandClicked();
}
m_fullTextContents = loadLocalFile( m_entry.m_url );
showLocalLicenseText();
connect( m_viewLicenseButton, &QAbstractButton::clicked, this, &LicenseWidget::expandClicked );
}
else
{
m_expandLicenseButton->setArrowType( ArrowOpenExternalLink );
connect( m_expandLicenseButton, &QAbstractButton::clicked, this, &LicenseWidget::viewClicked );
// Normally setOpenExternalLinks( true ) would do, but we need the
// open code anyway for the toolbutton, let's share it.
connect( m_viewLicenseLabel, &QLabel::linkActivated, this, &LicenseWidget::viewClicked );
setLayout( wiLayout ); // Only the horizontal layout needed
m_licenceTextLabel->setText( tr( "URL: %1" ).arg( m_entry.m_url.toDisplayString() ) );
connect( m_viewLicenseButton, &QAbstractButton::clicked, this, &LicenseWidget::viewClicked );
}
m_licenceTextLabel->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
vLayout->addWidget( m_licenceTextLabel );
setLayout( vLayout );
retranslateUi();
}
@ -172,21 +155,31 @@ LicenseWidget::retranslateUi()
}
void
LicenseWidget::expandClicked()
LicenseWidget::showLocalLicenseText()
{
if ( m_expandLicenseButton->arrowType() == ArrowLocalLicenseIsExpanded )
if ( m_isExpanded )
{
m_expandLicenseButton->setArrowType( ArrowLocalLicenseIsCollapsed );
m_licenceTextLabel->setText( m_fullTextContents );
}
else
{
m_expandLicenseButton->setArrowType( ArrowLocalLicenseIsExpanded );
QString fileName = m_entry.m_url.toDisplayString();
if ( fileName.startsWith( "file:" ) )
{
fileName = fileName.remove( 0, 5 );
}
m_licenceTextLabel->setText( tr( "File: %1" ).arg( fileName ) );
}
}
// Show/hide based on the new arrow direction.
if ( m_fullText )
void
LicenseWidget::expandClicked()
{
m_fullText->setHidden( m_expandLicenseButton->arrowType() == ArrowLocalLicenseIsCollapsed );
m_isExpanded = !m_isExpanded;
// Show/hide based on the new arrow direction.
if ( !m_fullTextContents.isEmpty() )
{
showLocalLicenseText();
}
updateExpandToolTip();
@ -198,17 +191,11 @@ LicenseWidget::updateExpandToolTip()
{
if ( m_entry.isLocal() )
{
const bool isNowCollapsed = m_expandLicenseButton->arrowType() == ArrowLocalLicenseIsCollapsed;
m_expandLicenseButton->setToolTip( isNowCollapsed ? tr( "Shows the complete license text" )
: tr( "Hide license text" ) );
m_viewLicenseLabel->setText( isNowCollapsed ? tr( "Show license agreement" ) : tr( "Hide license agreement" ) );
m_viewLicenseButton->setText( m_isExpanded ? tr( "Hide license text" ) : tr( "Show the license text" ) );
}
else
{
m_expandLicenseButton->setToolTip( tr( "Opens the license agreement in a browser window." ) );
m_viewLicenseLabel->setText(
tr( "<a href=\"%1\">View license agreement</a>" ).arg( m_entry.m_url.toString() ) );
m_viewLicenseButton->setText( tr( "Open license agreement in browser." ) );
}
}

View File

@ -27,7 +27,7 @@
#include <QLabel>
#include <QWidget>
class QToolButton;
class QPushButton;
class LicenseWidget : public QWidget
{
@ -38,14 +38,16 @@ public:
void retranslateUi();
private:
void showLocalLicenseText(); // Display (or hide) the local license text
void expandClicked(); // "slot" to toggle show/hide of local license text
void viewClicked(); // "slot" to open link
void updateExpandToolTip();
LicenseEntry m_entry;
QLabel* m_label;
QLabel* m_viewLicenseLabel;
QToolButton* m_expandLicenseButton;
QLabel* m_fullText;
QPushButton* m_viewLicenseButton;
QLabel* m_licenceTextLabel;
QString m_fullTextContents;
bool m_isExpanded;
};
#endif

View File

@ -28,6 +28,7 @@
#include "Settings.h"
#include "locale/Label.h"
#include "locale/TimeZone.h"
#include "utils/CalamaresUtilsGui.h"
#include "utils/Logger.h"
#include "utils/Retranslator.h"
@ -41,6 +42,8 @@
LocalePage::LocalePage( QWidget* parent )
: QWidget( parent )
, m_blockTzWidgetSet( false )
, m_regionList( CalamaresUtils::Locale::TZRegion::fromZoneTab() )
, m_regionModel( std::make_unique< CalamaresUtils::Locale::CStringListModel >( m_regionList ) )
{
QBoxLayout* mainLayout = new QVBoxLayout;
@ -109,7 +112,10 @@ LocalePage::LocalePage( QWidget* parent )
}
LocalePage::~LocalePage() {}
LocalePage::~LocalePage()
{
qDeleteAll( m_regionList );
}
void
@ -127,42 +133,16 @@ LocalePage::updateLocaleLabels()
m_formatsLabel->setText( labels.second );
}
static inline bool
containsLocation( const QList< LocaleGlobal::Location >& locations, const QString& zone )
{
for ( const LocaleGlobal::Location& location : locations )
{
if ( location.zone == zone )
{
return true;
}
}
return false;
}
void
LocalePage::init( const QString& initialRegion, const QString& initialZone, const QString& localeGenPath )
{
m_regionCombo->blockSignals( true );
m_zoneCombo->blockSignals( true );
// Setup locations
QHash< QString, QList< LocaleGlobal::Location > > regions = LocaleGlobal::getLocations();
QStringList keys = regions.keys();
keys.sort();
foreach ( const QString& key, keys )
{
m_regionCombo->addItem( LocaleGlobal::Location::pretty( key ), key );
}
m_regionCombo->blockSignals( false );
m_zoneCombo->blockSignals( false );
using namespace CalamaresUtils::Locale;
m_regionCombo->setModel( m_regionModel.get() );
m_regionCombo->currentIndexChanged( m_regionCombo->currentIndex() );
if ( keys.contains( initialRegion ) && containsLocation( regions.value( initialRegion ), initialZone ) )
auto* region = m_regionList.find< TZRegion >( initialRegion );
if ( region && region->zones().find< TZZone >( initialZone ) )
{
m_tzWidget->setCurrentLocation( initialRegion, initialZone );
}
@ -170,7 +150,6 @@ LocalePage::init( const QString& initialRegion, const QString& initialZone, cons
{
m_tzWidget->setCurrentLocation( "America", "New_York" );
}
emit m_tzWidget->locationChanged( m_tzWidget->getCurrentLocation() );
// 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
@ -301,13 +280,13 @@ LocalePage::prettyStatus() const
}
QList< Calamares::job_ptr >
Calamares::JobList
LocalePage::createJobs()
{
QList< Calamares::job_ptr > list;
LocaleGlobal::Location location = m_tzWidget->getCurrentLocation();
const CalamaresUtils::Locale::TZZone* location = m_tzWidget->currentLocation();
Calamares::Job* j = new SetTimezoneJob( location.region, location.zone );
Calamares::Job* j = new SetTimezoneJob( location->region(), location->zone() );
list.append( Calamares::job_ptr( j ) );
return list;
@ -340,7 +319,7 @@ LocaleConfiguration
LocalePage::guessLocaleConfiguration() const
{
return LocaleConfiguration::fromLanguageAndLocation(
QLocale().name(), m_localeGenLines, m_tzWidget->getCurrentLocation().country );
QLocale().name(), m_localeGenLines, m_tzWidget->currentLocation()->country() );
}
@ -358,12 +337,12 @@ LocalePage::updateGlobalStorage()
{
auto* gs = Calamares::JobQueue::instance()->globalStorage();
LocaleGlobal::Location location = m_tzWidget->getCurrentLocation();
bool locationChanged
= ( location.region != gs->value( "locationRegion" ) ) || ( location.zone != gs->value( "locationZone" ) );
const auto* location = m_tzWidget->currentLocation();
bool locationChanged = ( location->region() != gs->value( "locationRegion" ) )
|| ( location->zone() != gs->value( "locationZone" ) );
gs->insert( "locationRegion", location.region );
gs->insert( "locationZone", location.zone );
gs->insert( "locationRegion", location->region() );
gs->insert( "locationZone", location->zone() );
updateGlobalLocale();
@ -373,7 +352,7 @@ LocalePage::updateGlobalStorage()
if ( locationChanged && Calamares::Settings::instance()->doChroot() )
{
QProcess::execute( "timedatectl", // depends on systemd
{ "set-timezone", location.region + '/' + location.zone } );
{ "set-timezone", location->region() + '/' + location->zone() } );
}
#endif
@ -402,31 +381,23 @@ LocalePage::updateGlobalStorage()
updateLocaleLabels();
}
void
LocalePage::regionChanged( int currentIndex )
{
using namespace CalamaresUtils::Locale;
Q_UNUSED( currentIndex )
QHash< QString, QList< LocaleGlobal::Location > > regions = LocaleGlobal::getLocations();
if ( !regions.contains( m_regionCombo->currentData().toString() ) )
QString selectedRegion = m_regionCombo->currentData().toString();
TZRegion* region = m_regionList.find< TZRegion >( selectedRegion );
if ( !region )
{
return;
}
m_zoneCombo->blockSignals( true );
m_zoneCombo->clear();
const QList< LocaleGlobal::Location > zones = regions.value( m_regionCombo->currentData().toString() );
for ( const LocaleGlobal::Location& zone : zones )
{
m_zoneCombo->addItem( LocaleGlobal::Location::pretty( zone.zone ), zone.zone );
}
m_zoneCombo->model()->sort( 0 );
m_zoneCombo->setModel( new CStringListModel( region->zones() ) );
m_zoneCombo->blockSignals( false );
m_zoneCombo->currentIndexChanged( m_zoneCombo->currentIndex() );
}
@ -442,12 +413,12 @@ LocalePage::zoneChanged( int currentIndex )
}
void
LocalePage::locationChanged( LocaleGlobal::Location location )
LocalePage::locationChanged( const CalamaresUtils::Locale::TZZone* location )
{
m_blockTzWidgetSet = true;
// Set region index
int index = m_regionCombo->findData( location.region );
int index = m_regionCombo->findData( location->region() );
if ( index < 0 )
{
return;
@ -456,7 +427,7 @@ LocalePage::locationChanged( LocaleGlobal::Location location )
m_regionCombo->setCurrentIndex( index );
// Set zone index
index = m_zoneCombo->findData( location.zone );
index = m_zoneCombo->findData( location->zone() );
if ( index < 0 )
{
return;

View File

@ -24,9 +24,12 @@
#include "timezonewidget/localeglobal.h"
#include "Job.h"
#include "locale/TimeZone.h"
#include <QWidget>
#include <memory>
class QComboBox;
class QLabel;
class QPushButton;
@ -67,10 +70,14 @@ private:
void regionChanged( int currentIndex );
void zoneChanged( int currentIndex );
void locationChanged( LocaleGlobal::Location location );
void locationChanged( const CalamaresUtils::Locale::TZZone* location );
void changeLocale();
void changeFormats();
// Dynamically, QList< TZRegion* >
CalamaresUtils::Locale::CStringPairList m_regionList;
std::unique_ptr< CalamaresUtils::Locale::CStringListModel > m_regionModel;
TimeZoneWidget* m_tzWidget;
QComboBox* m_regionCombo;
QComboBox* m_zoneCombo;

View File

@ -142,7 +142,7 @@ LocaleViewStep::isAtEnd() const
}
QList< Calamares::job_ptr >
Calamares::JobList
LocaleViewStep::jobs() const
{
return m_jobs;
@ -163,12 +163,9 @@ LocaleViewStep::onActivate()
void
LocaleViewStep::onLeave()
{
m_jobs.clear();
if ( m_actualWidget )
{
m_jobs.append( m_actualWidget->createJobs() );
m_jobs = m_actualWidget->createJobs();
m_prettyStatus = m_actualWidget->prettyStatus();
auto map = m_actualWidget->localesMap();
@ -182,6 +179,7 @@ LocaleViewStep::onLeave()
}
else
{
m_jobs.clear();
Calamares::JobQueue::instance()->globalStorage()->remove( "localeConf" );
}
}

View File

@ -33,7 +33,6 @@
#include <memory>
class LocalePage;
class WaitingWidget;
class PLUGINDLLEXPORT LocaleViewStep : public Calamares::ViewStep
{
@ -54,7 +53,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;
@ -78,7 +77,7 @@ private:
CalamaresUtils::GeoIP::RegionZonePair m_startingTimezone;
QString m_localeGenPath;
QList< Calamares::job_ptr > m_jobs;
Calamares::JobList m_jobs;
std::unique_ptr< CalamaresUtils::GeoIP::Handler > m_geoip;
};

View File

@ -1,32 +0,0 @@
/* === This file is part of Calamares - <https://github.com/calamares> ===
*
* Copyright 2014, Teo Mrnjavac <teo@kde.org>
*
* Originally from the Manjaro Installation Framework
* by Roland Singer <roland@manjaro.org>
* Copyright (C) 2007 Free Software Foundation, Inc.
*
* 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 LOCALECONST_H
#define LOCALECONST_H
#define LOCALESDIR "/usr/share/i18n/locales"
#define TZ_DATA_FILE "/usr/share/zoneinfo/zone.tab"
#define USER_IMAGES_PATH "/usr/share/pixmaps/faces"
#endif // LOCALECONST_H

View File

@ -22,6 +22,8 @@
#include "localeglobal.h"
#include "locale/TimeZone.h"
#include <QTimeZone>
//###
@ -29,7 +31,6 @@
//###
QHash< QString, QHash< QString, QList< LocaleGlobal::Locale > > > LocaleGlobal::locales;
QHash<QString, QList<LocaleGlobal::Location> > LocaleGlobal::locations;
//###
@ -37,61 +38,43 @@ QHash<QString, QList<LocaleGlobal::Location> > LocaleGlobal::locations;
//###
QString
LocaleGlobal::Location::pretty( const QString& s )
{
return QString( s ).replace( '_', ' ' ).simplified();
}
QString
LocaleGlobal::Location::comment() const
{
QTimeZone qtz = QTimeZone( QString( "%1/%2" )
.arg( region )
.arg( zone ).toLatin1() );
return qtz.comment();
}
void
LocaleGlobal::init() {
LocaleGlobal::init()
{
// TODO: Error handling
initLocales();
initLocations();
}
QHash< QString, QHash< QString, QList< LocaleGlobal::Locale > > >
LocaleGlobal::getLocales() {
LocaleGlobal::getLocales()
{
return locales;
}
QHash< QString, QList< LocaleGlobal::Location > >
LocaleGlobal::getLocations() {
return locations;
}
//###
//### Private methods
//###
void
LocaleGlobal::initLocales() {
LocaleGlobal::initLocales()
{
static const char LOCALESDIR[] = "/usr/share/i18n/locales";
locales.clear();
QStringList files = QDir( LOCALESDIR ).entryList( QDir::Files, QDir::Name );
for (int i = 0; i < files.size(); ++i) {
for ( int i = 0; i < files.size(); ++i )
{
QString filename = files.at( i );
QFile file( QString( LOCALESDIR ) + "/" + filename );
if ( !file.open( QIODevice::ReadOnly | QIODevice::Text ) )
{
continue;
}
QTextStream in( &file );
QString commentChar = "%";
@ -100,95 +83,44 @@ LocaleGlobal::initLocales() {
locale.locale = filename;
while (!in.atEnd()) {
while ( !in.atEnd() )
{
QString line = in.readLine().trimmed();
QStringList split = line.split(commentChar, QString::KeepEmptyParts).first().split(QRegExp(" (?=[^\"]*(\"[^\"]*\"[^\"]*)*$)"), QString::SkipEmptyParts);
QStringList split = line.split( commentChar, QString::KeepEmptyParts )
.first()
.split( QRegExp( " (?=[^\"]*(\"[^\"]*\"[^\"]*)*$)" ), QString::SkipEmptyParts );
if ( split.size() < 2 )
{
continue;
}
QString sub1 = QString( split.at( 0 ) ).remove( "\"" );
QString sub2 = QString( split.at( 1 ) ).remove( "\"" );
if ( sub1 == "comment_char" )
{
commentChar = sub2;
}
else if ( sub1 == "title" )
{
locale.description = sub2;
}
else if ( sub1 == "territory" )
{
territory = sub2;
}
else if ( sub1 == "language" )
{
lang = sub2;
}
}
if ( lang.isEmpty() || territory.isEmpty() )
{
continue;
}
locales[ lang ][ territory ].append( locale );
}
}
void
LocaleGlobal::initLocations() {
locations.clear();
QFile file(TZ_DATA_FILE);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
return;
QTextStream in(&file);
while (!in.atEnd()) {
QString line = in.readLine().trimmed().split('#', QString::KeepEmptyParts).first().trimmed();
if (line.isEmpty())
continue;
QStringList list = line.split(QRegExp("[\t ]"), QString::SkipEmptyParts);
if (list.size() < 3)
continue;
Location location;
QStringList timezoneParts = list.at(2).split('/', QString::SkipEmptyParts);
int cooSplitPos = QString(list.at(1)).remove(0, 1).indexOf(QRegExp("[-+]")) + 1;
if (timezoneParts.size() < 2)
continue;
QString countryCode = list.at(0).trimmed();
if (countryCode.size() != 2)
continue;
location.region = timezoneParts.takeFirst();
location.zone = timezoneParts.join( '/' );
location.latitude = getRightGeoLocation(list.at(1).mid(0, cooSplitPos));
location.longitude = getRightGeoLocation(list.at(1).mid(cooSplitPos));
location.country = countryCode;
locations[location.region].append(location);
}
}
double
LocaleGlobal::getRightGeoLocation(QString str) {
double sign = 1, num = 0.00;
// Determind sign
if (str.startsWith('-')) {
sign = -1;
str.remove(0, 1);
}
else if (str.startsWith('+')) {
str.remove(0, 1);
}
if (str.length() == 4 || str.length() == 6)
num = str.mid(0, 2).toDouble() + str.mid(2, 2).toDouble() / 60;
else if (str.length() == 5 || str.length() == 7)
num = str.mid(0, 3).toDouble() + str.mid(3, 2).toDouble() / 60;
return sign * num;
}

View File

@ -24,17 +24,24 @@
#ifndef LOCALEGLOBAL_H
#define LOCALEGLOBAL_H
#include <QString>
#include <QFile>
#include <QTextStream>
#include <QDebug>
#include <QDir>
#include <QStringList>
#include <QList>
#include <QFile>
#include <QHash>
#include <QList>
#include <QMap>
#include <QRegExp>
#include <QDebug>
#include "localeconst.h"
#include <QString>
#include <QStringList>
#include <QTextStream>
namespace CalamaresUtils
{
namespace Locale
{
class TZZone;
}
} // namespace CalamaresUtils
class LocaleGlobal
{
@ -44,30 +51,13 @@ public:
QString description, locale;
};
struct Location
{
QString region, zone, country;
double latitude, longitude;
static QString pretty( const QString& s );
QString comment() const;
};
static void init();
static QHash< QString, QHash< QString, QList< LocaleGlobal::Locale > > > getLocales();
static QHash<QString, QList<LocaleGlobal::Location> > getLocations();
private:
static QHash< QString, QHash< QString, QList< LocaleGlobal::Locale > > > locales;
static QHash<QString, QList<LocaleGlobal::Location> > locations;
static void initLocales();
static void initLocations();
static double getRightGeoLocation( QString str );
};
inline QDebug& operator <<( QDebug& s, const LocaleGlobal::Location& l )
{
return s << l.region << '/' << l.zone << '(' << l.country << ") @N" << l.latitude << 'E' << l.longitude;
}
#endif // LOCALEGLOBAL_H

View File

@ -1,7 +1,7 @@
/* === This file is part of Calamares - <https://github.com/calamares> ===
*
* Copyright 2014-2015, Teo Mrnjavac <teo@kde.org>
* Copyright 2017-2018, Adriaan de Groot <groot@kde.org>
* Copyright 2017-2019, Adriaan de Groot <groot@kde.org>
*
* Originally from the Manjaro Installation Framework
* by Roland Singer <roland@manjaro.org>
@ -23,10 +23,13 @@
#include <cmath>
#include "locale/TimeZone.h"
#include "utils/Logger.h"
#include "timezonewidget.h"
// Pixel value indicating that a spot is outside of a zone
#define RGB_TRANSPARENT 0
static constexpr double MAP_Y_OFFSET = 0.125;
static constexpr double MAP_X_OFFSET = -0.0370;
@ -37,8 +40,8 @@ constexpr static double MATH_PI = 3.14159265;
constexpr static QLatin1String ZONE_NAME( "zone" );
#endif
TimeZoneWidget::TimeZoneWidget( QWidget* parent ) :
QWidget( parent )
TimeZoneWidget::TimeZoneWidget( QWidget* parent )
: QWidget( parent )
{
setMouseTracking( false );
setCursor( Qt::PointingHandCursor );
@ -48,54 +51,67 @@ TimeZoneWidget::TimeZoneWidget( QWidget* parent ) :
font.setBold( false );
// Images
background = QImage( ":/images/bg.png" ).scaled( X_SIZE, Y_SIZE, Qt::IgnoreAspectRatio, Qt::SmoothTransformation );
background = QImage( ":/images/bg.png" );
pin = QImage( ":/images/pin.png" );
#ifdef DEBUG_TIMEZONES
if ( background.size() != QSize( 780, 340 ) )
{
cWarning() << "Timezone background size mitsmatch" << background.size();
}
#endif
// Set size
setMinimumSize( background.size() );
setMaximumSize( background.size() );
// Zone images
QStringList zones = QString( ZONES ).split( " ", QString::SkipEmptyParts );
for ( int i = 0; i < zones.size(); ++i )
for ( const auto* zoneName :
{ "0.0", "1.0", "2.0", "3.0", "3.5", "4.0", "4.5", "5.0", "5.5", "5.75", "6.0", "6.5", "7.0",
"8.0", "9.0", "9.5", "10.0", "10.5", "11.0", "11.5", "12.0", "12.75", "13.0", "-1.0", "-2.0", "-3.0",
"-3.5", "-4.0", "-4.5", "-5.0", "-5.5", "-6.0", "-7.0", "-8.0", "-9.0", "-9.5", "-10.0", "-11.0" } )
{
timeZoneImages.append( QImage( ":/images/timezone_" + zones.at( i ) + ".png" ).scaled( X_SIZE, Y_SIZE, Qt::IgnoreAspectRatio, Qt::SmoothTransformation ) );
timeZoneImages.append( QImage( QStringLiteral( ":/images/timezone_" ) + zoneName + ".png" ) );
#ifdef DEBUG_TIMEZONES
timeZoneImages.last().setText( ZONE_NAME, zones.at( i ) );
if ( timeZoneImages.last().size() != background.size() )
{
cWarning() << "Timezone image size mismatch" << zoneName << timeZoneImages.last().size();
}
timeZoneImages.last().setText( ZONE_NAME, zoneName );
#endif
}
}
void TimeZoneWidget::setCurrentLocation( QString region, QString zone )
void
TimeZoneWidget::setCurrentLocation( QString regionName, QString zoneName )
{
using namespace CalamaresUtils::Locale;
const auto& regions = TZRegion::fromZoneTab();
auto* region = regions.find< TZRegion >( regionName );
if ( !region )
{
QHash<QString, QList<LocaleGlobal::Location> > hash = LocaleGlobal::getLocations();
if ( !hash.contains( region ) )
return;
QList<LocaleGlobal::Location> locations = hash.value( region );
for ( int i = 0; i < locations.size(); ++i )
{
if ( locations.at( i ).zone == zone )
{
setCurrentLocation( locations.at( i ) );
break;
}
auto* zone = region->zones().find< TZZone >( zoneName );
if ( zone )
{
setCurrentLocation( zone );
}
}
void TimeZoneWidget::setCurrentLocation( LocaleGlobal::Location location )
void
TimeZoneWidget::setCurrentLocation( const CalamaresUtils::Locale::TZZone* location )
{
currentLocation = location;
m_currentLocation = location;
// Set zone
QPoint pos = getLocationPosition( currentLocation.longitude, currentLocation.latitude );
QPoint pos = getLocationPosition( location );
#ifdef DEBUG_TIMEZONES
cDebug() << "Setting location" << location.region << location.zone << location.country;
cDebug() << Logger::SubEntry << "longitude" << location.longitude << "latitude" << location.latitude;
cDebug() << "Setting location" << location->region() << location->zone() << '(' << location->country() << '@' << location->latitude() << 'N' << location->longitude() << 'E' << ')';
cDebug() << Logger::SubEntry << "pixel x" << pos.x() << "pixel y" << pos.y();
bool found = false;
@ -119,7 +135,9 @@ void TimeZoneWidget::setCurrentLocation( LocaleGlobal::Location location )
cDebug() << Logger::SubEntry << "First zone found" << i << zone.text( ZONE_NAME );
}
else
{
cDebug() << Logger::SubEntry << "Also in zone" << i << zone.text( ZONE_NAME );
}
#else
currentZoneImage = zone;
break;
@ -129,16 +147,17 @@ void TimeZoneWidget::setCurrentLocation( LocaleGlobal::Location location )
// Repaint widget
repaint();
emit locationChanged( m_currentLocation );
}
//###
//### Private
//###
QPoint TimeZoneWidget::getLocationPosition( double longitude, double latitude )
QPoint
TimeZoneWidget::getLocationPosition( double longitude, double latitude )
{
const int width = this->width();
const int height = this->height();
@ -152,39 +171,64 @@ QPoint TimeZoneWidget::getLocationPosition( double longitude, double latitude )
// of the different cities / regions looks ok -- at least Thule ends up in the right
// country, and Inuvik isn't in the ocean.
if ( latitude > 70.0 )
{
y -= sin( MATH_PI * ( latitude - 70.0 ) / 56.0 ) * MAP_Y_OFFSET * height * 0.8;
}
if ( latitude > 74.0 )
{
y += 4;
}
if ( latitude > 69.0 )
{
y -= 2;
}
if ( latitude > 59.0 )
{
y -= 4 * int( ( latitude - 54.0 ) / 5.0 );
}
if ( latitude > 54.0 )
{
y -= 2;
}
if ( latitude > 49.0 )
{
y -= int( ( latitude - 44.0 ) / 5.0 );
}
// Far south, some stretching occurs as well, but it is less pronounced.
// Move down by 1 pixel per 5 degrees past 10 south
if ( latitude < 0 )
{
y += int( ( -latitude ) / 5.0 );
}
// Antarctica isn't shown on the map, but you could try clicking there
if ( latitude < -60 )
{
y = height - 1;
}
if ( x < 0 )
{
x = width + x;
}
if ( x >= width )
{
x -= width;
}
if ( y < 0 )
{
y = height + y;
}
if ( y >= height )
{
y -= height;
}
return QPoint( int( x ), int( y ) );
}
void TimeZoneWidget::paintEvent( QPaintEvent* )
void
TimeZoneWidget::paintEvent( QPaintEvent* )
{
const int width = this->width();
const int height = this->height();
@ -201,7 +245,7 @@ void TimeZoneWidget::paintEvent( QPaintEvent* )
painter.drawImage( 0, 0, currentZoneImage );
#ifdef DEBUG_TIMEZONES
QPoint point = getLocationPosition( currentLocation.longitude, currentLocation.latitude );
QPoint point = getLocationPosition( m_currentLocation );
// Draw latitude lines
for ( int y_lat = -50; y_lat < 80; y_lat += 5 )
{
@ -213,78 +257,95 @@ void TimeZoneWidget::paintEvent( QPaintEvent* )
int lly = latLine0.y();
for ( int c = 0; c < width; ++c )
{
painter.drawPoint( c, lly );
}
}
// Just a dot in the selected location, no label
painter.setPen( Qt::red );
painter.drawPoint( point );
#else
// Draw pin at current location
QPoint point = getLocationPosition( currentLocation.longitude, currentLocation.latitude );
QPoint point = getLocationPosition( m_currentLocation );
painter.drawImage( point.x() - pin.width() / 2, point.y() - pin.height() / 2, pin );
// Draw text and box
const int textWidth = fontMetrics.horizontalAdvance( LocaleGlobal::Location::pretty( currentLocation.zone ) );
const int textWidth = fontMetrics.horizontalAdvance( m_currentLocation ? m_currentLocation->tr() : QString() );
const int textHeight = fontMetrics.height();
QRect rect = QRect( point.x() - textWidth / 2 - 5, point.y() - textHeight - 8, textWidth + 10, textHeight - 2 );
if ( rect.x() <= 5 )
{
rect.moveLeft( 5 );
}
if ( rect.right() >= width - 5 )
{
rect.moveRight( width - 5 );
}
if ( rect.y() <= 5 )
{
rect.moveTop( 5 );
}
if ( rect.y() >= height - 5 )
{
rect.moveBottom( height - 5 );
}
painter.setPen( QPen() ); // no pen
painter.setBrush( QColor( 40, 40, 40 ) );
painter.drawRoundedRect( rect, 3, 3 );
painter.setPen( Qt::white );
painter.drawText( rect.x() + 5, rect.bottom() - 4, LocaleGlobal::Location::pretty( currentLocation.zone ) );
painter.drawText( rect.x() + 5, rect.bottom() - 4, m_currentLocation ? m_currentLocation->tr() : QString() );
#endif
painter.end();
}
void TimeZoneWidget::mousePressEvent( QMouseEvent* event )
void
TimeZoneWidget::mousePressEvent( QMouseEvent* event )
{
if ( event->button() != Qt::LeftButton )
{
return;
}
// Set nearest location
int nX = 999999, mX = event->pos().x();
int nY = 999999, mY = event->pos().y();
QHash<QString, QList<LocaleGlobal::Location> > hash = LocaleGlobal::getLocations();
QHash<QString, QList<LocaleGlobal::Location> >::iterator iter = hash.begin();
while ( iter != hash.end() )
using namespace CalamaresUtils::Locale;
const TZZone* closest = nullptr;
for ( const auto* region_p : TZRegion::fromZoneTab() )
{
QList<LocaleGlobal::Location> locations = iter.value();
for ( int i = 0; i < locations.size(); ++i )
const auto* region = dynamic_cast< const TZRegion* >( region_p );
if ( region )
{
LocaleGlobal::Location loc = locations[i];
QPoint locPos = getLocationPosition( loc.longitude, loc.latitude );
for ( const auto* zone_p : region->zones() )
{
const auto* zone = dynamic_cast< const TZZone* >( zone_p );
if ( zone )
{
QPoint locPos = getLocationPosition( zone->longitude(), zone->latitude() );
if ( ( abs( mX - locPos.x() ) + abs( mY - locPos.y() ) < abs( mX - nX ) + abs( mY - nY ) ) )
{
currentLocation = loc;
closest = zone;
nX = locPos.x();
nY = locPos.y();
}
}
++iter;
}
}
}
if ( closest )
{
// Set zone image and repaint widget
setCurrentLocation( currentLocation );
setCurrentLocation( closest );
// Emit signal
emit locationChanged( currentLocation );
emit locationChanged( m_currentLocation );
}
}

View File

@ -24,51 +24,44 @@
#ifndef TIMEZONEWIDGET_H
#define TIMEZONEWIDGET_H
#include <QWidget>
#include <QPainter>
#include <QImage>
#include <QFile>
#include <QTextStream>
#include <QList>
#include <QStringList>
#include <QMouseEvent>
#include <QFontMetrics>
#include <QFont>
#include "localeglobal.h"
#include "locale/TimeZone.h"
#define RGB_TRANSPARENT 0
#define ZONES "0.0 1.0 2.0 3.0 3.5 4.0 4.5 5.0 5.5 5.75 6.0 6.5 7.0 8.0 9.0 9.5 10.0 10.5 11.0 11.5 12.0 12.75 13.0 -1.0 -2.0 -3.0 -3.5 -4.0 -4.5 -5.0 -5.5 -6.0 -7.0 -8.0 -9.0 -9.5 -10.0 -11.0"
#define X_SIZE 780
#define Y_SIZE 340
#include <QFile>
#include <QFont>
#include <QFontMetrics>
#include <QImage>
#include <QList>
#include <QMouseEvent>
#include <QPainter>
#include <QStringList>
#include <QTextStream>
#include <QWidget>
class TimeZoneWidget : public QWidget
{
Q_OBJECT
public:
using TZZone = CalamaresUtils::Locale::TZZone;
explicit TimeZoneWidget( QWidget* parent = nullptr );
LocaleGlobal::Location getCurrentLocation()
{
return currentLocation;
}
void setCurrentLocation( QString region, QString zone );
void setCurrentLocation( LocaleGlobal::Location location );
void setCurrentLocation( const TZZone* location );
const TZZone* currentLocation() { return m_currentLocation; }
signals:
void locationChanged( LocaleGlobal::Location location );
void locationChanged( const TZZone* location );
private:
QFont font;
QImage background, pin, currentZoneImage;
QList< QImage > timeZoneImages;
LocaleGlobal::Location currentLocation;
const TZZone* m_currentLocation = nullptr; // Not owned by me
QPoint getLocationPosition( const LocaleGlobal::Location& l )
{
return getLocationPosition( l.longitude, l.latitude );
}
QPoint getLocationPosition( const TZZone* l ) { return getLocationPosition( l->longitude(), l->latitude() ); }
QPoint getLocationPosition( double longitude, double latitude );
void paintEvent( QPaintEvent* event );