Skip to content

Commit

Permalink
Collect dt_control_log() and dt_toast_log() messages
Browse files Browse the repository at this point in the history
Visibility of messges shown via dt_control_log(), dt_toast_log() and dt_toast_markup_log() is currently
pretty bad as only the last shown message is shown if new ones are "pushed".

This commit redesigns both buffers to be used as circular buffers, a new call to any function above
will not display the last text but all available and not-yet ackknowledged (or disappered) messages
for improved user readability.
  • Loading branch information
jenshannoschwalm committed Jul 19, 2024
1 parent 517889e commit 21577e9
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 25 deletions.
31 changes: 17 additions & 14 deletions src/control/control.c
Original file line number Diff line number Diff line change
Expand Up @@ -549,8 +549,7 @@ void dt_ctl_switch_mode()
static gboolean _dt_ctl_log_message_timeout_callback(gpointer data)
{
dt_pthread_mutex_lock(&darktable.control->log_mutex);
if(darktable.control->log_ack != darktable.control->log_pos)
darktable.control->log_ack = (darktable.control->log_ack + 1) % DT_CTL_LOG_SIZE;
darktable.control->log_ack = darktable.control->log_pos;
darktable.control->log_message_timeout_id = 0;
dt_pthread_mutex_unlock(&darktable.control->log_mutex);
dt_control_log_redraw();
Expand All @@ -560,8 +559,7 @@ static gboolean _dt_ctl_log_message_timeout_callback(gpointer data)
static gboolean _dt_ctl_toast_message_timeout_callback(gpointer data)
{
dt_pthread_mutex_lock(&darktable.control->toast_mutex);
if(darktable.control->toast_ack != darktable.control->toast_pos)
darktable.control->toast_ack = (darktable.control->toast_ack + 1) % DT_CTL_TOAST_SIZE;
darktable.control->toast_ack = darktable.control->toast_pos;
darktable.control->toast_message_timeout_id = 0;
dt_pthread_mutex_unlock(&darktable.control->toast_mutex);
dt_control_toast_redraw();
Expand Down Expand Up @@ -589,33 +587,37 @@ void dt_control_button_pressed(double x,
dt_pthread_mutex_lock(&darktable.control->log_mutex);
const double /*xc = wd/4.0-20,*/ yc = ht * 0.85 + 10.0;
if(darktable.control->log_ack != darktable.control->log_pos)
{
if(which == 1 /*&& x > xc - 10 && x < xc + 10*/ && y > yc - 10.0 && y < yc + 10.0)
{
if(darktable.control->log_message_timeout_id)
{
g_source_remove(darktable.control->log_message_timeout_id);
darktable.control->log_message_timeout_id = 0;
}
darktable.control->log_ack = (darktable.control->log_ack + 1) % DT_CTL_LOG_SIZE;
darktable.control->log_ack = darktable.control->log_pos;
dt_pthread_mutex_unlock(&darktable.control->log_mutex);
return;
}
}
dt_pthread_mutex_unlock(&darktable.control->log_mutex);

// ack toast message:
dt_pthread_mutex_lock(&darktable.control->toast_mutex);
if(darktable.control->toast_ack != darktable.control->toast_pos)
{
if(which == 1 /*&& x > xc - 10 && x < xc + 10*/ && y > yc - 10.0 && y < yc + 10.0)
{
if(darktable.control->toast_message_timeout_id)
{
g_source_remove(darktable.control->toast_message_timeout_id);
darktable.control->toast_message_timeout_id = 0;
}
darktable.control->toast_ack = (darktable.control->toast_ack + 1) % DT_CTL_TOAST_SIZE;
darktable.control->toast_ack = darktable.control->toast_pos;
dt_pthread_mutex_unlock(&darktable.control->toast_mutex);
return;
}
}
dt_pthread_mutex_unlock(&darktable.control->toast_mutex);

if(!dt_view_manager_button_pressed(darktable.view_manager, x, y,
Expand All @@ -637,14 +639,15 @@ void dt_control_log(const char *msg, ...)
va_start(ap, msg);
char *escaped_msg = g_markup_vprintf_escaped(msg, ap);
const int msglen = strlen(escaped_msg);
g_strlcpy(darktable.control->log_message[darktable.control->log_pos],
g_strlcpy(darktable.control->log_message[darktable.control->log_pos % DT_CTL_LOG_SIZE],
escaped_msg, DT_CTL_LOG_MSG_SIZE);
g_free(escaped_msg);
va_end(ap);

darktable.control->log_pos++;

if(darktable.control->log_message_timeout_id)
g_source_remove(darktable.control->log_message_timeout_id);
darktable.control->log_ack = darktable.control->log_pos;
darktable.control->log_pos = (darktable.control->log_pos + 1) % DT_CTL_LOG_SIZE;

darktable.control->log_message_timeout_id
= g_timeout_add(DT_CTL_LOG_TIMEOUT + 1000 * (msglen / 40),
Expand All @@ -660,20 +663,20 @@ static void _toast_log(const gboolean markup, const char *msg, va_list ap)

// if we don't want markup, we escape <>&... so they are not interpreted later
if(markup)
vsnprintf(darktable.control->toast_message[darktable.control->toast_pos],
vsnprintf(darktable.control->toast_message[darktable.control->toast_pos % DT_CTL_TOAST_SIZE],
DT_CTL_TOAST_MSG_SIZE, msg, ap);
else
{
char *escaped_msg = g_markup_vprintf_escaped(msg, ap);
g_strlcpy(darktable.control->toast_message[darktable.control->toast_pos],
g_strlcpy(darktable.control->toast_message[darktable.control->toast_pos % DT_CTL_TOAST_SIZE],
escaped_msg, DT_CTL_TOAST_MSG_SIZE);
g_free(escaped_msg);
}
darktable.control->toast_pos++;

if(darktable.control->toast_message_timeout_id)
g_source_remove(darktable.control->toast_message_timeout_id);
darktable.control->toast_ack = darktable.control->toast_pos;
darktable.control->toast_pos = (darktable.control->toast_pos + 1) % DT_CTL_TOAST_SIZE;

darktable.control->toast_message_timeout_id
= g_timeout_add(DT_CTL_TOAST_TIMEOUT, _dt_ctl_toast_message_timeout_callback, NULL);
dt_pthread_mutex_unlock(&darktable.control->toast_mutex);
Expand All @@ -700,7 +703,7 @@ void dt_toast_markup_log(const char *msg, ...)
static void _control_log_ack_all()
{
dt_pthread_mutex_lock(&darktable.control->log_mutex);
darktable.control->log_pos = darktable.control->log_ack;
darktable.control->log_ack = darktable.control->log_pos;
dt_pthread_mutex_unlock(&darktable.control->log_mutex);
dt_control_queue_redraw_center();
}
Expand Down
4 changes: 2 additions & 2 deletions src/control/control.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,14 +159,14 @@ typedef struct dt_control_t
gboolean lock_cursor_shape;

// message log
int log_pos, log_ack;
uint32_t log_pos, log_ack;
char log_message[DT_CTL_LOG_SIZE][DT_CTL_LOG_MSG_SIZE];
guint log_message_timeout_id;
int log_busy;
dt_pthread_mutex_t log_mutex;

// toast log
int toast_pos, toast_ack;
uint32_t toast_pos, toast_ack;
char toast_message[DT_CTL_TOAST_SIZE][DT_CTL_TOAST_MSG_SIZE];
guint toast_message_timeout_id;
int toast_busy;
Expand Down
44 changes: 35 additions & 9 deletions src/gui/gtk.c
Original file line number Diff line number Diff line change
Expand Up @@ -2640,17 +2640,30 @@ static void _ui_widget_redraw_callback(gpointer instance,
gtk_widget_queue_draw(widget);
}

#define ALLMESSSIZE (DT_CTL_LOG_SIZE * DT_CTL_LOG_MSG_SIZE)
static void _ui_log_redraw_callback(gpointer instance,
GtkWidget *widget)
{
// draw log message, if any
dt_pthread_mutex_lock(&darktable.control->log_mutex);
if(darktable.control->log_ack != darktable.control->log_pos)
{
if(strcmp(darktable.control->log_message[darktable.control->log_ack],
gtk_label_get_text(GTK_LABEL(widget))))
gtk_label_set_markup
(GTK_LABEL(widget), darktable.control->log_message[darktable.control->log_ack]);
const uint32_t first_message = MAX(darktable.control->log_ack,
darktable.control->log_pos - DT_CTL_LOG_SIZE + 1);
gchar *message = g_malloc(ALLMESSSIZE);
if(message)
{
message[0] = 0;
for(uint32_t idx = first_message; idx < darktable.control->log_pos; idx++)
{
g_strlcat(message, darktable.control->log_message[idx % DT_CTL_LOG_SIZE], ALLMESSSIZE);
if(idx != darktable.control->log_pos -1)
g_strlcat(message, "\n", ALLMESSSIZE);
}
gtk_label_set_markup(GTK_LABEL(widget), message);
g_free(message);
}

if(!gtk_widget_get_visible(widget))
{
const int h = gtk_widget_get_allocated_height(dt_ui_center_base(darktable.gui->ui));
Expand All @@ -2673,10 +2686,22 @@ static void _ui_toast_redraw_callback(gpointer instance,
dt_pthread_mutex_lock(&darktable.control->toast_mutex);
if(darktable.control->toast_ack != darktable.control->toast_pos)
{
if(strcmp(darktable.control->toast_message[darktable.control->toast_ack],
gtk_label_get_text(GTK_LABEL(widget))))
gtk_label_set_markup(GTK_LABEL(widget),
darktable.control->toast_message[darktable.control->toast_ack]);
const uint32_t first_message = MAX(darktable.control->toast_ack,
darktable.control->toast_pos - DT_CTL_TOAST_SIZE + 1);
gchar *message = g_malloc(ALLMESSSIZE);
if(message)
{
message[0] = 0;
for(uint32_t idx = first_message; idx < darktable.control->toast_pos; idx++)
{
g_strlcat(message, darktable.control->toast_message[idx % DT_CTL_TOAST_SIZE], ALLMESSSIZE);
if(idx != darktable.control->toast_pos -1)
g_strlcat(message, "\n", ALLMESSSIZE);
}
gtk_label_set_markup(GTK_LABEL(widget), message);
g_free(message);
}

if(!gtk_widget_get_visible(widget))
{
const int h = gtk_widget_get_allocated_height(dt_ui_center_base(darktable.gui->ui));
Expand All @@ -2691,6 +2716,7 @@ static void _ui_toast_redraw_callback(gpointer instance,
}
dt_pthread_mutex_unlock(&darktable.control->toast_mutex);
}
#undef ALLMESSSIZE

void dt_ellipsize_combo(GtkComboBox *cbox)
{
Expand Down Expand Up @@ -3871,7 +3897,7 @@ GtkWidget *dt_ui_resize_wrap(GtkWidget *w,
const float height = dt_conf_get_int(config_str);
dtgtk_drawing_area_set_height(w, height);
g_signal_connect(G_OBJECT(w),
"scroll-event",
"scroll-event",
G_CALLBACK(_scroll_wrap_height),
config_str);
}
Expand Down

0 comments on commit 21577e9

Please sign in to comment.