/** * operation: The operation to process * message: The message that will be pushed to the status bar * fract: The fraction of the progress bar to fill * swidget: The SeahorseWidget to extract the gtk widgets from * * This gets called whenever an operation updates it's progress status thingy. * We update the appbar as appropriate. If operation != NULL then we only * display the latest operation in our special list * **/ static void operation_progress (SeahorseOperation *operation, const gchar *message, gdouble fract, SeahorseWidget *swidget) { GtkProgressBar *progress; GtkStatusbar *status; guint id; progress = GTK_PROGRESS_BAR (seahorse_widget_get_widget (swidget, "progress")); status = GTK_STATUSBAR (seahorse_widget_get_widget (swidget, "status")); if (!seahorse_operation_is_running (operation)) fract = 0.0; if (message != NULL && status) { g_return_if_fail (GTK_IS_STATUSBAR (status)); id = gtk_statusbar_get_context_id (status, "operation-progress"); gtk_statusbar_pop (status, id); if (message[0]) gtk_statusbar_push (status, id, message); } if(progress) { g_return_if_fail (GTK_IS_PROGRESS_BAR (progress)); if (fract >= 0.0) { stop_pulse (progress); gtk_progress_bar_set_fraction (progress, fract); } else { start_pulse (progress); } } }
static int progress_main (int argc, char* argv[]) { SeahorseOperation *op; GIOChannel *io; gtk_init (&argc, &argv); op = g_object_new (SEAHORSE_TYPE_OPERATION, NULL); seahorse_operation_mark_start (op); /* Watch for done (ie: in this case only cancel) */ g_signal_connect (op, "done", G_CALLBACK (done_handler), NULL); /* Hook up an IO channel to stdin */ io = g_io_channel_unix_new (0); g_io_channel_set_encoding (io, NULL, NULL); g_io_add_watch (io, G_IO_IN | G_IO_HUP, (GIOFunc)io_handler, op); progress_visible = FALSE; progress_title = argc > 2 ? argv[2] : NULL; g_timeout_add (PROGRESS_DELAY, (GSourceFunc)progress_show, op); gtk_main (); if (seahorse_operation_is_running (op)) seahorse_operation_mark_done (op, FALSE, NULL); return 0; }
/* dispose of all our internal references */ static void seahorse_server_source_dispose (GObject *gobject) { SeahorseServerSource *ssrc; SeahorseSource *sksrc; /* * Note that after this executes the rest of the object should * still work without a segfault. This basically nullifies the * object, but doesn't free it. * * This function should also be able to run multiple times. */ ssrc = SEAHORSE_SERVER_SOURCE (gobject); sksrc = SEAHORSE_SOURCE (gobject); g_assert (ssrc->priv); /* Clear out all the operations */ if (ssrc->priv->mop) { if(seahorse_operation_is_running (SEAHORSE_OPERATION (ssrc->priv->mop))) seahorse_operation_cancel (SEAHORSE_OPERATION (ssrc->priv->mop)); g_object_unref (ssrc->priv->mop); ssrc->priv->mop = NULL; } G_OBJECT_CLASS (parent_class)->dispose (gobject); }
/** * operation: The operation to create a new progress window for * * Creates a new progress window and adds the operation to it. * * Returns FALSE **/ static gboolean progress_show (SeahorseOperation *operation) { SeahorseWidget *swidget; GtkWidget *w; const gchar *title; gchar *t; if (!seahorse_operation_is_running (operation)) { /* Matches the ref in seahorse_progress_show */ g_object_unref (operation); return FALSE; } swidget = seahorse_widget_new_allow_multiple ("progress", NULL); g_return_val_if_fail (swidget != NULL, FALSE); /* Release our reference on the operation when this window is destroyed */ g_object_set_data_full (G_OBJECT (swidget), "operation", operation, (GDestroyNotify)g_object_unref); w = GTK_WIDGET (seahorse_widget_get_widget (swidget, swidget->name)); gtk_window_move (GTK_WINDOW (w), 10, 10); /* Setup the title */ title = (const gchar*)g_object_get_data (G_OBJECT (operation), "progress-title"); if (title) { /* The window title */ w = GTK_WIDGET (seahorse_widget_get_widget (swidget, swidget->name)); g_return_val_if_fail (w != NULL, FALSE); gtk_window_set_title (GTK_WINDOW (w), title); /* The main message title */ w = GTK_WIDGET (seahorse_widget_get_widget (swidget, "operation-title")); g_return_val_if_fail (w != NULL, FALSE); t = g_strdup_printf ("<b>%s</b>", title); gtk_label_set_markup (GTK_LABEL (w), t); g_free (t); } /* The details */ progress_operation_update (operation, NULL, seahorse_operation_get_progress (operation), swidget); g_signal_connect (operation, "progress", G_CALLBACK (progress_operation_update), swidget); /* Cancel events */ g_signal_connect (seahorse_widget_get_toplevel (swidget), "delete_event", G_CALLBACK (progress_delete_event), operation); /* Done and cleanup */ w = GTK_WIDGET (seahorse_widget_get_widget (swidget, swidget->name)); g_signal_connect (w, "destroy", G_CALLBACK (progress_destroy), operation); g_signal_connect (operation, "done", G_CALLBACK (progress_operation_done), swidget); return FALSE; }
/** * seahorse_progress_status_set_operation: * @swidget: The SeahorseWidget to add the operation to * @operation: The operation to add * * Adds the operation to the widget. * */ void seahorse_progress_status_set_operation (SeahorseWidget *swidget, SeahorseOperation *operation) { SeahorseOperation *prev; /* * Note that this is not one off, the operation is monitored until it is * replaced, so if the operation starts up again the progress will be * displayed */ g_return_if_fail (SEAHORSE_IS_WIDGET (swidget)); g_return_if_fail (SEAHORSE_IS_OPERATION (operation)); prev = SEAHORSE_OPERATION (g_object_get_data (G_OBJECT (swidget), "operation")); if (prev) { /* If it's the same operation, just ignore */ if (prev == operation) return; /* If the previous one was a multi operation, just piggy back this one in */ if (SEAHORSE_IS_MULTI_OPERATION (prev)) { g_object_ref (operation); seahorse_multi_operation_take (SEAHORSE_MULTI_OPERATION (prev), operation); return; } /* Otherwise disconnect old progress, replace with new */ disconnect_progress (swidget, prev); } g_object_ref (operation); g_object_set_data_full (G_OBJECT (swidget), "operation", operation, (GDestroyNotify)g_object_unref); g_signal_connect (swidget, "destroy", G_CALLBACK (disconnect_progress), operation); if (!seahorse_operation_is_running (operation)) operation_done (operation, swidget); operation_progress (operation, seahorse_operation_get_message (operation), seahorse_operation_get_progress (operation), swidget); g_signal_connect (operation, "done", G_CALLBACK (operation_done), swidget); g_signal_connect (operation, "progress", G_CALLBACK (operation_progress), swidget); }
static void seahorse_hkp_operation_cancel (SeahorseOperation *operation) { SeahorseHKPOperation *hop; g_assert (SEAHORSE_IS_HKP_OPERATION (operation)); hop = SEAHORSE_HKP_OPERATION (operation); g_return_if_fail (seahorse_operation_is_running (operation)); hop->cancelling = TRUE; if (hop->session != NULL) soup_session_abort (hop->session); seahorse_operation_mark_done (operation, TRUE, NULL); }
/* Cancels operation and marks the HKP operation as failed */ static void fail_hkp_operation (SeahorseHKPOperation *hop, SoupMessage *msg, const gchar *text) { gchar *t, *server; GError *error = NULL; if (!seahorse_operation_is_running (SEAHORSE_OPERATION (hop))) return; g_object_get (hop->hsrc, "key-server", &server, NULL); if (text) { error = g_error_new (HKP_ERROR_DOMAIN, msg ? msg->status_code : 0, "%s", text); } else if (msg) { /* Make the body lower case, and no tags */ t = g_strndup (msg->response_body->data, msg->response_body->length); if (t != NULL) { dehtmlize (t); seahorse_util_string_lower (t); } if (t && strstr (t, "no keys")) error = NULL; /* not found is not an error */ else if (t && strstr (t, "too many")) error = g_error_new (HKP_ERROR_DOMAIN, 0, _("Search was not specific enough. Server '%s' found too many keys."), server); else error = g_error_new (HKP_ERROR_DOMAIN, msg->status_code, _("Couldn't communicate with server '%s': %s"), server, msg->reason_phrase); g_free (t); } else { /* We should always have msg or text */ g_assert (FALSE); } seahorse_operation_mark_done (SEAHORSE_OPERATION (hop), FALSE, error); g_free (server); }
static gboolean step_operation (FilesCtx *ctx, SeahorseToolMode *mode, GError **err) { SeahorsePGPOperation *pop = NULL; gpgme_data_t data = NULL; gboolean ret = FALSE; SeahorseOperation *op; FileInfo *finfo; GList *l; gchar *filename; /* Reset our done counter */ ctx->done = 0; for (l = ctx->finfos; l; l = g_list_next (l)) { finfo = (FileInfo*)l->data; if (!finfo || !finfo->file) continue; ctx->cur = finfo; /* A new operation for each context */ pop = seahorse_pgp_operation_new (NULL); op = SEAHORSE_OPERATION (pop); data = seahorse_vfs_data_create_full (finfo->file, SEAHORSE_VFS_READ, (SeahorseVfsProgressCb)progress_cb, ctx, err); if (!data) goto finally; /* Inhibit popping up of progress dialog */ seahorse_tool_progress_block (TRUE); /* Embed filename during encryption */ if (mode_encrypt) { filename = g_file_get_basename (finfo->file); gpgme_data_set_file_name (data, filename); g_free (filename); } /* The start callback */ if (mode->startcb) { if (!(mode->startcb) (mode, finfo->uri, data, pop, err)) goto finally; } /* Let progress dialog pop up */ seahorse_tool_progress_block (FALSE); /* Run until the operation completes */ seahorse_util_wait_until ((!seahorse_operation_is_running (op) || !seahorse_tool_progress_check ())); /* If cancel then reflect that */ if (seahorse_operation_is_running (op)) { seahorse_operation_cancel (op); goto finally; } if (!seahorse_operation_is_successful (op)) { seahorse_operation_copy_error (op, err); goto finally; } /* The done callback */ if (mode->donecb) { if (!(mode->donecb) (mode, finfo->uri, data, pop, err)) goto finally; } ctx->done += g_file_info_get_size (finfo->info); ctx->cur = NULL; g_object_unref (pop); pop = NULL; gpgme_data_release (data); data = NULL; } seahorse_tool_progress_update (1.0, ""); ret = TRUE; finally: if (pop) g_object_unref (pop); if (data) gpgme_data_release (data); return ret; }
/** * on_progress_operation_cancel: * @button: ignored * @operation: The operation to cancel * * Cancels an operation * */ G_MODULE_EXPORT void on_progress_operation_cancel (GtkButton *button, SeahorseOperation *operation) { if (seahorse_operation_is_running (operation)) seahorse_operation_cancel (operation); }