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:
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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(¤t, &localTime);
|
gmtime_r(¤t, &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(¤t, &localTime);
|
localtime_r(¤t, &localTime);
|
||||||
|
|
||||||
set_timezone(timeZoneCode);
|
set_timezone(code.String());
|
||||||
// disable button
|
// disable button
|
||||||
fSetZone->SetEnabled(false);
|
fSetZone->SetEnabled(false);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user