plover-gtk/transactionhelper.c
author J. Ali Harlow <ali@juiblex.co.uk>
Mon Aug 31 07:12:16 2020 +0100 (2020-08-31)
changeset 104 5cb36c12ac49
parent 99 0121592e2512
child 106 cc42fad3fe31
permissions -rw-r--r--
Prepare to release 0.6
ali@24
     1
/*
ali@103
     2
 * Copyright (C) 2014, 2016, 2018, 2020  J. Ali Harlow <ali@juiblex.co.uk>
ali@24
     3
 *
ali@24
     4
 * This program is free software; you can redistribute it and/or modify
ali@24
     5
 * it under the terms of the GNU General Public License as published by
ali@24
     6
 * the Free Software Foundation; either version 2 of the License, or
ali@24
     7
 * (at your option) any later version.
ali@24
     8
 *
ali@24
     9
 * This program is distributed in the hope that it will be useful,
ali@24
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ali@24
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
ali@24
    12
 * GNU General Public License for more details.
ali@24
    13
 *
ali@24
    14
 * You should have received a copy of the GNU General Public License along
ali@24
    15
 * with this program; if not, write to the Free Software Foundation, Inc.,
ali@24
    16
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
ali@24
    17
 */
ali@24
    18
ali@24
    19
#include "config.h"
ali@24
    20
#include <stdlib.h>
ali@61
    21
#include <string.h>
ali@24
    22
#include <errno.h>
ali@24
    23
#include <gtk/gtk.h>
ali@24
    24
#include <plover/plover.h>
ali@24
    25
#include <plover/transaction.h>
ali@24
    26
#include <plover-gtk/transactionhelper.h>
ali@44
    27
#include "plover/uri-handler.h"
ali@24
    28
ali@24
    29
/*
ali@24
    30
 * A PloverTransactionHelper uses a GtkAssistant to help a user run a
ali@24
    31
 * transaction.
ali@24
    32
 */
ali@24
    33
ali@24
    34
G_DEFINE_TYPE(PloverTransactionHelper,plover_transaction_helper,G_TYPE_OBJECT)
ali@24
    35
ali@38
    36
enum plover_transaction_type {
ali@38
    37
    TRANSACTION_TYPE_NULL=0,
ali@38
    38
    TRANSACTION_TYPE_INSTALL=1UL<<0,
ali@38
    39
    TRANSACTION_TYPE_REMOVE=1UL<<1,
ali@38
    40
    TRANSACTION_TYPE_UPDATE=TRANSACTION_TYPE_INSTALL|TRANSACTION_TYPE_REMOVE
ali@38
    41
};
ali@38
    42
ali@38
    43
typedef struct _PloverTransactionHelperPrivate {
ali@38
    44
    enum plover_transaction_type transaction_type;
ali@38
    45
    gchar *default_prefix;
ali@38
    46
} PloverTransactionHelperPrivate;
ali@38
    47
ali@38
    48
#define PLOVER_TRANSACTION_HELPER_GET_PRIVATE(obj)\
ali@38
    49
                                G_TYPE_INSTANCE_GET_PRIVATE(obj,\
ali@38
    50
				  PLOVER_TYPE_TRANSACTION_HELPER,\
ali@38
    51
				  PloverTransactionHelperPrivate)
ali@38
    52
ali@24
    53
enum {
ali@24
    54
    CLOSE=0,
ali@24
    55
    N_SIGNALS
ali@24
    56
};
ali@24
    57
ali@24
    58
static guint signals[N_SIGNALS];
ali@24
    59
ali@86
    60
static PloverTransaction *
ali@86
    61
  plover_transaction_helper_new_transaction(PloverTransactionHelper *helper,
ali@86
    62
  GError **error);
ali@86
    63
ali@24
    64
static void plover_transaction_helper_finalize(PloverTransactionHelper *helper)
ali@24
    65
{
ali@38
    66
    PloverTransactionHelperPrivate *priv;
ali@38
    67
    priv=PLOVER_TRANSACTION_HELPER_GET_PRIVATE(helper);
ali@38
    68
    g_free(priv->default_prefix);
ali@24
    69
    g_free(helper->error_primary_text);
ali@24
    70
    g_free(helper->base);
ali@98
    71
    g_free(helper->base_uri);
ali@24
    72
    g_free(helper->unsatisfied);
ali@24
    73
    if (helper->comps)
ali@24
    74
	plover_comps_free(helper->comps);
ali@24
    75
    plover_vector_free(helper->report_adding);
ali@24
    76
    plover_vector_free(helper->report_removing);
ali@24
    77
}
ali@24
    78
ali@24
    79
static void plover_transaction_helper_dispose(PloverTransactionHelper *helper)
ali@24
    80
{
ali@24
    81
    g_clear_error(&helper->error);
ali@24
    82
    if (helper->error_dialog)
ali@24
    83
    {
ali@24
    84
	g_signal_handlers_disconnect_by_data(helper->error_dialog,helper);
ali@24
    85
	gtk_widget_destroy(helper->error_dialog);
ali@24
    86
	helper->error_dialog=NULL;
ali@24
    87
    }
ali@24
    88
    if (helper->assistant)
ali@24
    89
    {
ali@24
    90
	g_signal_handlers_disconnect_by_data(helper->assistant,helper);
ali@24
    91
	g_clear_object(&helper->assistant);
ali@24
    92
    }
ali@24
    93
    g_clear_object(&helper->ui);
ali@24
    94
    g_slist_foreach(helper->transactions,(GFunc)g_object_unref,NULL);
ali@24
    95
    g_slist_free(helper->transactions);
ali@24
    96
    helper->transactions=NULL;
ali@61
    97
    g_clear_object(&helper->alternate_installed);
ali@24
    98
    g_clear_object(&helper->installed);
ali@24
    99
    g_clear_object(&helper->upstream);
ali@24
   100
    g_clear_object(&helper->relocated_upstream);
ali@24
   101
}
ali@24
   102
ali@24
   103
static void
ali@24
   104
  plover_transaction_helper_class_init(PloverTransactionHelperClass *klass)
ali@24
   105
{
ali@24
   106
    GObjectClass *gobject_class=G_OBJECT_CLASS(klass);
ali@24
   107
    gobject_class->finalize=
ali@24
   108
      (void (*)(GObject *))plover_transaction_helper_finalize;
ali@24
   109
    gobject_class->dispose=
ali@24
   110
      (void (*)(GObject *))plover_transaction_helper_dispose;
ali@38
   111
    g_type_class_add_private(klass,sizeof(PloverTransactionHelperPrivate));
ali@24
   112
    signals[CLOSE]=g_signal_newv("close",
ali@24
   113
      G_TYPE_FROM_CLASS(klass),G_SIGNAL_RUN_LAST,NULL,NULL,NULL,
ali@24
   114
      g_cclosure_marshal_VOID__VOID,G_TYPE_NONE,0,NULL);
ali@24
   115
}
ali@24
   116
ali@24
   117
static void plover_transaction_helper_init(PloverTransactionHelper *helper)
ali@24
   118
{
ali@24
   119
    helper->report_adding=plover_vector_new();
ali@24
   120
    helper->report_removing=plover_vector_new();
ali@24
   121
}
ali@24
   122
ali@24
   123
static void plover_transaction_helper_assistant_cancel(GtkAssistant *assistant,
ali@24
   124
  PloverTransactionHelper *helper)
ali@24
   125
{
ali@24
   126
    gtk_widget_hide(GTK_WIDGET(helper->assistant));
ali@24
   127
    gtk_assistant_set_current_page(helper->assistant,0);
ali@24
   128
    g_signal_emit(helper,signals[CLOSE],0);
ali@24
   129
}
ali@24
   130
ali@24
   131
static void plover_transaction_helper_assistant_close(GtkAssistant *assistant,
ali@24
   132
  PloverTransactionHelper *helper)
ali@24
   133
{
ali@24
   134
    gtk_widget_hide(GTK_WIDGET(helper->assistant));
ali@24
   135
    gtk_assistant_set_current_page(helper->assistant,0);
ali@24
   136
    g_signal_emit(helper,signals[CLOSE],0);
ali@24
   137
}
ali@24
   138
ali@24
   139
static void
ali@24
   140
  plover_transaction_helper_prepare_confirm(PloverTransactionHelper *helper)
ali@24
   141
{
ali@24
   142
    gchar *package_list,*add,*remove,*s;
ali@24
   143
    GtkLabel *label;
ali@24
   144
    struct plover_vector *report;
ali@24
   145
    if (helper->report_adding->len)
ali@24
   146
    {
ali@24
   147
	plover_vector_sort(helper->report_adding);
ali@24
   148
	if (helper->report_adding_dependencies)
ali@24
   149
	{
ali@24
   150
	    report=plover_vector_dup(helper->report_adding);
ali@24
   151
	    if (helper->report_adding->len==1)
ali@24
   152
		plover_vector_append(report,"its dependencies");
ali@24
   153
	    else
ali@24
   154
		plover_vector_append(report,"their dependencies");
ali@24
   155
	    package_list=plover_vector_format_for_display(report);
ali@24
   156
	    plover_vector_free(report);
ali@24
   157
	}
ali@24
   158
	else
ali@24
   159
	    package_list=
ali@24
   160
	      plover_vector_format_for_display(helper->report_adding);
ali@24
   161
	add=g_strconcat("Packages to be installed or updated: ",package_list,
ali@24
   162
	  ".",NULL);
ali@24
   163
	g_free(package_list);
ali@24
   164
    }
ali@24
   165
    else
ali@24
   166
	add=NULL;
ali@24
   167
    if (helper->report_removing->len)
ali@24
   168
    {
ali@24
   169
	plover_vector_sort(helper->report_removing);
ali@24
   170
	if (helper->report_removing_dependants)
ali@24
   171
	{
ali@24
   172
	    report=plover_vector_dup(helper->report_removing);
ali@24
   173
	    if (helper->report_adding->len==1)
ali@24
   174
		plover_vector_append(report,"its dependants");
ali@24
   175
	    else
ali@24
   176
		plover_vector_append(report,"their dependants");
ali@24
   177
	    package_list=plover_vector_format_for_display(report);
ali@24
   178
	    plover_vector_free(report);
ali@24
   179
	}
ali@24
   180
	else
ali@24
   181
	    package_list=
ali@24
   182
	      plover_vector_format_for_display(helper->report_removing);
ali@24
   183
	remove=g_strconcat("Packages to be removed: ",package_list,".",NULL);
ali@24
   184
	g_free(package_list);
ali@24
   185
    }
ali@24
   186
    else
ali@24
   187
	remove=NULL;
ali@24
   188
    label=GTK_LABEL(gtk_builder_get_object(helper->ui,"SISummaryOfWork"));
ali@24
   189
    if (add && remove)
ali@24
   190
	s=g_strconcat("<b>Installation Summary</b>\n\n",remove,"\n\n",add,NULL);
ali@24
   191
    else if (add || remove)
ali@24
   192
	s=g_strconcat("<b>Installation Summary</b>\n\n",add?add:remove,NULL);
ali@24
   193
    else
ali@24
   194
	s=g_strdup("<b>Installation Summary</b>\n\nNo changes scheduled");
ali@24
   195
    gtk_label_set_markup(label,s);
ali@24
   196
    g_free(s);
ali@24
   197
    g_free(add);
ali@24
   198
    g_free(remove);
ali@24
   199
}
ali@24
   200
ali@24
   201
static void plover_transaction_helper_run(PloverTransactionHelper *helper);
ali@24
   202
ali@24
   203
static void plover_transaction_helper_callback(GObject *source,
ali@24
   204
  GAsyncResult *result,gpointer user_data)
ali@24
   205
{
ali@24
   206
    GError *error=NULL;
ali@24
   207
    PloverTransactionHelper *helper=user_data;
ali@24
   208
    PloverTransaction *transaction=PLOVER_TRANSACTION(source);
ali@24
   209
    if (!plover_transaction_commit_finish(transaction,result,&error))
ali@24
   210
    {
ali@24
   211
	plover_transaction_helper_set_error(helper,error,
ali@24
   212
	  "Software installation failed");
ali@24
   213
	g_error_free(error);
ali@24
   214
    }
ali@24
   215
    else
ali@24
   216
	plover_transaction_helper_run(helper);
ali@38
   217
    /*
ali@38
   218
     * There may be status updates queued by transaction as idle events.
ali@38
   219
     * Process them now before we disconnect so that we don't lose them.
ali@38
   220
     */
ali@38
   221
    while(g_main_context_pending(NULL))
ali@38
   222
	g_main_context_iteration(NULL,FALSE);
ali@24
   223
    g_signal_handlers_disconnect_by_data(transaction,helper);
ali@24
   224
    g_object_unref(transaction);
ali@24
   225
}
ali@24
   226
ali@24
   227
static void plover_transaction_helper_transaction_status_changed(
ali@24
   228
  PloverTransaction *transaction,const char *status,
ali@24
   229
  PloverTransactionHelper *helper)
ali@24
   230
{
ali@24
   231
    GtkProgressBar *bar;
ali@24
   232
    bar=GTK_PROGRESS_BAR(gtk_builder_get_object(helper->ui,"SIProgressBar"));
ali@24
   233
    gtk_progress_bar_set_text(bar,status);
ali@24
   234
}
ali@24
   235
ali@24
   236
static void plover_transaction_helper_run(PloverTransactionHelper *helper)
ali@24
   237
{
ali@24
   238
    PloverTransaction *transaction;
ali@24
   239
    GtkWidget *page;
ali@24
   240
    page=GTK_WIDGET(gtk_builder_get_object(helper->ui,"SIProgress"));
ali@24
   241
    if (helper->transactions)
ali@24
   242
    {
ali@24
   243
	if (helper->assistant)
ali@24
   244
	    gtk_assistant_set_page_complete(helper->assistant,page,FALSE);
ali@24
   245
	transaction=helper->transactions->data;
ali@24
   246
	helper->transactions=g_slist_delete_link(helper->transactions,
ali@24
   247
	  helper->transactions);
ali@24
   248
	g_signal_connect(transaction,"status-changed",
ali@24
   249
	  G_CALLBACK(plover_transaction_helper_transaction_status_changed),
ali@24
   250
	  helper);
ali@24
   251
	plover_transaction_commit_async(transaction,NULL,
ali@24
   252
	  plover_transaction_helper_callback,helper);
ali@24
   253
    }
ali@24
   254
    else if (helper->assistant)
ali@24
   255
	gtk_assistant_set_page_complete(helper->assistant,page,TRUE);
ali@24
   256
}
ali@24
   257
ali@24
   258
static gboolean plover_transaction_helper_pulse(gpointer user_data)
ali@24
   259
{
ali@24
   260
    PloverTransactionHelper *helper=user_data;
ali@24
   261
    GtkWidget *w;
ali@24
   262
    GtkProgressBar *bar;
ali@24
   263
    if (!helper->assistant)
ali@24
   264
	return FALSE;
ali@24
   265
    w=GTK_WIDGET(gtk_builder_get_object(helper->ui,"SIProgress"));
ali@24
   266
    bar=GTK_PROGRESS_BAR(gtk_builder_get_object(helper->ui,"SIProgressBar"));
ali@24
   267
    if (gtk_assistant_get_page_complete(helper->assistant,w))
ali@24
   268
    {
ali@24
   269
	gtk_progress_bar_set_fraction(bar,1.0);
ali@24
   270
	helper->pulse_handler=0;
ali@24
   271
	return FALSE;
ali@24
   272
    }
ali@24
   273
    else
ali@24
   274
    {
ali@24
   275
	gtk_progress_bar_pulse(bar);
ali@24
   276
	return TRUE;
ali@24
   277
    }
ali@24
   278
}
ali@24
   279
ali@24
   280
static void
ali@24
   281
  plover_transaction_helper_prepare_progress(PloverTransactionHelper *helper)
ali@24
   282
{
ali@24
   283
    GError *error=NULL;
ali@24
   284
    GtkToggleButton *button;
ali@24
   285
    PloverTransaction *transaction;
ali@38
   286
    GSList *save_transactions;
ali@38
   287
    PloverTransactionHelperPrivate *priv;
ali@38
   288
    enum plover_transaction_type save_transaction_type;
ali@38
   289
    priv=PLOVER_TRANSACTION_HELPER_GET_PRIVATE(helper);
ali@24
   290
    button=GTK_TOGGLE_BUTTON(gtk_builder_get_object(helper->ui,
ali@24
   291
      "SIRemoveExisting"));
ali@24
   292
    if (gtk_toggle_button_get_active(button))
ali@24
   293
    {
ali@86
   294
	transaction=plover_transaction_helper_new_transaction(helper,&error);
ali@86
   295
	/*
ali@86
   296
	 * I think we want switch to the alternate installed set in the case of
ali@86
   297
	 * alternate_database_clashes, but not in the case of
ali@86
   298
	 * active_database_is_incompatible (see
ali@86
   299
	 * plover_transaction_helper_update_summary_page).
ali@86
   300
	 * Whether testing for helper->alternate_installed is sufficient I'm
ali@86
   301
	 * far from clear.
ali@86
   302
	 */
ali@86
   303
	if (helper->alternate_installed)
ali@86
   304
	    plover_transaction_set_installed(transaction,
ali@86
   305
	      helper->alternate_installed);
ali@86
   306
	if (transaction && !plover_transaction_remove(transaction,NULL,&error))
ali@86
   307
	{
ali@86
   308
	    g_object_unref(transaction);
ali@86
   309
	    transaction=NULL;
ali@86
   310
	}
ali@38
   311
	if (transaction)
ali@38
   312
	{
ali@38
   313
	    save_transactions=helper->transactions;
ali@38
   314
	    helper->transactions=NULL;
ali@38
   315
	    save_transaction_type=priv->transaction_type;
ali@38
   316
	    priv->transaction_type=0;
ali@38
   317
	    if (!plover_transaction_helper_add_transaction(helper,transaction,
ali@38
   318
	      NULL,PLOVER_TRANSACTION_HELPER_REPORT_REMOVE,&error))
ali@38
   319
	    {
ali@38
   320
		g_object_unref(transaction);
ali@38
   321
		transaction=NULL;
ali@38
   322
		helper->transactions=save_transactions;
ali@38
   323
		priv->transaction_type=save_transaction_type;
ali@38
   324
	    }
ali@38
   325
	    else
ali@38
   326
	    {
ali@38
   327
		g_slist_foreach(save_transactions,(GFunc)g_object_unref,NULL);
ali@38
   328
		g_slist_free(save_transactions);
ali@38
   329
	    }
ali@38
   330
	}
ali@24
   331
	if (!transaction)
ali@24
   332
	{
ali@24
   333
	    if (g_error_matches(error,PLOVER_POSIX_ERROR,ENOENT))
ali@24
   334
		g_clear_error(&error);
ali@24
   335
	    if (error)
ali@24
   336
	    {
ali@24
   337
		plover_transaction_helper_set_error(helper,error,
ali@38
   338
		  "Failed to remove existing packages");
ali@24
   339
		g_error_free(error);
ali@24
   340
		return;
ali@24
   341
	    }
ali@24
   342
	}
ali@24
   343
    }
ali@24
   344
    /*
ali@24
   345
     * Note that PloverTransaction does support cancelling a transaction, but
ali@24
   346
     * there are a number of challenges with using it:
ali@24
   347
     *	- cancellation is only supported during the file phase if razor
ali@24
   348
     *	  has atomic rollback,
ali@24
   349
     *  - cancellation is not supported during post-transaction scripts at all
ali@24
   350
     *    (since by the time the first script is started the atomic has already
ali@24
   351
     *    been committed) and these can take quite some time,
ali@24
   352
     *  - where a transaction has an embedded COMMIT, any rollback won't
ali@24
   353
     *    go back beyond this point.
ali@24
   354
     * To support user-cancel, then, we would need some mechanism to:
ali@24
   355
     *  - Comunicate that the operation is being cancelled and this may take
ali@24
   356
     *    some time,
ali@24
   357
     *  - Not allow cancellation at all after the last post-transaction script
ali@24
   358
     *    phase is started,
ali@24
   359
     *  - Report the partially completed transaction where cancellation
ali@24
   360
     *    occurred after a COMMIT point.
ali@24
   361
     * At present, this doesn't appear worth the effort.
ali@24
   362
     */
ali@24
   363
    if (helper->assistant)
ali@24
   364
	gtk_assistant_commit(helper->assistant);
ali@24
   365
    plover_transaction_helper_run(helper);
ali@24
   366
    helper->pulse_handler=g_timeout_add(100,plover_transaction_helper_pulse,
ali@24
   367
      helper);
ali@24
   368
}
ali@24
   369
ali@24
   370
static void plover_transaction_helper_assistant_prepare(GtkAssistant *assistant,
ali@24
   371
  GtkWidget *page,PloverTransactionHelper *helper)
ali@24
   372
{
ali@24
   373
    if (page==GTK_WIDGET(gtk_builder_get_object(helper->ui,"SIConfirm")))
ali@24
   374
	plover_transaction_helper_prepare_confirm(helper);
ali@24
   375
    else if (page==GTK_WIDGET(gtk_builder_get_object(helper->ui,"SIProgress")))
ali@24
   376
	plover_transaction_helper_prepare_progress(helper);
ali@24
   377
}
ali@24
   378
ali@24
   379
static void
ali@24
   380
  plover_transaction_helper_remove_existing_toggled(GtkToggleButton *button,
ali@24
   381
  PloverTransactionHelper *helper)
ali@24
   382
{
ali@24
   383
    GtkWidget *w;
ali@24
   384
    if (helper->assistant)
ali@24
   385
    {
ali@24
   386
	w=GTK_WIDGET(gtk_builder_get_object(helper->ui,"SIConfirm"));
ali@24
   387
	gtk_assistant_set_page_complete(helper->assistant,w,
ali@24
   388
	  gtk_toggle_button_get_active(button));
ali@24
   389
    }
ali@24
   390
}
ali@24
   391
ali@24
   392
PloverTransactionHelper *plover_transaction_helper_new(GtkBuilder *ui)
ali@24
   393
{
ali@24
   394
    gsize len;
ali@24
   395
    gchar *s,*directory,*contents;
ali@24
   396
    GError *error=NULL;
ali@24
   397
    GtkWidget *w;
ali@24
   398
    PloverTransactionHelper *helper;
ali@24
   399
    g_return_val_if_fail(ui == NULL || GTK_IS_BUILDER(ui),NULL);
ali@24
   400
    helper=PLOVER_TRANSACTION_HELPER(
ali@24
   401
      g_object_new(PLOVER_TYPE_TRANSACTION_HELPER,NULL));
ali@24
   402
    if (ui)
ali@24
   403
	helper->ui=g_object_ref(ui);
ali@24
   404
    else
ali@24
   405
	helper->ui=gtk_builder_new();
ali@24
   406
    helper->assistant=
ali@24
   407
      GTK_ASSISTANT(gtk_builder_get_object(helper->ui,"SoftwareInstallation"));
ali@24
   408
    if (!helper->assistant)
ali@24
   409
    {
ali@24
   410
	directory=g_strdup(g_getenv("PLOVER_DATADIR"));
ali@24
   411
	if (!directory)
ali@24
   412
	{
ali@24
   413
#ifdef WIN32
ali@24
   414
	    s=g_win32_get_package_installation_directory_of_module(NULL);
ali@24
   415
	    directory=g_build_filename(s,"share","plover",NULL);
ali@24
   416
	    g_free(s);
ali@24
   417
#else
ali@24
   418
	    directory=g_strdup(PLOVER_DATADIR);
ali@24
   419
#endif
ali@24
   420
	}
ali@24
   421
	s=g_build_filename(directory,"software-installation.ui",NULL);
ali@24
   422
	g_free(directory);
ali@24
   423
	(void)g_file_get_contents(s,&contents,&len,&error);
ali@24
   424
	g_free(s);
ali@24
   425
	if (!error)
ali@24
   426
	{
ali@24
   427
	    (void)gtk_builder_add_from_string(helper->ui,contents,len,&error);
ali@24
   428
	    g_free(contents);
ali@24
   429
	}
ali@24
   430
	if (error)
ali@24
   431
	{
ali@24
   432
	    g_critical("software-installation.ui: %s",error->message);
ali@24
   433
	    g_clear_error(&error);
ali@24
   434
	    g_set_error(&error,PLOVER_GENERAL_ERROR,PLOVER_GENERAL_ERROR_FAILED,
ali@24
   435
	      "Internal error (no user interface)");
ali@24
   436
	    plover_transaction_helper_set_error(helper,error,
ali@24
   437
	      "Can't start installer");
ali@24
   438
	    return helper;
ali@24
   439
	}
ali@24
   440
	helper->assistant=GTK_ASSISTANT(gtk_builder_get_object(helper->ui,
ali@24
   441
	  "SoftwareInstallation"));
ali@24
   442
    }
ali@24
   443
    if (!helper->assistant)
ali@24
   444
    {
ali@24
   445
	g_critical("\"SoftwareInstallation\" object not found");
ali@24
   446
	g_set_error(&error,PLOVER_GENERAL_ERROR,PLOVER_GENERAL_ERROR_FAILED,
ali@24
   447
	  "Internal error (missing wizard)");
ali@24
   448
	plover_transaction_helper_set_error(helper,error,
ali@24
   449
	  "Can't start installer");
ali@24
   450
	g_error_free(error);
ali@24
   451
	return helper;
ali@24
   452
    }
ali@24
   453
    else
ali@24
   454
	g_object_ref(helper->assistant);
ali@24
   455
    if (!GTK_IS_ASSISTANT(helper->assistant))
ali@24
   456
    {
ali@24
   457
	g_critical("\"SoftwareInstallation\" is not a GtkAssistant");
ali@24
   458
	g_set_error(&error,PLOVER_GENERAL_ERROR,PLOVER_GENERAL_ERROR_FAILED,
ali@24
   459
	  "Internal error (unexpected wizard type)");
ali@24
   460
	plover_transaction_helper_set_error(helper,error,
ali@24
   461
	  "Can't start installer");
ali@24
   462
	g_error_free(error);
ali@24
   463
	return helper;
ali@24
   464
    }
ali@24
   465
    g_signal_connect(helper->assistant,"cancel",
ali@24
   466
      G_CALLBACK(plover_transaction_helper_assistant_cancel),helper);
ali@24
   467
    g_signal_connect(helper->assistant,"close",
ali@24
   468
      G_CALLBACK(plover_transaction_helper_assistant_close),helper);
ali@24
   469
    g_signal_connect(helper->assistant,"prepare",
ali@24
   470
      G_CALLBACK(plover_transaction_helper_assistant_prepare),helper);
ali@24
   471
    w=GTK_WIDGET(gtk_builder_get_object(helper->ui,"SIRemoveExisting"));
ali@24
   472
    if (w)
ali@24
   473
	g_signal_connect(w,"toggled",
ali@24
   474
	  G_CALLBACK(plover_transaction_helper_remove_existing_toggled),helper);
ali@24
   475
    w=GTK_WIDGET(gtk_builder_get_object(helper->ui,"SIIntroduction"));
ali@24
   476
    if (w)
ali@24
   477
	gtk_assistant_set_page_complete(helper->assistant,w,TRUE);
ali@24
   478
    return helper;
ali@24
   479
}
ali@24
   480
ali@24
   481
PloverPackageSet *
ali@24
   482
  plover_transaction_helper_get_installed(PloverTransactionHelper *helper)
ali@24
   483
{
ali@61
   484
    gchar *s,*saved_database_uri;
ali@99
   485
    char *install_root,*local_database;
ali@99
   486
    char *active_database=NULL,*alternate_database=NULL;
ali@61
   487
    const char *prefix;
ali@61
   488
    struct comps *comps;
ali@61
   489
    PloverPackageSet *alternate_installed,*installed;
ali@61
   490
    GError *error=NULL;
ali@61
   491
    struct razor_error *razor_error=NULL;
ali@24
   492
    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),NULL);
ali@61
   493
    if (!helper->installed)
ali@61
   494
    {
ali@61
   495
	comps=plover_transaction_helper_get_comps(helper,NULL);
ali@61
   496
	if (!comps)
ali@61
   497
	{
ali@61
   498
	    g_warning("plover_transaction_helper_get_installed: No comps");
ali@61
   499
	    return NULL;
ali@61
   500
	}
ali@61
   501
	install_root=getenv("RAZOR_ROOT");
ali@61
   502
	if (!install_root)
ali@61
   503
	    install_root="file:/";
ali@61
   504
	prefix=plover_transaction_helper_get_prefix(helper,NULL);
ali@61
   505
	if (prefix)
ali@61
   506
	{
ali@61
   507
	    s=g_strconcat(prefix,"/var/lib/razor",NULL);
ali@61
   508
	    local_database=razor_path_relative_to_uri(install_root,*s=='/'?s+1:s,
ali@61
   509
	      &razor_error);
ali@61
   510
	    g_free(s);
ali@61
   511
	    if (!local_database)
ali@61
   512
	    {
ali@61
   513
		g_warning("plover_transaction_helper_get_installed: %s",
ali@61
   514
		  razor_error_get_msg(razor_error));
ali@61
   515
		razor_error_free(razor_error);
ali@61
   516
		return NULL;
ali@61
   517
	    }
ali@61
   518
	}
ali@61
   519
	else
ali@61
   520
	    local_database=NULL;
ali@61
   521
	switch(comps->database)
ali@61
   522
	{
ali@61
   523
	    case COMPS_DATABASE_DISTRIBUTION_LOCAL:
ali@61
   524
		active_database=local_database;
ali@61
   525
		break;
ali@61
   526
	    case COMPS_DATABASE_GLOBAL:
ali@61
   527
		alternate_database=local_database;
ali@61
   528
		break;
ali@61
   529
	}
ali@61
   530
	saved_database_uri=g_strdup(razor_get_database_uri());
ali@61
   531
	if (prefix)
ali@61
   532
	{
ali@61
   533
	    razor_set_database_uri(alternate_database);
ali@61
   534
	    alternate_installed=plover_package_set_new();
ali@61
   535
	    if (!plover_package_set_open(alternate_installed,install_root,TRUE,
ali@61
   536
	      &error))
ali@61
   537
	    {
ali@61
   538
		g_object_unref(alternate_installed);
ali@61
   539
		g_warning("plover_transaction_helper_get_installed: %s",
ali@61
   540
		  error->message);
ali@61
   541
		g_error_free(error);
ali@61
   542
		free(local_database);
ali@61
   543
		razor_set_database_uri(saved_database_uri);
ali@61
   544
		g_free(saved_database_uri);
ali@61
   545
		return NULL;
ali@61
   546
	    }
ali@61
   547
	}
ali@61
   548
	else
ali@61
   549
	    alternate_installed=NULL;
ali@61
   550
	razor_set_database_uri(active_database);
ali@61
   551
	free(local_database);
ali@61
   552
	installed=plover_package_set_new();
ali@61
   553
	if (plover_package_set_open(installed,install_root,TRUE,&error))
ali@61
   554
	{
ali@61
   555
	    helper->alternate_installed=alternate_installed;
ali@61
   556
	    helper->installed=installed;
ali@61
   557
	}
ali@61
   558
	else
ali@61
   559
	{
ali@61
   560
	    g_object_unref(installed);
ali@61
   561
	    if (alternate_installed)
ali@61
   562
		g_object_unref(alternate_installed);
ali@61
   563
	    g_warning("plover_transaction_helper_get_installed: %s",error->message);
ali@61
   564
	    g_error_free(error);
ali@61
   565
	}
ali@61
   566
	razor_set_database_uri(saved_database_uri);
ali@61
   567
	g_free(saved_database_uri);
ali@61
   568
    }
ali@24
   569
    return helper->installed;
ali@24
   570
}
ali@24
   571
ali@24
   572
void plover_transaction_helper_set_installed(PloverTransactionHelper *helper,
ali@24
   573
  PloverPackageSet *installed)
ali@24
   574
{
ali@24
   575
    g_return_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper));
ali@24
   576
    g_return_if_fail(PLOVER_IS_PACKAGE_SET(installed));
ali@24
   577
    g_return_if_fail(helper->installed == NULL);
ali@61
   578
    g_clear_object(&helper->alternate_installed);
ali@24
   579
    helper->installed=g_object_ref(installed);
ali@24
   580
}
ali@24
   581
ali@24
   582
PloverRepository *
ali@24
   583
  plover_transaction_helper_get_upstream(PloverTransactionHelper *helper,
ali@24
   584
  GError **error)
ali@24
   585
{
ali@98
   586
    const char *base_uri;
ali@24
   587
    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),NULL);
ali@24
   588
    if (!helper->upstream)
ali@24
   589
    {
ali@98
   590
	base_uri=plover_transaction_helper_get_base_uri(helper);
ali@98
   591
	helper->upstream=plover_repository_new_from_yum_uri(base_uri,error);
ali@24
   592
    }
ali@24
   593
    return helper->upstream;
ali@24
   594
}
ali@24
   595
ali@24
   596
void plover_transaction_helper_set_upstream(PloverTransactionHelper *helper,
ali@24
   597
  PloverRepository *upstream)
ali@24
   598
{
ali@24
   599
    g_return_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper));
ali@24
   600
    g_return_if_fail(PLOVER_IS_REPOSITORY(upstream));
ali@24
   601
    g_return_if_fail(helper->upstream == NULL);
ali@24
   602
    helper->upstream=g_object_ref(upstream);
ali@24
   603
}
ali@24
   604
ali@98
   605
const char *
ali@98
   606
  plover_transaction_helper_get_base_uri(PloverTransactionHelper *helper)
ali@98
   607
{
ali@98
   608
    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),NULL);
ali@98
   609
    return helper->base_uri;
ali@98
   610
}
ali@98
   611
ali@98
   612
static gboolean plover_gtk__uri_validate(const char *uri)
ali@98
   613
{
ali@98
   614
    char *s;
ali@98
   615
    s=razor_path_relative_to_uri(uri,".",NULL);
ali@98
   616
    free(s);
ali@98
   617
    return !!s;
ali@98
   618
}
ali@98
   619
ali@98
   620
void plover_transaction_helper_set_base_uri(PloverTransactionHelper *helper,
ali@98
   621
  const char *base_uri)
ali@98
   622
{
ali@98
   623
    g_return_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper));
ali@98
   624
    g_return_if_fail(helper->transactions == NULL);
ali@98
   625
    g_return_if_fail(plover_gtk__uri_validate(base_uri));
ali@98
   626
    g_free(helper->base_uri);
ali@98
   627
    helper->base_uri=g_strdup(base_uri);
ali@98
   628
    g_free(helper->base);
ali@98
   629
    helper->base=NULL;
ali@98
   630
}
ali@98
   631
ali@24
   632
const char *plover_transaction_helper_get_base(PloverTransactionHelper *helper)
ali@24
   633
{
ali@24
   634
    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),NULL);
ali@98
   635
    if (helper->base_uri && !helper->base)
ali@98
   636
	helper->base=razor_path_from_uri(helper->base_uri,NULL);
ali@24
   637
    return helper->base;
ali@24
   638
}
ali@24
   639
ali@24
   640
void plover_transaction_helper_set_base(PloverTransactionHelper *helper,
ali@24
   641
  const char *base)
ali@24
   642
{
ali@98
   643
    gchar *base_uri;
ali@24
   644
    g_return_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper));
ali@24
   645
    g_return_if_fail(helper->transactions == NULL);
ali@98
   646
    if (base)
ali@98
   647
	base_uri=razor_path_to_uri(base);
ali@98
   648
    else
ali@98
   649
	base_uri=NULL;
ali@98
   650
    plover_transaction_helper_set_base_uri(helper,base_uri);
ali@98
   651
    g_free(base_uri);
ali@24
   652
    helper->base=g_strdup(base);
ali@24
   653
}
ali@24
   654
ali@24
   655
struct comps *
ali@24
   656
  plover_transaction_helper_get_comps(PloverTransactionHelper *helper,
ali@24
   657
  GError **error)
ali@24
   658
{
ali@24
   659
    gchar *s;
ali@24
   660
    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),NULL);
ali@98
   661
    if (!helper->comps && helper->base_uri)
ali@24
   662
    {
ali@98
   663
	s=g_strconcat(helper->base_uri,"/repodata/comps.xml",NULL);
ali@98
   664
	helper->comps=plover_comps_new_from_uri(s,error);
ali@24
   665
	g_free(s);
ali@24
   666
    }
ali@24
   667
    return helper->comps;
ali@24
   668
}
ali@24
   669
ali@24
   670
const char *
ali@24
   671
  plover_transaction_helper_get_prefix(PloverTransactionHelper *helper,
ali@24
   672
  GError **error)
ali@24
   673
{
ali@24
   674
    const char *prefix;
ali@24
   675
    struct comps *comps;
ali@38
   676
    PloverTransactionHelperPrivate *priv;
ali@24
   677
    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),NULL);
ali@98
   678
    g_return_val_if_fail(helper->base_uri != NULL || plover_transaction_helper_get_installed(helper) != NULL,NULL);
ali@38
   679
    priv=PLOVER_TRANSACTION_HELPER_GET_PRIVATE(helper);
ali@98
   680
    if (helper->base_uri)
ali@24
   681
    {
ali@24
   682
	comps=plover_transaction_helper_get_comps(helper,error);
ali@24
   683
	if (!comps)
ali@24
   684
	    return NULL;
ali@38
   685
	g_free(priv->default_prefix);
ali@61
   686
	priv->default_prefix=plover_comps_get_default_prefix(comps);
ali@38
   687
	return priv->default_prefix;
ali@24
   688
    }
ali@24
   689
    prefix=plover_package_set_guess_prefix(helper->installed,error);
ali@24
   690
    return prefix;
ali@24
   691
}
ali@24
   692
ali@61
   693
#if 0
ali@24
   694
static int plover_transaction_helper_package_count(void)
ali@24
   695
{
ali@24
   696
    int count=0;
ali@24
   697
    char *install_root;
ali@24
   698
    struct razor_set *set;
ali@24
   699
    struct razor_package *package;
ali@24
   700
    struct razor_package_iterator *pi;
ali@24
   701
    install_root=getenv("RAZOR_ROOT");
ali@24
   702
    if (!install_root)
ali@24
   703
	install_root="";
ali@24
   704
    set=razor_root_open_read_only(install_root,NULL);
ali@24
   705
    if (set)
ali@24
   706
    {
ali@24
   707
	pi=razor_package_iterator_create(set);
ali@24
   708
	while (razor_package_iterator_next(pi,&package,RAZOR_DETAIL_LAST))
ali@24
   709
	    count++;
ali@24
   710
	razor_package_iterator_destroy(pi);
ali@24
   711
	razor_set_unref(set);
ali@24
   712
    }
ali@24
   713
    return count;
ali@24
   714
}
ali@61
   715
#endif
ali@61
   716
ali@61
   717
static gboolean prefix_clashes(const char *prefix,const char *alt)
ali@61
   718
{
ali@61
   719
    return g_str_has_prefix(prefix,alt) &&
ali@61
   720
      (prefix[strlen(alt)]=='\0' || prefix[strlen(alt)]=='/');
ali@61
   721
}
ali@24
   722
ali@76
   723
static void
ali@76
   724
  plover_transaction_helper_update_summary_page(PloverTransactionHelper *helper,
ali@24
   725
  GError **error)
ali@24
   726
{
ali@99
   727
    int remove_count=0;
ali@61
   728
    gboolean alternate_database_clashes=FALSE;
ali@61
   729
    gboolean active_database_is_incompatible=FALSE;
ali@61
   730
    const char *alternate_prefix;
ali@24
   731
    gchar *prefix=NULL,*s;
ali@24
   732
    struct comps *comps=NULL;
ali@38
   733
    GtkWidget *container,*summary,*page;
ali@24
   734
    GtkButton *button;
ali@24
   735
    GtkLabel *label;
ali@76
   736
    g_return_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper));
ali@61
   737
    comps=plover_transaction_helper_get_comps(helper,error);
ali@76
   738
    if (comps)
ali@76
   739
	prefix=plover_comps_get_default_prefix(comps);
ali@76
   740
    else
ali@76
   741
	prefix=NULL;
ali@24
   742
    button=GTK_BUTTON(gtk_builder_get_object(helper->ui,"SIRemoveExisting"));
ali@24
   743
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),FALSE);
ali@24
   744
    container=GTK_WIDGET(gtk_builder_get_object(helper->ui,
ali@24
   745
      "SIIncompatibleInstallation"));
ali@38
   746
    summary=GTK_WIDGET(gtk_builder_get_object(helper->ui,"SISummaryOfWork"));
ali@24
   747
    page=GTK_WIDGET(gtk_builder_get_object(helper->ui,"SIConfirm"));
ali@61
   748
    if (helper->check_vendor && prefix && helper->alternate_installed)
ali@61
   749
    {
ali@61
   750
	alternate_prefix=
ali@61
   751
	  plover_package_set_guess_prefix(helper->alternate_installed,NULL);
ali@61
   752
	if (alternate_prefix && prefix_clashes(prefix,alternate_prefix))
ali@61
   753
	{
ali@61
   754
	    alternate_database_clashes=TRUE;
ali@61
   755
	    remove_count=g_slist_length(
ali@61
   756
	      plover_package_set_get_packages(helper->alternate_installed));
ali@61
   757
	}
ali@61
   758
    }
ali@61
   759
    /*
ali@61
   760
     * Rather than try to be too clever, we only deal with one thing
ali@61
   761
     * at a time. That means that if the alternate database clashes
ali@61
   762
     * there's no point checking if the active database is compatible.
ali@61
   763
     */
ali@61
   764
    if (!alternate_database_clashes)
ali@61
   765
    {
ali@61
   766
	if (helper->check_vendor && prefix &&
ali@61
   767
	  !plover_package_set_files_match_prefix(helper->installed,prefix))
ali@61
   768
	{
ali@61
   769
	    active_database_is_incompatible=TRUE;
ali@61
   770
	    remove_count=
ali@61
   771
	      g_slist_length(plover_package_set_get_packages(helper->installed));
ali@61
   772
	}
ali@61
   773
    }
ali@61
   774
    if (alternate_database_clashes || active_database_is_incompatible)
ali@24
   775
    {
ali@76
   776
	g_assert(comps!=NULL);
ali@24
   777
	label=GTK_LABEL(gtk_builder_get_object(helper->ui,
ali@24
   778
	  "SIIncompatibleInstallationLabel"));
ali@61
   779
	if (alternate_database_clashes)
ali@61
   780
	    s=g_strdup_printf("<b>Incompatible Installation</b>\n\n"
ali@61
   781
	      "There is an existing installation under %s\n"
ali@61
   782
	      "which is not compatible with this distribution. In order\n"
ali@61
   783
	      "to continue, the existing installation must be uninstalled.",
ali@61
   784
	      comps->vendor);
ali@61
   785
	else /* active_database_is_incompatible */
ali@61
   786
	    s=g_strdup_printf("<b>Incompatible Installation</b>\n\n"
ali@61
   787
	      "The existing installation is not from %s.\n In order "
ali@61
   788
	      "to continue, all the existing packages must be removed.",
ali@61
   789
	      comps->vendor);
ali@24
   790
	gtk_label_set_markup(label,s);
ali@24
   791
	g_free(s);
ali@61
   792
	s=g_strdup_printf("Remove %d existing package%s",remove_count,
ali@61
   793
	  remove_count==1?"":"s");
ali@24
   794
	gtk_button_set_label(button,s);
ali@24
   795
	g_free(s);
ali@24
   796
	gtk_widget_show(container);
ali@38
   797
	gtk_widget_hide(summary);
ali@24
   798
	if (helper->assistant)
ali@24
   799
	    gtk_assistant_set_page_complete(helper->assistant,page,FALSE);
ali@24
   800
    }
ali@24
   801
    else
ali@24
   802
    {
ali@24
   803
	gtk_widget_hide(container);
ali@38
   804
	gtk_widget_show(summary);
ali@24
   805
	if (helper->assistant)
ali@24
   806
	    gtk_assistant_set_page_complete(helper->assistant,page,TRUE);
ali@24
   807
    }
ali@38
   808
    g_free(prefix);
ali@24
   809
}
ali@24
   810
ali@24
   811
void plover_transaction_helper_set_check_vendor(PloverTransactionHelper *helper,
ali@24
   812
  gboolean check_vendor)
ali@24
   813
{
ali@24
   814
    g_return_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper));
ali@24
   815
    if (helper->check_vendor!=check_vendor)
ali@24
   816
    {
ali@24
   817
	helper->check_vendor=check_vendor;
ali@24
   818
	if (helper->transactions)
ali@76
   819
	    plover_transaction_helper_update_summary_page(helper,NULL);
ali@24
   820
    }
ali@24
   821
}
ali@24
   822
ali@24
   823
/*
ali@75
   824
 * If plover_transaction_helper_add_transaction() fails with an error
ali@24
   825
 * of PLOVER_GENERAL_ERROR,PLOVER_GENERAL_ERROR_REQUIREMENTS_NOT_MET
ali@24
   826
 * then plover_transaction_helper_get_unsatisfied() can be used to
ali@24
   827
 * retrieve a textual description of the problem.
ali@24
   828
 */
ali@24
   829
ali@24
   830
const char *
ali@24
   831
  plover_transaction_helper_get_unsatisfied(PloverTransactionHelper *helper)
ali@24
   832
{
ali@24
   833
    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),NULL);
ali@24
   834
    return helper->unsatisfied;
ali@24
   835
}
ali@24
   836
ali@38
   837
#define PLOVER_TRANSACTION_HELPER_IS_VALID_REPORT_ACTION(action) \
ali@38
   838
  ((action)==PLOVER_TRANSACTION_HELPER_REPORT_INSTALL || \
ali@38
   839
  (action)==PLOVER_TRANSACTION_HELPER_REPORT_REMOVE || \
ali@38
   840
  (action)==PLOVER_TRANSACTION_HELPER_REPORT_UPDATE)
ali@38
   841
ali@24
   842
gboolean
ali@24
   843
  plover_transaction_helper_add_transaction(PloverTransactionHelper *helper,
ali@24
   844
  PloverTransaction *transaction,struct plover_vector *report_packages,
ali@38
   845
  PloverTransactionHelperReportAction report_action,GError **error)
ali@24
   846
{
ali@24
   847
    int i,count;
ali@24
   848
    gboolean other_packages;
ali@24
   849
    const char *s,*name;
ali@99
   850
    enum razor_install_action razor_action;
ali@99
   851
    PloverTransactionHelperReportAction action;
ali@24
   852
    struct razor_install_iterator *ii;
ali@38
   853
    struct razor_set *report_set;
ali@24
   854
    struct razor_package *package;
ali@24
   855
    struct plover_vector *tasked_packages;
ali@38
   856
    PloverTransactionHelperPrivate *priv;
ali@38
   857
    GtkWidget *w;
ali@24
   858
    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),FALSE);
ali@24
   859
    g_return_val_if_fail(PLOVER_IS_TRANSACTION(transaction),FALSE);
ali@38
   860
    g_return_val_if_fail(PLOVER_TRANSACTION_HELPER_IS_VALID_REPORT_ACTION(report_action),FALSE);
ali@38
   861
    g_return_val_if_fail(plover_transaction_get_system_set(transaction)!=NULL,FALSE);
ali@38
   862
    priv=PLOVER_TRANSACTION_HELPER_GET_PRIVATE(helper);
ali@24
   863
    g_free(helper->unsatisfied);
ali@24
   864
    helper->unsatisfied=NULL;
ali@24
   865
    if (!plover_transaction_resolve(transaction,error))
ali@24
   866
    {
ali@24
   867
	s=plover_transaction_get_unsatisfied(transaction);
ali@24
   868
	helper->unsatisfied=g_strdup(s);
ali@24
   869
	return FALSE;
ali@24
   870
    }
ali@24
   871
    ii=plover_transaction_get_install_iterator(transaction,error);
ali@24
   872
    if (!ii)
ali@24
   873
	return FALSE;
ali@38
   874
    if (report_action==PLOVER_TRANSACTION_HELPER_REPORT_REMOVE)
ali@38
   875
	report_set=plover_transaction_get_system_set(transaction);
ali@38
   876
    else
ali@38
   877
	report_set=plover_transaction_get_next_set(transaction,error);
ali@38
   878
    if (!report_set)
ali@24
   879
	return FALSE;
ali@24
   880
    tasked_packages=plover_vector_new();
ali@24
   881
    other_packages=FALSE;
ali@99
   882
    while (razor_install_iterator_next(ii,&package,&razor_action,&count))
ali@24
   883
    {
ali@99
   884
	if (razor_action==RAZOR_INSTALL_ACTION_ADD)
ali@99
   885
	    action=PLOVER_TRANSACTION_HELPER_REPORT_INSTALL;
ali@99
   886
	else if (razor_action==RAZOR_INSTALL_ACTION_REMOVE)
ali@99
   887
	    action=PLOVER_TRANSACTION_HELPER_REPORT_REMOVE;
ali@99
   888
	else
ali@99
   889
	    continue;
ali@99
   890
	if (action==report_action || razor_action==RAZOR_INSTALL_ACTION_ADD &&
ali@38
   891
	  report_action==PLOVER_TRANSACTION_HELPER_REPORT_UPDATE)
ali@24
   892
	{
ali@38
   893
	    razor_package_get_details(report_set,package,RAZOR_DETAIL_NAME,
ali@38
   894
	      &name,RAZOR_DETAIL_LAST);
ali@24
   895
	    if (!report_packages ||
ali@24
   896
	      plover_vector_contains(report_packages,name))
ali@24
   897
		plover_vector_append(tasked_packages,name);
ali@24
   898
	    else
ali@24
   899
		other_packages=TRUE;
ali@24
   900
	}
ali@24
   901
    }
ali@24
   902
    if (!tasked_packages->len)
ali@24
   903
    {
ali@24
   904
	/*
ali@24
   905
	 * If there are no reportable packages tasked for action there
ali@103
   906
	 * shouldn't be any packages at all, but let's be paranoid.
ali@24
   907
	 */
ali@24
   908
	other_packages=FALSE;
ali@24
   909
	razor_install_iterator_rewind(ii);
ali@99
   910
	while (razor_install_iterator_next(ii,&package,&razor_action,&count))
ali@24
   911
	{
ali@99
   912
	    if (razor_action==RAZOR_INSTALL_ACTION_ADD)
ali@99
   913
		action=PLOVER_TRANSACTION_HELPER_REPORT_INSTALL;
ali@99
   914
	    else if (razor_action==RAZOR_INSTALL_ACTION_REMOVE)
ali@99
   915
		action=PLOVER_TRANSACTION_HELPER_REPORT_REMOVE;
ali@99
   916
	    else
ali@99
   917
		continue;
ali@103
   918
	    if (action==report_action ||
ali@103
   919
	      razor_action==RAZOR_INSTALL_ACTION_ADD &&
ali@103
   920
	      report_action==PLOVER_TRANSACTION_HELPER_REPORT_UPDATE)
ali@24
   921
	    {
ali@38
   922
		razor_package_get_details(report_set,package,RAZOR_DETAIL_NAME,
ali@38
   923
		  &name,RAZOR_DETAIL_LAST);
ali@24
   924
		plover_vector_append(tasked_packages,name);
ali@24
   925
	    }
ali@24
   926
	}
ali@24
   927
    }
ali@24
   928
    if (!tasked_packages->len)
ali@24
   929
    {
ali@24
   930
	g_set_error(error,PLOVER_GENERAL_ERROR,
ali@24
   931
	  PLOVER_GENERAL_ERROR_NO_WORK,"Transaction includes no %s actions",
ali@38
   932
	  report_action==PLOVER_TRANSACTION_HELPER_REPORT_REMOVE?
ali@38
   933
	  "remove":"add");
ali@24
   934
	plover_vector_free(tasked_packages);
ali@24
   935
	return FALSE;
ali@24
   936
    }
ali@24
   937
    if (!helper->transactions)
ali@76
   938
	plover_transaction_helper_update_summary_page(helper,error);
ali@24
   939
    g_object_ref(transaction);
ali@24
   940
    helper->transactions=g_slist_append(helper->transactions,transaction);
ali@38
   941
    if (report_action==PLOVER_TRANSACTION_HELPER_REPORT_REMOVE)
ali@24
   942
    {
ali@38
   943
	priv->transaction_type|=TRANSACTION_TYPE_REMOVE;
ali@38
   944
	for(i=0;i<tasked_packages->len;i++)
ali@38
   945
	{
ali@38
   946
	    s=tasked_packages->strings[i];
ali@38
   947
	    if (!plover_vector_contains(helper->report_removing,s))
ali@38
   948
		plover_vector_append(helper->report_removing,s);
ali@38
   949
	}
ali@38
   950
	helper->report_removing_dependants|=other_packages;
ali@38
   951
    }
ali@38
   952
    else
ali@38
   953
    {
ali@38
   954
	if (report_action==PLOVER_TRANSACTION_HELPER_REPORT_UPDATE)
ali@38
   955
	    priv->transaction_type|=TRANSACTION_TYPE_REMOVE;
ali@38
   956
	priv->transaction_type|=TRANSACTION_TYPE_INSTALL;
ali@24
   957
	for(i=0;i<tasked_packages->len;i++)
ali@24
   958
	{
ali@24
   959
	    s=tasked_packages->strings[i];
ali@24
   960
	    if (!plover_vector_contains(helper->report_adding,s))
ali@24
   961
		plover_vector_append(helper->report_adding,s);
ali@24
   962
	}
ali@24
   963
	helper->report_adding_dependencies|=other_packages;
ali@24
   964
    }
ali@38
   965
    w=GTK_WIDGET(gtk_builder_get_object(helper->ui,"SIProgressLabel"));
ali@38
   966
    switch(priv->transaction_type)
ali@24
   967
    {
ali@38
   968
	case TRANSACTION_TYPE_INSTALL:
ali@38
   969
	    gtk_label_set_markup(GTK_LABEL(w),
ali@38
   970
	      "<b>Installing the Software</b>\n\n"
ali@38
   971
	      "Please wait while the Installation Assistant "
ali@38
   972
	      "installs the software.\n"
ali@38
   973
	      "This may take several minutes.");
ali@38
   974
	    break;
ali@38
   975
	case TRANSACTION_TYPE_REMOVE:
ali@38
   976
	    gtk_label_set_markup(GTK_LABEL(w),
ali@38
   977
	      "<b>Removing Packages</b>\n\n"
ali@38
   978
	      "Please wait while the Installation Assistant "
ali@38
   979
	      "removes packages.\n"
ali@38
   980
	      "This may take several minutes.");
ali@38
   981
	    break;
ali@38
   982
	default:
ali@38
   983
	case TRANSACTION_TYPE_UPDATE:
ali@38
   984
	    gtk_label_set_markup(GTK_LABEL(w),
ali@38
   985
	      "<b>Updating the Software</b>\n\n"
ali@38
   986
	      "Please wait while the Installation Assistant "
ali@38
   987
	      "updates the software.\n"
ali@38
   988
	      "This may take several minutes.");
ali@38
   989
	    break;
ali@24
   990
    }
ali@24
   991
    plover_vector_free(tasked_packages);
ali@24
   992
    return TRUE;
ali@24
   993
}
ali@24
   994
ali@24
   995
static PloverTransaction *
ali@24
   996
  plover_transaction_helper_new_transaction(PloverTransactionHelper *helper,
ali@24
   997
  GError **error)
ali@24
   998
{
ali@24
   999
    gboolean ok;
ali@98
  1000
    const char *base_uri,*prefix;
ali@24
  1001
    GError *tmp_error=NULL;
ali@24
  1002
    PloverTransaction *transaction;
ali@24
  1003
    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),NULL);
ali@61
  1004
    g_return_val_if_fail(plover_transaction_helper_get_installed(helper) != NULL,NULL);
ali@24
  1005
    prefix=plover_transaction_helper_get_prefix(helper,&tmp_error);
ali@24
  1006
    if (tmp_error)
ali@24
  1007
    {
ali@24
  1008
	g_propagate_error(error,tmp_error);
ali@24
  1009
	return NULL;
ali@24
  1010
    }
ali@24
  1011
    transaction=plover_transaction_new();
ali@24
  1012
    plover_transaction_set_prefix(transaction,prefix);
ali@24
  1013
    plover_transaction_set_installed(transaction,helper->installed);
ali@24
  1014
    if (helper->upstream)
ali@24
  1015
	ok=plover_transaction_set_upstream(transaction,helper->upstream,error);
ali@24
  1016
    else
ali@24
  1017
    {
ali@98
  1018
	base_uri=plover_transaction_helper_get_base_uri(helper);
ali@98
  1019
	ok=plover_transaction_set_upstream_from_yum_uri(transaction,base_uri,
ali@98
  1020
	  error);
ali@24
  1021
    }
ali@24
  1022
    if (!ok)
ali@24
  1023
    {
ali@24
  1024
	g_object_unref(transaction);
ali@24
  1025
	transaction=NULL;
ali@24
  1026
    }
ali@24
  1027
    return transaction;
ali@24
  1028
}
ali@24
  1029
ali@24
  1030
struct plover_vector *plover_transaction_helper_group_get_default_packages(
ali@24
  1031
  PloverTransactionHelper *helper,const char *group,GError **error)
ali@24
  1032
{
ali@24
  1033
    gboolean changed;
ali@24
  1034
    struct comps *comps;
ali@24
  1035
    struct comps_group *grp;
ali@24
  1036
    struct comps_requirement *pkg;
ali@24
  1037
    struct plover_vector *default_packages;
ali@24
  1038
    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),FALSE);
ali@24
  1039
    comps=plover_transaction_helper_get_comps(helper,error);
ali@24
  1040
    if (!comps)
ali@24
  1041
	return NULL;
ali@24
  1042
    grp=plover_comps_lookup_group(comps,group);
ali@24
  1043
    if (!grp)
ali@24
  1044
    {
ali@24
  1045
	g_set_error(error,PLOVER_GENERAL_ERROR,
ali@24
  1046
	  PLOVER_GENERAL_ERROR_FAILED,"%s: group not found",group);
ali@24
  1047
	return NULL;
ali@24
  1048
    }
ali@24
  1049
    default_packages=plover_vector_new();
ali@24
  1050
    do
ali@24
  1051
    {
ali@24
  1052
	changed=FALSE;
ali@24
  1053
	for(pkg=grp->packages;pkg;pkg=pkg->next)
ali@24
  1054
	{
ali@24
  1055
	    if (plover_vector_contains(default_packages,pkg->name))
ali@24
  1056
		continue;
ali@24
  1057
	    if (pkg->type==COMPS_REQUIREMENT_DEFAULT ||
ali@24
  1058
	      pkg->type==COMPS_REQUIREMENT_MANDATORY ||
ali@38
  1059
	      pkg->type==COMPS_REQUIREMENT_CONDITIONAL && pkg->requires &&
ali@24
  1060
	      plover_vector_contains(default_packages,pkg->requires))
ali@24
  1061
	    {
ali@24
  1062
		changed=TRUE;
ali@24
  1063
		plover_vector_append(default_packages,pkg->name);
ali@24
  1064
	    }
ali@24
  1065
	}
ali@24
  1066
    } while(changed);
ali@24
  1067
    return default_packages;
ali@24
  1068
}
ali@24
  1069
ali@24
  1070
/*
ali@24
  1071
 * Returns TRUE if there is work to be done or FALSE if the packages are
ali@24
  1072
 * already installed or on error.
ali@24
  1073
 */
ali@24
  1074
gboolean
ali@24
  1075
  plover_transaction_helper_install_packages(PloverTransactionHelper *helper,
ali@24
  1076
  struct plover_vector *packages,GError **error)
ali@24
  1077
{
ali@24
  1078
    gboolean retval;
ali@24
  1079
    PloverTransaction *transaction;
ali@24
  1080
    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),FALSE);
ali@24
  1081
    g_return_val_if_fail(packages != NULL,FALSE);
ali@24
  1082
    if (!packages->len)
ali@24
  1083
    {
ali@24
  1084
	g_set_error(error,PLOVER_GENERAL_ERROR,
ali@24
  1085
	  PLOVER_GENERAL_ERROR_NO_WORK,"No packages listed to be installed");
ali@24
  1086
	return FALSE;
ali@24
  1087
    }
ali@24
  1088
    transaction=plover_transaction_helper_new_transaction(helper,error);
ali@24
  1089
    if (!transaction)
ali@24
  1090
	return FALSE;
ali@24
  1091
    if (!plover_transaction_install(transaction,packages->strings,error))
ali@24
  1092
    {
ali@24
  1093
	g_object_unref(transaction);
ali@24
  1094
	return FALSE;
ali@24
  1095
    }
ali@24
  1096
    retval=plover_transaction_helper_add_transaction(helper,transaction,
ali@38
  1097
      packages,PLOVER_TRANSACTION_HELPER_REPORT_INSTALL,error);
ali@24
  1098
    g_object_unref(transaction);
ali@24
  1099
    return retval;
ali@24
  1100
}
ali@24
  1101
ali@24
  1102
/*
ali@24
  1103
 * Returns TRUE if there is work to be done or FALSE if the group is
ali@24
  1104
 * already installed or on error.
ali@24
  1105
 */
ali@24
  1106
gboolean
ali@24
  1107
  plover_transaction_helper_install_group(PloverTransactionHelper *helper,
ali@24
  1108
  const char *group,GError **error)
ali@24
  1109
{
ali@24
  1110
    gboolean retval;
ali@24
  1111
    struct plover_vector *selected_packages;
ali@24
  1112
    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),FALSE);
ali@24
  1113
    selected_packages=plover_transaction_helper_group_get_default_packages(
ali@24
  1114
      helper,group,error);
ali@24
  1115
    if (!selected_packages)
ali@24
  1116
	return FALSE;
ali@24
  1117
    if (!selected_packages->len)
ali@24
  1118
    {
ali@24
  1119
	g_set_error(error,PLOVER_GENERAL_ERROR,
ali@24
  1120
	  PLOVER_GENERAL_ERROR_FAILED,"%s: no default packages",group);
ali@24
  1121
	plover_vector_free(selected_packages);
ali@24
  1122
	return FALSE;
ali@24
  1123
    }
ali@24
  1124
    retval=plover_transaction_helper_install_packages(helper,selected_packages,
ali@24
  1125
      error);
ali@24
  1126
    plover_vector_free(selected_packages);
ali@24
  1127
    return retval;
ali@24
  1128
}
ali@24
  1129
ali@24
  1130
/*
ali@24
  1131
 * Returns TRUE if there is work to be done or FALSE if the group is
ali@24
  1132
 * not installed or on error.
ali@24
  1133
 */
ali@24
  1134
gboolean plover_transaction_helper_remove_group(PloverTransactionHelper *helper,
ali@24
  1135
  const char *group,GError **error)
ali@24
  1136
{
ali@24
  1137
    gboolean retval;
ali@24
  1138
    struct plover_vector *selected_packages;
ali@24
  1139
    PloverTransaction *transaction;
ali@24
  1140
    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),FALSE);
ali@61
  1141
    g_return_val_if_fail(plover_transaction_helper_get_installed(helper) != NULL,FALSE);
ali@24
  1142
    selected_packages=plover_transaction_helper_group_get_default_packages(
ali@24
  1143
      helper,group,error);
ali@24
  1144
    if (!selected_packages)
ali@24
  1145
	return FALSE;
ali@24
  1146
    if (!selected_packages->len)
ali@24
  1147
    {
ali@24
  1148
	g_set_error(error,PLOVER_GENERAL_ERROR,
ali@24
  1149
	  PLOVER_GENERAL_ERROR_FAILED,"%s: no default packages",group);
ali@24
  1150
	plover_vector_free(selected_packages);
ali@24
  1151
	return FALSE;
ali@24
  1152
    }
ali@24
  1153
    transaction=plover_transaction_new();
ali@24
  1154
    plover_transaction_set_installed(transaction,helper->installed);
ali@24
  1155
    if (!plover_transaction_remove(transaction,selected_packages->strings,
ali@24
  1156
      error))
ali@24
  1157
    {
ali@24
  1158
	plover_vector_free(selected_packages);
ali@24
  1159
	g_object_unref(transaction);
ali@24
  1160
	return FALSE;
ali@24
  1161
    }
ali@24
  1162
    retval=plover_transaction_helper_add_transaction(helper,transaction,
ali@38
  1163
      NULL,PLOVER_TRANSACTION_HELPER_REPORT_REMOVE,error);
ali@24
  1164
    g_object_unref(transaction);
ali@24
  1165
    plover_vector_free(selected_packages);
ali@24
  1166
    return retval;
ali@24
  1167
}
ali@24
  1168
ali@24
  1169
/*
ali@103
  1170
 * Returns TRUE if there is work to be done or FALSE if the group is
ali@103
  1171
 * empty or on error.
ali@103
  1172
 *
ali@103
  1173
 * The default action is to:
ali@103
  1174
 *	- install (and update all) if any of the packages in @group are
ali@103
  1175
 *	  missing or out of date,
ali@103
  1176
 *	- otherwise update all if any packages are out of date,
ali@103
  1177
 *	- otherwise remove ALL packages for distribution-local comps,
ali@103
  1178
 *	- otherwise remove all packages in @group, their dependants and leaves.
ali@103
  1179
 */
ali@103
  1180
gboolean plover_transaction_helper_default_action_on_group(
ali@103
  1181
  PloverTransactionHelper *helper,const char *group,GError **error)
ali@103
  1182
{
ali@103
  1183
    gboolean distribution_local=FALSE,retval;
ali@103
  1184
    GError *tmp_err=NULL;
ali@103
  1185
    struct comps *comps;
ali@103
  1186
    struct plover_vector *selected_packages;
ali@103
  1187
    PloverTransaction *transaction;
ali@103
  1188
    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),FALSE);
ali@103
  1189
    selected_packages=plover_transaction_helper_group_get_default_packages(
ali@103
  1190
      helper,group,error);
ali@103
  1191
    if (!selected_packages)
ali@103
  1192
	return FALSE;
ali@103
  1193
    if (!selected_packages->len)
ali@103
  1194
    {
ali@103
  1195
	g_set_error(error,PLOVER_GENERAL_ERROR,
ali@103
  1196
	  PLOVER_GENERAL_ERROR_FAILED,"%s: no default packages",group);
ali@103
  1197
	plover_vector_free(selected_packages);
ali@103
  1198
	return FALSE;
ali@103
  1199
    }
ali@103
  1200
    comps=plover_transaction_helper_get_comps(helper,NULL);
ali@103
  1201
    if (comps && comps->database==COMPS_DATABASE_DISTRIBUTION_LOCAL)
ali@103
  1202
	distribution_local=TRUE;
ali@103
  1203
    transaction=plover_transaction_helper_new_transaction(helper,error);
ali@103
  1204
    if (!transaction)
ali@103
  1205
    {
ali@103
  1206
	plover_vector_free(selected_packages);
ali@103
  1207
	return FALSE;
ali@103
  1208
    }
ali@103
  1209
    if (!plover_transaction_install_with_update_all(transaction,
ali@103
  1210
      selected_packages->strings,error))
ali@103
  1211
    {
ali@103
  1212
	g_object_unref(transaction);
ali@103
  1213
	plover_vector_free(selected_packages);
ali@103
  1214
	return FALSE;
ali@103
  1215
    }
ali@103
  1216
    retval=plover_transaction_helper_add_transaction(helper,transaction,
ali@103
  1217
      selected_packages,PLOVER_TRANSACTION_HELPER_REPORT_INSTALL,&tmp_err);
ali@103
  1218
    g_object_unref(transaction);
ali@103
  1219
    if (!retval)
ali@103
  1220
    {
ali@103
  1221
	if (!g_error_matches(tmp_err,PLOVER_GENERAL_ERROR,
ali@103
  1222
	  PLOVER_GENERAL_ERROR_NO_WORK))
ali@103
  1223
	{
ali@103
  1224
	    g_propagate_error(error,tmp_err);
ali@103
  1225
	    plover_vector_free(selected_packages);
ali@103
  1226
	    return FALSE;
ali@103
  1227
	}
ali@103
  1228
	g_clear_error(&tmp_err);
ali@103
  1229
	transaction=plover_transaction_helper_new_transaction(helper,error);
ali@103
  1230
	if (!transaction)
ali@103
  1231
	{
ali@103
  1232
	    plover_vector_free(selected_packages);
ali@103
  1233
	    return FALSE;
ali@103
  1234
	}
ali@103
  1235
	if (!plover_transaction_update(transaction,NULL,error))
ali@103
  1236
	{
ali@103
  1237
	    g_object_unref(transaction);
ali@103
  1238
	    plover_vector_free(selected_packages);
ali@103
  1239
	    return FALSE;
ali@103
  1240
	}
ali@103
  1241
	retval=plover_transaction_helper_add_transaction(helper,transaction,
ali@103
  1242
	  selected_packages,PLOVER_TRANSACTION_HELPER_REPORT_UPDATE,&tmp_err);
ali@103
  1243
	g_object_unref(transaction);
ali@103
  1244
	if (!retval)
ali@103
  1245
	{
ali@103
  1246
	    if (!g_error_matches(tmp_err,PLOVER_GENERAL_ERROR,
ali@103
  1247
	      PLOVER_GENERAL_ERROR_NO_WORK))
ali@103
  1248
	    {
ali@103
  1249
		g_propagate_error(error,tmp_err);
ali@103
  1250
		plover_vector_free(selected_packages);
ali@103
  1251
		return FALSE;
ali@103
  1252
	    }
ali@103
  1253
	    g_clear_error(&tmp_err);
ali@103
  1254
	    transaction=plover_transaction_helper_new_transaction(helper,error);
ali@103
  1255
	    if (!transaction)
ali@103
  1256
	    {
ali@103
  1257
		plover_vector_free(selected_packages);
ali@103
  1258
		return FALSE;
ali@103
  1259
	    }
ali@103
  1260
	    if (!plover_transaction_remove_with_dependants_and_leaves(
ali@103
  1261
	      transaction,distribution_local?NULL:selected_packages->strings,
ali@103
  1262
	      error))
ali@103
  1263
	    {
ali@103
  1264
		g_object_unref(transaction);
ali@103
  1265
		plover_vector_free(selected_packages);
ali@103
  1266
		return FALSE;
ali@103
  1267
	    }
ali@103
  1268
	    retval=plover_transaction_helper_add_transaction(helper,transaction,
ali@103
  1269
	      NULL,PLOVER_TRANSACTION_HELPER_REPORT_REMOVE,error);
ali@103
  1270
	    g_object_unref(transaction);
ali@103
  1271
	}
ali@103
  1272
    }
ali@103
  1273
    plover_vector_free(selected_packages);
ali@103
  1274
    return retval;
ali@103
  1275
}
ali@103
  1276
ali@103
  1277
/*
ali@24
  1278
 * Returns TRUE if there is work to be done or FALSE if all updates have
ali@24
  1279
 * already been applied or on error.
ali@24
  1280
 */
ali@24
  1281
gboolean plover_transaction_helper_update(PloverTransactionHelper *helper,
ali@24
  1282
  GError **error)
ali@24
  1283
{
ali@24
  1284
    gboolean retval;
ali@24
  1285
    PloverTransaction *transaction;
ali@24
  1286
    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),FALSE);
ali@24
  1287
    transaction=plover_transaction_helper_new_transaction(helper,error);
ali@24
  1288
    if (!transaction)
ali@24
  1289
	return FALSE;
ali@24
  1290
    if (!plover_transaction_update(transaction,NULL,error))
ali@24
  1291
    {
ali@24
  1292
	g_object_unref(transaction);
ali@24
  1293
	return FALSE;
ali@24
  1294
    }
ali@24
  1295
    retval=plover_transaction_helper_add_transaction(helper,transaction,
ali@38
  1296
      NULL,PLOVER_TRANSACTION_HELPER_REPORT_UPDATE,error);
ali@24
  1297
    g_object_unref(transaction);
ali@24
  1298
    return retval;
ali@24
  1299
}
ali@24
  1300
ali@24
  1301
gboolean plover_transaction_helper_get_visible(PloverTransactionHelper *helper)
ali@24
  1302
{
ali@24
  1303
    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),FALSE);
ali@24
  1304
    if (helper->error_dialog)
ali@24
  1305
	return TRUE;
ali@24
  1306
    else if (!helper->assistant)
ali@24
  1307
	return FALSE;
ali@24
  1308
    else
ali@24
  1309
	return gtk_widget_get_visible(GTK_WIDGET(helper->assistant));
ali@24
  1310
}
ali@24
  1311
ali@24
  1312
void plover_transaction_helper_present(PloverTransactionHelper *helper)
ali@24
  1313
{
ali@24
  1314
    g_return_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper));
ali@24
  1315
    if (helper->error_dialog)
ali@24
  1316
	gtk_window_present(GTK_WINDOW(helper->error_dialog));
ali@24
  1317
    else if (helper->assistant)
ali@24
  1318
	gtk_window_present(GTK_WINDOW(helper->assistant));
ali@24
  1319
}
ali@24
  1320
ali@24
  1321
static void
ali@24
  1322
  plover_transaction_helper_error_dialog_response(GtkDialog *error_dialog,
ali@24
  1323
  int response_id,PloverTransactionHelper *helper)
ali@24
  1324
{
ali@24
  1325
    g_signal_handlers_disconnect_by_data(error_dialog,helper);
ali@24
  1326
    if ((GtkWidget *)error_dialog==helper->error_dialog)
ali@24
  1327
    {
ali@24
  1328
	gtk_widget_destroy(helper->error_dialog);
ali@24
  1329
	helper->error_dialog=NULL;
ali@24
  1330
	if (helper->assistant)
ali@24
  1331
	{
ali@24
  1332
	    gtk_widget_hide(GTK_WIDGET(helper->assistant));
ali@24
  1333
	    gtk_assistant_set_current_page(helper->assistant,0);
ali@24
  1334
	}
ali@24
  1335
	g_signal_emit(helper,signals[CLOSE],0);
ali@24
  1336
    }
ali@24
  1337
}
ali@24
  1338
ali@24
  1339
const char *plover_transaction_helper_get_error(PloverTransactionHelper *helper,
ali@24
  1340
  const GError **error)
ali@24
  1341
{
ali@99
  1342
    g_return_val_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper),NULL);
ali@24
  1343
    if (!helper->error_dialog)
ali@24
  1344
	return NULL;
ali@24
  1345
    if (error)
ali@24
  1346
	*error=helper->error;
ali@24
  1347
    return helper->error_primary_text;
ali@24
  1348
}
ali@24
  1349
ali@24
  1350
void plover_transaction_helper_set_error(PloverTransactionHelper *helper,
ali@24
  1351
  const GError *error,const char *primary_text)
ali@24
  1352
{
ali@24
  1353
    GtkMessageType type;
ali@24
  1354
    GtkWindow *window;
ali@24
  1355
    g_return_if_fail(PLOVER_IS_TRANSACTION_HELPER(helper));
ali@24
  1356
    g_return_if_fail(error != NULL);
ali@24
  1357
    g_return_if_fail(primary_text != NULL);
ali@24
  1358
    if (helper->pulse_handler)
ali@24
  1359
    {
ali@24
  1360
	g_source_remove(helper->pulse_handler);
ali@24
  1361
	helper->pulse_handler=0;
ali@24
  1362
    }
ali@24
  1363
    if (helper->error_dialog)
ali@24
  1364
    {
ali@24
  1365
	gtk_widget_destroy(helper->error_dialog);
ali@24
  1366
	helper->error_dialog=NULL;
ali@24
  1367
    }
ali@24
  1368
    g_free(helper->error_primary_text);
ali@24
  1369
    helper->error_primary_text=g_strdup(primary_text);
ali@24
  1370
    g_clear_error(&helper->error);
ali@24
  1371
    helper->error=g_error_copy(error);
ali@24
  1372
    if (g_error_matches(error,PLOVER_GENERAL_ERROR,
ali@24
  1373
      PLOVER_GENERAL_ERROR_NO_WORK))
ali@24
  1374
	type=GTK_MESSAGE_INFO;
ali@24
  1375
    else
ali@24
  1376
	type=GTK_MESSAGE_ERROR;
ali@24
  1377
    if (helper->assistant)
ali@24
  1378
	window=GTK_WINDOW(helper->assistant);
ali@24
  1379
    else
ali@24
  1380
    	window=NULL;
ali@24
  1381
    helper->error_dialog=gtk_message_dialog_new(window,
ali@24
  1382
      GTK_DIALOG_DESTROY_WITH_PARENT,type,GTK_BUTTONS_CLOSE,primary_text);
ali@24
  1383
    gtk_message_dialog_format_secondary_text(
ali@24
  1384
      GTK_MESSAGE_DIALOG(helper->error_dialog),error->message);
ali@24
  1385
    gtk_widget_show(helper->error_dialog);
ali@24
  1386
    g_signal_connect(helper->error_dialog,"response",
ali@24
  1387
      G_CALLBACK(plover_transaction_helper_error_dialog_response),helper);
ali@24
  1388
}