# HG changeset patch # User Gabriel Schulhof # Date 1180471562 0 # Node ID af5f8bdc0babf8b2e124088ddb390e22dfa0d2e0 # Parent 1a1d9cf5cd79aa4835510607d0078d3b2c537bc4# Parent 3223413a9c809a6898b12879ebaac8c771e040c4 propagate from branch 'im.pidgin.pidgin' (head 61738e60f23bfd0eec3701fb8c7c28f263bc04ed) to branch 'org.maemo.garage.pidgin.smiley-install' (head a6dab6460ee13870320775495613164974a3be24) diff -r 1a1d9cf5cd79 -r af5f8bdc0bab pidgin/gtkprefs.c --- a/pidgin/gtkprefs.c Tue May 29 18:03:01 2007 +0000 +++ b/pidgin/gtkprefs.c Tue May 29 20:46:02 2007 +0000 @@ -60,6 +60,7 @@ static GtkWidget *sound_entry = NULL; static GtkListStore *smiley_theme_store = NULL; +static GtkWidget *smiley_theme_tree_view = NULL; static GtkWidget *prefs_proxy_frame = NULL; static GtkWidget *prefs = NULL; @@ -366,6 +367,7 @@ GValue val; GtkTreePath *path, *oldpath; struct smiley_theme *new_theme, *old_theme; + GtkWidget *remove_button = g_object_get_data(G_OBJECT(sel), "remove_button"); if (!gtk_tree_selection_get_selected(sel, &model, &iter)) return; @@ -375,6 +377,14 @@ gtk_tree_model_get_value(model, &iter, 3, &val); path = gtk_tree_model_get_path(model, &iter); themename = g_value_get_string(&val); + + /* + * Disallow removal of the "none" theme - note that there's a double check, so even if + * the button is not disabled here, the "none" theme still won't be removed when its clicked. + */ + if (remove_button) + gtk_widget_set_sensitive(remove_button, strcmp(themename, "none")); + purple_prefs_set_string(PIDGIN_PREFS_ROOT "/smileys/theme", themename); g_value_unset (&val); @@ -513,9 +523,23 @@ #endif g_free(destdir); - theme_rowref = theme_refresh_theme_list(); - if (theme_rowref != NULL) + if ((theme_rowref = theme_refresh_theme_list()) != NULL) { + GtkTreeIter itr; + GtkTreeModel *tm; + GtkTreePath *tp = NULL; + GtkTreeSelection *sel = NULL; + + if ((sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(smiley_theme_tree_view))) != NULL) { + if ((tm = gtk_tree_row_reference_get_model(theme_rowref)) != NULL) { + if ((tp = gtk_tree_row_reference_get_path(theme_rowref)) != NULL) { + if (gtk_tree_model_get_iter(tm, &itr, tp)) + gtk_tree_selection_select_iter(sel, &itr); + gtk_tree_path_free(tp); + } + } + } gtk_tree_row_reference_free(theme_rowref); + } } static void @@ -619,12 +643,90 @@ return ret; } +static void request_theme_file_name_cb (gpointer data, char *theme_file_name) +{ + theme_install_theme (theme_file_name, NULL) ; +} + +static void +add_theme_button_clicked_cb(GtkWidget *button, gpointer null) +{ + purple_request_file (NULL, _("Install Theme"), NULL, FALSE, (GCallback)request_theme_file_name_cb, NULL, NULL, NULL, NULL, NULL) ; +} + +static void +remove_theme_button_clicked_cb(GtkWidget *button, GtkTreeView *tree_view) +{ + static GtkTreeModel *tm = NULL; + static GtkTreeSelection *sel = NULL; + static GtkTreeIter itr; + static char *theme_path = NULL, *theme_name = NULL, *slash_before_filename = NULL; + + if ((tm = gtk_tree_view_get_model(tree_view)) == NULL) return; + if ((sel = gtk_tree_view_get_selection(tree_view)) == NULL) return; + if (!gtk_tree_selection_get_selected(sel, NULL, &itr)) return; + + gtk_tree_model_get(tm, &itr, 2, &theme_path, 3, &theme_name, -1); + + if (theme_name) { + if (strcmp(theme_name, "none")) { + if(theme_path) { + if ((slash_before_filename = g_strrstr(theme_path, G_DIR_SEPARATOR_S)) != NULL) { + GtkTreeRowReference *theme_rowref; + char *dir_file = NULL; + GDir *theme_dir = NULL; + + *slash_before_filename = 0; + if ((theme_dir = g_dir_open(theme_path, 0, NULL)) != NULL) { + while((dir_file = (char *)g_dir_read_name(theme_dir)) != NULL) { + if ((dir_file = g_strdup_printf ("%s%s%s", theme_path, G_DIR_SEPARATOR_S, dir_file)) != NULL) { + g_unlink(dir_file); + g_free(dir_file); + } + } + + g_dir_close(theme_dir); + g_rmdir(theme_path); + + /* + * Currently theme_refresh_theme_list() is rigged to remove all smiley themes which have disappeared from disk. + * This is fine, but for the next minor version we should add a + * pidgin_themes_remove_smiley_theme(struct smiley_theme *theme) to gtkthemes.[ch] which will remove an + * individual theme from the list. + */ + if (previous_smiley_row) + gtk_tree_row_reference_free(previous_smiley_row); + previous_smiley_row = NULL; + if ((theme_rowref = theme_refresh_theme_list()) != NULL) { + GtkTreePath *tp = NULL; + + if ((tp = gtk_tree_row_reference_get_path(theme_rowref)) != NULL) { + if (gtk_tree_model_get_iter(tm, &itr, tp)) + gtk_tree_selection_select_iter(sel, &itr); + gtk_tree_path_free(tp); + } + gtk_tree_row_reference_free(theme_rowref); + } + + } + } + } + } + } + + g_free(theme_name); + g_free(theme_path); +} + static GtkWidget * theme_page() { + GtkWidget *hbox_buttons; + GtkWidget *alignment; GtkWidget *ret; GtkWidget *sw; GtkWidget *view; + GtkWidget *add_button, *remove_button; GtkCellRenderer *rend; GtkTreeViewColumn *col; GtkTreeSelection *sel; @@ -653,7 +755,7 @@ rowref = theme_refresh_theme_list(); - view = gtk_tree_view_new_with_model (GTK_TREE_MODEL(smiley_theme_store)); + view = smiley_theme_tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL(smiley_theme_store)); gtk_drag_dest_set(view, GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT | GTK_DEST_DEFAULT_DROP, te, sizeof(te) / sizeof(GtkTargetEntry) , GDK_ACTION_COPY | GDK_ACTION_MOVE); @@ -694,10 +796,33 @@ gtk_tree_path_free(path); } + alignment = gtk_alignment_new(1.0, 0.5, 0.0, 1.0); + gtk_widget_show(alignment); + gtk_box_pack_start(GTK_BOX(ret), alignment, FALSE, TRUE, 0); + + hbox_buttons = gtk_hbox_new(TRUE, PIDGIN_HIG_CAT_SPACE); + gtk_widget_show(hbox_buttons); + gtk_container_add(GTK_CONTAINER(alignment), hbox_buttons); + + add_button = gtk_button_new_from_stock(GTK_STOCK_ADD); + gtk_widget_show(add_button); + gtk_box_pack_start(GTK_BOX(hbox_buttons), add_button, FALSE, TRUE, 0); + g_signal_connect(G_OBJECT(add_button), "clicked", (GCallback)add_theme_button_clicked_cb, NULL); + + remove_button = gtk_button_new_from_stock(GTK_STOCK_REMOVE); + gtk_widget_show(remove_button); + gtk_box_pack_start(GTK_BOX(hbox_buttons), remove_button, FALSE, TRUE, 0); + g_signal_connect(G_OBJECT(remove_button), "clicked", (GCallback)remove_theme_button_clicked_cb, view); + + g_object_set_data(G_OBJECT(sel), "remove_button", remove_button); + gtk_widget_show_all(ret); pidgin_set_accessible_label (view, label); + /* Handle initial selection */ + smiley_sel(sel, GTK_TREE_MODEL(smiley_theme_store)); + return ret; } diff -r 1a1d9cf5cd79 -r af5f8bdc0bab pidgin/gtkthemes.c --- a/pidgin/gtkthemes.c Tue May 29 18:03:01 2007 +0000 +++ b/pidgin/gtkthemes.c Tue May 29 20:46:02 2007 +0000 @@ -92,6 +92,42 @@ g_hash_table_destroy(already_freed); } +static void smiley_theme_free(struct smiley_theme *theme) +{ + pidgin_themes_destroy_smiley_theme(theme); + + g_free(theme->name); + g_free(theme->desc); + g_free(theme->author); + g_free(theme->icon); + g_free(theme->path); + g_free(theme); +} + +static void +pidgin_smiley_themes_remove_non_existing() +{ + static struct smiley_theme *theme = NULL; + GSList *iter = NULL; + + if (!smiley_themes) return ; + + for (iter = smiley_themes ; iter ; iter = iter->next) { + theme = ((struct smiley_theme *)(iter->data)); + if (!g_file_test(theme->path, G_FILE_TEST_EXISTS)) { + if (theme == current_smiley_theme) + current_smiley_theme = ((struct smiley_theme *)(NULL == iter->next ? NULL : iter->next->data)); + smiley_theme_free(theme); + iter->data = NULL; + } + } + /* Remove all elements whose data is NULL */ + smiley_themes = g_slist_remove_all(smiley_themes, NULL); + + if (!current_smiley_theme && smiley_themes) + current_smiley_theme = ((struct smiley_theme *)(g_slist_last(smiley_themes)->data)); +} + void pidgin_themes_load_smiley_theme(const char *file, gboolean load) { FILE *f = g_fopen(file, "r"); @@ -215,14 +251,7 @@ if (!theme->name || !theme->desc || !theme->author) { purple_debug_error("gtkthemes", "Invalid file format, not loading smiley theme from '%s'\n", file); - pidgin_themes_destroy_smiley_theme(theme); - - g_free(theme->name); - g_free(theme->desc); - g_free(theme->author); - g_free(theme->icon); - g_free(theme->path); - g_free(theme); + smiley_theme_free(theme); return; } @@ -253,10 +282,12 @@ { GDir *dir; const gchar *file; - gchar *path; + gchar *path, *test_path; int l; + char* probedirs[3]; - char* probedirs[3]; + pidgin_smiley_themes_remove_non_existing(); + probedirs[0] = g_build_filename(DATADIR, "pixmaps", "pidgin", "emotes", NULL); probedirs[1] = g_build_filename(purple_user_dir(), "smileys", NULL); probedirs[2] = 0; @@ -264,14 +295,20 @@ dir = g_dir_open(probedirs[l], 0, NULL); if (dir) { while ((file = g_dir_read_name(dir))) { - path = g_build_filename(probedirs[l], file, "theme", NULL); + test_path = g_build_filename(probedirs[l], file, NULL); + if (g_file_test(test_path, G_FILE_TEST_IS_DIR)) { + path = g_build_filename(probedirs[l], file, "theme", NULL); - /* Here we check to see that the theme has proper syntax. - * We set the second argument to FALSE so that it doesn't load - * the theme yet. - */ - pidgin_themes_load_smiley_theme(path, FALSE); - g_free(path); + /* Here we check to see that the theme has proper syntax. + * We set the second argument to FALSE so that it doesn't load + * the theme yet. + * + * Not quite ... we need to re-load the themes to enable theme removal + */ + pidgin_themes_load_smiley_theme(path, FALSE); + g_free(path); + } + g_free(test_path); } g_dir_close(dir); } else if (l == 1) { @@ -279,6 +316,9 @@ } g_free(probedirs[l]); } + + if (!current_smiley_theme && smiley_themes) + current_smiley_theme = ((struct smiley_theme *)(smiley_themes->data)); } GSList *pidgin_themes_get_proto_smileys(const char *id) {