#include "mainwindow.h" #include "mdiary.h" static gboolean mainWindow_workspace_entry_visible(GtkTreeModel *model, GtkTreeIter *iter, struct mainWindow *mainWindow) { GRegex *regex; GMatchInfo *match_info; gchar *searchString; gchar *temp; gboolean ret = FALSE; searchString = (gchar *)gtk_entry_get_text(GTK_ENTRY(mainWindow->workspaceSearch)); if (searchString[0]) { regex = g_regex_new(searchString, G_REGEX_CASELESS, 0, NULL); gtk_tree_model_get(model, iter, WSCOL_PATH, &temp, -1); if (g_regex_match(regex, temp, 0, &match_info) && g_match_info_matches(match_info)) ret = TRUE; g_free(temp); } else { ret = TRUE; } return ret; } void mainWindow_workspace_search_changed(GtkWidget *widget, gpointer user_data) { struct mainWindow *mainWindow = (struct mainWindow *)user_data; gtk_tree_model_filter_refilter(mainWindow->workspaceListFiltered); } /** * @brief mainWindow_list_entry_visible checks whether the entry should be displayed. * @param model N/A * @param iter N/A * @param mainWindow struct mainWindow * * @return True when it should displayed, else false. */ static gboolean mainWindow_list_entry_visible(GtkTreeModel *model, GtkTreeIter *iter, struct mainWindow *mainWindow) { GRegex *regex; GMatchInfo *match_info; gchar *searchString; gchar *temp; gboolean search_matched = 0; GDateTime *datetime; guint time; if (mainWindow->filterSettings.hide_all) return FALSE; /* Check text search */ searchString = (gchar *)gtk_entry_get_text(GTK_ENTRY(mainWindow->searchEntry)); if (searchString[0] != 0 && ( mainWindow->filterSettings.search_title || mainWindow->filterSettings.search_tags || mainWindow->filterSettings.search_text)) { regex = g_regex_new(searchString, G_REGEX_CASELESS, 0, NULL); gtk_tree_model_get(model, iter, COL_TITLE, &temp, -1); if (mainWindow->filterSettings.search_title && g_regex_match(regex, temp, 0, &match_info) && g_match_info_matches(match_info)) search_matched = 1; g_free(temp); gtk_tree_model_get(model, iter, COL_TAGS_TEXT, &temp, -1); if (!search_matched && mainWindow->filterSettings.search_tags && g_regex_match(regex, temp, 0, &match_info) && g_match_info_matches(match_info)) search_matched = 1; g_free(temp); gtk_tree_model_get(model, iter, COL_SUMMARY, &temp, -1); if (!search_matched && mainWindow->filterSettings.search_summary && g_regex_match(regex, temp, 0, &match_info) && g_match_info_matches(match_info)) search_matched = 1; g_free(temp); gtk_tree_model_get(model, iter, COL_TEXT, &temp, -1); if (!search_matched && mainWindow->filterSettings.search_text && g_regex_match(regex, temp, 0, &match_info) && g_match_info_matches(match_info)) search_matched = 1; g_free(temp); if (!search_matched) return 0; } /* Check time span */ gtk_tree_model_get(model, iter, COL_TIMESTAMP, &datetime, -1); if (datetime) { time = g_date_time_to_unix(datetime); /* The addition in braces allows for the whole day instead of just its first second. */ return time >= (mainWindow->filterSettings.time_start) && time <= mainWindow->filterSettings.time_end + (60 * 60 * 23 + 60 * 59 + 59); } else { return 0; } } /** * @brief mainWindow_sort_date_compare_func Compares the two GDateTimes from the main store. * @param model N/A * @param a N/A * @param b N/A * @param userdata N/A * @return N/A */ static gint mainWindow_sort_date_compare_func(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer userdata) { GDateTime *datetime1; GDateTime *datetime2; guint time1; guint time2; gtk_tree_model_get(model, a, COL_TIMESTAMP, &datetime1, -1); gtk_tree_model_get(model, b, COL_TIMESTAMP, &datetime2, -1); time1 = g_date_time_to_unix(datetime1); time2 = g_date_time_to_unix(datetime2); if (time1 == time2) return 0; else if (time1 > time2) return 1; else return -1; } void mainWindow_add_recent_workspace(struct mainWindow *mainWindow, gchar *path, gboolean append) { GtkTreeIter iter, iter_delete; GRegex *regex; GMatchInfo *match_info; gchar *temp; gboolean del_iter = FALSE; regex = g_regex_new("(.*)\\/(.*)", G_REGEX_RAW, 0, NULL); if (g_regex_match(regex, path, 0, &match_info) && g_regex_get_capture_count(regex) > 1 && g_match_info_matches(match_info)) { g_match_info_fetch(match_info, 1); if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(mainWindow->workspaceListStore), &iter)) { do { memcpy(&iter_delete, &iter, sizeof(iter)); /* scan for last */ gtk_tree_model_get(GTK_TREE_MODEL(mainWindow->workspaceListStore), &iter, WSCOL_PATH, &temp, -1); if (!g_strcmp0(temp, path)) { g_free(temp); gtk_list_store_remove(mainWindow->workspaceListStore, &iter); break; } g_free(temp); } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(mainWindow->workspaceListStore), &iter)); } temp = g_strdup_printf("%s\n%s", g_match_info_fetch(match_info, 2), g_match_info_fetch(match_info, 1)); if (append) gtk_list_store_append(mainWindow->workspaceListStore, &iter); else gtk_list_store_prepend(mainWindow->workspaceListStore, &iter); gtk_list_store_set(mainWindow->workspaceListStore, &iter, WSCOL_LABEL, temp, WSCOL_PATH, path, -1); g_free(temp); if (gtk_tree_model_iter_n_children(GTK_TREE_MODEL(mainWindow->workspaceListStore), NULL) > FILE_LIST_MAX_LEN) gtk_list_store_remove(mainWindow->workspaceListStore, &iter_delete); } g_regex_unref(regex); } /** * @brief mainWindow_wschooser_configure_treeView configures the GtkTreeView for workspace selection * @param mainWindow */ static void mainWindow_configure_workspaceTreeView(struct mainWindow *mainWindow) { GtkCellRenderer *renderer; GtkTreeViewColumn *col; mainWindow->workspaceListStore = gtk_list_store_new(WSCOL_COUNT, G_TYPE_STRING, G_TYPE_STRING); mainWindow->workspaceListFiltered = GTK_TREE_MODEL_FILTER( gtk_tree_model_filter_new( GTK_TREE_MODEL(mainWindow->workspaceListStore), NULL)); gtk_tree_model_filter_set_visible_func(mainWindow->workspaceListFiltered, (GtkTreeModelFilterVisibleFunc) mainWindow_workspace_entry_visible, mainWindow, NULL); gtk_tree_view_set_model(mainWindow->workspaceListView, GTK_TREE_MODEL(mainWindow->workspaceListFiltered)); renderer = gtk_cell_renderer_text_new(); gtk_tree_view_insert_column_with_attributes(mainWindow->workspaceListView, -1, "", renderer, "markup", WSCOL_LABEL, NULL); } /** * @brief mainWindow_configure_treeView configures GtkTreeView * @param mainWindow struct mainWindow * */ static void mainWindow_configure_treeView(struct mainWindow *mainWindow) { GtkCellRenderer *renderer; GtkTreeSortable *sortable; GtkTreeViewColumn *col; GtkTreeModelSort *sorted; GtkTreeModel *model; mainWindow->entryListStore = gtk_list_store_new(COL_COUNT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_STRING); mainWindow->entryListFiltered = GTK_TREE_MODEL_FILTER(gtk_tree_model_filter_new( GTK_TREE_MODEL(mainWindow->entryListStore), NULL)); sorted = GTK_TREE_MODEL_SORT(gtk_tree_model_sort_new_with_model( GTK_TREE_MODEL(mainWindow->entryListFiltered))); gtk_tree_model_filter_set_visible_func(mainWindow->entryListFiltered, (GtkTreeModelFilterVisibleFunc) mainWindow_list_entry_visible, mainWindow, NULL); model = GTK_TREE_MODEL(sorted); gtk_tree_view_set_model(mainWindow->entryListView, model); /* TODO: Unref mainWindow->entryListStore and filtered, sorted and model? */ sortable = GTK_TREE_SORTABLE(sorted); renderer = gtk_cell_renderer_text_new(); gtk_tree_view_insert_column_with_attributes(mainWindow->entryListView, -1, "Title", renderer, "text", COL_TITLE, NULL); col = gtk_tree_view_get_column(mainWindow->entryListView, COL_TITLE); gtk_tree_view_column_set_resizable(col, 1); gtk_tree_view_column_set_sort_column_id(col, COL_TITLE); renderer = gtk_cell_renderer_text_new(); gtk_tree_view_insert_column_with_attributes(mainWindow->entryListView, -1, "Date", renderer, "text", COL_DATE_TEXT, NULL); col = gtk_tree_view_get_column(mainWindow->entryListView, COL_DATE_TEXT); gtk_tree_view_column_set_resizable(col, 1); gtk_tree_sortable_set_sort_func(sortable, COL_DATE_TEXT, mainWindow_sort_date_compare_func, GINT_TO_POINTER(COL_DATE_TEXT), NULL); gtk_tree_view_column_set_sort_column_id(col, COL_DATE_TEXT); renderer = gtk_cell_renderer_text_new(); gtk_tree_view_insert_column_with_attributes(mainWindow->entryListView, -1, "Tags", renderer, "text", COL_TAGS_TEXT, NULL); col = gtk_tree_view_get_column(mainWindow->entryListView, COL_TAGS_TEXT); gtk_tree_view_column_set_resizable(col, 1); 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); } static void mainWindow_configure_entry_completion(struct mainWindow *mainWindow) { GtkCellRenderer *renderer; GtkTreeSortable *sortable; GtkTreeModelSort *sorted; GtkTreeModel *model; GtkTreeIter iter; mainWindow->completionListStore = gtk_list_store_new(1, G_TYPE_STRING); sorted = GTK_TREE_MODEL_SORT(gtk_tree_model_sort_new_with_model( GTK_TREE_MODEL(mainWindow->completionListStore))); model = GTK_TREE_MODEL(sorted); /* TODO: Unref mainWindow->completionListStore and filtered, sorted and model? */ sortable = GTK_TREE_SORTABLE(sorted); renderer = gtk_cell_renderer_text_new(); gtk_entry_completion_set_model(mainWindow->searchEntryCompletion, model); gtk_entry_completion_set_text_column(mainWindow->searchEntryCompletion, 0); gtk_tree_sortable_set_sort_column_id(sortable, 0, GTK_SORT_ASCENDING); } /** * @brief mainWindow_connect_signals connects are g signals * @param mainWindow struct mainWindow * */ static void mainWindow_connect_signals(struct mainWindow *mainWindow) { g_signal_connect(mainWindow->dateStart, "focus-in-event", (GCallback) mainWindow_showPopover, mainWindow); g_signal_connect(mainWindow->dateEnd, "focus-in-event", (GCallback) mainWindow_showPopover, mainWindow); g_signal_connect(mainWindow->labelDateToDate, "activate-link", (GCallback) mainWindow_showPopover, mainWindow); g_signal_connect(mainWindow->calendarRange, "day-selected", (GCallback) mainWindow_calendarSelected, mainWindow); g_signal_connect_swapped(mainWindow->calendarRange, "day-selected-double-click", (GCallback) gtk_popover_popdown, mainWindow->popoverDate); g_signal_connect(mainWindow->entryListSelection, "changed", (GCallback) mainWindow_entrySelected, mainWindow); g_signal_connect(mainWindow->dateStart, "changed", (GCallback) mainWindow_filterChanged, mainWindow); g_signal_connect(mainWindow->dateEnd, "changed", (GCallback) mainWindow_filterChanged, mainWindow); g_signal_connect(mainWindow->dateStart, "focus-out-event", (GCallback) mainWindow_checkDate, mainWindow); g_signal_connect(mainWindow->dateEnd, "focus-out-event", (GCallback) mainWindow_checkDate, mainWindow); g_signal_connect(mainWindow->searchEntry, "changed", (GCallback) mainWindow_filterChanged, mainWindow); g_signal_connect(mainWindow->checkSearchTitle, "toggled", (GCallback) mainWindow_filterChanged, mainWindow); g_signal_connect(mainWindow->checkSearchTags, "toggled", (GCallback) mainWindow_filterChanged, mainWindow); g_signal_connect(mainWindow->checkSearchText, "toggled", (GCallback) mainWindow_filterChanged, mainWindow); g_signal_connect(mainWindow->checkSearchSummary, "toggled", (GCallback) mainWindow_filterChanged, mainWindow); g_signal_connect(mainWindow->buttonClearSearch, "clicked", (GCallback) mainWindow_clearSearch, mainWindow); g_signal_connect(mainWindow->dateStart, "icon-press", (GCallback) mainWindow_dateIconPress, mainWindow); g_signal_connect(mainWindow->dateEnd, "icon-press", (GCallback) mainWindow_dateIconPress, mainWindow); g_signal_connect(mainWindow->buttonOtherWorkspace, "clicked", (GCallback) mainWindow_otherWorkspaceClicked, mainWindow); g_signal_connect(mainWindow->workspaceListView, "row-activated", (GCallback) mainWindow_workspaceListClicked, mainWindow); g_signal_connect(mainWindow->workspaceSearch, "changed", (GCallback) mainWindow_workspace_search_changed, mainWindow); } /** * @brief mainWindow_init_to_default initializes all non-date related UI elements to sensible values. * @param mainWindow */ static void mainWindow_init_to_default(struct mainWindow *mainWindow) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(mainWindow->checkSearchTitle), 1); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(mainWindow->checkSearchSummary), 1); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(mainWindow->checkSearchTags), 1); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(mainWindow->checkSearchText), 0); } /** * @brief mainWindow_new creates a new mainWindow. * @return Returns struct mainWindow * */ struct mainWindow *mainWindow_new() { GtkBuilder *builder; struct mainWindow *mainWindow; builder = gtk_builder_new_from_file("glade/mainWindow.glade"); mainWindow = malloc(sizeof(struct mainWindow)); mainWindow->mainWindow = GTK_WIDGET(gtk_builder_get_object(builder, "mainWindow")); mainWindow->mainPane = GTK_WIDGET(gtk_builder_get_object(builder, "mainPane")); mainWindow->searchEntry = GTK_WIDGET(gtk_builder_get_object(builder, "searchEntry")); mainWindow->dateStart = GTK_WIDGET(gtk_builder_get_object(builder, "dateStart")); mainWindow->dateEnd = GTK_WIDGET(gtk_builder_get_object(builder, "dateEnd")); mainWindow->entryText = GTK_WIDGET(gtk_builder_get_object(builder, "entryText")); mainWindow->popoverDate = GTK_WIDGET(gtk_builder_get_object(builder, "popoverDate")); mainWindow->calendarRange = GTK_WIDGET(gtk_builder_get_object(builder, "calendarRange")); mainWindow->checkSearchTitle = GTK_WIDGET(gtk_builder_get_object(builder, "checkSearchTitle")); mainWindow->checkSearchSummary = GTK_WIDGET(gtk_builder_get_object(builder, "checkSearchSummary")); mainWindow->checkSearchTags = GTK_WIDGET(gtk_builder_get_object(builder, "checkSearchTags")); mainWindow->checkSearchText = GTK_WIDGET(gtk_builder_get_object(builder, "checkSearchText")); mainWindow->labelSummary = GTK_WIDGET(gtk_builder_get_object(builder, "labelSummary")); mainWindow->buttonClearSearch = GTK_WIDGET(gtk_builder_get_object(builder, "buttonClearSearch")); mainWindow->headerBar = GTK_WIDGET(gtk_builder_get_object(builder, "headerBar")); mainWindow->labelDateToDate = GTK_WIDGET(gtk_builder_get_object(builder, "label_date_to_date")); mainWindow->buttonDecrypt = GTK_WIDGET(gtk_builder_get_object(builder, "buttonDecrypt")); mainWindow->entryListView = GTK_TREE_VIEW(gtk_builder_get_object(builder, "entryListView")); mainWindow->entryListSelection = GTK_TREE_SELECTION(gtk_builder_get_object(builder, "entryListSelection")); mainWindow->textBuffer = GTK_TEXT_BUFFER(gtk_builder_get_object(builder, "entryTextBuffer")); mainWindow->searchEntryCompletion = GTK_ENTRY_COMPLETION(gtk_builder_get_object( builder, "searchEntryCompletion")); mainWindow->buttonOtherWorkspace = GTK_WIDGET(gtk_builder_get_object(builder, "buttonOtherWorkspace")); mainWindow->workspaceSearch = GTK_WIDGET(gtk_builder_get_object(builder, "searchWorkspace")); mainWindow->popoverWorkspace = GTK_WIDGET(gtk_builder_get_object(builder, "popoverWorkspace")); mainWindow->workspaceListView = GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeWorkspace")); mainWindow->workspaceListSelection = GTK_TREE_SELECTION(gtk_builder_get_object(builder, "treeWorkspaceSelection")); mainWindow->filterSettings.time_start = 0; mainWindow->filterSettings.time_end = -1; mainWindow->filterSettings.hide_all = TRUE; mainWindow->time_earliest = 0; mainWindow->time_latest = 0; gtk_builder_connect_signals(builder, NULL); g_object_unref(G_OBJECT(builder)); mainWindow_configure_treeView(mainWindow); mainWindow_connect_signals(mainWindow); mainWindow_configure_workspaceTreeView(mainWindow); mainWindow_init_to_default(mainWindow); mainWindow_clearSearch(NULL, mainWindow); mainWindow_configure_entry_completion(mainWindow); mainWindow_set_meta_information(mainWindow, 0, 0, TRUE); return mainWindow; } /** * @brief mainWindow_set_meta_information sets some meta info for a nice GUI. It also resets the search. * @param mainWindow * @param time_earliest is the reset value for the filter start date * @param time_latest is the reset value for the filter end date */ void mainWindow_set_meta_information(struct mainWindow *mainWindow, guint time_earliest, guint time_latest, gboolean hide_all) { mainWindow->time_earliest = time_earliest; mainWindow->time_latest = time_latest; mainWindow->filterSettings.hide_all = hide_all; gtk_widget_set_sensitive(mainWindow->mainPane, !hide_all); mainWindow_clearSearch(NULL, mainWindow); } /** * @brief mainWindow_showPopover is called from a dateEntry when it is focused. * @param widget is the text entry. * @param event N/A * @param user_data struct mainWindow * */ void mainWindow_showPopover(GtkWidget *widget, GdkEvent *event, gpointer user_data) { struct mainWindow *mainWindow = (struct mainWindow *)user_data; GDateTime *datetime; mainWindow->selectedDateEntry = NULL; datetime = g_date_time_new_from_unix_local((widget == mainWindow->dateStart ? mainWindow->filterSettings.time_start : mainWindow->filterSettings.time_end)); if (datetime) { gtk_calendar_select_month(GTK_CALENDAR(mainWindow->calendarRange), g_date_time_get_month(datetime) - 1, g_date_time_get_year(datetime)); gtk_calendar_select_day(GTK_CALENDAR(mainWindow->calendarRange), g_date_time_get_day_of_month(datetime)); g_date_time_unref(datetime); } /* gtk_editable_select_region(GTK_EDITABLE(widget), 0, 255); */ mainWindow->selectedDateEntry = widget; if (!gtk_widget_get_visible(mainWindow->popoverDate)) gtk_popover_popup(GTK_POPOVER(mainWindow->popoverDate)); gtk_popover_set_relative_to(GTK_POPOVER(mainWindow->popoverDate), widget); } /** * @brief mainWindow_calendarSelected is the callback when the user selects a date in the calendar. * @param widget is the calendar. * @param user_data struct mainWindow * */ void mainWindow_calendarSelected(GtkWidget *widget, gpointer user_data) { struct mainWindow *mainWindow = (struct mainWindow *)user_data; guint year, month, day; gchar *text; gtk_calendar_get_date(GTK_CALENDAR(mainWindow->calendarRange), &year, &month, &day); text = g_strdup_printf("%d-%02d-%02d", year, month + 1, day); if (mainWindow->selectedDateEntry == mainWindow->labelDateToDate) { gtk_entry_set_text(GTK_ENTRY(mainWindow->dateStart), text); gtk_entry_set_text(GTK_ENTRY(mainWindow->dateEnd), text); } else if (mainWindow->selectedDateEntry) { gtk_entry_set_text(GTK_ENTRY(mainWindow->selectedDateEntry), text); } g_free(text); } /** * @brief mainWindow_entrySelected is the callback when the user selects a diary entry. * @param widget N/A * @param user_data struct mainWindow * */ void mainWindow_entrySelected(GtkWidget *widget, gpointer user_data) { struct mainWindow *mainWindow = (struct mainWindow *)user_data; GtkTreeSelection *selection; GtkTreeModel *model; GtkTreeIter iter; gchar *text; gchar *title; gchar *summary; gchar *temp; selection = gtk_tree_view_get_selection(mainWindow->entryListView); if (gtk_tree_selection_get_selected(selection, &model, &iter)) { gtk_tree_model_get(model, &iter, COL_TEXT, &text, -1); gtk_text_buffer_set_text(mainWindow->textBuffer, text, strlen(text)); g_free(text); gtk_tree_model_get(model, &iter, COL_SUMMARY, &summary, -1); gtk_tree_model_get(model, &iter, COL_TITLE, &title, -1); temp = g_strdup_printf("%s: %s", title, summary); gtk_label_set_markup(GTK_LABEL(mainWindow->labelSummary), temp); g_free(title); g_free(summary); g_free(temp); } else { gtk_text_buffer_set_text(mainWindow->textBuffer, "", 0); gtk_label_set_text(GTK_LABEL(mainWindow->labelSummary), "Please select an entry in the list above."); } } /** * @brief mainWindow_filterChanged updates the filter backend values * @param widget The widget that caused the update request. Can be NULL to update all. * @param user_data struct mainWindow * */ void mainWindow_filterChanged(GtkWidget *widget, gpointer user_data) { GDateTime *datetime; struct mainWindow *mainWindow = (struct mainWindow *)user_data; if (!widget || widget == 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); } gtk_entry_set_icon_from_icon_name(GTK_ENTRY(widget ? widget : mainWindow->dateStart), GTK_ENTRY_ICON_SECONDARY, "edit-clear-symbolic"); } if (!widget || widget == 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); } gtk_entry_set_icon_from_icon_name(GTK_ENTRY(widget ? widget : mainWindow->dateStart), GTK_ENTRY_ICON_SECONDARY, "edit-clear-symbolic"); } mainWindow->filterSettings.search_title = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(mainWindow->checkSearchTitle)); mainWindow->filterSettings.search_tags = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(mainWindow->checkSearchTags)); mainWindow->filterSettings.search_text = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(mainWindow->checkSearchText)); mainWindow->filterSettings.search_summary = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(mainWindow->checkSearchSummary)); gtk_tree_model_filter_refilter(mainWindow->entryListFiltered); } /** * @brief mainWindow_checkDate checks the date in a text box and resets it if necessary. * @param widget is the GtkEntry to be checked. * @param event N/A * @param user_data struct mainWindow * */ void mainWindow_checkDate(GtkWidget *widget, gint event, gpointer user_data) { struct mainWindow *mainWindow = (struct mainWindow *)user_data; GDateTime *datetime; 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 : mainWindow->filterSettings.time_end); gtk_entry_set_text(GTK_ENTRY(widget), g_date_time_format(datetime, "%Y-%m-%d")); } g_date_time_unref(datetime); } /** * @brief mainWindow_clearSearch resets all search UI elements * @param widget * @param event * @param user_data */ void mainWindow_clearSearch(GtkWidget *widget, gpointer user_data) { struct mainWindow *mainWindow = (struct mainWindow *)user_data; GDateTime *datetime; gchar *temp; if (widget == mainWindow->buttonClearSearch) widget = NULL; if (!widget || widget == mainWindow->searchEntry) gtk_entry_set_text(GTK_ENTRY(mainWindow->searchEntry), ""); if (!widget || widget == mainWindow->dateStart) { datetime = g_date_time_new_from_unix_local(mainWindow->time_earliest); temp = g_date_time_format(datetime, "%Y-%m-%d"); gtk_entry_set_text(GTK_ENTRY(mainWindow->dateStart), temp); g_date_time_unref(datetime); g_free(temp); gtk_entry_set_icon_from_icon_name(GTK_ENTRY(widget ? widget : mainWindow->dateStart), GTK_ENTRY_ICON_SECONDARY, ""); } if (!widget || widget == mainWindow->dateEnd) { datetime = g_date_time_new_from_unix_local(mainWindow->time_latest); temp = g_date_time_format(datetime, "%Y-%m-%d"); gtk_entry_set_text(GTK_ENTRY(mainWindow->dateEnd), temp); g_date_time_unref(datetime); g_free(temp); gtk_entry_set_icon_from_icon_name(GTK_ENTRY(widget ? widget : mainWindow->dateEnd), GTK_ENTRY_ICON_SECONDARY, ""); } } void mainWindow_dateIconPress(GtkWidget *widget, gint icon_pos, gint event, gpointer user_data) { mainWindow_clearSearch(widget, user_data); } static void mainWindow_show_error(struct mainWindow *mainWindow, gchar *text) { GtkWidget *dialog; dialog = gtk_message_dialog_new(GTK_WINDOW(mainWindow->mainWindow), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "Error: %s", text); gtk_dialog_run(GTK_DIALOG (dialog)); gtk_widget_destroy(dialog); } void mainWindow_switch_workspace(struct mainWindow *mainWindow, gchar *path) { g_print("Switching workspace to %s.\n", path); gtk_popover_popdown(GTK_POPOVER(mainWindow->popoverWorkspace)); mainWindow_set_meta_information(mainWindow, 0, 0, TRUE); mdiary_reset_store(mainWindow->entryListStore, mainWindow->completionListStore); if (mdiary_scan_to_store(path, mainWindow->entryListStore, mainWindow->completionListStore)) { mainWindow_set_meta_information(mainWindow, mdiary_get_time_earliest(), mdiary_get_time_latest(), FALSE); mainWindow_add_recent_workspace(mainWindow, path, FALSE); gtk_header_bar_set_subtitle(GTK_HEADER_BAR(mainWindow->headerBar), path); } else { gtk_header_bar_set_subtitle(GTK_HEADER_BAR(mainWindow->headerBar), "No workspace opened."); mainWindow_show_error(mainWindow, "Could not open workspace or no entries were found in it."); } } void mainWindow_workspaceListClicked(GtkWidget *widget, GtkTreePath *tree_path, GtkTreeViewColumn *column, gpointer user_data) { struct mainWindow *mainWindow = (struct mainWindow *)user_data; GtkTreeModel *model; GtkTreeIter iter; GtkTreeSelection *selection; gchar *path; gtk_popover_popdown(GTK_POPOVER(mainWindow->popoverWorkspace)); selection = gtk_tree_view_get_selection(mainWindow->workspaceListView); if (gtk_tree_selection_get_selected(selection, &model, &iter)) { gtk_tree_model_get(model, &iter, WSCOL_PATH, &path, -1); mainWindow_switch_workspace(mainWindow, path); g_free(path); } } /** * @brief mainWindow_otherWorkspaceClicked is called when the user clicks the Other Workspace button. * @param widget N/A * @param event N/A * @param user_data struct mainWindow * */ void mainWindow_otherWorkspaceClicked(GtkWidget *widget, gpointer user_data) { struct mainWindow *mainWindow = (struct mainWindow *)user_data; GtkWidget *dialog; gint res; dialog = gtk_file_chooser_dialog_new("Choose Workspace", GTK_WINDOW(mainWindow->mainWindow), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, "Cancel", GTK_RESPONSE_CANCEL, "Select", GTK_RESPONSE_ACCEPT, NULL); gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); res = gtk_dialog_run (GTK_DIALOG (dialog)); if (res == GTK_RESPONSE_ACCEPT) { char *directory; directory = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); mainWindow_switch_workspace(mainWindow, directory); g_free(directory); } gtk_widget_destroy (dialog); }