📄 bar_info.c
字号:
GtkWidget *label_file_time; GtkWidget *keyword_view; GtkWidget *keyword_treeview; GtkWidget *comment_view; GtkWidget *button_save; GtkWidget *button_set_add; GtkWidget *button_set_replace; gchar *path; gint changed; gint save_timeout_id; GList *(*list_func)(gpointer); gpointer list_data;};static GList *bar_list = NULL;static void bar_info_write(BarInfoData *bd){ GList *list; gchar *comment; if (!bd->path) return; list = keyword_list_pull(bd->keyword_view); comment = comment_pull(bd->comment_view); comment_cache_write(bd->path, list, comment); path_list_free(list); g_free(comment); bd->changed = FALSE; gtk_widget_set_sensitive(bd->button_save, FALSE);}static gint bar_info_autosave(gpointer data){ BarInfoData *bd = data; bar_info_write(bd); bd->save_timeout_id = -1; return FALSE;}static void bar_info_save_update(BarInfoData *bd, gint enable){ if (bd->save_timeout_id != -1) { g_source_remove(bd->save_timeout_id); bd->save_timeout_id = -1; } if (enable) { bd->save_timeout_id = g_timeout_add(BAR_KEYWORD_AUTOSAVE_TIME, bar_info_autosave, bd); }}static gint bar_keyword_list_find(GList *list, const gchar *keyword){ while (list) { gchar *haystack = list->data; if (haystack && keyword && strcmp(haystack, keyword) == 0) return TRUE; list = list->next; } return FALSE;}static void bar_keyword_list_sync(BarInfoData *bd, GList *keywords){ GList *list; GtkListStore *store; GtkTreeIter iter; list = history_list_get_by_key("keywords"); if (!list) { /* blank? set up a few example defaults */ gint i = 0; while (keyword_favorite_defaults[i] != NULL) { history_list_add_to_key("keywords", _(keyword_favorite_defaults[i]), 0); i++; } list = history_list_get_by_key("keywords"); } store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(bd->keyword_treeview))); gtk_list_store_clear(store); list = g_list_last(list); while (list) { gchar *key = list->data; gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, KEYWORD_COLUMN_TOGGLE, bar_keyword_list_find(keywords, key), KEYWORD_COLUMN_TEXT, key, -1); list = list->prev; }}static void bar_info_keyword_update_all(void){ GList *work; work = bar_list; while (work) { BarInfoData *bd; GList *keywords; bd = work->data; work = work->next; keywords = keyword_list_pull(bd->keyword_view); bar_keyword_list_sync(bd, keywords); path_list_free(keywords); }}static void bar_info_update(BarInfoData *bd){ GList *keywords = NULL; gchar *comment = NULL; if (bd->label_file_name) { gtk_label_set_text(GTK_LABEL(bd->label_file_name), (bd->path) ? filename_from_path(bd->path) : ""); } if (bd->label_file_time) { gtk_label_set_text(GTK_LABEL(bd->label_file_time), (bd->path) ? text_from_time(filetime(bd->path)) : ""); } if (comment_cache_read(bd->path, &keywords, &comment)) { keyword_list_push(bd->keyword_view, keywords); gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(bd->comment_view)), (comment) ? comment : "", -1); bar_keyword_list_sync(bd, keywords); path_list_free(keywords); g_free(comment); } else { gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(bd->keyword_view)), "", -1); gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(bd->comment_view)), "", -1); bar_keyword_list_sync(bd, NULL); } bar_info_save_update(bd, FALSE); bd->changed = FALSE; gtk_widget_set_sensitive(bd->button_save, FALSE); gtk_widget_set_sensitive(bd->group_box, (bd->path != NULL));}void bar_info_set(GtkWidget *bar, const gchar *path){ BarInfoData *bd; bd = g_object_get_data(G_OBJECT(bar), "bar_info_data"); if (!bd) return; if (bd->changed) bar_info_write(bd); g_free(bd->path); bd->path = g_strdup(path); bar_info_update(bd);}void bar_info_maint_renamed(GtkWidget *bar, const gchar *path){ BarInfoData *bd; bd = g_object_get_data(G_OBJECT(bar), "bar_info_data"); if (!bd) return; g_free(bd->path); bd->path = g_strdup(path); if (bd->label_file_name) { gtk_label_set_text(GTK_LABEL(bd->label_file_name), (bd->path) ? filename_from_path(bd->path) : ""); }}gint bar_info_event(GtkWidget *bar, GdkEvent *event){ BarInfoData *bd; bd = g_object_get_data(G_OBJECT(bar), "bar_info_data"); if (!bd) return FALSE; if (GTK_WIDGET_HAS_FOCUS(bd->keyword_view)) return gtk_widget_event(bd->keyword_view, event); if (GTK_WIDGET_HAS_FOCUS(bd->comment_view)) return gtk_widget_event(bd->comment_view, event); return FALSE;}static void bar_info_keyword_set(BarInfoData *bd, const gchar *keyword, gint active){ GList *list; gint found; if (!keyword) return; list = keyword_list_pull(bd->keyword_view); found = bar_keyword_list_find(list, keyword); if (active != found) { if (found) { GList *work = list; while (work) { gchar *key = work->data; work = work->next; if (key && keyword && strcmp(key, keyword) == 0) { list = g_list_remove(list, key); g_free(key); } } } else { list = g_list_append(list, g_strdup(keyword)); } keyword_list_push(bd->keyword_view, list); } path_list_free(list);}static void bar_info_keyword_toggle(GtkCellRendererToggle *toggle, const gchar *path, gpointer data){ BarInfoData *bd = data; GtkTreeModel *store; GtkTreeIter iter; GtkTreePath *tpath; gchar *key = NULL; gboolean active; store = gtk_tree_view_get_model(GTK_TREE_VIEW(bd->keyword_treeview)); tpath = gtk_tree_path_new_from_string(path); gtk_tree_model_get_iter(store, &iter, tpath); gtk_tree_path_free(tpath); gtk_tree_model_get(store, &iter, KEYWORD_COLUMN_TOGGLE, &active, KEYWORD_COLUMN_TEXT, &key, -1); active = (!active); gtk_list_store_set(GTK_LIST_STORE(store), &iter, KEYWORD_COLUMN_TOGGLE, active, -1); bar_info_keyword_set(bd, key, active); g_free(key);}static void bar_info_save(GtkWidget *button, gpointer data){ BarInfoData *bd = data; bar_info_save_update(bd, FALSE); bar_info_write(bd);}static void bar_info_set_selection(BarInfoData *bd, gint add){ GList *keywords; GList *list = NULL; GList *work; if (!bd->list_func) return; keywords = keyword_list_pull(bd->keyword_view); if (!keywords && add) return; list = bd->list_func(bd->list_data); work = list; while (work) { const gchar *path = work->data; work = work->next; metadata_set_keywords(path, keywords, add); } path_list_free(list); path_list_free(keywords);}static void bar_info_set_add(GtkWidget *button, gpointer data){ BarInfoData *bd = data; bar_info_set_selection(bd, TRUE);}static void bar_info_set_replace(GtkWidget *button, gpointer data){ BarInfoData *bd = data; bar_info_set_selection(bd, FALSE);}static void bar_info_changed(GtkTextBuffer *buffer, gpointer data){ BarInfoData *bd = data; bd->changed = TRUE; gtk_widget_set_sensitive(bd->button_save, TRUE); bar_info_save_update(bd, TRUE);}void bar_info_close(GtkWidget *bar){ BarInfoData *bd; bd = g_object_get_data(G_OBJECT(bar), "bar_info_data"); if (!bd) return; gtk_widget_destroy(bd->vbox);}static void bar_info_destroy(GtkWidget *widget, gpointer data){ BarInfoData *bd = data; if (bd->changed) bar_info_write(bd); bar_info_save_update(bd, FALSE); bar_list = g_list_remove(bar_list, bd); g_free(bd->path); g_free(bd);}GtkWidget *bar_info_new(const gchar *path, gint metadata_only, GtkWidget *bounding_widget){ BarInfoData *bd; GtkWidget *box; GtkWidget *hbox; GtkWidget *table; GtkWidget *scrolled; GtkTextBuffer *buffer; GtkWidget *label; GtkWidget *tbar; GtkListStore *store; GtkTreeViewColumn *column; GtkCellRenderer *renderer; bd = g_new0(BarInfoData, 1); bd->list_func = NULL; bd->list_data = NULL; bd->vbox = gtk_vbox_new(FALSE, PREF_PAD_GAP); g_object_set_data(G_OBJECT(bd->vbox), "bar_info_data", bd); g_signal_connect(G_OBJECT(bd->vbox), "destroy", G_CALLBACK(bar_info_destroy), bd); if (!metadata_only) { hbox = pref_box_new(bd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_GAP); label = sizer_new(bd->vbox, bounding_widget, SIZER_POS_LEFT); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); gtk_widget_show(label); label = gtk_label_new(_("Keywords")); pref_label_bold(label, TRUE, FALSE); gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0); gtk_widget_show(label); } bd->group_box = pref_box_new(bd->vbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP); if (!metadata_only) { GtkWidget *table; table = pref_table_new(bd->group_box, 2, 2, FALSE, FALSE); bd->label_file_name = table_add_line(table, 0, 0, _("Filename:"), NULL); bd->label_file_time = table_add_line(table, 0, 1, _("File date:"), NULL); } else { bd->label_file_name = NULL; bd->label_file_time = NULL; } table = gtk_table_new(3, 1, TRUE); gtk_table_set_row_spacings(GTK_TABLE(table), PREF_PAD_GAP); gtk_box_pack_start(GTK_BOX(bd->group_box), table, TRUE, TRUE, 0); gtk_widget_show(table); /* keyword entry */ box = gtk_vbox_new(FALSE, 0); gtk_table_attach(GTK_TABLE(table), box, 0, 1, 0, 2, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_widget_show(box); label = pref_label_new(box, _("Keywords:")); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); pref_label_bold(label, TRUE, FALSE); hbox = pref_box_new(box, TRUE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_GAP); scrolled = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_box_pack_start(GTK_BOX(hbox), scrolled, TRUE, TRUE, 0); gtk_widget_show(scrolled); bd->keyword_view = gtk_text_view_new(); gtk_container_add(GTK_CONTAINER(scrolled), bd->keyword_view); gtk_widget_show(bd->keyword_view); buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(bd->keyword_view)); g_signal_connect(G_OBJECT(buffer), "changed", G_CALLBACK(bar_info_changed), bd); scrolled = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_box_pack_start(GTK_BOX(hbox), scrolled, TRUE, TRUE, 0); gtk_widget_show(scrolled); store = gtk_list_store_new(2, G_TYPE_BOOLEAN, G_TYPE_STRING); bd->keyword_treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); g_object_unref(store); gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(bd->keyword_treeview), FALSE); if (metadata_only) { gtk_tree_view_set_search_column(GTK_TREE_VIEW(bd->keyword_treeview), KEYWORD_COLUMN_TEXT); } else { gtk_tree_view_set_enable_search(GTK_TREE_VIEW(bd->keyword_treeview), FALSE); } column = gtk_tree_view_column_new(); gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); renderer = gtk_cell_renderer_toggle_new(); gtk_tree_view_column_pack_start(column, renderer, FALSE); gtk_tree_view_column_add_attribute(column, renderer, "active", KEYWORD_COLUMN_TOGGLE); g_signal_connect(G_OBJECT(renderer), "toggled", G_CALLBACK(bar_info_keyword_toggle), bd); renderer = gtk_cell_renderer_text_new(); gtk_tree_view_column_pack_start(column, renderer, TRUE); gtk_tree_view_column_add_attribute(column, renderer, "text", KEYWORD_COLUMN_TEXT); gtk_tree_view_append_column(GTK_TREE_VIEW(bd->keyword_treeview), column); gtk_container_add(GTK_CONTAINER(scrolled), bd->keyword_treeview); gtk_widget_show(bd->keyword_treeview); /* comment entry */ box = gtk_vbox_new(FALSE, 0); gtk_table_attach(GTK_TABLE(table), box, 0, 1, 2, 3, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); gtk_widget_show(box); label = pref_label_new(box, _("Comment:")); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); pref_label_bold(label, TRUE, FALSE); scrolled = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_box_pack_start(GTK_BOX(box), scrolled, TRUE, TRUE, 0); gtk_widget_show(scrolled); bd->comment_view = gtk_text_view_new(); gtk_container_add(GTK_CONTAINER(scrolled), bd->comment_view); gtk_widget_show(bd->comment_view); buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(bd->comment_view)); g_signal_connect(G_OBJECT(buffer), "changed", G_CALLBACK(bar_info_changed), bd); /* toolbar */ tbar = pref_toolbar_new(bd->group_box, GTK_TOOLBAR_ICONS); pref_toolbar_button(tbar, GTK_STOCK_INDEX, NULL, FALSE, _("Edit favorite keywords list."), G_CALLBACK(bar_keyword_edit_cb), bd); pref_toolbar_spacer(tbar); bd->button_set_add = pref_toolbar_button(tbar, GTK_STOCK_ADD, NULL, FALSE, _("Add keywords to selected files"), G_CALLBACK(bar_info_set_add), bd); bd->button_set_replace = pref_toolbar_button(tbar, GTK_STOCK_CONVERT, NULL, FALSE, _("Add keywords to selected files, replacing the existing ones."), G_CALLBACK(bar_info_set_replace), bd); pref_toolbar_spacer(tbar); bd->button_save = pref_toolbar_button(tbar, GTK_STOCK_SAVE, NULL, FALSE, _("Save comment now"), G_CALLBACK(bar_info_save), bd); bd->save_timeout_id = -1; bd->path = g_strdup(path); bar_info_update(bd); bar_info_selection(bd->vbox, 0); bar_list = g_list_append(bar_list, bd); return bd->vbox;}void bar_info_set_selection_func(GtkWidget *bar, GList *(*list_func)(gpointer data), gpointer data){ BarInfoData *bd; bd = g_object_get_data(G_OBJECT(bar), "bar_info_data"); if (!bd) return; bd->list_func = list_func; bd->list_data = data;}void bar_info_selection(GtkWidget *bar, gint count){ BarInfoData *bd; gint enable; bd = g_object_get_data(G_OBJECT(bar), "bar_info_data"); if (!bd) return; enable = (count > 0 && bd->list_func != NULL); gtk_widget_set_sensitive(bd->button_set_add, enable); gtk_widget_set_sensitive(bd->button_set_replace, enable);}void bar_info_size_request(GtkWidget *bar, gint width){ BarInfoData *bd; bd = g_object_get_data(G_OBJECT(bar), "bar_info_data"); if (!bd) return; if (bd->label_file_name) { gtk_widget_set_size_request(bd->vbox, width, -1); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -