[gimp] app: various GimpDashboard improvements
- From: N/A <ell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] app: various GimpDashboard improvements
- Date: Sat, 30 Dec 2017 18:58:00 +0000 (UTC)
commit ee4181916573ce71c2747c64957352e3e219c90e
Author: Ell <ell_se yahoo com>
Date: Sat Dec 30 13:43:09 2017 -0500
app: various GimpDashboard improvements
Refactor GimpDashboard to autogenerate the UI based on a
description of the different variables, fields, and groups.
Allow individual groups to be expanded/collapsed, and individual
fields to be enabled/disabled. Save the relevant state in the
dashboard's aux-info.
Add fields for the new GeglStats properties, as per GEGL commit
25c39ce6c9bb618f06ac96d118e624be66464d74. The new fields are not
enabled by default.
Add "reset" action, to clear the history, and reset cumulative
data.
app/actions/dashboard-actions.c | 14 +-
app/actions/dashboard-commands.c | 9 +
app/actions/dashboard-commands.h | 3 +
app/widgets/gimpdashboard.c | 2040 ++++++++++++++++++++++++++++++--------
app/widgets/gimpdashboard.h | 53 +-
app/widgets/gimphelp-ids.h | 1 +
menus/dashboard-menu.xml | 1 +
7 files changed, 1652 insertions(+), 469 deletions(-)
---
diff --git a/app/actions/dashboard-actions.c b/app/actions/dashboard-actions.c
index 6acf18c..9ed2f4b 100644
--- a/app/actions/dashboard-actions.c
+++ b/app/actions/dashboard-actions.c
@@ -43,7 +43,13 @@ static const GimpActionEntry dashboard_actions[] =
{ "dashboard-update-interval", NULL,
NC_("dashboard-action", "Update Interval") },
{ "dashboard-history-duration", NULL,
- NC_("dashboard-action", "History Duration") }
+ NC_("dashboard-action", "History Duration") },
+
+ { "dashboard-reset", GIMP_ICON_RESET,
+ NC_("dashboard-action", "Reset"), NULL,
+ NC_("dashboard-action", "Reset cumulative data"),
+ G_CALLBACK (dashboard_reset_cmd_callback),
+ GIMP_HELP_DASHBOARD_RESET },
};
static const GimpToggleActionEntry dashboard_toggle_actions[] =
@@ -149,7 +155,7 @@ dashboard_actions_update (GimpActionGroup *group,
#define SET_ACTIVE(action,condition) \
gimp_action_group_set_action_active (group, action, (condition) != 0)
- switch (dashboard->update_interval)
+ switch (gimp_dashboard_get_update_interval (dashboard))
{
case GIMP_DASHBOARD_UPDATE_INTERVAL_0_25_SEC:
SET_ACTIVE ("dashboard-update-interval-0-25-sec", TRUE);
@@ -168,7 +174,7 @@ dashboard_actions_update (GimpActionGroup *group,
break;
}
- switch (dashboard->history_duration)
+ switch (gimp_dashboard_get_history_duration (dashboard))
{
case GIMP_DASHBOARD_HISTORY_DURATION_15_SEC:
SET_ACTIVE ("dashboard-history-duration-15-sec", TRUE);
@@ -188,7 +194,7 @@ dashboard_actions_update (GimpActionGroup *group,
}
SET_ACTIVE ("dashboard-low-swap-space-warning",
- dashboard->low_swap_space_warning);
+ gimp_dashboard_get_low_swap_space_warning (dashboard));
#undef SET_ACTIVE
}
diff --git a/app/actions/dashboard-commands.c b/app/actions/dashboard-commands.c
index c7b110b..2259490 100644
--- a/app/actions/dashboard-commands.c
+++ b/app/actions/dashboard-commands.c
@@ -62,6 +62,15 @@ dashboard_history_duration_cmd_callback (GtkAction *action,
}
void
+dashboard_reset_cmd_callback (GtkAction *action,
+ gpointer data)
+{
+ GimpDashboard *dashboard = GIMP_DASHBOARD (data);
+
+ gimp_dashboard_reset (dashboard);
+}
+
+void
dashboard_low_swap_space_warning_cmd_callback (GtkAction *action,
gpointer data)
{
diff --git a/app/actions/dashboard-commands.h b/app/actions/dashboard-commands.h
index 4314a14..2151238 100644
--- a/app/actions/dashboard-commands.h
+++ b/app/actions/dashboard-commands.h
@@ -26,6 +26,9 @@ void dashboard_history_duration_cmd_callback (GtkAction *action,
GtkAction *current,
gpointer data);
+void dashboard_reset_cmd_callback (GtkAction *action,
+ gpointer data);
+
void dashboard_low_swap_space_warning_cmd_callback (GtkAction *action,
gpointer data);
diff --git a/app/widgets/gimpdashboard.c b/app/widgets/gimpdashboard.c
index 37793f9..7f085a3 100644
--- a/app/widgets/gimpdashboard.c
+++ b/app/widgets/gimpdashboard.c
@@ -37,8 +37,10 @@
#include "gimpdocked.h"
#include "gimpdashboard.h"
#include "gimpdialogfactory.h"
+#include "gimphelp-ids.h"
#include "gimpmeter.h"
#include "gimpsessioninfo-aux.h"
+#include "gimpwidgets-utils.h"
#include "gimpwindowstrategy.h"
#include "gimp-intl.h"
@@ -51,35 +53,384 @@
#define LOW_SWAP_SPACE_WARNING_ON /* swap occupied is above */ 0.90 /* of swap limit */
#define LOW_SWAP_SPACE_WARNING_OFF /* swap occupied is below */ 0.85 /* of swap limit */
-#define CACHE_OCCUPIED_COLOR {0.3, 0.6, 0.3, 1.0}
-#define SWAP_OCCUPIED_COLOR {0.8, 0.2, 0.2, 1.0}
-#define SWAP_SIZE_COLOR {0.8, 0.6, 0.4, 1.0}
-#define SWAP_LED_COLOR {0.8, 0.4, 0.4, 1.0}
+
+typedef enum
+{
+ VARIABLE_NONE,
+ FIRST_VARIABLE,
+
+
+ /* cache */
+ VARIABLE_CACHE_OCCUPIED = FIRST_VARIABLE,
+ VARIABLE_CACHE_MAXIMUM,
+ VARIABLE_CACHE_LIMIT,
+
+ VARIABLE_CACHE_COMPRESSION,
+ VARIABLE_CACHE_HIT_MISS,
+
+ /* swap */
+ VARIABLE_SWAP_OCCUPIED,
+ VARIABLE_SWAP_SIZE,
+ VARIABLE_SWAP_LIMIT,
+
+ VARIABLE_SWAP_BUSY,
+
+
+ N_VARIABLES,
+
+ VARIABLE_SEPARATOR
+} Variable;
+
+typedef enum
+{
+ VARIABLE_TYPE_BOOLEAN,
+ VARIABLE_TYPE_SIZE,
+ VARIABLE_TYPE_SIZE_RATIO,
+ VARIABLE_TYPE_INT_RATIO
+} VariableType;
+
+typedef enum
+{
+ FIRST_GROUP,
+
+ GROUP_CACHE = FIRST_GROUP,
+ GROUP_SWAP,
+
+ N_GROUPS
+} Group;
+
+
+typedef struct _VariableInfo VariableInfo;
+typedef struct _FieldInfo FieldInfo;
+typedef struct _GroupInfo GroupInfo;
+typedef struct _VariableData VariableData;
+typedef struct _FieldData FieldData;
+typedef struct _GroupData GroupData;
+
+typedef void (* VariableSampleFunc) (GimpDashboard *dashboard,
+ Variable variable);
+
+
+struct _VariableInfo
+{
+ const gchar *name;
+ const gchar *title;
+ const gchar *description;
+ VariableType type;
+ GimpRGB color;
+ VariableSampleFunc sample_func;
+ gpointer data;
+};
+
+struct _FieldInfo
+{
+ Variable variable;
+ gboolean default_active;
+ gboolean meter_value;
+};
+
+struct _GroupInfo
+{
+ const gchar *name;
+ const gchar *title;
+ const gchar *description;
+ gboolean default_expanded;
+ gboolean has_meter;
+ Variable meter_limit;
+ Variable meter_led;
+ const FieldInfo *fields;
+};
+
+struct _VariableData
+{
+ gboolean available;
+
+ union
+ {
+ gboolean boolean;
+ guint64 size;
+ struct
+ {
+ guint64 antecedent;
+ guint64 consequent;
+ } size_ratio;
+ struct
+ {
+ gint antecedent;
+ gint consequent;
+ } int_ratio;
+ } value;
+};
+
+struct _FieldData
+{
+ gboolean active;
+
+ GtkCheckMenuItem *menu_item;
+ GtkLabel *value_label;
+};
+
+struct _GroupData
+{
+ gint n_fields;
+ gint n_meter_values;
+
+ GtkExpander *expander;
+ GtkButton *menu_button;
+ GtkMenu *menu;
+ GimpMeter *meter;
+ GtkTable *table;
+
+ FieldData *fields;
+};
+
+struct _GimpDashboardPrivate
+{
+ Gimp *gimp;
+
+ VariableData variables[N_VARIABLES];
+ GroupData groups[N_GROUPS];
+
+ GThread *thread;
+ GMutex mutex;
+ GCond cond;
+ gboolean quit;
+ gboolean update_now;
+
+ gint update_idle_id;
+ gint low_swap_space_idle_id;
+
+ GimpDashboardUpdateInteval update_interval;
+ GimpDashboardHistoryDuration history_duration;
+ gboolean low_swap_space_warning;
+};
-static void gimp_dashboard_docked_iface_init (GimpDockedInterface *iface);
+/* local function prototypes */
-static void gimp_dashboard_dispose (GObject *object);
-static void gimp_dashboard_finalize (GObject *object);
+static void gimp_dashboard_docked_iface_init (GimpDockedInterface *iface);
-static void gimp_dashboard_map (GtkWidget *widget);
-static void gimp_dashboard_unmap (GtkWidget *widget);
+static void gimp_dashboard_constructed (GObject *object);
+static void gimp_dashboard_dispose (GObject *object);
+static void gimp_dashboard_finalize (GObject *object);
-static void gimp_dashboard_set_aux_info (GimpDocked *docked,
- GList *aux_info);
-static GList * gimp_dashboard_get_aux_info (GimpDocked *docked);
+static void gimp_dashboard_map (GtkWidget *widget);
+static void gimp_dashboard_unmap (GtkWidget *widget);
-static gboolean gimp_dashboard_update (GimpDashboard *dashboard);
-static gboolean gimp_dashboard_low_swap_space (GimpDashboard *dashboard);
-static gpointer gimp_dashboard_sample (GimpDashboard *dashboard);
+static void gimp_dashboard_set_aux_info (GimpDocked *docked,
+ GList *aux_info);
+static GList * gimp_dashboard_get_aux_info (GimpDocked *docked);
-static void gimp_dashboard_label_set_text (GtkLabel *label,
- const gchar *text);
-static void gimp_dashboard_label_set_size (GtkLabel *label,
- guint64 size,
- guint64 limit);
+static gboolean gimp_dashboard_group_expander_button_press (GimpDashboard *dashboard,
+ GdkEventButton *bevent,
+ GtkWidget *widget);
-static guint64 gimp_dashboard_get_swap_limit (guint64 swap_size);
+static void gimp_dashboard_group_menu_item_toggled (GimpDashboard *dashboard,
+ GtkCheckMenuItem *item);
+
+static gpointer gimp_dashboard_sample (GimpDashboard *dashboard);
+
+static gboolean gimp_dashboard_update (GimpDashboard *dashboard);
+static gboolean gimp_dashboard_low_swap_space (GimpDashboard *dashboard);
+
+static void gimp_dashboard_sample_gegl_config (GimpDashboard *dashboard,
+ Variable variable);
+static void gimp_dashboard_sample_gegl_stats (GimpDashboard *dashboard,
+ Variable variable);
+static void gimp_dashboard_sample_swap_limit (GimpDashboard *dashboard,
+ Variable variable);
+
+static void gimp_dashboard_sample_object (GimpDashboard *dashboard,
+ GObject *object,
+ Variable variable);
+
+static void gimp_dashboard_container_remove (GtkWidget *widget,
+ GtkContainer *container);
+
+static void gimp_dashboard_group_menu_position (GtkMenu *menu,
+ gint *x,
+ gint *y,
+ gboolean *push_in,
+ gpointer user_data);
+
+static void gimp_dashboard_update_groups (GimpDashboard *dashboard);
+static void gimp_dashboard_update_group (GimpDashboard *dashboard,
+ Group group);
+static void gimp_dashboard_update_group_values (GimpDashboard *dashboard,
+ Group group);
+
+static void gimp_dashboard_field_set_active (GimpDashboard *dashboard,
+ Group group,
+ gint field,
+ gboolean active);
+
+static gboolean gimp_dashboard_variable_to_boolean (GimpDashboard *dashboard,
+ Variable variable);
+static gdouble gimp_dashboard_variable_to_double (GimpDashboard *dashboard,
+ Variable variable);
+
+
+/* static variables */
+
+static const VariableInfo variables[] =
+{
+ /* cache variables */
+
+ [VARIABLE_CACHE_OCCUPIED] =
+ { .name = "cache-occupied",
+ .title = NC_("dashboard-variable", "Occupied"),
+ .description = N_("Tile cache occupied size"),
+ .type = VARIABLE_TYPE_SIZE,
+ .color = {0.3, 0.6, 0.3, 1.0},
+ .sample_func = gimp_dashboard_sample_gegl_stats,
+ .data = "tile-cache-total"
+ },
+
+ [VARIABLE_CACHE_MAXIMUM] =
+ { .name = "cache-maximum",
+ .title = NC_("dashboard-variable", "Maximum"),
+ .description = N_("Maximal tile cache occupied size during this session"),
+ .type = VARIABLE_TYPE_SIZE,
+ .color = {0.3, 0.7, 0.8, 1.0},
+ .sample_func = gimp_dashboard_sample_gegl_stats,
+ .data = "tile-cache-total-max"
+ },
+
+ [VARIABLE_CACHE_LIMIT] =
+ { .name = "cache-limit",
+ .title = NC_("dashboard-variable", "Limit"),
+ .description = N_("Tile cache size limit"),
+ .type = VARIABLE_TYPE_SIZE,
+ .sample_func = gimp_dashboard_sample_gegl_config,
+ .data = "tile-cache-size"
+ },
+
+ [VARIABLE_CACHE_COMPRESSION] =
+ { .name = "cache-compression",
+ .title = NC_("dashboard-variable", "Compression"),
+ .description = N_("Tile cache compression ratio"),
+ .type = VARIABLE_TYPE_SIZE_RATIO,
+ .sample_func = gimp_dashboard_sample_gegl_stats,
+ .data = "tile-cache-total\0"
+ "tile-cache-total-uncloned"
+ },
+
+ [VARIABLE_CACHE_HIT_MISS] =
+ { .name = "cache-hit-miss",
+ .title = NC_("dashboard-variable", "Hit/Miss"),
+ .description = N_("Tile cache hit/miss ratio"),
+ .type = VARIABLE_TYPE_INT_RATIO,
+ .sample_func = gimp_dashboard_sample_gegl_stats,
+ .data = "tile-cache-hits\0"
+ "tile-cache-misses"
+ },
+
+
+ /* swap variables */
+
+ [VARIABLE_SWAP_OCCUPIED] =
+ { .name = "swap-occupied",
+ .title = NC_("dashboard-variable", "Occupied"),
+ .description = N_("Swap file occupied size"),
+ .type = VARIABLE_TYPE_SIZE,
+ .color = {0.8, 0.2, 0.2, 1.0},
+ .sample_func = gimp_dashboard_sample_gegl_stats,
+ .data = "swap-total"
+ },
+
+ [VARIABLE_SWAP_SIZE] =
+ { .name = "swap-size",
+ .title = NC_("dashboard-variable", "Size"),
+ .description = N_("Swap file size"),
+ .type = VARIABLE_TYPE_SIZE,
+ .color = {0.8, 0.6, 0.4, 1.0},
+ .sample_func = gimp_dashboard_sample_gegl_stats,
+ .data = "swap-file-size"
+ },
+
+ [VARIABLE_SWAP_LIMIT] =
+ { .name = "swap-limit",
+ .title = NC_("dashboard-variable", "Limit"),
+ .description = N_("Swap file size limit"),
+ .type = VARIABLE_TYPE_SIZE,
+ .sample_func = gimp_dashboard_sample_swap_limit,
+ },
+
+ [VARIABLE_SWAP_BUSY] =
+ { .name = "swap-busy",
+ .title = NC_("dashboard-variable", "Busy"),
+ .description = N_("Whether there is work queued for the swap file"),
+ .type = VARIABLE_TYPE_BOOLEAN,
+ .color = {0.8, 0.4, 0.4, 1.0},
+ .sample_func = gimp_dashboard_sample_gegl_stats,
+ .data = "swap-busy"
+ }
+};
+
+static const GroupInfo groups[] =
+{
+ /* cache group */
+ [GROUP_CACHE] =
+ { .name = "cache",
+ .title = NC_("dashboard-group", "Cache"),
+ .description = N_("In-memory tile cache"),
+ .default_expanded = TRUE,
+ .has_meter = TRUE,
+ .meter_limit = VARIABLE_CACHE_LIMIT,
+ .fields = (const FieldInfo[])
+ {
+ { .variable = VARIABLE_CACHE_OCCUPIED,
+ .default_active = TRUE,
+ .meter_value = 2
+ },
+ { .variable = VARIABLE_CACHE_MAXIMUM,
+ .default_active = FALSE,
+ .meter_value = 1
+ },
+ { .variable = VARIABLE_CACHE_LIMIT,
+ .default_active = TRUE
+ },
+
+ { VARIABLE_SEPARATOR },
+
+ { .variable = VARIABLE_CACHE_COMPRESSION,
+ .default_active = FALSE
+ },
+ { .variable = VARIABLE_CACHE_HIT_MISS,
+ .default_active = FALSE
+ },
+
+ {}
+ }
+ },
+
+ /* swap group */
+ [GROUP_SWAP] =
+ { .name = "swap",
+ .title = NC_("dashboard-group", "Swap"),
+ .description = N_("On-disk tile swap"),
+ .default_expanded = TRUE,
+ .has_meter = TRUE,
+ .meter_limit = VARIABLE_SWAP_LIMIT,
+ .meter_led = VARIABLE_SWAP_BUSY,
+ .fields = (const FieldInfo[])
+ {
+ { .variable = VARIABLE_SWAP_OCCUPIED,
+ .default_active = TRUE,
+ .meter_value = 2
+ },
+ { .variable = VARIABLE_SWAP_SIZE,
+ .default_active = TRUE,
+ .meter_value = 1
+ },
+ { .variable = VARIABLE_SWAP_LIMIT,
+ .default_active = TRUE
+ },
+
+ {}
+ }
+ }
+};
G_DEFINE_TYPE_WITH_CODE (GimpDashboard, gimp_dashboard, GIMP_TYPE_EDITOR,
@@ -100,27 +451,47 @@ gimp_dashboard_class_init (GimpDashboardClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
- object_class->dispose = gimp_dashboard_dispose;
- object_class->finalize = gimp_dashboard_finalize;
+ object_class->constructed = gimp_dashboard_constructed;
+ object_class->dispose = gimp_dashboard_dispose;
+ object_class->finalize = gimp_dashboard_finalize;
- widget_class->map = gimp_dashboard_map;
- widget_class->unmap = gimp_dashboard_unmap;
+ widget_class->map = gimp_dashboard_map;
+ widget_class->unmap = gimp_dashboard_unmap;
+
+ g_type_class_add_private (klass, sizeof (GimpDashboardPrivate));
}
static void
gimp_dashboard_init (GimpDashboard *dashboard)
{
- GtkWidget *box;
- GtkWidget *vbox;
- GtkWidget *frame;
- GtkWidget *table;
- GtkWidget *meter;
- GtkWidget *label;
- gint content_spacing;
-
- dashboard->update_interval = DEFAULT_UPDATE_INTERVAL;
- dashboard->history_duration = DEFAULT_HISTORY_DURATION;
- dashboard->low_swap_space_warning = DEFAULT_LOW_SWAP_SPACE_WARNING;
+ GimpDashboardPrivate *priv;
+ GtkWidget *box;
+ GtkWidget *vbox;
+ GtkWidget *expander;
+ GtkWidget *hbox;
+ GtkWidget *button;
+ GtkWidget *image;
+ GtkWidget *menu;
+ GtkWidget *item;
+ GtkWidget *frame;
+ GtkWidget *vbox2;
+ GtkWidget *meter;
+ GtkWidget *table;
+ GtkWidget *label;
+ gint content_spacing;
+ Group group;
+ gint field;
+
+ priv = dashboard->priv = G_TYPE_INSTANCE_GET_PRIVATE (dashboard,
+ GIMP_TYPE_DASHBOARD,
+ GimpDashboardPrivate);
+
+ g_mutex_init (&priv->mutex);
+ g_cond_init (&priv->cond);
+
+ priv->update_interval = DEFAULT_UPDATE_INTERVAL;
+ priv->history_duration = DEFAULT_HISTORY_DURATION;
+ priv->low_swap_space_warning = DEFAULT_LOW_SWAP_SPACE_WARNING;
gtk_widget_style_get (GTK_WIDGET (dashboard),
"content-spacing", &content_spacing,
@@ -140,166 +511,183 @@ gimp_dashboard_init (GimpDashboard *dashboard)
gtk_container_add (GTK_CONTAINER (box), vbox);
gtk_widget_show (vbox);
+ /* construct the groups */
+ for (group = FIRST_GROUP; group < N_GROUPS; group++)
+ {
+ const GroupInfo *group_info = &groups[group];
+ GroupData *group_data = &priv->groups[group];
- /* cache frame */
- frame = gimp_frame_new (NULL);
- gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
- gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
- gtk_widget_show (frame);
+ group_data->n_fields = 0;
+ group_data->n_meter_values = 0;
- /* cache frame label */
- box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
- gtk_frame_set_label_widget (GTK_FRAME (frame), box);
- gtk_widget_show (box);
+ for (field = 0; group_info->fields[field].variable; field++)
+ {
+ const FieldInfo *field_info = &group_info->fields[field];
- label = gtk_label_new (_("Cache"));
- gtk_label_set_xalign (GTK_LABEL (label), 0.0);
- gimp_label_set_attributes (GTK_LABEL (label),
- PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD,
- -1);
- gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
- gtk_widget_show (label);
-
- /* cache table */
- table = gtk_table_new (3, 2, FALSE);
- gtk_table_set_row_spacings (GTK_TABLE (table), content_spacing);
- gtk_table_set_col_spacings (GTK_TABLE (table), 4);
- gtk_container_add (GTK_CONTAINER (frame), table);
- gtk_widget_show (table);
-
- /* cache meter */
- meter = dashboard->cache_meter = gimp_meter_new (1);
- gimp_meter_set_color (GIMP_METER (meter),
- 0, &(GimpRGB) CACHE_OCCUPIED_COLOR);
- gimp_meter_set_history_resolution (GIMP_METER (meter),
- dashboard->update_interval / 1000.0);
- gimp_meter_set_history_duration (GIMP_METER (meter),
- dashboard->history_duration / 1000.0);
- gtk_table_attach (GTK_TABLE (table), meter, 0, 2, 0, 1,
- GTK_EXPAND | GTK_FILL, 0, 1, 0);
- gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2 * content_spacing);
- gtk_widget_show (meter);
-
- /* cache occupied field */
- label = gtk_label_new (_("Occupied:"));
- gtk_label_set_xalign (GTK_LABEL (label), 0.0);
- gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
- GTK_FILL, 0, 0, 0);
- gtk_widget_show (label);
-
- label = dashboard->cache_occupied_label = gtk_label_new (_("N/A"));
- gtk_label_set_xalign (GTK_LABEL (label), 0.0);
- gtk_table_attach (GTK_TABLE (table), label, 1, 2, 1, 2,
- GTK_EXPAND | GTK_FILL, 0, 0, 0);
- gtk_widget_show (label);
-
- /* cache limit field */
- label = gtk_label_new (_("Limit:"));
- gtk_label_set_xalign (GTK_LABEL (label), 0.0);
- gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3,
- GTK_FILL, 0, 0, 0);
- gtk_widget_show (label);
-
- label = dashboard->cache_limit_label = gtk_label_new (_("N/A"));
- gtk_label_set_xalign (GTK_LABEL (label), 0.0);
- gtk_table_attach (GTK_TABLE (table), label, 1, 2, 2, 3,
- GTK_EXPAND | GTK_FILL, 0, 0, 0);
- gtk_widget_show (label);
-
-
- /* swap frame */
- frame = gimp_frame_new (NULL);
- gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
- gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
- gtk_widget_show (frame);
-
- /* swap frame label */
- box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
- gtk_frame_set_label_widget (GTK_FRAME (frame), box);
- gtk_widget_show (box);
+ group_data->n_fields++;
+ group_data->n_meter_values = MAX (group_data->n_meter_values,
+ field_info->meter_value);
+ }
+
+ group_data->fields = g_new0 (FieldData, group_data->n_fields);
+
+ /* group expander */
+ expander = gtk_expander_new (NULL);
+ group_data->expander = GTK_EXPANDER (expander);
+ gtk_expander_set_expanded (GTK_EXPANDER (expander),
+ group_info->default_expanded);
+ gtk_expander_set_label_fill (GTK_EXPANDER (expander), TRUE);
+ gtk_box_pack_start (GTK_BOX (vbox), expander, FALSE, FALSE, 0);
+ gtk_widget_show (expander);
+
+ g_object_set_data (G_OBJECT (expander),
+ "gimp-dashboard-group", GINT_TO_POINTER (group));
+ g_signal_connect_swapped (expander, "button-press-event",
+ G_CALLBACK (gimp_dashboard_group_expander_button_press),
+ dashboard);
+
+ /* group expander label box */
+ hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ gimp_help_set_help_data (hbox,
+ g_dgettext (NULL, group_info->description),
+ NULL);
+ gtk_expander_set_label_widget (GTK_EXPANDER (expander), hbox);
+ gtk_widget_show (hbox);
+
+ /* group expander label */
+ label = gtk_label_new (g_dpgettext2 (NULL, "dashboard-group",
+ group_info->title));
+ gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+ gimp_label_set_attributes (GTK_LABEL (label),
+ PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD,
+ -1);
+ gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
+ gtk_widget_show (label);
+
+ /* group expander menu button */
+ button = gtk_button_new ();
+ group_data->menu_button = GTK_BUTTON (button);
+ gimp_help_set_help_data (button, _("Select fields"),
+ NULL);
+ gtk_widget_set_can_focus (button, FALSE);
+ gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
+ gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
+ gtk_widget_show (button);
+
+ image = gtk_image_new_from_icon_name (GIMP_ICON_MENU_LEFT,
+ GTK_ICON_SIZE_MENU);
+ gtk_image_set_pixel_size (GTK_IMAGE (image), 12);
+ gtk_image_set_from_icon_name (GTK_IMAGE (image), GIMP_ICON_MENU_LEFT,
+ GTK_ICON_SIZE_MENU);
+ gtk_container_add (GTK_CONTAINER (button), image);
+ gtk_widget_show (image);
+
+ /* group menu */
+ menu = gtk_menu_new ();
+ group_data->menu = GTK_MENU (menu);
+ gtk_menu_attach_to_widget (GTK_MENU (menu), button, NULL);
+
+ for (field = 0; field < group_data->n_fields; field++)
+ {
+ const FieldInfo *field_info = &group_info->fields[field];
+ FieldData *field_data = &group_data->fields[field];
+
+ if (field_info->variable != VARIABLE_SEPARATOR)
+ {
+ const VariableInfo *variable_info = &variables[field_info->variable];
+
+ item = gtk_check_menu_item_new_with_label (
+ g_dpgettext2 (NULL, "dashboard-field", variable_info->title));
+ field_data->menu_item = GTK_CHECK_MENU_ITEM (item);
+ gimp_help_set_help_data (item,
+ g_dgettext (NULL, variable_info->description),
+ NULL);
+
+ g_object_set_data (G_OBJECT (item),
+ "gimp-dashboard-group", GINT_TO_POINTER (group));
+ g_object_set_data (G_OBJECT (item),
+ "gimp-dashboard-field", GINT_TO_POINTER (field));
+ g_signal_connect_swapped (item, "toggled",
+ G_CALLBACK (gimp_dashboard_group_menu_item_toggled),
+ dashboard);
+
+ gimp_dashboard_field_set_active (dashboard, group, field,
+ field_info->default_active);
+ }
+ else
+ {
+ item = gtk_separator_menu_item_new ();
+ }
+
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show (item);
+ }
+
+ /* group frame */
+ frame = gimp_frame_new (NULL);
+ gtk_container_add (GTK_CONTAINER (expander), frame);
+ gtk_widget_show (frame);
+
+ /* group vbox */
+ vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2 * content_spacing);
+ gtk_container_add (GTK_CONTAINER (frame), vbox2);
+ gtk_widget_show (vbox2);
+
+ /* group meter */
+ if (group_info->has_meter)
+ {
+ meter = gimp_meter_new (group_data->n_meter_values);
+ group_data->meter = GIMP_METER (meter);
+ gimp_help_set_help_data (meter,
+ g_dgettext (NULL, group_info->description),
+ NULL);
+ gimp_meter_set_history_resolution (GIMP_METER (meter),
+ priv->update_interval / 1000.0);
+ gimp_meter_set_history_duration (GIMP_METER (meter),
+ priv->history_duration / 1000.0);
+ gtk_box_pack_start (GTK_BOX (vbox2), meter, FALSE, FALSE, 0);
+ gtk_widget_show (meter);
+
+ if (group_info->meter_led)
+ {
+ gimp_meter_set_led_color (GIMP_METER (meter),
+ &variables[group_info->meter_led].color);
+ }
+
+ for (field = 0; field < group_data->n_fields; field++)
+ {
+ const FieldInfo *field_info = &group_info->fields[field];
+
+ if (field_info->meter_value)
+ {
+ const VariableInfo *variable_info = &variables[field_info->variable];
+
+ gimp_meter_set_value_color (GIMP_METER (meter),
+ field_info->meter_value - 1,
+ &variable_info->color);
+ }
+ }
+ }
- label = gtk_label_new (_("Swap"));
- gtk_label_set_xalign (GTK_LABEL (label), 0.0);
- gimp_label_set_attributes (GTK_LABEL (label),
- PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD,
- -1);
- gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
- gtk_widget_show (label);
-
- /* swap table */
- table = gtk_table_new (4, 2, FALSE);
- gtk_table_set_row_spacings (GTK_TABLE (table), content_spacing);
- gtk_table_set_col_spacings (GTK_TABLE (table), 4);
- gtk_container_add (GTK_CONTAINER (frame), table);
- gtk_widget_show (table);
-
- /* swap meter */
- meter = dashboard->swap_meter = gimp_meter_new (2);
- gimp_meter_set_color (GIMP_METER (meter),
- 0, &(GimpRGB) SWAP_SIZE_COLOR);
- gimp_meter_set_color (GIMP_METER (meter),
- 1, &(GimpRGB) SWAP_OCCUPIED_COLOR);
- gimp_meter_set_history_resolution (GIMP_METER (meter),
- dashboard->update_interval / 1000.0);
- gimp_meter_set_history_duration (GIMP_METER (meter),
- dashboard->history_duration / 1000.0);
- gimp_meter_set_led_color (GIMP_METER (meter),
- &(GimpRGB) SWAP_LED_COLOR);
- gtk_table_attach (GTK_TABLE (table), meter, 0, 2, 0, 1,
- GTK_EXPAND | GTK_FILL, 0, 1, 0);
- gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2 * content_spacing);
- gtk_widget_show (meter);
-
- /* swap occupied field */
- label = gtk_label_new (_("Occupied:"));
- gtk_label_set_xalign (GTK_LABEL (label), 0.0);
- gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
- GTK_FILL, 0, 0, 0);
- gtk_widget_show (label);
-
- label = dashboard->swap_occupied_label = gtk_label_new (_("N/A"));
- gtk_label_set_xalign (GTK_LABEL (label), 0.0);
- gtk_table_attach (GTK_TABLE (table), label, 1, 2, 1, 2,
- GTK_EXPAND | GTK_FILL, 0, 0, 0);
- gtk_widget_show (label);
-
- /* swap size field */
- label = gtk_label_new (_("Size:"));
- gtk_label_set_xalign (GTK_LABEL (label), 0.0);
- gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3,
- GTK_FILL, 0, 0, 0);
- gtk_widget_show (label);
-
- label = dashboard->swap_size_label = gtk_label_new (_("N/A"));
- gtk_label_set_xalign (GTK_LABEL (label), 0.0);
- gtk_table_attach (GTK_TABLE (table), label, 1, 2, 2, 3,
- GTK_EXPAND | GTK_FILL, 0, 0, 0);
- gtk_widget_show (label);
-
- /* swap limit field */
- label = gtk_label_new (_("Limit:"));
- gtk_label_set_xalign (GTK_LABEL (label), 0.0);
- gtk_table_attach (GTK_TABLE (table), label, 0, 1, 3, 4,
- GTK_FILL, 0, 0, 0);
- gtk_widget_show (label);
-
- label = dashboard->swap_limit_label = gtk_label_new (_("N/A"));
- gtk_label_set_xalign (GTK_LABEL (label), 0.0);
- gtk_table_attach (GTK_TABLE (table), label, 1, 2, 3, 4,
- GTK_EXPAND | GTK_FILL, 0, 0, 0);
- gtk_widget_show (label);
-
-
- /* sampler thread */
- g_mutex_init (&dashboard->mutex);
- g_cond_init (&dashboard->cond);
-
- /* we use a separate thread for sampling, so that data is sampled even when
+ /* group table */
+ table = gtk_table_new (1, 1, FALSE);
+ group_data->table = GTK_TABLE (table);
+ gtk_table_set_row_spacings (GTK_TABLE (table), content_spacing);
+ gtk_table_set_col_spacings (GTK_TABLE (table), 4);
+ gtk_box_pack_start (GTK_BOX (vbox2), table, FALSE, FALSE, 0);
+ gtk_widget_show (table);
+
+ gimp_dashboard_update_group (dashboard, group);
+ }
+
+ /* sampler thread
+ *
+ * we use a separate thread for sampling, so that data is sampled even when
* the main thread is busy
*/
- dashboard->thread = g_thread_new ("dashboard",
- (GThreadFunc) gimp_dashboard_sample,
- dashboard);
+ priv->thread = g_thread_new ("dashboard",
+ (GThreadFunc) gimp_dashboard_sample,
+ dashboard);
}
static void
@@ -315,32 +703,44 @@ gimp_dashboard_docked_iface_init (GimpDockedInterface *iface)
}
static void
-gimp_dashboard_dispose (GObject *object)
+gimp_dashboard_constructed (GObject *object)
{
GimpDashboard *dashboard = GIMP_DASHBOARD (object);
- if (dashboard->thread)
+ G_OBJECT_CLASS (parent_class)->constructed (object);
+
+ gimp_editor_add_action_button (GIMP_EDITOR (dashboard), "dashboard",
+ "dashboard-reset", NULL);
+}
+
+static void
+gimp_dashboard_dispose (GObject *object)
+{
+ GimpDashboard *dashboard = GIMP_DASHBOARD (object);
+ GimpDashboardPrivate *priv = dashboard->priv;
+
+ if (priv->thread)
{
- g_mutex_lock (&dashboard->mutex);
+ g_mutex_lock (&priv->mutex);
- dashboard->quit = TRUE;
- g_cond_signal (&dashboard->cond);
+ priv->quit = TRUE;
+ g_cond_signal (&priv->cond);
- g_mutex_unlock (&dashboard->mutex);
+ g_mutex_unlock (&priv->mutex);
- g_clear_pointer (&dashboard->thread, g_thread_join);
+ g_clear_pointer (&priv->thread, g_thread_join);
}
- if (dashboard->timeout_id)
+ if (priv->update_idle_id)
{
- g_source_remove (dashboard->timeout_id);
- dashboard->timeout_id = 0;
+ g_source_remove (priv->update_idle_id);
+ priv->update_idle_id = 0;
}
- if (dashboard->low_swap_space_idle_id)
+ if (priv->low_swap_space_idle_id)
{
- g_source_remove (dashboard->low_swap_space_idle_id);
- dashboard->low_swap_space_idle_id = 0;
+ g_source_remove (priv->low_swap_space_idle_id);
+ priv->low_swap_space_idle_id = 0;
}
G_OBJECT_CLASS (parent_class)->dispose (object);
@@ -349,10 +749,15 @@ gimp_dashboard_dispose (GObject *object)
static void
gimp_dashboard_finalize (GObject *object)
{
- GimpDashboard *dashboard = GIMP_DASHBOARD (object);
+ GimpDashboard *dashboard = GIMP_DASHBOARD (object);
+ GimpDashboardPrivate *priv = dashboard->priv;
+ gint i;
- g_mutex_clear (&dashboard->mutex);
- g_cond_clear (&dashboard->cond);
+ for (i = FIRST_GROUP; i < N_GROUPS; i++)
+ g_free (priv->groups[i].fields);
+
+ g_mutex_clear (&priv->mutex);
+ g_cond_clear (&priv->cond);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@@ -364,25 +769,25 @@ gimp_dashboard_map (GtkWidget *widget)
GTK_WIDGET_CLASS (parent_class)->map (widget);
- if (! dashboard->timeout_id)
- {
- dashboard->timeout_id = g_timeout_add (dashboard->update_interval,
- (GSourceFunc) gimp_dashboard_update,
- dashboard);
- }
+ gimp_dashboard_update (dashboard);
}
static void
gimp_dashboard_unmap (GtkWidget *widget)
{
- GimpDashboard *dashboard = GIMP_DASHBOARD (widget);
+ GimpDashboard *dashboard = GIMP_DASHBOARD (widget);
+ GimpDashboardPrivate *priv = dashboard->priv;
+
+ g_mutex_lock (&priv->mutex);
- if (dashboard->timeout_id)
+ if (priv->update_idle_id)
{
- g_source_remove (dashboard->timeout_id);
- dashboard->timeout_id = 0;
+ g_source_remove (priv->update_idle_id);
+ priv->update_idle_id = 0;
}
+ g_mutex_unlock (&priv->mutex);
+
GTK_WIDGET_CLASS (parent_class)->unmap (widget);
}
@@ -394,8 +799,10 @@ static void
gimp_dashboard_set_aux_info (GimpDocked *docked,
GList *aux_info)
{
- GimpDashboard *dashboard = GIMP_DASHBOARD (docked);
- GList *list;
+ GimpDashboard *dashboard = GIMP_DASHBOARD (docked);
+ GimpDashboardPrivate *priv = dashboard->priv;
+ gchar *name;
+ GList *list;
parent_docked_iface->set_aux_info (docked, aux_info);
@@ -432,269 +839,447 @@ gimp_dashboard_set_aux_info (GimpDocked *docked,
gimp_dashboard_set_low_swap_space_warning (dashboard,
! strcmp (aux->value, "yes"));
}
- }
-}
+ else
+ {
+ Group group;
+ gint field;
-static GList *
-gimp_dashboard_get_aux_info (GimpDocked *docked)
-{
- GimpDashboard *dashboard = GIMP_DASHBOARD (docked);
- GList *aux_info;
- GimpSessionInfoAux *aux;
- gchar *value;
+ for (group = FIRST_GROUP; group < N_GROUPS; group++)
+ {
+ const GroupInfo *group_info = &groups[group];
+ GroupData *group_data = &priv->groups[group];
- aux_info = parent_docked_iface->get_aux_info (docked);
+ name = g_strdup_printf ("%s-expanded", group_info->name);
- value = g_strdup_printf ("%d", dashboard->update_interval);
- aux = gimp_session_info_aux_new (AUX_INFO_UPDATE_INTERVAL, value);
- aux_info = g_list_append (aux_info, aux);
- g_free (value);
+ if (! strcmp (aux->name, name))
+ {
+ gboolean expanded = ! strcmp (aux->value, "yes");
- value = g_strdup_printf ("%d", dashboard->history_duration);
- aux = gimp_session_info_aux_new (AUX_INFO_HISTORY_DURATION, value);
- aux_info = g_list_append (aux_info, aux);
- g_free (value);
+ gtk_expander_set_expanded (group_data->expander, expanded);
- value = dashboard->low_swap_space_warning ? "yes" : "no";
- aux = gimp_session_info_aux_new (AUX_INFO_LOW_SWAP_SPACE_WARNING, value);
- aux_info = g_list_append (aux_info, aux);
+ g_free (name);
+ goto next_aux_info;
+ }
- return aux_info;
+ g_free (name);
+
+ for (field = 0; field < group_data->n_fields; field++)
+ {
+ const FieldInfo *field_info = &group_info->fields[field];
+
+ if (field_info->variable != VARIABLE_SEPARATOR)
+ {
+ const VariableInfo *variable_info = &variables[field_info->variable];
+
+ name = g_strdup_printf ("%s-%s-active",
+ group_info->name,
+ variable_info->name);
+
+ if (! strcmp (aux->name, name))
+ {
+ gboolean active = ! strcmp (aux->value, "yes");
+
+ gimp_dashboard_field_set_active (dashboard,
+ group, field,
+ active);
+
+ g_free (name);
+ goto next_aux_info;
+ }
+
+ g_free (name);
+ }
+ }
+ }
+ }
+next_aux_info: ;
+ }
+
+ gimp_dashboard_update_groups (dashboard);
}
-static gboolean
-gimp_dashboard_update (GimpDashboard *dashboard)
+static GList *
+gimp_dashboard_get_aux_info (GimpDocked *docked)
{
- /* cache */
- {
- guint64 cache_occupied;
- guint64 cache_limit;
-
- g_object_get (gegl_stats (),
- "tile-cache-total", &cache_occupied,
- NULL);
- g_object_get (gegl_config (),
- "tile-cache-size", &cache_limit,
- NULL);
-
- gimp_meter_set_range (GIMP_METER (dashboard->cache_meter),
- 0.0, cache_limit);
-
- gimp_dashboard_label_set_size (GTK_LABEL (dashboard->cache_occupied_label),
- cache_occupied, cache_limit);
- gimp_dashboard_label_set_size (GTK_LABEL (dashboard->cache_limit_label),
- cache_limit, 0);
- }
+ GimpDashboard *dashboard = GIMP_DASHBOARD (docked);
+ GimpDashboardPrivate *priv = dashboard->priv;
+ GList *aux_info;
+ GimpSessionInfoAux *aux;
+ gchar *name;
+ gchar *value;
+ Group group;
+ gint field;
- /* swap */
- {
- guint64 swap_occupied;
- guint64 swap_size;
- guint64 swap_limit;
- gboolean swap_busy;
+ aux_info = parent_docked_iface->get_aux_info (docked);
- g_mutex_lock (&dashboard->mutex);
+ if (priv->update_interval != DEFAULT_UPDATE_INTERVAL)
+ {
+ value = g_strdup_printf ("%d", priv->update_interval);
+ aux = gimp_session_info_aux_new (AUX_INFO_UPDATE_INTERVAL, value);
+ aux_info = g_list_append (aux_info, aux);
+ g_free (value);
+ }
- g_object_get (gegl_stats (),
- "swap-total", &swap_occupied,
- "swap-file-size", &swap_size,
- "swap-busy", &swap_busy,
- NULL);
- swap_limit = gimp_dashboard_get_swap_limit (swap_size);
+ if (priv->history_duration != DEFAULT_HISTORY_DURATION)
+ {
+ value = g_strdup_printf ("%d", priv->history_duration);
+ aux = gimp_session_info_aux_new (AUX_INFO_HISTORY_DURATION, value);
+ aux_info = g_list_append (aux_info, aux);
+ g_free (value);
+ }
- g_mutex_unlock (&dashboard->mutex);
+ if (priv->low_swap_space_warning != DEFAULT_LOW_SWAP_SPACE_WARNING)
+ {
+ value = priv->low_swap_space_warning ? "yes" : "no";
+ aux = gimp_session_info_aux_new (AUX_INFO_LOW_SWAP_SPACE_WARNING, value);
+ aux_info = g_list_append (aux_info, aux);
+ }
- gimp_meter_set_range (GIMP_METER (dashboard->swap_meter),
- 0.0, swap_limit ? swap_limit : swap_size);
- gimp_meter_set_led_visible (GIMP_METER (dashboard->swap_meter), swap_busy);
+ for (group = FIRST_GROUP; group < N_GROUPS; group++)
+ {
+ const GroupInfo *group_info = &groups[group];
+ GroupData *group_data = &priv->groups[group];
+ gboolean expanded = gtk_expander_get_expanded (group_data->expander);
- gimp_dashboard_label_set_size (GTK_LABEL (dashboard->swap_occupied_label),
- swap_occupied, swap_limit);
- gimp_dashboard_label_set_size (GTK_LABEL (dashboard->swap_size_label),
- swap_size, swap_limit);
+ if (expanded != group_info->default_expanded)
+ {
+ name = g_strdup_printf ("%s-expanded", group_info->name);
+ value = expanded ? "yes" : "no";
+ aux = gimp_session_info_aux_new (name, value);
+ aux_info = g_list_append (aux_info, aux);
+ g_free (name);
+ }
- if (swap_limit)
- {
- gimp_dashboard_label_set_size (GTK_LABEL (dashboard->swap_limit_label),
- swap_limit, 0);
- }
- else
- {
- gimp_dashboard_label_set_text (GTK_LABEL (dashboard->swap_limit_label),
- _("N/A"));
- }
- }
+ for (field = 0; field < group_data->n_fields; field++)
+ {
+ const FieldInfo *field_info = &group_info->fields[field];
+ FieldData *field_data = &group_data->fields[field];
+ gboolean active = field_data->active;
- return G_SOURCE_CONTINUE;
+ if (field_info->variable != VARIABLE_SEPARATOR)
+ {
+ const VariableInfo *variable_info = &variables[field_info->variable];
+
+ if (active != field_info->default_active)
+ {
+ name = g_strdup_printf ("%s-%s-active",
+ group_info->name,
+ variable_info->name);
+ value = active ? "yes" : "no";
+ aux = gimp_session_info_aux_new (name, value);
+ aux_info = g_list_append (aux_info, aux);
+ g_free (name);
+ }
+ }
+ }
+ }
+
+ return aux_info;
}
static gboolean
-gimp_dashboard_low_swap_space (GimpDashboard *dashboard)
+gimp_dashboard_group_expander_button_press (GimpDashboard *dashboard,
+ GdkEventButton *bevent,
+ GtkWidget *widget)
{
- if (dashboard->gimp)
+ GimpDashboardPrivate *priv = dashboard->priv;
+ Group group;
+ GroupData *group_data;
+ GtkAllocation expander_allocation;
+ GtkAllocation allocation;
+
+ group = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
+ "gimp-dashboard-group"));
+ group_data = &priv->groups[group];
+
+ gtk_widget_get_allocation (GTK_WIDGET (group_data->expander),
+ &expander_allocation);
+ gtk_widget_get_allocation (GTK_WIDGET (group_data->menu_button),
+ &allocation);
+
+ allocation.x -= expander_allocation.x;
+ allocation.y -= expander_allocation.y;
+
+ if (bevent->button == 1 &&
+ bevent->x >= allocation.x &&
+ bevent->x < allocation.x + allocation.width &&
+ bevent->y >= allocation.y &&
+ bevent->y < allocation.y + allocation.height)
{
- GdkScreen *screen;
- gint monitor;
+ gtk_menu_popup (group_data->menu,
+ NULL, NULL,
+ gimp_dashboard_group_menu_position,
+ group_data->menu_button,
+ bevent->button, bevent->time);
- monitor = gimp_get_monitor_at_pointer (&screen);
+ return TRUE;
+ }
- gimp_window_strategy_show_dockable_dialog (
- GIMP_WINDOW_STRATEGY (gimp_get_window_strategy (dashboard->gimp)),
- dashboard->gimp,
- gimp_dialog_factory_get_singleton (),
- screen, monitor,
- "gimp-dashboard");
+ return FALSE;
+}
- gimp_dashboard_update (dashboard);
+static void
+gimp_dashboard_group_menu_item_toggled (GimpDashboard *dashboard,
+ GtkCheckMenuItem *item)
+{
+ GimpDashboardPrivate *priv = dashboard->priv;
+ Group group;
+ GroupData *group_data;
+ gint field;
+ FieldData *field_data;
- g_mutex_lock (&dashboard->mutex);
+ group = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item),
+ "gimp-dashboard-group"));
+ group_data = &priv->groups[group];
- dashboard->low_swap_space_idle_id = 0;
+ field = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item),
+ "gimp-dashboard-field"));
+ field_data = &group_data->fields[field];
- g_mutex_unlock (&dashboard->mutex);
- }
+ field_data->active = gtk_check_menu_item_get_active (item);
- return G_SOURCE_REMOVE;
+ gimp_dashboard_update_group (dashboard, group);
}
static gpointer
gimp_dashboard_sample (GimpDashboard *dashboard)
{
- GimpDashboardUpdateInteval update_interval;
- gint64 end_time;
- gboolean seen_low_swap_space = FALSE;
+ GimpDashboardPrivate *priv = dashboard->priv;
+ GimpDashboardUpdateInteval update_interval;
+ gint64 end_time;
+ gboolean seen_low_swap_space = FALSE;
- g_mutex_lock (&dashboard->mutex);
+ g_mutex_lock (&priv->mutex);
- update_interval = dashboard->update_interval;
+ update_interval = priv->update_interval;
end_time = g_get_monotonic_time ();
- while (! dashboard->quit)
+ while (! priv->quit)
{
- if (! g_cond_wait_until (&dashboard->cond, &dashboard->mutex, end_time))
+ if (! g_cond_wait_until (&priv->cond, &priv->mutex, end_time) ||
+ priv->update_now)
{
- /* cache */
- {
- guint64 cache_occupied;
- gdouble sample[1];
+ gboolean varaibles_changed = FALSE;
+ Variable variable;
+ Group group;
+ gint field;
- g_object_get (gegl_stats (),
- "tile-cache-total", &cache_occupied,
- NULL);
+ /* sample all varaibles */
+ for (variable = FIRST_VARIABLE; variable < N_VARIABLES; variable++)
+ {
+ const VariableInfo *variable_info = &variables[variable];
+ const VariableData *variable_data = &priv->variables[variable];
+ VariableData prev_variable_data = *variable_data;
- sample[0] = cache_occupied;
- gimp_meter_add_sample (GIMP_METER (dashboard->cache_meter), sample);
- }
+ variable_info->sample_func (dashboard, variable);
- /* swap */
- {
- guint64 swap_occupied;
- guint64 swap_size;
- gdouble sample[2];
+ varaibles_changed = varaibles_changed ||
+ memcmp (variable_data, &prev_variable_data,
+ sizeof (VariableData));
+ }
- g_object_get (gegl_stats (),
- "swap-total", &swap_occupied,
- "swap-file-size", &swap_size,
- NULL);
+ /* add samples to meters */
+ for (group = FIRST_GROUP; group < N_GROUPS; group++)
+ {
+ const GroupInfo *group_info = &groups[group];
+ GroupData *group_data = &priv->groups[group];
+ gdouble *sample;
- sample[0] = swap_size;
- sample[1] = swap_occupied;
- gimp_meter_add_sample (GIMP_METER (dashboard->swap_meter), sample);
+ if (! group_info->has_meter)
+ continue;
- if (dashboard->low_swap_space_warning)
- {
- guint64 swap_limit = gimp_dashboard_get_swap_limit (swap_size);
+ sample = g_new (gdouble, group_data->n_meter_values);
- if (swap_limit)
- {
- if (! seen_low_swap_space &&
- swap_occupied >= LOW_SWAP_SPACE_WARNING_ON * swap_limit)
- {
- if (! dashboard->low_swap_space_idle_id)
- {
- dashboard->low_swap_space_idle_id =
- g_idle_add_full (G_PRIORITY_HIGH,
- (GSourceFunc) gimp_dashboard_low_swap_space,
- dashboard, NULL);
- }
-
- seen_low_swap_space = TRUE;
- }
- else if (seen_low_swap_space &&
- swap_occupied <= LOW_SWAP_SPACE_WARNING_OFF * swap_limit)
- {
- if (dashboard->low_swap_space_idle_id)
- {
- g_source_remove (dashboard->low_swap_space_idle_id);
+ for (field = 0; field < group_data->n_fields; field++)
+ {
+ const FieldInfo *field_info = &group_info->fields[field];
- dashboard->low_swap_space_idle_id = 0;
- }
+ if (field_info->meter_value)
+ {
+ sample[field_info->meter_value - 1] =
+ gimp_dashboard_variable_to_double (dashboard,
+ field_info->variable);
+ }
+ }
- seen_low_swap_space = FALSE;
- }
- }
- }
- }
+ gimp_meter_add_sample (group_data->meter, sample);
+
+ g_free (sample);
+ }
+
+ if (varaibles_changed)
+ {
+ /* check for low swap space */
+ if (priv->low_swap_space_warning &&
+ priv->variables[VARIABLE_SWAP_OCCUPIED].available &&
+ priv->variables[VARIABLE_SWAP_LIMIT].available)
+ {
+ guint64 swap_occupied;
+ guint64 swap_limit;
+
+ swap_occupied = priv->variables[VARIABLE_SWAP_OCCUPIED].value.size;
+ swap_limit = priv->variables[VARIABLE_SWAP_LIMIT].value.size;
+
+ if (! seen_low_swap_space &&
+ swap_occupied >= LOW_SWAP_SPACE_WARNING_ON * swap_limit)
+ {
+ if (! priv->low_swap_space_idle_id)
+ {
+ priv->low_swap_space_idle_id =
+ g_idle_add_full (G_PRIORITY_HIGH,
+ (GSourceFunc) gimp_dashboard_low_swap_space,
+ dashboard, NULL);
+ }
+
+ seen_low_swap_space = TRUE;
+ }
+ else if (seen_low_swap_space &&
+ swap_occupied <= LOW_SWAP_SPACE_WARNING_OFF * swap_limit)
+ {
+ if (priv->low_swap_space_idle_id)
+ {
+ g_source_remove (priv->low_swap_space_idle_id);
+
+ priv->low_swap_space_idle_id = 0;
+ }
+
+ seen_low_swap_space = FALSE;
+ }
+ }
+
+ /* enqueue update source */
+ if (! priv->update_idle_id &&
+ gtk_widget_get_mapped (GTK_WIDGET (dashboard)))
+ {
+ priv->update_idle_id = g_idle_add_full (
+ G_PRIORITY_DEFAULT,
+ (GSourceFunc) gimp_dashboard_update,
+ dashboard, NULL);
+ }
+ }
+
+ priv->update_now = FALSE;
end_time = g_get_monotonic_time () +
update_interval * G_TIME_SPAN_SECOND / 1000;
}
- if (dashboard->update_interval != update_interval)
+ if (priv->update_interval != update_interval)
{
- update_interval = dashboard->update_interval;
+ update_interval = priv->update_interval;
end_time = g_get_monotonic_time () +
update_interval * G_TIME_SPAN_SECOND / 1000;
}
}
- g_mutex_unlock (&dashboard->mutex);
+ g_mutex_unlock (&priv->mutex);
return NULL;
}
-static void
-gimp_dashboard_label_set_text (GtkLabel *label,
- const gchar *text)
+static gboolean
+gimp_dashboard_update (GimpDashboard *dashboard)
{
- /* the strcmp() reduces the overhead of gtk_label_set_text() when the text
- * isn't changed
- */
- if (strcmp (gtk_label_get_text (label), text))
- gtk_label_set_text (label, text);
+ GimpDashboardPrivate *priv = dashboard->priv;
+ Group group;
+
+ g_mutex_lock (&priv->mutex);
+
+ for (group = FIRST_GROUP; group < N_GROUPS; group++)
+ {
+ const GroupInfo *group_info = &groups[group];
+ GroupData *group_data = &priv->groups[group];
+
+ if (group_info->has_meter && group_info->meter_led)
+ {
+ gboolean active;
+
+ active = gimp_dashboard_variable_to_boolean (dashboard,
+ group_info->meter_led);
+
+ gimp_meter_set_led_active (group_data->meter, active);
+ }
+
+ gimp_dashboard_update_group_values (dashboard, group);
+ }
+
+ priv->update_idle_id = 0;
+
+ g_mutex_unlock (&priv->mutex);
+
+ return G_SOURCE_REMOVE;
}
-static void
-gimp_dashboard_label_set_size (GtkLabel *label,
- guint64 size,
- guint64 limit)
+static gboolean
+gimp_dashboard_low_swap_space (GimpDashboard *dashboard)
{
- gchar *text;
+ GimpDashboardPrivate *priv = dashboard->priv;
- text = g_format_size_full (size, G_FORMAT_SIZE_IEC_UNITS);
-
- if (limit)
+ if (priv->gimp)
{
- gchar *temp;
+ GdkScreen *screen;
+ gint monitor;
+ gint field;
+
+ gtk_expander_set_expanded (priv->groups[GROUP_SWAP].expander, TRUE);
+
+ for (field = 0; field < priv->groups[GROUP_SWAP].n_fields; field++)
+ {
+ const FieldInfo *field_info = &groups[GROUP_SWAP].fields[field];
- temp = g_strdup_printf ("%s (%d%%)", text, ROUND (100.0 * size / limit));
- g_free (text);
+ if (field_info->variable == VARIABLE_SWAP_OCCUPIED ||
+ field_info->variable == VARIABLE_SWAP_LIMIT)
+ {
+ gimp_dashboard_field_set_active (dashboard,
+ GROUP_SWAP, field, TRUE);
+ }
+ }
- text = temp;
+ gimp_dashboard_update_groups (dashboard);
+
+ monitor = gimp_get_monitor_at_pointer (&screen);
+
+ gimp_window_strategy_show_dockable_dialog (
+ GIMP_WINDOW_STRATEGY (gimp_get_window_strategy (priv->gimp)),
+ priv->gimp,
+ gimp_dialog_factory_get_singleton (),
+ screen, monitor,
+ "gimp-dashboard");
+
+ g_mutex_lock (&priv->mutex);
+
+ priv->low_swap_space_idle_id = 0;
+
+ g_mutex_unlock (&priv->mutex);
}
- gimp_dashboard_label_set_text (label, text);
+ return G_SOURCE_REMOVE;
+}
+
+static void
+gimp_dashboard_sample_gegl_config (GimpDashboard *dashboard,
+ Variable variable)
+{
+ gimp_dashboard_sample_object (dashboard, G_OBJECT (gegl_config ()), variable);
+}
- g_free (text);
+static void
+gimp_dashboard_sample_gegl_stats (GimpDashboard *dashboard,
+ Variable variable)
+{
+ gimp_dashboard_sample_object (dashboard, G_OBJECT (gegl_stats ()), variable);
}
-static guint64
-gimp_dashboard_get_swap_limit (guint64 swap_size)
+static void
+gimp_dashboard_sample_swap_limit (GimpDashboard *dashboard,
+ Variable variable)
{
- static guint64 free_space = 0;
- static gboolean has_free_space = FALSE;
- static gint64 last_check_time = 0;
- gint64 time;
+ GimpDashboardPrivate *priv = dashboard->priv;
+ VariableData *variable_data = &priv->variables[variable];
+ static guint64 free_space = 0;
+ static gboolean has_free_space = FALSE;
+ static gint64 last_check_time = 0;
+ gint64 time;
/* we don't have a config option for limiting the swap size, so we simply
* return the free space available on the filesystem containing the swap
@@ -742,10 +1327,522 @@ gimp_dashboard_get_swap_limit (guint64 swap_size)
last_check_time = time;
}
- /* the swap limit is the sum of free_space and swap_size, since the swap
- * itself occupies space in the filesystem
- */
- return has_free_space ? free_space + swap_size : 0;
+ variable_data->available = has_free_space;
+
+ if (has_free_space)
+ {
+ variable_data->value.size = free_space;
+
+ if (priv->variables[VARIABLE_SWAP_SIZE].available)
+ {
+ /* the swap limit is the sum of free_space and swap_size, since the
+ * swap itself occupies space in the filesystem
+ */
+ variable_data->value.size +=
+ priv->variables[VARIABLE_SWAP_SIZE].value.size;
+ }
+ }
+}
+
+static void
+gimp_dashboard_sample_object (GimpDashboard *dashboard,
+ GObject *object,
+ Variable variable)
+{
+ GimpDashboardPrivate *priv = dashboard->priv;
+ GObjectClass *klass = G_OBJECT_GET_CLASS (object);
+ const VariableInfo *variable_info = &variables[variable];
+ VariableData *variable_data = &priv->variables[variable];
+
+ variable_data->available = FALSE;
+
+ switch (variable_info->type)
+ {
+ case VARIABLE_TYPE_BOOLEAN:
+ if (g_object_class_find_property (klass, variable_info->data))
+ {
+ variable_data->available = TRUE;
+
+ g_object_get (object,
+ variable_info->data, &variable_data->value.boolean,
+ NULL);
+ }
+ break;
+
+ case VARIABLE_TYPE_SIZE:
+ if (g_object_class_find_property (klass, variable_info->data))
+ {
+ variable_data->available = TRUE;
+
+ g_object_get (object,
+ variable_info->data, &variable_data->value.size,
+ NULL);
+ }
+ break;
+
+ case VARIABLE_TYPE_SIZE_RATIO:
+ {
+ const gchar *antecedent = variable_info->data;
+ const gchar *consequent = antecedent + strlen (antecedent) + 1;
+
+ if (g_object_class_find_property (klass, antecedent) &&
+ g_object_class_find_property (klass, consequent))
+ {
+ variable_data->available = TRUE;
+
+ g_object_get (object,
+ antecedent, &variable_data->value.size_ratio.antecedent,
+ consequent, &variable_data->value.size_ratio.consequent,
+ NULL);
+ }
+ }
+ break;
+
+ case VARIABLE_TYPE_INT_RATIO:
+ {
+ const gchar *antecedent = variable_info->data;
+ const gchar *consequent = antecedent + strlen (antecedent) + 1;
+
+ if (g_object_class_find_property (klass, antecedent) &&
+ g_object_class_find_property (klass, consequent))
+ {
+ variable_data->available = TRUE;
+
+ g_object_get (object,
+ antecedent, &variable_data->value.int_ratio.antecedent,
+ consequent, &variable_data->value.int_ratio.consequent,
+ NULL);
+ }
+ }
+ break;
+ }
+}
+
+static void
+gimp_dashboard_container_remove (GtkWidget *widget,
+ GtkContainer *container)
+{
+ gtk_container_remove (container, widget);
+}
+
+static void
+gimp_dashboard_group_menu_position (GtkMenu *menu,
+ gint *x,
+ gint *y,
+ gboolean *push_in,
+ gpointer user_data)
+{
+ gimp_button_menu_position (user_data, menu, GTK_POS_LEFT, x, y);
+}
+
+static void
+gimp_dashboard_update_groups (GimpDashboard *dashboard)
+{
+ Group group;
+
+ for (group = FIRST_GROUP; group < N_GROUPS; group++)
+ gimp_dashboard_update_group (dashboard, group);
+}
+
+static void
+gimp_dashboard_update_group (GimpDashboard *dashboard,
+ Group group)
+{
+ GimpDashboardPrivate *priv = dashboard->priv;
+ const GroupInfo *group_info = &groups[group];
+ GroupData *group_data = &priv->groups[group];
+ gint n_rows;
+ gboolean add_separator;
+ gint field;
+
+ n_rows = 0;
+ add_separator = FALSE;
+
+ for (field = 0; field < group_data->n_fields; field++)
+ {
+ const FieldInfo *field_info = &group_info->fields[field];
+ const FieldData *field_data = &group_data->fields[field];
+
+ if (field_info->variable != VARIABLE_SEPARATOR)
+ {
+ if (group_info->has_meter && field_info->meter_value)
+ {
+ gimp_meter_set_value_active (group_data->meter,
+ field_info->meter_value - 1,
+ field_data->active);
+ }
+
+ if (field_data->active)
+ {
+ if (add_separator)
+ {
+ add_separator = FALSE;
+ n_rows++;
+ }
+
+ n_rows++;
+ }
+ }
+ else
+ {
+ if (n_rows > 0)
+ add_separator = TRUE;
+ }
+ }
+
+ gtk_container_foreach (GTK_CONTAINER (group_data->table),
+ (GtkCallback) gimp_dashboard_container_remove,
+ group_data->table);
+ gtk_table_resize (group_data->table, MAX (n_rows, 1), 3);
+
+ n_rows = 0;
+ add_separator = FALSE;
+
+ for (field = 0; field < group_data->n_fields; field++)
+ {
+ const FieldInfo *field_info = &group_info->fields[field];
+ FieldData *field_data = &group_data->fields[field];
+
+ if (field_info->variable != VARIABLE_SEPARATOR)
+ {
+ const VariableInfo *variable_info = &variables[field_info->variable];
+ GtkWidget *separator;
+ GtkWidget *color_area;
+ GtkWidget *label;
+ const gchar *description;
+ gchar *str;
+
+ if (! field_data->active)
+ continue;
+
+ description = g_dgettext (NULL, variable_info->description);
+
+ if (add_separator)
+ {
+ separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
+ gtk_table_attach (group_data->table, separator,
+ 0, 3, n_rows, n_rows + 1,
+ GTK_EXPAND | GTK_FILL, 0,
+ 0, 0);
+ gtk_widget_show (separator);
+
+ add_separator = FALSE;
+ n_rows++;
+ }
+
+ if (variable_info->color.a)
+ {
+ color_area = gimp_color_area_new (&variable_info->color,
+ GIMP_COLOR_AREA_FLAT, 0);
+ gimp_help_set_help_data (color_area, description,
+ NULL);
+ gtk_widget_set_size_request (color_area, 5, 5);
+ gtk_table_attach (group_data->table, color_area,
+ 0, 1, n_rows, n_rows + 1,
+ 0, 0,
+ 0, 0);
+ gtk_widget_show (color_area);
+ }
+
+ str = g_strdup_printf ("%s:",
+ g_dpgettext2 (NULL, "dashboard-variable",
+ variable_info->title));
+
+ label = gtk_label_new (str);
+ gimp_help_set_help_data (label, description,
+ NULL);
+ gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+ gtk_table_attach (group_data->table, label,
+ 1, 2, n_rows, n_rows + 1,
+ GTK_FILL, 0,
+ 0, 0);
+ gtk_widget_show (label);
+
+ g_free (str);
+
+ label = gtk_label_new (NULL);
+ field_data->value_label = GTK_LABEL (label);
+ gimp_help_set_help_data (label, description,
+ NULL);
+ gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+ gtk_table_attach (group_data->table, label,
+ 2, 3, n_rows, n_rows + 1,
+ GTK_EXPAND | GTK_FILL, 0,
+ 0, 0);
+ gtk_widget_show (label);
+
+ n_rows++;
+ }
+ else
+ {
+ if (n_rows > 0)
+ add_separator = TRUE;
+ }
+ }
+
+ g_mutex_lock (&priv->mutex);
+
+ gimp_dashboard_update_group_values (dashboard, group);
+
+ g_mutex_unlock (&priv->mutex);
+}
+
+static void
+gimp_dashboard_update_group_values (GimpDashboard *dashboard,
+ Group group)
+{
+ GimpDashboardPrivate *priv = dashboard->priv;
+ const GroupInfo *group_info = &groups[group];
+ GroupData *group_data = &priv->groups[group];
+ gdouble limit = 0.0;
+ gint field;
+
+ if (group_info->has_meter)
+ {
+ if (group_info->meter_limit)
+ {
+ const VariableData *variable_data = &priv->variables[group_info->meter_limit];
+
+ if (variable_data->available)
+ {
+ limit = gimp_dashboard_variable_to_double (dashboard,
+ group_info->meter_limit);
+ }
+ else
+ {
+ for (field = 0; field < group_data->n_fields; field++)
+ {
+ const FieldInfo *field_info = &group_info->fields[field];
+ const FieldData *field_data = &group_data->fields[field];
+
+ if (field_info->meter_value && field_data->active)
+ {
+ gdouble value;
+
+ value = gimp_dashboard_variable_to_double (dashboard,
+ field_info->variable);
+
+ limit = MAX (limit, value);
+ }
+ }
+ }
+
+ gimp_meter_set_range (group_data->meter, 0.0, limit);
+ }
+
+ if (group_info->meter_led)
+ {
+ gimp_meter_set_led_active (
+ group_data->meter,
+ gimp_dashboard_variable_to_boolean (dashboard,
+ group_info->meter_led));
+ }
+ }
+
+ for (field = 0; field < group_data->n_fields; field++)
+ {
+ const FieldInfo *field_info = &group_info->fields[field];
+ const FieldData *field_data = &group_data->fields[field];
+
+ if (field_data->active)
+ {
+ const VariableInfo *variable_info = &variables[field_info->variable];
+ const VariableData *variable_data = &priv->variables[field_info->variable];
+ /* Tranlators: "N/A" is an abbreviation for "not available" */
+ const gchar *str = C_("dashboard-value", "N/A");
+ gboolean free_str = FALSE;
+
+ if (variable_data->available)
+ {
+ switch (variable_info->type)
+ {
+ case VARIABLE_TYPE_BOOLEAN:
+ str = variable_data->value.boolean ? C_("dashboard-value", "Yes") :
+ C_("dashboard-value", "No");
+ break;
+
+ case VARIABLE_TYPE_SIZE:
+ str = g_format_size_full (variable_data->value.size,
+ G_FORMAT_SIZE_IEC_UNITS);
+ free_str = TRUE;
+ break;
+
+ case VARIABLE_TYPE_SIZE_RATIO:
+ {
+ if (variable_data->value.size_ratio.consequent)
+ {
+ gdouble value;
+
+ value = 100.0 * variable_data->value.size_ratio.antecedent /
+ variable_data->value.size_ratio.consequent;
+
+ str = g_strdup_printf ("%d%%", SIGNED_ROUND (value));
+ free_str = TRUE;
+ }
+ }
+ break;
+
+ case VARIABLE_TYPE_INT_RATIO:
+ {
+ gdouble min;
+ gdouble max;
+ gdouble antecedent;
+ gdouble consequent;
+
+ antecedent = variable_data->value.int_ratio.antecedent;
+ consequent = variable_data->value.int_ratio.consequent;
+
+ min = MIN (ABS (antecedent), ABS (consequent));
+ max = MAX (ABS (antecedent), ABS (consequent));
+
+ if (min)
+ {
+ antecedent /= min;
+ consequent /= min;
+ }
+ else if (max)
+ {
+ antecedent /= max;
+ consequent /= max;
+ }
+
+ if (max)
+ {
+ str = g_strdup_printf ("%g:%g",
+ RINT (100.0 * antecedent) / 100.0,
+ RINT (100.0 * consequent) / 100.0);
+ free_str = TRUE;
+ }
+ }
+ break;
+ }
+
+ if (field_info->meter_value && limit)
+ {
+ gdouble value;
+ gchar *tmp;
+
+ value = gimp_dashboard_variable_to_double (dashboard,
+ field_info->variable);
+
+ tmp = g_strdup_printf ("%s (%d%%)",
+ str,
+ SIGNED_ROUND (100.0 * value / limit));
+
+ if (free_str)
+ g_free ((gpointer) str);
+
+ str = tmp;
+ free_str = TRUE;
+ }
+ }
+
+ /* the strcmp() reduces the overhead of gtk_label_set_text() when the
+ * text hasn't changed
+ */
+ if (strcmp (gtk_label_get_text (field_data->value_label), str))
+ gtk_label_set_text (field_data->value_label, str);
+
+ if (free_str)
+ g_free ((gpointer) str);
+ }
+ }
+}
+
+static void
+gimp_dashboard_field_set_active (GimpDashboard *dashboard,
+ Group group,
+ gint field,
+ gboolean active)
+{
+ GimpDashboardPrivate *priv = dashboard->priv;
+ GroupData *group_data = &priv->groups[group];
+ FieldData *field_data = &group_data->fields[field];
+
+ if (active != field_data->active)
+ {
+ field_data->active = active;
+
+ g_signal_handlers_block_by_func (field_data->menu_item,
+ gimp_dashboard_group_menu_item_toggled,
+ dashboard);
+
+ gtk_check_menu_item_set_active (field_data->menu_item, active);
+
+ g_signal_handlers_unblock_by_func (field_data->menu_item,
+ gimp_dashboard_group_menu_item_toggled,
+ dashboard);
+ }
+}
+
+static gboolean
+gimp_dashboard_variable_to_boolean (GimpDashboard *dashboard,
+ Variable variable)
+{
+ GimpDashboardPrivate *priv = dashboard->priv;
+ const VariableInfo *variable_info = &variables[variable];
+ const VariableData *variable_data = &priv->variables[variable];
+
+ if (variable_data->available)
+ {
+ switch (variable_info->type)
+ {
+ case VARIABLE_TYPE_BOOLEAN:
+ return variable_data->value.boolean;
+
+ case VARIABLE_TYPE_SIZE:
+ return variable_data->value.size > 0;
+
+ case VARIABLE_TYPE_SIZE_RATIO:
+ return variable_data->value.size_ratio.antecedent != 0 &&
+ variable_data->value.size_ratio.consequent != 0;
+
+ case VARIABLE_TYPE_INT_RATIO:
+ return variable_data->value.int_ratio.antecedent != 0 &&
+ variable_data->value.int_ratio.consequent != 0;
+ }
+ }
+
+ return FALSE;
+}
+
+static gdouble
+gimp_dashboard_variable_to_double (GimpDashboard *dashboard,
+ Variable variable)
+{
+ GimpDashboardPrivate *priv = dashboard->priv;
+ const VariableInfo *variable_info = &variables[variable];
+ const VariableData *variable_data = &priv->variables[variable];
+
+ if (variable_data->available)
+ {
+ switch (variable_info->type)
+ {
+ case VARIABLE_TYPE_BOOLEAN:
+ return variable_data->value.boolean ? 1.0 : 0.0;
+
+ case VARIABLE_TYPE_SIZE:
+ return variable_data->value.size;
+
+ case VARIABLE_TYPE_SIZE_RATIO:
+ if (variable_data->value.size_ratio.consequent)
+ {
+ return (gdouble) variable_data->value.size_ratio.antecedent /
+ (gdouble) variable_data->value.size_ratio.consequent;
+ }
+ break;
+
+ case VARIABLE_TYPE_INT_RATIO:
+ if (variable_data->value.int_ratio.consequent)
+ {
+ return (gdouble) variable_data->value.int_ratio.antecedent /
+ (gdouble) variable_data->value.int_ratio.consequent;
+ }
+ break;
+ }
+ }
+
+ return 0.0;
}
@@ -764,72 +1861,151 @@ gimp_dashboard_new (Gimp *gimp,
"ui-path", "/dashboard-popup",
NULL);
- dashboard->gimp = gimp;
+ dashboard->priv->gimp = gimp;
return GTK_WIDGET (dashboard);
}
void
+gimp_dashboard_reset (GimpDashboard *dashboard)
+{
+ GimpDashboardPrivate *priv;
+ Group group;
+
+ g_return_if_fail (GIMP_IS_DASHBOARD (dashboard));
+
+ priv = dashboard->priv;
+
+ g_mutex_lock (&priv->mutex);
+
+ gegl_reset_stats ();
+
+ for (group = FIRST_GROUP; group < N_GROUPS; group++)
+ {
+ GroupData *group_data = &priv->groups[group];
+
+ if (group_data->meter)
+ gimp_meter_clear_history (group_data->meter);
+ }
+
+ priv->update_now = TRUE;
+ g_cond_signal (&priv->cond);
+
+ g_mutex_unlock (&priv->mutex);
+}
+
+void
gimp_dashboard_set_update_interval (GimpDashboard *dashboard,
GimpDashboardUpdateInteval update_interval)
{
+ GimpDashboardPrivate *priv;
+
g_return_if_fail (GIMP_IS_DASHBOARD (dashboard));
- if (update_interval != dashboard->update_interval)
+ priv = dashboard->priv;
+
+ if (update_interval != priv->update_interval)
{
- g_mutex_lock (&dashboard->mutex);
+ Group group;
- dashboard->update_interval = update_interval;
+ g_mutex_lock (&priv->mutex);
- gimp_meter_set_history_resolution (GIMP_METER (dashboard->cache_meter),
- update_interval / 1000.0);
- gimp_meter_set_history_resolution (GIMP_METER (dashboard->swap_meter),
- update_interval / 1000.0);
+ priv->update_interval = update_interval;
- if (dashboard->timeout_id)
+ for (group = FIRST_GROUP; group < N_GROUPS; group++)
{
- g_source_remove (dashboard->timeout_id);
+ GroupData *group_data = &priv->groups[group];
- dashboard->timeout_id = g_timeout_add (update_interval,
- (GSourceFunc) gimp_dashboard_update,
- dashboard);
+ if (group_data->meter)
+ {
+ gimp_meter_set_history_resolution (group_data->meter,
+ update_interval / 1000.0);
+ }
}
- g_cond_signal (&dashboard->cond);
+ priv->update_now = TRUE;
+ g_cond_signal (&priv->cond);
- g_mutex_unlock (&dashboard->mutex);
+ g_mutex_unlock (&priv->mutex);
}
}
+GimpDashboardUpdateInteval
+gimp_dashboard_get_update_interval (GimpDashboard *dashboard)
+{
+ g_return_val_if_fail (GIMP_IS_DASHBOARD (dashboard), DEFAULT_UPDATE_INTERVAL);
+
+ return dashboard->priv->update_interval;
+}
+
void
gimp_dashboard_set_history_duration (GimpDashboard *dashboard,
GimpDashboardHistoryDuration history_duration)
{
+ GimpDashboardPrivate *priv;
+
g_return_if_fail (GIMP_IS_DASHBOARD (dashboard));
- if (history_duration != dashboard->history_duration)
+ priv = dashboard->priv;
+
+ if (history_duration != priv->history_duration)
{
- dashboard->history_duration = history_duration;
+ Group group;
+
+ g_mutex_lock (&priv->mutex);
+
+ priv->history_duration = history_duration;
- gimp_meter_set_history_duration (GIMP_METER (dashboard->cache_meter),
- history_duration / 1000.0);
- gimp_meter_set_history_duration (GIMP_METER (dashboard->swap_meter),
- history_duration / 1000.0);
+ for (group = FIRST_GROUP; group < N_GROUPS; group++)
+ {
+ GroupData *group_data = &priv->groups[group];
+
+ if (group_data->meter)
+ {
+ gimp_meter_set_history_duration (group_data->meter,
+ history_duration / 1000.0);
+ }
+ }
+
+ priv->update_now = TRUE;
+ g_cond_signal (&priv->cond);
+
+ g_mutex_unlock (&priv->mutex);
}
}
+GimpDashboardHistoryDuration
+gimp_dashboard_get_history_duration (GimpDashboard *dashboard)
+{
+ g_return_val_if_fail (GIMP_IS_DASHBOARD (dashboard), DEFAULT_HISTORY_DURATION);
+
+ return dashboard->priv->history_duration;
+}
+
void
gimp_dashboard_set_low_swap_space_warning (GimpDashboard *dashboard,
gboolean low_swap_space_warning)
{
+ GimpDashboardPrivate *priv;
+
g_return_if_fail (GIMP_IS_DASHBOARD (dashboard));
- if (low_swap_space_warning != dashboard->low_swap_space_warning)
+ priv = dashboard->priv;
+
+ if (low_swap_space_warning != priv->low_swap_space_warning)
{
- g_mutex_lock (&dashboard->mutex);
+ g_mutex_lock (&priv->mutex);
- dashboard->low_swap_space_warning = low_swap_space_warning;
+ priv->low_swap_space_warning = low_swap_space_warning;
- g_mutex_unlock (&dashboard->mutex);
+ g_mutex_unlock (&priv->mutex);
}
}
+
+gboolean
+gimp_dashboard_get_low_swap_space_warning (GimpDashboard *dashboard)
+{
+ g_return_val_if_fail (GIMP_IS_DASHBOARD (dashboard), DEFAULT_LOW_SWAP_SPACE_WARNING);
+
+ return dashboard->priv->low_swap_space_warning;
+}
diff --git a/app/widgets/gimpdashboard.h b/app/widgets/gimpdashboard.h
index dc6ee3a..e8e9249 100644
--- a/app/widgets/gimpdashboard.h
+++ b/app/widgets/gimpdashboard.h
@@ -33,34 +33,14 @@
#define GIMP_DASHBOARD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_DASHBOARD,
GimpDashboardClass))
-typedef struct _GimpDashboardClass GimpDashboardClass;
+typedef struct _GimpDashboardPrivate GimpDashboardPrivate;
+typedef struct _GimpDashboardClass GimpDashboardClass;
struct _GimpDashboard
{
- GimpEditor parent_instance;
+ GimpEditor parent_instance;
- Gimp *gimp;
-
- GtkWidget *cache_meter;
- GtkWidget *cache_occupied_label;
- GtkWidget *cache_limit_label;
-
- GtkWidget *swap_meter;
- GtkWidget *swap_occupied_label;
- GtkWidget *swap_size_label;
- GtkWidget *swap_limit_label;
-
- gint timeout_id;
- gint low_swap_space_idle_id;
-
- GThread *thread;
- GMutex mutex;
- GCond cond;
- gboolean quit;
-
- GimpDashboardUpdateInteval update_interval;
- GimpDashboardHistoryDuration history_duration;
- gboolean low_swap_space_warning;
+ GimpDashboardPrivate *priv;
};
struct _GimpDashboardClass
@@ -69,17 +49,24 @@ struct _GimpDashboardClass
};
-GType gimp_dashboard_get_type (void) G_GNUC_CONST;
+GType gimp_dashboard_get_type (void) G_GNUC_CONST;
+
+GtkWidget * gimp_dashboard_new (Gimp *gimp,
+ GimpMenuFactory
*menu_factory);
+
+void gimp_dashboard_reset (GimpDashboard
*dashboard);
+
+void gimp_dashboard_set_update_interval (GimpDashboard
*dashboard,
+ GimpDashboardUpdateInteval
update_interval);
+GimpDashboardUpdateInteval gimp_dashboard_get_update_interval (GimpDashboard
*dashboard);
-GtkWidget * gimp_dashboard_new (Gimp *gimp,
- GimpMenuFactory *menu_factory);
+void gimp_dashboard_set_history_duration (GimpDashboard
*dashboard,
+ GimpDashboardHistoryDuration
history_duration);
+GimpDashboardHistoryDuration gimp_dashboard_get_history_duration (GimpDashboard
*dashboard);
-void gimp_dashboard_set_update_interval (GimpDashboard *dashboard,
- GimpDashboardUpdateInteval update_interval);
-void gimp_dashboard_set_history_duration (GimpDashboard *dashboard,
- GimpDashboardHistoryDuration history_duration);
-void gimp_dashboard_set_low_swap_space_warning (GimpDashboard *dashboard,
- gboolean low_swap_space_warning);
+void gimp_dashboard_set_low_swap_space_warning (GimpDashboard
*dashboard,
+ gboolean
low_swap_space_warning);
+gboolean gimp_dashboard_get_low_swap_space_warning (GimpDashboard
*dashboard);
#endif /* __GIMP_DASHBOARD_H__ */
diff --git a/app/widgets/gimphelp-ids.h b/app/widgets/gimphelp-ids.h
index f8cec31..19f55cd 100644
--- a/app/widgets/gimphelp-ids.h
+++ b/app/widgets/gimphelp-ids.h
@@ -665,6 +665,7 @@
#define GIMP_HELP_DASHBOARD_DIALOG "gimp-dashboard-dialog"
#define GIMP_HELP_DASHBOARD_UPDATE_INTERVAL "gimp-dashboard-update-interval"
#define GIMP_HELP_DASHBOARD_HISTORY_DURATION "gimp-dashboard-history-duration"
+#define GIMP_HELP_DASHBOARD_RESET "gimp-dashboard-reset"
#define GIMP_HELP_DASHBOARD_LOW_SWAP_SPACE_WARNING "gimp-dashboard-low-swap-space-warning"
#define GIMP_HELP_DOCK "gimp-dock"
diff --git a/menus/dashboard-menu.xml b/menus/dashboard-menu.xml
index 9bdc05c..30548a7 100644
--- a/menus/dashboard-menu.xml
+++ b/menus/dashboard-menu.xml
@@ -17,6 +17,7 @@
<menuitem action="dashboard-history-duration-120-sec" />
<menuitem action="dashboard-history-duration-240-sec" />
</menu>
+ <menuitem action="dashboard-reset" />
<separator />
<menuitem action="dashboard-low-swap-space-warning" />
</popup>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]