diff --git a/src/mainwindow.c b/src/mainwindow.c index 1e94450..2f09d5b 100644 --- a/src/mainwindow.c +++ b/src/mainwindow.c @@ -1,109 +1,6 @@ #include "mainwindow.h" #include "mdiary.h" -/** - * @brief The dateFormats struct contains regex/date-info pairs to parse different date formats. - */ -struct dateFormats { - gchar *regex; - guint index_count; - guint index_year; - guint index_month; - guint index_day; - guint index_hour; - guint index_minute; -} dateFormats_list[] = { -{ - .regex = "(\\d{1,4})-(\\d{1,2})-(\\d{1,2})\\s*(\\d{1,2}):(\\d{1,2}).*", - .index_count = 5, - .index_year = 1, - .index_month = 2, - .index_day = 3, - .index_hour = 4, - .index_minute = 5 -}, -{ - .regex = "(\\d{1,2})\\.(\\d{1,2})\\.(\\d{1,4})\\s*(\\d{1,2}):(\\d{1,2}).*", - .index_count = 5, - .index_year = 3, - .index_month = 2, - .index_day = 1, - .index_hour = 4, - .index_minute = 5 -}, -{ - .regex = "(\\d{1,4})-(\\d{1,2})-(\\d{1,2}).*", - .index_count = 3, - .index_year = 1, - .index_month = 2, - .index_day = 3, -}, -{ - .regex = "(\\d{1,2})\\.(\\d{1,2})\\.(\\d{1,4}).*", - .index_count = 3, - .index_year = 3, - .index_month = 2, - .index_day = 1, -}, -{ - .regex = NULL -} -}; - -/** - * @brief mainWindow_get_date_from_string tries to guess the date format used and converts it to GDateTime. - * @param Input string. - * @return A GDateTime object or NULL on error. You need to free it after use. - */ -static GDateTime *mainWindow_get_date_from_string(gchar *string) -{ - GRegex *regex; - GMatchInfo *match_info; - GRegexError *regex_error; - struct dateFormats *dateFormats; - GDateTime *datetime = NULL; - guint year = 0; - guint month = 0; - guint day = 0; - guint hour = 0; - guint minute = 0; - - dateFormats = dateFormats_list; - do { - regex = g_regex_new(dateFormats->regex, G_REGEX_RAW, 0, NULL); - if (g_regex_match(regex, string, 0, &match_info) - && g_regex_get_capture_count(regex) >= dateFormats->index_count && - g_match_info_matches(match_info)) { - if (dateFormats->index_year) - year = atoi(g_match_info_fetch(match_info, dateFormats->index_year)); - if (dateFormats->index_month) - month = atoi(g_match_info_fetch(match_info, dateFormats->index_month)); - if (dateFormats->index_day) - day = atoi(g_match_info_fetch(match_info, dateFormats->index_day)); - if (dateFormats->index_hour) - hour = atoi(g_match_info_fetch(match_info, dateFormats->index_hour)); - if (dateFormats->index_minute) - minute = atoi(g_match_info_fetch(match_info, dateFormats->index_minute)); - - if (year >= 0 && - month >=1 && month <=12 && - day >= 1 && day <= 31 && - hour >= 0 && hour <= 23 && - minute >= 0 && minute <= 59) { - datetime = g_date_time_new_local(year, month, day, hour, minute, 0); - g_regex_unref(regex); - break; - } - } - g_regex_unref(regex); - } while ((++dateFormats)->regex); - - if (!datetime) - g_print("Warning! Could not match date in \"%s\"!\n", string); - - return datetime; -} - /** * @brief mainWindow_list_entry_visible checks whether the entry should be displayed. * @param model N/A @@ -255,28 +152,6 @@ static void mainWindow_configure_treeView(struct mainWindow *mainWindow) gtk_tree_view_column_set_sort_column_id(col, COL_TAGS_TEXT); gtk_tree_sortable_set_sort_column_id(sortable, COL_DATE_TEXT, GTK_SORT_DESCENDING); - - /* - * Test entries for debugging only - */ - GDateTime *dt; - GList *list = NULL; - - list = g_list_append(list, "Tag0"); - list = g_list_append(list, "Tag1"); - list = g_list_append(list, "Tag2"); - - dt = g_date_time_new_local(2017, 11, 21, 02, 03, 0); - mdiary_add_entry_to_store(mainWindow->entryListStore, "Title", dt, list, "Text text text"); - g_date_time_unref(dt); - - dt = g_date_time_new_local(2017, 2, 3, 6, 7, 1); - mdiary_add_entry_to_store(mainWindow->entryListStore, "AAA 2", dt, list, "fdfd Text text text"); - g_date_time_unref(dt); - - dt = g_date_time_new_local(2016, 4, 18, 13, 44, 2); - mdiary_add_entry_to_store(mainWindow->entryListStore, "Yey entries 3", dt, list, "The content is content."); - g_date_time_unref(dt); } /** @@ -491,16 +366,16 @@ void mainWindow_filterChanged(GtkWidget *widget, gpointer user_data) struct mainWindow *mainWindow = (struct mainWindow *)user_data; if (!widget || widget == mainWindow->dateStart) { - datetime = mainWindow_get_date_from_string((gchar *)gtk_entry_get_text( - GTK_ENTRY(mainWindow->dateStart))); + datetime = mdiary_get_date_from_string((gchar *)gtk_entry_get_text( + GTK_ENTRY(mainWindow->dateStart))); if (datetime) { mainWindow->filterSettings.time_start = g_date_time_to_unix(datetime); g_date_time_unref(datetime); } } if (!widget || widget == mainWindow->dateEnd) { - datetime = mainWindow_get_date_from_string((gchar *)gtk_entry_get_text( - GTK_ENTRY(mainWindow->dateEnd))); + datetime = mdiary_get_date_from_string((gchar *)gtk_entry_get_text( + GTK_ENTRY(mainWindow->dateEnd))); if (datetime) { mainWindow->filterSettings.time_end = g_date_time_to_unix(datetime); g_date_time_unref(datetime); @@ -528,7 +403,7 @@ void mainWindow_checkDate(GtkWidget *widget, gint event, gpointer user_data) struct mainWindow *mainWindow = (struct mainWindow *)user_data; GDateTime *datetime; - datetime = mainWindow_get_date_from_string((char *)gtk_entry_get_text(GTK_ENTRY(widget))); + datetime = mdiary_get_date_from_string((char *)gtk_entry_get_text(GTK_ENTRY(widget))); if (!datetime) { datetime = g_date_time_new_from_unix_local(widget == mainWindow->dateStart ? mainWindow->filterSettings.time_start diff --git a/src/mdiary.c b/src/mdiary.c index 25426e6..e93c1ba 100644 --- a/src/mdiary.c +++ b/src/mdiary.c @@ -1,8 +1,251 @@ #include "mdiary.h" +/** + * @brief The dateFormats struct contains regex/date-info pairs to parse different date formats. + */ +struct dateFormats { + gchar *regex; + guint index_count; + guint index_year; + guint index_month; + guint index_day; + guint index_hour; + guint index_minute; +} dateFormats_list[] = { +{ + .regex = "(\\d{1,4})-(\\d{1,2})-(\\d{1,2})\\s*(\\d{1,2}):(\\d{1,2}).*", + .index_count = 5, + .index_year = 1, + .index_month = 2, + .index_day = 3, + .index_hour = 4, + .index_minute = 5 +}, +{ + .regex = "(\\d{1,2})\\.(\\d{1,2})\\.(\\d{1,4})\\s*(\\d{1,2}):(\\d{1,2}).*", + .index_count = 5, + .index_year = 3, + .index_month = 2, + .index_day = 1, + .index_hour = 4, + .index_minute = 5 +}, +{ + .regex = "(\\d{1,4})-(\\d{1,2})-(\\d{1,2}).*", + .index_count = 3, + .index_year = 1, + .index_month = 2, + .index_day = 3, +}, +{ + .regex = "(\\d{1,2})\\.(\\d{1,2})\\.(\\d{1,4}).*", + .index_count = 3, + .index_year = 3, + .index_month = 2, + .index_day = 1, +}, +{ + .regex = NULL +} +}; + +/** + * @brief mdiary_get_date_from_string tries to guess the date format used and converts it to GDateTime. + * @param Input string. + * @return A GDateTime object or NULL on error. You need to free it after use. + */ +GDateTime *mdiary_get_date_from_string(gchar *string) +{ + return mdiary_get_date_from_string_ext(string, "", ""); +} + +/** + * @brief mdiary_get_date_from_string_ext tries to guess the date format used and converts it to GDateTime. + * @param Input string. + * @return A GDateTime object or NULL on error. You need to free it after use. + */ +GDateTime *mdiary_get_date_from_string_ext(gchar *string, gchar *prefix, gchar *suffix) +{ + GRegex *regex; + GMatchInfo *match_info; + struct dateFormats *dateFormats; + GDateTime *datetime = NULL; + guint year = 0; + guint month = 0; + guint day = 0; + guint hour = 0; + guint minute = 0; + gchar *regex_string; + + dateFormats = dateFormats_list; + do { + regex_string = g_strdup_printf("%s%s%s", prefix, dateFormats->regex, suffix); + regex = g_regex_new(regex_string, G_REGEX_RAW, 0, NULL); + if (g_regex_match(regex, string, 0, &match_info) + && g_regex_get_capture_count(regex) >= dateFormats->index_count && + g_match_info_matches(match_info)) { + if (dateFormats->index_year) + year = atoi(g_match_info_fetch(match_info, dateFormats->index_year)); + if (dateFormats->index_month) + month = atoi(g_match_info_fetch(match_info, dateFormats->index_month)); + if (dateFormats->index_day) + day = atoi(g_match_info_fetch(match_info, dateFormats->index_day)); + if (dateFormats->index_hour) + hour = atoi(g_match_info_fetch(match_info, dateFormats->index_hour)); + if (dateFormats->index_minute) + minute = atoi(g_match_info_fetch(match_info, dateFormats->index_minute)); + + if (year >= 0 && + month >=1 && month <=12 && + day >= 1 && day <= 31 && + hour >= 0 && hour <= 23 && + minute >= 0 && minute <= 59) { + datetime = g_date_time_new_local(year, month, day, hour, minute, 0); + g_regex_unref(regex); + g_free(regex_string); + break; + } + } + g_free(regex_string); + g_regex_unref(regex); + } while ((++dateFormats)->regex); + + return datetime; +} + +static gchar *mdiary_get_title_from_string(gchar *string) +{ + GRegex *regex; + GMatchInfo *match_info; + gchar *ret = NULL; + + regex = g_regex_new("\\# (.*)", G_REGEX_RAW, 0, NULL); + if (g_regex_match(regex, string, 0, &match_info) && + g_regex_get_capture_count(regex) > 0 && + g_match_info_matches(match_info)) { + ret = g_strdup(g_match_info_fetch(match_info, 1)); + } + + g_regex_unref(regex); + + return ret; +} + +static GList *mdiary_add_tags_from_string(gchar *string) +{ + GRegex *regex; + GMatchInfo *match_info; + GList *ret = NULL; + gchar *ptr; + gchar *beg_ptr; + gchar *orig_ptr; + gboolean collected = 0; + gchar bak; + + g_print("\n\nREGEX on %s\n", string); + regex = g_regex_new("^\\s*Tags: (.*)", G_REGEX_RAW, 0, NULL); + if (g_regex_match(regex, string, 0, &match_info) && + g_regex_get_capture_count(regex) > 0 && + g_match_info_matches(match_info)) { + g_print("T: Matched %d\n", g_regex_get_capture_count(regex)); + /** + * TODO: This function should be rewritten to fully use GRegex... + */ + ptr = beg_ptr = orig_ptr = g_strdup(g_match_info_fetch(match_info, 1)); + do { + if (*ptr == ',' || *ptr == ' ' || *ptr == '\0') { + bak = *ptr; + if (collected) { + collected = 0; + *ptr = '\0'; + ret = g_list_append(ret, g_strdup(beg_ptr)); + beg_ptr = ptr + 1; + *ptr = bak; + } else { + beg_ptr = ptr + 1; + } + } else { + collected = 1; + } + } while (*(ptr++)); + g_free(orig_ptr); + } + + g_regex_unref(regex); + + return ret; +} + static void mdiary_add_file_to_store(gchar *filename, GtkListStore *entryListStore) { + GFile *file; + GError *err = NULL; + GFileInputStream *stream; + GDataInputStream *dstream; + gchar *line; + + GDateTime *datetime = NULL; + gchar *title = NULL; + GList *tagList = NULL; + gchar *text = NULL; + gboolean in_header = 1; + g_print("Add file: %s\n", filename); + + file = g_file_new_for_path(filename); + stream = g_file_read(file, NULL, &err); + if (err != NULL) { + g_error("Could not open %s for reading: %s\n", filename, err->message); + g_error_free(err); + return; + } + dstream = g_data_input_stream_new(G_INPUT_STREAM(stream)); + + while (line = g_data_input_stream_read_line(G_DATA_INPUT_STREAM(dstream), NULL, NULL, NULL)) { + if (in_header) { + if (!datetime) { + datetime = mdiary_get_date_from_string_ext(line, "Date: .*", ""); + if (datetime) + continue; + } + if (!title) { + title = mdiary_get_title_from_string(line); + if (title) + continue; + } + if (!tagList) { + tagList = mdiary_add_tags_from_string(line); + if (tagList) + continue; + } + } + } + + if (!tagList) { + tagList = g_list_append(tagList, "untagged"); + tagList = g_list_append(tagList, "untagged"); + } + if (!datetime) { + g_error("Could not detect date in file!\n"); + datetime = g_date_time_new_from_unix_local(0); + } + if (!text) + text = g_strdup("No content found."); + if (!title) + title = g_strdup("Untitled"); + + mdiary_add_entry_to_store(entryListStore, + title, + datetime, + tagList, + text); + + g_input_stream_close(G_INPUT_STREAM(dstream), NULL, NULL); + g_input_stream_close(G_INPUT_STREAM(stream), NULL, NULL); + g_free(text); + g_free(title); + g_date_time_unref(datetime); + g_object_unref(file); } static void mdiary_recurse_and_collect(gchar *base_dir, GtkListStore *entryListStore, guint max_level) @@ -98,7 +341,7 @@ void mdiary_add_entry_to_store(GtkListStore *entryListStore, COL_DATE_TEXT, date_text, COL_TAGS_TEXT, taglistString, COL_TIMESTAMP, datetime_copy, - COL_TAGLIST, NULL, + COL_TAGLIST, NULL, /* TODO: !!!! */ COL_TEXT, g_strdup(text), -1); g_free(date_text); diff --git a/src/mdiary.h b/src/mdiary.h index 9e124b3..9ff790f 100644 --- a/src/mdiary.h +++ b/src/mdiary.h @@ -3,6 +3,7 @@ #include #include +#include enum { COL_TITLE = 0, /* Title of the entry */ @@ -21,4 +22,7 @@ void mdiary_add_entry_to_store(GtkListStore *entryListStore, GDateTime *datetime, GList *tags, gchar *text); +GDateTime *mdiary_get_date_from_string_ext(gchar *string, gchar *prefix, gchar *suffix); +GDateTime *mdiary_get_date_from_string(gchar *string); + #endif /* MDIARY_H */