/* * Stellarium * Copyright (C) 2006 Fabien Chereau * * This program 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 2 * of the License, or (at your option) any later version. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "StelLocaleMgr.hpp" #include "StelApp.hpp" #include "StelUtils.hpp" #include "StelFileMgr.hpp" #include #include #include #include #include #include #include QMap StelLocaleMgr::countryCodeToStringMap; StelLocaleMgr::StelLocaleMgr() : skyTranslator("stellarium", StelFileMgr::getLocaleDir(), ""), GMTShift(0) { //generateCountryList(); // Load from file QString path; try { path = StelFileMgr::findFile("data/countryCodes.dat"); } catch (std::runtime_error& e) { qWarning() << "ERROR - could not find country code data file." << e.what(); return; } QFile file(path); file.open(QIODevice::ReadOnly); QDataStream in(&file); // read the data serialized from the file in.setVersion(QDataStream::Qt_4_5); in >> countryCodeToStringMap; file.close(); } StelLocaleMgr::~StelLocaleMgr() {} // Mehtod which generates and save the map between 2 letters country code and english country names void StelLocaleMgr::generateCountryList() { // Load ISO 3166-1 two-letter country codes from file (slow) // The format is "[code][tab][country name containing spaces][newline]" QFile textFile("data/iso3166-1-alpha-2.utf8"); textFile.open(QFile::ReadOnly | QFile::Text); QTextStream list(&textFile); QString line; while(!(line = list.readLine()).isNull()) { qDebug() << line.section(QChar('\t'), 0, 0) << ":" << line.section(QChar('\t'), 1, 1); countryCodeToStringMap.insert(line.section(QChar('\t'), 0, 0), line.section(QChar('\t'), 1, 1)); } textFile.close(); // Save to binary file QFile binaryFile("data/countryCodes.dat"); binaryFile.open(QIODevice::WriteOnly); QDataStream out(&binaryFile); // save the data serialized to the file out.setVersion(QDataStream::Qt_4_5); out << countryCodeToStringMap; binaryFile.close(); } void StelLocaleMgr::init() { QSettings* conf = StelApp::getInstance().getSettings(); Q_ASSERT(conf); setSkyLanguage(conf->value("localization/sky_locale", "system").toString()); setAppLanguage(conf->value("localization/app_locale", "system").toString()); timeFormat = stringToSTimeFormat(conf->value("localization/time_display_format", "system_default").toString()); dateFormat = stringToSDateFormat(conf->value("localization/date_display_format", "system_default").toString()); // time_zone used to be in init_location section of config, // so use that as fallback when reading config - Rob QString tzstr = conf->value("localization/time_zone", conf->value("init_location/time_zone", "system_default").toString()).toString(); if (tzstr == "system_default") { timeZoneMode = STzSystemDefault; // Set the program global intern timezones variables from the system locale tzset(); } else { if (tzstr == "gmt+x") // TODO : handle GMT+X timezones form { timeZoneMode = STzGMTShift; // GMTShift = x; } else { // We have a custom time zone name timeZoneMode = STzCustom; setCustomTzName(tzstr); } } } /************************************************************************* Set the application locale. This apply to GUI, console messages etc.. *************************************************************************/ void StelLocaleMgr::setAppLanguage(const QString& newAppLanguageName) { // Update the translator with new locale name StelTranslator::globalTranslator = StelTranslator("stellarium", StelFileMgr::getLocaleDir(), newAppLanguageName); qDebug() << "Application language is " << StelTranslator::globalTranslator.getTrueLocaleName(); StelApp::getInstance().updateI18n(); } /************************************************************************* Set the sky language. *************************************************************************/ void StelLocaleMgr::setSkyLanguage(const QString& newSkyLanguageName) { // Update the translator with new locale name skyTranslator = StelTranslator("stellarium", StelFileMgr::getLocaleDir(), newSkyLanguageName); qDebug() << "Sky language is " << skyTranslator.getTrueLocaleName(); StelApp::getInstance().updateI18n(); } /************************************************************************* Get the language currently used for sky objects.. *************************************************************************/ QString StelLocaleMgr::getSkyLanguage() const { return skyTranslator.getTrueLocaleName(); } // Get the StelTranslator currently used for sky objects. StelTranslator& StelLocaleMgr::getSkyTranslator() { return skyTranslator; } // Return the time in ISO 8601 format that is : %Y-%m-%d %H:%M:%S QString StelLocaleMgr::getISO8601TimeLocal(double JD) const { double shift = 0.0; if (timeZoneMode == STzGMTShift) { shift = GMTShift; } else { shift = StelUtils::getGMTShiftFromQT(JD)*0.041666666666; } return StelUtils::julianDayToISO8601String(JD + shift); } //! get the six ints from an ISO8601 date time, understood to be local time, make a jdate out //! of them. double StelLocaleMgr::getJdFromISO8601TimeLocal(const QString& t, bool* ok) const { double jd = StelUtils::getJulianDayFromISO8601String(t, ok); if (!*ok) { qWarning() << "StelLocaleMgr::getJdFromISO8601TimeLocal: invalid ISO8601 date. Returning JD=0"; return 0.0; } // modified by shift if (timeZoneMode == STzGMTShift) jd -= GMTShift; else jd -= StelUtils::getGMTShiftFromQT(jd)*0.041666666666; return jd; } // Return a string with the local date formated according to the dateFormat variable QString StelLocaleMgr::getPrintableDateLocal(double JD) const { int year, month, day, dayOfWeek; double shift = 0.0; if (timeZoneMode == STzGMTShift) { shift = GMTShift; } else { shift = StelUtils::getGMTShiftFromQT(JD)*0.041666666666; } StelUtils::getDateFromJulianDay(JD+shift, &year, &month, &day); dayOfWeek = (int)floor(fmod(JD, 7)); QString str; switch (dateFormat) { case SDateMMDDYYYY: str = QString("%1-%2-%3").arg(month,2,10,QLatin1Char('0')).arg(day,2,10,QLatin1Char('0')).arg(year,4,10); break; case SDateDDMMYYYY: str = QString("%1-%2-%3").arg(day,2,10,QLatin1Char('0')).arg(month,2,10,QLatin1Char('0')).arg(year,4,10); break; case SDateYYYYMMDD: str = QString("%1-%2-%3").arg(year,4,10).arg(month,2,10,QLatin1Char('0')).arg(day,2,10,QLatin1Char('0')); break; case SDateSystemDefault: str = StelUtils::localeDateString(year, month, day, dayOfWeek); break; default: qWarning() << "WARNING: unknown date format fallback to system default"; str = StelUtils::localeDateString(year, month, day, dayOfWeek); } return str; } // Return a string with the local time (according to timeZoneMode variable) formated // according to the timeFormat variable QString StelLocaleMgr::getPrintableTimeLocal(double JD) const { int hour, minute, second; double shift = 0.0; if (timeZoneMode == STzGMTShift) { shift = GMTShift; } else { shift = StelUtils::getGMTShiftFromQT(JD)*0.041666666666; } StelUtils::getTimeFromJulianDay(JD+shift, &hour, &minute, &second); QTime t(hour, minute, second); switch (timeFormat) { case STimeSystemDefault: return t.toString(); case STime24h: return t.toString("hh:mm:ss"); case STime12h: return t.toString("hh:mm:ss ap"); default: qWarning() << "WARNING: unknown date format, fallback to system default"; return t.toString(Qt::LocaleDate); } } // Convert the time format enum to its associated string and reverse StelLocaleMgr::STimeFormat StelLocaleMgr::stringToSTimeFormat(const QString& tf) const { if (tf == "system_default") return STimeSystemDefault; if (tf == "24h") return STime24h; if (tf == "12h") return STime12h; qWarning() << "WARNING: unrecognized time_display_format : " << tf << " system_default used."; return STimeSystemDefault; } QString StelLocaleMgr::sTimeFormatToString(STimeFormat tf) const { if (tf == STimeSystemDefault) return "system_default"; if (tf == STime24h) return "24h"; if (tf == STime12h) return "12h"; qWarning() << "WARNING: unrecognized time_display_format value : " << (int)tf << " system_default used."; return "system_default"; } // Convert the date format enum to its associated string and reverse StelLocaleMgr::SDateFormat StelLocaleMgr::stringToSDateFormat(const QString& df) const { if (df == "system_default") return SDateSystemDefault; if (df == "mmddyyyy") return SDateMMDDYYYY; if (df == "ddmmyyyy") return SDateDDMMYYYY; if (df == "yyyymmdd") return SDateYYYYMMDD; // iso8601 qWarning() << "WARNING: unrecognized date_display_format : " << df << " system_default used."; return SDateSystemDefault; } QString StelLocaleMgr::sDateFormatToString(SDateFormat df) const { if (df == SDateSystemDefault) return "system_default"; if (df == SDateMMDDYYYY) return "mmddyyyy"; if (df == SDateDDMMYYYY) return "ddmmyyyy"; if (df == SDateYYYYMMDD) return "yyyymmdd"; qWarning() << "WARNING: unrecognized date_display_format value : " << (int)df << " system_default used."; return "system_default"; } void StelLocaleMgr::setCustomTzName(const QString& tzname) { customTzName = tzname; timeZoneMode = STzCustom; if( customTzName != "") { // set the TZ environement variable and update c locale stuff putenv(strdup(qPrintable("TZ=" + customTzName))); tzset(); } } float StelLocaleMgr::getGMTShift(double JD) const { if (timeZoneMode == STzGMTShift) return GMTShift; else return StelUtils::getGMTShiftFromQT(JD); } // Convert a 2 letter country code to string QString StelLocaleMgr::countryCodeToString(const QString& countryCode) { QMap::ConstIterator i = countryCodeToStringMap.find(countryCode); return (i!=countryCodeToStringMap.constEnd()) ? i.value() : QString(); } // Return a list of all the known country names QStringList StelLocaleMgr::getAllCountryNames() { QStringList res; for (QMap::ConstIterator i = countryCodeToStringMap.constBegin();i!=countryCodeToStringMap.constEnd();++i) res.append(i.value()); res.sort(); return res; }