xref: /haiku/src/preferences/time/DateTimeView.cpp (revision c2f3ee3b7b386d538f1181e7dc5e277307229c78)
1e4289a54SKarsten Heimrich /*
2323ba9b7SRyan Leavengood  * Copyright 2004-2011, Haiku, Inc. All Rights Reserved.
3e4289a54SKarsten Heimrich  * Distributed under the terms of the MIT License.
4e4289a54SKarsten Heimrich  *
5e4289a54SKarsten Heimrich  * Authors:
6e4289a54SKarsten Heimrich  *		Andrew McCall <mccall@@digitalparadise.co.uk>
7e4289a54SKarsten Heimrich  *		Mike Berg <mike@berg-net.us>
8e4289a54SKarsten Heimrich  *		Julun <host.haiku@gmx.de>
91cae077aSStephan Aßmus  *		Philippe Saint-Pierre <stpere@gmail.com>
10323ba9b7SRyan Leavengood  *		Hamish Morrison <hamish@lavabit.com>
11e4289a54SKarsten Heimrich  */
12e4289a54SKarsten Heimrich 
13e4289a54SKarsten Heimrich #include "DateTimeView.h"
14e4289a54SKarsten Heimrich 
15323ba9b7SRyan Leavengood #include <time.h>
16323ba9b7SRyan Leavengood #include <syscalls.h>
17323ba9b7SRyan Leavengood 
18323ba9b7SRyan Leavengood #include <Box.h>
1978092ae7SKarsten Heimrich #include <CalendarView.h>
209717d515SJoachim Seemer #include <Catalog.h>
21e4289a54SKarsten Heimrich #include <CheckBox.h>
22365839fbSRyan Leavengood #include <ControlLook.h>
2378092ae7SKarsten Heimrich #include <DateTime.h>
24e4289a54SKarsten Heimrich #include <Entry.h>
25e4289a54SKarsten Heimrich #include <File.h>
26e4289a54SKarsten Heimrich #include <FindDirectory.h>
27e4289a54SKarsten Heimrich #include <Message.h>
28e4289a54SKarsten Heimrich #include <Path.h>
29e4289a54SKarsten Heimrich #include <StringView.h>
30e4289a54SKarsten Heimrich #include <Window.h>
3138ac8defSOliver Tappe 
32323ba9b7SRyan Leavengood #include "AnalogClock.h"
33323ba9b7SRyan Leavengood #include "DateTimeEdit.h"
34323ba9b7SRyan Leavengood #include "TimeMessages.h"
35323ba9b7SRyan Leavengood #include "TimeWindow.h"
36e4289a54SKarsten Heimrich 
3738ac8defSOliver Tappe 
389717d515SJoachim Seemer #undef B_TRANSLATE_CONTEXT
399717d515SJoachim Seemer #define B_TRANSLATE_CONTEXT "Time"
409717d515SJoachim Seemer 
41e4289a54SKarsten Heimrich 
4278092ae7SKarsten Heimrich using BPrivate::BCalendarView;
4378092ae7SKarsten Heimrich using BPrivate::BDateTime;
4478092ae7SKarsten Heimrich using BPrivate::B_LOCAL_TIME;
4578092ae7SKarsten Heimrich 
4678092ae7SKarsten Heimrich 
47323ba9b7SRyan Leavengood DateTimeView::DateTimeView(const char* name)
48323ba9b7SRyan Leavengood 	:
49323ba9b7SRyan Leavengood 	BGroupView(name, B_HORIZONTAL, 5),
501cae077aSStephan Aßmus 	fInitialized(false),
511cae077aSStephan Aßmus 	fSystemTimeAtStart(system_time())
52e4289a54SKarsten Heimrich {
5385b69a94SKarsten Heimrich 	_InitView();
541cae077aSStephan Aßmus 
551cae077aSStephan Aßmus 	// record the current time to enable revert.
561cae077aSStephan Aßmus 	time(&fTimeAtStart);
57e4289a54SKarsten Heimrich }
58e4289a54SKarsten Heimrich 
59e4289a54SKarsten Heimrich 
60e4289a54SKarsten Heimrich DateTimeView::~DateTimeView()
61e4289a54SKarsten Heimrich {
62e4289a54SKarsten Heimrich }
63e4289a54SKarsten Heimrich 
64e4289a54SKarsten Heimrich 
65e4289a54SKarsten Heimrich void
66e4289a54SKarsten Heimrich DateTimeView::AttachedToWindow()
67e4289a54SKarsten Heimrich {
68e4289a54SKarsten Heimrich 	if (Parent())
69e4289a54SKarsten Heimrich 		SetViewColor(Parent()->ViewColor());
70e4289a54SKarsten Heimrich 
71e4289a54SKarsten Heimrich 	if (!fInitialized) {
72e4289a54SKarsten Heimrich 		fInitialized = true;
7385b69a94SKarsten Heimrich 
7485b69a94SKarsten Heimrich 		fCalendarView->SetTarget(this);
75e4289a54SKarsten Heimrich 	}
76f64b502dSRyan Leavengood 
77f64b502dSRyan Leavengood 	_NotifyClockSettingChanged();
78e4289a54SKarsten Heimrich }
79e4289a54SKarsten Heimrich 
80e4289a54SKarsten Heimrich 
81e4289a54SKarsten Heimrich void
82e4289a54SKarsten Heimrich DateTimeView::MessageReceived(BMessage* message)
83e4289a54SKarsten Heimrich {
84e4289a54SKarsten Heimrich 	int32 change;
85e4289a54SKarsten Heimrich 	switch (message->what) {
86e4289a54SKarsten Heimrich 		case B_OBSERVER_NOTICE_CHANGE:
87e4289a54SKarsten Heimrich 			message->FindInt32(B_OBSERVE_WHAT_CHANGE, &change);
88e4289a54SKarsten Heimrich 			switch (change) {
89e4289a54SKarsten Heimrich 				case H_TM_CHANGED:
90e4289a54SKarsten Heimrich 					_UpdateDateTime(message);
91e4289a54SKarsten Heimrich 					break;
92e4289a54SKarsten Heimrich 
93e4289a54SKarsten Heimrich 				default:
94e4289a54SKarsten Heimrich 					BView::MessageReceived(message);
95e4289a54SKarsten Heimrich 					break;
96e4289a54SKarsten Heimrich 			}
97e4289a54SKarsten Heimrich 			break;
98e4289a54SKarsten Heimrich 
99e4289a54SKarsten Heimrich 		case kDayChanged:
100e4289a54SKarsten Heimrich 		{
101e4289a54SKarsten Heimrich 			BMessage msg(*message);
102e4289a54SKarsten Heimrich 			msg.what = H_USER_CHANGE;
103e4289a54SKarsten Heimrich 			msg.AddBool("time", false);
104e4289a54SKarsten Heimrich 			Window()->PostMessage(&msg);
1051cae077aSStephan Aßmus 			break;
1061cae077aSStephan Aßmus 		}
107e4289a54SKarsten Heimrich 
1081cae077aSStephan Aßmus 		case kMsgRevert:
1091cae077aSStephan Aßmus 			_Revert();
110e4289a54SKarsten Heimrich 			break;
111e4289a54SKarsten Heimrich 
1123e58fe9eSStephan Aßmus 		case kChangeTimeFinished:
1133e58fe9eSStephan Aßmus 			if (fClock->IsChangingTime())
1143e58fe9eSStephan Aßmus 				fTimeEdit->MakeFocus(false);
1153e58fe9eSStephan Aßmus 			fClock->ChangeTimeFinished();
1163e58fe9eSStephan Aßmus 			break;
117d3bde5deSAxel Dörfler 
118*c2f3ee3bSAdrien Destugues 		case kRTCUpdate:
119*c2f3ee3bSAdrien Destugues 			break;
120*c2f3ee3bSAdrien Destugues 
121e4289a54SKarsten Heimrich 		default:
122e4289a54SKarsten Heimrich 			BView::MessageReceived(message);
123e4289a54SKarsten Heimrich 			break;
124e4289a54SKarsten Heimrich 	}
125e4289a54SKarsten Heimrich }
126e4289a54SKarsten Heimrich 
127e4289a54SKarsten Heimrich 
128310930fdSStephan Aßmus bool
1291cae077aSStephan Aßmus DateTimeView::CheckCanRevert()
1301cae077aSStephan Aßmus {
1311cae077aSStephan Aßmus 	// check for changed time
1321cae077aSStephan Aßmus 	time_t unchangedNow = fTimeAtStart + _PrefletUptime();
1331cae077aSStephan Aßmus 	time_t changedNow;
1341cae077aSStephan Aßmus 	time(&changedNow);
1351cae077aSStephan Aßmus 
136*c2f3ee3bSAdrien Destugues 	return changedNow != unchangedNow;
1371cae077aSStephan Aßmus }
1381cae077aSStephan Aßmus 
1391cae077aSStephan Aßmus 
1401cae077aSStephan Aßmus void
1411cae077aSStephan Aßmus DateTimeView::_Revert()
1421cae077aSStephan Aßmus {
1431cae077aSStephan Aßmus 	// Set the clock and calendar as they were at launch time +
144d3bde5deSAxel Dörfler 	// time elapsed since application launch.
1451cae077aSStephan Aßmus 
1461cae077aSStephan Aßmus 	time_t timeNow = fTimeAtStart + _PrefletUptime();
1471cae077aSStephan Aßmus 	struct tm result;
1481cae077aSStephan Aßmus 	struct tm* timeInfo;
1491cae077aSStephan Aßmus 	timeInfo = localtime_r(&timeNow, &result);
1501cae077aSStephan Aßmus 
1511cae077aSStephan Aßmus 	BDateTime dateTime = BDateTime::CurrentDateTime(B_LOCAL_TIME);
1521cae077aSStephan Aßmus 	BTime time = dateTime.Time();
1531cae077aSStephan Aßmus 	BDate date = dateTime.Date();
1541cae077aSStephan Aßmus 	time.SetTime(timeInfo->tm_hour, timeInfo->tm_min, timeInfo->tm_sec % 60);
1551cae077aSStephan Aßmus 	date.SetDate(timeInfo->tm_year + 1900, timeInfo->tm_mon + 1,
1561cae077aSStephan Aßmus 		timeInfo->tm_mday);
1571cae077aSStephan Aßmus 	dateTime.SetTime(time);
1581cae077aSStephan Aßmus 	dateTime.SetDate(date);
1591cae077aSStephan Aßmus 
1601cae077aSStephan Aßmus 	set_real_time_clock(dateTime.Time_t());
1611cae077aSStephan Aßmus }
1621cae077aSStephan Aßmus 
1631cae077aSStephan Aßmus 
1641cae077aSStephan Aßmus time_t
1651cae077aSStephan Aßmus DateTimeView::_PrefletUptime() const
1661cae077aSStephan Aßmus {
1671cae077aSStephan Aßmus 	return (time_t)((system_time() - fSystemTimeAtStart) / 1000000);
1681cae077aSStephan Aßmus }
1691cae077aSStephan Aßmus 
1701cae077aSStephan Aßmus 
1711cae077aSStephan Aßmus void
172e4289a54SKarsten Heimrich DateTimeView::_InitView()
173e4289a54SKarsten Heimrich {
1746846765fSOliver Tappe 	fCalendarView = new BCalendarView("calendar");
175e4289a54SKarsten Heimrich 	fCalendarView->SetWeekNumberHeaderVisible(false);
176e4289a54SKarsten Heimrich 	fCalendarView->SetSelectionMessage(new BMessage(kDayChanged));
177e4289a54SKarsten Heimrich 	fCalendarView->SetInvocationMessage(new BMessage(kDayChanged));
178e4289a54SKarsten Heimrich 
179323ba9b7SRyan Leavengood 	fDateEdit = new TDateEdit("dateEdit", 3);
180323ba9b7SRyan Leavengood 	fTimeEdit = new TTimeEdit("timeEdit", 4);
181323ba9b7SRyan Leavengood 	fClock = new TAnalogClock("analogClock");
182e4289a54SKarsten Heimrich 
18378092ae7SKarsten Heimrich 	BTime time(BTime::CurrentTime(B_LOCAL_TIME));
18478092ae7SKarsten Heimrich 	fClock->SetTime(time.Hour(), time.Minute(), time.Second());
185e4289a54SKarsten Heimrich 
186323ba9b7SRyan Leavengood 	BBox* divider = new BBox(BRect(0, 0, 1, 1),
187323ba9b7SRyan Leavengood 		B_EMPTY_STRING, B_FOLLOW_ALL_SIDES,
188323ba9b7SRyan Leavengood 		B_WILL_DRAW | B_FRAME_EVENTS, B_FANCY_BORDER);
189323ba9b7SRyan Leavengood 	divider->SetExplicitMaxSize(BSize(1, B_SIZE_UNLIMITED));
190323ba9b7SRyan Leavengood 
191365839fbSRyan Leavengood 	const float kInset = be_control_look->DefaultItemSpacing();
192323ba9b7SRyan Leavengood 	BLayoutBuilder::Group<>(this)
193365839fbSRyan Leavengood 		.AddGroup(B_VERTICAL, kInset / 2)
194323ba9b7SRyan Leavengood 			.Add(fDateEdit)
195323ba9b7SRyan Leavengood 			.Add(fCalendarView)
196323ba9b7SRyan Leavengood 		.End()
197323ba9b7SRyan Leavengood 		.Add(divider)
198365839fbSRyan Leavengood 		.AddGroup(B_VERTICAL, 0)
199323ba9b7SRyan Leavengood 			.Add(fTimeEdit)
200323ba9b7SRyan Leavengood 			.Add(fClock)
201323ba9b7SRyan Leavengood 		.End()
202365839fbSRyan Leavengood 		.SetInsets(kInset, kInset, kInset, kInset);
203e4289a54SKarsten Heimrich }
204e4289a54SKarsten Heimrich 
205e4289a54SKarsten Heimrich 
206e4289a54SKarsten Heimrich void
207e4289a54SKarsten Heimrich DateTimeView::_UpdateDateTime(BMessage* message)
208e4289a54SKarsten Heimrich {
209e4289a54SKarsten Heimrich 	int32 day;
210e4289a54SKarsten Heimrich 	int32 month;
211e4289a54SKarsten Heimrich 	int32 year;
212e4289a54SKarsten Heimrich 	if (message->FindInt32("month", &month) == B_OK
213e4289a54SKarsten Heimrich 		&& message->FindInt32("day", &day) == B_OK
214d3bde5deSAxel Dörfler 		&& message->FindInt32("year", &year) == B_OK) {
2156846765fSOliver Tappe 		static int32 lastDay;
2166846765fSOliver Tappe 		static int32 lastMonth;
2176846765fSOliver Tappe 		static int32 lastYear;
2186846765fSOliver Tappe 		if (day != lastDay || month != lastMonth || year != lastYear) {
219e4289a54SKarsten Heimrich 			fDateEdit->SetDate(year, month, day);
220e4289a54SKarsten Heimrich 			fCalendarView->SetDate(year, month, day);
2216846765fSOliver Tappe 			lastDay = day;
2226846765fSOliver Tappe 			lastMonth = month;
2236846765fSOliver Tappe 			lastYear = year;
2246846765fSOliver Tappe 		}
225e4289a54SKarsten Heimrich 	}
226e4289a54SKarsten Heimrich 
227e4289a54SKarsten Heimrich 	int32 hour;
228e4289a54SKarsten Heimrich 	int32 minute;
229e4289a54SKarsten Heimrich 	int32 second;
230e4289a54SKarsten Heimrich 	if (message->FindInt32("hour", &hour) == B_OK
231e4289a54SKarsten Heimrich 		&& message->FindInt32("minute", &minute) == B_OK
232d3bde5deSAxel Dörfler 		&& message->FindInt32("second", &second) == B_OK) {
233e4289a54SKarsten Heimrich 		fClock->SetTime(hour, minute, second);
23485b69a94SKarsten Heimrich 		fTimeEdit->SetTime(hour, minute, second);
235e4289a54SKarsten Heimrich 	}
236e4289a54SKarsten Heimrich }
237f64b502dSRyan Leavengood 
238f64b502dSRyan Leavengood 
239f64b502dSRyan Leavengood void
240f64b502dSRyan Leavengood DateTimeView::_NotifyClockSettingChanged()
241f64b502dSRyan Leavengood {
242f64b502dSRyan Leavengood 	BMessage msg(kMsgClockSettingChanged);
243f64b502dSRyan Leavengood 	Window()->PostMessage(&msg);
244f64b502dSRyan Leavengood }
245f64b502dSRyan Leavengood 
246