[libcalamares] Add spot-patches to timezone data
- for the purposes of Calamares's nearest-location selection algorithm for timezone selection, introduce spot patches: alternate markers on the map to indicate "things close to here belong in this timezone". - hide the implementation detail in the find() methods.
This commit is contained in:
parent
028d424c73
commit
e35992cf0b
@ -183,17 +183,30 @@ loadTZData( RegionVector& regions, ZoneVector& zones, QTextStream& in )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
/** @brief Extra, fake, timezones
|
||||||
loadTZData( RegionVector& regions, ZoneVector& zones )
|
*
|
||||||
{
|
* The timezone locations in zone.tab are not always very useful,
|
||||||
QFile file( TZ_DATA_FILE );
|
* given Calamares's standard "nearest zone" algorithm: for instance,
|
||||||
if ( file.open( QIODevice::ReadOnly | QIODevice::Text ) )
|
* in most locations physically in the country of South Africa,
|
||||||
{
|
* Maseru (the capital of Lesotho, and location for timezone Africa/Maseru)
|
||||||
QTextStream in( &file );
|
* is closer than Johannesburg (the location for timezone Africa/Johannesburg).
|
||||||
loadTZData( regions, zones, in );
|
*
|
||||||
}
|
* The algorithm picks the wrong place. This is for instance annoying
|
||||||
}
|
* when clicking on Cape Town, you get Maseru, and to get Johannesburg
|
||||||
|
* you need to click somewhere very carefully north of Maserru.
|
||||||
|
*
|
||||||
|
* These alternate zones are used to introduce "extra locations"
|
||||||
|
* into the timezone database, in order to influence the closest-location
|
||||||
|
* algorithm. Lines are formatted just like in zone.tab: remember the \n
|
||||||
|
*/
|
||||||
|
static const char altZones[] =
|
||||||
|
/* This extra zone is north-east of Karoo National park,
|
||||||
|
* and means that Western Cape province and a good chunk of
|
||||||
|
* Northern- and Eastern- Cape provinces get pulled in to Johannesburg.
|
||||||
|
* Bloemfontein is still closer to Maseru than either correct zone,
|
||||||
|
* but this is a definite improvement.
|
||||||
|
*/
|
||||||
|
"ZA -3230+02259 Africa/Johannesburg\n";
|
||||||
|
|
||||||
class Private : public QObject
|
class Private : public QObject
|
||||||
{
|
{
|
||||||
@ -201,13 +214,27 @@ class Private : public QObject
|
|||||||
public:
|
public:
|
||||||
RegionVector m_regions;
|
RegionVector m_regions;
|
||||||
ZoneVector m_zones;
|
ZoneVector m_zones;
|
||||||
|
ZoneVector m_altZones; //< Extra locations for zones
|
||||||
|
|
||||||
Private()
|
Private()
|
||||||
{
|
{
|
||||||
m_regions.reserve( 12 ); // reasonable guess
|
m_regions.reserve( 12 ); // reasonable guess
|
||||||
m_zones.reserve( 452 ); // wc -l /usr/share/zoneinfo/zone.tab
|
m_zones.reserve( 452 ); // wc -l /usr/share/zoneinfo/zone.tab
|
||||||
|
|
||||||
loadTZData( m_regions, m_zones );
|
// Load the official timezones
|
||||||
|
{
|
||||||
|
QFile file( TZ_DATA_FILE );
|
||||||
|
if ( file.open( QIODevice::ReadOnly | QIODevice::Text ) )
|
||||||
|
{
|
||||||
|
QTextStream in( &file );
|
||||||
|
loadTZData( m_regions, m_zones, in );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Load the alternate zones (see documentation at altZones)
|
||||||
|
{
|
||||||
|
QTextStream in( altZones );
|
||||||
|
loadTZData( m_regions, m_altZones, in );
|
||||||
|
}
|
||||||
|
|
||||||
std::sort( m_regions.begin(), m_regions.end(), []( const RegionData* lhs, const RegionData* rhs ) {
|
std::sort( m_regions.begin(), m_regions.end(), []( const RegionData* lhs, const RegionData* rhs ) {
|
||||||
return lhs->key() < rhs->key();
|
return lhs->key() < rhs->key();
|
||||||
@ -343,9 +370,9 @@ ZonesModel::find( const QString& region, const QString& zone ) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
STATICTEST const TimeZoneData*
|
STATICTEST const TimeZoneData*
|
||||||
find( const ZoneVector& zones, const std::function< double( const TimeZoneData* ) >& distanceFunc )
|
find( double startingDistance, const ZoneVector& zones, const std::function< double( const TimeZoneData* ) >& distanceFunc )
|
||||||
{
|
{
|
||||||
double smallestDistance = 1000000.0;
|
double smallestDistance = startingDistance;
|
||||||
const TimeZoneData* closest = nullptr;
|
const TimeZoneData* closest = nullptr;
|
||||||
|
|
||||||
for ( const auto* zone : zones )
|
for ( const auto* zone : zones )
|
||||||
@ -363,7 +390,14 @@ find( const ZoneVector& zones, const std::function< double( const TimeZoneData*
|
|||||||
const TimeZoneData*
|
const TimeZoneData*
|
||||||
ZonesModel::find( const std::function< double( const TimeZoneData* ) >& distanceFunc ) const
|
ZonesModel::find( const std::function< double( const TimeZoneData* ) >& distanceFunc ) const
|
||||||
{
|
{
|
||||||
return CalamaresUtils::Locale::find( m_private->m_zones, distanceFunc );
|
const auto* officialZone = CalamaresUtils::Locale::find( 1000000.0, m_private->m_zones, distanceFunc );
|
||||||
|
const auto* altZone = CalamaresUtils::Locale::find( distanceFunc( officialZone ), m_private->m_altZones, distanceFunc );
|
||||||
|
|
||||||
|
// If nothing was closer than the official zone already was, altZone is
|
||||||
|
// nullptr; but if there is a spot-patch, then we need to re-find
|
||||||
|
// the zone by name, since we want to always return pointers into
|
||||||
|
// m_zones, not into the alternative spots.
|
||||||
|
return altZone ? find( altZone->region(), altZone->zone() ) : officialZone;
|
||||||
}
|
}
|
||||||
|
|
||||||
const TimeZoneData*
|
const TimeZoneData*
|
||||||
|
Loading…
Reference in New Issue
Block a user