1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
3
* Copyright (C) 2013 Richard Hughes <richard@hughsie.com>
4
* Copyright (C) 2013 Matthias Clasen <mclasen@redhat.com>
6
* Licensed under the GNU General Public License Version 2
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or
11
* (at your option) any later version.
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
18
* You should have received a copy of the GNU General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26
#include <glib/gi18n.h>
27
#include <appstream-glib.h>
30
#include "gs-shell-installed.h"
33
#include "gs-app-row.h"
34
#include "gs-app-folder-dialog.h"
35
#include "gs-folders.h"
37
static void gs_shell_installed_finalize (GObject *object);
39
struct GsShellInstalledPrivate
41
GsPluginLoader *plugin_loader;
43
GCancellable *cancellable;
44
GtkSizeGroup *sizegroup_image;
45
GtkSizeGroup *sizegroup_name;
49
gboolean selection_mode;
51
GtkWidget *bottom_install;
52
GtkWidget *button_folder_add;
53
GtkWidget *button_folder_move;
54
GtkWidget *button_folder_remove;
55
GtkWidget *list_box_install;
56
GtkWidget *scrolledwindow_install;
57
GtkWidget *spinner_install;
58
GtkWidget *stack_install;
61
G_DEFINE_TYPE_WITH_PRIVATE (GsShellInstalled, gs_shell_installed, GTK_TYPE_BIN)
63
static void gs_shell_installed_pending_apps_changed_cb (GsPluginLoader *plugin_loader,
64
GsShellInstalled *shell_installed);
65
static void set_selection_mode (GsShellInstalled *shell_installed, gboolean selection_mode);
68
* gs_shell_installed_invalidate:
71
gs_shell_installed_invalidate (GsShellInstalled *shell_installed)
73
shell_installed->priv->cache_valid = FALSE;
77
gs_shell_installed_app_row_activated_cb (GtkListBox *list_box,
79
GsShellInstalled *shell_installed)
81
if (shell_installed->priv->selection_mode) {
83
selected = gs_app_row_get_selected (GS_APP_ROW (row));
84
gs_app_row_set_selected (GS_APP_ROW (row), !selected);
87
app = gs_app_row_get_app (GS_APP_ROW (row));
88
gs_shell_show_app (shell_installed->priv->shell, app);
94
GsShellInstalled *shell_installed;
95
} GsShellInstalledHelper;
98
row_unrevealed (GObject *row, GParamSpec *pspec, gpointer data)
102
list = gtk_widget_get_parent (GTK_WIDGET (row));
103
gtk_container_remove (GTK_CONTAINER (list), GTK_WIDGET (row));
107
* gs_shell_installed_app_removed_cb:
110
gs_shell_installed_app_removed_cb (GObject *source,
114
GError *error = NULL;
115
GsPluginLoader *plugin_loader = GS_PLUGIN_LOADER (source);
116
GsShellInstalledHelper *helper = (GsShellInstalledHelper *) user_data;
117
GsShellInstalledPrivate *priv = helper->shell_installed->priv;
121
ret = gs_plugin_loader_app_action_finish (plugin_loader,
125
app = gs_app_row_get_app (helper->app_row);
126
g_warning ("failed to remove %s: %s",
129
gs_app_notify_failed_modal (app,
130
gs_shell_get_window (priv->shell),
131
GS_PLUGIN_LOADER_ACTION_REMOVE,
133
g_error_free (error);
135
/* remove from the list */
136
app = gs_app_row_get_app (helper->app_row);
137
g_debug ("removed %s", gs_app_get_id (app));
138
gs_app_row_unreveal (helper->app_row);
139
g_signal_connect (helper->app_row, "unrevealed",
140
G_CALLBACK (row_unrevealed), NULL);
143
g_object_unref (helper->app_row);
144
g_object_unref (helper->shell_installed);
149
* gs_shell_installed_app_remove_cb:
152
gs_shell_installed_app_remove_cb (GsAppRow *app_row,
153
GsShellInstalled *shell_installed)
156
GsShellInstalledPrivate *priv = shell_installed->priv;
158
GtkResponseType response;
160
GsShellInstalledHelper *helper;
162
markup = g_string_new ("");
163
app = gs_app_row_get_app (app_row);
164
g_string_append_printf (markup,
165
/* TRANSLATORS: this is a prompt message, and
166
* '%s' is an application summary, e.g. 'GNOME Clocks' */
167
_("Are you sure you want to remove %s?"),
168
gs_app_get_name (app));
169
g_string_prepend (markup, "<b>");
170
g_string_append (markup, "</b>");
171
dialog = gtk_message_dialog_new (gs_shell_get_window (priv->shell),
173
GTK_MESSAGE_QUESTION,
176
gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog), markup->str);
177
gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG (dialog),
178
/* TRANSLATORS: longer dialog text */
179
_("%s will be removed, and you will have to install it to use it again."),
180
gs_app_get_name (app));
181
/* TRANSLATORS: this is button text to remove the application */
182
gtk_dialog_add_button (GTK_DIALOG (dialog), _("Remove"), GTK_RESPONSE_OK);
183
if (gs_app_get_state (app) == AS_APP_STATE_QUEUED_FOR_INSTALL)
184
response = GTK_RESPONSE_OK; /* pending install */
186
response = gtk_dialog_run (GTK_DIALOG (dialog));
187
if (response == GTK_RESPONSE_OK) {
188
g_debug ("removing %s", gs_app_get_id (app));
189
helper = g_new0 (GsShellInstalledHelper, 1);
190
helper->shell_installed = g_object_ref (shell_installed);
191
helper->app_row = g_object_ref (app_row);
192
gs_plugin_loader_app_action_async (priv->plugin_loader,
194
GS_PLUGIN_LOADER_ACTION_REMOVE,
196
gs_shell_installed_app_removed_cb,
199
g_string_free (markup, TRUE);
200
gtk_widget_destroy (dialog);
204
gs_shell_installed_invalidate_sort_idle (gpointer user_data)
206
GsShellInstalled *shell = GS_SHELL_INSTALLED (user_data);
208
gtk_list_box_invalidate_sort (GTK_LIST_BOX (shell->priv->list_box_install));
210
g_object_unref (shell);
211
return G_SOURCE_REMOVE;
215
* gs_shell_installed_notify_state_changed_cb:
218
gs_shell_installed_notify_state_changed_cb (GsApp *app,
220
GsShellInstalled *shell)
222
g_idle_add (gs_shell_installed_invalidate_sort_idle, g_object_ref (shell));
225
static void selection_changed (GsShellInstalled *shell);
228
gs_shell_installed_add_app (GsShellInstalled *shell, GsApp *app)
230
GsShellInstalledPrivate *priv = shell->priv;
233
app_row = gs_app_row_new ();
234
gs_app_row_set_colorful (GS_APP_ROW (app_row), FALSE);
235
g_signal_connect (app_row, "button-clicked",
236
G_CALLBACK (gs_shell_installed_app_remove_cb), shell);
237
g_signal_connect_object (app, "notify::state",
238
G_CALLBACK (gs_shell_installed_notify_state_changed_cb),
240
g_signal_connect_swapped (app_row, "notify::selected",
241
G_CALLBACK (selection_changed), shell);
242
gs_app_row_set_app (GS_APP_ROW (app_row), app);
243
gtk_container_add (GTK_CONTAINER (priv->list_box_install), app_row);
244
gs_app_row_set_size_groups (GS_APP_ROW (app_row),
245
priv->sizegroup_image,
246
priv->sizegroup_name);
248
gs_app_row_set_selectable (GS_APP_ROW (app_row),
249
priv->selection_mode);
251
gtk_widget_show (app_row);
255
* gs_shell_installed_get_installed_cb:
258
gs_shell_installed_get_installed_cb (GObject *source_object,
262
GError *error = NULL;
266
GsShellInstalled *shell_installed = GS_SHELL_INSTALLED (user_data);
267
GsShellInstalledPrivate *priv = shell_installed->priv;
268
GsPluginLoader *plugin_loader = GS_PLUGIN_LOADER (source_object);
270
gs_stop_spinner (GTK_SPINNER (priv->spinner_install));
271
gtk_stack_set_visible_child_name (GTK_STACK (priv->stack_install), "view");
273
priv->waiting = FALSE;
274
priv->cache_valid = TRUE;
276
list = gs_plugin_loader_get_installed_finish (plugin_loader,
280
g_warning ("failed to get installed apps: %s", error->message);
281
g_error_free (error);
284
for (l = list; l != NULL; l = l->next) {
285
app = GS_APP (l->data);
286
gs_shell_installed_add_app (shell_installed, app);
289
gs_plugin_list_free (list);
290
gs_shell_installed_pending_apps_changed_cb (plugin_loader, shell_installed);
294
* gs_shell_installed_load:
297
gs_shell_installed_load (GsShellInstalled *shell_installed)
299
GsShellInstalledPrivate *priv = shell_installed->priv;
303
priv->waiting = TRUE;
305
/* remove old entries */
306
gs_container_remove_all (GTK_CONTAINER (priv->list_box_install));
308
/* get popular apps */
309
gs_plugin_loader_get_installed_async (priv->plugin_loader,
310
GS_PLUGIN_REFINE_FLAGS_DEFAULT |
311
GS_PLUGIN_REFINE_FLAGS_REQUIRE_HISTORY |
312
GS_PLUGIN_REFINE_FLAGS_REQUIRE_SETUP_ACTION |
313
GS_PLUGIN_REFINE_FLAGS_REQUIRE_VERSION |
314
GS_PLUGIN_REFINE_FLAGS_REQUIRE_DESCRIPTION |
315
GS_PLUGIN_REFINE_FLAGS_REQUIRE_RATING,
317
gs_shell_installed_get_installed_cb,
319
gs_start_spinner (GTK_SPINNER (priv->spinner_install));
320
gtk_stack_set_visible_child_name (GTK_STACK (priv->stack_install), "spinner");
324
* gs_shell_installed_reload:
327
gs_shell_installed_reload (GsShellInstalled *shell_installed)
329
gs_shell_installed_invalidate (shell_installed);
330
gs_shell_installed_load (shell_installed);
334
* gs_shell_installed_switch_to:
337
gs_shell_installed_switch_to (GsShellInstalled *shell_installed, gboolean scroll_up)
339
GsShellInstalledPrivate *priv = shell_installed->priv;
342
if (gs_shell_get_mode (priv->shell) != GS_SHELL_MODE_INSTALLED) {
343
g_warning ("Called switch_to(installed) when in mode %s",
344
gs_shell_get_mode_string (priv->shell));
348
set_selection_mode (shell_installed, FALSE);
349
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "buttonbox_main"));
350
gtk_widget_show (widget);
352
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "button_select"));
353
gtk_widget_show (widget);
355
gtk_list_box_invalidate_sort (GTK_LIST_BOX (priv->list_box_install));
359
adj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scrolledwindow_install));
360
gtk_adjustment_set_value (adj, gtk_adjustment_get_lower (adj));
362
if (gs_shell_get_mode (priv->shell) == GS_SHELL_MODE_INSTALLED) {
363
gs_grab_focus_when_mapped (priv->scrolledwindow_install);
366
/* no need to refresh */
367
if (priv->cache_valid)
370
gs_shell_installed_load (shell_installed);
374
* gs_shell_installed_get_app_sort_key:
376
* Get a sort key to achive this:
378
* 1. state:installing applications
379
* 2. state:removing applications
380
* 3. kind:normal applications
381
* 4. kind:system applications
383
* Within each of these groups, they are sorted by the install date and then
387
gs_shell_installed_get_app_sort_key (GsApp *app)
390
gchar *casefolded_name;
392
key = g_string_sized_new (64);
394
/* sort installed, removing, other */
395
switch (gs_app_get_state (app)) {
396
case AS_APP_STATE_INSTALLING:
397
case AS_APP_STATE_QUEUED_FOR_INSTALL:
398
g_string_append (key, "1:");
400
case AS_APP_STATE_REMOVING:
401
g_string_append (key, "2:");
404
g_string_append (key, "3:");
408
/* sort desktop files, then addons */
409
switch (gs_app_get_id_kind (app)) {
410
case AS_ID_KIND_DESKTOP:
411
case AS_ID_KIND_WEB_APP:
412
g_string_append (key, "1:");
415
g_string_append (key, "2:");
419
/* sort normal, system, other */
420
switch (gs_app_get_kind (app)) {
421
case GS_APP_KIND_NORMAL:
422
g_string_append (key, "1:");
424
case GS_APP_KIND_SYSTEM:
425
g_string_append (key, "2:");
428
g_string_append (key, "3:");
432
/* finally, sort by short name */
433
casefolded_name = g_utf8_casefold (gs_app_get_name (app), -1);
434
g_string_append (key, casefolded_name);
435
g_free (casefolded_name);
437
return g_string_free (key, FALSE);
441
* gs_shell_installed_sort_func:
444
gs_shell_installed_sort_func (GtkListBoxRow *a,
454
if (!GTK_IS_BIN(a) || !GTK_IS_BIN(b)) {
455
g_warning ("GtkListBoxRow not valid");
459
a1 = gs_app_row_get_app (GS_APP_ROW (a));
460
a2 = gs_app_row_get_app (GS_APP_ROW (b));
461
key1 = gs_shell_installed_get_app_sort_key (a1);
462
key2 = gs_shell_installed_get_app_sort_key (a2);
464
/* compare the keys according to the algorithm above */
465
retval = g_strcmp0 (key1, key2);
473
* gs_shell_installed_is_addon_id_kind
476
gs_shell_installed_is_addon_id_kind (GsApp *app)
479
id_kind = gs_app_get_id_kind (app);
480
if (id_kind == AS_ID_KIND_DESKTOP)
482
if (id_kind == AS_ID_KIND_WEB_APP)
488
gs_shell_installed_is_system_application (GsApp *app)
490
if (gs_app_get_id_kind (app) == AS_ID_KIND_DESKTOP &&
491
gs_app_get_kind (app) == GS_APP_KIND_SYSTEM)
497
* gs_shell_installed_list_header_func
500
gs_shell_installed_list_header_func (GtkListBoxRow *row,
501
GtkListBoxRow *before,
504
GtkStyleContext *context;
508
gtk_list_box_row_set_header (row, NULL);
512
if (!gs_shell_installed_is_system_application (gs_app_row_get_app (GS_APP_ROW (before))) &&
513
gs_shell_installed_is_system_application (gs_app_row_get_app (GS_APP_ROW (row)))) {
514
/* TRANSLATORS: This is the header dividing the normal
515
* applications and the system ones */
516
header = gtk_label_new (_("System Applications"));
517
g_object_set (header,
520
context = gtk_widget_get_style_context (header);
521
gtk_style_context_add_class (context, "header-label");
522
} else if (!gs_shell_installed_is_addon_id_kind (gs_app_row_get_app (GS_APP_ROW (before))) &&
523
gs_shell_installed_is_addon_id_kind (gs_app_row_get_app (GS_APP_ROW (row)))) {
524
/* TRANSLATORS: This is the header dividing the normal
525
* applications and the addons */
526
header = gtk_label_new (_("Add-ons"));
527
g_object_set (header,
530
context = gtk_widget_get_style_context (header);
531
gtk_style_context_add_class (context, "header-label");
533
header = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
535
gtk_list_box_row_set_header (row, header);
539
gs_shell_installed_has_app (GsShellInstalled *shell_installed,
542
GsShellInstalledPrivate *priv = shell_installed->priv;
544
gboolean ret = FALSE;
546
children = gtk_container_get_children (GTK_CONTAINER (priv->list_box_install));
547
for (l = children; l; l = l->next) {
548
GsAppRow *app_row = GS_APP_ROW (l->data);
549
if (gs_app_row_get_app (app_row) == app) {
554
g_list_free (children);
560
* gs_shell_installed_pending_apps_changed_cb:
563
gs_shell_installed_pending_apps_changed_cb (GsPluginLoader *plugin_loader,
564
GsShellInstalled *shell_installed)
572
widget = GTK_WIDGET (gtk_builder_get_object (shell_installed->priv->builder,
573
"button_installed_counter"));
574
pending = gs_plugin_loader_get_pending (plugin_loader);
575
if (pending->len == 0) {
576
gtk_widget_hide (widget);
578
gtk_widget_show (widget);
579
label = g_strdup_printf ("%d", pending->len);
580
gtk_label_set_label (GTK_LABEL (widget), label);
583
for (i = 0; i < pending->len; i++) {
584
app = GS_APP (g_ptr_array_index (pending, i));
585
/* Be careful not to add pending apps more than once. */
586
if (gs_shell_installed_has_app (shell_installed, app) == FALSE)
587
gs_shell_installed_add_app (shell_installed, app);
590
g_ptr_array_unref (pending);
594
set_selection_mode (GsShellInstalled *shell_installed, gboolean selection_mode)
596
GsShellInstalledPrivate *priv = shell_installed->priv;
600
GtkStyleContext *context;
602
if (priv->selection_mode == selection_mode)
605
priv->selection_mode = selection_mode;
607
header = GTK_WIDGET (gtk_builder_get_object (priv->builder, "header"));
608
context = gtk_widget_get_style_context (header);
609
if (priv->selection_mode) {
610
gtk_header_bar_set_show_close_button (GTK_HEADER_BAR (header), FALSE);
611
gtk_style_context_add_class (context, "selection-mode");
612
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "button_select"));
613
gtk_button_set_image (GTK_BUTTON (widget), NULL);
614
gtk_button_set_label (GTK_BUTTON (widget), _("_Cancel"));
615
gtk_button_set_use_underline (GTK_BUTTON (widget), TRUE);
616
gtk_widget_show (widget);
617
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "buttonbox_main"));
618
gtk_widget_hide (widget);
619
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "header_selection_menu_button"));
620
gtk_widget_show (widget);
621
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "header_selection_label"));
622
gtk_label_set_label (GTK_LABEL (widget), _("Click on items to select them"));
624
gtk_header_bar_set_show_close_button (GTK_HEADER_BAR (header), TRUE);
625
gtk_style_context_remove_class (context, "selection-mode");
626
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "button_select"));
627
gtk_button_set_image (GTK_BUTTON (widget), gtk_image_new_from_icon_name ("object-select-symbolic", GTK_ICON_SIZE_MENU));
628
gtk_button_set_label (GTK_BUTTON (widget), NULL);
629
gtk_widget_show (widget);
630
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "buttonbox_main"));
631
gtk_widget_show (widget);
632
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "header_selection_menu_button"));
633
gtk_widget_hide (widget);
635
gtk_widget_hide (priv->button_folder_add);
636
gtk_widget_hide (priv->button_folder_move);
637
gtk_widget_hide (priv->button_folder_remove);
640
children = gtk_container_get_children (GTK_CONTAINER (priv->list_box_install));
641
for (l = children; l; l = l->next) {
642
GsAppRow *app_row = GS_APP_ROW (l->data);
643
gs_app_row_set_selectable (app_row,
644
priv->selection_mode);
646
g_list_free (children);
648
gtk_revealer_set_reveal_child (GTK_REVEALER (priv->bottom_install), priv->selection_mode);
652
selection_mode_cb (GtkButton *button, GsShellInstalled *shell_installed)
654
GsShellInstalledPrivate *priv = shell_installed->priv;
656
set_selection_mode (shell_installed, !priv->selection_mode);
660
get_selected_apps (GsShellInstalled *shell_installed)
662
GsShellInstalledPrivate *priv = shell_installed->priv;
663
GList *children, *l, *list;
666
children = gtk_container_get_children (GTK_CONTAINER (priv->list_box_install));
667
for (l = children; l; l = l->next) {
668
GsAppRow *app_row = GS_APP_ROW (l->data);
669
if (gs_app_row_get_selected (app_row)) {
670
list = g_list_prepend (list, gs_app_row_get_app (app_row));
673
g_list_free (children);
679
selection_changed (GsShellInstalled *shell_installed)
681
GsShellInstalledPrivate *priv = shell_installed->priv;
685
gboolean has_folders, has_nonfolders;
687
folders = gs_folders_get ();
688
has_folders = has_nonfolders = FALSE;
689
apps = get_selected_apps (shell_installed);
690
for (l = apps; l; l = l->next) {
692
if (gs_folders_get_app_folder (folders,
694
gs_app_get_categories (app))) {
697
has_nonfolders = TRUE;
701
g_object_unref (folders);
703
gtk_widget_set_visible (priv->button_folder_add, has_nonfolders);
704
gtk_widget_set_visible (priv->button_folder_move, has_folders && !has_nonfolders);
705
gtk_widget_set_visible (priv->button_folder_remove, has_folders);
709
folder_dialog_done (GsShellInstalled *shell_installed)
711
set_selection_mode (shell_installed, FALSE);
716
show_folder_dialog (GtkButton *button, GsShellInstalled *shell_installed)
722
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (button));
723
apps = get_selected_apps (shell_installed);
724
dialog = gs_app_folder_dialog_new (GTK_WINDOW (toplevel), apps);
726
gtk_window_present (GTK_WINDOW (dialog));
727
g_signal_connect_swapped (dialog, "delete-event",
728
G_CALLBACK (folder_dialog_done), shell_installed);
732
remove_folders (GtkButton *button, GsShellInstalled *shell_installed)
738
folders = gs_folders_get ();
739
apps = get_selected_apps (shell_installed);
740
for (l = apps; l; l = l->next) {
742
gs_folders_set_app_folder (folders,
744
gs_app_get_categories (app),
749
gs_folders_save (folders);
750
g_object_unref (folders);
752
set_selection_mode (shell_installed, FALSE);
756
select_all_cb (GtkMenuItem *item, GsShellInstalled *shell_installed)
758
GsShellInstalledPrivate *priv = shell_installed->priv;
761
children = gtk_container_get_children (GTK_CONTAINER (priv->list_box_install));
762
for (l = children; l; l = l->next) {
763
GsAppRow *app_row = GS_APP_ROW (l->data);
764
gs_app_row_set_selected (app_row, TRUE);
766
g_list_free (children);
770
select_none_cb (GtkMenuItem *item, GsShellInstalled *shell_installed)
772
GsShellInstalledPrivate *priv = shell_installed->priv;
775
children = gtk_container_get_children (GTK_CONTAINER (priv->list_box_install));
776
for (l = children; l; l = l->next) {
777
GsAppRow *app_row = GS_APP_ROW (l->data);
778
gs_app_row_set_selected (app_row, FALSE);
780
g_list_free (children);
784
* gs_shell_installed_setup:
787
gs_shell_installed_setup (GsShellInstalled *shell_installed,
789
GsPluginLoader *plugin_loader,
791
GCancellable *cancellable)
793
GsShellInstalledPrivate *priv = shell_installed->priv;
796
g_return_if_fail (GS_IS_SHELL_INSTALLED (shell_installed));
799
priv->plugin_loader = g_object_ref (plugin_loader);
800
g_signal_connect (priv->plugin_loader, "pending-apps-changed",
801
G_CALLBACK (gs_shell_installed_pending_apps_changed_cb),
804
priv->builder = g_object_ref (builder);
805
priv->cancellable = g_object_ref (cancellable);
807
/* setup installed */
808
g_signal_connect (priv->list_box_install, "row-activated",
809
G_CALLBACK (gs_shell_installed_app_row_activated_cb), shell_installed);
810
gtk_list_box_set_header_func (GTK_LIST_BOX (priv->list_box_install),
811
gs_shell_installed_list_header_func,
812
shell_installed, NULL);
813
gtk_list_box_set_sort_func (GTK_LIST_BOX (priv->list_box_install),
814
gs_shell_installed_sort_func,
815
shell_installed, NULL);
817
g_signal_connect (priv->button_folder_add, "clicked",
818
G_CALLBACK (show_folder_dialog), shell_installed);
820
g_signal_connect (priv->button_folder_move, "clicked",
821
G_CALLBACK (show_folder_dialog), shell_installed);
823
g_signal_connect (priv->button_folder_remove, "clicked",
824
G_CALLBACK (remove_folders), shell_installed);
826
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "button_select"));
827
g_signal_connect (widget, "clicked",
828
G_CALLBACK (selection_mode_cb), shell_installed);
830
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "button_select"));
831
gtk_button_set_image (GTK_BUTTON (widget), gtk_image_new_from_icon_name ("object-select-symbolic", GTK_ICON_SIZE_MENU));
832
gtk_button_set_label (GTK_BUTTON (widget), NULL);
834
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "select_all_menuitem"));
835
g_signal_connect (widget, "activate",
836
G_CALLBACK (select_all_cb), shell_installed);
837
widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "select_none_menuitem"));
838
g_signal_connect (widget, "activate",
839
G_CALLBACK (select_none_cb), shell_installed);
843
* gs_shell_installed_class_init:
846
gs_shell_installed_class_init (GsShellInstalledClass *klass)
848
GObjectClass *object_class = G_OBJECT_CLASS (klass);
849
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
851
object_class->finalize = gs_shell_installed_finalize;
853
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Software/gs-shell-installed.ui");
855
gtk_widget_class_bind_template_child_private (widget_class, GsShellInstalled, bottom_install);
856
gtk_widget_class_bind_template_child_private (widget_class, GsShellInstalled, button_folder_add);
857
gtk_widget_class_bind_template_child_private (widget_class, GsShellInstalled, button_folder_move);
858
gtk_widget_class_bind_template_child_private (widget_class, GsShellInstalled, button_folder_remove);
859
gtk_widget_class_bind_template_child_private (widget_class, GsShellInstalled, list_box_install);
860
gtk_widget_class_bind_template_child_private (widget_class, GsShellInstalled, scrolledwindow_install);
861
gtk_widget_class_bind_template_child_private (widget_class, GsShellInstalled, spinner_install);
862
gtk_widget_class_bind_template_child_private (widget_class, GsShellInstalled, stack_install);
866
* gs_shell_installed_init:
869
gs_shell_installed_init (GsShellInstalled *shell_installed)
871
gtk_widget_init_template (GTK_WIDGET (shell_installed));
873
shell_installed->priv = gs_shell_installed_get_instance_private (shell_installed);
874
shell_installed->priv->sizegroup_image = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
875
shell_installed->priv->sizegroup_name = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
879
* gs_shell_installed_finalize:
882
gs_shell_installed_finalize (GObject *object)
884
GsShellInstalled *shell_installed = GS_SHELL_INSTALLED (object);
885
GsShellInstalledPrivate *priv = shell_installed->priv;
887
g_object_unref (priv->sizegroup_image);
888
g_object_unref (priv->sizegroup_name);
890
g_object_unref (priv->builder);
891
g_object_unref (priv->plugin_loader);
892
g_object_unref (priv->cancellable);
894
G_OBJECT_CLASS (gs_shell_installed_parent_class)->finalize (object);
898
* gs_shell_installed_new:
901
gs_shell_installed_new (void)
903
GsShellInstalled *shell_installed;
904
shell_installed = g_object_new (GS_TYPE_SHELL_INSTALLED, NULL);
905
return GS_SHELL_INSTALLED (shell_installed);
908
/* vim: set noexpandtab: */