--- a/ChangeLog.API Fri May 27 14:52:34 2022 -0500
+++ b/ChangeLog.API Mon May 30 21:04:47 2022 -0500
@@ -1013,6 +1013,12 @@
* pidgin_status_box_pulse_connecting
* pidgin_status_box_set_buddy_icon
* pidgin_status_box_set_network_available
+ * pidgin_status_editor_show, use pidgin_status_editor_new instead. + * pidgin_status_get_handle + * pidgin_status_window_hide + * pidgin_status_window_show, use pidgin_status_manager_new instead. * All PIDGIN_STOCK_* macros
* PIDGIN_IS_STOCK_ICON_THEME
* PIDGIN_IS_STOCK_ICON_THEME_CLASS
--- a/pidgin/gtksavedstatuses.c Fri May 27 14:52:34 2022 -0500
+++ b/pidgin/gtksavedstatuses.c Mon May 30 21:04:47 2022 -0500
@@ -21,1447 +21,13 @@
#include <glib/gi18n-lib.h>
#include "gtksavedstatuses.h"
-#include "pidgindialog.h"
#include "pidginiconname.h"
-#include "pidginstatusprimitivechooser.h"
-#include "pidginstatusprimitivestore.h"
- * TODO: Should attach to the account-deleted and account-added signals
- * and update the GtkListStores in any StatusEditor windows that
- * These are used for the GtkTreeView when you're scrolling through
- * all your saved statuses.
- STATUS_WINDOW_COLUMN_TITLE,
- STATUS_WINDOW_COLUMN_TYPE,
- STATUS_WINDOW_COLUMN_MESSAGE,
- /** A hidden column containing a pointer to the editor for this saved status. */
- STATUS_WINDOW_COLUMN_WINDOW,
- STATUS_WINDOW_COLUMN_ICON,
- STATUS_WINDOW_NUM_COLUMNS
- STATUS_RESPONSE_USE = 1,
- STATUS_RESPONSE_MODIFY,
- STATUS_RESPONSE_DELETE,
- STATUS_RESPONSE_SAVE_AND_USE,
- * These are used for the GtkTreeView containing the list of accounts
- * at the bottom of the window when you're editing a particular
- /* A hidden column containing a pointer to the PurpleAccount. */
- STATUS_EDITOR_COLUMN_ACCOUNT,
- /* A hidden column containing a pointer to the editor for this substatus. */
- STATUS_EDITOR_COLUMN_WINDOW,
- STATUS_EDITOR_COLUMN_ENABLE_SUBSTATUS,
- STATUS_EDITOR_COLUMN_ICON,
- STATUS_EDITOR_COLUMN_USERNAME,
- /* A hidden column containing the ID of this PurpleStatusType. */
- STATUS_EDITOR_COLUMN_STATUS_ID,
- STATUS_EDITOR_COLUMN_STATUS_NAME,
- STATUS_EDITOR_COLUMN_STATUS_MESSAGE,
- STATUS_EDITOR_COLUMN_STATUS_ICON,
- STATUS_EDITOR_NUM_COLUMNS
- * These are used in the GtkComboBox to select the specific PurpleStatusType
- * when setting a (sub)status for a particular saved status.
- /** A hidden column containing the ID of this PurpleStatusType. */
- STATUS_COLUMN_STATUS_ID,
- STATUS_COLUMN_STATUS_NAME,
- GtkWidget *modify_button;
- GtkWidget *delete_button;
- GtkWidget *saveanduse_button;
- GtkWidget *save_button;
- GtkWidget *message_view;
- GtkTextBuffer *message_buffer;
- StatusEditor *status_editor;
- PurpleAccount *account;
- GtkWidget *message_view;
- GtkTextBuffer *message_buffer;
-static StatusWindow *status_window = NULL;
-/**************************************************************************
-**************************************************************************/
-status_window_find_savedstatus(GtkTreeIter *iter, const char *title)
- if ((status_window == NULL) || (title == NULL))
- model = GTK_TREE_MODEL(status_window->model);
- if (!gtk_tree_model_get_iter_first(model, iter))
- gtk_tree_model_get(model, iter, STATUS_WINDOW_COLUMN_TITLE, &cur, -1);
- if (purple_strequal(title, cur))
- } while (gtk_tree_model_iter_next(model, iter));
-status_window_destroy_cb(GtkWidget *widget, GdkEvent *event, gpointer user_data)
- StatusWindow *dialog = user_data;
- pidgin_status_window_hide();
-status_window_use(StatusWindow *dialog)
- GtkTreeSelection *selection;
- selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog->treeview));
- num_selected = gtk_tree_selection_count_selected_rows(selection);
- * This shouldn't happen because the "Use" button should have
- * been grayed out. Oh well.
- list = gtk_tree_selection_get_selected_rows(selection, NULL);
- if (gtk_tree_model_get_iter(GTK_TREE_MODEL(dialog->model),
- PurpleSavedStatus *saved_status;
- gtk_tree_model_get(GTK_TREE_MODEL(dialog->model), &iter,
- STATUS_WINDOW_COLUMN_TITLE, &title,
- saved_status = purple_savedstatus_find(title);
- purple_savedstatus_activate(saved_status);
- g_list_free_full(list, (GDestroyNotify)gtk_tree_path_free);
-status_window_modify_foreach(GtkTreeModel *model, GtkTreePath *path,
- GtkTreeIter *iter, gpointer user_data)
- PurpleSavedStatus *saved_status;
- gtk_tree_model_get(model, iter, STATUS_WINDOW_COLUMN_TITLE, &title, -1);
- saved_status = purple_savedstatus_find(title);
- pidgin_status_editor_show(TRUE, saved_status);
-status_window_modify(StatusWindow *dialog) {
- GtkTreeSelection *selection;
- selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog->treeview));
- gtk_tree_selection_selected_foreach(selection,
- status_window_modify_foreach, NULL);
-status_window_delete_cancel_cb(gpointer data)
- GList *sel_titles = data;
- g_list_free_full(sel_titles, g_free);
-status_window_delete_confirm_cb(gpointer data)
- GList *sel_titles = data, *l;
- for (l = sel_titles; l != NULL; l = l->next) {
- if (purple_savedstatus_find(title) != purple_savedstatus_get_current()) {
- if (status_window_find_savedstatus(&iter, title))
- gtk_list_store_remove(status_window->model, &iter);
- purple_savedstatus_delete(title);
- g_list_free(sel_titles);
-status_window_delete(StatusWindow *dialog) {
- GtkTreeSelection *selection;
- GList *sel_paths, *l, *sel_titles = NULL;
- GtkTreeModel *model = GTK_TREE_MODEL(dialog->model);
- selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog->treeview));
- sel_paths = gtk_tree_selection_get_selected_rows(selection, NULL);
- /* This is ugly because we're not allowed to modify the model from within
- * gtk_tree_selection_selected_foreach() and the GtkTreePaths can become invalid
- * when something is removed from the model. The selection can also change while
- * the request dialog is displayed, so we need to capture the selected rows at this time. */
- for (l = sel_paths; l != NULL; l = l->next) {
- if (gtk_tree_model_get_iter(model, &iter, l->data)) {
- gtk_tree_model_get(model, &iter, STATUS_WINDOW_COLUMN_TITLE, &title, -1);
- sel_titles = g_list_prepend(sel_titles, title);
- gtk_tree_path_free(l->data);
- g_list_free(sel_paths);
- g_return_if_fail(sel_titles != NULL);
- if (!sel_titles->next) {
- title = g_strdup_printf(_("Are you sure you want to delete %s?"),
- (const gchar *)sel_titles->data);
- handle = purple_savedstatus_find(sel_titles->data);
- title = g_strdup(_("Are you sure you want to delete the selected saved statuses?"));
- purple_request_action(handle, NULL, title, NULL, 0,
- _("Delete"), status_window_delete_confirm_cb,
- _("Cancel"), status_window_delete_cancel_cb);
-status_selected_cb(GtkTreeSelection *sel, gpointer user_data)
- StatusWindow *dialog = user_data;
- GList *sel_paths, *tmp;
- gboolean can_use = TRUE, can_delete = TRUE;
- GtkTreeModel *model = GTK_TREE_MODEL(dialog->model);
- sel_paths = gtk_tree_selection_get_selected_rows(sel, NULL);
- for (tmp = sel_paths, num_selected = 0; tmp; tmp = tmp->next, num_selected++) {
- if (gtk_tree_model_get_iter(model, &iter, tmp->data)) {
- gtk_tree_model_get(model, &iter,
- STATUS_WINDOW_COLUMN_TITLE, &title, -1);
- if (purple_savedstatus_find(title) == purple_savedstatus_get_current()) {
- can_use = can_delete = FALSE;
- gtk_tree_path_free(tmp->data);
- gtk_widget_set_sensitive(dialog->use_button, (num_selected == 1) && can_use);
- gtk_widget_set_sensitive(dialog->modify_button, (num_selected > 0));
- gtk_widget_set_sensitive(dialog->delete_button, num_selected > 0 && can_delete);
- g_list_free(sel_paths);
-add_status_to_saved_status_list(GtkListStore *model, PurpleSavedStatus *saved_status)
- if (purple_savedstatus_is_transient(saved_status))
- title = purple_savedstatus_get_title(saved_status);
- type = purple_primitive_get_name_from_type(purple_savedstatus_get_primitive_type(saved_status));
- message = purple_markup_strip_html(purple_savedstatus_get_message(saved_status));
- icon = pidgin_icon_name_from_status_primitive(purple_savedstatus_get_primitive_type(saved_status), NULL);
- gtk_list_store_append(model, &iter);
- gtk_list_store_set(model, &iter,
- STATUS_WINDOW_COLUMN_ICON, icon,
- STATUS_WINDOW_COLUMN_TITLE, title,
- STATUS_WINDOW_COLUMN_TYPE, type,
- STATUS_WINDOW_COLUMN_MESSAGE, message,
-populate_saved_status_list(StatusWindow *dialog)
- gtk_list_store_clear(dialog->model);
- for (saved_statuses = purple_savedstatuses_get_all(); saved_statuses != NULL;
- saved_statuses = g_list_next(saved_statuses))
- add_status_to_saved_status_list(dialog->model, saved_statuses->data);
-search_func(GtkTreeModel *model, gint column, const gchar *key, GtkTreeIter *iter, gpointer search_data)
- gtk_tree_model_get(model, iter, column, &haystack, -1);
- result = (purple_strcasestr(haystack, key) == NULL);
-savedstatus_activated_cb(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColumn *column, StatusWindow *dialog)
- status_window_use(dialog);
- pidgin_status_window_hide();
-saved_status_updated_cb(PurpleSavedStatus *status, StatusWindow *sw)
- populate_saved_status_list(sw);
-create_saved_status_list(StatusWindow *dialog)
- GtkTreeViewColumn *column;
- GtkCellRenderer *renderer;
- /* Create the list model */
- dialog->model = gtk_list_store_new(STATUS_WINDOW_NUM_COLUMNS,
- /* Create the treeview */
- treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(dialog->model));
- dialog->treeview = treeview;
- g_signal_connect(G_OBJECT(treeview), "row-activated",
- G_CALLBACK(savedstatus_activated_cb), dialog);
- sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
- gtk_tree_selection_set_mode(sel, GTK_SELECTION_MULTIPLE);
- g_signal_connect(G_OBJECT(sel), "changed",
- G_CALLBACK(status_selected_cb), dialog);
- column = gtk_tree_view_column_new();
- gtk_tree_view_column_set_title(column, _("Title"));
- gtk_tree_view_column_set_resizable(column, TRUE);
- gtk_tree_view_column_set_min_width(column, 100);
- gtk_tree_view_column_set_sort_column_id(column,
- STATUS_WINDOW_COLUMN_TITLE);
- gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
- renderer = gtk_cell_renderer_text_new();
- gtk_tree_view_column_pack_start(column, renderer, TRUE);
- gtk_tree_view_column_add_attribute(column, renderer, "text",
- STATUS_WINDOW_COLUMN_TITLE);
- g_object_set(renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
- column = gtk_tree_view_column_new();
- gtk_tree_view_column_set_title(column, _("Type"));
- gtk_tree_view_column_set_resizable(column, TRUE);
- gtk_tree_view_column_set_sort_column_id(column,
- STATUS_WINDOW_COLUMN_TYPE);
- gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
- renderer = gtk_cell_renderer_pixbuf_new();
- gtk_tree_view_column_pack_start(column, renderer, TRUE);
- gtk_tree_view_column_add_attribute(column, renderer, "icon-name",
- STATUS_WINDOW_COLUMN_ICON);
- renderer = gtk_cell_renderer_text_new();
- gtk_tree_view_column_pack_start(column, renderer, TRUE);
- gtk_tree_view_column_add_attribute(column, renderer, "text",
- STATUS_WINDOW_COLUMN_TYPE);
- column = gtk_tree_view_column_new();
- gtk_tree_view_column_set_title(column, _("Message"));
- gtk_tree_view_column_set_resizable(column, TRUE);
- gtk_tree_view_column_set_sort_column_id(column,
- STATUS_WINDOW_COLUMN_MESSAGE);
- gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
- renderer = gtk_cell_renderer_text_new();
- gtk_tree_view_column_pack_start(column, renderer, TRUE);
- gtk_tree_view_column_add_attribute(column, renderer, "text",
- STATUS_WINDOW_COLUMN_MESSAGE);
- g_object_set(renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
- /* Enable CTRL+F searching */
- gtk_tree_view_set_search_column(GTK_TREE_VIEW(treeview), STATUS_WINDOW_COLUMN_TITLE);
- gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(treeview), search_func, NULL, NULL);
- /* Sort the title column by default */
- gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(dialog->model),
- STATUS_WINDOW_COLUMN_TITLE,
- populate_saved_status_list(dialog);
- gtk_widget_show_all(treeview);
- return pidgin_make_scrollable(treeview, GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS, GTK_SHADOW_IN, -1, -1);
-response_cb(GtkDialog *dialog, gint response_id, gpointer data) {
- StatusWindow *window = data;
- case STATUS_RESPONSE_USE:
- status_window_use(window);
- case STATUS_RESPONSE_ADD:
- pidgin_status_editor_show(FALSE, NULL);
- case STATUS_RESPONSE_MODIFY:
- status_window_modify(window);
- case STATUS_RESPONSE_DELETE:
- status_window_delete(window);
- case GTK_RESPONSE_CLOSE:
- pidgin_status_window_hide();
-current_status_changed(PurpleSavedStatus *old, PurpleSavedStatus *new_status,
- status_selected_cb(gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog->treeview)), dialog);
-pidgin_status_window_show(void)
- if (status_window != NULL)
- gtk_window_present(GTK_WINDOW(status_window->window));
- status_window = dialog = g_new0(StatusWindow, 1);
- dialog->window = win = pidgin_dialog_new(_("Saved Statuses"), 12, "statuses", TRUE);
- gtk_window_set_default_size(GTK_WINDOW(win), 550, 250);
- g_signal_connect(win, "delete_event", G_CALLBACK(status_window_destroy_cb),
- g_signal_connect(win, "response", G_CALLBACK(response_cb), dialog);
- vbox = gtk_dialog_get_content_area(GTK_DIALOG(win));
- gtk_box_set_spacing(GTK_BOX(vbox), 12);
- /* List of saved status states */
- list = create_saved_status_list(dialog);
- gtk_box_pack_start(GTK_BOX(vbox), list, TRUE, TRUE, 0);
- dialog->use_button = gtk_dialog_add_button(GTK_DIALOG(win), _("_Use"),
- gtk_widget_set_sensitive(dialog->use_button, FALSE);
- gtk_dialog_add_button(GTK_DIALOG(win), _("_Add"), STATUS_RESPONSE_ADD);
- dialog->modify_button = gtk_dialog_add_button(GTK_DIALOG(win),
- STATUS_RESPONSE_MODIFY);
- gtk_widget_set_sensitive(dialog->modify_button, FALSE);
- dialog->delete_button = gtk_dialog_add_button(GTK_DIALOG(win), _("Delete"),
- STATUS_RESPONSE_DELETE);
- gtk_widget_set_sensitive(dialog->delete_button, FALSE);
- gtk_dialog_add_button(GTK_DIALOG(win), _("Close"), GTK_RESPONSE_CLOSE);
- purple_signal_connect(purple_savedstatuses_get_handle(),
- "savedstatus-changed", status_window,
- G_CALLBACK(current_status_changed), dialog);
- purple_signal_connect(purple_savedstatuses_get_handle(),
- "savedstatus-added", status_window,
- G_CALLBACK(saved_status_updated_cb), dialog);
- purple_signal_connect(purple_savedstatuses_get_handle(),
- "savedstatus-deleted", status_window,
- G_CALLBACK(saved_status_updated_cb), dialog);
- purple_signal_connect(purple_savedstatuses_get_handle(),
- "savedstatus-modified", status_window,
- G_CALLBACK(saved_status_updated_cb), dialog);
- gtk_widget_show_all(win);
-pidgin_status_window_hide(void)
- if (status_window == NULL)
- if (status_window->window != NULL)
- gtk_widget_destroy(status_window->window);
- purple_request_close_with_handle(status_window);
- purple_notify_close_with_handle(status_window);
- purple_signals_disconnect_by_handle(status_window);
- g_object_unref(G_OBJECT(status_window->model));
-/**************************************************************************
-**************************************************************************/
-static void substatus_editor_cancel(SubStatusEditor *dialog);
-status_editor_remove_dialog(StatusEditor *dialog)
- /* Remove the reference to this dialog from our parent's list store */
- if (status_window_find_savedstatus(&iter, dialog->original_title))
- gtk_list_store_set(status_window->model, &iter,
- STATUS_WINDOW_COLUMN_WINDOW, NULL,
- /* Close any substatus editors that may be open */
- model = GTK_TREE_MODEL(dialog->model);
- if (gtk_tree_model_get_iter_first(model, &iter))
- SubStatusEditor *substatus_dialog;
- gtk_tree_model_get(model, &iter,
- STATUS_EDITOR_COLUMN_WINDOW, &substatus_dialog,
- if (substatus_dialog != NULL)
- gtk_list_store_set(dialog->model, &iter,
- STATUS_EDITOR_COLUMN_WINDOW, NULL,
- substatus_editor_cancel(substatus_dialog);
- } while (gtk_tree_model_iter_next(model, &iter));
-status_editor_destroy_cb(GtkWidget *widget, gpointer user_data)
- StatusEditor *dialog = user_data;
- status_editor_remove_dialog(dialog);
- g_free(dialog->original_title);
- g_object_unref(G_OBJECT(dialog->model));
-status_editor_ok(StatusEditor *dialog, gboolean use, gboolean save) {
- PurpleStatusPrimitive type;
- char *message, *unformatted;
- PurpleSavedStatus *saved_status = NULL;
- title = gtk_entry_get_text(dialog->title);
- * If we're saving this status, and the title is already taken
- * then show an error dialog and don't do anything.
- if ((save) && (purple_savedstatus_find(title) != NULL) &&
- ((dialog->original_title == NULL) || (!purple_strequal(title, dialog->original_title))))
- purple_notify_error(status_window, NULL, _("Title already in use. You must "
- "choose a unique title."), NULL, NULL);
- type = gtk_combo_box_get_active(dialog->type) + (PURPLE_STATUS_UNSET + 1);
- message = talkatu_markup_get_html(dialog->message_buffer, NULL);
- unformatted = purple_markup_strip_html(message);
- * If we're editing an old status, then lookup the old status.
- * Note: It is possible that it has been deleted or renamed
- * or something, and no longer exists.
- if (dialog->original_title != NULL)
- saved_status = purple_savedstatus_find(dialog->original_title);
- if (status_window_find_savedstatus(&iter, dialog->original_title))
- gtk_list_store_remove(status_window->model, &iter);
- if(saved_status == NULL) {
- /* This is a new status */
- saved_status = purple_savedstatus_new(title, type);
- saved_status = purple_savedstatus_new(NULL, type);
- /* Modify the old status */
- if(!purple_strequal(title, dialog->original_title)) {
- purple_savedstatus_set_title(saved_status, title);
- purple_savedstatus_set_primitive_type(saved_status, type);
- if (*unformatted == '\0')
- purple_savedstatus_set_message(saved_status, NULL);
- purple_savedstatus_set_message(saved_status, message);
- /* Set any substatuses */
- model = GTK_TREE_MODEL(dialog->model);
- if (gtk_tree_model_get_iter_first(model, &iter))
- PurpleAccount *account;
- PurpleStatusType *type;
- gtk_tree_model_get(model, &iter,
- STATUS_EDITOR_COLUMN_ACCOUNT, &account,
- STATUS_EDITOR_COLUMN_ENABLE_SUBSTATUS, &enabled,
- STATUS_EDITOR_COLUMN_STATUS_ID, &id,
- STATUS_EDITOR_COLUMN_STATUS_MESSAGE, &message,
- type = purple_account_get_status_type(account, id);
- purple_savedstatus_set_substatus(saved_status, account, type, message);
- purple_savedstatus_unset_substatus(saved_status, account);
- } while (gtk_tree_model_iter_next(model, &iter));
- /* If they clicked on "Save and Use" or "Use," then activate the status */
- purple_savedstatus_activate(saved_status);
- gtk_widget_destroy(dialog->window);
-status_editor_response_cb(GtkDialog *dialog, gint response, gpointer data) {
- StatusEditor *window = data;
- case GTK_RESPONSE_CLOSE:
- gtk_widget_destroy(window->window);
- case STATUS_RESPONSE_USE:
- status_editor_ok(window, TRUE, FALSE);
- case STATUS_RESPONSE_SAVE_AND_USE:
- status_editor_ok(window, TRUE, TRUE);
- case STATUS_RESPONSE_SAVE:
- status_editor_ok(window, FALSE, TRUE);
-editor_title_changed_cb(GtkWidget *widget, gpointer user_data)
- StatusEditor *dialog = user_data;
- text = gtk_entry_get_text(dialog->title);
- gtk_widget_set_sensitive(GTK_WIDGET(dialog->saveanduse_button), (*text != '\0'));
- gtk_widget_set_sensitive(GTK_WIDGET(dialog->save_button), (*text != '\0'));
-static void edit_substatus(StatusEditor *status_editor, PurpleAccount *account);
-edit_substatus_cb(GtkTreeView *tv, GtkTreePath *path, GtkTreeViewColumn *col, gpointer user_data)
- StatusEditor *dialog = user_data;
- PurpleAccount *account;
- gtk_tree_model_get_iter(GTK_TREE_MODEL(dialog->model), &iter, path);
- gtk_tree_model_get(GTK_TREE_MODEL(dialog->model), &iter,
- STATUS_EDITOR_COLUMN_ACCOUNT, &account,
- edit_substatus(dialog, account);
-status_editor_substatus_cb(GtkCellRendererToggle *renderer, gchar *path_str, gpointer data)
- StatusEditor *dialog = (StatusEditor *)data;
- PurpleAccount *account;
- gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(dialog->model), &iter, path_str);
- gtk_tree_model_get(GTK_TREE_MODEL(dialog->model), &iter,
- STATUS_EDITOR_COLUMN_ACCOUNT, &account,
- STATUS_EDITOR_COLUMN_ENABLE_SUBSTATUS, &enabled,
- edit_substatus(dialog, account);
- /* Remove the substatus */
- gtk_list_store_set(dialog->model, &iter,
- STATUS_EDITOR_COLUMN_ENABLE_SUBSTATUS, enabled,
- STATUS_EDITOR_COLUMN_STATUS_ID, NULL,
- STATUS_EDITOR_COLUMN_STATUS_NAME, NULL,
- STATUS_EDITOR_COLUMN_STATUS_MESSAGE, NULL,
- STATUS_EDITOR_COLUMN_STATUS_ICON, NULL,
-status_editor_add_columns(StatusEditor *dialog)
- GtkCellRenderer *renderer;
- GtkTreeViewColumn *column;
- /* Enable Different status column */
- renderer = gtk_cell_renderer_toggle_new();
- gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(dialog->treeview),
- "active", STATUS_EDITOR_COLUMN_ENABLE_SUBSTATUS,
- g_signal_connect(G_OBJECT(renderer), "toggled",
- G_CALLBACK(status_editor_substatus_cb), dialog);
- column = gtk_tree_view_column_new();
- gtk_tree_view_column_set_resizable(column, TRUE);
- gtk_tree_view_column_set_title(column, _("Username"));
- gtk_tree_view_insert_column(GTK_TREE_VIEW(dialog->treeview), column, -1);
- gtk_tree_view_column_set_resizable(column, TRUE);
- renderer = gtk_cell_renderer_pixbuf_new();
- gtk_tree_view_column_pack_start(column, renderer, FALSE);
- gtk_tree_view_column_add_attribute(column, renderer, "pixbuf",
- STATUS_EDITOR_COLUMN_ICON);
- renderer = gtk_cell_renderer_text_new();
- gtk_tree_view_column_pack_start(column, renderer, TRUE);
- gtk_tree_view_column_add_attribute(column, renderer, "text",
- STATUS_EDITOR_COLUMN_USERNAME);
- column = gtk_tree_view_column_new();
- gtk_tree_view_column_set_resizable(column, TRUE);
- gtk_tree_view_column_set_title(column, _("Status"));
- gtk_tree_view_insert_column(GTK_TREE_VIEW(dialog->treeview), column, -1);
- gtk_tree_view_column_set_resizable(column, TRUE);
- renderer = gtk_cell_renderer_pixbuf_new();
- gtk_tree_view_column_pack_start(column, renderer, FALSE);
- gtk_tree_view_column_add_attribute(column, renderer, "stock-id",
- STATUS_EDITOR_COLUMN_STATUS_ICON);
- renderer = gtk_cell_renderer_text_new();
- gtk_tree_view_column_pack_start(column, renderer, TRUE);
- gtk_tree_view_column_add_attribute(column, renderer, "text",
- STATUS_EDITOR_COLUMN_STATUS_NAME);
- column = gtk_tree_view_column_new();
- gtk_tree_view_column_set_resizable(column, TRUE);
- gtk_tree_view_column_set_title(column, _("Message"));
- gtk_tree_view_insert_column(GTK_TREE_VIEW(dialog->treeview), column, -1);
- gtk_tree_view_column_set_resizable(column, TRUE);
- renderer = gtk_cell_renderer_text_new();
- gtk_tree_view_column_pack_start(column, renderer, TRUE);
- gtk_tree_view_column_add_attribute(column, renderer, "text",
- STATUS_EDITOR_COLUMN_STATUS_MESSAGE);
- g_signal_connect(G_OBJECT(dialog->treeview), "row-activated",
- G_CALLBACK(edit_substatus_cb), dialog);
-status_editor_set_account(GtkListStore *store, PurpleAccount *account,
- GtkTreeIter *iter, PurpleSavedStatusSub *substatus)
- const char *id = NULL, *name = NULL, *message = NULL;
- PurpleStatusPrimitive prim = PURPLE_STATUS_UNSET;
- pixbuf = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_MEDIUM);
- if ((pixbuf != NULL) && !purple_account_is_connected(account))
- gdk_pixbuf_saturate_and_pixelate(pixbuf, pixbuf, 0.0, FALSE);
- const PurpleStatusType *type;
- type = purple_savedstatus_substatus_get_status_type(substatus);
- id = purple_status_type_get_id(type);
- name = purple_status_type_get_name(type);
- prim = purple_status_type_get_primitive(type);
- if (purple_status_type_get_attr(type, "message"))
- message = purple_savedstatus_substatus_get_message(substatus);
- gtk_list_store_set(store, iter,
- STATUS_EDITOR_COLUMN_ACCOUNT, account,
- STATUS_EDITOR_COLUMN_ENABLE_SUBSTATUS, (substatus != NULL),
- STATUS_EDITOR_COLUMN_ICON, pixbuf,
- STATUS_EDITOR_COLUMN_USERNAME, purple_account_get_username(account),
- STATUS_EDITOR_COLUMN_STATUS_ID, id,
- STATUS_EDITOR_COLUMN_STATUS_NAME, name,
- STATUS_EDITOR_COLUMN_STATUS_MESSAGE, message,
- STATUS_EDITOR_COLUMN_STATUS_ICON, pidgin_icon_name_from_status_primitive(prim, NULL),
- g_object_unref(G_OBJECT(pixbuf));
-status_editor_add_account(StatusEditor *dialog, PurpleAccount *account,
- PurpleSavedStatusSub *substatus)
- gtk_list_store_append(dialog->model, &iter);
- status_editor_set_account(dialog->model, account, &iter, substatus);
-status_editor_populate_list(StatusEditor *dialog, PurpleSavedStatus *saved_status)
- PurpleAccountManager *manager = NULL;
- PurpleSavedStatusSub *substatus;
- gtk_list_store_clear(dialog->model);
- manager = purple_account_manager_get_default();
- iter = purple_account_manager_get_all(manager);
- for(; iter != NULL; iter = iter->next) {
- PurpleAccount *account = (PurpleAccount *)iter->data;
- if (saved_status != NULL) {
- substatus = purple_savedstatus_get_substatus(saved_status, account);
- status_editor_add_account(dialog, account, substatus);
-pidgin_status_editor_show(gboolean edit, PurpleSavedStatus *saved_status)
- PurpleStatusPrimitive primitive = PURPLE_STATUS_AWAY;
- g_return_if_fail(saved_status != NULL);
- g_return_if_fail(!purple_savedstatus_is_transient(saved_status));
- /* Find a possible window for this saved status and present it */
- if (edit && status_window_find_savedstatus(&iter, purple_savedstatus_get_title(saved_status)))
- gtk_tree_model_get(GTK_TREE_MODEL(status_window->model), &iter,
- STATUS_WINDOW_COLUMN_WINDOW, &dialog,
- gtk_window_present(GTK_WINDOW(dialog->window));
- dialog = g_new0(StatusEditor, 1);
- if (edit && status_window_find_savedstatus(&iter, purple_savedstatus_get_title(saved_status)))
- gtk_list_store_set(status_window->model, &iter,
- STATUS_WINDOW_COLUMN_WINDOW, dialog,
- dialog->original_title = g_strdup(purple_savedstatus_get_title(saved_status));
- dialog->window = win = pidgin_dialog_new(_("Status"), 12, "status", TRUE);
- g_signal_connect(win, "destroy", G_CALLBACK(status_editor_destroy_cb),
- g_signal_connect(win, "response", G_CALLBACK(status_editor_response_cb),
- vbox = gtk_dialog_get_content_area(GTK_DIALOG(win));
- gtk_box_set_spacing(GTK_BOX(vbox), 12);
- sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
- entry = gtk_entry_new();
- dialog->title = GTK_ENTRY(entry);
- if ((saved_status != NULL)
- && !purple_savedstatus_is_transient(saved_status)
- && (purple_savedstatus_get_title(saved_status) != NULL))
- gtk_entry_set_text(GTK_ENTRY(entry), purple_savedstatus_get_title(saved_status));
- g_signal_connect(G_OBJECT(entry), "changed",
- G_CALLBACK(editor_title_changed_cb), dialog);
- pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("_Title:"), sg, entry, TRUE, NULL);
- if (saved_status != NULL) {
- primitive = purple_savedstatus_get_primitive_type(saved_status);
- store = pidgin_status_primitive_store_new();
- dropdown = pidgin_status_primitive_chooser_new();
- dialog->type = GTK_COMBO_BOX(dropdown);
- gtk_combo_box_set_model(GTK_COMBO_BOX(dropdown), GTK_TREE_MODEL(store));
- gtk_combo_box_set_active_id(GTK_COMBO_BOX(dropdown),
- purple_primitive_get_id_from_type(primitive));
- pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("_Status:"), sg, dropdown, TRUE, NULL);
- editor = talkatu_editor_new();
- dialog->message_view = talkatu_editor_get_input(TALKATU_EDITOR(editor));
- hbox = pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("_Message:"), sg, editor, TRUE, NULL);
- dialog->message_buffer = talkatu_html_buffer_new();
- gtk_text_view_set_buffer(GTK_TEXT_VIEW(dialog->message_view), dialog->message_buffer);
- gtk_container_child_set(GTK_CONTAINER(vbox), hbox, "expand", TRUE, "fill", TRUE, NULL);
- if ((saved_status != NULL) && (purple_savedstatus_get_message(saved_status) != NULL)) {
- talkatu_markup_set_html(
- TALKATU_BUFFER(dialog->message_buffer),
- purple_savedstatus_get_message(saved_status),
- /* Different status message expander */
- expander = gtk_expander_new_with_mnemonic(_("Use a _different status for some accounts"));
- gtk_box_pack_start(GTK_BOX(vbox), expander, FALSE, FALSE, 0);
- /* Setup the box that the expander will cover */
- dbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 18);
- gtk_container_add(GTK_CONTAINER(expander), dbox);
- /* Create the list model */
- dialog->model = gtk_list_store_new(STATUS_EDITOR_NUM_COLUMNS,
- /* Create the treeview */
- dialog->treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(dialog->model));
- gtk_widget_set_size_request(dialog->treeview, -1, 150);
- gtk_box_pack_start(GTK_BOX(dbox),
- pidgin_make_scrollable(dialog->treeview, GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS, GTK_SHADOW_IN, -1, -1),
- status_editor_add_columns(dialog);
- status_editor_populate_list(dialog, saved_status);
- /* Expand the treeview if we have substatuses */
- gtk_expander_set_expanded(GTK_EXPANDER(expander),
- (saved_status != NULL) && purple_savedstatus_has_substatuses(saved_status));
- gtk_dialog_add_button(GTK_DIALOG(win), _("Cancel"), GTK_RESPONSE_CLOSE);
- gtk_dialog_add_button(GTK_DIALOG(win), _("_Use"), STATUS_RESPONSE_USE);
- dialog->saveanduse_button = gtk_dialog_add_button(GTK_DIALOG(win),
- STATUS_RESPONSE_SAVE_AND_USE);
- if(dialog->original_title == NULL) {
- gtk_widget_set_sensitive(dialog->saveanduse_button, FALSE);
- dialog->save_button = gtk_dialog_add_button(GTK_DIALOG(win), _("Save"),
- if(dialog->original_title == NULL) {
- gtk_widget_set_sensitive(dialog->save_button, FALSE);
- gtk_widget_show_all(win);
-/**************************************************************************
-**************************************************************************/
-substatus_selection_changed_cb(GtkComboBox *box, gpointer user_data)
- SubStatusEditor *select = user_data;
- PurpleStatusType *type;
- PurpleStatusPrimitive primitive;
- id = gtk_combo_box_get_active_id(box);
- primitive = purple_primitive_get_type_from_id(id);
- if(primitive == PURPLE_STATUS_UNSET) {
- type = purple_account_get_status_type_with_primitive(select->account,
- if(purple_status_type_get_attr(type, "message") == NULL) {
- gtk_widget_set_sensitive(select->message_view, FALSE);
- gtk_widget_set_sensitive(select->message_view, TRUE);
-status_editor_find_account_in_treemodel(GtkTreeIter *iter,
- StatusEditor *status_editor,
- PurpleAccount *account)
- g_return_val_if_fail(status_editor != NULL, FALSE);
- g_return_val_if_fail(account != NULL, FALSE);
- model = GTK_TREE_MODEL(status_editor->model);
- if (!gtk_tree_model_get_iter_first(model, iter))
- gtk_tree_model_get(model, iter, STATUS_EDITOR_COLUMN_ACCOUNT, &cur, -1);
- } while (gtk_tree_model_iter_next(model, iter));
-substatus_editor_remove_dialog(SubStatusEditor *dialog)
- if (status_editor_find_account_in_treemodel(&iter, dialog->status_editor, dialog->account))
- /* Remove the reference to this dialog from our parent's list store */
- gtk_list_store_set(dialog->status_editor->model, &iter,
- STATUS_EDITOR_COLUMN_WINDOW, NULL,
-substatus_editor_destroy_cb(GtkWidget *widget, gpointer user_data)
- SubStatusEditor *dialog = user_data;
- substatus_editor_remove_dialog(dialog);
-substatus_editor_cancel(SubStatusEditor *dialog)
- gtk_widget_destroy(dialog->window);
-substatus_editor_ok(SubStatusEditor *dialog)
- StatusEditor *status_editor;
- PurpleStatusType *type;
- PurpleStatusPrimitive primitive;
- const gchar *name = NULL, *icon_name = NULL;
- id = gtk_combo_box_get_active_id(GTK_COMBO_BOX(dialog->box));
- gtk_widget_destroy(dialog->window);
- primitive = purple_primitive_get_type_from_id(id);
- if(primitive == PURPLE_STATUS_UNSET) {
- gtk_widget_destroy(dialog->window);
- type = purple_account_get_status_type_with_primitive(dialog->account,
- if (purple_status_type_get_attr(type, "message") != NULL) {
- message = talkatu_markup_get_html(dialog->message_buffer, NULL);
- name = purple_status_type_get_name(type);
- icon_name = pidgin_icon_name_from_status_primitive(primitive, NULL);
- status_editor = dialog->status_editor;
- if (status_editor_find_account_in_treemodel(&iter, status_editor, dialog->account))
- gtk_list_store_set(status_editor->model, &iter,
- STATUS_EDITOR_COLUMN_ENABLE_SUBSTATUS, TRUE,
- STATUS_EDITOR_COLUMN_STATUS_ID, id,
- STATUS_EDITOR_COLUMN_STATUS_NAME, name,
- STATUS_EDITOR_COLUMN_STATUS_MESSAGE, message,
- STATUS_EDITOR_COLUMN_WINDOW, NULL,
- STATUS_EDITOR_COLUMN_STATUS_ICON, icon_name,
- gtk_widget_destroy(dialog->window);
-substatus_editor_response_cb(GtkDialog *dialog, gint response_id,
- SubStatusEditor *editor = data;
- case GTK_RESPONSE_CANCEL:
- substatus_editor_cancel(editor);
- substatus_editor_ok(editor);
-edit_substatus(StatusEditor *status_editor, PurpleAccount *account)
- SubStatusEditor *dialog;
- char *status_id = NULL;
- gboolean parent_dialog_has_substatus = FALSE;
- PurpleStatusPrimitive primitive = PURPLE_STATUS_AWAY;
- g_return_if_fail(status_editor != NULL);
- g_return_if_fail(account != NULL);
- status_editor_find_account_in_treemodel(&iter, status_editor, account);
- gtk_tree_model_get(GTK_TREE_MODEL(status_editor->model), &iter,
- STATUS_EDITOR_COLUMN_WINDOW, &dialog,
- gtk_window_present(GTK_WINDOW(dialog->window));
- dialog = g_new0(SubStatusEditor, 1);
- gtk_list_store_set(status_editor->model, &iter,
- STATUS_EDITOR_COLUMN_WINDOW, dialog,
- dialog->status_editor = status_editor;
- dialog->account = account;
- tmp = g_strdup_printf(_("Status for %s"), purple_account_get_username(account));
- dialog->window = win = pidgin_dialog_new(tmp, 12, "substatus", TRUE);
- g_signal_connect(G_OBJECT(win), "destroy",
- G_CALLBACK(substatus_editor_destroy_cb), dialog);
- g_signal_connect(win, "response", G_CALLBACK(substatus_editor_response_cb),
- vbox = gtk_dialog_get_content_area(GTK_DIALOG(win));
- gtk_box_set_spacing(GTK_BOX(vbox), 12);
- sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
- hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
- gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
- label = gtk_label_new_with_mnemonic(_("_Status:"));
- gtk_label_set_xalign(GTK_LABEL(label), 0);
- gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
- gtk_size_group_add_widget(sg, label);
- store = pidgin_status_primitive_store_new();
- pidgin_status_primitive_store_set_account(PIDGIN_STATUS_PRIMITIVE_STORE(store),
- combo = pidgin_status_primitive_chooser_new();
- gtk_combo_box_set_model(GTK_COMBO_BOX(combo), GTK_TREE_MODEL(store));
- dialog->box = GTK_COMBO_BOX(combo);
- g_signal_connect(G_OBJECT(combo), "changed",
- G_CALLBACK(substatus_selection_changed_cb), dialog);
- gtk_box_pack_start(GTK_BOX(hbox), combo, FALSE, FALSE, 0);
- hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
- gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
- label = gtk_label_new_with_mnemonic(_("_Message:"));
- gtk_label_set_xalign(GTK_LABEL(label), 0);
- gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
- gtk_size_group_add_widget(sg, label);
- editor = talkatu_editor_new();
- gtk_box_pack_start(GTK_BOX(hbox), editor, TRUE, TRUE, 0);
- dialog->message_view = talkatu_editor_get_input(TALKATU_EDITOR(editor));
- dialog->message_buffer = talkatu_html_buffer_new();
- gtk_text_view_set_buffer(GTK_TEXT_VIEW(dialog->message_view), dialog->message_buffer);
- gtk_dialog_add_button(GTK_DIALOG(win), _("Cancel"), GTK_RESPONSE_CANCEL);
- gtk_dialog_add_button(GTK_DIALOG(win), _("Okay"), GTK_RESPONSE_OK);
- /* Seed the input widgets with the current values */
- /* Only look at the saved status if we can't find it in the parent status dialog's substatuses model */
- gtk_tree_model_get(GTK_TREE_MODEL(status_editor->model), &iter,
- STATUS_EDITOR_COLUMN_ENABLE_SUBSTATUS, &parent_dialog_has_substatus, -1);
- if (parent_dialog_has_substatus) {
- gtk_tree_model_get(GTK_TREE_MODEL(status_editor->model), &iter,
- STATUS_EDITOR_COLUMN_STATUS_ID, &status_id,
- STATUS_EDITOR_COLUMN_STATUS_MESSAGE, &message, -1);
- } else if (status_editor->original_title != NULL) {
- PurpleSavedStatus *saved_status = NULL;
- PurpleSavedStatusSub *substatus = NULL;
- if ((saved_status = purple_savedstatus_find(status_editor->original_title)) != NULL) {
- if ((substatus = purple_savedstatus_get_substatus(saved_status, account)) != NULL) {
- message = (char *)purple_savedstatus_substatus_get_message(substatus);
- status_id = (char *)purple_status_type_get_id(
- purple_savedstatus_substatus_get_status_type(substatus));
- /* TODO: Else get the generic status type from our parent */
- if(status_id != NULL) {
- PurpleStatus *status = purple_account_get_status(account, status_id);
- PurpleStatusType *type = purple_status_get_status_type(status);
- primitive = purple_status_type_get_primitive(type);
- gtk_combo_box_set_active_id(GTK_COMBO_BOX(combo),
- purple_primitive_get_id_from_type(primitive));
- talkatu_markup_set_html(TALKATU_BUFFER(dialog->message_buffer), message, -1);
- if (parent_dialog_has_substatus) {
- /* These two were gotten from the parent tree model, so they need to be freed */
- gtk_widget_show_all(win);
-/**************************************************************************
- **************************************************************************/
SS_MENU_ENTRY_TYPE_PRIMITIVE,
SS_MENU_ENTRY_TYPE_SAVEDSTATUS
@@ -1729,27 +295,3 @@
-/**************************************************************************
-**************************************************************************/
-pidgin_status_get_handle(void)
-pidgin_status_init(void)
-pidgin_status_uninit(void)
- pidgin_status_window_hide();
--- a/pidgin/gtksavedstatuses.h Fri May 27 14:52:34 2022 -0500
+++ b/pidgin/gtksavedstatuses.h Mon May 30 21:04:47 2022 -0500
@@ -31,40 +31,6 @@
- * pidgin_status_window_show:
- * Shows the status window.
-void pidgin_status_window_show(void);
- * pidgin_status_window_hide:
- * Hides the status window.
-void pidgin_status_window_hide(void);
- * pidgin_status_editor_show:
- * @edit: %TRUE if we want to edit an existing saved
- * status or %FALSE to create a new one. You
- * can not edit transient statuses--they don't
- * have titles. If you want to edit a transient
- * status, set this to %FALSE and seed the dialog
- * with the transient status using the status
- * parameter to this function.
- * @status: If edit is %TRUE then this should be a
- * pointer to the PurpleSavedStatus to edit.
- * If edit is %FALSE then this can be NULL,
- * or you can pass in a saved status to
- * seed the initial values of the new status.
- * Shows a status editor (used for adding a new saved status or
- * editing an already existing saved status).
-void pidgin_status_editor_show(gboolean edit, PurpleSavedStatus *status);
* @status: The default saved_status to show as 'selected'
* @callback: (scope call): The callback to call when the selection changes
@@ -76,29 +42,6 @@
GtkWidget *pidgin_status_menu(PurpleSavedStatus *status, GCallback callback);
- * pidgin_status_get_handle:
- * Returns the GTK status handle.
- * Returns: The handle to the GTK status system.
-void *pidgin_status_get_handle(void);
- * Initializes the GTK status system.
-void pidgin_status_init(void);
- * pidgin_status_uninit:
- * Uninitializes the GTK status system.
-void pidgin_status_uninit(void);
#endif /* _PIDGINSAVEDSTATUSES_H_ */
--- a/pidgin/libpidgin.c Fri May 27 14:52:34 2022 -0500
+++ b/pidgin/libpidgin.c Mon May 30 21:04:47 2022 -0500
@@ -44,7 +44,6 @@
-#include "gtksavedstatuses.h"
#include "gtkwhiteboard.h"
#include "pidginapplication.h"
@@ -265,7 +264,6 @@
pidgin_connection_init();
pidgin_conversations_init();
@@ -286,7 +284,6 @@
pidgin_commands_uninit();
pidgin_conversations_uninit();
- pidgin_status_uninit();
pidgin_connection_uninit();
--- a/pidgin/pidginapplication.c Fri May 27 14:52:34 2022 -0500
+++ b/pidgin/pidginapplication.c Mon May 30 21:04:47 2022 -0500
@@ -52,6 +52,7 @@
#include "pidginmooddialog.h"
#include "pidginpluginsdialog.h"
#include "pidginpluginsmenu.h"
+#include "pidginstatuseditor.h" #include "pidginstatusmanager.h"
@@ -361,7 +362,8 @@
G_GNUC_UNUSED GVariant *parameter,
G_GNUC_UNUSED gpointer data)
- pidgin_status_editor_show(FALSE, NULL);
+ GtkWidget *editor = pidgin_status_editor_new(NULL); + gtk_widget_show(editor);