/** * hif_state_child_percentage_changed_cb: **/ static void hif_state_child_percentage_changed_cb(HifState *child, guint percentage, HifState *state) { HifStatePrivate *priv = GET_PRIVATE(state); gfloat offset; gfloat range; gfloat extra; guint parent_percentage; /* propagate up the stack if HifState has only one step */ if (priv->steps == 1) { hif_state_set_percentage(state, percentage); return; } /* did we call done on a state that did not have a size set? */ if (priv->steps == 0) return; /* already at >= 100% */ if (priv->current >= priv->steps) { g_warning("already at %i/%i steps on %p", priv->current, priv->steps, state); return; } /* we have to deal with non-linear steps */ if (priv->step_data != NULL) { /* we don't store zero */ if (priv->current == 0) { parent_percentage = percentage * priv->step_data[priv->current] / 100; } else { /* bilinearly interpolate for speed */ parent_percentage =(((100 - percentage) * priv->step_data[priv->current-1]) + (percentage * priv->step_data[priv->current])) / 100; } goto out; } /* get the offset */ offset = hif_state_discrete_to_percent(priv->current, priv->steps); /* get the range between the parent step and the next parent step */ range = hif_state_discrete_to_percent(priv->current+1, priv->steps) - offset; if (range < 0.01) { g_warning("range=%f(from %i to %i), should be impossible", range, priv->current+1, priv->steps); return; } /* restore the pre-child action */ if (percentage == 100) priv->last_action = priv->child_action; /* get the extra contributed by the child */ extra =((gfloat) percentage / 100.0f) * range; /* emit from the parent */ parent_percentage =(guint)(offset + extra); out: hif_state_set_percentage(state, parent_percentage); }
/** * hif_state_done_real: **/ gboolean hif_state_done_real (HifState *state, GError **error, const gchar *strloc) { gboolean ret; gdouble elapsed; gfloat percentage; g_return_val_if_fail (state != NULL, FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); /* check */ ret = hif_state_check (state, error); if (!ret) goto out; /* do we care */ if (!state->priv->report_progress) goto out; /* did we call done on a state that did not have a size set? */ if (state->priv->steps == 0) { g_set_error (error, HIF_ERROR, PK_ERROR_ENUM_INTERNAL_ERROR, "done on a state %p that did not have a size set! [%s]", state, strloc); hif_state_print_parent_chain (state, 0); ret = FALSE; goto out; } /* check the interval was too big in allow_cancel false mode */ if (state->priv->enable_profile) { elapsed = g_timer_elapsed (state->priv->timer, NULL); if (!state->priv->allow_cancel_changed_state && state->priv->current > 0) { if (elapsed > 0.1f) { g_warning ("%.1fms between hif_state_done() and no hif_state_set_allow_cancel()", elapsed * 1000); hif_state_print_parent_chain (state, 0); } } /* save the duration in the array */ if (state->priv->step_profile != NULL) state->priv->step_profile[state->priv->current] = elapsed; g_timer_start (state->priv->timer); } /* is already at 100%? */ if (state->priv->current >= state->priv->steps) { g_set_error (error, HIF_ERROR, PK_ERROR_ENUM_INTERNAL_ERROR, "already at 100%% state [%s]", strloc); hif_state_print_parent_chain (state, 0); ret = FALSE; goto out; } /* is child not at 100%? */ if (state->priv->child != NULL) { HifStatePrivate *child_priv = state->priv->child->priv; if (child_priv->current != child_priv->steps) { g_print ("child is at %i/%i steps and parent done [%s]\n", child_priv->current, child_priv->steps, strloc); hif_state_print_parent_chain (state->priv->child, 0); ret = TRUE; /* do not abort, as we want to clean this up */ } } /* we just checked for cancel, so it's not true to say we're blocking */ hif_state_set_allow_cancel (state, TRUE); /* another */ state->priv->current++; /* find new percentage */ if (state->priv->step_data == NULL) { percentage = hif_state_discrete_to_percent (state->priv->current, state->priv->steps); } else { /* this is cumalative, for speedy access */ percentage = state->priv->step_data[state->priv->current - 1]; } hif_state_set_percentage (state, (guint) percentage); /* show any profiling stats */ if (state->priv->enable_profile && state->priv->current == state->priv->steps && state->priv->step_profile != NULL) { hif_state_show_profile (state); } /* reset child if it exists */ if (state->priv->child != NULL) hif_state_reset (state->priv->child); out: return ret; }