//#include #include #include #include #include "window_main.h" #include "walls_ui.h" #include "db.h" #include "browse_model.h" #include "walls_model.h" #include "wallpapers.h" #include "thumbnails.h" struct wallpaper_t *cur_wall = NULL; GdkPixbuf *orig_pixbuf = NULL; gint last_width = 0, last_height = 0, last_pos = 0; GtkImage *image = NULL; GtkWidget *layout = NULL; GtkStatusbar *statusbar; GtkIconView *thumbview; GThread *add_thread = NULL, *thumb_thread = NULL; guint image_context; void on_foldtree_selection_changed(GtkTreeSelection *treeselection, gpointer user_data); inline static void foldtree_create_model(GtkTreeView *foldtree) { GtkTreeModel *tree_model; tree_model = GTK_TREE_MODEL(browse_model_new()); gtk_tree_view_set_model(foldtree, GTK_TREE_MODEL(tree_model)); } inline static void foldtree_init(GtkTreeView *foldtree) { GtkTreeViewColumn *col1; GtkCellRenderer *renderer; GtkTreeSelection *selection; col1 = gtk_tree_view_column_new(); gtk_tree_view_column_set_title(col1, "Name"); gtk_tree_view_append_column(foldtree, col1); renderer = gtk_cell_renderer_text_new(); gtk_tree_view_column_pack_start(col1, renderer, TRUE); gtk_tree_view_column_add_attribute(col1, renderer, "text", 0); foldtree_create_model(foldtree); selection = gtk_tree_view_get_selection(foldtree); g_signal_connect(selection, "changed", G_CALLBACK(on_foldtree_selection_changed), foldtree); } static void resize_pixbuf() { GdkPixbuf *pb; GdkWindow *window; gint win_width, win_height, img_width, img_height, width, height; gdouble scalex, scaley, width_ratio, height_ratio, max_ratio; window = gtk_widget_get_window(layout); gdk_drawable_get_size(window, &win_width, &win_height); gtk_layout_set_size(GTK_LAYOUT(layout), win_width, win_height); img_width = gdk_pixbuf_get_width(orig_pixbuf); img_height = gdk_pixbuf_get_height(orig_pixbuf); /* do we need to resize? */ if(img_width > win_width || img_height > win_height) { /* resize by width */ width_ratio = (gdouble)img_width / (gdouble)win_width; height_ratio = (gdouble)img_height / (gdouble)win_height; if(width_ratio > height_ratio) { width = win_width; height = (gint)(1.0 / width_ratio * img_height); scalex = (gdouble)width / (gdouble)img_width; scaley = (gdouble)height / (gdouble)img_height; } else { /* resize by height */ height = win_height; width = (gint)(1.0 / height_ratio * img_width); scalex = (gdouble)width / (gdouble)img_width; scaley = (gdouble)height / (gdouble)img_height; } pb = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, width, height); gdk_pixbuf_scale(orig_pixbuf, pb, 0, 0, width, height, 0, 0, scalex, scaley, GDK_INTERP_BILINEAR); } else { width = img_width; height = img_height; pb = gdk_pixbuf_copy(orig_pixbuf); } gtk_widget_set_size_request(GTK_WIDGET(image), width, height); gtk_widget_set_uposition(GTK_WIDGET(image), (width < win_width ? win_width / 2 - width / 2 : 0), (height < win_height ? win_height / 2 - height / 2 : 0)); gtk_image_set_from_pixbuf(image, pb); g_object_unref(pb); } void on_window_size_allocate(GtkWidget *widget, GtkAllocation *allocation, gpointer user_data) { if(orig_pixbuf && (allocation->width != last_width || allocation->height != last_height)) { resize_pixbuf(); last_width = allocation->width; last_height = allocation->height; } } void on_window_hpane_resized(GObject *gobject, GParamSpec *pspec, gpointer user_data) { gint pos; pos = gtk_paned_get_position(GTK_PANED(gobject)); if(orig_pixbuf && pos != last_pos) { resize_pixbuf(); last_pos = pos; } } static void load_pixbuf(const gchar *filepath) { GdkPixbuf *pb; GError *error = NULL; GdkWindow *window; sqlite_uint64 wallid; struct wallpaper_t *wall; gchar *msg, *base; if(orig_pixbuf) g_object_unref(orig_pixbuf); orig_pixbuf = gdk_pixbuf_new_from_file(filepath, &error); if(!orig_pixbuf) { g_warning("%s", error->message); g_free(error); return; } if(cur_wall) { g_free(cur_wall->filepath); g_free(cur_wall); cur_wall = NULL; } wallid = db_get_wallpaper(filepath); if(wallid) { wall = g_malloc(sizeof(struct wallpaper_t)); if(db_get_wallpaper_data(wallid, wall)) { cur_wall = wall; } else { g_free(wall->filepath); g_free(wall); } } if(cur_wall) { base = g_path_get_basename(cur_wall->filepath); msg = g_strdup_printf("%s: %dx%d", base, cur_wall->width, cur_wall->height); gtk_statusbar_push(statusbar, image_context, msg); g_free(base); g_free(msg); } resize_pixbuf(); } static void fill_wall_list(GtkListStore *liststore, GArray *array) { GtkTreeIter iter; for(int i = 0; i < array->len; i++) { struct wallpaper_t *wall; wall = &g_array_index(array, struct wallpaper_t, i); gtk_list_store_append(liststore, &iter); gtk_list_store_set(liststore, &iter, 0, NULL, 1, wall->filepath, -1); g_free(wall->filepath); } g_array_free(array, TRUE); } void on_foldtree_selection_changed(GtkTreeSelection *treeselection, gpointer user_data) { GtkTreeModel *model; GtkTreeIter iter; struct directory_t *dir; GArray *array; GtkListStore *liststore; GError *error = NULL; if(gtk_tree_selection_get_selected(treeselection, &model, &iter)) { browse_model_get_dir_record(model, &iter, &dir); if(!db_get_wallpapers(dir->dirid, &array)) return; liststore = gtk_list_store_new(2, GDK_TYPE_PIXBUF, G_TYPE_STRING); fill_wall_list(liststore, array); gtk_icon_view_set_model(thumbview, GTK_TREE_MODEL(liststore)); thumb_thread = g_thread_create(add_thumbs_thread, liststore, FALSE, &error); if(!thumb_thread) { g_warning("%s", error->message); g_free(error); } } } void on_thumbview_selection_changed(GtkIconView *iconview, gpointer user_data) { GList *list; GValue value; const gchar *filename; GtkTreePath *path; GtkTreeModel *model; GtkTreeIter iter; list = gtk_icon_view_get_selected_items(iconview); if(list) { if(g_list_length(list) == 1) { path = g_list_nth_data(list, 0); model = gtk_icon_view_get_model(iconview); gtk_tree_model_get_iter(model, &iter, path); memset(&value, 0, sizeof(GValue)); gtk_tree_model_get_value(model, &iter, 1, &value); filename = g_value_get_string(&value); load_pixbuf(filename); g_value_unset(&value); } g_list_foreach(list, gtk_tree_path_free, NULL); g_list_free(list); } } gpointer add_dir_thread(gpointer data) { gchar *directory; directory = (gchar*)data; add_dir_recursive(directory, 0, statusbar); g_free(directory); return NULL; } void on_add_dir_action_activate(GtkAction *action, gpointer user_data) { GtkWidget *dialog; GError *error; if(add_thread) return; dialog = gtk_file_chooser_dialog_new("Choose Directory", NULL, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { char *directory; directory = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); add_thread = g_thread_create(add_dir_thread, strdup(directory), FALSE, &error); if(!add_thread) { g_warning("%s", error->message); g_free(error); } } gtk_widget_destroy(dialog); } int gui_main(int argc, char **argv) { GtkWidget *window; GtkWidget *foldtree; GtkWidget *window_hpane; GtkBuilder *builder ; GError *error = NULL; GdkColor color; g_thread_init(NULL); gdk_threads_init(); if(!db_open()) return 1; gtk_init(&argc, &argv); builder = gtk_builder_new(); if(!gtk_builder_add_from_string(builder, ui_string, -1, &error)) { g_warning("%s", error->message); g_free(error); return 1; } window = GTK_WIDGET(gtk_builder_get_object(builder, "window")); gtk_window_set_title(GTK_WINDOW(window), "walls"); foldtree = GTK_WIDGET(gtk_builder_get_object(builder, "foldtree")); foldtree_init(GTK_TREE_VIEW(foldtree)); thumbview = GTK_ICON_VIEW(gtk_builder_get_object(builder, "thumbview")); gtk_icon_view_set_pixbuf_column(thumbview, 0); image = GTK_IMAGE(gtk_builder_get_object(builder, "image")); layout = GTK_WIDGET(gtk_builder_get_object(builder, "layout")); if(gdk_color_parse("#000", &color)) gtk_widget_modify_bg(GTK_WIDGET(layout), GTK_STATE_NORMAL, &color); window_hpane = GTK_WIDGET(gtk_builder_get_object(builder, "window_hpane")); g_signal_connect(window_hpane, "notify::position", G_CALLBACK(on_window_hpane_resized), window_hpane); statusbar = GTK_STATUSBAR(gtk_builder_get_object(builder, "statusbar")); image_context = gtk_statusbar_get_context_id(GTK_STATUSBAR(statusbar), "Image display"); gtk_builder_connect_signals(builder, NULL); g_object_unref(G_OBJECT(builder)); gtk_widget_show_all(window); gtk_main(); db_close(); return 0; }