1 #include <string.h>
2 #include <sys/time.h>
3
4 #include <gtk/gtk.h>
5
6 #include "Calendar.hpp"
7 #include "Config.hpp"
8
9
fork_and_run(char * cmdline)10 void fork_and_run(char* cmdline)
11 {
12 if (strlen(cmdline)) {
13 if (fork() == 0) {
14 execl("/bin/sh", "/bin/sh", "-c", cmdline, NULL);
15 _exit(0);
16 }
17 }
18 }
19
monthChangedCb(GtkCalendar * calendar,gpointer cls)20 void monthChangedCb(GtkCalendar *calendar, gpointer cls)
21 {
22 if (cls) {
23 ((Calendar*)cls)->markToday();
24 }
25 }
dayDoubleClickCb(GtkCalendar * calendar,gpointer cls)26 void dayDoubleClickCb(GtkCalendar *calendar, gpointer cls)
27 {
28 if (cls) {
29 ((Calendar*)cls)->runExternalViewer();
30 }
31 }
32
33
Calendar()34 Calendar::Calendar()
35 {
36 widget = gtk_calendar_new();
37
38 Config* config = Config::getInstance();
39 g_object_set(widget,
40 "show-heading", true,
41 "show-day-names", true,
42 "show-details", false,
43 "show-week-numbers", config->show_week_numbers,
44 NULL);
45 // Store today date to be able to jump to it.
46 gtk_calendar_get_date((GtkCalendar*)widget,
47 &today_year, &today_month, &today_day);
48 if (config->mark_today) {
49 markToday();
50 g_signal_connect(widget, "month-changed",
51 GCallback(monthChangedCb), (gpointer)this);
52 }
53 g_signal_connect(widget, "day-selected-double-click",
54 GCallback(dayDoubleClickCb), (gpointer)this);
55
56 gtk_widget_show(widget);
57 }
58
~Calendar()59 Calendar::~Calendar()
60 {
61 gtk_widget_destroy(widget);
62 }
63
nextYear()64 void Calendar::nextYear()
65 {
66 _change(1, 0, 0);
67 }
prevYear()68 void Calendar::prevYear()
69 {
70 _change(-1, 0, 0);
71 }
72
nextMonth()73 void Calendar::nextMonth()
74 {
75 _change(0, 1, 0);
76 }
prevMonth()77 void Calendar::prevMonth()
78 {
79 _change(0, -1, 0);
80 }
81
goLeft()82 void Calendar::goLeft()
83 {
84 _change(0, 0, -1);
85 }
goDown()86 void Calendar::goDown()
87 {
88 _change(0, 0, 7);
89 }
goUp()90 void Calendar::goUp()
91 {
92 _change(0, 0, -7);
93 }
goRight()94 void Calendar::goRight()
95 {
96 _change(0, 0, 1);
97 }
98
_change(int year_offset,int month_offset,int day_offset)99 void Calendar::_change(int year_offset, int month_offset, int day_offset)
100 {
101 int year, month, day;
102 gtk_calendar_get_date((GtkCalendar*)widget,
103 (guint*)&year, (guint*)&month, (guint*)&day);
104
105 unsigned int n_days = _n_days(year, month);
106 day += day_offset;
107 if (day < 1) {
108 day += _n_days(year, month - 1);
109 month_offset--;
110 } else if (day > n_days) {
111 day -= n_days;
112 month_offset++;
113 }
114
115 month += month_offset;
116 if (month > 11) {
117 month = 0;
118 year_offset++;
119 } else if (month < 0) {
120 month = 11;
121 year_offset--;
122 }
123
124 year += year_offset;
125
126 gtk_calendar_select_month((GtkCalendar*)widget, (guint)month, (guint)year);
127 gtk_calendar_select_day((GtkCalendar*)widget, day);
128 }
129
_n_days(unsigned int year,unsigned int month)130 unsigned int Calendar::_n_days(unsigned int year, unsigned int month)
131 {
132 if (month == 3 || month == 5 || month == 8 || month == 10) {
133 return 30;
134 } else if (month == 1) {
135 bool leap = (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
136 if (leap) {
137 return 29;
138 } else {
139 return 28;
140 }
141 } else {
142 return 31;
143 }
144 }
145
markToday()146 bool Calendar::markToday()
147 {
148 guint year, month;
149 gtk_calendar_get_date((GtkCalendar*)widget, &year, &month, NULL);
150 if (year == today_year && month == today_month) {
151 gtk_calendar_mark_day((GtkCalendar*)widget, today_day);
152 return true;
153 } else {
154 gtk_calendar_unmark_day((GtkCalendar*)widget, today_day);
155 return false;
156 }
157 }
158
goToday()159 void Calendar::goToday()
160 {
161 gtk_calendar_select_month((GtkCalendar*)widget, today_month, today_year);
162 gtk_calendar_select_day((GtkCalendar*)widget, today_day);
163 }
164
runExternalViewer()165 bool Calendar::runExternalViewer()
166 {
167 Config* config = Config::getInstance();
168 size_t len = config->external_viewer.length();
169 if (len > 0) {
170 int year, month, day;
171 gtk_calendar_get_date((GtkCalendar*)widget,
172 (guint*)&year, (guint*)&month, (guint*)&day);
173 struct tm date;
174 date.tm_year = year - 1900;
175 date.tm_mon = month;
176 date.tm_mday = day;
177 date.tm_sec = date.tm_min = date.tm_hour = date.tm_wday
178 = date.tm_yday = date.tm_isdst = 0;
179
180 size_t buf_size = len + 64;
181 char* cmd = new char[buf_size];
182 strftime(cmd, buf_size, config->external_viewer.c_str(), &date);
183 fork_and_run(cmd);
184 delete[] cmd;
185 return true;
186 } else {
187 return false;
188 }
189 }
190