123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461 |
- #include "TimerEditWindow.h"
- #include <math.h>
- enum { TIMER_AM = 0, TIMER_PM = 1 };
- enum { TIMER_LAST_START, TIMER_LAST_END };
- struct _TimerEditWindow {
- GtkDialog parent;
- GtkWidget *deleteButton;
- GtkWidget *cancelButton;
- GtkWidget *saveButton;
- GtkWidget *nameBox;
- GtkWidget *startCalendar;
- GtkWidget *endCalendar;
- GtkWidget *endCalCheck;
- GtkWidget *startHour;
- GtkWidget *startMinute;
- GtkWidget *startSecond;
- GtkWidget *startLean;
- GtkWidget *endHour;
- GtkWidget *endMinute;
- GtkWidget *endSecond;
- GtkWidget *endLean;
- GtkWidget *lengthHour;
- GtkWidget *lengthMinute;
- GtkWidget *lengthSecond;
- GtkWidget *followBox;
- GtkWidget *followButton;
- GDateTime *lastTask;
- int lastEdit;
- gboolean invalidTime;
- gboolean enableAutoEdit;
- };
- G_DEFINE_TYPE(TimerEditWindow, timer_edit_window, GTK_TYPE_DIALOG);
- #define TIMER_MAX_LENGTH ((3600 * 99) + (60 * 59) + 59)
- static gboolean compare_dates(GDateTime *dt1, GDateTime *dt2) {
- int y1, m1, d1, y2, m2, d2;
- g_date_time_get_ymd(dt1, &y1, &m1, &d1);
- g_date_time_get_ymd(dt2, &y2, &m2, &d2);
- return y1 == y2 && m1 == m2 && d1 == d2;
- }
- static void to_leaned_time(/* 0-23 */ int t, /* 1-12*/ int *h, int *l) {
- if (t == 0) {
- *h = 12;
- *l = TIMER_AM;
- } else if (t == 12) {
- *h = 12;
- *l = TIMER_PM;
- } else if (t > 12) {
- *h = t - 12;
- *l = TIMER_PM;
- } else {
- *h = t;
- *l = TIMER_AM;
- }
- }
- static void to_total_time(/* 1-12 */ int h, int l, /* 0-23 */ int *t) {
- if (h == 12 && l == TIMER_AM) {
- *t = 0;
- } else if (h == 12 && l == TIMER_PM) {
- *t = 12;
- } else if (l == TIMER_PM) {
- *t = h + 12;
- } else {
- *t = h;
- }
- }
- static void timer_edit_window_calculate_start(TimerEditWindow *self) {
- GDateTime *end = timer_edit_window_get_end(self);
- gint64 length = timer_edit_window_get_length(self);
- GDateTime *start = g_date_time_add_seconds(end, -length);
- if (!compare_dates(start, end)) {
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(self->endCalCheck),
- FALSE);
- }
- int y, month, d;
- g_date_time_get_ymd(start, &y, &month, &d);
- int s = g_date_time_get_second(start);
- int min = g_date_time_get_minute(start);
- int h, l;
- to_leaned_time(g_date_time_get_hour(start), &h, &l);
- gtk_calendar_select_day(GTK_CALENDAR(self->startCalendar), d);
- gtk_calendar_select_month(GTK_CALENDAR(self->startCalendar), month - 1, y);
- gtk_spin_button_set_value(GTK_SPIN_BUTTON(self->startSecond), s);
- gtk_spin_button_set_value(GTK_SPIN_BUTTON(self->startMinute), min);
- gtk_spin_button_set_value(GTK_SPIN_BUTTON(self->startHour), h);
- gtk_combo_box_set_active(GTK_COMBO_BOX(self->startLean), l);
- g_date_time_unref(end);
- g_date_time_unref(start);
- }
- static void timer_edit_window_calculate_end(TimerEditWindow *self) {
- GDateTime *start = timer_edit_window_get_start(self);
- gint64 length = timer_edit_window_get_length(self);
- GDateTime *end = g_date_time_add_seconds(start, length);
- if (!compare_dates(start, end)) {
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(self->endCalCheck),
- FALSE);
- }
- int y, month, d;
- g_date_time_get_ymd(end, &y, &month, &d);
- int s = g_date_time_get_second(end);
- int min = g_date_time_get_minute(end);
- int h, l;
- to_leaned_time(g_date_time_get_hour(end), &h, &l);
- gtk_calendar_select_day(GTK_CALENDAR(self->endCalendar), d);
- gtk_calendar_select_month(GTK_CALENDAR(self->endCalendar), month - 1, y);
- gtk_spin_button_set_value(GTK_SPIN_BUTTON(self->endSecond), s);
- gtk_spin_button_set_value(GTK_SPIN_BUTTON(self->endMinute), min);
- gtk_spin_button_set_value(GTK_SPIN_BUTTON(self->endHour), h);
- gtk_combo_box_set_active(GTK_COMBO_BOX(self->endLean), l);
- g_date_time_unref(start);
- g_date_time_unref(end);
- }
- static void timer_edit_window_calculate_length(TimerEditWindow *self) {
- GDateTime *start = timer_edit_window_get_start(self);
- GDateTime *end = timer_edit_window_get_end(self);
- GTimeSpan length = g_date_time_difference(end, start) / 1000000;
- if (length < 0 || length > TIMER_MAX_LENGTH) {
- self->invalidTime = TRUE;
- } else {
- self->invalidTime = FALSE;
- int h = floor(length / 3600.0f);
- int m = floor(length / 60.0f) - (h * 60);
- int s = length - (m * 60) - (h * 3600);
- gtk_spin_button_set_value(GTK_SPIN_BUTTON(self->lengthSecond), s);
- gtk_spin_button_set_value(GTK_SPIN_BUTTON(self->lengthMinute), m);
- gtk_spin_button_set_value(GTK_SPIN_BUTTON(self->lengthHour), h);
- }
- g_date_time_unref(start);
- g_date_time_unref(end);
- }
- TimerEditWindow *timer_edit_window_new(const char *task, GDateTime *start,
- gint64 length, const char **taskOptions,
- gsize optionsLen, gboolean isNew, GDateTime *lastTask) {
- TimerEditWindow *win = g_object_new(TIMER_TYPE_EDIT_WINDOW, NULL);
- gtk_widget_set_visible(win->deleteButton, !isNew);
- gsize i;
- for (i = 0; i < optionsLen; ++i) {
- gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(win->nameBox),
- taskOptions[i]);
- }
- gtk_entry_set_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(win->nameBox))),
- task);
- int sy, smonth, sd;
- g_date_time_get_ymd(start, &sy, &smonth, &sd);
- int ss = g_date_time_get_second(start);
- int smin = g_date_time_get_minute(start);
- int sh, sl;
- to_leaned_time(g_date_time_get_hour(start), &sh, &sl);
- gtk_calendar_select_day(GTK_CALENDAR(win->startCalendar), sd);
- gtk_calendar_select_month(GTK_CALENDAR(win->startCalendar), smonth - 1, sy);
- gtk_spin_button_set_value(GTK_SPIN_BUTTON(win->startSecond), ss);
- gtk_spin_button_set_value(GTK_SPIN_BUTTON(win->startMinute), smin);
- gtk_spin_button_set_value(GTK_SPIN_BUTTON(win->startHour), sh);
- gtk_combo_box_set_active(GTK_COMBO_BOX(win->startLean), sl);
- int lh = floor(length / 3600.0f);
- int lm = floor(length / 60.0f) - (lh * 60);
- int ls = length - (lm * 60) - (lh * 3600);
- gtk_spin_button_set_value(GTK_SPIN_BUTTON(win->lengthSecond), ls);
- gtk_spin_button_set_value(GTK_SPIN_BUTTON(win->lengthMinute), lm);
- gtk_spin_button_set_value(GTK_SPIN_BUTTON(win->lengthHour), lh);
- timer_edit_window_calculate_end(win);
- if (isNew && lastTask) {
- win->lastTask = lastTask;
- gtk_widget_show_all(win->followBox);
- }
- win->lastEdit = TIMER_LAST_END;
- win->enableAutoEdit = TRUE;
- return win;
- }
- GDateTime *timer_edit_window_get_start(TimerEditWindow *self) {
- unsigned int y, mn, d;
- gtk_calendar_get_date(GTK_CALENDAR(self->startCalendar), &y, &mn, &d);
- int s =
- gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(self->startSecond));
- int mi =
- gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(self->startMinute));
- int h = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(self->startHour));
- int l = gtk_combo_box_get_active(GTK_COMBO_BOX(self->startLean));
- int t;
- to_total_time(h, l, &t);
- return g_date_time_new_local(y, mn + 1, d, t, mi, s);
- }
- GDateTime *timer_edit_window_get_end(TimerEditWindow *self) {
- unsigned int y, mn, d;
- if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(self->endCalCheck))) {
- gtk_calendar_get_date(GTK_CALENDAR(self->endCalendar), &y, &mn, &d);
- } else {
- gtk_calendar_get_date(GTK_CALENDAR(self->startCalendar), &y, &mn, &d);
- }
- int s = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(self->endSecond));
- int mi = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(self->endMinute));
- int h = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(self->endHour));
- int l = gtk_combo_box_get_active(GTK_COMBO_BOX(self->endLean));
- int t;
- to_total_time(h, l, &t);
- return g_date_time_new_local(y, mn + 1, d, t, mi, s);
- }
- gint64 timer_edit_window_get_length(TimerEditWindow *self) {
- int h = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(self->lengthHour));
- int m =
- gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(self->lengthMinute));
- int s =
- gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(self->lengthSecond));
- return (h * 3600) + (m * 60) + s;
- }
- char *timer_edit_window_get_name(TimerEditWindow *self) {
- char *name;
- if (gtk_entry_get_text_length(
- GTK_ENTRY(gtk_bin_get_child(GTK_BIN(self->nameBox)))) == 0) {
- name = g_strdup("Untitled");
- } else {
- name = gtk_combo_box_text_get_active_text(
- GTK_COMBO_BOX_TEXT(self->nameBox));
- }
- return name;
- }
- static void save_button_callback(GtkButton *btn, TimerEditWindow *win) {
- if (win->invalidTime) {
- GtkWidget *diag =
- gtk_message_dialog_new(GTK_WINDOW(win), GTK_DIALOG_MODAL,
- GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
- "Start time must be before end time and "
- "length must be under 100 hours!");
- gtk_window_set_position(GTK_WINDOW(diag), GTK_WIN_POS_MOUSE);
- gtk_dialog_run(GTK_DIALOG(diag));
- gtk_widget_destroy(diag);
- } else {
- gtk_dialog_response(GTK_DIALOG(win), GTK_RESPONSE_APPLY);
- gtk_window_close(GTK_WINDOW(win));
- }
- }
- static void cancel_button_callback(GtkButton *btn, TimerEditWindow *win) {
- gtk_dialog_response(GTK_DIALOG(win), GTK_RESPONSE_CANCEL);
- gtk_window_close(GTK_WINDOW(win));
- }
- static void delete_button_callback(GtkButton *btn, TimerEditWindow *win) {
- GtkWidget *diag = gtk_message_dialog_new(
- GTK_WINDOW(win), GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION,
- GTK_BUTTONS_YES_NO, "Are you sure you would like to delete this task?");
- gtk_window_set_position(GTK_WINDOW(diag), GTK_WIN_POS_MOUSE);
- int resp = gtk_dialog_run(GTK_DIALOG(diag));
- gtk_widget_destroy(GTK_WIDGET(diag));
- if (resp == GTK_RESPONSE_YES) {
- gtk_dialog_response(GTK_DIALOG(win), GTK_RESPONSE_REJECT);
- gtk_window_close(GTK_WINDOW(win));
- }
- }
- static void start_edit_callback(GtkWidget *obj, TimerEditWindow *win) {
- if (win->enableAutoEdit) {
- win->enableAutoEdit = FALSE;
- timer_edit_window_calculate_length(win);
- win->lastEdit = TIMER_LAST_START;
- win->enableAutoEdit = TRUE;
- }
- }
- static void end_edit_callback(GtkWidget *btn, TimerEditWindow *win) {
- if (win->enableAutoEdit) {
- win->enableAutoEdit = FALSE;
- timer_edit_window_calculate_length(win);
- win->lastEdit = TIMER_LAST_END;
- win->enableAutoEdit = TRUE;
- }
- }
- static void length_edit_callback(GtkSpinButton *btn, TimerEditWindow *win) {
- if (win->enableAutoEdit) {
- win->enableAutoEdit = FALSE;
- if (win->lastEdit == TIMER_LAST_START) {
- timer_edit_window_calculate_end(win);
- } else {
- timer_edit_window_calculate_start(win);
- }
- win->enableAutoEdit = TRUE;
- }
- }
- static void end_calendar_check_callback(GtkToggleButton *tgb,
- TimerEditWindow *win) {
- gtk_widget_set_visible(win->endCalendar,
- !gtk_toggle_button_get_active(tgb));
- if (win->enableAutoEdit) {
- win->enableAutoEdit = FALSE;
- timer_edit_window_calculate_length(win);
- win->lastEdit = TIMER_LAST_END;
- win->enableAutoEdit = TRUE;
- }
- }
- static void follow_button_callback(GtkButton *btn, TimerEditWindow *win) {
- GDateTime *end = timer_edit_window_get_end(win);
- win->enableAutoEdit = FALSE;
- int sy, smonth, sd;
- g_date_time_get_ymd(win->lastTask, &sy, &smonth, &sd);
- int ss = g_date_time_get_second(win->lastTask);
- int smin = g_date_time_get_minute(win->lastTask);
- int sh, sl;
- to_leaned_time(g_date_time_get_hour(win->lastTask), &sh, &sl);
- gtk_calendar_select_day(GTK_CALENDAR(win->startCalendar), sd);
- gtk_calendar_select_month(GTK_CALENDAR(win->startCalendar), smonth - 1, sy);
- gtk_spin_button_set_value(GTK_SPIN_BUTTON(win->startSecond), ss);
- gtk_spin_button_set_value(GTK_SPIN_BUTTON(win->startMinute), smin);
- gtk_spin_button_set_value(GTK_SPIN_BUTTON(win->startHour), sh);
- gtk_combo_box_set_active(GTK_COMBO_BOX(win->startLean), sl);
- GDateTime *start = timer_edit_window_get_start(win);
- if (!compare_dates(start, end)) {
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(win->endCalCheck), FALSE);
- }
- timer_edit_window_calculate_length(win);
- win->lastEdit = TIMER_LAST_START;
- win->enableAutoEdit = TRUE;
- }
- static void timer_edit_window_finalize(GObject *obj) {
- if (TIMER_EDIT_WINDOW(obj)->lastTask) {
- g_date_time_unref(TIMER_EDIT_WINDOW(obj)->lastTask);
- }
- G_OBJECT_CLASS(timer_edit_window_parent_class)->finalize(obj);
- }
- static void timer_edit_window_class_init(TimerEditWindowClass *class) {
- G_OBJECT_CLASS(class)->finalize = timer_edit_window_finalize;
- gtk_widget_class_set_template_from_resource(
- GTK_WIDGET_CLASS(class), "/zander/practicetimer/ui/edit-window.glade");
- gtk_widget_class_bind_template_child_internal(
- GTK_WIDGET_CLASS(class), TimerEditWindow, cancelButton);
- gtk_widget_class_bind_template_child_internal(
- GTK_WIDGET_CLASS(class), TimerEditWindow, deleteButton);
- gtk_widget_class_bind_template_child_internal(GTK_WIDGET_CLASS(class),
- TimerEditWindow, saveButton);
- gtk_widget_class_bind_template_child_internal(GTK_WIDGET_CLASS(class),
- TimerEditWindow, nameBox);
- gtk_widget_class_bind_template_child_internal(
- GTK_WIDGET_CLASS(class), TimerEditWindow, startCalendar);
- gtk_widget_class_bind_template_child_internal(GTK_WIDGET_CLASS(class),
- TimerEditWindow, endCalendar);
- gtk_widget_class_bind_template_child_internal(GTK_WIDGET_CLASS(class),
- TimerEditWindow, endCalCheck);
- gtk_widget_class_bind_template_child_internal(GTK_WIDGET_CLASS(class),
- TimerEditWindow, startHour);
- gtk_widget_class_bind_template_child_internal(GTK_WIDGET_CLASS(class),
- TimerEditWindow, startMinute);
- gtk_widget_class_bind_template_child_internal(GTK_WIDGET_CLASS(class),
- TimerEditWindow, startSecond);
- gtk_widget_class_bind_template_child_internal(GTK_WIDGET_CLASS(class),
- TimerEditWindow, startLean);
- gtk_widget_class_bind_template_child_internal(GTK_WIDGET_CLASS(class),
- TimerEditWindow, endHour);
- gtk_widget_class_bind_template_child_internal(GTK_WIDGET_CLASS(class),
- TimerEditWindow, endMinute);
- gtk_widget_class_bind_template_child_internal(GTK_WIDGET_CLASS(class),
- TimerEditWindow, endSecond);
- gtk_widget_class_bind_template_child_internal(GTK_WIDGET_CLASS(class),
- TimerEditWindow, endLean);
- gtk_widget_class_bind_template_child_internal(GTK_WIDGET_CLASS(class),
- TimerEditWindow, lengthHour);
- gtk_widget_class_bind_template_child_internal(
- GTK_WIDGET_CLASS(class), TimerEditWindow, lengthMinute);
- gtk_widget_class_bind_template_child_internal(
- GTK_WIDGET_CLASS(class), TimerEditWindow, lengthSecond);
- gtk_widget_class_bind_template_child_internal(GTK_WIDGET_CLASS(class), TimerEditWindow, followButton);
- gtk_widget_class_bind_template_child_internal(GTK_WIDGET_CLASS(class), TimerEditWindow, followBox);
- }
- static void timer_edit_window_init(TimerEditWindow *self) {
- self->enableAutoEdit = FALSE;
- gtk_widget_init_template(GTK_WIDGET(self));
- gtk_window_set_keep_above(GTK_WINDOW(self), TRUE);
- g_signal_connect(self->deleteButton, "clicked",
- G_CALLBACK(delete_button_callback), self);
- g_signal_connect(self->saveButton, "clicked",
- G_CALLBACK(save_button_callback), self);
- g_signal_connect(self->cancelButton, "clicked",
- G_CALLBACK(cancel_button_callback), self);
- g_signal_connect(self->startHour, "value-changed",
- G_CALLBACK(start_edit_callback), self);
- g_signal_connect(self->startMinute, "value-changed",
- G_CALLBACK(start_edit_callback), self);
- g_signal_connect(self->startSecond, "value-changed",
- G_CALLBACK(start_edit_callback), self);
- g_signal_connect(self->startLean, "changed",
- G_CALLBACK(start_edit_callback), self);
- g_signal_connect(self->startCalendar, "day-selected",
- G_CALLBACK(start_edit_callback), self);
- g_signal_connect(self->startCalendar, "month-changed",
- G_CALLBACK(start_edit_callback), self);
- g_signal_connect(self->startCalendar, "next-year",
- G_CALLBACK(start_edit_callback), self);
- g_signal_connect(self->startCalendar, "prev-year",
- G_CALLBACK(start_edit_callback), self);
- g_signal_connect(self->endHour, "value-changed",
- G_CALLBACK(end_edit_callback), self);
- g_signal_connect(self->endMinute, "value-changed",
- G_CALLBACK(end_edit_callback), self);
- g_signal_connect(self->endSecond, "value-changed",
- G_CALLBACK(end_edit_callback), self);
- g_signal_connect(self->endLean, "changed", G_CALLBACK(end_edit_callback),
- self);
- g_signal_connect(self->endCalendar, "day-selected",
- G_CALLBACK(end_edit_callback), self);
- g_signal_connect(self->endCalendar, "month-changed",
- G_CALLBACK(end_edit_callback), self);
- g_signal_connect(self->endCalendar, "next-year",
- G_CALLBACK(end_edit_callback), self);
- g_signal_connect(self->endCalendar, "prev-year",
- G_CALLBACK(end_edit_callback), self);
- g_signal_connect(self->lengthHour, "value-changed",
- G_CALLBACK(length_edit_callback), self);
- g_signal_connect(self->lengthMinute, "value-changed",
- G_CALLBACK(length_edit_callback), self);
- g_signal_connect(self->lengthSecond, "value-changed",
- G_CALLBACK(length_edit_callback), self);
- g_signal_connect(self->endCalCheck, "toggled",
- G_CALLBACK(end_calendar_check_callback), self);
- g_signal_connect(self->followButton, "clicked", G_CALLBACK(follow_button_callback), self);
- }
|