xref: /haiku/src/preferences/time/ZoneView.cpp (revision a096bb6509694fd2788ad557b6843ce5727de14e)
1a10cf76eSAxel Dörfler /*
24ae5a452SAdrien Destugues  * Copyright 2004-2010, Haiku, Inc. All Rights Reserved.
353d9356eSStephan Aßmus  * Distributed under the terms of the MIT License.
453d9356eSStephan Aßmus  *
553d9356eSStephan Aßmus  * Authors:
600826781SKarsten Heimrich  *		Mike Berg <mike@berg-net.us>
753d9356eSStephan Aßmus  *		Julun <host.haiku@gmx.de>
8310930fdSStephan Aßmus  *		Philippe Saint-Pierre <stpere@gmail.com>
94ae5a452SAdrien Destugues  *		Adrien Destugues <pulkomandy@pulkomandy.ath.cx>
1099d2aa98SOliver Tappe  *		Oliver Tappe <zooey@hirschkaefer.de>
1153d9356eSStephan Aßmus  */
1242b3a11fSStephan Aßmus 
13a10cf76eSAxel Dörfler 
1442b3a11fSStephan Aßmus #include "ZoneView.h"
15a10cf76eSAxel Dörfler 
16317bd7ddSAxel Dörfler #include <stdlib.h>
1742b3a11fSStephan Aßmus 
1838ac8defSOliver Tappe #include <new>
1938ac8defSOliver Tappe 
2038ac8defSOliver Tappe #include <AutoDeleter.h>
2142b3a11fSStephan Aßmus #include <Button.h>
2299d2aa98SOliver Tappe #include <Collator.h>
23a10cf76eSAxel Dörfler #include <Directory.h>
24a10cf76eSAxel Dörfler #include <Entry.h>
2585b54438SOliver Tappe #include <File.h>
26a10cf76eSAxel Dörfler #include <FindDirectory.h>
2742b3a11fSStephan Aßmus #include <ListItem.h>
284ae5a452SAdrien Destugues #include <Locale.h>
2938ac8defSOliver Tappe #include <MutableLocaleRoster.h>
304ae5a452SAdrien Destugues #include <OutlineListView.h>
3185b54438SOliver Tappe #include <Path.h>
32a10cf76eSAxel Dörfler #include <ScrollView.h>
33a10cf76eSAxel Dörfler #include <StorageDefs.h>
34a10cf76eSAxel Dörfler #include <String.h>
354ae5a452SAdrien Destugues #include <TimeZone.h>
36a10cf76eSAxel Dörfler #include <View.h>
37310930fdSStephan Aßmus #include <Window.h>
38a10cf76eSAxel Dörfler 
39317bd7ddSAxel Dörfler #include <syscalls.h>
40a10cf76eSAxel Dörfler 
4138ac8defSOliver Tappe #include <unicode/datefmt.h>
4238ac8defSOliver Tappe #include <unicode/utmscale.h>
4338ac8defSOliver Tappe #include <ICUWrapper.h>
4438ac8defSOliver Tappe 
45317bd7ddSAxel Dörfler #include "TimeMessages.h"
464ae5a452SAdrien Destugues #include "TimeZoneListItem.h"
47317bd7ddSAxel Dörfler #include "TZDisplay.h"
48317bd7ddSAxel Dörfler #include "TimeWindow.h"
49a10cf76eSAxel Dörfler 
50a10cf76eSAxel Dörfler 
5134a79bffSOliver Tappe using BPrivate::gMutableLocaleRoster;
5238ac8defSOliver Tappe using BPrivate::ObjectDeleter;
5399d2aa98SOliver Tappe 
5499d2aa98SOliver Tappe 
5585b69a94SKarsten Heimrich TimeZoneView::TimeZoneView(BRect frame)
5699d2aa98SOliver Tappe 	:
5799d2aa98SOliver Tappe 	BView(frame, "timeZoneView", B_FOLLOW_NONE, B_WILL_DRAW | B_NAVIGABLE_JUMP),
5838ac8defSOliver Tappe 	fCurrentZoneItem(NULL),
5938ac8defSOliver Tappe 	fOldZoneItem(NULL),
6099d2aa98SOliver Tappe 	fInitialized(false)
61a10cf76eSAxel Dörfler {
626d6408d6SOliver Tappe 	_InitView();
63a10cf76eSAxel Dörfler }
64a10cf76eSAxel Dörfler 
65a10cf76eSAxel Dörfler 
66310930fdSStephan Aßmus bool
67310930fdSStephan Aßmus TimeZoneView::CheckCanRevert()
68310930fdSStephan Aßmus {
6938ac8defSOliver Tappe 	return fCurrentZoneItem != fOldZoneItem;
70310930fdSStephan Aßmus }
71310930fdSStephan Aßmus 
72310930fdSStephan Aßmus 
73310930fdSStephan Aßmus void
74310930fdSStephan Aßmus TimeZoneView::_Revert()
75310930fdSStephan Aßmus {
7638ac8defSOliver Tappe 	fCurrentZoneItem = fOldZoneItem;
77310930fdSStephan Aßmus 
7838ac8defSOliver Tappe 	if (fCurrentZoneItem != NULL) {
7938ac8defSOliver Tappe 		int32 currentZoneIndex = fZoneList->IndexOf(fCurrentZoneItem);
8038ac8defSOliver Tappe 		fZoneList->Select(currentZoneIndex);
8138ac8defSOliver Tappe 	} else
8238ac8defSOliver Tappe 		fZoneList->DeselectAll();
8338ac8defSOliver Tappe 	fZoneList->ScrollToSelection();
844ae5a452SAdrien Destugues 
8538ac8defSOliver Tappe 	_SetSystemTimeZone();
8638ac8defSOliver Tappe 	_UpdatePreview();
8738ac8defSOliver Tappe 	_UpdateCurrent();
88310930fdSStephan Aßmus }
89310930fdSStephan Aßmus 
90310930fdSStephan Aßmus 
9185b69a94SKarsten Heimrich TimeZoneView::~TimeZoneView()
92a10cf76eSAxel Dörfler {
93a10cf76eSAxel Dörfler }
94a10cf76eSAxel Dörfler 
95a10cf76eSAxel Dörfler 
96a10cf76eSAxel Dörfler void
9785b69a94SKarsten Heimrich TimeZoneView::AttachedToWindow()
98a10cf76eSAxel Dörfler {
99a10cf76eSAxel Dörfler 	if (Parent())
100a10cf76eSAxel Dörfler 		SetViewColor(Parent()->ViewColor());
101a10cf76eSAxel Dörfler 
10285b69a94SKarsten Heimrich 	if (!fInitialized) {
10385b69a94SKarsten Heimrich 		fInitialized = true;
10485b69a94SKarsten Heimrich 
10542b3a11fSStephan Aßmus 		fSetZone->SetTarget(this);
10638ac8defSOliver Tappe 		fZoneList->SetTarget(this);
10742b3a11fSStephan Aßmus 
108a10cf76eSAxel Dörfler 		// update displays
1094ae5a452SAdrien Destugues 		int32 czone = 0;
11038ac8defSOliver Tappe 		if (fCurrentZoneItem != NULL) {
11138ac8defSOliver Tappe 			czone = fZoneList->IndexOf(fCurrentZoneItem);
112310930fdSStephan Aßmus 		} else {
1134ae5a452SAdrien Destugues 			// TODO : else, select ??!
11438ac8defSOliver Tappe 			fCurrentZoneItem = (TimeZoneListItem*)fZoneList->ItemAt(0);
1154ae5a452SAdrien Destugues 		}
1164ae5a452SAdrien Destugues 
11738ac8defSOliver Tappe 		fZoneList->Select(czone);
1184ae5a452SAdrien Destugues 
11938ac8defSOliver Tappe 		fZoneList->ScrollToSelection();
12038ac8defSOliver Tappe 		fCurrent->SetText(fCurrentZoneItem->Text());
121a10cf76eSAxel Dörfler 	}
12238ac8defSOliver Tappe 	fZoneList->ScrollToSelection();
123a10cf76eSAxel Dörfler }
124a10cf76eSAxel Dörfler 
125a10cf76eSAxel Dörfler 
126a10cf76eSAxel Dörfler void
12785b69a94SKarsten Heimrich TimeZoneView::MessageReceived(BMessage* message)
128a10cf76eSAxel Dörfler {
129a10cf76eSAxel Dörfler 	switch (message->what) {
130a10cf76eSAxel Dörfler 		case B_OBSERVER_NOTICE_CHANGE:
131317bd7ddSAxel Dörfler 		{
132317bd7ddSAxel Dörfler 			int32 change;
133a10cf76eSAxel Dörfler 			message->FindInt32(B_OBSERVE_WHAT_CHANGE, &change);
134a10cf76eSAxel Dörfler 			switch(change) {
135a10cf76eSAxel Dörfler 				case H_TM_CHANGED:
1366d6408d6SOliver Tappe 					_UpdateDateTime(message);
137a10cf76eSAxel Dörfler 					break;
138a10cf76eSAxel Dörfler 
139a10cf76eSAxel Dörfler 				default:
140a10cf76eSAxel Dörfler 					BView::MessageReceived(message);
141a10cf76eSAxel Dörfler 					break;
142a10cf76eSAxel Dörfler 			}
143a10cf76eSAxel Dörfler 			break;
144317bd7ddSAxel Dörfler 		}
145317bd7ddSAxel Dörfler 
146a10cf76eSAxel Dörfler 		case H_SET_TIME_ZONE:
147310930fdSStephan Aßmus 		{
14838ac8defSOliver Tappe 			_SetSystemTimeZone();
149310930fdSStephan Aßmus 			((TTimeWindow*)Window())->SetRevertStatus();
150310930fdSStephan Aßmus 			break;
151310930fdSStephan Aßmus 		}
152310930fdSStephan Aßmus 
153310930fdSStephan Aßmus 		case kMsgRevert:
154310930fdSStephan Aßmus 			_Revert();
155a10cf76eSAxel Dörfler 			break;
156a10cf76eSAxel Dörfler 
157a10cf76eSAxel Dörfler 		case H_CITY_CHANGED:
15838ac8defSOliver Tappe 			_UpdatePreview();
159a10cf76eSAxel Dörfler 			break;
160a10cf76eSAxel Dörfler 
161a10cf76eSAxel Dörfler 		default:
162a10cf76eSAxel Dörfler 			BView::MessageReceived(message);
163a10cf76eSAxel Dörfler 			break;
164a10cf76eSAxel Dörfler 	}
165a10cf76eSAxel Dörfler }
166a10cf76eSAxel Dörfler 
167a10cf76eSAxel Dörfler 
168a10cf76eSAxel Dörfler void
1696d6408d6SOliver Tappe TimeZoneView::_UpdateDateTime(BMessage* message)
170a10cf76eSAxel Dörfler {
17138ac8defSOliver Tappe 	// only need to update once every minute
17242b3a11fSStephan Aßmus 	int32 minute;
17338ac8defSOliver Tappe 	if (message->FindInt32("minute", &minute) == B_OK) {
17438ac8defSOliver Tappe 		if (fLastUpdateMinute != minute) {
17538ac8defSOliver Tappe 			_UpdateCurrent();
17638ac8defSOliver Tappe 			_UpdatePreview();
177a10cf76eSAxel Dörfler 
17838ac8defSOliver Tappe 			fLastUpdateMinute = minute;
179a10cf76eSAxel Dörfler 		}
180a10cf76eSAxel Dörfler 	}
181a10cf76eSAxel Dörfler }
182a10cf76eSAxel Dörfler 
183a10cf76eSAxel Dörfler 
184a10cf76eSAxel Dörfler void
1856d6408d6SOliver Tappe TimeZoneView::_InitView()
186a10cf76eSAxel Dörfler {
18742b3a11fSStephan Aßmus 	// left side
18842b3a11fSStephan Aßmus 	BRect frameLeft(Bounds());
18985b69a94SKarsten Heimrich 	frameLeft.right = frameLeft.Width() / 2.0;
19042b3a11fSStephan Aßmus 	frameLeft.InsetBy(10.0f, 10.0f);
191a10cf76eSAxel Dörfler 
192a10cf76eSAxel Dörfler 	// City Listing
19338ac8defSOliver Tappe 	fZoneList = new BOutlineListView(frameLeft, "cityList",
1944ae5a452SAdrien Destugues 		B_SINGLE_SELECTION_LIST);
19538ac8defSOliver Tappe 	fZoneList->SetSelectionMessage(new BMessage(H_CITY_CHANGED));
19638ac8defSOliver Tappe 	fZoneList->SetInvocationMessage(new BMessage(H_SET_TIME_ZONE));
197a10cf76eSAxel Dörfler 
1986d6408d6SOliver Tappe 	_BuildRegionMenu();
1994ae5a452SAdrien Destugues 
20038ac8defSOliver Tappe 	BScrollView* scrollList = new BScrollView("scrollList", fZoneList,
20142b3a11fSStephan Aßmus 		B_FOLLOW_ALL, 0, false, true);
202a10cf76eSAxel Dörfler 	AddChild(scrollList);
203a10cf76eSAxel Dörfler 
20442b3a11fSStephan Aßmus 	// right side
20542b3a11fSStephan Aßmus 	BRect frameRight(Bounds());
20685b69a94SKarsten Heimrich 	frameRight.left = frameRight.Width() / 2.0;
20742b3a11fSStephan Aßmus 	frameRight.InsetBy(10.0f, 10.0f);
20842b3a11fSStephan Aßmus 	frameRight.top = frameLeft.top;
209a10cf76eSAxel Dörfler 
210a10cf76eSAxel Dörfler 	// Time Displays
21185b69a94SKarsten Heimrich 	fCurrent = new TTZDisplay(frameRight, "currentTime", "Current time:");
21242b3a11fSStephan Aßmus 	AddChild(fCurrent);
21342b3a11fSStephan Aßmus 	fCurrent->ResizeToPreferred();
214a10cf76eSAxel Dörfler 
21585b69a94SKarsten Heimrich 	frameRight.top = fCurrent->Frame().bottom + 10.0;
21685b69a94SKarsten Heimrich 	fPreview = new TTZDisplay(frameRight, "previewTime", "Preview time:");
21742b3a11fSStephan Aßmus 	AddChild(fPreview);
21842b3a11fSStephan Aßmus 	fPreview->ResizeToPreferred();
219a10cf76eSAxel Dörfler 
220a10cf76eSAxel Dörfler 	// set button
2219c1a9b92SAdrien Destugues 	fSetZone = new BButton(frameRight, "setTimeZone", "Set time zone",
22285b69a94SKarsten Heimrich 		new BMessage(H_SET_TIME_ZONE));
22342b3a11fSStephan Aßmus 	AddChild(fSetZone);
22442b3a11fSStephan Aßmus 	fSetZone->SetEnabled(false);
22542b3a11fSStephan Aßmus 	fSetZone->ResizeToPreferred();
226a10cf76eSAxel Dörfler 
22742b3a11fSStephan Aßmus 	fSetZone->MoveTo(frameRight.right - fSetZone->Bounds().Width(),
22842b3a11fSStephan Aßmus 		scrollList->Frame().bottom - fSetZone->Bounds().Height());
229a10cf76eSAxel Dörfler }
230a10cf76eSAxel Dörfler 
231a10cf76eSAxel Dörfler 
232a10cf76eSAxel Dörfler void
2336d6408d6SOliver Tappe TimeZoneView::_BuildRegionMenu()
234a10cf76eSAxel Dörfler {
23538ac8defSOliver Tappe 	BTimeZone defaultTimeZone = NULL;
23699d2aa98SOliver Tappe 	be_locale_roster->GetDefaultTimeZone(&defaultTimeZone);
23799d2aa98SOliver Tappe 
23899d2aa98SOliver Tappe 	// Get a list of countries and, for each country, get all the timezones and
23999d2aa98SOliver Tappe 	// AddUnder() them (only if there are multiple ones).
24099d2aa98SOliver Tappe 	// Finally expand the current country and highlight the active TZ.
241a10cf76eSAxel Dörfler 
2424ae5a452SAdrien Destugues 	BMessage countryList;
2434ae5a452SAdrien Destugues 	be_locale_roster->GetAvailableCountries(&countryList);
244a10cf76eSAxel Dörfler 
2454ae5a452SAdrien Destugues 	BString countryCode;
2464ae5a452SAdrien Destugues 	for (int i = 0; countryList.FindString("countries", i, &countryCode)
2474ae5a452SAdrien Destugues 			== B_OK; i++) {
2484ae5a452SAdrien Destugues 		BCountry country("", countryCode);
2494ae5a452SAdrien Destugues 		BString fullName;
25038ac8defSOliver Tappe 		country.GetName(fullName);
251a10cf76eSAxel Dörfler 
2524ae5a452SAdrien Destugues 		// Now list the timezones for this country
2534ae5a452SAdrien Destugues 		BList tzList;
254a10cf76eSAxel Dörfler 
25599d2aa98SOliver Tappe 		BTimeZone* timeZone;
2564ae5a452SAdrien Destugues 		TimeZoneListItem* countryItem;
2574ae5a452SAdrien Destugues 		switch (country.GetTimeZones(tzList))
258a10cf76eSAxel Dörfler 		{
2594ae5a452SAdrien Destugues 			case 0:
2604ae5a452SAdrien Destugues 				// No TZ info for this country. Sorry guys!
2614ae5a452SAdrien Destugues 				break;
2624ae5a452SAdrien Destugues 			case 1:
2634ae5a452SAdrien Destugues 				// Only one Timezone, no need to add it to the list
26499d2aa98SOliver Tappe 				timeZone = (BTimeZone*)tzList.ItemAt(0);
26599d2aa98SOliver Tappe 				countryItem
26699d2aa98SOliver Tappe 					= new TimeZoneListItem(fullName, &country, timeZone);
26738ac8defSOliver Tappe 				fZoneList->AddItem(countryItem);
26838ac8defSOliver Tappe 				if (timeZone->Code() == defaultTimeZone.Code())
26938ac8defSOliver Tappe 					fCurrentZoneItem = countryItem;
2704ae5a452SAdrien Destugues 				break;
2714ae5a452SAdrien Destugues 			default:
2724ae5a452SAdrien Destugues 				countryItem = new TimeZoneListItem(fullName, &country, NULL);
27399d2aa98SOliver Tappe 				countryItem->SetExpanded(false);
27438ac8defSOliver Tappe 				fZoneList->AddItem(countryItem);
2754ae5a452SAdrien Destugues 
2766d6408d6SOliver Tappe 				for (int j = 0;
2776d6408d6SOliver Tappe 						(timeZone = (BTimeZone*)tzList.ItemAt(j)) != NULL;
2786d6408d6SOliver Tappe 						j++) {
27999d2aa98SOliver Tappe 					TimeZoneListItem* tzItem = new TimeZoneListItem(
28099d2aa98SOliver Tappe 						timeZone->Name(), NULL, timeZone);
28138ac8defSOliver Tappe 					fZoneList->AddUnder(tzItem, countryItem);
28238ac8defSOliver Tappe 					if (timeZone->Code() == defaultTimeZone.Code())
28399d2aa98SOliver Tappe 					{
28438ac8defSOliver Tappe 						fCurrentZoneItem = tzItem;
28599d2aa98SOliver Tappe 						countryItem->SetExpanded(true);
28699d2aa98SOliver Tappe 					}
28742b3a11fSStephan Aßmus 				}
2884ae5a452SAdrien Destugues 				break;
289a10cf76eSAxel Dörfler 		}
290a10cf76eSAxel Dörfler 	}
291317bd7ddSAxel Dörfler 
29238ac8defSOliver Tappe 	// add an artifical (i.e. belongs to no country) entry for GMT/UTC
29338ac8defSOliver Tappe 	BTimeZone* gmtZone = new(std::nothrow) BTimeZone(BTimeZone::kNameOfGmtZone);
29438ac8defSOliver Tappe 	TimeZoneListItem* gmtItem
29538ac8defSOliver Tappe 		= new TimeZoneListItem("- GMT/UTC (Universal Time) -", NULL, gmtZone);
29638ac8defSOliver Tappe 	fZoneList->AddItem(gmtItem);
29738ac8defSOliver Tappe 	if (gmtZone->Code() == defaultTimeZone.Code())
29838ac8defSOliver Tappe 		fCurrentZoneItem = gmtItem;
29999d2aa98SOliver Tappe 
30038ac8defSOliver Tappe 	fOldZoneItem = fCurrentZoneItem;
30199d2aa98SOliver Tappe 
30299d2aa98SOliver Tappe 	struct ListSorter {
30399d2aa98SOliver Tappe 		static int compare(const BListItem* first, const BListItem* second)
30499d2aa98SOliver Tappe 		{
30538ac8defSOliver Tappe 			static BCollator collator;
30638ac8defSOliver Tappe 			return collator.Compare(((BStringItem*)first)->Text(),
30799d2aa98SOliver Tappe 				((BStringItem*)second)->Text());
30899d2aa98SOliver Tappe 		}
30999d2aa98SOliver Tappe 	};
31038ac8defSOliver Tappe 	fZoneList->SortItemsUnder(NULL, false, ListSorter::compare);
311a10cf76eSAxel Dörfler }
312a10cf76eSAxel Dörfler 
313a10cf76eSAxel Dörfler 
314a10cf76eSAxel Dörfler void
31538ac8defSOliver Tappe TimeZoneView::_UpdatePreview()
316a10cf76eSAxel Dörfler {
31738ac8defSOliver Tappe 	int32 selection = fZoneList->CurrentSelection();
318a10cf76eSAxel Dörfler 	if (selection < 0)
319a10cf76eSAxel Dörfler 		return;
320a10cf76eSAxel Dörfler 
32138ac8defSOliver Tappe 	TimeZoneListItem* item = (TimeZoneListItem*)fZoneList->ItemAt(selection);
32238ac8defSOliver Tappe 	if (!item->HasTimeZone())
32338ac8defSOliver Tappe 		return;
324a10cf76eSAxel Dörfler 
32538ac8defSOliver Tappe 	BString timeString = _FormatTime(item);
32638ac8defSOliver Tappe 	fPreview->SetText(item->Text());
32738ac8defSOliver Tappe 	fPreview->SetTime(timeString.String());
328a10cf76eSAxel Dörfler 
32938ac8defSOliver Tappe 	fSetZone->SetEnabled((strcmp(fCurrent->Text(), item->Text()) != 0));
330a10cf76eSAxel Dörfler }
331a10cf76eSAxel Dörfler 
332a10cf76eSAxel Dörfler 
333a10cf76eSAxel Dörfler void
33438ac8defSOliver Tappe TimeZoneView::_UpdateCurrent()
335a10cf76eSAxel Dörfler {
33638ac8defSOliver Tappe 	if (fCurrentZoneItem == NULL)
33738ac8defSOliver Tappe 		return;
3381855b44cSAdrien Destugues 
33938ac8defSOliver Tappe 	BString timeString = _FormatTime(fCurrentZoneItem);
34038ac8defSOliver Tappe 	fCurrent->SetText(fCurrentZoneItem->Text());
34138ac8defSOliver Tappe 	fCurrent->SetTime(timeString.String());
342a10cf76eSAxel Dörfler }
343a10cf76eSAxel Dörfler 
34438ac8defSOliver Tappe 
34538ac8defSOliver Tappe void
34638ac8defSOliver Tappe TimeZoneView::_SetSystemTimeZone()
34738ac8defSOliver Tappe {
34838ac8defSOliver Tappe 	/*	Set sytem timezone for all different API levels. How to do this?
34938ac8defSOliver Tappe 	 *	1) tell locale-roster about new default timezone
35085b54438SOliver Tappe 	 *	2) tell kernel about new timezone offset
35185b54438SOliver Tappe 	 *	3) write new POSIX-timezone-info file
35238ac8defSOliver Tappe 	 */
35338ac8defSOliver Tappe 
35438ac8defSOliver Tappe 	int32 selection = fZoneList->CurrentSelection();
35538ac8defSOliver Tappe 	if (selection < 0)
35638ac8defSOliver Tappe 		return;
35738ac8defSOliver Tappe 
35838ac8defSOliver Tappe 	fCurrentZoneItem = (TimeZoneListItem*)(fZoneList->ItemAt(selection));
3590aa23047SOliver Tappe 	const BTimeZone& timeZone = fCurrentZoneItem->TimeZone();
36038ac8defSOliver Tappe 
36134a79bffSOliver Tappe 	gMutableLocaleRoster->SetDefaultTimeZone(timeZone);
36238ac8defSOliver Tappe 
3637e965f50SOliver Tappe 	_kern_set_timezone(timeZone.OffsetFromGMT());
36438ac8defSOliver Tappe 
36585b54438SOliver Tappe 	BPath path;
36685b54438SOliver Tappe 	status_t status = find_directory(B_COMMON_SETTINGS_DIRECTORY, &path, true);
36785b54438SOliver Tappe 	BFile file;
36885b54438SOliver Tappe 	if (status == B_OK) {
369*a096bb65SOliver Tappe 		path.Append("libroot_timezone_info");
37085b54438SOliver Tappe 		status = file.SetTo(path.Path(),
37185b54438SOliver Tappe 			B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY);
37285b54438SOliver Tappe 	}
37385b54438SOliver Tappe 	if (status == B_OK) {
374*a096bb65SOliver Tappe 		const BString& timeZoneID = timeZone.Code();
375*a096bb65SOliver Tappe 		file.Write(timeZoneID.String(), timeZoneID.Length());
37685b54438SOliver Tappe 		file.Sync();
37785b54438SOliver Tappe 	}
37885b54438SOliver Tappe 
37938ac8defSOliver Tappe 	fSetZone->SetEnabled(false);
38038ac8defSOliver Tappe 	fLastUpdateMinute = -1;
38138ac8defSOliver Tappe 		// just to trigger updating immediately
38238ac8defSOliver Tappe }
38338ac8defSOliver Tappe 
38438ac8defSOliver Tappe 
38538ac8defSOliver Tappe BString
38638ac8defSOliver Tappe TimeZoneView::_FormatTime(TimeZoneListItem* zoneItem)
38738ac8defSOliver Tappe {
38838ac8defSOliver Tappe 	BString result;
38938ac8defSOliver Tappe 
39038ac8defSOliver Tappe 	if (zoneItem == NULL)
39138ac8defSOliver Tappe 		return result;
39238ac8defSOliver Tappe 
3935c3a3034SAdrien Destugues 	BLocale locale;
3945c3a3034SAdrien Destugues 	be_locale_roster->GetDefaultLocale(&locale);
395*a096bb65SOliver Tappe 	time_t now = time(NULL);
396*a096bb65SOliver Tappe 	bool rtcIsGMT;
397*a096bb65SOliver Tappe 	_kern_get_real_time_clock_is_gmt(&rtcIsGMT);
398*a096bb65SOliver Tappe 	if (!rtcIsGMT) {
399*a096bb65SOliver Tappe 		now -= zoneItem->OffsetFromGMT() - fCurrentZoneItem->OffsetFromGMT();
400*a096bb65SOliver Tappe 	}
401*a096bb65SOliver Tappe 	locale.FormatTime(&result, now, false, &zoneItem->TimeZone());
40238ac8defSOliver Tappe 
40338ac8defSOliver Tappe 	return result;
40438ac8defSOliver Tappe }
405