mirror of
https://git.proxmox.com/git/fwupd
synced 2025-07-24 14:57:13 +00:00
Fix various printing issues with the progressbar
Specifically, fix the progressbar to: * Print at 100% after an 'unknown' percentage task has completed * Refresh the progressbar if being called without a main loop running * Allow the progressbar to start with a h-offset without moving 'left' * Don't cause high CPU load when calling fu_progressbar_update() ever few us Also, add some unit tests to discover all the issues.
This commit is contained in:
parent
4f98fe89ba
commit
b5b4beb472
@ -38,6 +38,7 @@ struct _FuProgressbar
|
||||
guint percentage;
|
||||
guint to_erase; /* chars */
|
||||
guint timer_id;
|
||||
gint64 last_animated; /* monotonic */
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (FuProgressbar, fu_progressbar, G_TYPE_OBJECT)
|
||||
@ -87,10 +88,11 @@ fu_progressbar_status_to_string (FwupdStatus status)
|
||||
}
|
||||
|
||||
static void
|
||||
fu_progressbar_refresh (FuProgressbar *self)
|
||||
fu_progressbar_refresh (FuProgressbar *self, FwupdStatus status, guint percentage)
|
||||
{
|
||||
const gchar *title;
|
||||
guint i;
|
||||
gboolean is_idle_newline = FALSE;
|
||||
g_autoptr(GString) str = g_string_new (NULL);
|
||||
|
||||
/* erase previous line */
|
||||
@ -98,21 +100,20 @@ fu_progressbar_refresh (FuProgressbar *self)
|
||||
g_print ("\b");
|
||||
|
||||
/* add status */
|
||||
if (self->status == FWUPD_STATUS_IDLE) {
|
||||
if (self->to_erase > 0)
|
||||
g_print ("\n");
|
||||
self->to_erase = 0;
|
||||
return;
|
||||
if (status == FWUPD_STATUS_IDLE) {
|
||||
percentage = 100;
|
||||
status = self->status;
|
||||
is_idle_newline = TRUE;
|
||||
}
|
||||
title = fu_progressbar_status_to_string (self->status);
|
||||
title = fu_progressbar_status_to_string (status);
|
||||
g_string_append (str, title);
|
||||
for (i = str->len; i < self->length_status; i++)
|
||||
g_string_append_c (str, ' ');
|
||||
|
||||
/* add progressbar */
|
||||
g_string_append (str, "[");
|
||||
if (self->percentage > 0) {
|
||||
for (i = 0; i < self->length_percentage * self->percentage / 100; i++)
|
||||
if (percentage > 0) {
|
||||
for (i = 0; i < (self->length_percentage - 1) * percentage / 100; i++)
|
||||
g_string_append_c (str, '*');
|
||||
for (i = i + 1; i < self->length_percentage; i++)
|
||||
g_string_append_c (str, ' ');
|
||||
@ -121,14 +122,37 @@ fu_progressbar_refresh (FuProgressbar *self)
|
||||
for (i = 0; i < self->spinner_idx; i++)
|
||||
g_string_append_c (str, ' ');
|
||||
g_string_append_c (str, chars[i / 4 % G_N_ELEMENTS(chars)]);
|
||||
for (i = i + 1; i < self->length_percentage; i++)
|
||||
for (i = i + 1; i < self->length_percentage - 1; i++)
|
||||
g_string_append_c (str, ' ');
|
||||
}
|
||||
g_string_append_c (str, ']');
|
||||
|
||||
/* dump to screen */
|
||||
g_print ("%s", str->str);
|
||||
self->to_erase = str->len;
|
||||
self->to_erase = str->len - 2;
|
||||
|
||||
/* done */
|
||||
if (is_idle_newline) {
|
||||
g_print ("\n");
|
||||
self->to_erase = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fu_progressbar_spin_inc (FuProgressbar *self)
|
||||
{
|
||||
/* reset */
|
||||
self->last_animated = g_get_monotonic_time ();
|
||||
|
||||
/* up to down */
|
||||
if (self->spinner_count_up) {
|
||||
if (++self->spinner_idx > self->length_percentage - 3)
|
||||
self->spinner_count_up = FALSE;
|
||||
} else {
|
||||
if (--self->spinner_idx == 0)
|
||||
self->spinner_count_up = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -137,16 +161,10 @@ fu_progressbar_spin_cb (gpointer user_data)
|
||||
FuProgressbar *self = FU_PROGRESSBAR (user_data);
|
||||
|
||||
/* move the spinner index up to down */
|
||||
if (self->spinner_count_up) {
|
||||
if (++self->spinner_idx > self->length_percentage - 2)
|
||||
self->spinner_count_up = FALSE;
|
||||
} else {
|
||||
if (--self->spinner_idx == 0)
|
||||
self->spinner_count_up = TRUE;
|
||||
}
|
||||
fu_progressbar_spin_inc (self);
|
||||
|
||||
/* update the terminal */
|
||||
fu_progressbar_refresh (self);
|
||||
fu_progressbar_refresh (self, self->status, self->percentage);
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
@ -177,9 +195,21 @@ fu_progressbar_update (FuProgressbar *self, FwupdStatus status, guint percentage
|
||||
{
|
||||
g_return_if_fail (FU_IS_PROGRESSBAR (self));
|
||||
|
||||
/* cache */
|
||||
self->status = status;
|
||||
self->percentage = percentage;
|
||||
/* if the main loop isn't spinning and we've not had a chance to
|
||||
* execute the callback just do the refresh now manually */
|
||||
if (percentage == 0 &&
|
||||
status != FWUPD_STATUS_IDLE &&
|
||||
self->status != FWUPD_STATUS_UNKNOWN) {
|
||||
if ((g_get_monotonic_time () - self->last_animated) / 1000 > 40) {
|
||||
fu_progressbar_spin_inc (self);
|
||||
fu_progressbar_refresh (self, status, percentage);
|
||||
}
|
||||
}
|
||||
|
||||
/* ignore duplicates */
|
||||
if (self->status == status &&
|
||||
self->percentage == percentage)
|
||||
return;
|
||||
|
||||
/* enable or disable the spinner timeout */
|
||||
if (percentage > 0) {
|
||||
@ -189,7 +219,11 @@ fu_progressbar_update (FuProgressbar *self, FwupdStatus status, guint percentage
|
||||
}
|
||||
|
||||
/* update the terminal */
|
||||
fu_progressbar_refresh (self);
|
||||
fu_progressbar_refresh (self, status, percentage);
|
||||
|
||||
/* cache */
|
||||
self->status = status;
|
||||
self->percentage = percentage;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "fu-keyring.h"
|
||||
#include "fu-pending.h"
|
||||
#include "fu-plugin-private.h"
|
||||
#include "fu-progressbar.h"
|
||||
#include "fu-hwids.h"
|
||||
#include "fu-smbios.h"
|
||||
#include "fu-test.h"
|
||||
@ -735,6 +736,34 @@ fu_common_spawn_func (void)
|
||||
g_assert_cmpint (lines, ==, 6);
|
||||
}
|
||||
|
||||
static void
|
||||
fu_progressbar_func (void)
|
||||
{
|
||||
g_autoptr(FuProgressbar) progressbar = fu_progressbar_new ();
|
||||
|
||||
fu_progressbar_set_length_status (progressbar, 20);
|
||||
fu_progressbar_set_length_percentage (progressbar, 50);
|
||||
|
||||
g_print ("\n");
|
||||
for (guint i = 0; i < 100; i++) {
|
||||
fu_progressbar_update (progressbar, FWUPD_STATUS_DECOMPRESSING, i);
|
||||
g_usleep (10000);
|
||||
}
|
||||
fu_progressbar_update (progressbar, FWUPD_STATUS_IDLE, 0);
|
||||
for (guint i = 0; i < 100; i++) {
|
||||
guint pc = (i > 25 && i < 75) ? 0 : i;
|
||||
fu_progressbar_update (progressbar, FWUPD_STATUS_LOADING, pc);
|
||||
g_usleep (10000);
|
||||
}
|
||||
fu_progressbar_update (progressbar, FWUPD_STATUS_IDLE, 0);
|
||||
|
||||
for (guint i = 0; i < 5000; i++) {
|
||||
fu_progressbar_update (progressbar, FWUPD_STATUS_LOADING, 0);
|
||||
g_usleep (1000);
|
||||
}
|
||||
fu_progressbar_update (progressbar, FWUPD_STATUS_IDLE, 0);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
@ -747,6 +776,8 @@ main (int argc, char **argv)
|
||||
g_assert_cmpint (g_mkdir_with_parents ("/tmp/fwupd-self-test/var/lib/fwupd", 0755), ==, 0);
|
||||
|
||||
/* tests go here */
|
||||
if (g_test_slow ())
|
||||
g_test_add_func ("/fwupd/progressbar", fu_progressbar_func);
|
||||
g_test_add_func ("/fwupd/device-locker{success}", fu_device_locker_func);
|
||||
g_test_add_func ("/fwupd/device-locker{fail}", fu_device_locker_fail_func);
|
||||
g_test_add_func ("/fwupd/device{metadata}", fu_device_metadata_func);
|
||||
|
@ -166,6 +166,7 @@ if get_option('enable-tests')
|
||||
'fu-keyring.c',
|
||||
'fu-keyring-result.c',
|
||||
'fu-plugin.c',
|
||||
'fu-progressbar.c',
|
||||
'fu-smbios.c',
|
||||
'fu-test.c',
|
||||
],
|
||||
|
Loading…
Reference in New Issue
Block a user