]> Pileus Git - ~andy/gtk/blob - gtk/gtkappchooserwidget.c
Coding style fixups
[~andy/gtk] / gtk / gtkappchooserwidget.c
1 /*
2  * gtkappchooserwidget.c: an app-chooser widget
3  *
4  * Copyright (C) 2004 Novell, Inc.
5  * Copyright (C) 2007, 2010 Red Hat, Inc.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public License as
9  * published by the Free Software Foundation; either version 2 of the
10  * License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with the Gnome Library; see the file COPYING.LIB.  If not,
19  * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  *
22  * Authors: Dave Camp <dave@novell.com>
23  *          Alexander Larsson <alexl@redhat.com>
24  *          Cosimo Cecchi <ccecchi@redhat.com>
25  */
26
27 #include "config.h"
28
29 #include "gtkappchooserwidget.h"
30
31 #include "gtkintl.h"
32 #include "gtkmarshalers.h"
33 #include "gtkappchooserwidget.h"
34 #include "gtkappchooserprivate.h"
35 #include "gtkliststore.h"
36 #include "gtkcellrenderertext.h"
37 #include "gtkcellrendererpixbuf.h"
38 #include "gtktreeview.h"
39 #include "gtktreeselection.h"
40 #include "gtktreemodelsort.h"
41 #include "gtkorientable.h"
42 #include "gtkscrolledwindow.h"
43
44 #include <string.h>
45 #include <glib/gi18n-lib.h>
46 #include <gio/gio.h>
47
48 struct _GtkAppChooserWidgetPrivate {
49   GAppInfo *selected_app_info;
50
51   gchar *content_type;
52   gchar *default_text;
53   gboolean show_default;
54   gboolean show_recommended;
55   gboolean show_fallback;
56   gboolean show_other;
57   gboolean show_all;
58
59   GtkWidget *program_list;
60   GtkListStore *program_list_store;
61
62   GtkCellRenderer *padding_renderer;
63 };
64
65 enum {
66   COLUMN_APP_INFO,
67   COLUMN_GICON,
68   COLUMN_NAME,
69   COLUMN_DESC,
70   COLUMN_EXEC,
71   COLUMN_DEFAULT,
72   COLUMN_HEADING,
73   COLUMN_HEADING_TEXT,
74   COLUMN_RECOMMENDED,
75   COLUMN_FALLBACK,
76   NUM_COLUMNS
77 };
78
79
80 enum {
81   PROP_CONTENT_TYPE = 1,
82   PROP_GFILE,
83   PROP_SHOW_DEFAULT,
84   PROP_SHOW_RECOMMENDED,
85   PROP_SHOW_FALLBACK,
86   PROP_SHOW_OTHER,
87   PROP_SHOW_ALL,
88   PROP_DEFAULT_TEXT,
89   N_PROPERTIES
90 };
91
92 enum {
93   SIGNAL_APPLICATION_SELECTED,
94   SIGNAL_APPLICATION_ACTIVATED,
95   SIGNAL_POPULATE_POPUP,
96   N_SIGNALS
97 };
98
99 static guint signals[N_SIGNALS] = { 0, };
100
101 static void gtk_app_chooser_widget_iface_init (GtkAppChooserIface *iface);
102
103 G_DEFINE_TYPE_WITH_CODE (GtkAppChooserWidget, gtk_app_chooser_widget, GTK_TYPE_BOX,
104                          G_IMPLEMENT_INTERFACE (GTK_TYPE_APP_CHOOSER,
105                                                 gtk_app_chooser_widget_iface_init));
106
107 static void
108 refresh_and_emit_app_selected (GtkAppChooserWidget *self,
109                                GtkTreeSelection    *selection)
110 {
111   GtkTreeModel *model;
112   GtkTreeIter iter;
113   GAppInfo *info = NULL;
114   gboolean should_emit = FALSE;
115
116   if (gtk_tree_selection_get_selected (selection, &model, &iter))
117     gtk_tree_model_get (model, &iter, COLUMN_APP_INFO, &info, -1);
118
119   if (info == NULL)
120     return;
121
122   if (self->priv->selected_app_info)
123     {
124       if (!g_app_info_equal (self->priv->selected_app_info, info))
125         {
126           should_emit = TRUE;
127           g_object_unref (self->priv->selected_app_info);
128
129           self->priv->selected_app_info = info;
130         }
131     }
132   else
133     {
134       should_emit = TRUE;
135       self->priv->selected_app_info = info;
136     }
137
138   if (should_emit)
139     g_signal_emit (self, signals[SIGNAL_APPLICATION_SELECTED], 0,
140                    self->priv->selected_app_info);
141 }
142
143 static GAppInfo *
144 get_app_info_for_event (GtkAppChooserWidget *self,
145                         GdkEventButton      *event)
146 {
147   GtkTreePath *path = NULL;
148   GtkTreeIter iter;
149   GtkTreeModel *model;
150   GAppInfo *info;
151   gboolean recommended;
152
153   if (!gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (self->priv->program_list),
154                                       event->x, event->y,
155                                       &path,
156                                       NULL, NULL, NULL))
157     return NULL;
158
159   model = gtk_tree_view_get_model (GTK_TREE_VIEW (self->priv->program_list));
160
161   if (!gtk_tree_model_get_iter (model, &iter, path))
162     {
163       gtk_tree_path_free (path);
164       return NULL;
165     }
166
167   /* we only allow interaction with recommended applications */
168   gtk_tree_model_get (model, &iter,
169                       COLUMN_APP_INFO, &info,
170                       COLUMN_RECOMMENDED, &recommended,
171                       -1);
172
173   if (!recommended)
174     g_clear_object (&info);
175
176   return info;
177 }
178
179 static gboolean
180 widget_button_press_event_cb (GtkWidget      *widget,
181                               GdkEventButton *event,
182                               gpointer        user_data)
183 {
184   GtkAppChooserWidget *self = user_data;
185
186   if (event->button == 3 && event->type == GDK_BUTTON_PRESS)
187     {
188       GAppInfo *info;
189       GtkWidget *menu;
190       GList *children;
191       gint n_children;
192
193       info = get_app_info_for_event (self, event);
194
195       if (info == NULL)
196         return FALSE;
197
198       menu = gtk_menu_new ();
199
200       g_signal_emit (self, signals[SIGNAL_POPULATE_POPUP], 0,
201                      menu, info);
202
203       g_object_unref (info);
204
205       /* see if clients added menu items to this container */
206       children = gtk_container_get_children (GTK_CONTAINER (menu));
207       n_children = g_list_length (children);
208
209       if (n_children > 0)
210         {
211           /* actually popup the menu */
212           gtk_menu_attach_to_widget (GTK_MENU (menu), self->priv->program_list, NULL);
213           gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
214                           event->button, event->time);
215         }
216
217       g_list_free (children);
218     }
219
220   return FALSE;
221 }
222
223 static gboolean
224 path_is_heading (GtkTreeView *view,
225                  GtkTreePath *path)
226 {
227   GtkTreeIter iter;
228   GtkTreeModel *model;
229   gboolean res;
230
231   model = gtk_tree_view_get_model (view);
232   gtk_tree_model_get_iter (model, &iter, path);
233   gtk_tree_model_get (model, &iter,
234                       COLUMN_HEADING, &res,
235                       -1);
236
237   return res;
238 }
239
240 static void
241 program_list_selection_activated (GtkTreeView       *view,
242                                   GtkTreePath       *path,
243                                   GtkTreeViewColumn *column,
244                                   gpointer           user_data)
245 {
246   GtkAppChooserWidget *self = user_data;
247   GtkTreeSelection *selection;
248
249   if (path_is_heading (view, path))
250     return;
251
252   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (self->priv->program_list));
253
254   refresh_and_emit_app_selected (self, selection);
255
256   g_signal_emit (self, signals[SIGNAL_APPLICATION_ACTIVATED], 0,
257                  self->priv->selected_app_info);
258 }
259
260 static gboolean
261 gtk_app_chooser_search_equal_func (GtkTreeModel *model,
262                                    gint          column,
263                                    const gchar  *key,
264                                    GtkTreeIter  *iter,
265                                    gpointer      user_data)
266 {
267   gchar *normalized_key;
268   gchar *name, *normalized_name;
269   gchar *path, *normalized_path;
270   gchar *basename, *normalized_basename;
271   gboolean ret;
272
273   if (key != NULL)
274     {
275       normalized_key = g_utf8_casefold (key, -1);
276       g_assert (normalized_key != NULL);
277
278       ret = TRUE;
279
280       gtk_tree_model_get (model, iter,
281                           COLUMN_NAME, &name,
282                           COLUMN_EXEC, &path,
283                           -1);
284
285       if (name != NULL)
286         {
287           normalized_name = g_utf8_casefold (name, -1);
288           g_assert (normalized_name != NULL);
289
290           if (strncmp (normalized_name, normalized_key, strlen (normalized_key)) == 0)
291             ret = FALSE;
292
293           g_free (normalized_name);
294         }
295
296       if (ret && path != NULL)
297         {
298           normalized_path = g_utf8_casefold (path, -1);
299           g_assert (normalized_path != NULL);
300
301           basename = g_path_get_basename (path);
302           g_assert (basename != NULL);
303
304           normalized_basename = g_utf8_casefold (basename, -1);
305           g_assert (normalized_basename != NULL);
306
307           if (strncmp (normalized_path, normalized_key, strlen (normalized_key)) == 0 ||
308               strncmp (normalized_basename, normalized_key, strlen (normalized_key)) == 0)
309             ret = FALSE;
310
311           g_free (basename);
312           g_free (normalized_basename);
313           g_free (normalized_path);
314         }
315
316       g_free (name);
317       g_free (path);
318       g_free (normalized_key);
319
320       return ret;
321     }
322   else
323     {
324       return TRUE;
325     }
326 }
327
328 static gint
329 gtk_app_chooser_sort_func (GtkTreeModel *model,
330                            GtkTreeIter  *a,
331                            GtkTreeIter  *b,
332                            gpointer      user_data)
333 {
334   gboolean a_recommended, b_recommended;
335   gboolean a_fallback, b_fallback;
336   gboolean a_heading, b_heading;
337   gboolean a_default, b_default;
338   gchar *a_name, *b_name, *a_casefold, *b_casefold;
339   gint retval = 0;
340
341   /* this returns:
342    * - <0 if a should show before b
343    * - =0 if a is the same as b
344    * - >0 if a should show after b
345    */
346
347   gtk_tree_model_get (model, a,
348                       COLUMN_NAME, &a_name,
349                       COLUMN_RECOMMENDED, &a_recommended,
350                       COLUMN_FALLBACK, &a_fallback,
351                       COLUMN_HEADING, &a_heading,
352                       COLUMN_DEFAULT, &a_default,
353                       -1);
354
355   gtk_tree_model_get (model, b,
356                       COLUMN_NAME, &b_name,
357                       COLUMN_RECOMMENDED, &b_recommended,
358                       COLUMN_FALLBACK, &b_fallback,
359                       COLUMN_HEADING, &b_heading,
360                       COLUMN_DEFAULT, &b_default,
361                       -1);
362
363   /* the default one always wins */
364   if (a_default && !b_default)
365     {
366       retval = -1;
367       goto out;
368     }
369
370   if (b_default && !a_default)
371     {
372       retval = 1;
373       goto out;
374     }
375   
376   /* the recommended one always wins */
377   if (a_recommended && !b_recommended)
378     {
379       retval = -1;
380       goto out;
381     }
382
383   if (b_recommended && !a_recommended)
384     {
385       retval = 1;
386       goto out;
387     }
388
389   /* the recommended one always wins */
390   if (a_fallback && !b_fallback)
391     {
392       retval = -1;
393       goto out;
394     }
395
396   if (b_fallback && !a_fallback)
397     {
398       retval = 1;
399       goto out;
400     }
401
402   /* they're both recommended/falback or not, so if one is a heading, wins */
403   if (a_heading)
404     {
405       return -1;
406       goto out;
407     }
408
409   if (b_heading)
410     {
411       return 1;
412       goto out;
413     }
414
415   /* don't order by name recommended applications, but use GLib's ordering */
416   if (!a_recommended)
417     {
418       a_casefold = a_name != NULL ?
419         g_utf8_casefold (a_name, -1) : NULL;
420       b_casefold = b_name != NULL ?
421         g_utf8_casefold (b_name, -1) : NULL;
422
423       retval = g_strcmp0 (a_casefold, b_casefold);
424
425       g_free (a_casefold);
426       g_free (b_casefold);
427     }
428
429  out:
430   g_free (a_name);
431   g_free (b_name);
432
433   return retval;
434 }
435
436 static void
437 padding_cell_renderer_func (GtkTreeViewColumn *column,
438                             GtkCellRenderer   *cell,
439                             GtkTreeModel      *model,
440                             GtkTreeIter       *iter,
441                             gpointer           user_data)
442 {
443   gboolean heading;
444
445   gtk_tree_model_get (model, iter,
446                       COLUMN_HEADING, &heading,
447                       -1);
448   if (heading)
449     g_object_set (cell,
450                   "visible", FALSE,
451                   "xpad", 0,
452                   "ypad", 0,
453                   NULL);
454   else
455     g_object_set (cell,
456                   "visible", TRUE,
457                   "xpad", 3,
458                   "ypad", 3,
459                   NULL);
460 }
461
462 static gboolean
463 gtk_app_chooser_selection_func (GtkTreeSelection *selection,
464                                 GtkTreeModel     *model,
465                                 GtkTreePath      *path,
466                                 gboolean          path_currently_selected,
467                                 gpointer          user_data)
468 {
469   GtkTreeIter iter;
470   gboolean heading;
471
472   gtk_tree_model_get_iter (model, &iter, path);
473   gtk_tree_model_get (model, &iter,
474                       COLUMN_HEADING, &heading,
475                       -1);
476
477   return !heading;
478 }
479
480 static gint
481 compare_apps_func (gconstpointer a,
482                    gconstpointer b)
483 {
484   return !g_app_info_equal (G_APP_INFO (a), G_APP_INFO (b));
485 }
486
487 static gboolean
488 gtk_app_chooser_widget_add_section (GtkAppChooserWidget *self,
489                                     const gchar         *heading_title,
490                                     gboolean             show_headings,
491                                     gboolean             recommended,
492                                     gboolean             fallback,
493                                     GList               *applications,
494                                     GList               *exclude_apps)
495 {
496   gboolean heading_added, unref_icon;
497   GtkTreeIter iter;
498   GAppInfo *app;
499   gchar *app_string, *bold_string;
500   GIcon *icon;
501   GList *l;
502   gboolean retval;
503
504   retval = FALSE;
505   heading_added = FALSE;
506   bold_string = g_strdup_printf ("<b>%s</b>", heading_title);
507   
508   for (l = applications; l != NULL; l = l->next)
509     {
510       app = l->data;
511
512       if (!g_app_info_supports_uris (app) &&
513           !g_app_info_supports_files (app))
514         continue;
515
516       if (g_list_find_custom (exclude_apps, app,
517                               (GCompareFunc) compare_apps_func))
518         continue;
519
520       if (!heading_added && show_headings)
521         {
522           gtk_list_store_append (self->priv->program_list_store, &iter);
523           gtk_list_store_set (self->priv->program_list_store, &iter,
524                               COLUMN_HEADING_TEXT, bold_string,
525                               COLUMN_HEADING, TRUE,
526                               COLUMN_RECOMMENDED, recommended,
527                               COLUMN_FALLBACK, fallback,
528                               -1);
529
530           heading_added = TRUE;
531         }
532
533       app_string = g_markup_printf_escaped ("<b>%s</b>\n%s",
534                                             g_app_info_get_display_name (app) != NULL ?
535                                             g_app_info_get_display_name (app) : "",
536                                             g_app_info_get_description (app) != NULL ?
537                                             g_app_info_get_description (app) : "");
538
539       icon = g_app_info_get_icon (app);
540       unref_icon = FALSE;
541       if (icon == NULL)
542         {
543           icon = g_themed_icon_new ("application-x-executable");
544           unref_icon = TRUE;
545         }
546
547       gtk_list_store_append (self->priv->program_list_store, &iter);
548       gtk_list_store_set (self->priv->program_list_store, &iter,
549                           COLUMN_APP_INFO, app,
550                           COLUMN_GICON, icon,
551                           COLUMN_NAME, g_app_info_get_display_name (app),
552                           COLUMN_DESC, app_string,
553                           COLUMN_EXEC, g_app_info_get_executable (app),
554                           COLUMN_HEADING, FALSE,
555                           COLUMN_RECOMMENDED, recommended,
556                           COLUMN_FALLBACK, fallback,
557                           -1);
558
559       retval = TRUE;
560
561       g_free (app_string);
562       if (unref_icon)
563         g_object_unref (icon);
564     }
565
566   g_free (bold_string);
567
568   return retval;
569 }
570
571
572 static void
573 gtk_app_chooser_add_default (GtkAppChooserWidget *self,
574                              GAppInfo            *app)
575 {
576   GtkTreeIter iter;
577   GIcon *icon;
578   gchar *string;
579   gboolean unref_icon;
580
581   unref_icon = FALSE;
582   string = g_strdup_printf ("<b>%s</b>", _("Default Application"));
583
584   gtk_list_store_append (self->priv->program_list_store, &iter);
585   gtk_list_store_set (self->priv->program_list_store, &iter,
586                       COLUMN_HEADING_TEXT, string,
587                       COLUMN_HEADING, TRUE,
588                       COLUMN_DEFAULT, TRUE,
589                       -1);
590
591   g_free (string);
592
593   string = g_markup_printf_escaped ("<b>%s</b>\n%s",
594                                     g_app_info_get_display_name (app) != NULL ?
595                                     g_app_info_get_display_name (app) : "",
596                                     g_app_info_get_description (app) != NULL ?
597                                     g_app_info_get_description (app) : "");
598
599   icon = g_app_info_get_icon (app);
600   if (icon == NULL)
601     {
602       icon = g_themed_icon_new ("application-x-executable");
603       unref_icon = TRUE;
604     }
605
606   gtk_list_store_append (self->priv->program_list_store, &iter);
607   gtk_list_store_set (self->priv->program_list_store, &iter,
608                       COLUMN_APP_INFO, app,
609                       COLUMN_GICON, icon,
610                       COLUMN_NAME, g_app_info_get_display_name (app),
611                       COLUMN_DESC, string,
612                       COLUMN_EXEC, g_app_info_get_executable (app),
613                       COLUMN_HEADING, FALSE,
614                       COLUMN_DEFAULT, TRUE,
615                       -1);
616
617   g_free (string);
618
619   if (unref_icon)
620     g_object_unref (icon);
621 }
622
623 static void
624 add_no_applications_label (GtkAppChooserWidget *self)
625 {
626   gchar *text = NULL, *desc;
627   const gchar *string;
628   GtkTreeIter iter;
629
630   if (self->priv->default_text == NULL)
631     {
632       desc = g_content_type_get_description (self->priv->content_type);
633       string = text = g_strdup_printf (_("No applications available to open \"%s\""),
634                                        desc);
635       g_free (desc);
636     }
637   else
638     {
639       string = self->priv->default_text;
640     }
641
642   gtk_list_store_append (self->priv->program_list_store, &iter);
643   gtk_list_store_set (self->priv->program_list_store, &iter,
644                       COLUMN_HEADING_TEXT, string,
645                       COLUMN_HEADING, TRUE,
646                       -1);
647
648   g_free (text);
649 }
650
651 static void
652 gtk_app_chooser_widget_select_first (GtkAppChooserWidget *self)
653 {
654   GtkTreeIter iter;
655   GAppInfo *info = NULL;
656   GtkTreeModel *model;
657
658   model = gtk_tree_view_get_model (GTK_TREE_VIEW (self->priv->program_list));
659   gtk_tree_model_get_iter_first (model, &iter);
660
661   while (info == NULL)
662     {
663       gtk_tree_model_get (model, &iter,
664                           COLUMN_APP_INFO, &info,
665                           -1);
666
667       if (info != NULL)
668         break;
669
670       if (!gtk_tree_model_iter_next (model, &iter))
671         break;
672     }
673
674   if (info != NULL)
675     {
676       GtkTreeSelection *selection;
677
678       selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (self->priv->program_list));
679       gtk_tree_selection_select_iter (selection, &iter);
680
681       g_object_unref (info);
682     }
683 }
684
685 static void
686 gtk_app_chooser_widget_real_add_items (GtkAppChooserWidget *self)
687 {
688   GList *all_applications = NULL;
689   GList *recommended_apps = NULL;
690   GList *fallback_apps = NULL;
691   GList *exclude_apps = NULL;
692   GAppInfo *default_app = NULL;
693   gboolean show_headings;
694   gboolean apps_added;
695
696   show_headings = TRUE;
697   apps_added = FALSE;
698
699   if (self->priv->show_all)
700     show_headings = FALSE;
701
702   if (self->priv->show_default)
703     {
704       default_app = g_app_info_get_default_for_type (self->priv->content_type, FALSE);
705
706       if (default_app != NULL)
707         {
708           gtk_app_chooser_add_default (self, default_app);
709           apps_added = TRUE;
710           exclude_apps = g_list_prepend (exclude_apps, default_app);
711         }
712     }
713
714   if (self->priv->show_recommended || self->priv->show_all)
715     {
716       recommended_apps = g_app_info_get_recommended_for_type (self->priv->content_type);
717
718       apps_added |= gtk_app_chooser_widget_add_section (self, _("Recommended Applications"),
719                                                         show_headings,
720                                                         !self->priv->show_all, /* mark as recommended */
721                                                         FALSE, /* mark as fallback */
722                                                         recommended_apps, exclude_apps);
723
724       exclude_apps = g_list_concat (exclude_apps,
725                                     g_list_copy (recommended_apps));
726     }
727
728   if (self->priv->show_fallback || self->priv->show_all)
729     {
730       fallback_apps = g_app_info_get_fallback_for_type (self->priv->content_type);
731
732       apps_added |= gtk_app_chooser_widget_add_section (self, _("Related Applications"),
733                                                         show_headings,
734                                                         FALSE, /* mark as recommended */
735                                                         !self->priv->show_all, /* mark as fallback */
736                                                         fallback_apps, exclude_apps);
737       exclude_apps = g_list_concat (exclude_apps,
738                                     g_list_copy (fallback_apps));
739     }
740
741   if (self->priv->show_other || self->priv->show_all)
742     {
743       all_applications = g_app_info_get_all ();
744
745       apps_added |= gtk_app_chooser_widget_add_section (self, _("Other Applications"),
746                                                         show_headings,
747                                                         FALSE,
748                                                         FALSE,
749                                                         all_applications, exclude_apps);
750     }
751
752   if (!apps_added)
753     add_no_applications_label (self);
754
755   gtk_app_chooser_widget_select_first (self);
756
757   if (default_app != NULL)
758     g_object_unref (default_app);
759
760   if (all_applications != NULL)
761     g_list_free_full (all_applications, g_object_unref);
762
763   if (recommended_apps != NULL)
764     g_list_free_full (recommended_apps, g_object_unref);
765
766   if (fallback_apps != NULL)
767     g_list_free_full (fallback_apps, g_object_unref);
768
769   if (exclude_apps != NULL)
770     g_list_free (exclude_apps);
771 }
772
773 static void
774 gtk_app_chooser_widget_add_items (GtkAppChooserWidget *self)
775 {
776   GtkCellRenderer *renderer;
777   GtkTreeViewColumn *column;
778   GtkTreeModel *sort;
779
780   /* create list store */
781   self->priv->program_list_store = gtk_list_store_new (NUM_COLUMNS,
782                                                        G_TYPE_APP_INFO,
783                                                        G_TYPE_ICON,
784                                                        G_TYPE_STRING,
785                                                        G_TYPE_STRING,
786                                                        G_TYPE_STRING,
787                                                        G_TYPE_BOOLEAN,
788                                                        G_TYPE_BOOLEAN,
789                                                        G_TYPE_STRING,
790                                                        G_TYPE_BOOLEAN,
791                                                        G_TYPE_BOOLEAN);
792   sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (self->priv->program_list_store));
793
794   gtk_tree_view_set_model (GTK_TREE_VIEW (self->priv->program_list),
795                            GTK_TREE_MODEL (sort));
796   gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort),
797                                         COLUMN_NAME,
798                                         GTK_SORT_ASCENDING);
799   gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (sort),
800                                    COLUMN_NAME,
801                                    gtk_app_chooser_sort_func,
802                                    self, NULL);
803   gtk_tree_view_set_search_column (GTK_TREE_VIEW (self->priv->program_list),
804                                    COLUMN_NAME);
805   gtk_tree_view_set_search_equal_func (GTK_TREE_VIEW (self->priv->program_list),
806                                        gtk_app_chooser_search_equal_func,
807                                        NULL, NULL);
808
809   column = gtk_tree_view_column_new ();
810
811   /* initial padding */
812   renderer = gtk_cell_renderer_text_new ();
813   gtk_tree_view_column_pack_start (column, renderer, FALSE);
814   g_object_set (renderer,
815                 "xpad", self->priv->show_all ? 0 : 6,
816                 NULL);
817   self->priv->padding_renderer = renderer;
818
819   /* heading text renderer */
820   renderer = gtk_cell_renderer_text_new ();
821   gtk_tree_view_column_pack_start (column, renderer, FALSE);
822   gtk_tree_view_column_set_attributes (column, renderer,
823                                        "markup", COLUMN_HEADING_TEXT,
824                                        "visible", COLUMN_HEADING,
825                                        NULL);
826   g_object_set (renderer,
827                 "ypad", 6,
828                 "xpad", 0,
829                 "wrap-width", 350,
830                 "wrap-mode", PANGO_WRAP_WORD,
831                 NULL);
832
833   /* padding renderer for non-heading cells */
834   renderer = gtk_cell_renderer_text_new ();
835   gtk_tree_view_column_pack_start (column, renderer, FALSE);
836   gtk_tree_view_column_set_cell_data_func (column, renderer,
837                                            padding_cell_renderer_func,
838                                            NULL, NULL);
839
840   /* app icon renderer */
841   renderer = gtk_cell_renderer_pixbuf_new ();
842   gtk_tree_view_column_pack_start (column, renderer, FALSE);
843   gtk_tree_view_column_set_attributes (column, renderer,
844                                        "gicon", COLUMN_GICON,
845                                        NULL);
846   g_object_set (renderer,
847                 "stock-size", GTK_ICON_SIZE_DIALOG,
848                 NULL);
849
850   /* app name renderer */
851   renderer = gtk_cell_renderer_text_new ();
852   gtk_tree_view_column_pack_start (column, renderer, TRUE);
853   gtk_tree_view_column_set_attributes (column, renderer,
854                                        "markup", COLUMN_DESC,
855                                        NULL);
856   g_object_set (renderer,
857                 "ellipsize", PANGO_ELLIPSIZE_END,
858                 "ellipsize-set", TRUE,
859                 NULL);
860   
861   gtk_tree_view_column_set_sort_column_id (column, COLUMN_NAME);
862   gtk_tree_view_append_column (GTK_TREE_VIEW (self->priv->program_list), column);
863
864   /* populate the widget */
865   gtk_app_chooser_widget_real_add_items (self);
866 }
867
868 static void
869 gtk_app_chooser_widget_set_property (GObject      *object,
870                                      guint         property_id,
871                                      const GValue *value,
872                                      GParamSpec   *pspec)
873 {
874   GtkAppChooserWidget *self = GTK_APP_CHOOSER_WIDGET (object);
875
876   switch (property_id)
877     {
878     case PROP_CONTENT_TYPE:
879       self->priv->content_type = g_value_dup_string (value);
880       break;
881     case PROP_SHOW_DEFAULT:
882       gtk_app_chooser_widget_set_show_default (self, g_value_get_boolean (value));
883       break;
884     case PROP_SHOW_RECOMMENDED:
885       gtk_app_chooser_widget_set_show_recommended (self, g_value_get_boolean (value));
886       break;
887     case PROP_SHOW_FALLBACK:
888       gtk_app_chooser_widget_set_show_fallback (self, g_value_get_boolean (value));
889       break;
890     case PROP_SHOW_OTHER:
891       gtk_app_chooser_widget_set_show_other (self, g_value_get_boolean (value));
892       break;
893     case PROP_SHOW_ALL:
894       gtk_app_chooser_widget_set_show_all (self, g_value_get_boolean (value));
895       break;
896     case PROP_DEFAULT_TEXT:
897       gtk_app_chooser_widget_set_default_text (self, g_value_get_string (value));
898       break;
899     default:
900       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
901       break;
902     }
903 }
904
905 static void
906 gtk_app_chooser_widget_get_property (GObject    *object,
907                                      guint       property_id,
908                                      GValue     *value,
909                                      GParamSpec *pspec)
910 {
911   GtkAppChooserWidget *self = GTK_APP_CHOOSER_WIDGET (object);
912
913   switch (property_id)
914     {
915     case PROP_CONTENT_TYPE:
916       g_value_set_string (value, self->priv->content_type);
917       break;
918     case PROP_SHOW_DEFAULT:
919       g_value_set_boolean (value, self->priv->show_default);
920       break;
921     case PROP_SHOW_RECOMMENDED:
922       g_value_set_boolean (value, self->priv->show_recommended);
923       break;
924     case PROP_SHOW_FALLBACK:
925       g_value_set_boolean (value, self->priv->show_fallback);
926       break;
927     case PROP_SHOW_OTHER:
928       g_value_set_boolean (value, self->priv->show_other);
929       break;
930     case PROP_SHOW_ALL:
931       g_value_set_boolean (value, self->priv->show_all);
932       break;
933     case PROP_DEFAULT_TEXT:
934       g_value_set_string (value, self->priv->default_text);
935       break;
936     default:
937       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
938       break;
939     }
940 }
941
942 static void
943 gtk_app_chooser_widget_constructed (GObject *object)
944 {
945   GtkAppChooserWidget *self = GTK_APP_CHOOSER_WIDGET (object);
946
947   g_assert (self->priv->content_type != NULL);
948
949   if (G_OBJECT_CLASS (gtk_app_chooser_widget_parent_class)->constructed != NULL)
950     G_OBJECT_CLASS (gtk_app_chooser_widget_parent_class)->constructed (object);
951
952   gtk_app_chooser_widget_add_items (self);
953 }
954
955 static void
956 gtk_app_chooser_widget_finalize (GObject *object)
957 {
958   GtkAppChooserWidget *self = GTK_APP_CHOOSER_WIDGET (object);
959
960   g_free (self->priv->content_type);
961   g_free (self->priv->default_text);
962
963   G_OBJECT_CLASS (gtk_app_chooser_widget_parent_class)->finalize (object);
964 }
965
966 static void
967 gtk_app_chooser_widget_dispose (GObject *object)
968 {
969   GtkAppChooserWidget *self = GTK_APP_CHOOSER_WIDGET (object);
970
971   if (self->priv->selected_app_info != NULL)
972     {
973       g_object_unref (self->priv->selected_app_info);
974       self->priv->selected_app_info = NULL;
975     }
976
977   G_OBJECT_CLASS (gtk_app_chooser_widget_parent_class)->dispose (object);
978 }
979
980 static void
981 gtk_app_chooser_widget_class_init (GtkAppChooserWidgetClass *klass)
982 {
983   GObjectClass *gobject_class;
984   GParamSpec *pspec;
985
986   gobject_class = G_OBJECT_CLASS (klass);
987   gobject_class->dispose = gtk_app_chooser_widget_dispose;
988   gobject_class->finalize = gtk_app_chooser_widget_finalize;
989   gobject_class->set_property = gtk_app_chooser_widget_set_property;
990   gobject_class->get_property = gtk_app_chooser_widget_get_property;
991   gobject_class->constructed = gtk_app_chooser_widget_constructed;
992
993   g_object_class_override_property (gobject_class, PROP_CONTENT_TYPE, "content-type");
994
995   /**
996    * GtkAppChooserWidget:show-default:
997    *
998    * The ::show-default property determines whether the app chooser
999    * should show the default handler for the content type in a
1000    * separate section. If %FALSE, the default handler is listed
1001    * among the recommended applications.
1002    */
1003   pspec = g_param_spec_boolean ("show-default",
1004                                 P_("Show default app"),
1005                                 P_("Whether the widget should show the default application"),
1006                                 FALSE,
1007                                 G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
1008   g_object_class_install_property (gobject_class, PROP_SHOW_DEFAULT, pspec);
1009
1010   /**
1011    * GtkAppChooserWidget:show-recommended:
1012    *
1013    * The ::show-recommended property determines whether the app chooser
1014    * should show a section for recommended applications. If %FALSE, the
1015    * recommended applications are listed among the other applications.
1016    */
1017   pspec = g_param_spec_boolean ("show-recommended",
1018                                 P_("Show recommended apps"),
1019                                 P_("Whether the widget should show recommended applications"),
1020                                 TRUE,
1021                                 G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
1022   g_object_class_install_property (gobject_class, PROP_SHOW_RECOMMENDED, pspec);
1023
1024   /**
1025    * GtkAppChooserWidget:show-fallback:
1026    *
1027    * The ::show-fallback property determines whether the app chooser
1028    * should show a section for related applications. If %FALSE, the
1029    * related applications are listed among the other applications.
1030    */
1031   pspec = g_param_spec_boolean ("show-fallback",
1032                                 P_("Show fallback apps"),
1033                                 P_("Whether the widget should show fallback applications"),
1034                                 FALSE,
1035                                 G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
1036   g_object_class_install_property (gobject_class, PROP_SHOW_FALLBACK, pspec);
1037
1038   /**
1039    * GtkAppChooserWidget:show-other:
1040    *
1041    * The ::show-other property determines whether the app chooser
1042    * should show a section for other applications.
1043    */
1044   pspec = g_param_spec_boolean ("show-other",
1045                                 P_("Show other apps"),
1046                                 P_("Whether the widget should show other applications"),
1047                                 FALSE,
1048                                 G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
1049   g_object_class_install_property (gobject_class, PROP_SHOW_OTHER, pspec);
1050
1051   /**
1052    * GtkAppChooserWidget:show-all:
1053    *
1054    * If the ::show-all property is %TRUE, the app chooser presents
1055    * all applications in a single list, without subsections for
1056    * default, recommended or related applications.
1057    */
1058   pspec = g_param_spec_boolean ("show-all",
1059                                 P_("Show all apps"),
1060                                 P_("Whether the widget should show all applications"),
1061                                 FALSE,
1062                                 G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
1063   g_object_class_install_property (gobject_class, PROP_SHOW_ALL, pspec);
1064
1065   pspec = g_param_spec_string ("default-text",
1066                                P_("Widget's default text"),
1067                                P_("The default text appearing when there are no applications"),
1068                                NULL,
1069                                G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1070   g_object_class_install_property (gobject_class, PROP_DEFAULT_TEXT, pspec);
1071
1072   signals[SIGNAL_APPLICATION_SELECTED] =
1073     g_signal_new ("application-selected",
1074                   GTK_TYPE_APP_CHOOSER_WIDGET,
1075                   G_SIGNAL_RUN_FIRST,
1076                   G_STRUCT_OFFSET (GtkAppChooserWidgetClass, application_selected),
1077                   NULL, NULL,
1078                   _gtk_marshal_VOID__OBJECT,
1079                   G_TYPE_NONE,
1080                   1, G_TYPE_APP_INFO);
1081
1082   signals[SIGNAL_APPLICATION_ACTIVATED] =
1083     g_signal_new ("application-activated",
1084                   GTK_TYPE_APP_CHOOSER_WIDGET,
1085                   G_SIGNAL_RUN_FIRST,
1086                   G_STRUCT_OFFSET (GtkAppChooserWidgetClass, application_activated),
1087                   NULL, NULL,
1088                   _gtk_marshal_VOID__OBJECT,
1089                   G_TYPE_NONE,
1090                   1, G_TYPE_APP_INFO);
1091
1092   signals[SIGNAL_POPULATE_POPUP] =
1093     g_signal_new ("populate-popup",
1094                   GTK_TYPE_APP_CHOOSER_WIDGET,
1095                   G_SIGNAL_RUN_FIRST,
1096                   G_STRUCT_OFFSET (GtkAppChooserWidgetClass, populate_popup),
1097                   NULL, NULL,
1098                   _gtk_marshal_VOID__OBJECT_OBJECT,
1099                   G_TYPE_NONE,
1100                   2, GTK_TYPE_MENU, G_TYPE_APP_INFO);
1101
1102   g_type_class_add_private (klass, sizeof (GtkAppChooserWidgetPrivate));
1103 }
1104
1105 static void
1106 gtk_app_chooser_widget_init (GtkAppChooserWidget *self)
1107 {
1108   GtkWidget *scrolled_window;
1109   GtkTreeSelection *selection;
1110
1111   self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTK_TYPE_APP_CHOOSER_WIDGET,
1112                                             GtkAppChooserWidgetPrivate);
1113   gtk_orientable_set_orientation (GTK_ORIENTABLE (self), GTK_ORIENTATION_VERTICAL);
1114
1115   scrolled_window = gtk_scrolled_window_new (NULL, NULL);
1116   gtk_widget_set_size_request (scrolled_window, 400, 300);
1117   gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
1118                                        GTK_SHADOW_IN);
1119   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
1120                                   GTK_POLICY_NEVER,
1121                                   GTK_POLICY_AUTOMATIC);
1122   gtk_widget_show (scrolled_window);
1123
1124   self->priv->program_list = gtk_tree_view_new ();
1125   gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (self->priv->program_list),
1126                                      FALSE);
1127   gtk_container_add (GTK_CONTAINER (scrolled_window), self->priv->program_list);
1128   gtk_box_pack_start (GTK_BOX (self), scrolled_window, TRUE, TRUE, 0);
1129   gtk_widget_show (self->priv->program_list);
1130
1131   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (self->priv->program_list));
1132   gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
1133   gtk_tree_selection_set_select_function (selection, gtk_app_chooser_selection_func,
1134                                           self, NULL);
1135   g_signal_connect_swapped (selection, "changed",
1136                             G_CALLBACK (refresh_and_emit_app_selected),
1137                             self);
1138   g_signal_connect (self->priv->program_list, "row-activated",
1139                     G_CALLBACK (program_list_selection_activated),
1140                     self);
1141   g_signal_connect (self->priv->program_list, "button-press-event",
1142                     G_CALLBACK (widget_button_press_event_cb),
1143                     self);
1144 }
1145
1146 static GAppInfo *
1147 gtk_app_chooser_widget_get_app_info (GtkAppChooser *object)
1148 {
1149   GtkAppChooserWidget *self = GTK_APP_CHOOSER_WIDGET (object);
1150
1151   if (self->priv->selected_app_info == NULL)
1152     return NULL;
1153
1154   return g_object_ref (self->priv->selected_app_info);
1155 }
1156
1157 static void
1158 gtk_app_chooser_widget_refresh (GtkAppChooser *object)
1159 {
1160   GtkAppChooserWidget *self = GTK_APP_CHOOSER_WIDGET (object);
1161
1162   if (self->priv->program_list_store != NULL)
1163     {
1164       gtk_list_store_clear (self->priv->program_list_store);
1165
1166       /* don't add additional xpad if we don't have headings */
1167       g_object_set (self->priv->padding_renderer,
1168                     "visible", !self->priv->show_all,
1169                     NULL);
1170
1171       gtk_app_chooser_widget_real_add_items (self);
1172     }
1173 }
1174
1175 static void
1176 gtk_app_chooser_widget_iface_init (GtkAppChooserIface *iface)
1177 {
1178   iface->get_app_info = gtk_app_chooser_widget_get_app_info;
1179   iface->refresh = gtk_app_chooser_widget_refresh;
1180 }
1181
1182 /**
1183  * gtk_app_chooser_widget_new:
1184  * @content_type: the content type to show applications for
1185  *
1186  * Creates a new #GtkAppChooserWidget for applications
1187  * that can handle content of the given type.
1188  *
1189  * Returns: a newly created #GtkAppChooserWidget
1190  *
1191  * Since: 3.0
1192  */
1193 GtkWidget *
1194 gtk_app_chooser_widget_new (const gchar *content_type)
1195 {
1196   return g_object_new (GTK_TYPE_APP_CHOOSER_WIDGET,
1197                        "content-type", content_type,
1198                        NULL);
1199 }
1200
1201 /**
1202  * gtk_app_chooser_widget_set_show_default:
1203  * @self: a #GtkAppChooserWidget
1204  * @setting: the new value for #GtkAppChooserWidget:show-default
1205  *
1206  * Sets whether the app chooser should show the default handler
1207  * for the content type in a separate section.
1208  *
1209  * Since: 3.0
1210  */
1211 void
1212 gtk_app_chooser_widget_set_show_default (GtkAppChooserWidget *self,
1213                                          gboolean             setting)
1214 {
1215   g_return_if_fail (GTK_IS_APP_CHOOSER_WIDGET (self));
1216
1217   if (self->priv->show_default != setting)
1218     {
1219       self->priv->show_default = setting;
1220
1221       g_object_notify (G_OBJECT (self), "show-default");
1222
1223       gtk_app_chooser_refresh (GTK_APP_CHOOSER (self));
1224     }
1225 }
1226
1227 /**
1228  * gtk_app_chooser_widget_get_show_default:
1229  * @self: a #GtkAppChooserWidget
1230  *
1231  * Returns the current value of the #GtkAppChooserWidget:show-default
1232  * property.
1233  *
1234  * Returns: the value of #GtkAppChooserWidget:show-default
1235  *
1236  * Since: 3.0
1237  */
1238 gboolean
1239 gtk_app_chooser_widget_get_show_default (GtkAppChooserWidget *self)
1240 {
1241   g_return_val_if_fail (GTK_IS_APP_CHOOSER_WIDGET (self), FALSE);
1242
1243   return self->priv->show_default;
1244 }
1245
1246 /**
1247  * gtk_app_chooser_widget_set_show_recommended:
1248  * @self: a #GtkAppChooserWidget
1249  * @setting: the new value for #GtkAppChooserWidget:show-recommended
1250  *
1251  * Sets whether the app chooser should show recommended applications
1252  * for the content type in a separate section.
1253  *
1254  * Since: 3.0
1255  */
1256 void
1257 gtk_app_chooser_widget_set_show_recommended (GtkAppChooserWidget *self,
1258                                              gboolean             setting)
1259 {
1260   g_return_if_fail (GTK_IS_APP_CHOOSER_WIDGET (self));
1261
1262   if (self->priv->show_recommended != setting)
1263     {
1264       self->priv->show_recommended = setting;
1265
1266       g_object_notify (G_OBJECT (self), "show-recommended");
1267
1268       gtk_app_chooser_refresh (GTK_APP_CHOOSER (self));
1269     }
1270 }
1271
1272 /**
1273  * gtk_app_chooser_widget_get_show_recommended:
1274  * @self: a #GtkAppChooserWidget
1275  *
1276  * Returns the current value of the #GtkAppChooserWidget:show-recommended
1277  * property.
1278  *
1279  * Returns: the value of #GtkAppChooserWidget:show-recommended
1280  *
1281  * Since: 3.0
1282  */
1283 gboolean
1284 gtk_app_chooser_widget_get_show_recommended (GtkAppChooserWidget *self)
1285 {
1286   g_return_val_if_fail (GTK_IS_APP_CHOOSER_WIDGET (self), FALSE);
1287
1288   return self->priv->show_recommended;
1289 }
1290
1291 /**
1292  * gtk_app_chooser_widget_set_show_fallback:
1293  * @self: a #GtkAppChooserWidget
1294  * @setting: the new value for #GtkAppChooserWidget:show-fallback
1295  *
1296  * Sets whether the app chooser should show related applications
1297  * for the content type in a separate section.
1298  *
1299  * Since: 3.0
1300  */
1301 void
1302 gtk_app_chooser_widget_set_show_fallback (GtkAppChooserWidget *self,
1303                                           gboolean             setting)
1304 {
1305   g_return_if_fail (GTK_IS_APP_CHOOSER_WIDGET (self));
1306
1307   if (self->priv->show_fallback != setting)
1308     {
1309       self->priv->show_fallback = setting;
1310
1311       g_object_notify (G_OBJECT (self), "show-fallback");
1312
1313       gtk_app_chooser_refresh (GTK_APP_CHOOSER (self));
1314     }
1315 }
1316
1317 /**
1318  * gtk_app_chooser_widget_get_show_fallback:
1319  * @self: a #GtkAppChooserWidget
1320  *
1321  * Returns the current value of the #GtkAppChooserWidget:show-fallback
1322  * property.
1323  *
1324  * Returns: the value of #GtkAppChooserWidget:show-fallback
1325  *
1326  * Since: 3.0
1327  */
1328 gboolean
1329 gtk_app_chooser_widget_get_show_fallback (GtkAppChooserWidget *self)
1330 {
1331   g_return_val_if_fail (GTK_IS_APP_CHOOSER_WIDGET (self), FALSE);
1332
1333   return self->priv->show_fallback;
1334 }
1335
1336 /**
1337  * gtk_app_chooser_widget_set_show_other:
1338  * @self: a #GtkAppChooserWidget
1339  * @setting: the new value for #GtkAppChooserWidget:show-other
1340  *
1341  * Sets whether the app chooser should show applications
1342  * which are unrelated to the content type.
1343  *
1344  * Since: 3.0
1345  */
1346 void
1347 gtk_app_chooser_widget_set_show_other (GtkAppChooserWidget *self,
1348                                        gboolean             setting)
1349 {
1350   g_return_if_fail (GTK_IS_APP_CHOOSER_WIDGET (self));
1351
1352   if (self->priv->show_other != setting)
1353     {
1354       self->priv->show_other = setting;
1355
1356       g_object_notify (G_OBJECT (self), "show-other");
1357
1358       gtk_app_chooser_refresh (GTK_APP_CHOOSER (self));
1359     }
1360 }
1361
1362 /**
1363  * gtk_app_chooser_widget_get_show_other:
1364  * @self: a #GtkAppChooserWidget
1365  *
1366  * Returns the current value of the #GtkAppChooserWidget:show-other
1367  * property.
1368  *
1369  * Returns: the value of #GtkAppChooserWidget:show-other
1370  *
1371  * Since: 3.0
1372  */
1373 gboolean
1374 gtk_app_chooser_widget_get_show_other (GtkAppChooserWidget *self)
1375 {
1376   g_return_val_if_fail (GTK_IS_APP_CHOOSER_WIDGET (self), FALSE);
1377
1378   return self->priv->show_other;
1379 }
1380
1381 /**
1382  * gtk_app_chooser_widget_set_show_all:
1383  * @self: a #GtkAppChooserWidget
1384  * @setting: the new value for #GtkAppChooserWidget:show-all
1385  *
1386  * Sets whether the app chooser should show all applications
1387  * in a flat list.
1388  *
1389  * Since: 3.0
1390  */
1391 void
1392 gtk_app_chooser_widget_set_show_all (GtkAppChooserWidget *self,
1393                                      gboolean             setting)
1394 {
1395   g_return_if_fail (GTK_IS_APP_CHOOSER_WIDGET (self));
1396
1397   if (self->priv->show_all != setting)
1398     {
1399       self->priv->show_all = setting;
1400
1401       g_object_notify (G_OBJECT (self), "show-all");
1402
1403       gtk_app_chooser_refresh (GTK_APP_CHOOSER (self));
1404     }
1405 }
1406
1407 /**
1408  * gtk_app_chooser_widget_get_show_all:
1409  * @self: a #GtkAppChooserWidget
1410  *
1411  * Returns the current value of the #GtkAppChooserWidget:show-all
1412  * property.
1413  *
1414  * Returns: the value of #GtkAppChooserWidget:show-all
1415  *
1416  * Since: 3.0
1417  */
1418 gboolean
1419 gtk_app_chooser_widget_get_show_all (GtkAppChooserWidget *self)
1420 {
1421   g_return_val_if_fail (GTK_IS_APP_CHOOSER_WIDGET (self), FALSE);
1422
1423   return self->priv->show_all;
1424 }
1425
1426 /**
1427  * gtk_app_chooser_widget_set_default_text:
1428  * @self: a #GtkAppChooserWidget
1429  * @text: the new value for #GtkAppChooserWidget:default-text
1430  *
1431  * Sets the text that is shown if there are not applications
1432  * that can handle the content type.
1433  */
1434 void
1435 gtk_app_chooser_widget_set_default_text (GtkAppChooserWidget *self,
1436                                          const gchar         *text)
1437 {
1438   g_return_if_fail (GTK_IS_APP_CHOOSER_WIDGET (self));
1439
1440   if (g_strcmp0 (text, self->priv->default_text) != 0)
1441     {
1442       g_free (self->priv->default_text);
1443       self->priv->default_text = g_strdup (text);
1444
1445       g_object_notify (G_OBJECT (self), "default-text");
1446
1447       gtk_app_chooser_refresh (GTK_APP_CHOOSER (self));
1448     }
1449 }
1450
1451 /**
1452  * gtk_app_chooser_widget_get_default_text:
1453  * @self: a #GtkAppChooserWidget
1454  *
1455  * Returns the text that is shown if there are not applications
1456  * that can handle the content type.
1457  *
1458  * Returns: the value of #GtkAppChooserWidget:default-text
1459  *
1460  * Since: 3.0
1461  */
1462 const gchar *
1463 gtk_app_chooser_widget_get_default_text (GtkAppChooserWidget *self)
1464 {
1465   g_return_val_if_fail (GTK_IS_APP_CHOOSER_WIDGET (self), NULL);
1466
1467   return self->priv->default_text;
1468 }