Improved the Time preflet (still not working properly, though)

* basically rewrote TimeZone to sport a nicer to use interface
* adjusted all users of TimeZone accordingly
* changed TZDisplay to show the Date next to the label, in
  order to avoid that long timezone names draw all over it
* the timezone listview is now properly sorted according
  to the current language (using BCollator)
* fixed a couple of bugs (overflows, etc.) that caused
  incorrect GMT offsets to be used during computations


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@37813 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Oliver Tappe
2010-07-29 20:10:26 +00:00
parent 96e5a8739a
commit 99d2aa985b
9 changed files with 178 additions and 111 deletions
+23 -20
View File
@@ -1,31 +1,34 @@
/* /*
Copyright 2010, Haiku, Inc. * Copyright 2010, Haiku, Inc. All rights reserved.
Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#ifndef _TIME_ZONE_H
#define _TIME_ZONE_H
#ifndef __TIMEZONE_H__ #include <String.h>
#define __TIMEZONE_H__
class BString;
namespace icu_44 {
class TimeZone;
}
class BTimeZone { class BTimeZone {
public: public:
BTimeZone(const char* zoneCode); BTimeZone(const char* zoneCode = NULL);
~BTimeZone(); ~BTimeZone();
void GetName(BString& name); const BString& Code() const;
void GetCode(char* buffer, int size); const BString& Name() const;
int OffsetFromGMT(); int OffsetFromGMT() const;
private: status_t InitCheck() const;
icu_44::TimeZone* fICUTimeZone;
private:
void _Init(const char* zoneCode);
BString fCode;
BString fName;
int fOffsetFromGMT;
status_t fInitStatus;
}; };
#endif #endif // _TIME_ZONE_H
+1 -3
View File
@@ -1065,10 +1065,8 @@ BCountry::GetTimeZones(BList& timezones)
// remaining zones after that // remaining zones after that
while ((tzName = icuTimeZoneList->next(NULL, error)) != NULL) { while ((tzName = icuTimeZoneList->next(NULL, error)) != NULL) {
if (error == U_ZERO_ERROR) { if (error == U_ZERO_ERROR) {
BString readableName;
BTimeZone* timeZone = new BTimeZone(tzName); BTimeZone* timeZone = new BTimeZone(tzName);
timeZone->GetName(readableName); timeZoneMap.insert(std::pair<BString, BTimeZone*>(timeZone->Name(),
timeZoneMap.insert(std::pair<BString, BTimeZone*>(readableName,
timeZone)); timeZone));
} else } else
error = U_ZERO_ERROR; error = U_ZERO_ERROR;
+1 -1
View File
@@ -511,7 +511,7 @@ BLocaleRoster::GetDefaultTimeZone(BTimeZone **timezone) const
if (!timezone) if (!timezone)
return B_BAD_VALUE; return B_BAD_VALUE;
*timezone = new(std::nothrow) BTimeZone(""); *timezone = new(std::nothrow) BTimeZone();
return B_OK; return B_OK;
} }
+56 -29
View File
@@ -1,62 +1,89 @@
/* /*
Copyright 2010, Adrien Destugues <[email protected]> * Copyright (c) 2010, Haiku, Inc.
Distributed under the terms of the MIT License. * Distributed under the terms of the MIT license.
*/ *
* Authors:
* Adrien Destugues <[email protected]>
* Oliver Tappe <[email protected]>
*/
#include <TimeZone.h> #include <TimeZone.h>
#include <String.h>
#include <unicode/timezone.h> #include <unicode/timezone.h>
#include <ICUWrapper.h> #include <ICUWrapper.h>
BTimeZone::BTimeZone(const char* zoneCode) BTimeZone::BTimeZone(const char* zoneCode)
{ {
fICUTimeZone = TimeZone::createTimeZone(zoneCode); _Init(zoneCode);
} }
BTimeZone::~BTimeZone() BTimeZone::~BTimeZone()
{ {
delete fICUTimeZone;
} }
void const BString&
BTimeZone::GetName(BString& name) BTimeZone::Name() const
{ {
UnicodeString unicodeName; return fName;
fICUTimeZone->getDisplayName(unicodeName);
BStringByteSink converter(&name);
unicodeName.toUTF8(converter);
} }
void const BString&
BTimeZone::GetCode(char* buffer, int size) BTimeZone::Code() const
{ {
UnicodeString unicodeName; return fCode;
fICUTimeZone->getID(unicodeName);
CheckedArrayByteSink converter(buffer, size);
unicodeName.toUTF8(converter);
} }
int int
BTimeZone::OffsetFromGMT() BTimeZone::OffsetFromGMT() const
{ {
return fOffsetFromGMT;
}
status_t
BTimeZone::InitCheck() const
{
return fInitStatus;
}
void
BTimeZone::_Init(const char* zoneCode)
{
TimeZone* icuTimeZone;
if (zoneCode == NULL || zoneCode[0] == '\0')
icuTimeZone = TimeZone::createDefault();
else
icuTimeZone = TimeZone::createTimeZone(zoneCode);
UnicodeString unicodeString;
icuTimeZone->getID(unicodeString);
BStringByteSink converter(&fCode);
unicodeString.toUTF8(converter);
unicodeString.remove();
icuTimeZone->getDisplayName(unicodeString);
converter.SetTo(&fName);
unicodeString.toUTF8(converter);
int32_t rawOffset; int32_t rawOffset;
int32_t dstOffset; int32_t dstOffset;
time_t now; UDate nowMillis = 1000 * (double)time(NULL);
UErrorCode error = U_ZERO_ERROR; UErrorCode error = U_ZERO_ERROR;
fICUTimeZone->getOffset(time(&now) * 1000, FALSE, rawOffset, dstOffset icuTimeZone->getOffset(nowMillis, FALSE, rawOffset, dstOffset, error);
, error);
if (error != U_ZERO_ERROR) if (error != U_ZERO_ERROR) {
return 0; fOffsetFromGMT = 0;
else fInitStatus = B_ERROR;
return rawOffset + dstOffset; } else {
fOffsetFromGMT = (rawOffset + dstOffset) / 1000;
// we want seconds, not ms (which ICU gives us)
fInitStatus = B_OK;
}
} }
+11 -11
View File
@@ -5,19 +5,19 @@ SetSubDirSupportedPlatformsBeOSCompatible ;
UsePrivateHeaders shared ; UsePrivateHeaders shared ;
UsePrivateSystemHeaders ; UsePrivateSystemHeaders ;
Preference Time : Preference Time :
AnalogClock.cpp AnalogClock.cpp
BaseView.cpp BaseView.cpp
Bitmaps.cpp Bitmaps.cpp
DateTimeEdit.cpp DateTimeEdit.cpp
SectionEdit.cpp SectionEdit.cpp
DateTimeView.cpp DateTimeView.cpp
Time.cpp Time.cpp
TimeSettings.cpp TimeSettings.cpp
TimeWindow.cpp TimeWindow.cpp
TimeZoneListItem.cpp TimeZoneListItem.cpp
TZDisplay.cpp TZDisplay.cpp
ZoneView.cpp ZoneView.cpp
: be libshared.a $(TARGET_LIBSUPC++) $(HAIKU_LOCALE_LIBS) : be libshared.a $(TARGET_LIBSUPC++) $(HAIKU_LOCALE_LIBS)
: Time.rdef : Time.rdef
; ;
+1
View File
@@ -71,6 +71,7 @@ TTZDisplay::Draw(BRect /* updateRect */)
pt.y += fontHeight; pt.y += fontHeight;
DrawString(fText.String(), pt); DrawString(fText.String(), pt);
pt.y -= fontHeight;
pt.x = bounds.right - StringWidth(fTime.String()) - 2.0; pt.x = bounds.right - StringWidth(fTime.String()) - 2.0;
DrawString(fTime.String(), pt); DrawString(fTime.String(), pt);
} }
+28 -7
View File
@@ -21,6 +21,9 @@
#include <Window.h> #include <Window.h>
static const BString skDefaultString;
TimeZoneListItem::TimeZoneListItem(const char* text, BCountry* country, TimeZoneListItem::TimeZoneListItem(const char* text, BCountry* country,
BTimeZone* timeZone) BTimeZone* timeZone)
: :
@@ -92,13 +95,31 @@ TimeZoneListItem::DrawItem(BView* owner, BRect frame, bool complete)
} }
void const BString&
TimeZoneListItem::Code(char* buffer) TimeZoneListItem::Code() const
{ {
if (fTimeZone == NULL) { if (fTimeZone == NULL)
buffer[0] = '\0'; return skDefaultString;
return;
}
fTimeZone->GetCode(buffer, 50); return fTimeZone->Code();
}
const BString&
TimeZoneListItem::Name() const
{
if (fTimeZone == NULL)
return skDefaultString;
return fTimeZone->Name();
}
int
TimeZoneListItem::OffsetFromGMT() const
{
if (fTimeZone == NULL)
return 0;
return fTimeZone->OffsetFromGMT();
} }
+4 -1
View File
@@ -26,7 +26,10 @@ public:
void DrawItem(BView* owner, BRect frame, void DrawItem(BView* owner, BRect frame,
bool complete = false); bool complete = false);
void Code(char* buffer);
const BString& Code() const;
const BString& Name() const;
int OffsetFromGMT() const;
private: private:
BBitmap* fIcon; BBitmap* fIcon;
+53 -39
View File
@@ -7,6 +7,7 @@
* Julun <[email protected]> * Julun <[email protected]>
* Philippe Saint-Pierre <[email protected]> * Philippe Saint-Pierre <[email protected]>
* Adrien Destugues <[email protected]> * Adrien Destugues <[email protected]>
* Oliver Tappe <[email protected]>
*/ */
/* /*
@@ -20,6 +21,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <Button.h> #include <Button.h>
#include <Collator.h>
#include <Directory.h> #include <Directory.h>
#include <Entry.h> #include <Entry.h>
#include <FindDirectory.h> #include <FindDirectory.h>
@@ -42,13 +44,17 @@
#include "TimeWindow.h" #include "TimeWindow.h"
static BCollator sCollator;
// used to sort the timezone list
TimeZoneView::TimeZoneView(BRect frame) TimeZoneView::TimeZoneView(BRect frame)
: BView(frame, "timeZoneView", B_FOLLOW_NONE, B_WILL_DRAW :
| B_NAVIGABLE_JUMP), fInitialized(false) BView(frame, "timeZoneView", B_FOLLOW_NONE, B_WILL_DRAW | B_NAVIGABLE_JUMP),
fCurrentZone(NULL),
fOldZone(NULL),
fInitialized(false)
{ {
fCurrentZone = NULL;
fOldZone = NULL;
// TODO : get default timezone from locale kit
_InitView(); _InitView();
} }
@@ -231,10 +237,12 @@ TimeZoneView::_InitView()
void void
TimeZoneView::_BuildRegionMenu() TimeZoneView::_BuildRegionMenu()
{ {
// Get a list of countries BTimeZone* defaultTimeZone = NULL;
// For each country, get all the timezones and AddItemUnder them be_locale_roster->GetDefaultTimeZone(&defaultTimeZone);
// (only if there are multiple ones ?)
// Unfold the current country and highlight the selected TZ // Get a list of countries and, for each country, get all the timezones and
// AddUnder() them (only if there are multiple ones).
// Finally expand the current country and highlight the active TZ.
BMessage countryList; BMessage countryList;
be_locale_roster->GetAvailableCountries(&countryList); be_locale_roster->GetAvailableCountries(&countryList);
@@ -249,6 +257,7 @@ TimeZoneView::_BuildRegionMenu()
// Now list the timezones for this country // Now list the timezones for this country
BList tzList; BList tzList;
BTimeZone* timeZone;
TimeZoneListItem* countryItem; TimeZoneListItem* countryItem;
switch (country.GetTimeZones(tzList)) switch (country.GetTimeZones(tzList))
{ {
@@ -257,30 +266,47 @@ TimeZoneView::_BuildRegionMenu()
break; break;
case 1: case 1:
// Only one Timezone, no need to add it to the list // Only one Timezone, no need to add it to the list
countryItem = new TimeZoneListItem(fullName, &country, timeZone = (BTimeZone*)tzList.ItemAt(0);
(BTimeZone*)tzList.ItemAt(0)); countryItem
= new TimeZoneListItem(fullName, &country, timeZone);
fCityList->AddItem(countryItem); fCityList->AddItem(countryItem);
if (timeZone->Code() == defaultTimeZone->Code())
fCurrentZone = countryItem;
break; break;
default: default:
countryItem = new TimeZoneListItem(fullName, &country, NULL); countryItem = new TimeZoneListItem(fullName, &country, NULL);
countryItem->SetExpanded(false);
fCityList->AddItem(countryItem); fCityList->AddItem(countryItem);
BTimeZone* timeZone;
for (int j = 0; for (int j = 0;
(timeZone = (BTimeZone*)tzList.ItemAt(j)) != NULL; (timeZone = (BTimeZone*)tzList.ItemAt(j)) != NULL;
j++) { j++) {
BString readableName; TimeZoneListItem* tzItem = new TimeZoneListItem(
timeZone->GetName(readableName); timeZone->Name(), NULL, timeZone);
BStringItem* tzItem = new TimeZoneListItem(readableName,
NULL, timeZone);
fCityList->AddUnder(tzItem, countryItem); fCityList->AddUnder(tzItem, countryItem);
if (timeZone->Code() == defaultTimeZone->Code())
{
fCurrentZone = tzItem;
countryItem->SetExpanded(true);
}
} }
break; break;
} }
} }
fCurrentZone = fOldZone = (TimeZoneListItem*)fCityList->ItemAt(0); fOldZone = fCurrentZone;
// TODO get the actual setting from locale kit
delete defaultTimeZone;
struct ListSorter {
static int compare(const BListItem* first, const BListItem* second)
{
return sCollator.Compare(((BStringItem*)first)->Text(),
((BStringItem*)second)->Text());
}
};
fCityList->SortItemsUnder(NULL, true, ListSorter::compare);
} }
@@ -289,26 +315,18 @@ TimeZoneView::_SetPreview()
{ {
int32 selection = fCityList->CurrentSelection(); int32 selection = fCityList->CurrentSelection();
if (selection >= 0) { if (selection >= 0) {
TimeZoneListItem* item = (TimeZoneListItem*)fCityList->ItemAt( TimeZoneListItem* item
selection); = (TimeZoneListItem*)fCityList->ItemAt(selection);
// set timezone to selection
char buffer[50];
item->Code(buffer);
_SetTimeZone(buffer);
// calc preview time // calc preview time
time_t current = time(NULL); time_t current = time(NULL) + item->OffsetFromGMT();
struct tm localTime; struct tm localTime;
localtime_r(&current, &localTime); gmtime_r(&current, &localTime);
// update prview // update prview
fPreview->SetText(item->Text()); fPreview->SetText(item->Text());
fPreview->SetTime(localTime.tm_hour, localTime.tm_min); fPreview->SetTime(localTime.tm_hour, localTime.tm_min);
fCurrentZone->Code(buffer);
_SetTimeZone(buffer);
fSetZone->SetEnabled((strcmp(fCurrent->Text(), item->Text()) != 0)); fSetZone->SetEnabled((strcmp(fCurrent->Text(), item->Text()) != 0));
} }
} }
@@ -317,9 +335,7 @@ TimeZoneView::_SetPreview()
void void
TimeZoneView::_SetCurrent(const char* text) TimeZoneView::_SetCurrent(const char* text)
{ {
char buffer[50]; _SetTimeZone(fCurrentZone->Code().String());
fCurrentZone->Code(buffer);
_SetTimeZone(buffer);
time_t current = time(NULL); time_t current = time(NULL);
struct tm localTime; struct tm localTime;
@@ -345,18 +361,16 @@ TimeZoneView::_SetTimeZone()
if (selection < 0) if (selection < 0)
return; return;
char timeZoneCode[50]; const BString& code
((TimeZoneListItem*)fCityList->ItemAt(selection))->Code(timeZoneCode); = ((TimeZoneListItem*)fCityList->ItemAt(selection))->Code();
_SetTimeZone(code.String());
// update environment
_SetTimeZone(timeZoneCode);
// update display // update display
time_t current = time(NULL); time_t current = time(NULL);
struct tm localTime; struct tm localTime;
localtime_r(&current, &localTime); localtime_r(&current, &localTime);
set_timezone(timeZoneCode); set_timezone(code.String());
// disable button // disable button
fSetZone->SetEnabled(false); fSetZone->SetEnabled(false);