More Time preflet improvements:
* fixed another instance of BToolTip deletion, when we should be releasing a reference instead (the first one was fixed by Rene - thanks BTW!) * brought BCountry back into the game, such that the localized name of the country is now being used, where possible (avoiding the " Time" suffixes in English) * country-items containing only one timezone are now being filtered (the timezone moves up one level, replacing the country item, but adopting the country's name) * added the date to the timezone-item's tooltip, in order to make it obvious which timezone is "before" and which is "behind" the date-borderline I'm pretty happy with how it works now - what's yet missing is conversion of the preflet to the layout kit and localization of the GUI. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@38382 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -27,7 +27,7 @@ static const BString skDefaultString;
|
|||||||
TimeZoneListItem::TimeZoneListItem(const char* text, BCountry* country,
|
TimeZoneListItem::TimeZoneListItem(const char* text, BCountry* country,
|
||||||
BTimeZone* timeZone)
|
BTimeZone* timeZone)
|
||||||
:
|
:
|
||||||
BStringItem(text),
|
BStringItem(text, 0, false),
|
||||||
fIcon(NULL),
|
fIcon(NULL),
|
||||||
fTimeZone(timeZone)
|
fTimeZone(timeZone)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include <AutoDeleter.h>
|
#include <AutoDeleter.h>
|
||||||
#include <Button.h>
|
#include <Button.h>
|
||||||
#include <Collator.h>
|
#include <Collator.h>
|
||||||
|
#include <Country.h>
|
||||||
#include <Directory.h>
|
#include <Directory.h>
|
||||||
#include <Entry.h>
|
#include <Entry.h>
|
||||||
#include <File.h>
|
#include <File.h>
|
||||||
@@ -92,7 +93,7 @@ TimeZoneView::CheckCanRevert()
|
|||||||
|
|
||||||
TimeZoneView::~TimeZoneView()
|
TimeZoneView::~TimeZoneView()
|
||||||
{
|
{
|
||||||
if (fToolTip)
|
if (fToolTip != NULL)
|
||||||
fToolTip->ReleaseReference();
|
fToolTip->ReleaseReference();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,12 +182,22 @@ TimeZoneView::GetToolTipAt(BPoint point, BToolTip** _tip)
|
|||||||
if (item == NULL || !item->HasTimeZone())
|
if (item == NULL || !item->HasTimeZone())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
BString nowInTimeZone;
|
||||||
|
BLocale locale;
|
||||||
|
be_locale_roster->GetDefaultLocale(&locale);
|
||||||
|
time_t now = time(NULL);
|
||||||
|
locale.FormatTime(&nowInTimeZone, now, false, &item->TimeZone());
|
||||||
|
|
||||||
|
BString dateInTimeZone;
|
||||||
|
locale.FormatDate(&dateInTimeZone, now, false, &item->TimeZone());
|
||||||
|
|
||||||
BString toolTip = item->Text();
|
BString toolTip = item->Text();
|
||||||
toolTip << '\n' << item->TimeZone().ShortName() << " / "
|
toolTip << '\n' << item->TimeZone().ShortName() << " / "
|
||||||
<< item->TimeZone().ShortDaylightSavingName()
|
<< item->TimeZone().ShortDaylightSavingName()
|
||||||
<< "\nNow: " << _FormatTime(item->TimeZone(), false).String();
|
<< "\nNow: " << nowInTimeZone << " (" << dateInTimeZone << ')';
|
||||||
|
|
||||||
delete fToolTip;
|
if (fToolTip != NULL)
|
||||||
|
fToolTip->ReleaseReference();
|
||||||
fToolTip = new (std::nothrow) BTextToolTip(toolTip.String());
|
fToolTip = new (std::nothrow) BTextToolTip(toolTip.String());
|
||||||
if (fToolTip == NULL)
|
if (fToolTip == NULL)
|
||||||
return false;
|
return false;
|
||||||
@@ -270,13 +281,14 @@ TimeZoneView::_BuildZoneMenu()
|
|||||||
BLanguage defaultLanguage;
|
BLanguage defaultLanguage;
|
||||||
be_locale_roster->GetDefaultLanguage(&defaultLanguage);
|
be_locale_roster->GetDefaultLanguage(&defaultLanguage);
|
||||||
|
|
||||||
|
BMessage countryList;
|
||||||
|
be_locale_roster->GetAvailableCountries(&countryList);
|
||||||
|
countryList.AddString("countries", "");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Group timezones by regions, but filter out unwanted (duplicate) regions
|
* Group timezones by regions, but filter out unwanted (duplicate) regions
|
||||||
* and add an additional region with generic GMT-offset timezones at the end
|
* and add an additional region with generic GMT-offset timezones at the end
|
||||||
*/
|
*/
|
||||||
BMessage zoneList;
|
|
||||||
be_locale_roster->GetAvailableTimeZones(&zoneList);
|
|
||||||
|
|
||||||
typedef std::map<BString, TimeZoneListItem*, TimeZoneItemLess> ZoneItemMap;
|
typedef std::map<BString, TimeZoneListItem*, TimeZoneItemLess> ZoneItemMap;
|
||||||
ZoneItemMap zoneMap;
|
ZoneItemMap zoneMap;
|
||||||
const char* kOtherRegion = "<Other>";
|
const char* kOtherRegion = "<Other>";
|
||||||
@@ -287,12 +299,29 @@ TimeZoneView::_BuildZoneMenu()
|
|||||||
for (const char** region = kSupportedRegions; *region != NULL; ++region)
|
for (const char** region = kSupportedRegions; *region != NULL; ++region)
|
||||||
zoneMap[*region] = NULL;
|
zoneMap[*region] = NULL;
|
||||||
|
|
||||||
|
BString countryCode;
|
||||||
|
for (int c = 0; countryList.FindString("countries", c, &countryCode)
|
||||||
|
== B_OK; c++) {
|
||||||
|
BCountry country("", countryCode);
|
||||||
|
BString countryName;
|
||||||
|
country.GetName(countryName);
|
||||||
|
|
||||||
|
// Now list the timezones for this country
|
||||||
|
BMessage zoneList;
|
||||||
|
be_locale_roster->GetAvailableTimeZonesForCountry(&zoneList,
|
||||||
|
countryCode.Length() == 0 ? NULL : countryCode.String());
|
||||||
|
|
||||||
|
int32 count = 0;
|
||||||
|
type_code dummy;
|
||||||
|
zoneList.GetInfo("timeZone", &dummy, &count);
|
||||||
|
|
||||||
BString zoneID;
|
BString zoneID;
|
||||||
for (int i = 0; zoneList.FindString("timeZone", i, &zoneID) == B_OK; i++) {
|
for (int tz = 0; zoneList.FindString("timeZone", tz, &zoneID) == B_OK;
|
||||||
|
tz++) {
|
||||||
int32 slashPos = zoneID.FindFirst('/');
|
int32 slashPos = zoneID.FindFirst('/');
|
||||||
|
|
||||||
// ignore any "global" timezones, as those are just aliases of regional
|
// ignore any "global" timezones, as those are just aliases of
|
||||||
// ones
|
// regional ones
|
||||||
if (slashPos <= 0)
|
if (slashPos <= 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -300,17 +329,26 @@ TimeZoneView::_BuildZoneMenu()
|
|||||||
|
|
||||||
if (region == "Etc")
|
if (region == "Etc")
|
||||||
region = kOtherRegion;
|
region = kOtherRegion;
|
||||||
|
else if (countryName.Length() == 0) {
|
||||||
|
// skip global timezones from other regions, we are just
|
||||||
|
// interested in the generic GMT-based ones under "Etc/"
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// just accept timezones from "known" regions, as all others are aliases
|
|
||||||
|
// just accept timezones from "proper" regions, others are aliases
|
||||||
ZoneItemMap::iterator regionIter = zoneMap.find(region);
|
ZoneItemMap::iterator regionIter = zoneMap.find(region);
|
||||||
if (regionIter == zoneMap.end())
|
if (regionIter == zoneMap.end())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
BString fullCountryID = region;
|
||||||
|
if (countryName != region)
|
||||||
|
fullCountryID << "/" << countryName;
|
||||||
|
|
||||||
TimeZoneListItem* regionItem = regionIter->second;
|
TimeZoneListItem* regionItem = regionIter->second;
|
||||||
if (regionItem == NULL) {
|
if (regionItem == NULL) {
|
||||||
regionItem = new TimeZoneListItem(region, NULL, NULL);
|
regionItem = new TimeZoneListItem(region, NULL, NULL);
|
||||||
regionItem->SetOutlineLevel(0);
|
regionItem->SetOutlineLevel(0);
|
||||||
regionItem->SetExpanded(false);
|
|
||||||
zoneMap[region] = regionItem;
|
zoneMap[region] = regionItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -318,19 +356,14 @@ TimeZoneView::_BuildZoneMenu()
|
|||||||
BString tzName = timeZone->Name();
|
BString tzName = timeZone->Name();
|
||||||
if (tzName == "GMT+00:00")
|
if (tzName == "GMT+00:00")
|
||||||
tzName = "GMT";
|
tzName = "GMT";
|
||||||
|
|
||||||
int32 openParenthesisPos = tzName.FindFirst('(');
|
int32 openParenthesisPos = tzName.FindFirst('(');
|
||||||
BString country;
|
|
||||||
if (openParenthesisPos >= 0) {
|
if (openParenthesisPos >= 0) {
|
||||||
if (openParenthesisPos > 0)
|
|
||||||
country.SetTo(tzName, openParenthesisPos - 1);
|
|
||||||
tzName.Remove(0, openParenthesisPos + 1);
|
tzName.Remove(0, openParenthesisPos + 1);
|
||||||
int32 closeParenthesisPos = tzName.FindLast(')');
|
int32 closeParenthesisPos = tzName.FindLast(')');
|
||||||
if (closeParenthesisPos >= 0)
|
if (closeParenthesisPos >= 0)
|
||||||
tzName.Truncate(closeParenthesisPos);
|
tzName.Truncate(closeParenthesisPos);
|
||||||
}
|
}
|
||||||
BString fullCountryID = region;
|
|
||||||
if (country.Length() > 0 && country != region)
|
|
||||||
fullCountryID << "/" << country;
|
|
||||||
BString fullZoneID = fullCountryID;
|
BString fullZoneID = fullCountryID;
|
||||||
fullZoneID << "/" << tzName;
|
fullZoneID << "/" << tzName;
|
||||||
|
|
||||||
@@ -342,20 +375,23 @@ TimeZoneView::_BuildZoneMenu()
|
|||||||
}
|
}
|
||||||
|
|
||||||
TimeZoneListItem* countryItem = NULL;
|
TimeZoneListItem* countryItem = NULL;
|
||||||
if (country.Length() > 0) {
|
TimeZoneListItem* zoneItem = NULL;
|
||||||
|
if (count > 1 && countryName.Length() > 0) {
|
||||||
ZoneItemMap::iterator countryIter = zoneMap.find(fullCountryID);
|
ZoneItemMap::iterator countryIter = zoneMap.find(fullCountryID);
|
||||||
if (countryIter == zoneMap.end()) {
|
if (countryIter == zoneMap.end()) {
|
||||||
countryItem = new TimeZoneListItem(country, NULL, NULL);
|
countryItem = new TimeZoneListItem(countryName, NULL, NULL);
|
||||||
countryItem->SetOutlineLevel(1);
|
countryItem->SetOutlineLevel(1);
|
||||||
countryItem->SetExpanded(false);
|
|
||||||
zoneMap[fullCountryID] = countryItem;
|
zoneMap[fullCountryID] = countryItem;
|
||||||
} else
|
} else
|
||||||
countryItem = countryIter->second;
|
countryItem = countryIter->second;
|
||||||
}
|
|
||||||
|
|
||||||
TimeZoneListItem* zoneItem
|
zoneItem = new TimeZoneListItem(tzName, NULL, timeZone);
|
||||||
= new TimeZoneListItem(tzName, NULL, timeZone);
|
zoneItem->SetOutlineLevel(2);
|
||||||
zoneItem->SetOutlineLevel(countryItem == NULL ? 1 : 2);
|
} else {
|
||||||
|
BString& name = countryName.Length() > 0 ? countryName : tzName;
|
||||||
|
zoneItem = new TimeZoneListItem(name, NULL, timeZone);
|
||||||
|
zoneItem->SetOutlineLevel(1);
|
||||||
|
}
|
||||||
zoneMap[fullZoneID] = zoneItem;
|
zoneMap[fullZoneID] = zoneItem;
|
||||||
|
|
||||||
if (timeZone->ID() == defaultTimeZone.ID()) {
|
if (timeZone->ID() == defaultTimeZone.ID()) {
|
||||||
@@ -365,12 +401,37 @@ TimeZoneView::_BuildZoneMenu()
|
|||||||
regionItem->SetExpanded(true);
|
regionItem->SetExpanded(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fOldZoneItem = fCurrentZoneItem;
|
fOldZoneItem = fCurrentZoneItem;
|
||||||
|
|
||||||
ZoneItemMap::iterator zoneIter;
|
ZoneItemMap::iterator zoneIter;
|
||||||
for (zoneIter = zoneMap.begin(); zoneIter != zoneMap.end(); ++zoneIter)
|
bool lastWasCountryItem = false;
|
||||||
|
TimeZoneListItem* lastCountryItem = NULL;
|
||||||
|
for (zoneIter = zoneMap.begin(); zoneIter != zoneMap.end(); ++zoneIter) {
|
||||||
|
if (zoneIter->second->OutlineLevel() == 2 && lastWasCountryItem) {
|
||||||
|
/* Some countries (e.g. Spain and Chile) have their timezones
|
||||||
|
* spread across different regions. As a result, there might still
|
||||||
|
* be country items with only one timezone below them. We manually
|
||||||
|
* filter those country items here.
|
||||||
|
*/
|
||||||
|
ZoneItemMap::iterator next = zoneIter;
|
||||||
|
++next;
|
||||||
|
if (next != zoneMap.end() && next->second->OutlineLevel() != 2) {
|
||||||
|
fZoneList->RemoveItem(lastCountryItem);
|
||||||
|
zoneIter->second->SetText(lastCountryItem->Text());
|
||||||
|
zoneIter->second->SetOutlineLevel(1);
|
||||||
|
delete lastCountryItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fZoneList->AddItem(zoneIter->second);
|
fZoneList->AddItem(zoneIter->second);
|
||||||
|
if (zoneIter->second->OutlineLevel() == 1) {
|
||||||
|
lastWasCountryItem = true;
|
||||||
|
lastCountryItem = zoneIter->second;
|
||||||
|
} else
|
||||||
|
lastWasCountryItem = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -459,8 +520,7 @@ TimeZoneView::_SetSystemTimeZone()
|
|||||||
|
|
||||||
|
|
||||||
BString
|
BString
|
||||||
TimeZoneView::_FormatTime(const BTimeZone& timeZone,
|
TimeZoneView::_FormatTime(const BTimeZone& timeZone)
|
||||||
bool compensateForLocalOffset)
|
|
||||||
{
|
{
|
||||||
BString result;
|
BString result;
|
||||||
|
|
||||||
@@ -469,7 +529,7 @@ TimeZoneView::_FormatTime(const BTimeZone& timeZone,
|
|||||||
time_t now = time(NULL);
|
time_t now = time(NULL);
|
||||||
bool rtcIsGMT;
|
bool rtcIsGMT;
|
||||||
_kern_get_real_time_clock_is_gmt(&rtcIsGMT);
|
_kern_get_real_time_clock_is_gmt(&rtcIsGMT);
|
||||||
if (!rtcIsGMT && compensateForLocalOffset) {
|
if (!rtcIsGMT) {
|
||||||
int32 currentOffset
|
int32 currentOffset
|
||||||
= fCurrentZoneItem != NULL && fCurrentZoneItem->HasTimeZone()
|
= fCurrentZoneItem != NULL && fCurrentZoneItem->HasTimeZone()
|
||||||
? fCurrentZoneItem->OffsetFromGMT()
|
? fCurrentZoneItem->OffsetFromGMT()
|
||||||
|
|||||||
@@ -44,8 +44,7 @@ private:
|
|||||||
|
|
||||||
void _UpdatePreview();
|
void _UpdatePreview();
|
||||||
void _UpdateCurrent();
|
void _UpdateCurrent();
|
||||||
BString _FormatTime(const BTimeZone& timeZone,
|
BString _FormatTime(const BTimeZone& timeZone);
|
||||||
bool compensateForLocalOffset = true);
|
|
||||||
|
|
||||||
void _InitView();
|
void _InitView();
|
||||||
void _BuildZoneMenu();
|
void _BuildZoneMenu();
|
||||||
|
|||||||
Reference in New Issue
Block a user