[gtk+/open-with-dialog] app-chooser-combobox: add a method to trigger the GtkAppChooserDialog
- From: Cosimo Cecchi <cosimoc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/open-with-dialog] app-chooser-combobox: add a method to trigger the GtkAppChooserDialog
- Date: Thu, 25 Nov 2010 16:33:01 +0000 (UTC)
commit 67e842be87f7fca790a8172042304dbe11be6ca3
Author: Cosimo Cecchi <cosimoc gnome org>
Date: Thu Nov 25 17:17:45 2010 +0100
app-chooser-combobox: add a method to trigger the GtkAppChooserDialog
It's an optional special item in the combobox, turned off by default.
gtk/gtkappchoosercombobox.c | 252 +++++++++++++++++++++++++++++++++++++++----
gtk/gtkappchoosercombobox.h | 4 +
tests/testappchoosercombo.c | 3 +
3 files changed, 238 insertions(+), 21 deletions(-)
---
diff --git a/gtk/gtkappchoosercombobox.c b/gtk/gtkappchoosercombobox.c
index 625f536..db7d532 100644
--- a/gtk/gtkappchoosercombobox.c
+++ b/gtk/gtkappchoosercombobox.c
@@ -26,14 +26,18 @@
#include "gtkappchoosercombobox.h"
#include "gtkappchooser.h"
+#include "gtkappchooserdialog.h"
#include "gtkappchooserprivate.h"
#include "gtkcelllayout.h"
#include "gtkcellrendererpixbuf.h"
#include "gtkcellrenderertext.h"
#include "gtkcombobox.h"
+#include "gtkdialog.h"
+#include "gtkintl.h"
enum {
PROP_CONTENT_TYPE = 1,
+ PROP_SHOW_DIALOG_ITEM,
};
enum {
@@ -78,13 +82,27 @@ G_DEFINE_BOXED_TYPE (CustomAppComboData, custom_app_combo_data,
static void app_chooser_iface_init (GtkAppChooserIface *iface);
+static void real_insert_custom_item (GtkAppChooserComboBox *self,
+ const gchar *label,
+ GIcon *icon,
+ GtkAppChooserComboBoxItemFunc func,
+ gpointer user_data,
+ gboolean custom,
+ GtkTreeIter *iter);
+
+static void real_insert_separator (GtkAppChooserComboBox *self,
+ gboolean custom,
+ GtkTreeIter *iter);
+
G_DEFINE_TYPE_WITH_CODE (GtkAppChooserComboBox, gtk_app_chooser_combo_box, GTK_TYPE_COMBO_BOX,
G_IMPLEMENT_INTERFACE (GTK_TYPE_APP_CHOOSER,
app_chooser_iface_init));
struct _GtkAppChooserComboBoxPrivate {
- gchar *content_type;
GtkListStore *store;
+
+ gchar *content_type;
+ gboolean show_dialog_item;
};
static gboolean
@@ -119,6 +137,140 @@ get_first_iter (GtkListStore *store,
}
}
+typedef struct {
+ GtkAppChooserComboBox *self;
+ GAppInfo *info;
+ gint active_index;
+} SelectAppData;
+
+static void
+select_app_data_free (SelectAppData *data)
+{
+ g_clear_object (&data->self);
+ g_clear_object (&data->info);
+
+ g_slice_free (SelectAppData, data);
+}
+
+static gboolean
+select_application_func_cb (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer user_data)
+{
+ SelectAppData *data = user_data;
+ GAppInfo *app_to_match = data->info, *app = NULL;
+ gboolean custom;
+
+ gtk_tree_model_get (model, iter,
+ COLUMN_APP_INFO, &app,
+ COLUMN_CUSTOM, &custom,
+ -1);
+
+ /* cutsom items are always after GAppInfos, so iterating further here
+ * is just useless.
+ */
+ if (custom)
+ return TRUE;
+
+ if (g_app_info_equal (app, app_to_match))
+ {
+ gtk_combo_box_set_active_iter (GTK_COMBO_BOX (data->self), iter);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+gtk_app_chooser_combo_box_select_application (GtkAppChooserComboBox *self,
+ GAppInfo *info)
+{
+ SelectAppData *data;
+
+ data = g_slice_new0 (SelectAppData);
+ data->self = g_object_ref (self);
+ data->info = g_object_ref (info);
+
+ gtk_tree_model_foreach (GTK_TREE_MODEL (self->priv->store),
+ select_application_func_cb, data);
+
+ select_app_data_free (data);
+}
+
+static void
+other_application_dialog_response_cb (GtkDialog *dialog,
+ gint response_id,
+ gpointer user_data)
+{
+ GtkAppChooserComboBox *self = user_data;
+ GAppInfo *info;
+
+ if (response_id != GTK_RESPONSE_OK)
+ {
+ /* reset the active item, otherwise we are stuck on
+ * 'Other application...'
+ */
+ gtk_combo_box_set_active (GTK_COMBO_BOX (self), 0);
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+ return;
+ }
+
+ info = gtk_app_chooser_get_app_info (GTK_APP_CHOOSER (dialog));
+
+ /* refresh the combobox to get the new application */
+ gtk_app_chooser_refresh (GTK_APP_CHOOSER (self));
+ gtk_app_chooser_combo_box_select_application (self, info);
+
+ g_object_unref (info);
+}
+
+static void
+other_application_item_activated_cb (GtkAppChooserComboBox *self,
+ gpointer _user_data)
+{
+ GtkWidget *dialog, *widget;
+ GtkWindow *toplevel;
+
+ toplevel = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self)));
+ dialog = gtk_app_chooser_dialog_new_for_content_type (toplevel, GTK_DIALOG_DESTROY_WITH_PARENT,
+ self->priv->content_type);
+ widget = gtk_app_chooser_dialog_get_widget (GTK_APP_CHOOSER_DIALOG (dialog));
+ g_object_set (widget,
+ "show-fallback", TRUE,
+ "show-other", TRUE,
+ NULL);
+ gtk_widget_show (dialog);
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (other_application_dialog_response_cb), self);
+}
+
+static void
+gtk_app_chooser_combo_box_ensure_dialog_item (GtkAppChooserComboBox *self,
+ GtkTreeIter *prev_iter)
+{
+ GIcon *icon;
+ GtkTreeIter iter;
+
+ if (!self->priv->show_dialog_item)
+ return;
+
+ icon = g_themed_icon_new ("application-x-executable");
+
+ gtk_list_store_insert_after (self->priv->store, &iter, prev_iter);
+ real_insert_separator (self, FALSE, &iter);
+ *prev_iter = iter;
+
+ gtk_list_store_insert_after (self->priv->store, &iter, prev_iter);
+ real_insert_custom_item (self,
+ _("Other application..."), icon,
+ other_application_item_activated_cb,
+ NULL, FALSE, &iter);
+
+ g_object_unref (icon);
+}
+
static void
gtk_app_chooser_combo_box_populate (GtkAppChooserComboBox *self)
{
@@ -163,6 +315,7 @@ gtk_app_chooser_combo_box_populate (GtkAppChooserComboBox *self)
g_object_unref (icon);
}
+ gtk_app_chooser_combo_box_ensure_dialog_item (self, &iter);
gtk_combo_box_set_active (GTK_COMBO_BOX (self), 0);
}
@@ -195,6 +348,7 @@ gtk_app_chooser_combo_box_build_ui (GtkAppChooserComboBox *self)
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (self), cell, TRUE);
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (self), cell,
"text", COLUMN_NAME,
+ "xpad", 6,
NULL);
gtk_app_chooser_combo_box_populate (self);
@@ -228,20 +382,16 @@ gtk_app_chooser_combo_box_changed (GtkComboBox *object)
{
GtkAppChooserComboBox *self = GTK_APP_CHOOSER_COMBO_BOX (object);
GtkTreeIter iter;
- gboolean custom, separator;
CustomAppComboData *custom_data = NULL;
if (!gtk_combo_box_get_active_iter (object, &iter))
return;
gtk_tree_model_get (GTK_TREE_MODEL (self->priv->store), &iter,
- COLUMN_CUSTOM, &custom,
- COLUMN_SEPARATOR, &separator,
COLUMN_CALLBACK, &custom_data,
-1);
- if (custom && !separator &&
- custom_data != NULL && custom_data->func != NULL)
+ if (custom_data != NULL && custom_data->func != NULL)
custom_data->func (self, custom_data->user_data);
}
@@ -297,6 +447,9 @@ gtk_app_chooser_combo_box_set_property (GObject *obj,
case PROP_CONTENT_TYPE:
self->priv->content_type = g_value_dup_string (value);
break;
+ case PROP_SHOW_DIALOG_ITEM:
+ gtk_app_chooser_combo_box_set_show_dialog_item (self, g_value_get_boolean (value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec);
break;
@@ -316,6 +469,9 @@ gtk_app_chooser_combo_box_get_property (GObject *obj,
case PROP_CONTENT_TYPE:
g_value_set_string (value, self->priv->content_type);
break;
+ case PROP_SHOW_DIALOG_ITEM:
+ g_value_set_boolean (value, self->priv->show_dialog_item);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec);
break;
@@ -344,6 +500,7 @@ gtk_app_chooser_combo_box_class_init (GtkAppChooserComboBoxClass *klass)
{
GObjectClass *oclass = G_OBJECT_CLASS (klass);
GtkComboBoxClass *combo_class = GTK_COMBO_BOX_CLASS (klass);
+ GParamSpec *pspec;
oclass->set_property = gtk_app_chooser_combo_box_set_property;
oclass->get_property = gtk_app_chooser_combo_box_get_property;
@@ -354,6 +511,13 @@ gtk_app_chooser_combo_box_class_init (GtkAppChooserComboBoxClass *klass)
g_object_class_override_property (oclass, PROP_CONTENT_TYPE, "content-type");
+ pspec = g_param_spec_boolean ("show-dialog-item",
+ P_("Include an 'Other...' item"),
+ P_("Whether the combobox should include an item that triggers a GtkAppChooserDialog"),
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (oclass, PROP_SHOW_DIALOG_ITEM, pspec);
+
g_type_class_add_private (klass, sizeof (GtkAppChooserComboBoxPrivate));
}
@@ -364,6 +528,41 @@ gtk_app_chooser_combo_box_init (GtkAppChooserComboBox *self)
GtkAppChooserComboBoxPrivate);
}
+static void
+real_insert_custom_item (GtkAppChooserComboBox *self,
+ const gchar *label,
+ GIcon *icon,
+ GtkAppChooserComboBoxItemFunc func,
+ gpointer user_data,
+ gboolean custom,
+ GtkTreeIter *iter)
+{
+ CustomAppComboData *data;
+
+ data = g_slice_new0 (CustomAppComboData);
+ data->func = func;
+ data->user_data = user_data;
+
+ gtk_list_store_set (self->priv->store, iter,
+ COLUMN_NAME, label,
+ COLUMN_ICON, icon,
+ COLUMN_CALLBACK, data,
+ COLUMN_CUSTOM, custom,
+ COLUMN_SEPARATOR, FALSE,
+ -1);
+}
+
+static void
+real_insert_separator (GtkAppChooserComboBox *self,
+ gboolean custom,
+ GtkTreeIter *iter)
+{
+ gtk_list_store_set (self->priv->store, iter,
+ COLUMN_CUSTOM, custom,
+ COLUMN_SEPARATOR, TRUE,
+ -1);
+}
+
/**
* gtk_app_chooser_combo_box_new:
* @content_type: the content type to show applications for
@@ -402,10 +601,7 @@ gtk_app_chooser_combo_box_append_separator (GtkAppChooserComboBox *self)
g_return_if_fail (GTK_IS_APP_CHOOSER_COMBO_BOX (self));
gtk_list_store_append (self->priv->store, &iter);
- gtk_list_store_set (self->priv->store, &iter,
- COLUMN_CUSTOM, TRUE,
- COLUMN_SEPARATOR, TRUE,
- -1);
+ real_insert_separator (self, TRUE, &iter);
}
/**
@@ -429,18 +625,32 @@ gtk_app_chooser_combo_box_append_custom_item (GtkAppChooserComboBox *sel
gpointer user_data)
{
GtkTreeIter iter;
- CustomAppComboData *data;
- data = g_slice_new0 (CustomAppComboData);
- data->func = func;
- data->user_data = user_data;
+ g_return_if_fail (GTK_IS_APP_CHOOSER_COMBO_BOX (self));
gtk_list_store_append (self->priv->store, &iter);
- gtk_list_store_set (self->priv->store, &iter,
- COLUMN_NAME, label,
- COLUMN_ICON, icon,
- COLUMN_CALLBACK, data,
- COLUMN_CUSTOM, TRUE,
- COLUMN_SEPARATOR, FALSE,
- -1);
+ real_insert_custom_item (self, label, icon,
+ func, user_data, TRUE, &iter);
+}
+
+gboolean
+gtk_app_chooser_combo_box_get_show_dialog_item (GtkAppChooserComboBox *self)
+{
+ g_return_val_if_fail (GTK_IS_APP_CHOOSER_COMBO_BOX (self), FALSE);
+
+ return self->priv->show_dialog_item;
+}
+
+void
+gtk_app_chooser_combo_box_set_show_dialog_item (GtkAppChooserComboBox *self,
+ gboolean setting)
+{
+ if (self->priv->show_dialog_item != setting)
+ {
+ self->priv->show_dialog_item = setting;
+
+ g_object_notify (G_OBJECT (self), "show-dialog-item");
+
+ gtk_app_chooser_refresh (GTK_APP_CHOOSER (self));
+ }
}
diff --git a/gtk/gtkappchoosercombobox.h b/gtk/gtkappchoosercombobox.h
index b124c7a..e593031 100644
--- a/gtk/gtkappchoosercombobox.h
+++ b/gtk/gtkappchoosercombobox.h
@@ -70,4 +70,8 @@ void gtk_app_chooser_combo_box_append_custom_item (GtkAppChooserComboBox
GtkAppChooserComboBoxItemFunc func,
gpointer user_data);
+void gtk_app_chooser_combo_box_set_show_dialog_item (GtkAppChooserComboBox *self,
+ gboolean setting);
+gboolean gtk_app_chooser_combo_box_get_show_dialog_item (GtkAppChooserComboBox *self);
+
#endif /* __GTK_APP_CHOOSER_COMBO_BOX_H__ */
diff --git a/tests/testappchoosercombo.c b/tests/testappchoosercombo.c
index 59a44fa..d393aec 100644
--- a/tests/testappchoosercombo.c
+++ b/tests/testappchoosercombo.c
@@ -92,6 +92,9 @@ main (int argc,
special_item_activated_cb,
NULL);
+ gtk_app_chooser_combo_box_set_show_dialog_item (GTK_APP_CHOOSER_COMBO_BOX (combobox),
+ TRUE);
+
/* test refresh on a combo */
gtk_app_chooser_refresh (GTK_APP_CHOOSER (combobox));
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]