1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 * Copyright (C) Johannes Schmid 2010 <jhs@gnome.org>
6 * pkg-config-chooser is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
11 * pkg-config-chooser is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "anjuta-pkg-config-chooser.h"
21 #include <glib/gi18n.h>
22 #include <libanjuta/anjuta-launcher.h>
24 #define PKG_CONFIG_LIST_ALL "pkg-config --list-all"
41 struct _AnjutaPkgConfigChooserPrivate
43 AnjutaLauncher
* launcher
;
45 GtkTreeModelFilter
* filter_model
;
46 GtkTreeModelSort
* sort_model
;
48 gboolean selected_only
;
51 GList
* selected_cache
;
54 static guint pkg_config_chooser_signals
[LAST_SIGNAL
] = { 0 };
56 G_DEFINE_TYPE (AnjutaPkgConfigChooser
, anjuta_pkg_config_chooser
, GTK_TYPE_TREE_VIEW
);
59 filter_visible_func (GtkTreeModel
* model
,
63 AnjutaPkgConfigChooser
* chooser
= data
;
65 if (!chooser
->priv
->selected_only
)
70 gtk_tree_model_get (model
, iter
,
71 COLUMN_ACTIVE
, &show
, -1);
77 on_listall_output (AnjutaLauncher
* launcher
,
78 AnjutaLauncherOutputType output_type
,
79 const gchar
* chars
, gpointer user_data
)
82 const gchar
*curr_line
;
84 AnjutaPkgConfigChooser
* chooser
;
87 if (output_type
== ANJUTA_LAUNCHER_OUTPUT_STDERR
)
89 /* no way. We don't like errors on stderr... */
93 chooser
= ANJUTA_PKG_CONFIG_CHOOSER (user_data
);
95 store
= GTK_LIST_STORE (chooser
->priv
->model
);
96 lines
= g_strsplit (chars
, "\n", -1);
98 while ((curr_line
= lines
[i
++]) != NULL
)
103 pkgs
= g_strsplit (curr_line
, " ", 2);
105 /* just take the first token as it's the package-name */
109 if (pkgs
[0] == NULL
|| pkgs
[1] == NULL
) {
114 gtk_list_store_append (store
, &iter
);
115 gtk_list_store_set (store
, &iter
,
116 COLUMN_ACTIVE
, FALSE
,
117 COLUMN_NAME
, pkgs
[0],
118 COLUMN_DESCRIPTION
, g_strstrip(pkgs
[1]), -1);
125 on_listall_exit (AnjutaLauncher
* launcher
, int child_pid
,
126 int exit_status
, gulong time_taken_in_seconds
,
129 AnjutaPkgConfigChooser
* chooser
= ANJUTA_PKG_CONFIG_CHOOSER (user_data
);
131 g_signal_handlers_disconnect_by_func (launcher
, on_listall_exit
,
133 chooser
->priv
->scanning
= FALSE
;
135 anjuta_pkg_config_chooser_set_active_packages (chooser
, chooser
->priv
->selected_cache
);
136 g_list_free_full (chooser
->priv
->selected_cache
, g_free
);
137 chooser
->priv
->selected_cache
= NULL
;
139 g_clear_object (&chooser
->priv
->launcher
);
143 on_package_toggled (GtkCellRenderer
* renderer
,
145 AnjutaPkgConfigChooser
* chooser
)
147 GtkTreeIter sort_iter
;
148 GtkTreeIter filter_iter
;
153 GtkTreePath
* tree_path
= gtk_tree_path_new_from_string (path
);
155 gtk_tree_model_get_iter (GTK_TREE_MODEL (chooser
->priv
->sort_model
),
156 &sort_iter
, tree_path
);
157 gtk_tree_model_sort_convert_iter_to_child_iter (chooser
->priv
->sort_model
,
158 &filter_iter
, &sort_iter
);
159 gtk_tree_model_filter_convert_iter_to_child_iter (chooser
->priv
->filter_model
,
160 &iter
, &filter_iter
);
161 g_object_get (renderer
, "active", &active
, NULL
);
165 gtk_list_store_set (GTK_LIST_STORE (chooser
->priv
->model
),
166 &iter
, COLUMN_ACTIVE
, active
, -1);
167 gtk_tree_model_get (chooser
->priv
->model
, &iter
,
168 COLUMN_NAME
, &package
, -1);
171 g_signal_emit_by_name (chooser
, "package-activated", package
, NULL
);
173 g_signal_emit_by_name (chooser
, "package-deactivated", package
, NULL
);
177 anjuta_pkg_config_chooser_init (AnjutaPkgConfigChooser
*chooser
)
179 GtkTreeViewColumn
* column
;
180 GtkCellRenderer
* renderer
;
182 chooser
->priv
= G_TYPE_INSTANCE_GET_PRIVATE (chooser
, ANJUTA_TYPE_PKG_CONFIG_CHOOSER
,
183 AnjutaPkgConfigChooserPrivate
);
186 chooser
->priv
->model
= GTK_TREE_MODEL (gtk_list_store_new (N_COLUMNS
,
190 chooser
->priv
->filter_model
= GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (chooser
->priv
->model
,
192 gtk_tree_model_filter_set_visible_func (chooser
->priv
->filter_model
,
196 chooser
->priv
->sort_model
=
197 GTK_TREE_MODEL_SORT (gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL(chooser
->priv
->filter_model
)));
198 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (chooser
->priv
->sort_model
),
199 COLUMN_NAME
, GTK_SORT_ASCENDING
);
201 gtk_tree_view_set_model (GTK_TREE_VIEW (chooser
),
202 GTK_TREE_MODEL (chooser
->priv
->sort_model
));
205 renderer
= gtk_cell_renderer_toggle_new ();
206 g_signal_connect (renderer
, "toggled", G_CALLBACK(on_package_toggled
), chooser
);
207 column
= gtk_tree_view_column_new_with_attributes ("",
209 "active", COLUMN_ACTIVE
,
211 gtk_tree_view_append_column (GTK_TREE_VIEW (chooser
), column
);
213 renderer
= gtk_cell_renderer_text_new ();
214 column
= gtk_tree_view_column_new_with_attributes ("",
218 gtk_tree_view_append_column (GTK_TREE_VIEW (chooser
), column
);
219 renderer
= gtk_cell_renderer_text_new ();
220 column
= gtk_tree_view_column_new_with_attributes ("",
222 "text", COLUMN_DESCRIPTION
,
224 gtk_tree_view_append_column (GTK_TREE_VIEW (chooser
), column
);
225 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (chooser
), FALSE
);
227 gtk_tree_view_set_search_column (GTK_TREE_VIEW (chooser
),
230 /* Create launcher */
231 chooser
->priv
->scanning
= TRUE
;
232 chooser
->priv
->launcher
= anjuta_launcher_new ();
233 anjuta_launcher_set_check_passwd_prompt (chooser
->priv
->launcher
,
236 g_signal_connect (G_OBJECT (chooser
->priv
->launcher
), "child-exited",
237 G_CALLBACK (on_listall_exit
), chooser
);
239 anjuta_launcher_execute (chooser
->priv
->launcher
,
240 PKG_CONFIG_LIST_ALL
, on_listall_output
,
245 anjuta_pkg_config_chooser_finalize (GObject
*object
)
247 AnjutaPkgConfigChooser
*chooser
= ANJUTA_PKG_CONFIG_CHOOSER (object
);
249 g_object_unref (chooser
->priv
->model
);
250 g_object_unref (chooser
->priv
->filter_model
);
251 g_object_unref (chooser
->priv
->sort_model
);
253 if (chooser
->priv
->launcher
)
254 g_object_unref (chooser
->priv
->launcher
);
256 g_list_free_full (chooser
->priv
->selected_cache
, g_free
);
258 G_OBJECT_CLASS (anjuta_pkg_config_chooser_parent_class
)->finalize (object
);
262 anjuta_pkg_config_chooser_class_init (AnjutaPkgConfigChooserClass
*klass
)
264 GObjectClass
* object_class
= G_OBJECT_CLASS (klass
);
266 object_class
->finalize
= anjuta_pkg_config_chooser_finalize
;
269 * AnjutaPkgConfigChooser::package-activated:
270 * @widget: the AnjutaPkgConfigChooser that received the signal
271 * @package: Name of the package that was activated
273 * The ::package-activated signal is emitted when a package is activated in the list
275 pkg_config_chooser_signals
[PACKAGE_ACTIVATED
] =
276 g_signal_new ("package-activated",
277 G_OBJECT_CLASS_TYPE (klass
),
279 G_STRUCT_OFFSET (AnjutaPkgConfigChooserClass
, package_activated
),
281 g_cclosure_marshal_VOID__STRING
,
285 * AnjutaPkgConfigChooser::package-deactivated:
286 * @widget: the AnjutaPkgConfigChooser that received the signal
287 * @package: Name of the package that was deactivated
289 * The ::package-activated signal is emitted when a package is deactivated in the list
291 pkg_config_chooser_signals
[PACKAGE_DEACTIVATED
] =
292 g_signal_new ("package-deactivated",
293 G_OBJECT_CLASS_TYPE (klass
),
295 G_STRUCT_OFFSET (AnjutaPkgConfigChooserClass
, package_deactivated
),
297 g_cclosure_marshal_VOID__STRING
,
301 g_type_class_add_private (klass
, sizeof(AnjutaPkgConfigChooserPrivate
));
305 * anjuta_pkg_config_chooser_new:
307 * Returns: A new AnjutaPkgConfigChooser widget
310 anjuta_pkg_config_chooser_new (void)
312 return GTK_WIDGET (g_object_new (ANJUTA_TYPE_PKG_CONFIG_CHOOSER
, NULL
));
316 * anjuta_pkg_config_chooser_get_active_packages:
317 * @chooser: A AnjutaPkgConfigChooser
319 * Return value: (element-type utf8) (transfer full):
320 * List of packages that are activated
323 anjuta_pkg_config_chooser_get_active_packages (AnjutaPkgConfigChooser
* chooser
)
325 GList
* packages
= NULL
;
328 g_return_val_if_fail (ANJUTA_IS_PKG_CONFIG_CHOOSER (chooser
), NULL
);
330 if (gtk_tree_model_get_iter_first (chooser
->priv
->model
, &iter
))
336 gtk_tree_model_get (chooser
->priv
->model
, &iter
,
337 COLUMN_NAME
, &model_pkg
,
338 COLUMN_ACTIVE
, &active
, -1);
341 packages
= g_list_append (packages
, model_pkg
);
344 while (gtk_tree_model_iter_next (chooser
->priv
->model
,
351 * anjuta_pkg_config_chooser_get_active_packages:
352 * @chooser: A AnjutaPkgConfigChooser
353 * @packages: (element-type utf8) (transfer full): List of packages to be activated in the list
357 anjuta_pkg_config_chooser_set_active_packages (AnjutaPkgConfigChooser
* chooser
, GList
* packages
)
362 g_return_if_fail (ANJUTA_IS_PKG_CONFIG_CHOOSER (chooser
));
364 /* Deselect all packages */
365 if (gtk_tree_model_get_iter_first (chooser
->priv
->model
, &iter
))
369 gtk_list_store_set (GTK_LIST_STORE (chooser
->priv
->model
), &iter
,
370 COLUMN_ACTIVE
, FALSE
, -1);
372 while (gtk_tree_model_iter_next (chooser
->priv
->model
,
376 for (pkg
= packages
; pkg
!= NULL
; pkg
= g_list_next (pkg
))
378 if (chooser
->priv
->scanning
)
380 chooser
->priv
->selected_cache
= g_list_append (chooser
->priv
->selected_cache
,
381 g_strdup(pkg
->data
));
383 else if (gtk_tree_model_get_iter_first (chooser
->priv
->model
, &iter
))
388 gtk_tree_model_get (chooser
->priv
->model
, &iter
,
389 COLUMN_NAME
, &model_pkg
, -1);
390 if (g_str_equal (model_pkg
, pkg
->data
))
392 gtk_list_store_set (GTK_LIST_STORE (chooser
->priv
->model
), &iter
,
393 COLUMN_ACTIVE
, TRUE
, -1);
397 while (gtk_tree_model_iter_next (chooser
->priv
->model
,
404 * anjuta_pkg_config_chooser_show_active_only:
405 * @chooser: A AnjutaPkgConfigChooser
406 * @show_selected: whether to show only activated packages
408 * Show activated packages only, this is mainly useful when the tree is set
409 * insensitive but the user should be able to see which packages have been activated
412 anjuta_pkg_config_chooser_show_active_only (AnjutaPkgConfigChooser
* chooser
, gboolean show_selected
)
414 g_return_if_fail (ANJUTA_IS_PKG_CONFIG_CHOOSER (chooser
));
416 chooser
->priv
->selected_only
= show_selected
;
417 gtk_tree_model_filter_refilter (chooser
->priv
->filter_model
);
421 * anjuta_pkg_config_chooser_show_active_column:
422 * @chooser: A AnjutaPkgConfigChooser
423 * @show_column: whether the active column should be shown
425 * Can be used to hide the active column in situation where you are more interested
426 * in the selection then in the activated packages.
429 anjuta_pkg_config_chooser_show_active_column (AnjutaPkgConfigChooser
* chooser
, gboolean show_column
)
431 GtkTreeViewColumn
* column
;
433 g_return_if_fail (ANJUTA_IS_PKG_CONFIG_CHOOSER (chooser
));
435 column
= gtk_tree_view_get_column (GTK_TREE_VIEW (chooser
), COLUMN_ACTIVE
);
436 gtk_tree_view_column_set_visible (column
, show_column
);
440 * anjuta_pkg_config_chooser_get_selected_package:
441 * @chooser: A AnjutaPkgConfigChooser
443 * Return value: the currently selected packages in the list
447 anjuta_pkg_config_chooser_get_selected_package (AnjutaPkgConfigChooser
* chooser
)
449 GtkTreeIter sort_iter
;
450 GtkTreeSelection
* selection
;
452 g_return_val_if_fail (ANJUTA_IS_PKG_CONFIG_CHOOSER (chooser
), NULL
);
454 selection
= gtk_tree_view_get_selection (GTK_TREE_VIEW (chooser
));
456 if (gtk_tree_selection_get_selected (selection
, NULL
, &sort_iter
))
459 GtkTreeIter filter_iter
;
461 gtk_tree_model_sort_convert_iter_to_child_iter (chooser
->priv
->sort_model
,
462 &filter_iter
, &sort_iter
);
463 gtk_tree_model_filter_convert_iter_to_child_iter (chooser
->priv
->filter_model
,
464 &iter
, &filter_iter
);
465 gtk_tree_model_get (chooser
->priv
->model
, &iter
, COLUMN_NAME
, &package
, -1);