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:
Oliver Tappe
2010-08-26 22:27:25 +00:00
parent 9ef134d918
commit 3740f52dca
3 changed files with 138 additions and 79 deletions
+1 -1
View File
@@ -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)
{ {
+88 -28
View File
@@ -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()
+1 -2
View File
@@ -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();