ali@9: /* ali@9: * Copyright (C) 2010 J. Ali Harlow ali@9: * ali@9: * This program is free software; you can redistribute it and/or modify ali@9: * it under the terms of the GNU General Public License as published by ali@9: * the Free Software Foundation; either version 2 of the License, or ali@9: * (at your option) any later version. ali@9: * ali@9: * This program is distributed in the hope that it will be useful, ali@9: * but WITHOUT ANY WARRANTY; without even the implied warranty of ali@9: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ali@9: * GNU General Public License for more details. ali@9: * ali@9: * You should have received a copy of the GNU General Public License along ali@9: * with this program; if not, write to the Free Software Foundation, Inc., ali@9: * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ali@9: */ ali@9: ali@9: #include "config.h" ali@9: #include ali@9: #include ali@9: #include ali@109: #include ali@24: #include ali@24: #include ali@109: #include ali@9: #include ali@9: #include ali@9: #include "app-manager.h" ali@9: ali@9: GtkTreeView *view=NULL; ali@9: PloverPackage *active=NULL; ali@9: gboolean view_files=FALSE; ali@9: ali@9: void package_present(PloverPackage *package) ali@9: { ali@109: gchar *s,*prefix,*prefix_path; ali@9: const char *text,*t; ali@109: char *multiple_prefixes="multiple"; ali@109: GError *tmp_err=NULL; ali@109: GSList *sets,*repositories,*lnk; ali@9: GtkWidget *w; ali@9: GtkTextBuffer *buf; ali@109: GtkTreeModel *model; ali@109: struct comps *comps; ali@109: PloverPackageSet *set; ali@24: PloverPackageFileStore *store; ali@109: PloverRepository *repository; ali@9: buf=GTK_TEXT_BUFFER(gtk_builder_get_object(ui,"description")); ali@9: if (package) ali@9: { ali@9: s=g_strdup(plover_package_get_description(package)); ali@9: g_strdelimit(s,"\t\n",' '); ali@9: } ali@9: else ali@109: { ali@109: model=gtk_tree_view_get_model(view); ali@109: while(model && ali@109: (GTK_IS_TREE_MODEL_FILTER(model) || GTK_IS_TREE_MODEL_SORT(model))) ali@109: { ali@109: if (GTK_IS_TREE_MODEL_FILTER(model)) ali@109: model= ali@109: gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(model)); ali@109: else ali@109: model=gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(model)); ali@109: } ali@109: repositories=NULL; ali@109: prefix=NULL; ali@109: if (model && PLOVER_IS_PACKAGE_STORE(model)) ali@109: { ali@109: sets=plover_package_store_get_sets(PLOVER_PACKAGE_STORE(model)); ali@109: for(lnk=sets;lnk;lnk=lnk->next) ali@109: { ali@109: set=lnk->data; ali@109: repository=plover_package_set_get_repository(set); ali@109: if (repository && !g_slist_find(repositories,repository)) ali@109: repositories=g_slist_prepend(repositories,repository); ali@109: t=plover_package_set_guess_prefix(set,tmp_err?NULL:&tmp_err); ali@109: if (!t) ali@109: continue; ali@109: if (!prefix) ali@109: prefix=g_strdup(t); ali@109: else if (prefix!=multiple_prefixes && strcmp(prefix,t)) ali@109: { ali@109: g_free(prefix); ali@109: prefix=multiple_prefixes; ali@109: } ali@109: } ali@109: if (prefix==multiple_prefixes) ali@109: s=g_strdup("Multiple install prefixes"); ali@109: else if (repositories) ali@109: { ali@109: if (prefix!=multiple_prefixes) ali@109: g_free(prefix); ali@109: prefix=NULL; ali@109: for(lnk=repositories;lnk;lnk=lnk->next) ali@109: { ali@109: repository=lnk->data; ali@109: if (PLOVER_IS_YUM_REPOSITORY(repository)) ali@109: { ali@109: comps=plover_yum_repository_get_comps( ali@109: PLOVER_YUM_REPOSITORY(repository),NULL); ali@109: t=plover_comps_get_default_prefix(comps); ali@109: if (!prefix) ali@109: prefix=g_strdup(t); ali@109: else if (prefix!=multiple_prefixes && strcmp(prefix,t)) ali@109: { ali@109: g_free(prefix); ali@109: prefix=multiple_prefixes; ali@109: } ali@109: } ali@109: } ali@109: if (prefix==multiple_prefixes) ali@109: s=g_strdup("Repositories intended to be installed to " ali@109: "multiple destinations"); ali@109: else if (prefix) ali@109: { ali@109: prefix_path=razor_path_from_uri(prefix,NULL); ali@109: s=g_strdup_printf("Repository intended to be installed to: " ali@109: "%s",prefix_path?prefix_path:prefix); ali@109: g_free(prefix_path); ali@109: } ali@109: else ali@109: s=g_strdup("Repository with no default " ali@109: "install destination"); ali@109: } ali@109: else if (prefix) ali@109: { ali@109: prefix_path=razor_path_from_uri(prefix,NULL); ali@109: s=g_strdup_printf("Installed in: %s", ali@109: prefix_path?prefix_path:prefix); ali@109: g_free(prefix_path); ali@109: } ali@109: else if (sets) ali@109: s=g_strdup("No common installation destination found"); ali@109: else ali@109: s=g_strdup("Empty package store"); ali@109: if (prefix!=multiple_prefixes) ali@109: g_free(prefix); ali@109: g_slist_free(repositories); ali@109: g_clear_error(&tmp_err); ali@109: } ali@109: else if (model) ali@109: s=g_strdup_printf("Unsupported package list container (%s)", ali@109: G_OBJECT_TYPE_NAME(model)); ali@109: else ali@109: s=g_strdup("No Package list container"); ali@109: } ali@9: gtk_text_buffer_set_text(buf,s,-1); ali@9: g_free(s); ali@9: w=GTK_WIDGET(gtk_builder_get_object(ui,"PackageDetails")); ali@9: if (!package) ali@9: { ali@9: gtk_widget_hide(w); ali@9: w=GTK_WIDGET(gtk_builder_get_object(ui,"FilesScrolledWindow")); ali@9: gtk_widget_hide(w); ali@9: w=GTK_WIDGET(gtk_builder_get_object(ui,"DescriptionScrolledWindow")); ali@9: gtk_widget_show(w); ali@9: } ali@9: else ali@9: { ali@9: if (view_files) ali@9: gtk_widget_hide(w); ali@9: else ali@9: { ali@9: gtk_widget_show(w); ali@9: w=GTK_WIDGET(gtk_builder_get_object(ui,"HomepageBox")); ali@9: text=plover_package_get_URL(package); ali@9: if (!*text) ali@9: gtk_widget_hide(w); ali@9: else ali@9: { ali@9: gtk_widget_show(w); ali@9: w=GTK_WIDGET(gtk_builder_get_object(ui,"Homepage")); ali@9: gtk_link_button_set_uri(GTK_LINK_BUTTON(w),text); ali@9: t=strstr(text,"://"); ali@9: if (t) ali@9: t+=3; ali@9: if (t) ali@10: s=g_strndup(t,strcspn(t,"/")); ali@9: else ali@10: s=g_strdup(text); ali@9: gtk_button_set_label(GTK_BUTTON(w),s); ali@9: g_free(s); ali@9: } ali@9: w=GTK_WIDGET(gtk_builder_get_object(ui,"Architecture")); ali@9: gtk_label_set_text(GTK_LABEL(w),plover_package_get_arch(package)); ali@9: w=GTK_WIDGET(gtk_builder_get_object(ui,"License")); ali@9: gtk_label_set_text(GTK_LABEL(w), ali@9: plover_package_get_license(package)); ali@9: } ali@9: w=GTK_WIDGET(gtk_builder_get_object(ui,"FilesScrolledWindow")); ali@9: if (view_files) ali@9: gtk_widget_show(w); ali@9: else ali@9: gtk_widget_hide(w); ali@9: w=GTK_WIDGET(gtk_builder_get_object(ui,"DescriptionScrolledWindow")); ali@9: if (view_files) ali@9: { ali@9: gtk_widget_hide(w); ali@9: w=GTK_WIDGET(gtk_builder_get_object(ui,"Files")); ali@24: store=plover_package_file_store_new_from_package(package); ali@24: gtk_tree_view_set_model(GTK_TREE_VIEW(w),GTK_TREE_MODEL(store)); ali@24: g_object_unref(store); ali@9: } ali@9: else ali@9: { ali@9: gtk_widget_show(w); ali@9: /* Without this, Gtk+ 2.18.6 just truncates long license tags */ ali@9: w=GTK_WIDGET(gtk_builder_get_object(ui,"DetailsScrolledWindow")); ali@9: gtk_widget_queue_resize(w); ali@9: } ali@9: } ali@9: } ali@9: ali@9: void package_filelist_present(PloverPackage *package) ali@9: { ali@9: } ali@9: ali@9: static void package_selection_changed(GtkTreeSelection *selection) ali@9: { ali@9: GtkTreeIter iter; ali@9: GtkTreeView *view; ali@9: GtkTreeModel *model; ali@9: if (active) ali@9: g_object_unref(active); ali@9: if (gtk_tree_selection_get_selected(selection,NULL,&iter)) ali@9: { ali@9: view=gtk_tree_selection_get_tree_view(selection); ali@9: model=gtk_tree_view_get_model(view); ali@9: gtk_tree_model_get(model,&iter,PLOVER_PACKAGE_STORE_OBJ_COLUMN,&active, ali@9: -1); ali@9: } ali@9: else ali@9: active=NULL; ali@9: package_present(active); ali@9: } ali@9: ali@9: static void package_activated(GtkTreeView *view,GtkTreePath *path, ali@9: GtkTreeViewColumn *column,gpointer data) ali@9: { ali@9: GtkTreeIter iter; ali@9: GtkTreeModel *model=gtk_tree_view_get_model(view); ali@9: PloverPackage *package; ali@9: if (gtk_tree_model_get_iter(model,&iter,path)) ali@9: { ali@9: gtk_tree_model_get(model,&iter,PLOVER_PACKAGE_STORE_OBJ_COLUMN,&package, ali@9: -1); ali@9: package_filelist_present(package); ali@9: } ali@9: } ali@9: ali@109: static void package_inserted(GtkTreeModel *tree_model,GtkTreePath *path, ali@109: GtkTreeIter *iter,gpointer data) ali@109: { ali@109: gchar *s; ali@109: s=gtk_tree_path_to_string(path); ali@109: g_message("package_inserted(%s): %sactive package", ali@109: s,active?"":"no "); ali@109: g_free(s); ali@109: if (!active) ali@109: package_present(NULL); ali@109: } ali@109: ali@109: static void package_deleted(GtkTreeModel *tree_model,GtkTreePath *path, ali@109: gpointer data) ali@109: { ali@109: /* ali@109: * If the deleted package was the active one, then selection-changed ali@109: * will be emitted which will handle that case. ali@109: */ ali@109: gchar *s; ali@109: s=gtk_tree_path_to_string(path); ali@109: g_message("package_deleted(%s): %sactive package",s,active?"":"no "); ali@109: g_free(s); ali@109: if (!active) ali@109: package_present(NULL); ali@109: } ali@109: ali@9: static void package_cell_data_func(GtkTreeViewColumn *column, ali@9: GtkCellRenderer *cell,GtkTreeModel *model,GtkTreeIter *iter,gpointer data) ali@9: { ali@9: gchar *markup; ali@9: gchar *summary,*name,*version; ali@10: g_return_if_fail(GTK_IS_TREE_MODEL(model)); ali@9: gtk_tree_model_get(model,iter,PLOVER_PACKAGE_STORE_SUMMARY_COLUMN,&summary, ali@9: PLOVER_PACKAGE_STORE_NAME_COLUMN,&name, ali@9: PLOVER_PACKAGE_STORE_VERSION_COLUMN,&version,-1); ali@10: markup=g_markup_printf_escaped("%s\n%s %s",summary,name,version); ali@9: g_free(summary); ali@9: g_free(name); ali@9: g_free(version); ali@9: g_object_set(cell,"markup",markup,NULL); ali@9: g_free(markup); ali@9: } ali@9: ali@9: void set_package_model(GtkTreeModel *model) ali@9: { ali@9: GtkWidget *w; ali@109: GtkTreeModel *old_model; ali@9: GtkTreeViewColumn *column; ali@9: GtkCellRenderer *renderer; ali@9: GtkTreeSelection *selection; ali@109: if (view) ali@109: { ali@109: old_model=gtk_tree_view_get_model(view); ali@109: if (old_model) ali@109: { ali@109: g_signal_handlers_disconnect_by_func(old_model, ali@109: G_CALLBACK(package_inserted),NULL); ali@109: g_signal_handlers_disconnect_by_func(old_model, ali@109: G_CALLBACK(package_deleted),NULL); ali@109: } ali@109: } ali@9: if (!view) ali@9: { ali@9: w=GTK_WIDGET(gtk_builder_get_object(ui,"Packages")); ali@9: if (w) ali@9: { ali@9: view=GTK_TREE_VIEW(w); ali@9: #if 0 ali@9: column=gtk_tree_view_column_new_with_attributes("Icon", ali@9: gtk_cell_renderer_pixbuf_new(),"pixbuf", ali@9: PLOVER_PACKAGE_FILE_STORE_ICON_COLUMN,NULL); ali@9: gtk_tree_view_append_column(GTK_TREE_VIEW(w),column); ali@9: #endif ali@9: column=gtk_tree_view_column_new(); ali@9: gtk_tree_view_column_set_title(column,"Summary"); ali@9: renderer=gtk_cell_renderer_text_new(); ali@9: gtk_tree_view_column_pack_start(column,renderer,FALSE); ali@9: gtk_tree_view_column_set_cell_data_func(column,renderer, ali@9: package_cell_data_func,NULL,NULL); ali@9: gtk_tree_view_append_column(view,column); ali@9: gtk_widget_show_all(w); ali@9: gtk_tree_view_set_headers_visible(view,FALSE); ali@9: w=GTK_WIDGET(gtk_builder_get_object(ui,"SearchEntry")); ali@9: gtk_tree_view_set_search_entry(view,GTK_ENTRY(w)); ali@9: selection=gtk_tree_view_get_selection(view); ali@9: g_signal_connect(selection,"changed", ali@9: G_CALLBACK(package_selection_changed),NULL); ali@9: g_signal_connect(view,"row-activated",G_CALLBACK(package_activated), ali@9: NULL); ali@9: } ali@9: else ali@9: g_warning("Packages: no such widget in UI"); ali@9: w=GTK_WIDGET(gtk_builder_get_object(ui,"Files")); ali@9: if (w) ali@9: { ali@9: column=gtk_tree_view_column_new_with_attributes("Name", ali@9: gtk_cell_renderer_text_new(),"text", ali@9: PLOVER_PACKAGE_FILE_STORE_NAME_COLUMN,NULL); ali@9: gtk_tree_view_append_column(GTK_TREE_VIEW(w),column); ali@9: gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(w),FALSE); ali@9: gtk_widget_show_all(w); ali@9: } ali@9: else ali@9: g_warning("Files: no such widget in UI"); ali@9: } ali@9: if (view) ali@9: { ali@109: g_warning("set_package_model: Calling gtk_tree_view_set_model()"); ali@9: gtk_tree_view_set_model(view,model); ali@109: g_warning("set_package_model: gtk_tree_view_set_model() returns"); ali@9: gtk_tree_view_set_search_column(view, ali@9: PLOVER_PACKAGE_STORE_NAME_COLUMN); ali@109: if (model) ali@109: { ali@109: g_signal_connect(model,"row-inserted",G_CALLBACK(package_inserted), ali@109: NULL); ali@109: g_signal_connect(model,"row-deleted",G_CALLBACK(package_deleted), ali@109: NULL); ali@109: } ali@9: } ali@9: package_present(NULL); ali@9: } ali@9: ali@9: PloverPackage *get_active_package(void) ali@9: { ali@9: return active; ali@9: } ali@9: ali@9: G_MODULE_EXPORT void ali@9: on_view_files_toggled(GtkCheckMenuItem *menuitem,gpointer data) ali@9: { ali@9: view_files=gtk_check_menu_item_get_active(menuitem); ali@9: package_present(active); ali@9: } ali@9: ali@9: G_MODULE_EXPORT void ali@9: on_view_details_toggled(GtkCheckMenuItem *menuitem,gpointer data) ali@9: { ali@9: }