app-manager/packagelist.c
author J. Ali Harlow <ali@juiblex.co.uk>
Tue Apr 25 17:41:00 2023 +0100 (2023-04-25)
changeset 109 2947214c450e
parent 24 2b9f54d14cc2
permissions -rw-r--r--
Partial fix for #5537
ali@9
     1
/*
ali@9
     2
 * Copyright (C) 2010  J. Ali Harlow <ali@juiblex.co.uk>
ali@9
     3
 *
ali@9
     4
 * This program is free software; you can redistribute it and/or modify
ali@9
     5
 * it under the terms of the GNU General Public License as published by
ali@9
     6
 * the Free Software Foundation; either version 2 of the License, or
ali@9
     7
 * (at your option) any later version.
ali@9
     8
 *
ali@9
     9
 * This program is distributed in the hope that it will be useful,
ali@9
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ali@9
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
ali@9
    12
 * GNU General Public License for more details.
ali@9
    13
 *
ali@9
    14
 * You should have received a copy of the GNU General Public License along
ali@9
    15
 * with this program; if not, write to the Free Software Foundation, Inc.,
ali@9
    16
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
ali@9
    17
 */
ali@9
    18
ali@9
    19
#include "config.h"
ali@9
    20
#include <stdlib.h>
ali@9
    21
#include <string.h>
ali@9
    22
#include <gtk/gtk.h>
ali@109
    23
#include <plover/plover.h>
ali@24
    24
#include <plover/package.h>
ali@24
    25
#include <plover/packageset.h>
ali@109
    26
#include <plover/yumrepository.h>
ali@9
    27
#include <plover-gtk/packagestore.h>
ali@9
    28
#include <plover-gtk/packagefilestore.h>
ali@9
    29
#include "app-manager.h"
ali@9
    30
ali@9
    31
GtkTreeView *view=NULL;
ali@9
    32
PloverPackage *active=NULL;
ali@9
    33
gboolean view_files=FALSE;
ali@9
    34
ali@9
    35
void package_present(PloverPackage *package)
ali@9
    36
{
ali@109
    37
    gchar *s,*prefix,*prefix_path;
ali@9
    38
    const char *text,*t;
ali@109
    39
    char *multiple_prefixes="multiple";
ali@109
    40
    GError *tmp_err=NULL;
ali@109
    41
    GSList *sets,*repositories,*lnk;
ali@9
    42
    GtkWidget *w;
ali@9
    43
    GtkTextBuffer *buf;
ali@109
    44
    GtkTreeModel *model;
ali@109
    45
    struct comps *comps;
ali@109
    46
    PloverPackageSet *set;
ali@24
    47
    PloverPackageFileStore *store;
ali@109
    48
    PloverRepository *repository;
ali@9
    49
    buf=GTK_TEXT_BUFFER(gtk_builder_get_object(ui,"description"));
ali@9
    50
    if (package)
ali@9
    51
    {
ali@9
    52
	s=g_strdup(plover_package_get_description(package));
ali@9
    53
	g_strdelimit(s,"\t\n",' ');
ali@9
    54
    }
ali@9
    55
    else
ali@109
    56
    {
ali@109
    57
	model=gtk_tree_view_get_model(view);
ali@109
    58
	while(model &&
ali@109
    59
	  (GTK_IS_TREE_MODEL_FILTER(model) || GTK_IS_TREE_MODEL_SORT(model)))
ali@109
    60
	{
ali@109
    61
	    if (GTK_IS_TREE_MODEL_FILTER(model))
ali@109
    62
		model=
ali@109
    63
		  gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(model));
ali@109
    64
	    else
ali@109
    65
		model=gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(model));
ali@109
    66
	}
ali@109
    67
	repositories=NULL;
ali@109
    68
	prefix=NULL;
ali@109
    69
	if (model && PLOVER_IS_PACKAGE_STORE(model))
ali@109
    70
	{
ali@109
    71
	    sets=plover_package_store_get_sets(PLOVER_PACKAGE_STORE(model));
ali@109
    72
	    for(lnk=sets;lnk;lnk=lnk->next)
ali@109
    73
	    {
ali@109
    74
		set=lnk->data;
ali@109
    75
		repository=plover_package_set_get_repository(set);
ali@109
    76
		if (repository && !g_slist_find(repositories,repository))
ali@109
    77
		    repositories=g_slist_prepend(repositories,repository);
ali@109
    78
		t=plover_package_set_guess_prefix(set,tmp_err?NULL:&tmp_err);
ali@109
    79
		if (!t)
ali@109
    80
		    continue;
ali@109
    81
		if (!prefix)
ali@109
    82
		    prefix=g_strdup(t);
ali@109
    83
		else if (prefix!=multiple_prefixes && strcmp(prefix,t))
ali@109
    84
		{
ali@109
    85
		    g_free(prefix);
ali@109
    86
		    prefix=multiple_prefixes;
ali@109
    87
		}
ali@109
    88
	    }
ali@109
    89
	    if (prefix==multiple_prefixes)
ali@109
    90
		s=g_strdup("Multiple install prefixes");
ali@109
    91
	    else if (repositories)
ali@109
    92
	    {
ali@109
    93
		if (prefix!=multiple_prefixes)
ali@109
    94
		    g_free(prefix);
ali@109
    95
		prefix=NULL;
ali@109
    96
		for(lnk=repositories;lnk;lnk=lnk->next)
ali@109
    97
		{
ali@109
    98
		    repository=lnk->data;
ali@109
    99
		    if (PLOVER_IS_YUM_REPOSITORY(repository))
ali@109
   100
		    {
ali@109
   101
			comps=plover_yum_repository_get_comps(
ali@109
   102
			  PLOVER_YUM_REPOSITORY(repository),NULL);
ali@109
   103
			t=plover_comps_get_default_prefix(comps);
ali@109
   104
			if (!prefix)
ali@109
   105
			    prefix=g_strdup(t);
ali@109
   106
			else if (prefix!=multiple_prefixes && strcmp(prefix,t))
ali@109
   107
			{
ali@109
   108
			    g_free(prefix);
ali@109
   109
			    prefix=multiple_prefixes;
ali@109
   110
			}
ali@109
   111
		    }
ali@109
   112
		}
ali@109
   113
		if (prefix==multiple_prefixes)
ali@109
   114
		    s=g_strdup("Repositories intended to be installed to "
ali@109
   115
		      "multiple destinations");
ali@109
   116
		else if (prefix)
ali@109
   117
		{
ali@109
   118
		    prefix_path=razor_path_from_uri(prefix,NULL);
ali@109
   119
		    s=g_strdup_printf("Repository intended to be installed to: "
ali@109
   120
		      "%s",prefix_path?prefix_path:prefix);
ali@109
   121
		    g_free(prefix_path);
ali@109
   122
		}
ali@109
   123
		else
ali@109
   124
		    s=g_strdup("Repository with no default "
ali@109
   125
		      "install destination");
ali@109
   126
	    }
ali@109
   127
	    else if (prefix)
ali@109
   128
	    {
ali@109
   129
		prefix_path=razor_path_from_uri(prefix,NULL);
ali@109
   130
		s=g_strdup_printf("Installed in: %s",
ali@109
   131
		  prefix_path?prefix_path:prefix);
ali@109
   132
		g_free(prefix_path);
ali@109
   133
	    }
ali@109
   134
	    else if (sets)
ali@109
   135
		s=g_strdup("No common installation destination found");
ali@109
   136
	    else
ali@109
   137
		s=g_strdup("Empty package store");
ali@109
   138
	    if (prefix!=multiple_prefixes)
ali@109
   139
		g_free(prefix);
ali@109
   140
	    g_slist_free(repositories);
ali@109
   141
	    g_clear_error(&tmp_err);
ali@109
   142
	}
ali@109
   143
	else if (model)
ali@109
   144
	    s=g_strdup_printf("Unsupported package list container (%s)",
ali@109
   145
	      G_OBJECT_TYPE_NAME(model));
ali@109
   146
	else
ali@109
   147
	    s=g_strdup("No Package list container");
ali@109
   148
    }
ali@9
   149
    gtk_text_buffer_set_text(buf,s,-1);
ali@9
   150
    g_free(s);
ali@9
   151
    w=GTK_WIDGET(gtk_builder_get_object(ui,"PackageDetails"));
ali@9
   152
    if (!package)
ali@9
   153
    {
ali@9
   154
	gtk_widget_hide(w);
ali@9
   155
	w=GTK_WIDGET(gtk_builder_get_object(ui,"FilesScrolledWindow"));
ali@9
   156
	gtk_widget_hide(w);
ali@9
   157
	w=GTK_WIDGET(gtk_builder_get_object(ui,"DescriptionScrolledWindow"));
ali@9
   158
	gtk_widget_show(w);
ali@9
   159
    }
ali@9
   160
    else
ali@9
   161
    {
ali@9
   162
	if (view_files)
ali@9
   163
	    gtk_widget_hide(w);
ali@9
   164
	else
ali@9
   165
	{
ali@9
   166
	    gtk_widget_show(w);
ali@9
   167
	    w=GTK_WIDGET(gtk_builder_get_object(ui,"HomepageBox"));
ali@9
   168
	    text=plover_package_get_URL(package);
ali@9
   169
	    if (!*text)
ali@9
   170
		gtk_widget_hide(w);
ali@9
   171
	    else
ali@9
   172
	    {
ali@9
   173
		gtk_widget_show(w);
ali@9
   174
		w=GTK_WIDGET(gtk_builder_get_object(ui,"Homepage"));
ali@9
   175
		gtk_link_button_set_uri(GTK_LINK_BUTTON(w),text);
ali@9
   176
		t=strstr(text,"://");
ali@9
   177
		if (t)
ali@9
   178
		    t+=3;
ali@9
   179
		if (t)
ali@10
   180
		    s=g_strndup(t,strcspn(t,"/"));
ali@9
   181
		else
ali@10
   182
		    s=g_strdup(text);
ali@9
   183
		gtk_button_set_label(GTK_BUTTON(w),s);
ali@9
   184
		g_free(s);
ali@9
   185
	    }
ali@9
   186
	    w=GTK_WIDGET(gtk_builder_get_object(ui,"Architecture"));
ali@9
   187
	    gtk_label_set_text(GTK_LABEL(w),plover_package_get_arch(package));
ali@9
   188
	    w=GTK_WIDGET(gtk_builder_get_object(ui,"License"));
ali@9
   189
	    gtk_label_set_text(GTK_LABEL(w),
ali@9
   190
	      plover_package_get_license(package));
ali@9
   191
	}
ali@9
   192
	w=GTK_WIDGET(gtk_builder_get_object(ui,"FilesScrolledWindow"));
ali@9
   193
	if (view_files)
ali@9
   194
	    gtk_widget_show(w);
ali@9
   195
	else
ali@9
   196
	    gtk_widget_hide(w);
ali@9
   197
	w=GTK_WIDGET(gtk_builder_get_object(ui,"DescriptionScrolledWindow"));
ali@9
   198
	if (view_files)
ali@9
   199
	{
ali@9
   200
	    gtk_widget_hide(w);
ali@9
   201
	    w=GTK_WIDGET(gtk_builder_get_object(ui,"Files"));
ali@24
   202
	    store=plover_package_file_store_new_from_package(package);
ali@24
   203
	    gtk_tree_view_set_model(GTK_TREE_VIEW(w),GTK_TREE_MODEL(store));
ali@24
   204
	    g_object_unref(store);
ali@9
   205
	}
ali@9
   206
	else
ali@9
   207
	{
ali@9
   208
	    gtk_widget_show(w);
ali@9
   209
	    /* Without this, Gtk+ 2.18.6 just truncates long license tags */
ali@9
   210
	    w=GTK_WIDGET(gtk_builder_get_object(ui,"DetailsScrolledWindow"));
ali@9
   211
	    gtk_widget_queue_resize(w);
ali@9
   212
	}
ali@9
   213
    }
ali@9
   214
}
ali@9
   215
ali@9
   216
void package_filelist_present(PloverPackage *package)
ali@9
   217
{
ali@9
   218
}
ali@9
   219
ali@9
   220
static void package_selection_changed(GtkTreeSelection *selection)
ali@9
   221
{
ali@9
   222
    GtkTreeIter iter;
ali@9
   223
    GtkTreeView *view;
ali@9
   224
    GtkTreeModel *model;
ali@9
   225
    if (active)
ali@9
   226
	g_object_unref(active);
ali@9
   227
    if (gtk_tree_selection_get_selected(selection,NULL,&iter))
ali@9
   228
    {
ali@9
   229
	view=gtk_tree_selection_get_tree_view(selection);
ali@9
   230
	model=gtk_tree_view_get_model(view);
ali@9
   231
	gtk_tree_model_get(model,&iter,PLOVER_PACKAGE_STORE_OBJ_COLUMN,&active,
ali@9
   232
	  -1);
ali@9
   233
    }
ali@9
   234
    else
ali@9
   235
	active=NULL;
ali@9
   236
    package_present(active);
ali@9
   237
}
ali@9
   238
ali@9
   239
static void package_activated(GtkTreeView *view,GtkTreePath *path,
ali@9
   240
  GtkTreeViewColumn *column,gpointer data)
ali@9
   241
{
ali@9
   242
    GtkTreeIter iter;
ali@9
   243
    GtkTreeModel *model=gtk_tree_view_get_model(view);
ali@9
   244
    PloverPackage *package;
ali@9
   245
    if (gtk_tree_model_get_iter(model,&iter,path))
ali@9
   246
    {
ali@9
   247
	gtk_tree_model_get(model,&iter,PLOVER_PACKAGE_STORE_OBJ_COLUMN,&package,
ali@9
   248
	  -1);
ali@9
   249
	package_filelist_present(package);
ali@9
   250
    }
ali@9
   251
}
ali@9
   252
ali@109
   253
static void package_inserted(GtkTreeModel *tree_model,GtkTreePath *path,
ali@109
   254
  GtkTreeIter *iter,gpointer data)
ali@109
   255
{
ali@109
   256
    gchar *s;
ali@109
   257
    s=gtk_tree_path_to_string(path);
ali@109
   258
    g_message("package_inserted(%s): %sactive package",
ali@109
   259
      s,active?"":"no ");
ali@109
   260
    g_free(s);
ali@109
   261
    if (!active)
ali@109
   262
	package_present(NULL);
ali@109
   263
}
ali@109
   264
ali@109
   265
static void package_deleted(GtkTreeModel *tree_model,GtkTreePath *path,
ali@109
   266
  gpointer data)
ali@109
   267
{
ali@109
   268
    /*
ali@109
   269
     * If the deleted package was the active one, then selection-changed
ali@109
   270
     * will be emitted which will handle that case.
ali@109
   271
     */
ali@109
   272
    gchar *s;
ali@109
   273
    s=gtk_tree_path_to_string(path);
ali@109
   274
    g_message("package_deleted(%s): %sactive package",s,active?"":"no ");
ali@109
   275
    g_free(s);
ali@109
   276
    if (!active)
ali@109
   277
	package_present(NULL);
ali@109
   278
}
ali@109
   279
ali@9
   280
static void package_cell_data_func(GtkTreeViewColumn *column,
ali@9
   281
  GtkCellRenderer *cell,GtkTreeModel *model,GtkTreeIter *iter,gpointer data)
ali@9
   282
{
ali@9
   283
    gchar *markup;
ali@9
   284
    gchar *summary,*name,*version;
ali@10
   285
    g_return_if_fail(GTK_IS_TREE_MODEL(model));
ali@9
   286
    gtk_tree_model_get(model,iter,PLOVER_PACKAGE_STORE_SUMMARY_COLUMN,&summary,
ali@9
   287
      PLOVER_PACKAGE_STORE_NAME_COLUMN,&name,
ali@9
   288
      PLOVER_PACKAGE_STORE_VERSION_COLUMN,&version,-1);
ali@10
   289
    markup=g_markup_printf_escaped("<b>%s</b>\n%s %s",summary,name,version);
ali@9
   290
    g_free(summary);
ali@9
   291
    g_free(name);
ali@9
   292
    g_free(version);
ali@9
   293
    g_object_set(cell,"markup",markup,NULL);
ali@9
   294
    g_free(markup);
ali@9
   295
}
ali@9
   296
ali@9
   297
void set_package_model(GtkTreeModel *model)
ali@9
   298
{
ali@9
   299
    GtkWidget *w;
ali@109
   300
    GtkTreeModel *old_model;
ali@9
   301
    GtkTreeViewColumn *column;
ali@9
   302
    GtkCellRenderer *renderer;
ali@9
   303
    GtkTreeSelection *selection;
ali@109
   304
    if (view)
ali@109
   305
    {
ali@109
   306
	old_model=gtk_tree_view_get_model(view);
ali@109
   307
	if (old_model)
ali@109
   308
	{
ali@109
   309
	    g_signal_handlers_disconnect_by_func(old_model,
ali@109
   310
	      G_CALLBACK(package_inserted),NULL);
ali@109
   311
	    g_signal_handlers_disconnect_by_func(old_model,
ali@109
   312
	      G_CALLBACK(package_deleted),NULL);
ali@109
   313
	}
ali@109
   314
    }
ali@9
   315
    if (!view)
ali@9
   316
    {
ali@9
   317
	w=GTK_WIDGET(gtk_builder_get_object(ui,"Packages"));
ali@9
   318
	if (w)
ali@9
   319
	{
ali@9
   320
	    view=GTK_TREE_VIEW(w);
ali@9
   321
#if 0
ali@9
   322
	    column=gtk_tree_view_column_new_with_attributes("Icon",
ali@9
   323
	      gtk_cell_renderer_pixbuf_new(),"pixbuf",
ali@9
   324
	      PLOVER_PACKAGE_FILE_STORE_ICON_COLUMN,NULL);
ali@9
   325
	    gtk_tree_view_append_column(GTK_TREE_VIEW(w),column);
ali@9
   326
#endif
ali@9
   327
	    column=gtk_tree_view_column_new();
ali@9
   328
	    gtk_tree_view_column_set_title(column,"Summary");
ali@9
   329
	    renderer=gtk_cell_renderer_text_new();
ali@9
   330
	    gtk_tree_view_column_pack_start(column,renderer,FALSE);
ali@9
   331
	    gtk_tree_view_column_set_cell_data_func(column,renderer,
ali@9
   332
	      package_cell_data_func,NULL,NULL);
ali@9
   333
	    gtk_tree_view_append_column(view,column);
ali@9
   334
	    gtk_widget_show_all(w);
ali@9
   335
	    gtk_tree_view_set_headers_visible(view,FALSE);
ali@9
   336
	    w=GTK_WIDGET(gtk_builder_get_object(ui,"SearchEntry"));
ali@9
   337
	    gtk_tree_view_set_search_entry(view,GTK_ENTRY(w));
ali@9
   338
	    selection=gtk_tree_view_get_selection(view);
ali@9
   339
	    g_signal_connect(selection,"changed",
ali@9
   340
	      G_CALLBACK(package_selection_changed),NULL);
ali@9
   341
	    g_signal_connect(view,"row-activated",G_CALLBACK(package_activated),
ali@9
   342
	      NULL);
ali@9
   343
	}
ali@9
   344
	else
ali@9
   345
	    g_warning("Packages: no such widget in UI");
ali@9
   346
	w=GTK_WIDGET(gtk_builder_get_object(ui,"Files"));
ali@9
   347
	if (w)
ali@9
   348
	{
ali@9
   349
	    column=gtk_tree_view_column_new_with_attributes("Name",
ali@9
   350
	      gtk_cell_renderer_text_new(),"text",
ali@9
   351
	      PLOVER_PACKAGE_FILE_STORE_NAME_COLUMN,NULL);
ali@9
   352
	    gtk_tree_view_append_column(GTK_TREE_VIEW(w),column);
ali@9
   353
	    gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(w),FALSE);
ali@9
   354
	    gtk_widget_show_all(w);
ali@9
   355
	}
ali@9
   356
	else
ali@9
   357
	    g_warning("Files: no such widget in UI");
ali@9
   358
    }
ali@9
   359
    if (view)
ali@9
   360
    {
ali@109
   361
	g_warning("set_package_model: Calling gtk_tree_view_set_model()");
ali@9
   362
	gtk_tree_view_set_model(view,model);
ali@109
   363
	g_warning("set_package_model: gtk_tree_view_set_model() returns");
ali@9
   364
	gtk_tree_view_set_search_column(view,
ali@9
   365
	  PLOVER_PACKAGE_STORE_NAME_COLUMN);
ali@109
   366
	if (model)
ali@109
   367
	{
ali@109
   368
	    g_signal_connect(model,"row-inserted",G_CALLBACK(package_inserted),
ali@109
   369
	      NULL);
ali@109
   370
	    g_signal_connect(model,"row-deleted",G_CALLBACK(package_deleted),
ali@109
   371
	      NULL);
ali@109
   372
	}
ali@9
   373
    }
ali@9
   374
    package_present(NULL);
ali@9
   375
}
ali@9
   376
ali@9
   377
PloverPackage *get_active_package(void)
ali@9
   378
{
ali@9
   379
    return active;
ali@9
   380
}
ali@9
   381
ali@9
   382
G_MODULE_EXPORT void
ali@9
   383
  on_view_files_toggled(GtkCheckMenuItem *menuitem,gpointer data)
ali@9
   384
{
ali@9
   385
    view_files=gtk_check_menu_item_get_active(menuitem);
ali@9
   386
    package_present(active);
ali@9
   387
}
ali@9
   388
ali@9
   389
G_MODULE_EXPORT void
ali@9
   390
  on_view_details_toggled(GtkCheckMenuItem *menuitem,gpointer data)
ali@9
   391
{
ali@9
   392
}