File indexing completed on 2024-12-08 09:38:10
0001 /* 0002 This file is part of the kholidays library. 0003 0004 SPDX-FileCopyrightText: 2001 Cornelius Schumacher <schumacher@kde.org> 0005 SPDX-FileCopyrightText: 2004-2020 Allen Winter <winter@kde.org> 0006 SPDX-FileCopyrightText: 2008 David Jarvie <djarvie@kde.org> 0007 SPDX-FileCopyrightText: 2010 John Layt <john@layt.net> 0008 0009 The functions languageToCode(), codeToLanguage(), countryToCode() and codeToCounty() are copyright by 0010 SPDX-FileCopyrightText: 2014 Digia Plc and/or its subsidiary(-ies). 0011 0012 SPDX-License-Identifier: LGPL-2.0-or-later 0013 */ 0014 0015 #include "holidayregion.h" 0016 0017 #include <QCoreApplication> 0018 #include <QDirIterator> 0019 #include <QFile> 0020 #include <QFileInfo> 0021 #include <QLocale> 0022 #include <QSharedData> 0023 #include <QStandardPaths> 0024 0025 #include "holiday_p.h" 0026 #include "parsers/plan2/holidayparserdriverplan_p.h" 0027 0028 using namespace KHolidays; 0029 0030 // Copied from qlocale_data_p.h and qlocale.h, see copyright information at top of file 0031 // To later be replaced by OpenCodes or public Qt api 0032 static const unsigned char country_code_list[] = 0033 "ZZ\0" // AnyCountry 0034 "AF\0" // Afghanistan 0035 "AL\0" // Albania 0036 "DZ\0" // Algeria 0037 "AS\0" // AmericanSamoa 0038 "AD\0" // Andorra 0039 "AO\0" // Angola 0040 "AI\0" // Anguilla 0041 "AQ\0" // Antarctica 0042 "AG\0" // AntiguaAndBarbuda 0043 "AR\0" // Argentina 0044 "AM\0" // Armenia 0045 "AW\0" // Aruba 0046 "AU\0" // Australia 0047 "AT\0" // Austria 0048 "AZ\0" // Azerbaijan 0049 "BS\0" // Bahamas 0050 "BH\0" // Bahrain 0051 "BD\0" // Bangladesh 0052 "BB\0" // Barbados 0053 "BY\0" // Belarus 0054 "BE\0" // Belgium 0055 "BZ\0" // Belize 0056 "BJ\0" // Benin 0057 "BM\0" // Bermuda 0058 "BT\0" // Bhutan 0059 "BO\0" // Bolivia 0060 "BA\0" // BosniaAndHerzegowina 0061 "BW\0" // Botswana 0062 "BV\0" // BouvetIsland 0063 "BR\0" // Brazil 0064 "IO\0" // BritishIndianOceanTerritory 0065 "BN\0" // Brunei 0066 "BG\0" // Bulgaria 0067 "BF\0" // BurkinaFaso 0068 "BI\0" // Burundi 0069 "KH\0" // Cambodia 0070 "CM\0" // Cameroon 0071 "CA\0" // Canada 0072 "CV\0" // CapeVerde 0073 "KY\0" // CaymanIslands 0074 "CF\0" // CentralAfricanRepublic 0075 "TD\0" // Chad 0076 "CL\0" // Chile 0077 "CN\0" // China 0078 "CX\0" // ChristmasIsland 0079 "CC\0" // CocosIslands 0080 "CO\0" // Colombia 0081 "KM\0" // Comoros 0082 "CD\0" // CongoKinshasa 0083 "CG\0" // CongoBrazzaville 0084 "CK\0" // CookIslands 0085 "CR\0" // CostaRica 0086 "CI\0" // IvoryCoast 0087 "HR\0" // Croatia 0088 "CU\0" // Cuba 0089 "CY\0" // Cyprus 0090 "CZ\0" // CzechRepublic 0091 "DK\0" // Denmark 0092 "DJ\0" // Djibouti 0093 "DM\0" // Dominica 0094 "DO\0" // DominicanRepublic 0095 "TL\0" // EastTimor 0096 "EC\0" // Ecuador 0097 "EG\0" // Egypt 0098 "SV\0" // ElSalvador 0099 "GQ\0" // EquatorialGuinea 0100 "ER\0" // Eritrea 0101 "EE\0" // Estonia 0102 "ET\0" // Ethiopia 0103 "FK\0" // FalklandIslands 0104 "FO\0" // FaroeIslands 0105 "FJ\0" // Fiji 0106 "FI\0" // Finland 0107 "FR\0" // France 0108 "GG\0" // Guernsey 0109 "GF\0" // FrenchGuiana 0110 "PF\0" // FrenchPolynesia 0111 "TF\0" // FrenchSouthernTerritories 0112 "GA\0" // Gabon 0113 "GM\0" // Gambia 0114 "GE\0" // Georgia 0115 "DE\0" // Germany 0116 "GH\0" // Ghana 0117 "GI\0" // Gibraltar 0118 "GR\0" // Greece 0119 "GL\0" // Greenland 0120 "GD\0" // Grenada 0121 "GP\0" // Guadeloupe 0122 "GU\0" // Guam 0123 "GT\0" // Guatemala 0124 "GN\0" // Guinea 0125 "GW\0" // GuineaBissau 0126 "GY\0" // Guyana 0127 "HT\0" // Haiti 0128 "HM\0" // HeardAndMcDonaldIslands 0129 "HN\0" // Honduras 0130 "HK\0" // HongKong 0131 "HU\0" // Hungary 0132 "IS\0" // Iceland 0133 "IN\0" // India 0134 "ID\0" // Indonesia 0135 "IR\0" // Iran 0136 "IQ\0" // Iraq 0137 "IE\0" // Ireland 0138 "IL\0" // Israel 0139 "IT\0" // Italy 0140 "JM\0" // Jamaica 0141 "JP\0" // Japan 0142 "JO\0" // Jordan 0143 "KZ\0" // Kazakhstan 0144 "KE\0" // Kenya 0145 "KI\0" // Kiribati 0146 "KP\0" // NorthKorea 0147 "KR\0" // SouthKorea 0148 "KW\0" // Kuwait 0149 "KG\0" // Kyrgyzstan 0150 "LA\0" // Laos 0151 "LV\0" // Latvia 0152 "LB\0" // Lebanon 0153 "LS\0" // Lesotho 0154 "LR\0" // Liberia 0155 "LY\0" // Libya 0156 "LI\0" // Liechtenstein 0157 "LT\0" // Lithuania 0158 "LU\0" // Luxembourg 0159 "MO\0" // Macau 0160 "MK\0" // Macedonia 0161 "MG\0" // Madagascar 0162 "MW\0" // Malawi 0163 "MY\0" // Malaysia 0164 "MV\0" // Maldives 0165 "ML\0" // Mali 0166 "MT\0" // Malta 0167 "MH\0" // MarshallIslands 0168 "MQ\0" // Martinique 0169 "MR\0" // Mauritania 0170 "MU\0" // Mauritius 0171 "YT\0" // Mayotte 0172 "MX\0" // Mexico 0173 "FM\0" // Micronesia 0174 "MD\0" // Moldova 0175 "MC\0" // Monaco 0176 "MN\0" // Mongolia 0177 "MS\0" // Montserrat 0178 "MA\0" // Morocco 0179 "MZ\0" // Mozambique 0180 "MM\0" // Myanmar 0181 "NA\0" // Namibia 0182 "NR\0" // Nauru 0183 "NP\0" // Nepal 0184 "NL\0" // Netherlands 0185 "CW\0" // CuraSao 0186 "NC\0" // NewCaledonia 0187 "NZ\0" // NewZealand 0188 "NI\0" // Nicaragua 0189 "NE\0" // Niger 0190 "NG\0" // Nigeria 0191 "NU\0" // Niue 0192 "NF\0" // NorfolkIsland 0193 "MP\0" // NorthernMarianaIslands 0194 "NO\0" // Norway 0195 "OM\0" // Oman 0196 "PK\0" // Pakistan 0197 "PW\0" // Palau 0198 "PS\0" // PalestinianTerritories 0199 "PA\0" // Panama 0200 "PG\0" // PapuaNewGuinea 0201 "PY\0" // Paraguay 0202 "PE\0" // Peru 0203 "PH\0" // Philippines 0204 "PN\0" // Pitcairn 0205 "PL\0" // Poland 0206 "PT\0" // Portugal 0207 "PR\0" // PuertoRico 0208 "QA\0" // Qatar 0209 "RE\0" // Reunion 0210 "RO\0" // Romania 0211 "RU\0" // Russia 0212 "RW\0" // Rwanda 0213 "KN\0" // SaintKittsAndNevis 0214 "LC\0" // SaintLucia 0215 "VC\0" // SaintVincentAndTheGrenadines 0216 "WS\0" // Samoa 0217 "SM\0" // SanMarino 0218 "ST\0" // SaoTomeAndPrincipe 0219 "SA\0" // SaudiArabia 0220 "SN\0" // Senegal 0221 "SC\0" // Seychelles 0222 "SL\0" // SierraLeone 0223 "SG\0" // Singapore 0224 "SK\0" // Slovakia 0225 "SI\0" // Slovenia 0226 "SB\0" // SolomonIslands 0227 "SO\0" // Somalia 0228 "ZA\0" // SouthAfrica 0229 "GS\0" // SouthGeorgiaAndTheSouthSandwichIslands 0230 "ES\0" // Spain 0231 "LK\0" // SriLanka 0232 "SH\0" // SaintHelena 0233 "PM\0" // SaintPierreAndMiquelon 0234 "SD\0" // Sudan 0235 "SR\0" // Suriname 0236 "SJ\0" // SvalbardAndJanMayenIslands 0237 "SZ\0" // Swaziland 0238 "SE\0" // Sweden 0239 "CH\0" // Switzerland 0240 "SY\0" // Syria 0241 "TW\0" // Taiwan 0242 "TJ\0" // Tajikistan 0243 "TZ\0" // Tanzania 0244 "TH\0" // Thailand 0245 "TG\0" // Togo 0246 "TK\0" // Tokelau 0247 "TO\0" // Tonga 0248 "TT\0" // TrinidadAndTobago 0249 "TN\0" // Tunisia 0250 "TR\0" // Turkey 0251 "TM\0" // Turkmenistan 0252 "TC\0" // TurksAndCaicosIslands 0253 "TV\0" // Tuvalu 0254 "UG\0" // Uganda 0255 "UA\0" // Ukraine 0256 "AE\0" // UnitedArabEmirates 0257 "GB\0" // UnitedKingdom 0258 "US\0" // UnitedStates 0259 "UM\0" // UnitedStatesMinorOutlyingIslands 0260 "UY\0" // Uruguay 0261 "UZ\0" // Uzbekistan 0262 "VU\0" // Vanuatu 0263 "VA\0" // VaticanCityState 0264 "VE\0" // Venezuela 0265 "VN\0" // Vietnam 0266 "VG\0" // BritishVirginIslands 0267 "VI\0" // UnitedStatesVirginIslands 0268 "WF\0" // WallisAndFutunaIslands 0269 "EH\0" // WesternSahara 0270 "YE\0" // Yemen 0271 "IC\0" // CanaryIslands 0272 "ZM\0" // Zambia 0273 "ZW\0" // Zimbabwe 0274 "CP\0" // ClippertonIsland 0275 "ME\0" // Montenegro 0276 "RS\0" // Serbia 0277 "BL\0" // Saint Barthelemy 0278 "MF\0" // Saint Martin 0279 "419" // LatinAmericaAndTheCaribbean 0280 "AC\0" // AscensionIsland 0281 "AX\0" // AlandIslands 0282 "DG\0" // DiegoGarcia 0283 "EA\0" // CeutaAndMelilla 0284 "IM\0" // IsleOfMan 0285 "JE\0" // Jersey 0286 "TA\0" // TristanDaCunha 0287 "SS\0" // SouthSudan 0288 "BQ\0" // Bonaire 0289 "SX\0" // SintMaarten 0290 "XK\0" // Kosovo 0291 ; 0292 0293 static const unsigned char language_code_list[] = 0294 " \0" // AnyLanguage 0295 " \0" // C 0296 "ab\0" // Abkhazian 0297 "om\0" // Oromo 0298 "aa\0" // Afar 0299 "af\0" // Afrikaans 0300 "sq\0" // Albanian 0301 "am\0" // Amharic 0302 "ar\0" // Arabic 0303 "hy\0" // Armenian 0304 "as\0" // Assamese 0305 "ay\0" // Aymara 0306 "az\0" // Azerbaijani 0307 "ba\0" // Bashkir 0308 "eu\0" // Basque 0309 "bn\0" // Bengali 0310 "dz\0" // Dzongkha 0311 "bh\0" // Bihari 0312 "bi\0" // Bislama 0313 "br\0" // Breton 0314 "bg\0" // Bulgarian 0315 "my\0" // Burmese 0316 "be\0" // Belarusian 0317 "km\0" // Khmer 0318 "ca\0" // Catalan 0319 "zh\0" // Chinese 0320 "co\0" // Corsican 0321 "hr\0" // Croatian 0322 "cs\0" // Czech 0323 "da\0" // Danish 0324 "nl\0" // Dutch 0325 "en\0" // English 0326 "eo\0" // Esperanto 0327 "et\0" // Estonian 0328 "fo\0" // Faroese 0329 "fj\0" // Fijian 0330 "fi\0" // Finnish 0331 "fr\0" // French 0332 "fy\0" // Western Frisian 0333 "gd\0" // Gaelic 0334 "gl\0" // Galician 0335 "ka\0" // Georgian 0336 "de\0" // German 0337 "el\0" // Greek 0338 "kl\0" // Greenlandic 0339 "gn\0" // Guarani 0340 "gu\0" // Gujarati 0341 "ha\0" // Hausa 0342 "he\0" // Hebrew 0343 "hi\0" // Hindi 0344 "hu\0" // Hungarian 0345 "is\0" // Icelandic 0346 "id\0" // Indonesian 0347 "ia\0" // Interlingua 0348 "ie\0" // Interlingue 0349 "iu\0" // Inuktitut 0350 "ik\0" // Inupiak 0351 "ga\0" // Irish 0352 "it\0" // Italian 0353 "ja\0" // Japanese 0354 "jv\0" // Javanese 0355 "kn\0" // Kannada 0356 "ks\0" // Kashmiri 0357 "kk\0" // Kazakh 0358 "rw\0" // Kinyarwanda 0359 "ky\0" // Kirghiz 0360 "ko\0" // Korean 0361 "ku\0" // Kurdish 0362 "rn\0" // Rundi 0363 "lo\0" // Lao 0364 "la\0" // Latin 0365 "lv\0" // Latvian 0366 "ln\0" // Lingala 0367 "lt\0" // Lithuanian 0368 "mk\0" // Macedonian 0369 "mg\0" // Malagasy 0370 "ms\0" // Malay 0371 "ml\0" // Malayalam 0372 "mt\0" // Maltese 0373 "mi\0" // Maori 0374 "mr\0" // Marathi 0375 "mh\0" // Marshallese 0376 "mn\0" // Mongolian 0377 "na\0" // Nauru 0378 "ne\0" // Nepali 0379 "nb\0" // NorwegianBokmal 0380 "oc\0" // Occitan 0381 "or\0" // Oriya 0382 "ps\0" // Pashto 0383 "fa\0" // Persian 0384 "pl\0" // Polish 0385 "pt\0" // Portuguese 0386 "pa\0" // Punjabi 0387 "qu\0" // Quechua 0388 "rm\0" // Romansh 0389 "ro\0" // Romanian 0390 "ru\0" // Russian 0391 "sm\0" // Samoan 0392 "sg\0" // Sango 0393 "sa\0" // Sanskrit 0394 "sr\0" // Serbian 0395 "os\0" // Ossetic 0396 "st\0" // Southern Sotho 0397 "tn\0" // Tswana 0398 "sn\0" // Shona 0399 "sd\0" // Sindhi 0400 "si\0" // Sinhala 0401 "ss\0" // Swati 0402 "sk\0" // Slovak 0403 "sl\0" // Slovenian 0404 "so\0" // Somali 0405 "es\0" // Spanish 0406 "su\0" // Sundanese 0407 "sw\0" // Swahili 0408 "sv\0" // Swedish 0409 "sc\0" // Sardinian 0410 "tg\0" // Tajik 0411 "ta\0" // Tamil 0412 "tt\0" // Tatar 0413 "te\0" // Telugu 0414 "th\0" // Thai 0415 "bo\0" // Tibetan 0416 "ti\0" // Tigrinya 0417 "to\0" // Tongan 0418 "ts\0" // Tsonga 0419 "tr\0" // Turkish 0420 "tk\0" // Turkmen 0421 "ty\0" // Tahitian 0422 "ug\0" // Uighur 0423 "uk\0" // Ukrainian 0424 "ur\0" // Urdu 0425 "uz\0" // Uzbek 0426 "vi\0" // Vietnamese 0427 "vo\0" // Volapuk 0428 "cy\0" // Welsh 0429 "wo\0" // Wolof 0430 "xh\0" // Xhosa 0431 "yi\0" // Yiddish 0432 "yo\0" // Yoruba 0433 "za\0" // Zhuang 0434 "zu\0" // Zulu 0435 "nn\0" // NorwegianNynorsk 0436 "bs\0" // Bosnian 0437 "dv\0" // Divehi 0438 "gv\0" // Manx 0439 "kw\0" // Cornish 0440 "ak\0" // Akan 0441 "kok" // Konkani 0442 "gaa" // Ga 0443 "ig\0" // Igbo 0444 "kam" // Kamba 0445 "syr" // Syriac 0446 "byn" // Blin 0447 "gez" // Geez 0448 "kfo" // Koro 0449 "sid" // Sidamo 0450 "cch" // Atsam 0451 "tig" // Tigre 0452 "kaj" // Jju 0453 "fur" // Friulian 0454 "ve\0" // Venda 0455 "ee\0" // Ewe 0456 "wal" // Walamo 0457 "haw" // Hawaiian 0458 "kcg" // Tyap 0459 "ny\0" // Nyanja 0460 "fil" // Filipino 0461 "gsw" // Swiss German 0462 "ii\0" // Sichuan Yi 0463 "kpe" // Kpelle 0464 "nds" // Low German 0465 "nr\0" // South Ndebele 0466 "nso" // Northern Sotho 0467 "se\0" // Northern Sami 0468 "trv" // Taroko 0469 "guz" // Gusii 0470 "dav" // Taita 0471 "ff\0" // Fulah 0472 "ki\0" // Kikuyu 0473 "saq" // Samburu 0474 "seh" // Sena 0475 "nd\0" // North Ndebele 0476 "rof" // Rombo 0477 "shi" // Tachelhit 0478 "kab" // Kabyle 0479 "nyn" // Nyankole 0480 "bez" // Bena 0481 "vun" // Vunjo 0482 "bm\0" // Bambara 0483 "ebu" // Embu 0484 "chr" // Cherokee 0485 "mfe" // Morisyen 0486 "kde" // Makonde 0487 "lag" // Langi 0488 "lg\0" // Ganda 0489 "bem" // Bemba 0490 "kea" // Kabuverdianu 0491 "mer" // Meru 0492 "kln" // Kalenjin 0493 "naq" // Nama 0494 "jmc" // Machame 0495 "ksh" // Colognian 0496 "mas" // Masai 0497 "xog" // Soga 0498 "luy" // Luyia 0499 "asa" // Asu 0500 "teo" // Teso 0501 "ssy" // Saho 0502 "khq" // Koyra Chiini 0503 "rwk" // Rwa 0504 "luo" // Luo 0505 "cgg" // Chiga 0506 "tzm" // Central Morocco Tamazight 0507 "ses" // Koyraboro Senni 0508 "ksb" // Shambala 0509 "brx" // Bodo 0510 "av\0" // Avaric 0511 "ch\0" // Chamorro 0512 "ce\0" // Chechen 0513 "cu\0" // Church 0514 "cv\0" // Chuvash 0515 "cr\0" // Cree 0516 "ht\0" // Haitian 0517 "hz\0" // Herero 0518 "ho\0" // Hiri Motu 0519 "kr\0" // Kanuri 0520 "kv\0" // Komi 0521 "kg\0" // Kongo 0522 "kj\0" // Kwanyama 0523 "li\0" // Limburgish 0524 "lu\0" // LubaKatanga 0525 "lb\0" // Luxembourgish 0526 "nv\0" // Navaho 0527 "ng\0" // Ndonga 0528 "oj\0" // Ojibwa 0529 "pi\0" // Pali 0530 "wa\0" // Walloon 0531 "agq" // Aghem 0532 "bas" // Basaa 0533 "dje" // Zarma 0534 "dua" // Duala 0535 "dyo" // JolaFonyi 0536 "ewo" // Ewondo 0537 "ksf" // Bafia 0538 "mgh" // MakhuwaMeetto 0539 "mua" // Mundang 0540 "nmg" // Kwasio 0541 "nus" // Nuer 0542 "sah" // Sakha 0543 "sbp" // Sangu 0544 "swc" // Congo Swahili 0545 "twq" // Tasawaq 0546 "vai" // Vai 0547 "wae" // Walser 0548 "yav" // Yangben 0549 "ae\0" // Avestan 0550 "ast" // Asturian 0551 "jgo" // Ngomba 0552 "kkj" // Kako 0553 "mgo" // Meta 0554 "nnh" // Ngiemboon 0555 "an\0" // Aragonese 0556 "akk" // Akkadian 0557 "egy" // AncientEgyptian 0558 "grc" // AncientGreek 0559 "arc" // Aramaic 0560 "ban" // Balinese 0561 "bax" // Bamun 0562 "bbc" // BatakToba 0563 "bug" // Buginese 0564 "bku" // Buhid 0565 "xcr" // Carian 0566 "ccp" // Chakma 0567 "myz" // ClassicalMandaic 0568 "cop" // Coptic 0569 "doi" // Dogri 0570 "cjm" // EasternCham 0571 "eky" // EasternKayah 0572 "ett" // Etruscan 0573 "got" // Gothic 0574 "hnn" // Hanunoo 0575 "inh" // Ingush 0576 "hmd" // LargeFloweryMiao 0577 "lep" // Lepcha 0578 "lif" // Limbu 0579 "lis" // Lisu 0580 "khb" // Lu 0581 "xlc" // Lycian 0582 "xld" // Lydian 0583 "man" // Mandingo 0584 "mni" // Manipuri 0585 "xmr" // Meroitic 0586 "nod" // NorthernThai 0587 "sga" // OldIrish 0588 "non" // OldNorse 0589 "peo" // OldPersian 0590 "otk" // OldTurkish 0591 "pal" // Pahlavi 0592 "xpr" // Parthian 0593 "phn" // Phoenician 0594 "pra" // PrakritLanguage 0595 "rej" // Rejang 0596 "xsa" // Sabaean 0597 "smp" // Samaritan 0598 "sat" // Santali 0599 "saz" // Saurashtra 0600 "srb" // Sora 0601 "syl" // Sylheti 0602 "tbw" // Tagbanwa 0603 "blt" // TaiDam 0604 "tdd" // TaiNua 0605 "uga" // Ugaritic 0606 "bss" // Akoose 0607 "lkt" // Lakota 0608 "zgh" // Standard Moroccan Tamazight 0609 ; 0610 0611 static QString languageToCode(QLocale::Language language) 0612 { 0613 if (language == QLocale::AnyLanguage) { 0614 return QString(); 0615 } 0616 if (language == QLocale::C) { 0617 return QStringLiteral("C"); 0618 } 0619 0620 const unsigned char *c = language_code_list + 3 * (uint(language)); 0621 0622 QString code(c[2] == 0 ? 2 : 3, Qt::Uninitialized); 0623 0624 code[0] = ushort(c[0]); 0625 code[1] = ushort(c[1]); 0626 if (c[2] != 0) { 0627 code[2] = ushort(c[2]); 0628 } 0629 0630 return code; 0631 } 0632 0633 static QString countryToCode(QLocale::Country country) 0634 { 0635 if (country == QLocale::AnyCountry) { 0636 return QString(); 0637 } 0638 0639 const unsigned char *c = country_code_list + 3 * (uint(country)); 0640 0641 QString code(c[2] == 0 ? 2 : 3, Qt::Uninitialized); 0642 0643 code[0] = ushort(c[0]); 0644 code[1] = ushort(c[1]); 0645 if (c[2] != 0) { 0646 code[2] = ushort(c[2]); 0647 } 0648 0649 return code; 0650 } 0651 0652 static QLocale::Country codeToCountry(const QString &code) 0653 { 0654 int len = code.length(); 0655 if (len != 2 && len != 3) { 0656 return QLocale::AnyCountry; 0657 } 0658 ushort uc1 = len-- > 0 ? code[0].toUpper().unicode() : 0; 0659 ushort uc2 = len-- > 0 ? code[1].toUpper().unicode() : 0; 0660 ushort uc3 = len-- > 0 ? code[2].toUpper().unicode() : 0; 0661 0662 const unsigned char *c = country_code_list; 0663 for (; *c != 0; c += 3) { 0664 if (uc1 == c[0] && uc2 == c[1] && uc3 == c[2]) { 0665 return QLocale::Country((c - country_code_list) / 3); 0666 } 0667 } 0668 0669 return QLocale::AnyCountry; 0670 } 0671 0672 #if 0 0673 static QLocale::Language codeToLanguage(const QString &code) 0674 { 0675 int len = code.length(); 0676 if (len != 2 && len != 3) { 0677 return QLocale::C; 0678 } 0679 ushort uc1 = len-- > 0 ? code[0].toLower().unicode() : 0; 0680 ushort uc2 = len-- > 0 ? code[1].toLower().unicode() : 0; 0681 ushort uc3 = len-- > 0 ? code[2].toLower().unicode() : 0; 0682 0683 const unsigned char *c = language_code_list; 0684 for (; *c != 0; c += 3) { 0685 if (uc1 == c[0] && uc2 == c[1] && uc3 == c[2]) { 0686 return QLocale::Language((c - language_code_list) / 3); 0687 } 0688 } 0689 0690 // legacy codes 0691 if (uc1 == 'n' && uc2 == 'o' && uc3 == 0) { // no -> nb 0692 Q_STATIC_ASSERT(QLocale::Norwegian == QLocale::NorwegianBokmal); 0693 return QLocale::Norwegian; 0694 } 0695 if (uc1 == 't' && uc2 == 'l' && uc3 == 0) { // tl -> fil 0696 Q_STATIC_ASSERT(QLocale::Tagalog == QLocale::Filipino); 0697 return QLocale::Tagalog; 0698 } 0699 if (uc1 == 's' && uc2 == 'h' && uc3 == 0) { // sh -> sr[_Latn] 0700 Q_STATIC_ASSERT(QLocale::SerboCroatian == QLocale::Serbian); 0701 return QLocale::SerboCroatian; 0702 } 0703 if (uc1 == 'm' && uc2 == 'o' && uc3 == 0) { // mo -> ro 0704 Q_STATIC_ASSERT(QLocale::Moldavian == QLocale::Romanian); 0705 return QLocale::Moldavian; 0706 } 0707 0708 return QLocale::C; 0709 } 0710 #endif 0711 // End Qt copied code 0712 0713 static void initResources() 0714 { 0715 static bool initDone = false; 0716 if (!initDone) { 0717 Q_INIT_RESOURCE(holidays); 0718 initDone = true; 0719 } 0720 } 0721 0722 static QStringList allHolidayFiles(const QString &location = QString()) 0723 { 0724 initResources(); 0725 QStringList dirs{QStringLiteral(":/org.kde.kholidays/plan2")}; 0726 dirs += QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, // 0727 QStringLiteral("kf5/libkholidays/plan2"), 0728 QStandardPaths::LocateDirectory); 0729 QStringList files; 0730 for (const QString &dir : std::as_const(dirs)) { 0731 QDirIterator it(dir, QStringList() << QStringLiteral("holiday_") + location + '*'); 0732 while (it.hasNext()) { 0733 files.push_back(it.next()); 0734 } 0735 } 0736 return files; 0737 } 0738 0739 namespace KHolidays 0740 { 0741 class HolidayRegionPrivate : public QSharedData 0742 { 0743 public: 0744 explicit HolidayRegionPrivate(const QString ®ionCode) 0745 : mDriver(nullptr) 0746 , mRegionCode(regionCode) 0747 { 0748 if (!mRegionCode.isEmpty()) { 0749 auto file = QStandardPaths::locate(QStandardPaths::GenericDataLocation, // 0750 QLatin1String("kf5/libkholidays/plan2/holiday_") + mRegionCode); 0751 if (!file.isEmpty()) { 0752 mHolidayFile.setFile(file); 0753 } else { 0754 initResources(); 0755 file = QStringLiteral(":/org.kde.kholidays/plan2/holiday_") + mRegionCode; 0756 if (QFile::exists(file)) { 0757 mHolidayFile.setFile(file); 0758 } 0759 } 0760 } 0761 0762 init(); 0763 } 0764 0765 explicit HolidayRegionPrivate(const QFileInfo ®ionFile) 0766 : mDriver(nullptr) 0767 , mHolidayFile(regionFile) 0768 { 0769 init(); 0770 } 0771 0772 ~HolidayRegionPrivate() 0773 { 0774 delete mDriver; 0775 } 0776 0777 void init() 0778 { 0779 if (mHolidayFile.exists()) { 0780 mDriver = new HolidayParserDriverPlan(mHolidayFile.absoluteFilePath()); 0781 if (mDriver) { 0782 if (mRegionCode.isEmpty()) { 0783 if (mHolidayFile.fileName().startsWith(QLatin1String("holiday_"))) { 0784 mRegionCode = mHolidayFile.fileName().mid(8); 0785 } else { 0786 mRegionCode = mHolidayFile.fileName(); 0787 } 0788 } 0789 0790 } else { 0791 mRegionCode.clear(); 0792 } 0793 } else { 0794 mRegionCode.clear(); 0795 } 0796 } 0797 0798 HolidayParserDriver *mDriver; // The parser driver for the holiday file 0799 QString mRegionCode; // region code of holiday region 0800 QFileInfo mHolidayFile; // file containing holiday data, or null 0801 }; 0802 } 0803 0804 HolidayRegion::HolidayRegion(const QString ®ionCode) 0805 : d(new HolidayRegionPrivate(regionCode)) 0806 { 0807 } 0808 0809 HolidayRegion::HolidayRegion(const QFileInfo ®ionFile) 0810 : d(new HolidayRegionPrivate(regionFile)) 0811 { 0812 } 0813 0814 HolidayRegion::HolidayRegion(const HolidayRegion &) = default; 0815 HolidayRegion::HolidayRegion(HolidayRegion &&) = default; 0816 HolidayRegion::~HolidayRegion() = default; 0817 0818 HolidayRegion &HolidayRegion::operator=(const HolidayRegion &) = default; 0819 HolidayRegion &HolidayRegion::operator=(HolidayRegion &&) = default; 0820 0821 QStringList HolidayRegion::regionCodes() 0822 { 0823 const QStringList files = allHolidayFiles(); 0824 0825 QStringList regionCodesList; 0826 regionCodesList.reserve(files.count()); 0827 for (const QString &filename : files) { 0828 regionCodesList.append(filename.mid(filename.lastIndexOf(QLatin1String("holiday_")) + 8)); 0829 } 0830 0831 std::sort(regionCodesList.begin(), regionCodesList.end()); 0832 return regionCodesList; 0833 } 0834 0835 QString HolidayRegion::regionCode() const 0836 { 0837 return d->mRegionCode; 0838 } 0839 0840 QString HolidayRegion::countryCode() const 0841 { 0842 return d->mDriver->fileCountryCode(); 0843 } 0844 0845 QString HolidayRegion::countryCode(const QString ®ionCode) 0846 { 0847 HolidayRegion temp(regionCode); 0848 if (temp.isValid()) { 0849 return temp.countryCode(); 0850 } else { 0851 return QString(); 0852 } 0853 } 0854 0855 QString HolidayRegion::languageCode() const 0856 { 0857 return d->mDriver->fileLanguageCode(); 0858 } 0859 0860 QString HolidayRegion::languageCode(const QString ®ionCode) 0861 { 0862 HolidayRegion temp(regionCode); 0863 if (temp.isValid()) { 0864 return temp.languageCode(); 0865 } else { 0866 return QString(); 0867 } 0868 } 0869 0870 QString HolidayRegion::name() const 0871 { 0872 QString tempName = d->mDriver->fileName(); 0873 0874 if (tempName.isEmpty()) { 0875 QStringList countryParts = countryCode().toLower().split(QLatin1Char('-')); 0876 const QString &country = countryParts.at(0); 0877 QString regionName; 0878 QString typeName; 0879 0880 if (country != QLatin1String("xx")) { 0881 if (countryParts.count() == 2) { 0882 // Temporary measure to get regions translated, only those files that already exist 0883 // In 4.6 hope to have isocodes project integration for translations via KLocale 0884 const QString &subdivision = countryParts.at(1); 0885 if (country == QLatin1String("ca") && subdivision == QLatin1String("qc")) { 0886 regionName = QCoreApplication::translate("HolidayRegion", "Quebec", "Canadian region"); 0887 } else if (country == QLatin1String("de")) { 0888 if (subdivision == QLatin1String("by")) { 0889 regionName = QCoreApplication::translate("HolidayRegion", "Germany, Bavaria", "German region"); 0890 } else if (subdivision == QLatin1String("bb")) { 0891 regionName = QCoreApplication::translate("HolidayRegion", "Germany, Brandenburg", "German region"); 0892 } else if (subdivision == QLatin1String("be")) { 0893 regionName = QCoreApplication::translate("HolidayRegion", "Germany, Berlin", "German region"); 0894 } else if (subdivision == QLatin1String("bw")) { 0895 regionName = QCoreApplication::translate("HolidayRegion", "Germany, Baden-Wuerttemberg", "German region"); 0896 } else if (subdivision == QLatin1String("he")) { 0897 regionName = QCoreApplication::translate("HolidayRegion", "Germany, Hesse", "German region"); 0898 } else if (subdivision == QLatin1String("mv")) { 0899 regionName = QCoreApplication::translate("HolidayRegion", "Germany, Mecklenburg-Hither Pomerania", "German region"); 0900 } else if (subdivision == QLatin1String("ni")) { 0901 regionName = QCoreApplication::translate("HolidayRegion", "Germany, Lower Saxony", "German region"); 0902 } else if (subdivision == QLatin1String("nw")) { 0903 regionName = QCoreApplication::translate("HolidayRegion", "Germany, North Rhine-Westphalia", "German region"); 0904 } else if (subdivision == QLatin1String("rp")) { 0905 regionName = QCoreApplication::translate("HolidayRegion", "Germany, Rhineland-Palatinate", "German region"); 0906 } else if (subdivision == QLatin1String("sh")) { 0907 regionName = QCoreApplication::translate("HolidayRegion", "Germany, Schleswig-Holstein", "German region"); 0908 } else if (subdivision == QLatin1String("sl")) { 0909 regionName = QCoreApplication::translate("HolidayRegion", "Germany, Saarland", "German region"); 0910 } else if (subdivision == QLatin1String("sn")) { 0911 regionName = QCoreApplication::translate("HolidayRegion", "Germany, Saxony", "German region"); 0912 } else if (subdivision == QLatin1String("st")) { 0913 regionName = QCoreApplication::translate("HolidayRegion", "Germany, Saxony-Anhalt", "German region"); 0914 } else if (subdivision == QLatin1String("th")) { 0915 regionName = QCoreApplication::translate("HolidayRegion", "Germany, Thuringia", "German region"); 0916 } 0917 } else if (country == QLatin1String("es") && subdivision == QLatin1String("ct")) { 0918 regionName = QCoreApplication::translate("HolidayRegion", "Catalonia", "Spanish region"); 0919 } else if (country == QLatin1String("gb") && subdivision == QLatin1String("eaw")) { 0920 regionName = QCoreApplication::translate("HolidayRegion", "England and Wales", "UK Region"); 0921 } else if (country == QLatin1String("gb") && subdivision == QLatin1String("eng")) { 0922 regionName = QCoreApplication::translate("HolidayRegion", "England", "UK Region"); 0923 } else if (country == QLatin1String("gb") && subdivision == QLatin1String("wls")) { 0924 regionName = QCoreApplication::translate("HolidayRegion", "Wales", "UK Region"); 0925 } else if (country == QLatin1String("gb") && subdivision == QLatin1String("sct")) { 0926 regionName = QCoreApplication::translate("HolidayRegion", "Scotland", "UK Region"); 0927 } else if (country == QLatin1String("gb") && subdivision == QLatin1String("nir")) { 0928 regionName = QCoreApplication::translate("HolidayRegion", "Northern Ireland", "UK Region"); 0929 } else if (country == QLatin1String("it") && subdivision == QLatin1String("bz")) { 0930 regionName = QCoreApplication::translate("HolidayRegion", "South Tyrol", "Italian Region"); 0931 } else if (country == QLatin1String("au") && subdivision == QLatin1String("nsw")) { 0932 regionName = QCoreApplication::translate("HolidayRegion", "New South Wales"); 0933 } else if (country == QLatin1String("au") && subdivision == QLatin1String("qld")) { 0934 regionName = QCoreApplication::translate("HolidayRegion", "Queensland", "Australian Region"); 0935 } else if (country == QLatin1String("au") && subdivision == QLatin1String("vic")) { 0936 regionName = QCoreApplication::translate("HolidayRegion", "Victoria", "Australian Region"); 0937 } else if (country == QLatin1String("au") && subdivision == QLatin1String("sa")) { 0938 regionName = QCoreApplication::translate("HolidayRegion", "South Australia", "Australian Region"); 0939 } else if (country == QLatin1String("au") && subdivision == QLatin1String("nt")) { 0940 regionName = QCoreApplication::translate("HolidayRegion", "Northern Territory", "Australian Region"); 0941 } else if (country == QLatin1String("au") && subdivision == QLatin1String("act")) { 0942 regionName = QCoreApplication::translate("HolidayRegion", "Australian Capital Territory", "Australian Region"); 0943 } else if (country == QLatin1String("au") && subdivision == QLatin1String("wa")) { 0944 regionName = QCoreApplication::translate("HolidayRegion", "Western Australia", "Australian Region"); 0945 } else if (country == QLatin1String("au") && subdivision == QLatin1String("tas")) { 0946 regionName = QCoreApplication::translate("HolidayRegion", "Tasmania", "Australian Region"); 0947 } else if (country == QLatin1String("ba") && subdivision == QLatin1String("srp")) { 0948 regionName = QCoreApplication::translate("HolidayRegion", "Republic of Srpska", "Bosnian and Herzegovinian Region"); 0949 } else { 0950 // TODO Note this does not give the current QLocale translation! 0951 regionName = QLocale::countryToString(codeToCountry(country)) + QLatin1String(" (") + subdivision + QLatin1Char(')'); 0952 } 0953 } else { 0954 // TODO Note this does not give the current QLocale translation! 0955 regionName = QLocale::countryToString(codeToCountry(country)); 0956 } 0957 } 0958 0959 // Cheat on type for now,take direct from region code until API is introduced in SC 4.6 0960 QStringList regionParts = regionCode().toLower().split(QLatin1Char('_')); 0961 if (regionParts.count() == 3) { 0962 const QString &type = regionParts.at(2); 0963 // Will create lots more in 4.6 0964 // Religious types, just simple for now 0965 if (type == QLatin1String("public")) { 0966 typeName = QCoreApplication::translate("HolidayRegion", "Public", "Holiday type"); 0967 } else if (type == QLatin1String("civil")) { 0968 typeName = QCoreApplication::translate("HolidayRegion", "Civil", "Holiday type"); 0969 } else if (type == QLatin1String("religious")) { 0970 typeName = QCoreApplication::translate("HolidayRegion", "Religious", "Holiday type"); 0971 } else if (type == QLatin1String("government")) { 0972 typeName = QCoreApplication::translate("HolidayRegion", "Government", "Holiday type"); 0973 } else if (type == QLatin1String("financial")) { 0974 typeName = QCoreApplication::translate("HolidayRegion", "Financial", "Holiday type"); 0975 } else if (type == QLatin1String("cultural")) { 0976 typeName = QCoreApplication::translate("HolidayRegion", "Cultural", "Holiday type"); 0977 } else if (type == QLatin1String("commemorative")) { 0978 typeName = QCoreApplication::translate("HolidayRegion", "Commemorative", "Holiday type"); 0979 } else if (type == QLatin1String("historical")) { 0980 typeName = QCoreApplication::translate("HolidayRegion", "Historical", "Holiday type"); 0981 } else if (type == QLatin1String("school")) { 0982 typeName = QCoreApplication::translate("HolidayRegion", "School", "Holiday type"); 0983 } else if (type == QLatin1String("seasonal")) { 0984 typeName = QCoreApplication::translate("HolidayRegion", "Seasonal", "Holiday type"); 0985 } else if (type == QLatin1String("nameday")) { 0986 typeName = QCoreApplication::translate("HolidayRegion", "Name Days", "Holiday type"); 0987 } else if (type == QLatin1String("personal")) { 0988 typeName = QCoreApplication::translate("HolidayRegion", "Personal", "Holiday type"); 0989 } else if (type == QLatin1String("christian")) { 0990 typeName = QCoreApplication::translate("HolidayRegion", "Christian", "Holiday type"); 0991 } else if (type == QLatin1String("anglican")) { 0992 typeName = QCoreApplication::translate("HolidayRegion", "Anglican", "Holiday type"); 0993 } else if (type == QLatin1String("catholic")) { 0994 typeName = QCoreApplication::translate("HolidayRegion", "Catholic", "Holiday type"); 0995 } else if (type == QLatin1String("protestant")) { 0996 typeName = QCoreApplication::translate("HolidayRegion", "Protestant", "Holiday type"); 0997 } else if (type == QLatin1String("orthodox")) { 0998 typeName = QCoreApplication::translate("HolidayRegion", "Orthodox", "Holiday type"); 0999 } else if (type == QLatin1String("jewish")) { 1000 typeName = QCoreApplication::translate("HolidayRegion", "Jewish", "Holiday type"); 1001 } else if (type == QLatin1String("jewish-orthodox")) { 1002 typeName = QCoreApplication::translate("HolidayRegion", "Jewish Orthodox", "Holiday type"); 1003 } else if (type == QLatin1String("jewish-conservative")) { 1004 typeName = QCoreApplication::translate("HolidayRegion", "Jewish Conservative", "Holiday type"); 1005 } else if (type == QLatin1String("jewish-reform")) { 1006 typeName = QCoreApplication::translate("HolidayRegion", "Jewish Reform", "Holiday type"); 1007 } else if (type == QLatin1String("islamic")) { 1008 typeName = QCoreApplication::translate("HolidayRegion", "Islamic", "Holiday type"); 1009 } else if (type == QLatin1String("islamic-sunni")) { 1010 typeName = QCoreApplication::translate("HolidayRegion", "Islamic Sunni", "Holiday type"); 1011 } else if (type == QLatin1String("islamic-shia")) { 1012 typeName = QCoreApplication::translate("HolidayRegion", "Islamic Shia", "Holiday type"); 1013 } else if (type == QLatin1String("islamic-sufi")) { 1014 typeName = QCoreApplication::translate("HolidayRegion", "Islamic Sufi", "Holiday type"); 1015 } 1016 } 1017 1018 if (!regionName.isEmpty()) { 1019 if (!typeName.isEmpty()) { 1020 tempName = QCoreApplication::translate("HolidayRegion", "%1 - %2", "Holiday file display name, %1 = region name, %2 = holiday type") 1021 .arg(regionName, typeName); 1022 } else { 1023 tempName = regionName; 1024 } 1025 } else if (!typeName.isEmpty()) { 1026 tempName = typeName; 1027 } else { 1028 tempName = QCoreApplication::translate("HolidayRegion", "Unknown", "Unknown holiday region"); 1029 } 1030 } 1031 return tempName; 1032 } 1033 1034 QString HolidayRegion::name(const QString ®ionCode) 1035 { 1036 HolidayRegion temp(regionCode); 1037 if (temp.isValid()) { 1038 return temp.name(); 1039 } else { 1040 return QString(); 1041 } 1042 } 1043 1044 QString HolidayRegion::description() const 1045 { 1046 return d->mDriver->fileDescription(); 1047 } 1048 1049 QString HolidayRegion::description(const QString ®ionCode) 1050 { 1051 HolidayRegion temp(regionCode); 1052 if (temp.isValid()) { 1053 return temp.description(); 1054 } else { 1055 return QString(); 1056 } 1057 } 1058 1059 bool HolidayRegion::isValid() const 1060 { 1061 return d->mHolidayFile.exists() && d->mDriver; 1062 } 1063 1064 bool HolidayRegion::isValid(const QString ®ionCode) 1065 { 1066 HolidayRegion temp(regionCode); 1067 return temp.isValid(); 1068 } 1069 1070 Holiday::List HolidayRegion::rawHolidays(const QDate &startDate, const QDate &endDate, const QString &category) const 1071 { 1072 if (isValid()) { 1073 return d->mDriver->parseHolidays(startDate, endDate, category); 1074 } else { 1075 return Holiday::List(); 1076 } 1077 } 1078 1079 #if KHOLIDAYS_BUILD_DEPRECATED_SINCE(5, 95) 1080 Holiday::List HolidayRegion::holidays(const QDate &startDate, const QDate &endDate) const 1081 { 1082 return rawHolidaysWithAstroSeasons(startDate, endDate); 1083 } 1084 #endif 1085 1086 Holiday::List HolidayRegion::rawHolidays(const QDate &startDate, const QDate &endDate) const 1087 { 1088 if (isValid()) { 1089 return d->mDriver->parseRawHolidays(startDate, endDate); 1090 } else { 1091 return Holiday::List(); 1092 } 1093 } 1094 1095 Holiday::List HolidayRegion::rawHolidaysWithAstroSeasons(const QDate &startDate, const QDate &endDate) const 1096 { 1097 if (isValid()) { 1098 return d->mDriver->parseHolidays(startDate, endDate); 1099 } else { 1100 return Holiday::List(); 1101 } 1102 } 1103 1104 #if KHOLIDAYS_BUILD_DEPRECATED_SINCE(5, 95) 1105 Holiday::List HolidayRegion::holidays(const QDate &date) const 1106 { 1107 return rawHolidaysWithAstroSeasons(date); 1108 } 1109 #endif 1110 1111 Holiday::List HolidayRegion::rawHolidaysWithAstroSeasons(const QDate &date) const 1112 { 1113 if (isValid()) { 1114 return d->mDriver->parseHolidays(date); 1115 } else { 1116 return Holiday::List(); 1117 } 1118 } 1119 1120 #if KHOLIDAYS_BUILD_DEPRECATED_SINCE(5, 95) 1121 Holiday::List HolidayRegion::holidays(int calendarYear) const 1122 { 1123 return rawHolidaysWithAstroSeasons(calendarYear); 1124 } 1125 #endif 1126 1127 Holiday::List HolidayRegion::rawHolidaysWithAstroSeasons(int calendarYear) const 1128 { 1129 if (isValid()) { 1130 return d->mDriver->parseHolidays(calendarYear); 1131 } else { 1132 return Holiday::List(); 1133 } 1134 } 1135 1136 bool HolidayRegion::isHoliday(const QDate &date) const 1137 { 1138 const Holiday::List holidayList = rawHolidaysWithAstroSeasons(date); 1139 if (!holidayList.isEmpty()) { 1140 for (const KHolidays::Holiday &holiday : holidayList) { 1141 if (holiday.dayType() == Holiday::NonWorkday) { 1142 return true; 1143 } 1144 } 1145 } 1146 return false; 1147 } 1148 1149 static bool maybeCountry(QStringView holidayId, QStringView country) 1150 { 1151 if (country.isEmpty()) { 1152 return false; 1153 } 1154 if (holidayId.size() < 2 || country.size() < 2 || (country.size() > 2 && country[2] != QLatin1Char('-'))) { 1155 return true; // not the format we expect, check the content 1156 } 1157 return holidayId.startsWith(country.left(2)); 1158 } 1159 1160 QString HolidayRegion::defaultRegionCode(const QString &country, const QString &language) 1161 { 1162 // Try to match against the users country and language, or failing that the language country. 1163 // Scan through all the regions finding the first match for each possible default 1164 // Holiday Region Country Code can be a country subdivision or the country itself, 1165 // e.g. US or US-CA for California, so we can try match on both but an exact match has priority 1166 // The Holiday Region file is in one language only, so give priority to any file in the 1167 // users language, e.g. bilingual countries with a separate file for each language 1168 // Locale language can have a country code embedded in it e.g. en_GB, which we can try use if 1169 // no country set, but a lot of countries use en_GB so it's a lower priority option 1170 1171 QString localeCountry; 1172 QString localeSubdivision; 1173 QString localeLanguage; 1174 QString localeLanguageCountry; 1175 1176 if (country.isEmpty()) { 1177 localeCountry = countryToCode(QLocale().country()).toLower(); 1178 } else { 1179 localeCountry = country.toLower(); 1180 const auto idx = localeCountry.indexOf(QLatin1Char('-')); 1181 localeSubdivision = idx > 0 ? localeCountry.left(idx) : localeCountry; 1182 } 1183 1184 if (language.isEmpty()) { 1185 localeLanguage = languageToCode(QLocale().language()).toLower(); 1186 } else { 1187 localeLanguage = language.toLower(); 1188 } 1189 1190 if (localeLanguage.split(QLatin1Char('_')).count() > 1) { 1191 localeLanguageCountry = localeLanguage.split(QLatin1Char('_')).at(1); 1192 } 1193 1194 QString countryAndLanguageMatch; 1195 QString countryOnlyMatch; 1196 QString subdivisionAndLanguageMatch; 1197 QString subdivisionOnlyMatch; 1198 QString languageCountryAndLanguageMatch; 1199 QString languageCountryOnlyMatch; 1200 QString languageSubdivisionAndLanguageMatch; 1201 QString languageSubdivisionOnlyMatch; 1202 1203 const QStringList regionList = KHolidays::HolidayRegion::regionCodes(); 1204 for (const QString &aRegionCode : regionList) { 1205 // avoid expensive parsing in most cases by leveraging the country being in the file name 1206 if (!maybeCountry(aRegionCode, localeCountry) && !maybeCountry(aRegionCode, localeLanguageCountry)) { 1207 continue; 1208 } 1209 1210 const auto hr = KHolidays::HolidayRegion(aRegionCode); 1211 QString regionCountry = hr.countryCode().toLower(); 1212 QString regionSubdivisionCountry; 1213 if (regionCountry.split(QLatin1Char('-')).count() > 1) { 1214 regionSubdivisionCountry = regionCountry.split(QLatin1Char('-')).at(0); 1215 } else { 1216 regionSubdivisionCountry = regionCountry; 1217 } 1218 QString regionLanguage = hr.languageCode().toLower(); 1219 1220 if (regionCountry == localeCountry && regionLanguage == localeLanguage) { 1221 // exact match so don't look further 1222 return aRegionCode; 1223 } else if (regionCountry == localeSubdivision && regionLanguage == localeLanguage) { 1224 countryAndLanguageMatch = aRegionCode; 1225 } else if (regionCountry == localeCountry) { 1226 if (countryOnlyMatch.isEmpty()) { 1227 countryOnlyMatch = aRegionCode; 1228 } 1229 } else if (!regionSubdivisionCountry.isEmpty() && regionSubdivisionCountry == localeSubdivision && regionLanguage == localeLanguage) { 1230 if (subdivisionAndLanguageMatch.isEmpty()) { 1231 subdivisionAndLanguageMatch = aRegionCode; 1232 } 1233 } else if (!regionSubdivisionCountry.isEmpty() && regionSubdivisionCountry == localeSubdivision) { 1234 if (subdivisionOnlyMatch.isEmpty()) { 1235 subdivisionOnlyMatch = aRegionCode; 1236 } 1237 } else if (!localeLanguageCountry.isEmpty() && regionCountry == localeLanguageCountry && regionLanguage == localeLanguage) { 1238 if (languageCountryAndLanguageMatch.isEmpty()) { 1239 languageCountryAndLanguageMatch = aRegionCode; 1240 } 1241 } else if (!localeLanguageCountry.isEmpty() && regionCountry == localeLanguageCountry) { 1242 if (languageCountryOnlyMatch.isEmpty()) { 1243 languageCountryOnlyMatch = aRegionCode; 1244 } 1245 } else if (!regionSubdivisionCountry.isEmpty() && !localeLanguageCountry.isEmpty() && regionSubdivisionCountry == localeLanguageCountry 1246 && regionLanguage == localeLanguage) { 1247 if (languageSubdivisionAndLanguageMatch.isEmpty()) { 1248 languageSubdivisionAndLanguageMatch = aRegionCode; 1249 } 1250 } else if (!regionSubdivisionCountry.isEmpty() && !localeLanguageCountry.isEmpty() && regionSubdivisionCountry == localeLanguageCountry) { 1251 if (languageSubdivisionOnlyMatch.isEmpty()) { 1252 languageSubdivisionOnlyMatch = aRegionCode; 1253 } 1254 } 1255 } 1256 1257 QString defaultRegionCode; 1258 1259 if (!countryAndLanguageMatch.isEmpty()) { 1260 defaultRegionCode = countryAndLanguageMatch; 1261 } else if (!countryOnlyMatch.isEmpty()) { 1262 defaultRegionCode = countryOnlyMatch; 1263 } else if (!subdivisionAndLanguageMatch.isEmpty()) { 1264 defaultRegionCode = subdivisionAndLanguageMatch; 1265 } else if (!subdivisionOnlyMatch.isEmpty()) { 1266 defaultRegionCode = subdivisionOnlyMatch; 1267 } else if (!languageCountryAndLanguageMatch.isEmpty()) { 1268 defaultRegionCode = languageCountryAndLanguageMatch; 1269 } else if (!languageCountryOnlyMatch.isEmpty()) { 1270 defaultRegionCode = languageCountryOnlyMatch; 1271 } else if (!languageSubdivisionAndLanguageMatch.isEmpty()) { 1272 defaultRegionCode = languageSubdivisionAndLanguageMatch; 1273 } else if (!languageSubdivisionOnlyMatch.isEmpty()) { 1274 defaultRegionCode = languageSubdivisionOnlyMatch; 1275 } 1276 1277 return defaultRegionCode; 1278 }