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 /* Create launcher */
227 chooser
->priv
->scanning
= TRUE
;
228 chooser
->priv
->launcher
= anjuta_launcher_new ();
229 anjuta_launcher_set_check_passwd_prompt (chooser
->priv
->launcher
,
232 g_signal_connect (G_OBJECT (chooser
->priv
->launcher
), "child-exited",
233 G_CALLBACK (on_listall_exit
), chooser
);
235 anjuta_launcher_execute (chooser
->priv
->launcher
,
236 PKG_CONFIG_LIST_ALL
, on_listall_output
,
241 anjuta_pkg_config_chooser_finalize (GObject
*object
)
244 G_OBJECT_CLASS (anjuta_pkg_config_chooser_parent_class
)->finalize (object
);
248 anjuta_pkg_config_chooser_class_init (AnjutaPkgConfigChooserClass
*klass
)
250 GObjectClass
* object_class
= G_OBJECT_CLASS (klass
);
252 object_class
->finalize
= anjuta_pkg_config_chooser_finalize
;
255 * AnjutaPkgConfigChooser::package-activated:
256 * @widget: the AnjutaPkgConfigChooser that received the signal
257 * @package: Name of the package that was activated
259 * The ::package-activated signal is emitted when a package is activated in the list
261 pkg_config_chooser_signals
[PACKAGE_ACTIVATED
] =
262 g_signal_new ("package-activated",
263 G_OBJECT_CLASS_TYPE (klass
),
265 G_STRUCT_OFFSET (AnjutaPkgConfigChooserClass
, package_activated
),
267 g_cclosure_marshal_VOID__STRING
,
271 * AnjutaPkgConfigChooser::package-deactivated:
272 * @widget: the AnjutaPkgConfigChooser that received the signal
273 * @package: Name of the package that was deactivated
275 * The ::package-activated signal is emitted when a package is deactivated in the list
277 pkg_config_chooser_signals
[PACKAGE_DEACTIVATED
] =
278 g_signal_new ("package-deactivated",
279 G_OBJECT_CLASS_TYPE (klass
),
281 G_STRUCT_OFFSET (AnjutaPkgConfigChooserClass
, package_deactivated
),
283 g_cclosure_marshal_VOID__STRING
,
287 g_type_class_add_private (klass
, sizeof(AnjutaPkgConfigChooserPrivate
));
291 * anjuta_pkg_config_chooser_new:
293 * Returns: A new AnjutaPkgConfigChooser widget
296 anjuta_pkg_config_chooser_new (void)
298 return GTK_WIDGET (g_object_new (ANJUTA_TYPE_PKG_CONFIG_CHOOSER
, NULL
));
302 * anjuta_pkg_config_chooser_get_active_packages:
303 * @chooser: A AnjutaPkgConfigChooser
305 * Return value: (element-type utf8) (transfer full):
306 * List of packages that are activated
309 anjuta_pkg_config_chooser_get_active_packages (AnjutaPkgConfigChooser
* chooser
)
311 GList
* packages
= NULL
;
314 g_return_val_if_fail (ANJUTA_IS_PKG_CONFIG_CHOOSER (chooser
), NULL
);
316 if (gtk_tree_model_get_iter_first (chooser
->priv
->model
, &iter
))
322 gtk_tree_model_get (chooser
->priv
->model
, &iter
,
323 COLUMN_NAME
, &model_pkg
,
324 COLUMN_ACTIVE
, &active
, -1);
327 packages
= g_list_append (packages
, model_pkg
);
330 while (gtk_tree_model_iter_next (chooser
->priv
->model
,
337 * anjuta_pkg_config_chooser_get_active_packages:
338 * @chooser: A AnjutaPkgConfigChooser
339 * @packages: (element-type utf8) (transfer full): List of packages to be activated in the list
343 anjuta_pkg_config_chooser_set_active_packages (AnjutaPkgConfigChooser
* chooser
, GList
* packages
)
347 g_return_if_fail (ANJUTA_IS_PKG_CONFIG_CHOOSER (chooser
));
349 for (pkg
= packages
; pkg
!= NULL
; pkg
= g_list_next (pkg
))
352 if (chooser
->priv
->scanning
)
354 chooser
->priv
->selected_cache
= g_list_append (chooser
->priv
->selected_cache
,
355 g_strdup(pkg
->data
));
357 else if (gtk_tree_model_get_iter_first (chooser
->priv
->model
, &iter
))
362 gtk_tree_model_get (chooser
->priv
->model
, &iter
,
363 COLUMN_NAME
, &model_pkg
, -1);
364 if (g_str_equal (model_pkg
, pkg
->data
))
366 gtk_list_store_set (GTK_LIST_STORE (chooser
->priv
->model
), &iter
,
367 COLUMN_ACTIVE
, TRUE
, -1);
371 while (gtk_tree_model_iter_next (chooser
->priv
->model
,
378 * anjuta_pkg_config_chooser_show_active_only:
379 * @chooser: A AnjutaPkgConfigChooser
380 * @show_selected: whether to show only activated packages
382 * Show activated packages only, this is mainly useful when the tree is set
383 * insensitive but the user should be able to see which packages have been activated
386 anjuta_pkg_config_chooser_show_active_only (AnjutaPkgConfigChooser
* chooser
, gboolean show_selected
)
388 g_return_if_fail (ANJUTA_IS_PKG_CONFIG_CHOOSER (chooser
));
390 chooser
->priv
->selected_only
= show_selected
;
391 gtk_tree_model_filter_refilter (chooser
->priv
->filter_model
);
395 * anjuta_pkg_config_chooser_show_active_column:
396 * @chooser: A AnjutaPkgConfigChooser
397 * @show_column: whether the active column should be shown
399 * Can be used to hide the active column in situation where you are more interested
400 * in the selection then in the activated packages.
403 anjuta_pkg_config_chooser_show_active_column (AnjutaPkgConfigChooser
* chooser
, gboolean show_column
)
405 GtkTreeViewColumn
* column
;
407 g_return_if_fail (ANJUTA_IS_PKG_CONFIG_CHOOSER (chooser
));
409 column
= gtk_tree_view_get_column (GTK_TREE_VIEW (chooser
), COLUMN_ACTIVE
);
410 gtk_tree_view_column_set_visible (column
, show_column
);
414 * anjuta_pkg_config_chooser_get_selected_package:
415 * @chooser: A AnjutaPkgConfigChooser
417 * Return value: the currently selected packages in the list
421 anjuta_pkg_config_chooser_get_selected_package (AnjutaPkgConfigChooser
* chooser
)
423 GtkTreeIter sort_iter
;
424 GtkTreeSelection
* selection
;
426 g_return_val_if_fail (ANJUTA_IS_PKG_CONFIG_CHOOSER (chooser
), NULL
);
428 selection
= gtk_tree_view_get_selection (GTK_TREE_VIEW (chooser
));
430 if (gtk_tree_selection_get_selected (selection
, NULL
, &sort_iter
))
433 GtkTreeIter filter_iter
;
435 gtk_tree_model_sort_convert_iter_to_child_iter (chooser
->priv
->sort_model
,
436 &filter_iter
, &sort_iter
);
437 gtk_tree_model_filter_convert_iter_to_child_iter (chooser
->priv
->filter_model
,
438 &iter
, &filter_iter
);
439 gtk_tree_model_get (chooser
->priv
->model
, &iter
, COLUMN_NAME
, &package
, -1);