summaryrefslogtreecommitdiff
path: root/gui/simple-greeter/gdm-chooser-widget.c
diff options
context:
space:
mode:
Diffstat (limited to 'gui/simple-greeter/gdm-chooser-widget.c')
-rw-r--r--gui/simple-greeter/gdm-chooser-widget.c2849
1 files changed, 0 insertions, 2849 deletions
diff --git a/gui/simple-greeter/gdm-chooser-widget.c b/gui/simple-greeter/gdm-chooser-widget.c
deleted file mode 100644
index cab506c5..00000000
--- a/gui/simple-greeter/gdm-chooser-widget.c
+++ /dev/null
@@ -1,2849 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
- *
- * Copyright (C) 2007 Ray Strode <rstrode@redhat.com>
- * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
- * Copyright (C) 2008 Red Hat, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <dirent.h>
-#include <sys/stat.h>
-#include <syslog.h>
-#include <locale.h>
-
-#include <glib.h>
-#include <glib/gi18n.h>
-#include <glib/gstdio.h>
-#include <gtk/gtk.h>
-
-#include "gdm-chooser-widget.h"
-#include "gdm-scrollable-widget.h"
-#include "gdm-cell-renderer-timer.h"
-#include "gdm-timer.h"
-
-#define GDM_CHOOSER_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_CHOOSER_WIDGET, GdmChooserWidgetPrivate))
-
-#ifndef GDM_CHOOSER_WIDGET_DEFAULT_ICON_SIZE
-#define GDM_CHOOSER_WIDGET_DEFAULT_ICON_SIZE 64
-#endif
-
-typedef enum {
- GDM_CHOOSER_WIDGET_STATE_GROWN = 0,
- GDM_CHOOSER_WIDGET_STATE_GROWING,
- GDM_CHOOSER_WIDGET_STATE_SHRINKING,
- GDM_CHOOSER_WIDGET_STATE_SHRUNK,
-} GdmChooserWidgetState;
-
-struct GdmChooserWidgetPrivate
-{
- GtkWidget *frame;
- GtkWidget *frame_alignment;
- GtkWidget *scrollable_widget;
-
- GtkWidget *items_view;
- GtkListStore *list_store;
-
- GtkTreeModelFilter *model_filter;
- GtkTreeModelSort *model_sorter;
-
- GdkPixbuf *is_in_use_pixbuf;
-
- /* row for the list_store model */
- GtkTreeRowReference *active_row;
- GtkTreeRowReference *separator_row;
-
- GHashTable *rows_with_timers;
-
- GtkTreeViewColumn *status_column;
- GtkTreeViewColumn *image_column;
-
- char *inactive_text;
- char *active_text;
- char *in_use_message;
-
- gint number_of_normal_rows;
- gint number_of_separated_rows;
- gint number_of_rows_with_status;
- gint number_of_rows_with_images;
- gint number_of_active_timers;
-
- guint update_idle_id;
- guint update_separator_idle_id;
- guint update_cursor_idle_id;
- guint update_visibility_idle_id;
- guint update_items_idle_id;
- guint timer_animation_timeout_id;
-
- gboolean list_visible;
-
- guint32 should_hide_inactive_items : 1;
- guint32 emit_activated_after_resize_animation : 1;
-
- GdmChooserWidgetPosition separator_position;
- GdmChooserWidgetState state;
-
- double active_row_normalized_position;
-};
-
-enum {
- PROP_0,
- PROP_INACTIVE_TEXT,
- PROP_ACTIVE_TEXT,
- PROP_LIST_VISIBLE
-};
-
-enum {
- ACTIVATED = 0,
- DEACTIVATED,
- LOADED,
- NUMBER_OF_SIGNALS
-};
-
-static guint signals[NUMBER_OF_SIGNALS];
-
-static void gdm_chooser_widget_class_init (GdmChooserWidgetClass *klass);
-static void gdm_chooser_widget_init (GdmChooserWidget *chooser_widget);
-static void gdm_chooser_widget_finalize (GObject *object);
-
-static void update_timer_from_time (GdmChooserWidget *widget,
- GtkTreeRowReference *row,
- double now);
-
-G_DEFINE_TYPE (GdmChooserWidget, gdm_chooser_widget, GTK_TYPE_ALIGNMENT)
-
-enum {
- CHOOSER_IMAGE_COLUMN = 0,
- CHOOSER_NAME_COLUMN,
- CHOOSER_COMMENT_COLUMN,
- CHOOSER_PRIORITY_COLUMN,
- CHOOSER_ITEM_IS_IN_USE_COLUMN,
- CHOOSER_ITEM_IS_SEPARATED_COLUMN,
- CHOOSER_ITEM_IS_VISIBLE_COLUMN,
- CHOOSER_TIMER_START_TIME_COLUMN,
- CHOOSER_TIMER_DURATION_COLUMN,
- CHOOSER_TIMER_VALUE_COLUMN,
- CHOOSER_ID_COLUMN,
- CHOOSER_LOAD_FUNC_COLUMN,
- CHOOSER_LOAD_DATA_COLUMN,
- NUMBER_OF_CHOOSER_COLUMNS
-};
-
-static gboolean
-find_item (GdmChooserWidget *widget,
- const char *id,
- GtkTreeIter *iter)
-{
- GtkTreeModel *model;
- gboolean found_item;
-
- g_assert (GDM_IS_CHOOSER_WIDGET (widget));
- g_assert (id != NULL);
-
- found_item = FALSE;
- model = GTK_TREE_MODEL (widget->priv->list_store);
-
- if (!gtk_tree_model_get_iter_first (model, iter)) {
- return FALSE;
- }
-
- do {
- char *item_id;
-
- gtk_tree_model_get (model,
- iter,
- CHOOSER_ID_COLUMN,
- &item_id,
- -1);
-
- g_assert (item_id != NULL);
-
- if (strcmp (id, item_id) == 0) {
- found_item = TRUE;
- }
- g_free (item_id);
-
- } while (!found_item && gtk_tree_model_iter_next (model, iter));
-
- return found_item;
-}
-
-typedef struct {
- GdmChooserWidget *widget;
- GdmChooserUpdateForeachFunc func;
- gpointer user_data;
-} UpdateForeachData;
-
-static gboolean
-foreach_item (GtkTreeModel *model,
- GtkTreePath *path,
- GtkTreeIter *iter,
- UpdateForeachData *data)
-{
- GdkPixbuf *image;
- char *name;
- char *comment;
- gboolean in_use;
- gboolean is_separate;
- gboolean res;
- char *id;
- gulong priority;
-
- gtk_tree_model_get (model,
- iter,
- CHOOSER_ID_COLUMN, &id,
- CHOOSER_IMAGE_COLUMN, &image,
- CHOOSER_NAME_COLUMN, &name,
- CHOOSER_COMMENT_COLUMN, &comment,
- CHOOSER_PRIORITY_COLUMN, &priority,
- CHOOSER_ITEM_IS_IN_USE_COLUMN, &in_use,
- CHOOSER_ITEM_IS_SEPARATED_COLUMN, &is_separate,
- -1);
- res = data->func (data->widget,
- (const char *)id,
- &image,
- &name,
- &comment,
- &priority,
- &in_use,
- &is_separate,
- data->user_data);
- if (res) {
- gtk_list_store_set (GTK_LIST_STORE (model),
- iter,
- CHOOSER_ID_COLUMN, id,
- CHOOSER_IMAGE_COLUMN, image,
- CHOOSER_NAME_COLUMN, name,
- CHOOSER_COMMENT_COLUMN, comment,
- CHOOSER_PRIORITY_COLUMN, priority,
- CHOOSER_ITEM_IS_IN_USE_COLUMN, in_use,
- CHOOSER_ITEM_IS_SEPARATED_COLUMN, is_separate,
- -1);
- }
-
- g_free (name);
- g_free (comment);
- if (image != NULL) {
- g_object_unref (image);
- }
-
- return FALSE;
-}
-
-void
-gdm_chooser_widget_update_foreach_item (GdmChooserWidget *widget,
- GdmChooserUpdateForeachFunc func,
- gpointer user_data)
-{
- UpdateForeachData fdata;
-
- fdata.widget = widget;
- fdata.func = func;
- fdata.user_data = user_data;
- gtk_tree_model_foreach (GTK_TREE_MODEL (widget->priv->list_store),
- (GtkTreeModelForeachFunc) foreach_item,
- &fdata);
-}
-
-static void
-translate_list_path_to_view_path (GdmChooserWidget *widget,
- GtkTreePath **path)
-{
- GtkTreePath *filtered_path;
- GtkTreePath *sorted_path;
-
- /* the child model is the source for the filter */
- filtered_path = gtk_tree_model_filter_convert_child_path_to_path (widget->priv->model_filter,
- *path);
- sorted_path = gtk_tree_model_sort_convert_child_path_to_path (widget->priv->model_sorter,
- filtered_path);
- gtk_tree_path_free (filtered_path);
-
- gtk_tree_path_free (*path);
- *path = sorted_path;
-}
-
-
-static void
-translate_view_path_to_list_path (GdmChooserWidget *widget,
- GtkTreePath **path)
-{
- GtkTreePath *filtered_path;
- GtkTreePath *list_path;
-
- /* the child model is the source for the filter */
- filtered_path = gtk_tree_model_sort_convert_path_to_child_path (widget->priv->model_sorter,
- *path);
-
- list_path = gtk_tree_model_filter_convert_path_to_child_path (widget->priv->model_filter,
- filtered_path);
- gtk_tree_path_free (filtered_path);
-
- gtk_tree_path_free (*path);
- *path = list_path;
-}
-
-static GtkTreePath *
-get_list_path_to_active_row (GdmChooserWidget *widget)
-{
- GtkTreePath *path;
-
- if (widget->priv->active_row == NULL) {
- return NULL;
- }
-
- path = gtk_tree_row_reference_get_path (widget->priv->active_row);
- if (path == NULL) {
- return NULL;
- }
-
- return path;
-}
-
-static GtkTreePath *
-get_view_path_to_active_row (GdmChooserWidget *widget)
-{
- GtkTreePath *path;
-
- path = get_list_path_to_active_row (widget);
- if (path == NULL) {
- return NULL;
- }
-
- translate_list_path_to_view_path (widget, &path);
-
- return path;
-}
-
-static char *
-get_active_item_id (GdmChooserWidget *widget,
- GtkTreeIter *iter)
-{
- char *item_id;
- GtkTreeModel *model;
- GtkTreePath *path;
-
- g_return_val_if_fail (GDM_IS_CHOOSER_WIDGET (widget), NULL);
-
- model = GTK_TREE_MODEL (widget->priv->list_store);
- item_id = NULL;
-
- if (widget->priv->active_row == NULL) {
- return NULL;
- }
-
- path = get_list_path_to_active_row (widget);
- if (path == NULL) {
- return NULL;
- }
-
- if (gtk_tree_model_get_iter (model, iter, path)) {
- gtk_tree_model_get (model,
- iter,
- CHOOSER_ID_COLUMN,
- &item_id,
- -1);
- }
- gtk_tree_path_free (path);
-
- return item_id;
-}
-
-char *
-gdm_chooser_widget_get_active_item (GdmChooserWidget *widget)
-{
- GtkTreeIter iter;
-
- return get_active_item_id (widget, &iter);
-}
-
-static void
-get_selected_list_path (GdmChooserWidget *widget,
- GtkTreePath **pathp)
-{
- GtkTreeSelection *selection;
- GtkTreeModel *sort_model;
- GtkTreeIter sorted_iter;
- GtkTreePath *path;
-
- path = NULL;
-
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget->priv->items_view));
- if (gtk_tree_selection_get_selected (selection, &sort_model, &sorted_iter)) {
-
- g_assert (sort_model == GTK_TREE_MODEL (widget->priv->model_sorter));
-
- path = gtk_tree_model_get_path (sort_model, &sorted_iter);
-
- translate_view_path_to_list_path (widget, &path);
- } else {
- g_debug ("GdmChooserWidget: no rows selected");
- }
-
- *pathp = path;
-}
-
-char *
-gdm_chooser_widget_get_selected_item (GdmChooserWidget *widget)
-{
- GtkTreeIter iter;
- GtkTreeModel *model;
- GtkTreePath *path;
- char *id;
-
- id = NULL;
-
- get_selected_list_path (widget, &path);
-
- if (path == NULL) {
- return NULL;
- }
-
- model = GTK_TREE_MODEL (widget->priv->list_store);
-
- if (gtk_tree_model_get_iter (model, &iter, path)) {
- gtk_tree_model_get (model,
- &iter,
- CHOOSER_ID_COLUMN,
- &id,
- -1);
- }
-
- gtk_tree_path_free (path);
-
- return id;
-}
-
-void
-gdm_chooser_widget_set_selected_item (GdmChooserWidget *widget,
- const char *id)
-{
- GtkTreeIter iter;
- GtkTreeSelection *selection;
- GtkTreeModel *model;
-
- g_return_if_fail (GDM_IS_CHOOSER_WIDGET (widget));
-
- g_debug ("GdmChooserWidget: setting selected item '%s'",
- id ? id : "(null)");
-
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget->priv->items_view));
-
- model = GTK_TREE_MODEL (widget->priv->list_store);
-
- if (find_item (widget, id, &iter)) {
- GtkTreePath *path;
-
- path = gtk_tree_model_get_path (model, &iter);
- translate_list_path_to_view_path (widget, &path);
-
- gtk_tree_selection_select_path (selection, path);
-
- gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (widget->priv->items_view),
- path,
- NULL,
- TRUE,
- 0.5,
- 0.0);
-
- gtk_tree_view_set_cursor (GTK_TREE_VIEW (widget->priv->items_view),
- path,
- NULL,
- FALSE);
- gtk_tree_path_free (path);
- } else {
- gtk_tree_selection_unselect_all (selection);
- }
-}
-
-static void
-activate_from_item_id (GdmChooserWidget *widget,
- const char *item_id)
-{
- GtkTreeModel *model;
- GtkTreePath *path;
- GtkTreeIter iter;
- char *path_str;
-
- model = GTK_TREE_MODEL (widget->priv->list_store);
- path = NULL;
-
- if (find_item (widget, item_id, &iter)) {
- path = gtk_tree_model_get_path (model, &iter);
-
- path_str = gtk_tree_path_to_string (path);
- g_debug ("GdmChooserWidget: got list path '%s'", path_str);
- g_free (path_str);
-
- translate_list_path_to_view_path (widget, &path);
-
- path_str = gtk_tree_path_to_string (path);
- g_debug ("GdmChooserWidget: translated to view path '%s'", path_str);
- g_free (path_str);
- }
-
- if (path == NULL) {
- g_debug ("GdmChooserWidget: unable to activate - path for item '%s' not found", item_id);
- return;
- }
-
- gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (widget->priv->items_view),
- path,
- NULL,
- TRUE,
- 0.5,
- 0.0);
-
- gtk_tree_view_set_cursor (GTK_TREE_VIEW (widget->priv->items_view),
- path,
- NULL,
- FALSE);
-
- gtk_tree_view_row_activated (GTK_TREE_VIEW (widget->priv->items_view),
- path,
- NULL);
- gtk_tree_path_free (path);
-}
-
-static void
-set_frame_text (GdmChooserWidget *widget,
- const char *text)
-{
- GtkWidget *label;
-
- label = gtk_frame_get_label_widget (GTK_FRAME (widget->priv->frame));
-
- if (text == NULL && label != NULL) {
- gtk_frame_set_label_widget (GTK_FRAME (widget->priv->frame),
- NULL);
- gtk_alignment_set_padding (GTK_ALIGNMENT (widget->priv->frame_alignment),
- 0, 0, 0, 0);
- } else if (text != NULL && label == NULL) {
- label = gtk_label_new ("");
- gtk_label_set_mnemonic_widget (GTK_LABEL (label),
- widget->priv->items_view);
- gtk_widget_show (label);
- gtk_frame_set_label_widget (GTK_FRAME (widget->priv->frame),
- label);
- gtk_alignment_set_padding (GTK_ALIGNMENT (widget->priv->frame_alignment),
- 0, 0, 0, 0);
- }
-
- if (label != NULL && text != NULL) {
- char *markup;
- markup = g_strdup_printf ("%s", text);
- gtk_label_set_markup_with_mnemonic (GTK_LABEL (label), markup);
- g_free (markup);
- }
-}
-
-static void
-on_shrink_animation_step (GdmScrollableWidget *scrollable_widget,
- double progress,
- int *new_height,
- GdmChooserWidget *widget)
-{
- GtkTreePath *active_row_path;
- const double final_alignment = 0.5;
- double row_alignment;
-
- active_row_path = get_view_path_to_active_row (widget);
- row_alignment = widget->priv->active_row_normalized_position + progress * (final_alignment - widget->priv->active_row_normalized_position);
-
- gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (widget->priv->items_view),
- active_row_path, NULL, TRUE, row_alignment, 0.0);
- gtk_tree_path_free (active_row_path);
-}
-
-static gboolean
-update_separator_visibility (GdmChooserWidget *widget)
-{
- GtkTreePath *separator_path;
- GtkTreeIter iter;
- gboolean is_visible;
-
- g_debug ("GdmChooserWidget: updating separator visibility");
-
- separator_path = gtk_tree_row_reference_get_path (widget->priv->separator_row);
-
- if (separator_path == NULL) {
- goto out;
- }
-
- gtk_tree_model_get_iter (GTK_TREE_MODEL (widget->priv->list_store),
- &iter, separator_path);
-
- if (widget->priv->number_of_normal_rows > 0 &&
- widget->priv->number_of_separated_rows > 0 &&
- widget->priv->state != GDM_CHOOSER_WIDGET_STATE_SHRUNK) {
- is_visible = TRUE;
- } else {
- is_visible = FALSE;
- }
-
- gtk_list_store_set (widget->priv->list_store,
- &iter,
- CHOOSER_ITEM_IS_VISIBLE_COLUMN, is_visible,
- -1);
-
- out:
- widget->priv->update_separator_idle_id = 0;
- return FALSE;
-}
-
-static void
-queue_update_separator_visibility (GdmChooserWidget *widget)
-{
- if (widget->priv->update_separator_idle_id == 0) {
- g_debug ("GdmChooserWidget: queuing update separator visibility");
-
- widget->priv->update_separator_idle_id =
- g_idle_add ((GSourceFunc) update_separator_visibility, widget);
- }
-}
-
-static gboolean
-update_visible_items (GdmChooserWidget *widget)
-{
- GtkTreePath *path;
- GtkTreePath *end;
- GtkTreeIter iter;
-
- if (! gtk_tree_view_get_visible_range (GTK_TREE_VIEW (widget->priv->items_view), &path, &end)) {
- g_debug ("GdmChooserWidget: Unable to get visible range");
- goto out;
- }
-
- for (; gtk_tree_path_compare (path, end) <= 0; gtk_tree_path_next (path)) {
- char *id;
- gpointer user_data;
- GdmChooserWidgetItemLoadFunc func;
-
- if (! gtk_tree_model_get_iter (GTK_TREE_MODEL (widget->priv->model_sorter), &iter, path))
- break;
-
- id = NULL;
- gtk_tree_model_get (GTK_TREE_MODEL (widget->priv->model_sorter),
- &iter,
- CHOOSER_ID_COLUMN, &id,
- CHOOSER_LOAD_FUNC_COLUMN, &func,
- CHOOSER_LOAD_DATA_COLUMN, &user_data,
- -1);
- if (id != NULL && func != NULL) {
- GtkTreeIter child_iter;
- GtkTreeIter list_iter;
-
- g_debug ("Updating for %s", id);
-
- gtk_tree_model_sort_convert_iter_to_child_iter (widget->priv->model_sorter,
- &child_iter,
- &iter);
-
- gtk_tree_model_filter_convert_iter_to_child_iter (widget->priv->model_filter,
- &list_iter,
- &child_iter);
- /* remove the func so it doesn't need to load again */
- gtk_list_store_set (GTK_LIST_STORE (widget->priv->list_store),
- &list_iter,
- CHOOSER_LOAD_FUNC_COLUMN, NULL,
- -1);
-
- func (widget, id, user_data);
- }
-
- g_free (id);
- }
-
- gtk_tree_path_free (path);
- gtk_tree_path_free (end);
- out:
- widget->priv->update_items_idle_id = 0;
-
- return FALSE;
-}
-
-static void
-set_chooser_list_visible (GdmChooserWidget *widget,
- gboolean is_visible)
-{
- if (widget->priv->list_visible != is_visible) {
- widget->priv->list_visible = is_visible;
- g_object_notify (G_OBJECT (widget), "list-visible");
- }
-}
-
-static gboolean
-update_chooser_visibility (GdmChooserWidget *widget)
-{
- update_visible_items (widget);
-
- if (gdm_chooser_widget_get_number_of_items (widget) > 0) {
- gtk_widget_show (widget->priv->frame);
- set_chooser_list_visible (widget, gtk_widget_get_visible (GTK_WIDGET (widget)));
- } else {
- gtk_widget_hide (widget->priv->frame);
- set_chooser_list_visible (widget, FALSE);
- }
-
- widget->priv->update_visibility_idle_id = 0;
-
- return FALSE;
-}
-
-static inline gboolean
-iters_equal (GtkTreeIter *a,
- GtkTreeIter *b)
-{
- if (a->stamp != b->stamp)
- return FALSE;
-
- if (a->user_data != b->user_data)
- return FALSE;
-
- /* user_data2 and user_data3 are not used in GtkListStore */
-
- return TRUE;
-}
-
-static void
-set_inactive_items_visible (GdmChooserWidget *widget,
- gboolean should_show)
-{
- GtkTreeModel *model;
- GtkTreeModel *view_model;
- char *active_item_id;
- GtkTreeIter active_item_iter;
- GtkTreeIter iter;
-
- g_debug ("setting inactive items visible");
-
- active_item_id = get_active_item_id (widget, &active_item_iter);
- if (active_item_id == NULL) {
- g_debug ("GdmChooserWidget: No active item set");
- }
-
- model = GTK_TREE_MODEL (widget->priv->list_store);
-
- if (!gtk_tree_model_get_iter_first (model, &iter)) {
- goto out;
- }
-
- /* unset tree view model to hide row add/remove signals from gail */
- view_model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget->priv->items_view));
- g_object_ref (view_model);
- gtk_tree_view_set_model (GTK_TREE_VIEW (widget->priv->items_view), NULL);
-
- g_debug ("GdmChooserWidget: Setting inactive items visible: %s", should_show ? "true" : "false");
-
- do {
- if (active_item_id == NULL || !iters_equal (&active_item_iter, &iter)) {
- /* inactive item */
- gtk_list_store_set (widget->priv->list_store,
- &iter,
- CHOOSER_ITEM_IS_VISIBLE_COLUMN, should_show,
- -1);
- } else {
- /* always show the active item */
- gtk_list_store_set (widget->priv->list_store,
- &iter,
- CHOOSER_ITEM_IS_VISIBLE_COLUMN, TRUE,
- -1);
- }
- } while (gtk_tree_model_iter_next (model, &iter));
-
- gtk_tree_view_set_model (GTK_TREE_VIEW (widget->priv->items_view), view_model);
- g_object_unref (view_model);
-
- queue_update_separator_visibility (widget);
-
- out:
- g_free (active_item_id);
-}
-
-static void
-on_shrink_animation_complete (GdmScrollableWidget *scrollable_widget,
- GdmChooserWidget *widget)
-{
- g_assert (widget->priv->state == GDM_CHOOSER_WIDGET_STATE_SHRINKING);
-
- g_debug ("GdmChooserWidget: shrink complete");
-
- widget->priv->active_row_normalized_position = 0.5;
- set_inactive_items_visible (GDM_CHOOSER_WIDGET (widget), FALSE);
- gtk_tree_view_set_enable_search (GTK_TREE_VIEW (widget->priv->items_view), FALSE);
- widget->priv->state = GDM_CHOOSER_WIDGET_STATE_SHRUNK;
-
- queue_update_separator_visibility (widget);
-
- if (widget->priv->emit_activated_after_resize_animation) {
- g_signal_emit (widget, signals[ACTIVATED], 0);
- widget->priv->emit_activated_after_resize_animation = FALSE;
- }
-}
-
-static int
-get_height_of_row_at_path (GdmChooserWidget *widget,
- GtkTreePath *path)
-{
- GdkRectangle area;
-
- gtk_tree_view_get_background_area (GTK_TREE_VIEW (widget->priv->items_view),
- path, NULL, &area);
-
- return area.height;
-}
-
-static double
-get_normalized_position_of_row_at_path (GdmChooserWidget *widget,
- GtkTreePath *path)
-{
- GdkRectangle area_of_row_at_path;
- GdkRectangle area_of_visible_rows;
- GtkAllocation items_view_allocation;
-
- gtk_widget_get_allocation (widget->priv->items_view, &items_view_allocation);
-
- gtk_tree_view_get_background_area (GTK_TREE_VIEW (widget->priv->items_view),
- path, NULL, &area_of_row_at_path);
-
- gtk_tree_view_convert_tree_to_widget_coords (GTK_TREE_VIEW (widget->priv->items_view),
- area_of_visible_rows.x,
- area_of_visible_rows.y,
- &area_of_visible_rows.x,
- &area_of_visible_rows.y);
- return CLAMP (((double) area_of_row_at_path.y) / items_view_allocation.height, 0.0, 1.0);
-}
-
-static void
-start_shrink_animation (GdmChooserWidget *widget)
-{
- GtkTreePath *active_row_path;
- int active_row_height;
- int number_of_visible_rows;
-
- g_assert (widget->priv->active_row != NULL);
-
- number_of_visible_rows = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (widget->priv->model_sorter), NULL);
-
- if (number_of_visible_rows <= 1) {
- on_shrink_animation_complete (GDM_SCROLLABLE_WIDGET (widget->priv->scrollable_widget),
- widget);
- return;
- }
-
- active_row_path = get_view_path_to_active_row (widget);
- active_row_height = get_height_of_row_at_path (widget, active_row_path);
- widget->priv->active_row_normalized_position = get_normalized_position_of_row_at_path (widget, active_row_path);
- gtk_tree_path_free (active_row_path);
-
- gdm_scrollable_widget_slide_to_height (GDM_SCROLLABLE_WIDGET (widget->priv->scrollable_widget),
- active_row_height,
- (GdmScrollableWidgetSlideStepFunc)
- on_shrink_animation_step, widget,
- (GdmScrollableWidgetSlideDoneFunc)
- on_shrink_animation_complete, widget);
-}
-
-static char *
-get_first_item (GdmChooserWidget *widget)
-{
- GtkTreeModel *model;
- GtkTreeIter iter;
- char *id;
-
- model = GTK_TREE_MODEL (widget->priv->list_store);
-
- if (!gtk_tree_model_get_iter_first (model, &iter)) {
- g_assert_not_reached ();
- }
-
- gtk_tree_model_get (model, &iter,
- CHOOSER_ID_COLUMN, &id, -1);
- return id;
-}
-
-static gboolean
-activate_if_one_item (GdmChooserWidget *widget)
-{
- char *id;
-
- g_debug ("GdmChooserWidget: attempting to activate single item");
-
- if (gdm_chooser_widget_get_number_of_items (widget) != 1) {
- g_debug ("GdmChooserWidget: unable to activate single item - has %d items", gdm_chooser_widget_get_number_of_items (widget));
- return FALSE;
- }
-
- id = get_first_item (widget);
- if (id != NULL) {
- gdm_chooser_widget_set_active_item (widget, id);
- g_free (id);
- }
-
- return FALSE;
-}
-
-static void
-_grab_focus (GtkWidget *widget)
-{
- GtkWidget *foc_widget;
-
- foc_widget = GDM_CHOOSER_WIDGET (widget)->priv->items_view;
- g_debug ("GdmChooserWidget: grabbing focus");
-
- if (gtk_widget_has_focus (foc_widget)) {
- g_debug ("GdmChooserWidget: not grabbing focus - already has it");
- return;
- }
-
- gtk_widget_child_focus (foc_widget, GTK_DIR_TAB_FORWARD);
-}
-
-static void
-queue_update_visible_items (GdmChooserWidget *widget)
-{
- if (widget->priv->update_items_idle_id != 0) {
- g_source_remove (widget->priv->update_items_idle_id);
- }
-
- widget->priv->update_items_idle_id =
- g_timeout_add (100, (GSourceFunc) update_visible_items, widget);
-}
-
-static void
-on_grow_animation_complete (GdmScrollableWidget *scrollable_widget,
- GdmChooserWidget *widget)
-{
- g_assert (widget->priv->state == GDM_CHOOSER_WIDGET_STATE_GROWING);
- widget->priv->state = GDM_CHOOSER_WIDGET_STATE_GROWN;
- gtk_tree_view_set_enable_search (GTK_TREE_VIEW (widget->priv->items_view), TRUE);
- queue_update_visible_items (widget);
-
- _grab_focus (GTK_WIDGET (widget));
-}
-
-static int
-get_number_of_on_screen_rows (GdmChooserWidget *widget)
-{
- GtkTreePath *start_path;
- GtkTreePath *end_path;
- int *start_index;
- int *end_index;
- int number_of_rows;
-
- if (!gtk_tree_view_get_visible_range (GTK_TREE_VIEW (widget->priv->items_view),
- &start_path, &end_path)) {
- return 0;
- }
-
- start_index = gtk_tree_path_get_indices (start_path);
- end_index = gtk_tree_path_get_indices (end_path);
-
- number_of_rows = *end_index - *start_index + 1;
-
- gtk_tree_path_free (start_path);
- gtk_tree_path_free (end_path);
-
- return number_of_rows;
-}
-
-static void
-on_grow_animation_step (GdmScrollableWidget *scrollable_widget,
- double progress,
- int *new_height,
- GdmChooserWidget *widget)
-{
- int number_of_visible_rows;
- int number_of_on_screen_rows;
-
- number_of_visible_rows = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (widget->priv->model_sorter), NULL);
- number_of_on_screen_rows = get_number_of_on_screen_rows (widget);
-
- GtkRequisition scrollable_widget_req;
- gtk_widget_get_requisition (gtk_bin_get_child (GTK_BIN (scrollable_widget)), &scrollable_widget_req);
- *new_height = scrollable_widget_req.height;
-}
-
-static void
-start_grow_animation (GdmChooserWidget *widget)
-{
- GtkRequisition scrollable_widget_req;
- gtk_widget_get_requisition (gtk_bin_get_child (GTK_BIN (widget->priv->scrollable_widget)),
- &scrollable_widget_req);
-
- set_inactive_items_visible (widget, TRUE);
-
- gdm_scrollable_widget_slide_to_height (GDM_SCROLLABLE_WIDGET (widget->priv->scrollable_widget),
- scrollable_widget_req.height,
- (GdmScrollableWidgetSlideStepFunc)
- on_grow_animation_step, widget,
- (GdmScrollableWidgetSlideDoneFunc)
- on_grow_animation_complete, widget);
-}
-
-static void
-skip_resize_animation (GdmChooserWidget *widget)
-{
- if (widget->priv->state == GDM_CHOOSER_WIDGET_STATE_SHRINKING) {
- set_inactive_items_visible (GDM_CHOOSER_WIDGET (widget), FALSE);
- gtk_tree_view_set_enable_search (GTK_TREE_VIEW (widget->priv->items_view), FALSE);
- widget->priv->state = GDM_CHOOSER_WIDGET_STATE_SHRUNK;
- } else if (widget->priv->state == GDM_CHOOSER_WIDGET_STATE_GROWING) {
- set_inactive_items_visible (GDM_CHOOSER_WIDGET (widget), TRUE);
- gtk_tree_view_set_enable_search (GTK_TREE_VIEW (widget->priv->items_view), TRUE);
- widget->priv->state = GDM_CHOOSER_WIDGET_STATE_GROWN;
- _grab_focus (GTK_WIDGET (widget));
- }
-}
-
-static void
-gdm_chooser_widget_grow (GdmChooserWidget *widget)
-{
- if (widget->priv->state == GDM_CHOOSER_WIDGET_STATE_GROWN) {
- g_debug ("GdmChooserWidget: Asking for grow but already grown");
- return;
- }
-
- if (widget->priv->state == GDM_CHOOSER_WIDGET_STATE_SHRINKING) {
- gdm_scrollable_widget_stop_sliding (GDM_SCROLLABLE_WIDGET (widget->priv->scrollable_widget));
- }
-
- gtk_alignment_set (GTK_ALIGNMENT (widget->priv->frame_alignment),
- 0.0, 0.0, 1.0, 1.0);
-
- set_frame_text (widget, widget->priv->inactive_text);
-
- widget->priv->state = GDM_CHOOSER_WIDGET_STATE_GROWING;
-
- if (gtk_widget_get_visible (GTK_WIDGET (widget))) {
- start_grow_animation (widget);
- } else {
- skip_resize_animation (widget);
- }
-}
-
-static gboolean
-move_cursor_to_top (GdmChooserWidget *widget)
-{
- GtkTreeModel *model;
- GtkTreePath *path;
- GtkTreeIter iter;
-
- model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget->priv->items_view));
- path = gtk_tree_path_new_first ();
- if (gtk_tree_model_get_iter (model, &iter, path)) {
- gtk_tree_view_set_cursor (GTK_TREE_VIEW (widget->priv->items_view),
- path,
- NULL,
- FALSE);
-
- gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (widget->priv->items_view),
- path,
- NULL,
- TRUE,
- 0.5,
- 0.0);
-
- }
- gtk_tree_path_free (path);
-
- widget->priv->update_cursor_idle_id = 0;
- return FALSE;
-}
-
-static gboolean
-clear_selection (GdmChooserWidget *widget)
-{
- GtkTreeSelection *selection;
- GtkWidget *window;
-
- g_debug ("GdmChooserWidget: clearing selection");
-
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget->priv->items_view));
- gtk_tree_selection_unselect_all (selection);
-
- window = gtk_widget_get_ancestor (GTK_WIDGET (widget), GTK_TYPE_WINDOW);
-
- if (window != NULL) {
- gtk_window_set_focus (GTK_WINDOW (window), NULL);
- }
-
- return FALSE;
-}
-
-static void
-gdm_chooser_widget_shrink (GdmChooserWidget *widget)
-{
- g_assert (widget->priv->should_hide_inactive_items == TRUE);
-
- if (widget->priv->state == GDM_CHOOSER_WIDGET_STATE_GROWING) {
- gdm_scrollable_widget_stop_sliding (GDM_SCROLLABLE_WIDGET (widget->priv->scrollable_widget));
- }
-
- set_frame_text (widget, widget->priv->active_text);
-
- gtk_alignment_set (GTK_ALIGNMENT (widget->priv->frame_alignment),
- 0.0, 0.0, 1.0, 0.0);
-
- clear_selection (widget);
-
- widget->priv->state = GDM_CHOOSER_WIDGET_STATE_SHRINKING;
-
- if (gtk_widget_get_visible (GTK_WIDGET (widget))) {
- start_shrink_animation (widget);
- } else {
- skip_resize_animation (widget);
- }
-}
-
-static void
-activate_from_row (GdmChooserWidget *widget,
- GtkTreeRowReference *row)
-{
- g_assert (row != NULL);
- g_assert (gtk_tree_row_reference_valid (row));
-
- if (widget->priv->active_row != NULL) {
- gtk_tree_row_reference_free (widget->priv->active_row);
- widget->priv->active_row = NULL;
- }
-
- widget->priv->active_row = gtk_tree_row_reference_copy (row);
-
- if (widget->priv->should_hide_inactive_items) {
- g_debug ("GdmChooserWidget: will emit activated after resize");
- widget->priv->emit_activated_after_resize_animation = TRUE;
- gdm_chooser_widget_shrink (widget);
- } else {
- g_debug ("GdmChooserWidget: emitting activated");
- g_signal_emit (widget, signals[ACTIVATED], 0);
- }
-}
-
-static void
-deactivate (GdmChooserWidget *widget)
-{
- GtkTreePath *path;
-
- if (widget->priv->active_row == NULL) {
- return;
- }
-
- path = get_view_path_to_active_row (widget);
-
- gtk_tree_row_reference_free (widget->priv->active_row);
- widget->priv->active_row = NULL;
-
- gtk_tree_view_set_cursor (GTK_TREE_VIEW (widget->priv->items_view),
- path, NULL, FALSE);
- gtk_tree_path_free (path);
-
- if (widget->priv->state != GDM_CHOOSER_WIDGET_STATE_GROWN) {
- gdm_chooser_widget_grow (widget);
- } else {
- queue_update_visible_items (widget);
- }
-
- g_signal_emit (widget, signals[DEACTIVATED], 0);
-}
-
-void
-gdm_chooser_widget_activate_selected_item (GdmChooserWidget *widget)
-{
- GtkTreeRowReference *row;
- gboolean is_already_active;
- GtkTreePath *path;
- GtkTreeModel *model;
-
- row = NULL;
- model = GTK_TREE_MODEL (widget->priv->list_store);
- is_already_active = FALSE;
-
- path = NULL;
-
- get_selected_list_path (widget, &path);
- if (path == NULL) {
- g_debug ("GdmChooserWidget: no row selected");
- return;
- }
-
- if (widget->priv->active_row != NULL) {
- GtkTreePath *active_path;
-
- active_path = gtk_tree_row_reference_get_path (widget->priv->active_row);
-
- if (gtk_tree_path_compare (path, active_path) == 0) {
- is_already_active = TRUE;
- }
- gtk_tree_path_free (active_path);
- }
- g_assert (path != NULL);
- row = gtk_tree_row_reference_new (model, path);
- gtk_tree_path_free (path);
-
- if (!is_already_active) {
- activate_from_row (widget, row);
- } else {
- g_debug ("GdmChooserWidget: row is already active");
- }
- gtk_tree_row_reference_free (row);
-}
-
-void
-gdm_chooser_widget_set_active_item (GdmChooserWidget *widget,
- const char *id)
-{
- g_return_if_fail (GDM_IS_CHOOSER_WIDGET (widget));
-
- g_debug ("GdmChooserWidget: setting active item '%s'",
- id ? id : "(null)");
-
- if (id != NULL) {
- activate_from_item_id (widget, id);
- } else {
- deactivate (widget);
- }
-}
-
-static void
-gdm_chooser_widget_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GdmChooserWidget *self;
-
- self = GDM_CHOOSER_WIDGET (object);
-
- switch (prop_id) {
-
- case PROP_INACTIVE_TEXT:
- g_free (self->priv->inactive_text);
- self->priv->inactive_text = g_value_dup_string (value);
-
- if (self->priv->active_row == NULL) {
- set_frame_text (self, self->priv->inactive_text);
- }
- break;
-
- case PROP_ACTIVE_TEXT:
- g_free (self->priv->active_text);
- self->priv->active_text = g_value_dup_string (value);
-
- if (self->priv->active_row != NULL) {
- set_frame_text (self, self->priv->active_text);
- }
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gdm_chooser_widget_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GdmChooserWidget *self;
-
- self = GDM_CHOOSER_WIDGET (object);
-
- switch (prop_id) {
- case PROP_INACTIVE_TEXT:
- g_value_set_string (value, self->priv->inactive_text);
- break;
-
- case PROP_ACTIVE_TEXT:
- g_value_set_string (value, self->priv->active_text);
- break;
- case PROP_LIST_VISIBLE:
- g_value_set_boolean (value, self->priv->list_visible);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gdm_chooser_widget_dispose (GObject *object)
-{
- GdmChooserWidget *widget;
-
- widget = GDM_CHOOSER_WIDGET (object);
-
- if (widget->priv->update_items_idle_id > 0) {
- g_source_remove (widget->priv->update_items_idle_id);
- widget->priv->update_items_idle_id = 0;
- }
-
- if (widget->priv->update_separator_idle_id > 0) {
- g_source_remove (widget->priv->update_separator_idle_id);
- widget->priv->update_separator_idle_id = 0;
- }
-
- if (widget->priv->update_visibility_idle_id > 0) {
- g_source_remove (widget->priv->update_visibility_idle_id);
- widget->priv->update_visibility_idle_id = 0;
- }
-
- if (widget->priv->update_cursor_idle_id > 0) {
- g_source_remove (widget->priv->update_cursor_idle_id);
- widget->priv->update_cursor_idle_id = 0;
- }
-
- if (widget->priv->separator_row != NULL) {
- gtk_tree_row_reference_free (widget->priv->separator_row);
- widget->priv->separator_row = NULL;
- }
-
- if (widget->priv->active_row != NULL) {
- gtk_tree_row_reference_free (widget->priv->active_row);
- widget->priv->active_row = NULL;
- }
-
- if (widget->priv->inactive_text != NULL) {
- g_free (widget->priv->inactive_text);
- widget->priv->inactive_text = NULL;
- }
-
- if (widget->priv->active_text != NULL) {
- g_free (widget->priv->active_text);
- widget->priv->active_text = NULL;
- }
-
- if (widget->priv->in_use_message != NULL) {
- g_free (widget->priv->in_use_message);
- widget->priv->in_use_message = NULL;
- }
-
- G_OBJECT_CLASS (gdm_chooser_widget_parent_class)->dispose (object);
-}
-
-static void
-gdm_chooser_widget_hide (GtkWidget *widget)
-{
- skip_resize_animation (GDM_CHOOSER_WIDGET (widget));
- GTK_WIDGET_CLASS (gdm_chooser_widget_parent_class)->hide (widget);
-}
-
-static void
-gdm_chooser_widget_show (GtkWidget *widget)
-{
- skip_resize_animation (GDM_CHOOSER_WIDGET (widget));
-
- GTK_WIDGET_CLASS (gdm_chooser_widget_parent_class)->show (widget);
-}
-
-static void
-gdm_chooser_widget_map (GtkWidget *widget)
-{
- queue_update_visible_items (GDM_CHOOSER_WIDGET (widget));
-
- GTK_WIDGET_CLASS (gdm_chooser_widget_parent_class)->map (widget);
-}
-
-static void
-gdm_chooser_widget_size_allocate (GtkWidget *widget,
- GtkAllocation *allocation)
-{
- GdmChooserWidget *chooser_widget;
-
- GTK_WIDGET_CLASS (gdm_chooser_widget_parent_class)->size_allocate (widget, allocation);
-
- chooser_widget = GDM_CHOOSER_WIDGET (widget);
-
-}
-
-static gboolean
-gdm_chooser_widget_focus (GtkWidget *widget,
- GtkDirectionType direction)
-{
- /* Since we only have one focusable child (the tree view),
- * no matter which direction we're going the rules are the
- * same:
- *
- * 1) if it's aready got focus, return FALSE to surrender
- * that focus.
- * 2) if it doesn't already have focus, then grab it
- */
- if (gtk_container_get_focus_child (GTK_CONTAINER (widget)) != NULL) {
- g_debug ("GdmChooserWidget: not focusing - focus child not null");
- return FALSE;
- }
-
- _grab_focus (widget);
-
- return TRUE;
-}
-
-static gboolean
-gdm_chooser_widget_focus_in_event (GtkWidget *widget,
- GdkEventFocus *focus_event)
-{
- /* We don't ever want the chooser widget itself to have focus.
- * Focus should always go to the tree view.
- */
- _grab_focus (widget);
-
- return FALSE;
-}
-
-static void
-gdm_chooser_widget_class_init (GdmChooserWidgetClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
-
- object_class->get_property = gdm_chooser_widget_get_property;
- object_class->set_property = gdm_chooser_widget_set_property;
- object_class->dispose = gdm_chooser_widget_dispose;
- object_class->finalize = gdm_chooser_widget_finalize;
- widget_class->size_allocate = gdm_chooser_widget_size_allocate;
- widget_class->hide = gdm_chooser_widget_hide;
- widget_class->show = gdm_chooser_widget_show;
- widget_class->map = gdm_chooser_widget_map;
- widget_class->focus = gdm_chooser_widget_focus;
- widget_class->focus_in_event = gdm_chooser_widget_focus_in_event;
-
- signals [LOADED] = g_signal_new ("loaded",
- G_TYPE_FROM_CLASS (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GdmChooserWidgetClass, loaded),
- NULL,
- NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE,
- 0);
-
- signals [ACTIVATED] = g_signal_new ("activated",
- G_TYPE_FROM_CLASS (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GdmChooserWidgetClass, activated),
- NULL,
- NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE,
- 0);
-
- signals [DEACTIVATED] = g_signal_new ("deactivated",
- G_TYPE_FROM_CLASS (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GdmChooserWidgetClass, deactivated),
- NULL,
- NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE,
- 0);
-
- g_object_class_install_property (object_class,
- PROP_INACTIVE_TEXT,
- g_param_spec_string ("inactive-text",
- _("Inactive Text"),
- _("The text to use in the label if the "
- "user hasn't picked an item yet"),
- NULL,
- (G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT)));
- g_object_class_install_property (object_class,
- PROP_ACTIVE_TEXT,
- g_param_spec_string ("active-text",
- _("Active Text"),
- _("The text to use in the label if the "
- "user has picked an item"),
- NULL,
- (G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT)));
-
- g_object_class_install_property (object_class,
- PROP_LIST_VISIBLE,
- g_param_spec_boolean ("list-visible",
- _("List Visible"),
- _("Whether the chooser list is visible"),
- FALSE,
- G_PARAM_READABLE));
-
- g_type_class_add_private (klass, sizeof (GdmChooserWidgetPrivate));
-}
-
-static void
-on_row_activated (GtkTreeView *tree_view,
- GtkTreePath *tree_path,
- GtkTreeViewColumn *tree_column,
- GdmChooserWidget *widget)
-{
- char *path_str;
-
- path_str = gtk_tree_path_to_string (tree_path);
- g_debug ("GdmChooserWidget: row activated '%s'", path_str ? path_str : "(null)");
- g_free (path_str);
- gdm_chooser_widget_activate_selected_item (widget);
-}
-
-static gboolean
-path_is_separator (GdmChooserWidget *widget,
- GtkTreeModel *model,
- GtkTreePath *path)
-{
- GtkTreePath *separator_path;
- GtkTreePath *translated_path;
- gboolean is_separator;
-
- separator_path = gtk_tree_row_reference_get_path (widget->priv->separator_row);
-
- if (separator_path == NULL) {
- return FALSE;
- }
-
- if (model == GTK_TREE_MODEL (widget->priv->model_sorter)) {
- GtkTreePath *filtered_path;
-
- filtered_path = gtk_tree_model_sort_convert_path_to_child_path (widget->priv->model_sorter, path);
-
- translated_path = gtk_tree_model_filter_convert_path_to_child_path (widget->priv->model_filter, filtered_path);
- gtk_tree_path_free (filtered_path);
- } else if (model == GTK_TREE_MODEL (widget->priv->model_filter)) {
- translated_path = gtk_tree_model_filter_convert_path_to_child_path (widget->priv->model_filter, path);
- } else {
- g_assert (model == GTK_TREE_MODEL (widget->priv->list_store));
- translated_path = gtk_tree_path_copy (path);
- }
-
- if (gtk_tree_path_compare (separator_path, translated_path) == 0) {
- is_separator = TRUE;
- } else {
- is_separator = FALSE;
- }
- gtk_tree_path_free (translated_path);
-
- return is_separator;
-}
-
-static int
-gdm_multilingual_collate (const gchar *text_a, const gchar *text_b)
-{
- PangoDirection direction_a;
- PangoDirection direction_b;
- const gchar *p_a;
- const gchar *p_b;
- gchar *org_locale = NULL;
- gchar *sub_a;
- gchar *sub_b;
- gunichar ch_a;
- gunichar ch_b;
- GUnicodeScript script_a;
- GUnicodeScript script_b;
- gboolean composed_alpha_a;
- gboolean composed_alpha_b;
- gboolean all_alpha_a;
- gboolean all_alpha_b;
- int result;
-
- direction_a = pango_find_base_dir (text_a, -1);
- direction_b = pango_find_base_dir (text_b, -1);
- if ((direction_a == PANGO_DIRECTION_LTR ||
- direction_a == PANGO_DIRECTION_NEUTRAL) &&
- direction_b == PANGO_DIRECTION_RTL)
- return -1;
- if (direction_a == PANGO_DIRECTION_RTL &&
- (direction_b == PANGO_DIRECTION_LTR ||
- direction_b == PANGO_DIRECTION_NEUTRAL))
- return 1;
-
- if (!g_get_charset (NULL)) {
- org_locale = g_strdup (setlocale (LC_ALL, NULL));
- if (!setlocale (LC_ALL, "en_US.UTF-8")) {
- setlocale (LC_ALL, org_locale);
- g_free (org_locale);
- org_locale = NULL;
- }
- }
-
- result = 0;
- all_alpha_a = all_alpha_b = TRUE;
- for (p_a = text_a, p_b = text_b;
- p_a && *p_a && p_b && *p_b;
- p_a = g_utf8_next_char (p_a), p_b = g_utf8_next_char (p_b)) {
- ch_a = g_utf8_get_char (p_a);
- ch_b = g_utf8_get_char (p_b);
- script_a = g_unichar_get_script (ch_a);
- script_b = g_unichar_get_script (ch_b);
- composed_alpha_a = (script_a == G_UNICODE_SCRIPT_LATIN ||
- script_a == G_UNICODE_SCRIPT_GREEK ||
- script_a == G_UNICODE_SCRIPT_CYRILLIC );
- composed_alpha_b = (script_b == G_UNICODE_SCRIPT_LATIN ||
- script_b == G_UNICODE_SCRIPT_GREEK ||
- script_b == G_UNICODE_SCRIPT_CYRILLIC );
- all_alpha_a &= composed_alpha_a;
- all_alpha_b &= composed_alpha_b;
- if (all_alpha_a && !composed_alpha_b &&
- ch_b >= 0x530) {
- result = -1;
- break;
- } else if (!composed_alpha_a && all_alpha_b &&
- ch_a >= 0x530) {
- result = 1;
- break;
- } else if (ch_a != ch_b) {
- sub_a = g_strndup (text_a, g_utf8_next_char (p_a) - text_a);
- sub_b = g_strndup (text_b, g_utf8_next_char (p_b) - text_b);
- result = g_utf8_collate (sub_a, sub_b);
- g_free (sub_a);
- g_free (sub_b);
- if (result != 0) {
- break;
- }
- }
- }
- if (result != 0) {
- if (org_locale) {
- setlocale (LC_ALL, org_locale);
- g_free (org_locale);
- org_locale = NULL;
- }
- return result;
- }
- if (org_locale) {
- setlocale (LC_ALL, org_locale);
- g_free (org_locale);
- org_locale = NULL;
- }
- return g_utf8_collate (text_a, text_b);
-}
-
-static int
-compare_item (GtkTreeModel *model,
- GtkTreeIter *a,
- GtkTreeIter *b,
- gpointer data)
-{
- GdmChooserWidget *widget;
- char *name_a;
- char *name_b;
- gulong prio_a;
- gulong prio_b;
- gboolean is_separate_a;
- gboolean is_separate_b;
- int result;
- int direction;
- GtkTreeIter *separator_iter;
- char *id;
- PangoAttrList *attrs;
-
- g_assert (GDM_IS_CHOOSER_WIDGET (data));
-
- widget = GDM_CHOOSER_WIDGET (data);
-
- separator_iter = NULL;
- if (widget->priv->separator_row != NULL) {
-
- GtkTreePath *path_a;
- GtkTreePath *path_b;
-
- path_a = gtk_tree_model_get_path (model, a);
- path_b = gtk_tree_model_get_path (model, b);
-
- if (path_is_separator (widget, model, path_a)) {
- separator_iter = a;
- } else if (path_is_separator (widget, model, path_b)) {
- separator_iter = b;
- }
-
- gtk_tree_path_free (path_a);
- gtk_tree_path_free (path_b);
- }
-
- name_a = NULL;
- is_separate_a = FALSE;
- if (separator_iter != a) {
- gtk_tree_model_get (model, a,
- CHOOSER_NAME_COLUMN, &name_a,
- CHOOSER_PRIORITY_COLUMN, &prio_a,
- CHOOSER_ITEM_IS_SEPARATED_COLUMN, &is_separate_a,
- -1);
- }
-
- name_b = NULL;
- is_separate_b = FALSE;
- if (separator_iter != b) {
- gtk_tree_model_get (model, b,
- CHOOSER_NAME_COLUMN, &name_b,
- CHOOSER_ID_COLUMN, &id,
- CHOOSER_PRIORITY_COLUMN, &prio_b,
- CHOOSER_ITEM_IS_SEPARATED_COLUMN, &is_separate_b,
- -1);
- }
-
- if (widget->priv->separator_position == GDM_CHOOSER_WIDGET_POSITION_TOP) {
- direction = -1;
- } else {
- direction = 1;
- }
-
- if (separator_iter == b) {
- result = is_separate_a? 1 : -1;
- result *= direction;
- } else if (separator_iter == a) {
- result = is_separate_b? -1 : 1;
- result *= direction;
- } else if (is_separate_b == is_separate_a) {
- if (prio_a == prio_b) {
- char *text_a;
- char *text_b;
-
- text_a = NULL;
- text_b = NULL;
- pango_parse_markup (name_a, -1, 0, &attrs, &text_a, NULL, NULL);
- if (text_a == NULL) {
- g_debug ("GdmChooserWidget: unable to parse markup: '%s'", name_a);
- }
- pango_parse_markup (name_b, -1, 0, &attrs, &text_b, NULL, NULL);
- if (text_b == NULL) {
- g_debug ("GdmChooserWidget: unable to parse markup: '%s'", name_b);
- }
- if (text_a != NULL && text_b != NULL) {
- result = gdm_multilingual_collate (text_a, text_b);
- } else {
- result = gdm_multilingual_collate (name_a, name_b);
- }
- g_free (text_a);
- g_free (text_b);
- } else if (prio_a > prio_b) {
- result = -1;
- } else {
- result = 1;
- }
- } else {
- result = is_separate_a - is_separate_b;
- result *= direction;
- }
-
- g_free (name_a);
- g_free (name_b);
-
- return result;
-}
-
-static void
-name_cell_data_func (GtkTreeViewColumn *tree_column,
- GtkCellRenderer *cell,
- GtkTreeModel *model,
- GtkTreeIter *iter,
- GdmChooserWidget *widget)
-{
- gboolean is_in_use;
- char *name;
- char *markup;
-
- name = NULL;
- gtk_tree_model_get (model,
- iter,
- CHOOSER_ITEM_IS_IN_USE_COLUMN, &is_in_use,
- CHOOSER_NAME_COLUMN, &name,
- -1);
-
- if (is_in_use) {
- markup = g_strdup_printf ("<b>%s</b>\n"
- "<i><span size=\"x-small\">%s</span></i>",
- name ? name : "(null)", widget->priv->in_use_message);
- } else {
- markup = g_strdup_printf ("%s", name ? name : "(null)");
- }
- g_free (name);
-
- g_object_set (cell, "markup", markup, NULL);
- g_free (markup);
-}
-
-static void
-check_cell_data_func (GtkTreeViewColumn *tree_column,
- GtkCellRenderer *cell,
- GtkTreeModel *model,
- GtkTreeIter *iter,
- GdmChooserWidget *widget)
-{
- gboolean is_in_use;
- GdkPixbuf *pixbuf;
-
- gtk_tree_model_get (model,
- iter,
- CHOOSER_ITEM_IS_IN_USE_COLUMN, &is_in_use,
- -1);
-
- if (is_in_use) {
- pixbuf = widget->priv->is_in_use_pixbuf;
- } else {
- pixbuf = NULL;
- }
-
- g_object_set (cell, "pixbuf", pixbuf, NULL);
-}
-
-static GdkPixbuf *
-get_is_in_use_pixbuf (GdmChooserWidget *widget)
-{
- GtkIconTheme *theme;
- GdkPixbuf *pixbuf;
-
- theme = gtk_icon_theme_get_default ();
- pixbuf = gtk_icon_theme_load_icon (theme,
- "emblem-default",
- GDM_CHOOSER_WIDGET_DEFAULT_ICON_SIZE / 3,
- 0,
- NULL);
-
- return pixbuf;
-}
-
-static gboolean
-separator_func (GtkTreeModel *model,
- GtkTreeIter *iter,
- gpointer data)
-{
- GdmChooserWidget *widget;
- GtkTreePath *path;
- gboolean is_separator;
-
- g_assert (GDM_IS_CHOOSER_WIDGET (data));
-
- widget = GDM_CHOOSER_WIDGET (data);
-
- g_assert (widget->priv->separator_row != NULL);
-
- path = gtk_tree_model_get_path (model, iter);
-
- is_separator = path_is_separator (widget, model, path);
-
- gtk_tree_path_free (path);
-
- return is_separator;
-}
-
-static void
-add_separator (GdmChooserWidget *widget)
-{
- GtkTreeIter iter;
- GtkTreeModel *model;
- GtkTreePath *path;
-
- g_assert (widget->priv->separator_row == NULL);
-
- model = GTK_TREE_MODEL (widget->priv->list_store);
-
- gtk_list_store_insert_with_values (widget->priv->list_store,
- &iter, 0,
- CHOOSER_ID_COLUMN, "-", -1);
- path = gtk_tree_model_get_path (model, &iter);
- widget->priv->separator_row = gtk_tree_row_reference_new (model, path);
- gtk_tree_path_free (path);
-}
-
-static gboolean
-update_column_visibility (GdmChooserWidget *widget)
-{
- g_debug ("GdmChooserWidget: updating column visibility");
-
- if (widget->priv->number_of_rows_with_images > 0) {
- gtk_tree_view_column_set_visible (widget->priv->image_column,
- TRUE);
- } else {
- gtk_tree_view_column_set_visible (widget->priv->image_column,
- FALSE);
- }
- if (widget->priv->number_of_rows_with_status > 0) {
- gtk_tree_view_column_set_visible (widget->priv->status_column,
- TRUE);
- } else {
- gtk_tree_view_column_set_visible (widget->priv->status_column,
- FALSE);
- }
-
- return FALSE;
-}
-
-static void
-clear_canceled_visibility_update (GdmChooserWidget *widget)
-{
- widget->priv->update_idle_id = 0;
-}
-
-static void
-queue_column_visibility_update (GdmChooserWidget *widget)
-{
- if (widget->priv->update_idle_id == 0) {
- widget->priv->update_idle_id =
- g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
- (GSourceFunc)
- update_column_visibility, widget,
- (GDestroyNotify)
- clear_canceled_visibility_update);
- }
-}
-
-static void
-on_row_changed (GtkTreeModel *model,
- GtkTreePath *path,
- GtkTreeIter *iter,
- GdmChooserWidget *widget)
-{
- queue_column_visibility_update (widget);
-}
-
-static void
-add_frame (GdmChooserWidget *widget)
-{
- widget->priv->frame = gtk_frame_new (NULL);
- gtk_frame_set_shadow_type (GTK_FRAME (widget->priv->frame),
- GTK_SHADOW_NONE);
- gtk_widget_show (widget->priv->frame);
- gtk_container_add (GTK_CONTAINER (widget), widget->priv->frame);
-
- widget->priv->frame_alignment = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
- gtk_widget_show (widget->priv->frame_alignment);
- gtk_container_add (GTK_CONTAINER (widget->priv->frame),
- widget->priv->frame_alignment);
-}
-
-static gboolean
-on_button_release (GtkTreeView *items_view,
- GdkEventButton *event,
- GdmChooserWidget *widget)
-{
- GtkTreeModel *model;
- GtkTreeIter iter;
- GtkTreeSelection *selection;
-
- if (!widget->priv->should_hide_inactive_items) {
- return FALSE;
- }
-
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget->priv->items_view));
- if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
- GtkTreePath *path;
-
- path = gtk_tree_model_get_path (model, &iter);
- gtk_tree_view_row_activated (GTK_TREE_VIEW (items_view),
- path, NULL);
- gtk_tree_path_free (path);
- }
-
- return FALSE;
-}
-
-static gboolean
-search_equal_func (GtkTreeModel *model,
- int column,
- const char *key,
- GtkTreeIter *iter,
- GdmChooserWidget *widget)
-{
- char *id;
- char *name;
- char *key_folded;
- gboolean ret;
-
- if (key == NULL) {
- return FALSE;
- }
-
- ret = TRUE;
- id = NULL;
- name = NULL;
-
- key_folded = g_utf8_casefold (key, -1);
-
- gtk_tree_model_get (model,
- iter,
- CHOOSER_ID_COLUMN, &id,
- CHOOSER_NAME_COLUMN, &name,
- -1);
- if (name != NULL) {
- char *name_folded;
-
- name_folded = g_utf8_casefold (name, -1);
- ret = !g_str_has_prefix (name_folded, key_folded);
- g_free (name_folded);
-
- if (!ret) {
- goto out;
- }
- }
-
- if (id != NULL) {
- char *id_folded;
-
-
- id_folded = g_utf8_casefold (id, -1);
- ret = !g_str_has_prefix (id_folded, key_folded);
- g_free (id_folded);
-
- if (!ret) {
- goto out;
- }
- }
- out:
- g_free (id);
- g_free (name);
- g_free (key_folded);
-
- return ret;
-}
-
-static void
-search_position_func (GtkTreeView *tree_view,
- GtkWidget *search_dialog,
- gpointer user_data)
-{
- /* Move it outside the region viewable by
- * the user.
- * FIXME: This is pretty inelegant.
- *
- * It might be nicer to make a GdmOffscreenBin
- * widget that we pack into the chooser widget below
- * the frame but gets redirected offscreen.
- *
- * Then we would add a GtkEntry to the bin and set
- * that entry as the search entry for the tree view
- * instead of using a search position func.
- */
- gtk_window_move (GTK_WINDOW (search_dialog), -24000, -24000);
-}
-
-static void
-on_selection_changed (GtkTreeSelection *selection,
- GdmChooserWidget *widget)
-{
- GtkTreePath *path;
-
- get_selected_list_path (widget, &path);
- if (path != NULL) {
- char *path_str;
- path_str = gtk_tree_path_to_string (path);
- g_debug ("GdmChooserWidget: selection change to list path '%s'", path_str);
- g_free (path_str);
- } else {
- g_debug ("GdmChooserWidget: selection cleared");
- }
-}
-
-static void
-on_adjustment_value_changed (GtkAdjustment *adjustment,
- GdmChooserWidget *widget)
-{
- queue_update_visible_items (widget);
-}
-
-static void
-gdm_chooser_widget_init (GdmChooserWidget *widget)
-{
- GtkTreeViewColumn *column;
- GtkTreeSelection *selection;
- GtkCellRenderer *renderer;
- GtkAdjustment *adjustment;
-
- widget->priv = GDM_CHOOSER_WIDGET_GET_PRIVATE (widget);
-
- /* Even though, we're a container and also don't ever take
- * focus for ourselve, we set CAN_FOCUS so that gtk_widget_grab_focus
- * works on us. We then override grab_focus requests to
- * be redirected our internal tree view
- */
- gtk_widget_set_can_focus (GTK_WIDGET (widget), TRUE);
-
- gtk_alignment_set_padding (GTK_ALIGNMENT (widget), 0, 0, 0, 0);
-
- add_frame (widget);
-
- widget->priv->scrollable_widget = gdm_scrollable_widget_new ();
- gtk_widget_show (widget->priv->scrollable_widget);
- gtk_container_add (GTK_CONTAINER (widget->priv->frame_alignment),
- widget->priv->scrollable_widget);
-
- widget->priv->items_view = gtk_tree_view_new ();
- gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (widget->priv->items_view),
- FALSE);
- g_signal_connect (widget->priv->items_view,
- "row-activated",
- G_CALLBACK (on_row_activated),
- widget);
-
- gtk_tree_view_set_search_equal_func (GTK_TREE_VIEW (widget->priv->items_view),
- (GtkTreeViewSearchEqualFunc)search_equal_func,
- widget,
- NULL);
-
- gtk_tree_view_set_search_position_func (GTK_TREE_VIEW (widget->priv->items_view),
- (GtkTreeViewSearchPositionFunc)search_position_func,
- widget,
- NULL);
-
- /* hack to make single-click activate work
- */
- g_signal_connect_after (widget->priv->items_view,
- "button-release-event",
- G_CALLBACK (on_button_release),
- widget);
-
- gtk_widget_show (widget->priv->items_view);
- gtk_container_add (GTK_CONTAINER (widget->priv->scrollable_widget),
- widget->priv->items_view);
-
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget->priv->items_view));
- gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
-
- g_signal_connect (selection, "changed", G_CALLBACK (on_selection_changed), widget);
-
- g_assert (NUMBER_OF_CHOOSER_COLUMNS == 13);
- widget->priv->list_store = gtk_list_store_new (NUMBER_OF_CHOOSER_COLUMNS,
- GDK_TYPE_PIXBUF,
- G_TYPE_STRING,
- G_TYPE_STRING,
- G_TYPE_ULONG,
- G_TYPE_BOOLEAN,
- G_TYPE_BOOLEAN,
- G_TYPE_BOOLEAN,
- G_TYPE_DOUBLE,
- G_TYPE_DOUBLE,
- G_TYPE_DOUBLE,
- G_TYPE_STRING,
- G_TYPE_POINTER,
- G_TYPE_POINTER);
-
- widget->priv->model_filter = GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (GTK_TREE_MODEL (widget->priv->list_store), NULL));
-
- gtk_tree_model_filter_set_visible_column (widget->priv->model_filter,
- CHOOSER_ITEM_IS_VISIBLE_COLUMN);
- g_signal_connect (G_OBJECT (widget->priv->model_filter), "row-changed",
- G_CALLBACK (on_row_changed), widget);
-
- widget->priv->model_sorter = GTK_TREE_MODEL_SORT (gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (widget->priv->model_filter)));
-
- gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (widget->priv->model_sorter),
- CHOOSER_ID_COLUMN,
- compare_item,
- widget, NULL);
-
- gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (widget->priv->model_sorter),
- CHOOSER_ID_COLUMN,
- GTK_SORT_ASCENDING);
- gtk_tree_view_set_model (GTK_TREE_VIEW (widget->priv->items_view),
- GTK_TREE_MODEL (widget->priv->model_sorter));
- gtk_tree_view_set_row_separator_func (GTK_TREE_VIEW (widget->priv->items_view),
- separator_func,
- widget, NULL);
-
- /* IMAGE COLUMN */
- renderer = gtk_cell_renderer_pixbuf_new ();
- column = gtk_tree_view_column_new ();
- gtk_tree_view_column_pack_start (column, renderer, FALSE);
- gtk_tree_view_append_column (GTK_TREE_VIEW (widget->priv->items_view), column);
- widget->priv->image_column = column;
-
- gtk_tree_view_column_set_attributes (column,
- renderer,
- "pixbuf", CHOOSER_IMAGE_COLUMN,
- NULL);
-
- g_object_set (renderer,
- "xalign", 1.0,
- NULL);
-
- /* NAME COLUMN */
- renderer = gtk_cell_renderer_text_new ();
- column = gtk_tree_view_column_new ();
- gtk_tree_view_column_pack_start (column, renderer, FALSE);
- gtk_tree_view_append_column (GTK_TREE_VIEW (widget->priv->items_view), column);
- gtk_tree_view_column_set_cell_data_func (column,
- renderer,
- (GtkTreeCellDataFunc) name_cell_data_func,
- widget,
- NULL);
-
- gtk_tree_view_set_tooltip_column (GTK_TREE_VIEW (widget->priv->items_view),
- CHOOSER_COMMENT_COLUMN);
-
- /* STATUS COLUMN */
- renderer = gtk_cell_renderer_pixbuf_new ();
- column = gtk_tree_view_column_new ();
- gtk_tree_view_column_pack_start (column, renderer, FALSE);
- gtk_tree_view_append_column (GTK_TREE_VIEW (widget->priv->items_view), column);
- widget->priv->status_column = column;
-
- gtk_tree_view_column_set_cell_data_func (column,
- renderer,
- (GtkTreeCellDataFunc) check_cell_data_func,
- widget,
- NULL);
- widget->priv->is_in_use_pixbuf = get_is_in_use_pixbuf (widget);
-
- renderer = gdm_cell_renderer_timer_new ();
- gtk_tree_view_column_pack_start (column, renderer, FALSE);
- gtk_tree_view_column_add_attribute (column, renderer, "value",
- CHOOSER_TIMER_VALUE_COLUMN);
-
- widget->priv->rows_with_timers =
- g_hash_table_new_full (g_str_hash,
- g_str_equal,
- (GDestroyNotify) g_free,
- (GDestroyNotify)
- gtk_tree_row_reference_free);
-
- add_separator (widget);
- queue_column_visibility_update (widget);
-
- adjustment = gtk_tree_view_get_vadjustment (GTK_TREE_VIEW (widget->priv->items_view));
- g_signal_connect (adjustment, "value-changed", G_CALLBACK (on_adjustment_value_changed), widget);
-}
-
-static void
-gdm_chooser_widget_finalize (GObject *object)
-{
- GdmChooserWidget *widget;
-
- g_return_if_fail (object != NULL);
- g_return_if_fail (GDM_IS_CHOOSER_WIDGET (object));
-
- widget = GDM_CHOOSER_WIDGET (object);
-
- g_return_if_fail (widget->priv != NULL);
-
- g_hash_table_destroy (widget->priv->rows_with_timers);
- widget->priv->rows_with_timers = NULL;
-
- G_OBJECT_CLASS (gdm_chooser_widget_parent_class)->finalize (object);
-}
-
-GtkWidget *
-gdm_chooser_widget_new (const char *inactive_text,
- const char *active_text)
-{
- GObject *object;
-
- object = g_object_new (GDM_TYPE_CHOOSER_WIDGET,
- "inactive-text", inactive_text,
- "active-text", active_text, NULL);
-
- return GTK_WIDGET (object);
-}
-
-void
-gdm_chooser_widget_update_item (GdmChooserWidget *widget,
- const char *id,
- GdkPixbuf *new_image,
- const char *new_name,
- const char *new_comment,
- gulong new_priority,
- gboolean new_in_use,
- gboolean new_is_separate)
-{
- GtkTreeModel *model;
- GtkTreeIter iter;
- GdkPixbuf *image;
- gboolean is_separate;
- gboolean in_use;
-
- g_return_if_fail (GDM_IS_CHOOSER_WIDGET (widget));
-
- model = GTK_TREE_MODEL (widget->priv->list_store);
-
- if (!find_item (widget, id, &iter)) {
- g_critical ("Tried to remove non-existing item from chooser");
- return;
- }
-
- is_separate = FALSE;
- gtk_tree_model_get (model, &iter,
- CHOOSER_IMAGE_COLUMN, &image,
- CHOOSER_ITEM_IS_IN_USE_COLUMN, &in_use,
- CHOOSER_ITEM_IS_SEPARATED_COLUMN, &is_separate,
- -1);
-
- if (image != new_image) {
- if (image == NULL && new_image != NULL) {
- widget->priv->number_of_rows_with_images++;
- } else if (image != NULL && new_image == NULL) {
- widget->priv->number_of_rows_with_images--;
- }
- queue_column_visibility_update (widget);
- }
- if (image != NULL) {
- g_object_unref (image);
- }
-
- if (in_use != new_in_use) {
- if (new_in_use) {
- widget->priv->number_of_rows_with_status++;
- } else {
- widget->priv->number_of_rows_with_status--;
- }
- queue_column_visibility_update (widget);
- }
-
- if (is_separate != new_is_separate) {
- if (new_is_separate) {
- widget->priv->number_of_separated_rows++;
- widget->priv->number_of_normal_rows--;
- } else {
- widget->priv->number_of_separated_rows--;
- widget->priv->number_of_normal_rows++;
- }
- queue_update_separator_visibility (widget);
- }
-
- gtk_list_store_set (widget->priv->list_store,
- &iter,
- CHOOSER_IMAGE_COLUMN, new_image,
- CHOOSER_NAME_COLUMN, new_name,
- CHOOSER_COMMENT_COLUMN, new_comment,
- CHOOSER_PRIORITY_COLUMN, new_priority,
- CHOOSER_ITEM_IS_IN_USE_COLUMN, new_in_use,
- CHOOSER_ITEM_IS_SEPARATED_COLUMN, new_is_separate,
- -1);
-}
-
-static void
-queue_update_chooser_visibility (GdmChooserWidget *widget)
-{
- if (widget->priv->update_visibility_idle_id == 0) {
- widget->priv->update_visibility_idle_id =
- g_idle_add ((GSourceFunc) update_chooser_visibility, widget);
- }
-}
-
-static void
-queue_move_cursor_to_top (GdmChooserWidget *widget)
-{
- if (widget->priv->update_cursor_idle_id == 0) {
- widget->priv->update_cursor_idle_id =
- g_idle_add ((GSourceFunc) move_cursor_to_top, widget);
- }
-}
-
-void
-gdm_chooser_widget_add_item (GdmChooserWidget *widget,
- const char *id,
- GdkPixbuf *image,
- const char *name,
- const char *comment,
- gulong priority,
- gboolean in_use,
- gboolean keep_separate,
- GdmChooserWidgetItemLoadFunc load_func,
- gpointer load_data)
-{
- gboolean is_visible;
-
- g_return_if_fail (GDM_IS_CHOOSER_WIDGET (widget));
-
- if (keep_separate) {
- widget->priv->number_of_separated_rows++;
- } else {
- widget->priv->number_of_normal_rows++;
- }
- queue_update_separator_visibility (widget);
-
- if (in_use) {
- widget->priv->number_of_rows_with_status++;
- queue_column_visibility_update (widget);
- }
-
- if (image != NULL) {
- widget->priv->number_of_rows_with_images++;
- queue_column_visibility_update (widget);
- }
-
- is_visible = widget->priv->active_row == NULL;
-
- gtk_list_store_insert_with_values (widget->priv->list_store,
- NULL, 0,
- CHOOSER_IMAGE_COLUMN, image,
- CHOOSER_NAME_COLUMN, name,
- CHOOSER_COMMENT_COLUMN, comment,
- CHOOSER_PRIORITY_COLUMN, priority,
- CHOOSER_ITEM_IS_IN_USE_COLUMN, in_use,
- CHOOSER_ITEM_IS_SEPARATED_COLUMN, keep_separate,
- CHOOSER_ITEM_IS_VISIBLE_COLUMN, is_visible,
- CHOOSER_ID_COLUMN, id,
- CHOOSER_LOAD_FUNC_COLUMN, load_func,
- CHOOSER_LOAD_DATA_COLUMN, load_data,
- -1);
-
- queue_update_chooser_visibility (widget);
-}
-
-void
-gdm_chooser_widget_remove_item (GdmChooserWidget *widget,
- const char *id)
-{
- GtkTreeModel *model;
- GtkTreeIter iter;
- GdkPixbuf *image;
- gboolean is_separate;
- gboolean is_in_use;
-
- g_return_if_fail (GDM_IS_CHOOSER_WIDGET (widget));
-
- model = GTK_TREE_MODEL (widget->priv->list_store);
-
- if (!find_item (widget, id, &iter)) {
- g_critical ("Tried to remove non-existing item from chooser");
- return;
- }
-
- is_separate = FALSE;
- gtk_tree_model_get (model, &iter,
- CHOOSER_IMAGE_COLUMN, &image,
- CHOOSER_ITEM_IS_IN_USE_COLUMN, &is_in_use,
- CHOOSER_ITEM_IS_SEPARATED_COLUMN, &is_separate,
- -1);
-
- if (image != NULL) {
- widget->priv->number_of_rows_with_images--;
- g_object_unref (image);
- }
-
- if (is_in_use) {
- widget->priv->number_of_rows_with_status--;
- queue_column_visibility_update (widget);
- }
-
- if (is_separate) {
- widget->priv->number_of_separated_rows--;
- } else {
- widget->priv->number_of_normal_rows--;
- }
- queue_update_separator_visibility (widget);
-
- gtk_list_store_remove (widget->priv->list_store, &iter);
-
- queue_update_chooser_visibility (widget);
-}
-
-gboolean
-gdm_chooser_widget_lookup_item (GdmChooserWidget *widget,
- const char *id,
- GdkPixbuf **image,
- char **name,
- char **comment,
- gulong *priority,
- gboolean *is_in_use,
- gboolean *is_separate)
-{
- GtkTreeIter iter;
- char *active_item_id;
-
- g_return_val_if_fail (GDM_IS_CHOOSER_WIDGET (widget), FALSE);
- g_return_val_if_fail (id != NULL, FALSE);
-
- active_item_id = get_active_item_id (widget, &iter);
-
- if (active_item_id == NULL || strcmp (active_item_id, id) != 0) {
- g_free (active_item_id);
- active_item_id = NULL;
-
- if (!find_item (widget, id, &iter)) {
- return FALSE;
- }
- }
- g_free (active_item_id);
-
- if (image != NULL) {
- gtk_tree_model_get (GTK_TREE_MODEL (widget->priv->list_store), &iter,
- CHOOSER_IMAGE_COLUMN, image, -1);
- }
-
- if (name != NULL) {
- gtk_tree_model_get (GTK_TREE_MODEL (widget->priv->list_store), &iter,
- CHOOSER_NAME_COLUMN, name, -1);
- }
-
- if (priority != NULL) {
- gtk_tree_model_get (GTK_TREE_MODEL (widget->priv->list_store), &iter,
- CHOOSER_PRIORITY_COLUMN, priority, -1);
- }
-
- if (is_in_use != NULL) {
- gtk_tree_model_get (GTK_TREE_MODEL (widget->priv->list_store), &iter,
- CHOOSER_ITEM_IS_IN_USE_COLUMN, is_in_use, -1);
- }
-
- if (is_separate != NULL) {
- gtk_tree_model_get (GTK_TREE_MODEL (widget->priv->list_store), &iter,
- CHOOSER_ITEM_IS_SEPARATED_COLUMN, is_separate, -1);
- }
-
- return TRUE;
-}
-
-void
-gdm_chooser_widget_set_item_in_use (GdmChooserWidget *widget,
- const char *id,
- gboolean is_in_use)
-{
- GtkTreeIter iter;
- gboolean was_in_use;
-
- g_return_if_fail (GDM_IS_CHOOSER_WIDGET (widget));
-
- if (!find_item (widget, id, &iter)) {
- return;
- }
-
- gtk_tree_model_get (GTK_TREE_MODEL (widget->priv->list_store), &iter,
- CHOOSER_ITEM_IS_IN_USE_COLUMN, &was_in_use,
- -1);
-
- if (was_in_use != is_in_use) {
-
- if (is_in_use) {
- widget->priv->number_of_rows_with_status++;
- } else {
- widget->priv->number_of_rows_with_status--;
- }
- queue_column_visibility_update (widget);
-
- gtk_list_store_set (widget->priv->list_store,
- &iter,
- CHOOSER_ITEM_IS_IN_USE_COLUMN, is_in_use,
- -1);
-
- }
-}
-
-void
-gdm_chooser_widget_set_item_priority (GdmChooserWidget *widget,
- const char *id,
- gulong priority)
-{
- GtkTreeIter iter;
- gulong was_priority;
-
- g_return_if_fail (GDM_IS_CHOOSER_WIDGET (widget));
-
- if (!find_item (widget, id, &iter)) {
- return;
- }
-
- gtk_tree_model_get (GTK_TREE_MODEL (widget->priv->list_store), &iter,
- CHOOSER_PRIORITY_COLUMN, &was_priority,
- -1);
-
- if (was_priority != priority) {
-
- gtk_list_store_set (widget->priv->list_store,
- &iter,
- CHOOSER_PRIORITY_COLUMN, priority,
- -1);
- gtk_tree_model_filter_refilter (widget->priv->model_filter);
- }
-}
-
-static double
-get_current_time (void)
-{
- const double microseconds_per_second = 1000000.0;
- double timestamp;
- GTimeVal now;
-
- g_get_current_time (&now);
-
- timestamp = ((microseconds_per_second * now.tv_sec) + now.tv_usec) /
- microseconds_per_second;
-
- return timestamp;
-}
-
-static gboolean
-on_timer_timeout (GdmChooserWidget *widget)
-{
- GHashTableIter iter;
- GSList *list;
- GSList *tmp;
- gpointer key;
- gpointer value;
- double now;
-
- list = NULL;
- g_hash_table_iter_init (&iter, widget->priv->rows_with_timers);
- while (g_hash_table_iter_next (&iter, &key, &value)) {
- list = g_slist_prepend (list, value);
- }
-
- now = get_current_time ();
- for (tmp = list; tmp != NULL; tmp = tmp->next) {
- GtkTreeRowReference *row;
-
- row = (GtkTreeRowReference *) tmp->data;
-
- update_timer_from_time (widget, row, now);
- }
- g_slist_free (list);
-
- return TRUE;
-}
-
-static void
-start_timer (GdmChooserWidget *widget,
- GtkTreeRowReference *row,
- double duration)
-{
- GtkTreeModel *model;
- GtkTreePath *path;
- GtkTreeIter iter;
-
- model = GTK_TREE_MODEL (widget->priv->list_store);
-
- path = gtk_tree_row_reference_get_path (row);
- gtk_tree_model_get_iter (model, &iter, path);
- gtk_tree_path_free (path);
-
- gtk_list_store_set (widget->priv->list_store, &iter,
- CHOOSER_TIMER_START_TIME_COLUMN,
- get_current_time (), -1);
- gtk_list_store_set (widget->priv->list_store, &iter,
- CHOOSER_TIMER_DURATION_COLUMN,
- duration, -1);
- gtk_list_store_set (widget->priv->list_store, &iter,
- CHOOSER_TIMER_VALUE_COLUMN, 0.0, -1);
-
- widget->priv->number_of_active_timers++;
- if (widget->priv->timer_animation_timeout_id == 0) {
- g_assert (g_hash_table_size (widget->priv->rows_with_timers) == 1);
-
- widget->priv->timer_animation_timeout_id =
- g_timeout_add (1000 / 20,
- (GSourceFunc) on_timer_timeout,
- widget);
-
- }
-}
-
-static void
-stop_timer (GdmChooserWidget *widget,
- GtkTreeRowReference *row)
-{
- GtkTreeModel *model;
- GtkTreePath *path;
- GtkTreeIter iter;
-
- model = GTK_TREE_MODEL (widget->priv->list_store);
-
- path = gtk_tree_row_reference_get_path (row);
- gtk_tree_model_get_iter (model, &iter, path);
- gtk_tree_path_free (path);
-
- gtk_list_store_set (widget->priv->list_store, &iter,
- CHOOSER_TIMER_START_TIME_COLUMN,
- 0.0, -1);
- gtk_list_store_set (widget->priv->list_store, &iter,
- CHOOSER_TIMER_DURATION_COLUMN,
- 0.0, -1);
- gtk_list_store_set (widget->priv->list_store, &iter,
- CHOOSER_TIMER_VALUE_COLUMN, 0.0, -1);
-
- widget->priv->number_of_active_timers--;
- if (widget->priv->number_of_active_timers == 0) {
- g_source_remove (widget->priv->timer_animation_timeout_id);
- widget->priv->timer_animation_timeout_id = 0;
- }
-}
-
-static void
-update_timer_from_time (GdmChooserWidget *widget,
- GtkTreeRowReference *row,
- double now)
-{
- GtkTreeModel *model;
- GtkTreePath *path;
- GtkTreeIter iter;
- double start_time;
- double duration;
- double elapsed_ratio;
-
- model = GTK_TREE_MODEL (widget->priv->list_store);
-
- path = gtk_tree_row_reference_get_path (row);
- gtk_tree_model_get_iter (model, &iter, path);
- gtk_tree_path_free (path);
-
- gtk_tree_model_get (model, &iter,
- CHOOSER_TIMER_START_TIME_COLUMN, &start_time,
- CHOOSER_TIMER_DURATION_COLUMN, &duration, -1);
-
- if (duration > G_MINDOUBLE) {
- elapsed_ratio = (now - start_time) / duration;
- } else {
- elapsed_ratio = 0.0;
- }
-
- gtk_list_store_set (widget->priv->list_store, &iter,
- CHOOSER_TIMER_VALUE_COLUMN,
- elapsed_ratio, -1);
-
- if (elapsed_ratio > .999) {
- char *id;
-
- stop_timer (widget, row);
-
- gtk_tree_model_get (model, &iter,
- CHOOSER_ID_COLUMN, &id, -1);
- g_hash_table_remove (widget->priv->rows_with_timers,
- id);
- g_free (id);
-
- widget->priv->number_of_rows_with_status--;
- queue_column_visibility_update (widget);
- }
-}
-
-void
-gdm_chooser_widget_set_item_timer (GdmChooserWidget *widget,
- const char *id,
- gulong timeout)
-{
- GtkTreeModel *model;
- GtkTreeRowReference *row;
-
- g_return_if_fail (GDM_IS_CHOOSER_WIDGET (widget));
-
- model = GTK_TREE_MODEL (widget->priv->list_store);
-
- row = g_hash_table_lookup (widget->priv->rows_with_timers,
- id);
-
- g_assert (row == NULL || gtk_tree_row_reference_valid (row));
-
- if (row != NULL) {
- stop_timer (widget, row);
- }
-
- if (timeout == 0) {
- if (row == NULL) {
- g_warning ("could not find item with ID '%s' to "
- "remove timer", id);
- return;
- }
-
- g_hash_table_remove (widget->priv->rows_with_timers,
- id);
- gtk_tree_model_filter_refilter (widget->priv->model_filter);
- return;
- }
-
- if (row == NULL) {
- GtkTreeIter iter;
- GtkTreePath *path;
-
- if (!find_item (widget, id, &iter)) {
- g_warning ("could not find item with ID '%s' to "
- "add timer", id);
- return;
- }
-
- path = gtk_tree_model_get_path (model, &iter);
- row = gtk_tree_row_reference_new (model, path);
-
- g_hash_table_insert (widget->priv->rows_with_timers,
- g_strdup (id), row);
-
- widget->priv->number_of_rows_with_status++;
- queue_column_visibility_update (widget);
- }
-
- start_timer (widget, row, timeout / 1000.0);
-}
-
-void
-gdm_chooser_widget_set_in_use_message (GdmChooserWidget *widget,
- const char *message)
-{
- g_return_if_fail (GDM_IS_CHOOSER_WIDGET (widget));
-
- g_free (widget->priv->in_use_message);
- widget->priv->in_use_message = g_strdup (message);
-}
-
-void
-gdm_chooser_widget_set_separator_position (GdmChooserWidget *widget,
- GdmChooserWidgetPosition position)
-{
- g_return_if_fail (GDM_IS_CHOOSER_WIDGET (widget));
-
- if (widget->priv->separator_position != position) {
- widget->priv->separator_position = position;
- }
-
- gtk_tree_model_filter_refilter (widget->priv->model_filter);
-}
-
-void
-gdm_chooser_widget_set_hide_inactive_items (GdmChooserWidget *widget,
- gboolean should_hide)
-{
- widget->priv->should_hide_inactive_items = should_hide;
-
- if (should_hide &&
- (widget->priv->state != GDM_CHOOSER_WIDGET_STATE_SHRUNK
- || widget->priv->state != GDM_CHOOSER_WIDGET_STATE_SHRINKING) &&
- widget->priv->active_row != NULL) {
- gdm_chooser_widget_shrink (widget);
- } else if (!should_hide &&
- (widget->priv->state != GDM_CHOOSER_WIDGET_STATE_GROWN
- || widget->priv->state != GDM_CHOOSER_WIDGET_STATE_GROWING)) {
- gdm_chooser_widget_grow (widget);
- }
-}
-
-int
-gdm_chooser_widget_get_number_of_items (GdmChooserWidget *widget)
-{
- return widget->priv->number_of_normal_rows +
- widget->priv->number_of_separated_rows;
-}
-
-void
-gdm_chooser_widget_activate_if_one_item (GdmChooserWidget *widget)
-{
- activate_if_one_item (widget);
-}
-
-void
-gdm_chooser_widget_propagate_pending_key_events (GdmChooserWidget *widget)
-{
- if (!gdm_scrollable_widget_has_queued_key_events (GDM_SCROLLABLE_WIDGET (widget->priv->scrollable_widget))) {
- return;
- }
-
- gdm_scrollable_widget_replay_queued_key_events (GDM_SCROLLABLE_WIDGET (widget->priv->scrollable_widget));
-}
-
-void
-gdm_chooser_widget_loaded (GdmChooserWidget *widget)
-{
- g_signal_emit (widget, signals[LOADED], 0);
- update_chooser_visibility (widget);
- queue_move_cursor_to_top (widget);
-}