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_foreach (chooser
->priv
->selected_cache
, (GFunc
) g_free
, NULL
);
138 g_object_unref (launcher
);
142 on_package_toggled (GtkCellRenderer
* renderer
,
144 AnjutaPkgConfigChooser
* chooser
)
146 GtkTreeIter sort_iter
;
147 GtkTreeIter filter_iter
;
152 GtkTreePath
* tree_path
= gtk_tree_path_new_from_string (path
);
154 gtk_tree_model_get_iter (GTK_TREE_MODEL (chooser
->priv
->sort_model
),
155 &sort_iter
, tree_path
);
156 gtk_tree_model_sort_convert_iter_to_child_iter (chooser
->priv
->sort_model
,
157 &filter_iter
, &sort_iter
);
158 gtk_tree_model_filter_convert_iter_to_child_iter (chooser
->priv
->filter_model
,
159 &iter
, &filter_iter
);
160 g_object_get (renderer
, "active", &active
, NULL
);
164 gtk_list_store_set (GTK_LIST_STORE (chooser
->priv
->model
),
165 &iter
, COLUMN_ACTIVE
, active
, -1);
166 gtk_tree_model_get (chooser
->priv
->model
, &iter
,
167 COLUMN_NAME
, &package
, -1);
170 g_signal_emit_by_name (chooser
, "package-activated", package
, NULL
);
172 g_signal_emit_by_name (chooser
, "package-deactivated", package
, NULL
);
176 anjuta_pkg_config_chooser_init (AnjutaPkgConfigChooser
*chooser
)
178 GtkTreeViewColumn
* column
;
179 GtkCellRenderer
* renderer
;
181 chooser
->priv
= G_TYPE_INSTANCE_GET_PRIVATE (chooser
, ANJUTA_TYPE_PKG_CONFIG_CHOOSER
,
182 AnjutaPkgConfigChooserPrivate
);
185 chooser
->priv
->model
= GTK_TREE_MODEL (gtk_list_store_new (N_COLUMNS
,
189 chooser
->priv
->filter_model
= GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (chooser
->priv
->model
,
191 gtk_tree_model_filter_set_visible_func (chooser
->priv
->filter_model
,
195 chooser
->priv
->sort_model
=
196 GTK_TREE_MODEL_SORT (gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL(chooser
->priv
->filter_model
)));
197 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (chooser
->priv
->sort_model
),
198 COLUMN_NAME
, GTK_SORT_ASCENDING
);
200 gtk_tree_view_set_model (GTK_TREE_VIEW (chooser
),
201 GTK_TREE_MODEL (chooser
->priv
->sort_model
));
204 renderer
= gtk_cell_renderer_toggle_new ();
205 g_signal_connect (renderer
, "toggled", G_CALLBACK(on_package_toggled
), chooser
);
206 column
= gtk_tree_view_column_new_with_attributes ("",
208 "active", COLUMN_ACTIVE
,
210 gtk_tree_view_append_column (GTK_TREE_VIEW (chooser
), column
);
212 renderer
= gtk_cell_renderer_text_new ();
213 column
= gtk_tree_view_column_new_with_attributes ("",
217 gtk_tree_view_append_column (GTK_TREE_VIEW (chooser
), column
);
218 renderer
= gtk_cell_renderer_text_new ();
219 column
= gtk_tree_view_column_new_with_attributes ("",
221 "text", COLUMN_DESCRIPTION
,
223 gtk_tree_view_append_column (GTK_TREE_VIEW (chooser
), column
);
224 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (chooser
), FALSE
);
226 gtk_tree_view_set_search_column (GTK_TREE_VIEW (chooser
),
229 /* Create launcher */
230 chooser
->priv
->scanning
= TRUE
;
231 chooser
->priv
->launcher
= anjuta_launcher_new ();
232 anjuta_launcher_set_check_passwd_prompt (chooser
->priv
->launcher
,
235 g_signal_connect (G_OBJECT (chooser
->priv
->launcher
), "child-exited",
236 G_CALLBACK (on_listall_exit
), chooser
);
238 anjuta_launcher_execute (chooser
->priv
->launcher
,
239 PKG_CONFIG_LIST_ALL
, on_listall_output
,
244 anjuta_pkg_config_chooser_finalize (GObject
*object
)
247 G_OBJECT_CLASS (anjuta_pkg_config_chooser_parent_class
)->finalize (object
);
251 anjuta_pkg_config_chooser_class_init (AnjutaPkgConfigChooserClass
*klass
)
253 GObjectClass
* object_class
= G_OBJECT_CLASS (klass
);
255 object_class
->finalize
= anjuta_pkg_config_chooser_finalize
;
258 * AnjutaPkgConfigChooser::package-activated:
259 * @widget: the AnjutaPkgConfigChooser that received the signal
260 * @package: Name of the package that was activated
262 * The ::package-activated signal is emitted when a package is activated in the list
264 pkg_config_chooser_signals
[PACKAGE_ACTIVATED
] =
265 g_signal_new ("package-activated",
266 G_OBJECT_CLASS_TYPE (klass
),
268 G_STRUCT_OFFSET (AnjutaPkgConfigChooserClass
, package_activated
),
270 g_cclosure_marshal_VOID__STRING
,
274 * AnjutaPkgConfigChooser::package-deactivated:
275 * @widget: the AnjutaPkgConfigChooser that received the signal
276 * @package: Name of the package that was deactivated
278 * The ::package-activated signal is emitted when a package is deactivated in the list
280 pkg_config_chooser_signals
[PACKAGE_DEACTIVATED
] =
281 g_signal_new ("package-deactivated",
282 G_OBJECT_CLASS_TYPE (klass
),
284 G_STRUCT_OFFSET (AnjutaPkgConfigChooserClass
, package_deactivated
),
286 g_cclosure_marshal_VOID__STRING
,
290 g_type_class_add_private (klass
, sizeof(AnjutaPkgConfigChooserPrivate
));
294 * anjuta_pkg_config_chooser_new:
296 * Returns: A new AnjutaPkgConfigChooser widget
299 anjuta_pkg_config_chooser_new (void)
301 return GTK_WIDGET (g_object_new (ANJUTA_TYPE_PKG_CONFIG_CHOOSER
, NULL
));
305 * anjuta_pkg_config_chooser_get_active_packages:
306 * @chooser: A AnjutaPkgConfigChooser
308 * Return value: (element-type utf8) (transfer full):
309 * List of packages that are activated
312 anjuta_pkg_config_chooser_get_active_packages (AnjutaPkgConfigChooser
* chooser
)
314 GList
* packages
= NULL
;
317 g_return_val_if_fail (ANJUTA_IS_PKG_CONFIG_CHOOSER (chooser
), NULL
);
319 if (gtk_tree_model_get_iter_first (chooser
->priv
->model
, &iter
))
325 gtk_tree_model_get (chooser
->priv
->model
, &iter
,
326 COLUMN_NAME
, &model_pkg
,
327 COLUMN_ACTIVE
, &active
, -1);
330 packages
= g_list_append (packages
, model_pkg
);
333 while (gtk_tree_model_iter_next (chooser
->priv
->model
,
340 * anjuta_pkg_config_chooser_get_active_packages:
341 * @chooser: A AnjutaPkgConfigChooser
342 * @packages: (element-type utf8) (transfer full): List of packages to be activated in the list
346 anjuta_pkg_config_chooser_set_active_packages (AnjutaPkgConfigChooser
* chooser
, GList
* packages
)
351 g_return_if_fail (ANJUTA_IS_PKG_CONFIG_CHOOSER (chooser
));
353 /* Deselect all packages */
354 if (gtk_tree_model_get_iter_first (chooser
->priv
->model
, &iter
))
358 gtk_list_store_set (GTK_LIST_STORE (chooser
->priv
->model
), &iter
,
359 COLUMN_ACTIVE
, FALSE
, -1);
361 while (gtk_tree_model_iter_next (chooser
->priv
->model
,
365 for (pkg
= packages
; pkg
!= NULL
; pkg
= g_list_next (pkg
))
367 if (chooser
->priv
->scanning
)
369 chooser
->priv
->selected_cache
= g_list_append (chooser
->priv
->selected_cache
,
370 g_strdup(pkg
->data
));
372 else if (gtk_tree_model_get_iter_first (chooser
->priv
->model
, &iter
))
377 gtk_tree_model_get (chooser
->priv
->model
, &iter
,
378 COLUMN_NAME
, &model_pkg
, -1);
379 if (g_str_equal (model_pkg
, pkg
->data
))
381 gtk_list_store_set (GTK_LIST_STORE (chooser
->priv
->model
), &iter
,
382 COLUMN_ACTIVE
, TRUE
, -1);
386 while (gtk_tree_model_iter_next (chooser
->priv
->model
,
393 * anjuta_pkg_config_chooser_show_active_only:
394 * @chooser: A AnjutaPkgConfigChooser
395 * @show_selected: whether to show only activated packages
397 * Show activated packages only, this is mainly useful when the tree is set
398 * insensitive but the user should be able to see which packages have been activated
401 anjuta_pkg_config_chooser_show_active_only (AnjutaPkgConfigChooser
* chooser
, gboolean show_selected
)
403 g_return_if_fail (ANJUTA_IS_PKG_CONFIG_CHOOSER (chooser
));
405 chooser
->priv
->selected_only
= show_selected
;
406 gtk_tree_model_filter_refilter (chooser
->priv
->filter_model
);
410 * anjuta_pkg_config_chooser_show_active_column:
411 * @chooser: A AnjutaPkgConfigChooser
412 * @show_column: whether the active column should be shown
414 * Can be used to hide the active column in situation where you are more interested
415 * in the selection then in the activated packages.
418 anjuta_pkg_config_chooser_show_active_column (AnjutaPkgConfigChooser
* chooser
, gboolean show_column
)
420 GtkTreeViewColumn
* column
;
422 g_return_if_fail (ANJUTA_IS_PKG_CONFIG_CHOOSER (chooser
));
424 column
= gtk_tree_view_get_column (GTK_TREE_VIEW (chooser
), COLUMN_ACTIVE
);
425 gtk_tree_view_column_set_visible (column
, show_column
);
429 * anjuta_pkg_config_chooser_get_selected_package:
430 * @chooser: A AnjutaPkgConfigChooser
432 * Return value: the currently selected packages in the list
436 anjuta_pkg_config_chooser_get_selected_package (AnjutaPkgConfigChooser
* chooser
)
438 GtkTreeIter sort_iter
;
439 GtkTreeSelection
* selection
;
441 g_return_val_if_fail (ANJUTA_IS_PKG_CONFIG_CHOOSER (chooser
), NULL
);
443 selection
= gtk_tree_view_get_selection (GTK_TREE_VIEW (chooser
));
445 if (gtk_tree_selection_get_selected (selection
, NULL
, &sort_iter
))
448 GtkTreeIter filter_iter
;
450 gtk_tree_model_sort_convert_iter_to_child_iter (chooser
->priv
->sort_model
,
451 &filter_iter
, &sort_iter
);
452 gtk_tree_model_filter_convert_iter_to_child_iter (chooser
->priv
->filter_model
,
453 &iter
, &filter_iter
);
454 gtk_tree_model_get (chooser
->priv
->model
, &iter
, COLUMN_NAME
, &package
, -1);