📄 bar_info.c
字号:
/* * GQview * (C) 2004 John Ellis * * Author: John Ellis * * This software is released under the GNU General Public License (GNU GPL). * Please read the included file COPYING for more information. * This software comes with no warranty of any kind, use at your own risk! */#include "gqview.h"#include "bar_info.h"#include "cache.h"#include "filelist.h"#include "info.h"#include "utilops.h"#include "ui_bookmark.h"#include "ui_fileops.h"#include "ui_misc.h"#include "ui_utildlg.h"#define BAR_KEYWORD_AUTOSAVE_TIME 10000static const gchar *keyword_favorite_defaults[] = { N_("Favorite"), N_("Todo"), N_("People"), N_("Places"), N_("Art"), N_("Nature"), N_("Possessions"), NULL};static void bar_info_keyword_update_all(void);/* *------------------------------------------------------------------- * keyword / comment utils *------------------------------------------------------------------- */gint comment_write(const gchar *path, GList *keywords, const gchar *comment){ FILE *f; f = fopen(path, "w"); if (!f) return FALSE; fprintf(f, "#GQview comment (%s)\n\n", VERSION); fprintf(f, "[keywords]\n"); while (keywords) { const gchar *word = keywords->data; keywords = keywords->next; fprintf(f, "%s\n", word); } fprintf(f, "\n"); fprintf(f, "[comment]\n"); fprintf(f, "%s\n", (comment) ? comment : ""); fprintf(f, "#end\n"); fclose(f); return TRUE;}gint comment_cache_write(const gchar *path, GList *keywords, const gchar *comment){ gchar *comment_path; gint success = FALSE; /* If an existing metadata file exists, we will try writing to * it's location regardless of the user's preference. */ comment_path = cache_find_location(CACHE_TYPE_METADATA, path); if (comment_path && !access_file(comment_path, W_OK)) { g_free(comment_path); comment_path = NULL; } if (!comment_path) { gchar *comment_dir; mode_t mode = 0755; comment_dir = cache_get_location(CACHE_TYPE_METADATA, path, FALSE, &mode); if (cache_ensure_dir_exists(comment_dir, mode)) { comment_path = g_strconcat(comment_dir, "/", filename_from_path(path), GQVIEW_CACHE_EXT_METADATA, NULL); } g_free(comment_dir); } if (comment_path) { gchar *comment_pathl; if (debug) printf("Saving comment: %s\n", comment_path); comment_pathl = path_from_utf8(comment_path); success = comment_write(comment_pathl, keywords, comment); g_free(comment_pathl); g_free(comment_path); } return success;}gint comment_read(const gchar *path, GList **keywords, gchar **comment){ FILE *f; gchar s_buf[1024]; gchar *key = NULL; GList *list = NULL; GString *comment_build = NULL; f = fopen(path, "r"); if (!f) return FALSE; while (fgets(s_buf,sizeof(s_buf), f)) { if (s_buf[0]=='#') continue; if (s_buf[0]=='[') { gint c = 0; gchar *ptr = s_buf + 1; while(ptr[c] != ']' && ptr[c] != '\n' && ptr[c] != '\0') c++; g_free(key); key = g_strndup(ptr, c); } else if (key) { gint newline = FALSE; gchar *ptr = s_buf; while (*ptr != '\n' && *ptr != '\0') ptr++; if (*ptr == '\n') { *ptr = '\0'; newline = TRUE; } if (strcasecmp(key, "keywords") == 0) { if (strlen(s_buf) > 0) list = g_list_prepend(list, g_strdup(s_buf)); } else if (strcasecmp(key, "comment") == 0) { if (!comment_build) comment_build = g_string_new(""); g_string_append(comment_build, s_buf); if (strlen(s_buf) > 0 && newline) g_string_append_c(comment_build, '\n'); } } } fclose(f); g_free(key); *keywords = g_list_reverse(list); if (comment_build) { if (comment) *comment = g_strdup(comment_build->str); g_string_free(comment_build, TRUE); } return TRUE;}gint comment_cache_read(const gchar *path, GList **keywords, gchar **comment){ gchar *comment_path; gchar *comment_pathl; gint success = FALSE; comment_path = cache_find_location(CACHE_TYPE_METADATA, path); if (!comment_path) return FALSE; comment_pathl = path_from_utf8(comment_path); success = comment_read(comment_pathl, keywords, comment); g_free(comment_pathl); g_free(comment_path); return success;}static gchar *comment_pull(GtkWidget *textview){ GtkTextBuffer *buffer; GtkTextIter start, end; buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview)); gtk_text_buffer_get_bounds(buffer, &start, &end); return gtk_text_buffer_get_text(buffer, &start, &end, FALSE);}GList *keyword_list_pull(GtkWidget *text_widget){ GList *list = NULL; gchar *text; gchar *ptr; if (GTK_IS_TEXT_VIEW(text_widget)) { text = comment_pull(text_widget); } else if (GTK_IS_ENTRY(text_widget)) { text = g_strdup(gtk_entry_get_text(GTK_ENTRY(text_widget))); } else { return NULL; } ptr = text; while (*ptr != '\0') { gchar *begin; gint l = 0; while (*ptr == ' ' || *ptr == ',' || *ptr == '\n' || *ptr == '\r' || *ptr == '\b') ptr++; begin = ptr; if (*ptr != '\0') { while (*ptr != ' ' && *ptr != ',' && *ptr != '\n' && *ptr != '\r' && *ptr != '\b' && *ptr != '\0') { ptr++; l++; } } if (l > 0) list = g_list_append(list, g_strndup(begin, l)); } g_free(text); return list;}void keyword_list_push(GtkWidget *textview, GList *list){ GtkTextBuffer *buffer; GtkTextIter start, end; buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview)); gtk_text_buffer_get_bounds(buffer, &start, &end); gtk_text_buffer_delete (buffer, &start, &end); while (list) { const gchar *word = list->data; GtkTextIter iter; gtk_text_buffer_get_end_iter(buffer, &iter); if (word) gtk_text_buffer_insert(buffer, &iter, word, -1); gtk_text_buffer_get_end_iter(buffer, &iter); gtk_text_buffer_insert(buffer, &iter, "\n", -1); list = list->next; }}static void metadata_set_keywords(const gchar *path, GList *list, gint add){ gchar *comment = NULL; GList *keywords = NULL; GList *save_list = NULL; comment_cache_read(path, &keywords, &comment); if (add) { GList *work; work = list; while (work) { gchar *key; GList *p; key = work->data; work = work->next; p = keywords; while (p && key) { gchar *needle = p->data; p = p->next; if (strcmp(needle, key) == 0) key = NULL; } if (key) keywords = g_list_append(keywords, g_strdup(key)); } save_list = keywords; } else { save_list = list; } comment_cache_write(path, save_list, comment); path_list_free(keywords); g_free(comment);}/* *------------------------------------------------------------------- * keyword list dialog *------------------------------------------------------------------- */#define KEYWORD_DIALOG_WIDTH 200#define KEYWORD_DIALOG_HEIGHT 250typedef struct _KeywordDlg KeywordDlg;struct _KeywordDlg{ GenericDialog *gd; GtkWidget *treeview;};static KeywordDlg *keyword_dialog = NULL;static void keyword_dialog_cancel_cb(GenericDialog *gd, gpointer data){ g_free(keyword_dialog); keyword_dialog = NULL;}static void keyword_dialog_ok_cb(GenericDialog *gd, gpointer data){ KeywordDlg *kd = data; GtkTreeModel *store; GtkTreeIter iter; gint valid; history_list_free_key("keywords"); store = gtk_tree_view_get_model(GTK_TREE_VIEW(kd->treeview)); valid = gtk_tree_model_get_iter_first(store, &iter); while (valid) { gchar *key; gtk_tree_model_get(store, &iter, 0, &key, -1); valid = gtk_tree_model_iter_next(store, &iter); history_list_add_to_key("keywords", key, 0); } keyword_dialog_cancel_cb(gd, data); bar_info_keyword_update_all();}static void keyword_dialog_add_cb(GtkWidget *button, gpointer data){ KeywordDlg *kd = data; GtkTreeSelection *selection; GtkTreeModel *store; GtkTreeIter sibling; GtkTreeIter iter; GtkTreePath *tpath; selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(kd->treeview)); if (gtk_tree_selection_get_selected(selection, &store, &sibling)) { gtk_list_store_insert_before(GTK_LIST_STORE(store), &iter, &sibling); } else { store = gtk_tree_view_get_model(GTK_TREE_VIEW(kd->treeview)); gtk_list_store_append(GTK_LIST_STORE(store), &iter); } gtk_list_store_set(GTK_LIST_STORE(store), &iter, 1, TRUE, -1); tpath = gtk_tree_model_get_path(store, &iter); gtk_tree_view_set_cursor(GTK_TREE_VIEW(kd->treeview), tpath, gtk_tree_view_get_column(GTK_TREE_VIEW(kd->treeview), 0), TRUE); gtk_tree_path_free(tpath);}static void keyword_dialog_remove_cb(GtkWidget *button, gpointer data){ KeywordDlg *kd = data; GtkTreeSelection *selection; GtkTreeModel *store; GtkTreeIter iter; GtkTreeIter next; GtkTreePath *tpath; selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(kd->treeview)); if (!gtk_tree_selection_get_selected(selection, &store, &iter)) return; tpath = NULL; next = iter; if (gtk_tree_model_iter_next(store, &next)) { tpath = gtk_tree_model_get_path(store, &next); } else { tpath = gtk_tree_model_get_path(store, &iter); if (!gtk_tree_path_prev(tpath)) { gtk_tree_path_free(tpath); tpath = NULL; } } if (tpath) { gtk_tree_view_set_cursor(GTK_TREE_VIEW(kd->treeview), tpath, gtk_tree_view_get_column(GTK_TREE_VIEW(kd->treeview), 0), FALSE); gtk_tree_path_free(tpath); } gtk_list_store_remove(GTK_LIST_STORE(store), &iter);}static void keyword_dialog_edit_cb(GtkCellRendererText *renderer, const gchar *path, const gchar *new_text, gpointer data){ KeywordDlg *kd = data; GtkTreeModel *store; GtkTreeIter iter; GtkTreePath *tpath; if (!new_text || strlen(new_text) == 0) return; store = gtk_tree_view_get_model(GTK_TREE_VIEW(kd->treeview)); tpath = gtk_tree_path_new_from_string(path); gtk_tree_model_get_iter(store, &iter, tpath); gtk_tree_path_free(tpath); gtk_list_store_set(GTK_LIST_STORE(store), &iter, 0, new_text, -1);}static void keyword_dialog_populate(KeywordDlg *kd){ GtkListStore *store; GList *list; store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(kd->treeview))); gtk_list_store_clear(store); list = history_list_get_by_key("keywords"); list = g_list_last(list); while (list) { GtkTreeIter iter; gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, 0, list->data, 1, TRUE, -1); list = list->prev; }}static void keyword_dialog_show(void){ GtkWidget *scrolled; GtkListStore *store; GtkTreeViewColumn *column; GtkCellRenderer *renderer; GtkWidget *hbox; GtkWidget *button; if (keyword_dialog) { gtk_window_present(GTK_WINDOW(keyword_dialog->gd->dialog)); return; } keyword_dialog = g_new0(KeywordDlg, 1); keyword_dialog->gd = generic_dialog_new(_("Keyword Presets"), "GQview", "keyword_presets", NULL, TRUE, keyword_dialog_cancel_cb, keyword_dialog); generic_dialog_add_message(keyword_dialog->gd, NULL, _("Favorite keywords list"), NULL); generic_dialog_add_button(keyword_dialog->gd, GTK_STOCK_OK, NULL, keyword_dialog_ok_cb, TRUE); scrolled = gtk_scrolled_window_new(NULL, NULL); gtk_widget_set_size_request(scrolled, KEYWORD_DIALOG_WIDTH, KEYWORD_DIALOG_HEIGHT); 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(keyword_dialog->gd->vbox), scrolled, TRUE, TRUE, 5); gtk_widget_show(scrolled); store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_BOOLEAN); keyword_dialog->treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); g_object_unref(store); gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(keyword_dialog->treeview), FALSE); gtk_tree_view_set_search_column(GTK_TREE_VIEW(keyword_dialog->treeview), 0); gtk_tree_view_set_reorderable(GTK_TREE_VIEW(keyword_dialog->treeview), TRUE); column = gtk_tree_view_column_new(); gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); renderer = gtk_cell_renderer_text_new(); g_signal_connect(G_OBJECT(renderer), "edited", G_CALLBACK(keyword_dialog_edit_cb), keyword_dialog); gtk_tree_view_column_pack_start(column, renderer, TRUE); gtk_tree_view_column_add_attribute(column, renderer, "text", 0); gtk_tree_view_column_add_attribute(column, renderer, "editable", 1); gtk_tree_view_append_column(GTK_TREE_VIEW(keyword_dialog->treeview), column); gtk_container_add(GTK_CONTAINER(scrolled), keyword_dialog->treeview); gtk_widget_show(keyword_dialog->treeview); hbox = gtk_hbox_new(FALSE, 5); gtk_box_pack_start(GTK_BOX(keyword_dialog->gd->vbox), hbox, FALSE, FALSE, 0); gtk_widget_show(hbox); button = gtk_button_new_from_stock(GTK_STOCK_ADD); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(keyword_dialog_add_cb), keyword_dialog); gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); gtk_widget_show(button); button = gtk_button_new_from_stock(GTK_STOCK_REMOVE); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(keyword_dialog_remove_cb), keyword_dialog); gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); gtk_widget_show(button); keyword_dialog_populate(keyword_dialog); gtk_widget_show(keyword_dialog->gd->dialog);}static void bar_keyword_edit_cb(GtkWidget *button, gpointer data){ keyword_dialog_show();}/* *------------------------------------------------------------------- * info bar *------------------------------------------------------------------- */typedef enum { BAR_SORT_COPY, BAR_SORT_MOVE, BAR_SORT_LINK} SortActionType;enum { KEYWORD_COLUMN_TOGGLE = 0, KEYWORD_COLUMN_TEXT};typedef struct _BarInfoData BarInfoData;struct _BarInfoData{ GtkWidget *vbox; GtkWidget *group_box; GtkWidget *label_file_name;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -