diff --git a/app/actions/Makefile.am b/app/actions/Makefile.am
index 3613fbb11a..8b5eb8c95b 100644
--- a/app/actions/Makefile.am
+++ b/app/actions/Makefile.am
@@ -44,6 +44,10 @@ libappactions_a_SOURCES = \
cursor-info-actions.h \
cursor-info-commands.c \
cursor-info-commands.h \
+ dashboard-actions.c \
+ dashboard-actions.h \
+ dashboard-commands.c \
+ dashboard-commands.h \
data-commands.c \
data-commands.h \
data-editor-commands.c \
diff --git a/app/actions/actions.c b/app/actions/actions.c
index ecae6d541a..22bee0a6a3 100644
--- a/app/actions/actions.c
+++ b/app/actions/actions.c
@@ -57,6 +57,7 @@
#include "colormap-actions.h"
#include "context-actions.h"
#include "cursor-info-actions.h"
+#include "dashboard-actions.h"
#include "debug-actions.h"
#include "dialogs-actions.h"
#include "dock-actions.h"
@@ -128,6 +129,9 @@ static const GimpActionFactoryEntry action_groups[] =
{ "cursor-info", N_("Pointer Information"), NULL,
cursor_info_actions_setup,
cursor_info_actions_update },
+ { "dashboard", N_("Dashboard"), GIMP_ICON_DIALOG_DASHBOARD,
+ dashboard_actions_setup,
+ dashboard_actions_update },
{ "debug", N_("Debug"), NULL,
debug_actions_setup,
debug_actions_update },
diff --git a/app/actions/dashboard-actions.c b/app/actions/dashboard-actions.c
new file mode 100644
index 0000000000..73449e537a
--- /dev/null
+++ b/app/actions/dashboard-actions.c
@@ -0,0 +1,193 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include "config.h"
+
+#include
+#include
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimpdashboard.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "dashboard-actions.h"
+#include "dashboard-commands.h"
+
+#include "gimp-intl.h"
+
+
+static const GimpActionEntry dashboard_actions[] =
+{
+ { "dashboard-popup", GIMP_ICON_DIALOG_DASHBOARD,
+ NC_("dashboard-action", "Dashboard Menu"), NULL, NULL, NULL,
+ GIMP_HELP_DASHBOARD_DIALOG },
+
+ { "dashboard-update-interval", NULL,
+ NC_("dashboard-action", "Update Interval") },
+ { "dashboard-history-duration", NULL,
+ NC_("dashboard-action", "History Duration") }
+};
+
+static const GimpToggleActionEntry dashboard_toggle_actions[] =
+{
+ { "dashboard-low-swap-space-warning", NULL,
+ NC_("dashboard-action", "Low Swap Space Warning"), NULL,
+ N_("Raise the dashboard when the swap size approaches its limit"),
+ G_CALLBACK (dashboard_low_swap_space_warning_cmd_callback),
+ FALSE,
+ GIMP_HELP_DASHBOARD_LOW_SWAP_SPACE_WARNING }
+};
+
+static const GimpRadioActionEntry dashboard_update_interval_actions[] =
+{
+ { "dashboard-update-interval-0-25-sec", NULL,
+ NC_("dashboard-update-interval", "0.25 Seconds"), NULL, NULL,
+ GIMP_DASHBOARD_UPDATE_INTERVAL_0_25_SEC,
+ GIMP_HELP_DASHBOARD_UPDATE_INTERVAL },
+
+ { "dashboard-update-interval-0-5-sec", NULL,
+ NC_("dashboard-update-interval", "0.5 Seconds"), NULL, NULL,
+ GIMP_DASHBOARD_UPDATE_INTERVAL_0_5_SEC,
+ GIMP_HELP_DASHBOARD_UPDATE_INTERVAL },
+
+ { "dashboard-update-interval-1-sec", NULL,
+ NC_("dashboard-update-interval", "1 Second"), NULL, NULL,
+ GIMP_DASHBOARD_UPDATE_INTERVAL_1_SEC,
+ GIMP_HELP_DASHBOARD_UPDATE_INTERVAL },
+
+ { "dashboard-update-interval-2-sec", NULL,
+ NC_("dashboard-update-interval", "2 Seconds"), NULL, NULL,
+ GIMP_DASHBOARD_UPDATE_INTERVAL_2_SEC,
+ GIMP_HELP_DASHBOARD_UPDATE_INTERVAL },
+
+ { "dashboard-update-interval-4-sec", NULL,
+ NC_("dashboard-update-interval", "4 Seconds"), NULL, NULL,
+ GIMP_DASHBOARD_UPDATE_INTERVAL_4_SEC,
+ GIMP_HELP_DASHBOARD_UPDATE_INTERVAL }
+};
+
+static const GimpRadioActionEntry dashboard_history_duration_actions[] =
+{
+ { "dashboard-history-duration-15-sec", NULL,
+ NC_("dashboard-history-duration", "15 Seconds"), NULL, NULL,
+ GIMP_DASHBOARD_HISTORY_DURATION_15_SEC,
+ GIMP_HELP_DASHBOARD_HISTORY_DURATION },
+
+ { "dashboard-history-duration-30-sec", NULL,
+ NC_("dashboard-history-duration", "30 Seconds"), NULL, NULL,
+ GIMP_DASHBOARD_HISTORY_DURATION_30_SEC,
+ GIMP_HELP_DASHBOARD_HISTORY_DURATION },
+
+ { "dashboard-history-duration-60-sec", NULL,
+ NC_("dashboard-history-duration", "60 Seconds"), NULL, NULL,
+ GIMP_DASHBOARD_HISTORY_DURATION_60_SEC,
+ GIMP_HELP_DASHBOARD_HISTORY_DURATION },
+
+ { "dashboard-history-duration-120-sec", NULL,
+ NC_("dashboard-history-duration", "120 Seconds"), NULL, NULL,
+ GIMP_DASHBOARD_HISTORY_DURATION_120_SEC,
+ GIMP_HELP_DASHBOARD_HISTORY_DURATION },
+
+ { "dashboard-history-duration-240-sec", NULL,
+ NC_("dashboard-history-duration", "240 Seconds"), NULL, NULL,
+ GIMP_DASHBOARD_HISTORY_DURATION_240_SEC,
+ GIMP_HELP_DASHBOARD_HISTORY_DURATION }
+};
+
+
+void
+dashboard_actions_setup (GimpActionGroup *group)
+{
+ gimp_action_group_add_actions (group, "dashboard-action",
+ dashboard_actions,
+ G_N_ELEMENTS (dashboard_actions));
+
+ gimp_action_group_add_toggle_actions (group, "dashboard-action",
+ dashboard_toggle_actions,
+ G_N_ELEMENTS (dashboard_toggle_actions));
+
+ gimp_action_group_add_radio_actions (group, "dashboard-update-interval",
+ dashboard_update_interval_actions,
+ G_N_ELEMENTS (dashboard_update_interval_actions),
+ NULL,
+ 0,
+ G_CALLBACK (dashboard_update_interval_cmd_callback));
+
+ gimp_action_group_add_radio_actions (group, "dashboard-history-duration",
+ dashboard_history_duration_actions,
+ G_N_ELEMENTS (dashboard_history_duration_actions),
+ NULL,
+ 0,
+ G_CALLBACK (dashboard_history_duration_cmd_callback));
+}
+
+void
+dashboard_actions_update (GimpActionGroup *group,
+ gpointer data)
+{
+ GimpDashboard *dashboard = GIMP_DASHBOARD (data);
+
+#define SET_ACTIVE(action,condition) \
+ gimp_action_group_set_action_active (group, action, (condition) != 0)
+
+ switch (dashboard->update_interval)
+ {
+ case GIMP_DASHBOARD_UPDATE_INTERVAL_0_25_SEC:
+ SET_ACTIVE ("dashboard-update-interval-0-25-sec", TRUE);
+ break;
+ case GIMP_DASHBOARD_UPDATE_INTERVAL_0_5_SEC:
+ SET_ACTIVE ("dashboard-update-interval-0-5-sec", TRUE);
+ break;
+ case GIMP_DASHBOARD_UPDATE_INTERVAL_1_SEC:
+ SET_ACTIVE ("dashboard-update-interval-1-sec", TRUE);
+ break;
+ case GIMP_DASHBOARD_UPDATE_INTERVAL_2_SEC:
+ SET_ACTIVE ("dashboard-update-interval-2-sec", TRUE);
+ break;
+ case GIMP_DASHBOARD_UPDATE_INTERVAL_4_SEC:
+ SET_ACTIVE ("dashboard-update-interval-4-sec", TRUE);
+ break;
+ }
+
+ switch (dashboard->history_duration)
+ {
+ case GIMP_DASHBOARD_HISTORY_DURATION_15_SEC:
+ SET_ACTIVE ("dashboard-history-duration-15-sec", TRUE);
+ break;
+ case GIMP_DASHBOARD_HISTORY_DURATION_30_SEC:
+ SET_ACTIVE ("dashboard-history-duration-30-sec", TRUE);
+ break;
+ case GIMP_DASHBOARD_HISTORY_DURATION_60_SEC:
+ SET_ACTIVE ("dashboard-history-duration-60-sec", TRUE);
+ break;
+ case GIMP_DASHBOARD_HISTORY_DURATION_120_SEC:
+ SET_ACTIVE ("dashboard-history-duration-120-sec", TRUE);
+ break;
+ case GIMP_DASHBOARD_HISTORY_DURATION_240_SEC:
+ SET_ACTIVE ("dashboard-history-duration-240-sec", TRUE);
+ break;
+ }
+
+ SET_ACTIVE ("dashboard-low-swap-space-warning",
+ dashboard->low_swap_space_warning);
+
+#undef SET_ACTIVE
+}
diff --git a/app/actions/dashboard-actions.h b/app/actions/dashboard-actions.h
new file mode 100644
index 0000000000..08b7a4166e
--- /dev/null
+++ b/app/actions/dashboard-actions.h
@@ -0,0 +1,27 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef __DASHBOARD_ACTIONS_H__
+#define __DASHBOARD_ACTIONS_H__
+
+
+void dashboard_actions_setup (GimpActionGroup *group);
+void dashboard_actions_update (GimpActionGroup *group,
+ gpointer data);
+
+
+#endif /* __DASHBOARD_ACTIONS_H__ */
diff --git a/app/actions/dashboard-commands.c b/app/actions/dashboard-commands.c
new file mode 100644
index 0000000000..c7b110b780
--- /dev/null
+++ b/app/actions/dashboard-commands.c
@@ -0,0 +1,74 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include "config.h"
+
+#include
+#include
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "widgets/gimpdashboard.h"
+#include "widgets/gimphelp-ids.h"
+
+#include "dashboard-commands.h"
+
+#include "gimp-intl.h"
+
+
+/* public functionss */
+
+
+void
+dashboard_update_interval_cmd_callback (GtkAction *action,
+ GtkAction *current,
+ gpointer data)
+{
+ GimpDashboard *dashboard = GIMP_DASHBOARD (data);
+ GimpDashboardUpdateInteval update_interval;
+
+ update_interval = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action));
+
+ gimp_dashboard_set_update_interval (dashboard, update_interval);
+}
+
+void
+dashboard_history_duration_cmd_callback (GtkAction *action,
+ GtkAction *current,
+ gpointer data)
+{
+ GimpDashboard *dashboard = GIMP_DASHBOARD (data);
+ GimpDashboardHistoryDuration history_duration;
+
+ history_duration = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action));
+
+ gimp_dashboard_set_history_duration (dashboard, history_duration);
+}
+
+void
+dashboard_low_swap_space_warning_cmd_callback (GtkAction *action,
+ gpointer data)
+{
+ GimpDashboard *dashboard = GIMP_DASHBOARD (data);
+ gboolean low_swap_space_warning;
+
+ low_swap_space_warning = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
+
+ gimp_dashboard_set_low_swap_space_warning (dashboard, low_swap_space_warning);
+}
diff --git a/app/actions/dashboard-commands.h b/app/actions/dashboard-commands.h
new file mode 100644
index 0000000000..4314a144f1
--- /dev/null
+++ b/app/actions/dashboard-commands.h
@@ -0,0 +1,33 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef __DASHBOARD_COMMANDS_H__
+#define __DASHBOARD_COMMANDS_H__
+
+
+void dashboard_update_interval_cmd_callback (GtkAction *action,
+ GtkAction *current,
+ gpointer data);
+void dashboard_history_duration_cmd_callback (GtkAction *action,
+ GtkAction *current,
+ gpointer data);
+
+void dashboard_low_swap_space_warning_cmd_callback (GtkAction *action,
+ gpointer data);
+
+
+#endif /* __DASHBOARD_COMMANDS_H__ */
diff --git a/app/actions/dialogs-actions.c b/app/actions/dialogs-actions.c
index 08aa4264ed..8c573dc9d2 100644
--- a/app/actions/dialogs-actions.c
+++ b/app/actions/dialogs-actions.c
@@ -233,6 +233,12 @@ const GimpStringActionEntry dialogs_dockable_actions[] =
NC_("dialogs-action", "Error Co_nsole"), NULL,
NC_("dialogs-action", "Open the error console"),
"gimp-error-console",
+ GIMP_HELP_ERRORS_DIALOG },
+
+ { "dialogs-dashboard", GIMP_ICON_DIALOG_DASHBOARD,
+ NC_("dialogs-action", "_Dashboard"), NULL,
+ NC_("dialogs-action", "Open the dashboard"),
+ "gimp-dashboard",
GIMP_HELP_ERRORS_DIALOG }
};
diff --git a/app/dialogs/dialogs-constructors.c b/app/dialogs/dialogs-constructors.c
index 7a659284d0..7ef92fe973 100644
--- a/app/dialogs/dialogs-constructors.c
+++ b/app/dialogs/dialogs-constructors.c
@@ -35,6 +35,7 @@
#include "widgets/gimpchanneltreeview.h"
#include "widgets/gimpcoloreditor.h"
#include "widgets/gimpcolormapeditor.h"
+#include "widgets/gimpdashboard.h"
#include "widgets/gimpdevicestatus.h"
#include "widgets/gimpdialogfactory.h"
#include "widgets/gimpdockwindow.h"
@@ -344,6 +345,16 @@ dialogs_cursor_view_new (GimpDialogFactory *factory,
return gimp_cursor_view_new (gimp_dialog_factory_get_menu_factory (factory));
}
+GtkWidget *
+dialogs_dashboard_new (GimpDialogFactory *factory,
+ GimpContext *context,
+ GimpUIManager *ui_manager,
+ gint view_size)
+{
+ return gimp_dashboard_new (context->gimp,
+ gimp_dialog_factory_get_menu_factory (factory));
+}
+
/***** list views *****/
diff --git a/app/dialogs/dialogs-constructors.h b/app/dialogs/dialogs-constructors.h
index 496725c578..bcdfbedcc6 100644
--- a/app/dialogs/dialogs-constructors.h
+++ b/app/dialogs/dialogs-constructors.h
@@ -125,6 +125,10 @@ GtkWidget * dialogs_cursor_view_new (GimpDialogFactory *factory,
GimpContext *context,
GimpUIManager *ui_manager,
gint view_size);
+GtkWidget * dialogs_dashboard_new (GimpDialogFactory *factory,
+ GimpContext *context,
+ GimpUIManager *ui_manager,
+ gint view_size);
GtkWidget * dialogs_image_list_view_new (GimpDialogFactory *factory,
GimpContext *context,
diff --git a/app/dialogs/dialogs.c b/app/dialogs/dialogs.c
index 8a4ed321b0..d817d741be 100644
--- a/app/dialogs/dialogs.c
+++ b/app/dialogs/dialogs.c
@@ -320,6 +320,10 @@ static const GimpDialogFactoryEntry entries[] =
N_("Pointer"), N_("Pointer Information"), GIMP_ICON_CURSOR,
GIMP_HELP_POINTER_INFO_DIALOG,
dialogs_cursor_view_new, 0, TRUE),
+ DOCKABLE ("gimp-dashboard",
+ N_("Dashboard"), N_("Dashboard"), GIMP_ICON_DIALOG_DASHBOARD,
+ GIMP_HELP_ERRORS_DIALOG,
+ dialogs_dashboard_new, 0, TRUE),
/* list & grid views */
LISTGRID (image, image,
diff --git a/app/menus/menus.c b/app/menus/menus.c
index fff8b3cfbd..2c7ff98e31 100644
--- a/app/menus/menus.c
+++ b/app/menus/menus.c
@@ -387,6 +387,14 @@ menus_init (Gimp *gimp,
"sample-points-menu.xml",
NULL,
NULL);
+
+ gimp_menu_factory_manager_register (global_menu_factory, "",
+ "dashboard",
+ NULL,
+ "/dashboard-popup",
+ "dashboard-menu.xml",
+ NULL,
+ NULL);
}
void
diff --git a/app/widgets/Makefile.am b/app/widgets/Makefile.am
index 6501bda556..bb6546ce43 100644
--- a/app/widgets/Makefile.am
+++ b/app/widgets/Makefile.am
@@ -120,6 +120,8 @@ libappwidgets_a_sources = \
gimpcursor.h \
gimpcurveview.c \
gimpcurveview.h \
+ gimpdashboard.c \
+ gimpdashboard.h \
gimpdasheditor.c \
gimpdasheditor.h \
gimpdataeditor.c \
diff --git a/app/widgets/gimpdashboard.c b/app/widgets/gimpdashboard.c
new file mode 100644
index 0000000000..bea895f039
--- /dev/null
+++ b/app/widgets/gimpdashboard.c
@@ -0,0 +1,818 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995-1999 Spencer Kimball and Peter Mattis
+ *
+ * gimpdashboard.c
+ * Copyright (C) 2017 Ell
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include "config.h"
+
+#include
+
+#include
+#include
+#include
+
+#include "libgimpbase/gimpbase.h"
+#include "libgimpmath/gimpmath.h"
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "widgets-types.h"
+
+#include "core/gimp.h"
+
+#include "gimpdocked.h"
+#include "gimpdashboard.h"
+#include "gimpdialogfactory.h"
+#include "gimpmeter.h"
+#include "gimpsessioninfo-aux.h"
+#include "gimpwindowstrategy.h"
+
+#include "gimp-intl.h"
+
+
+#define DEFAULT_UPDATE_INTERVAL GIMP_DASHBOARD_UPDATE_INTERVAL_0_25_SEC
+#define DEFAULT_HISTORY_DURATION GIMP_DASHBOARD_HISTORY_DURATION_60_SEC
+#define DEFAULT_LOW_SWAP_SPACE_WARNING TRUE
+
+#define LOW_SWAP_SPACE_WARNING_ON /* swap occupied is above */ 0.90 /* times swap limit */
+#define LOW_SWAP_SPACE_WARNING_OFF /* swap occupied is below */ 0.85 /* times 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}
+
+
+static void gimp_dashboard_docked_iface_init (GimpDockedInterface *iface);
+
+static void gimp_dashboard_finalize (GObject *object);
+
+static void gimp_dashboard_map (GtkWidget *widget);
+static void gimp_dashboard_unmap (GtkWidget *widget);
+
+static void gimp_dashboard_set_aux_info (GimpDocked *docked,
+ GList *aux_info);
+static GList * gimp_dashboard_get_aux_info (GimpDocked *docked);
+
+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_label_set_text (GtkLabel *label,
+ const gchar *text);
+static void gimp_dashboard_label_set_size (GtkLabel *label,
+ guint64 size,
+ guint64 limit);
+
+static guint64 gimp_dashboard_get_swap_limit (guint64 swap_size);
+
+
+G_DEFINE_TYPE_WITH_CODE (GimpDashboard, gimp_dashboard, GIMP_TYPE_EDITOR,
+ G_IMPLEMENT_INTERFACE (GIMP_TYPE_DOCKED,
+ gimp_dashboard_docked_iface_init))
+
+#define parent_class gimp_dashboard_parent_class
+
+static GimpDockedInterface *parent_docked_iface = NULL;
+
+
+/* private functions */
+
+
+static void
+gimp_dashboard_class_init (GimpDashboardClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->finalize = gimp_dashboard_finalize;
+
+ widget_class->map = gimp_dashboard_map;
+ widget_class->unmap = gimp_dashboard_unmap;
+}
+
+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;
+
+ gtk_widget_style_get (GTK_WIDGET (dashboard),
+ "content-spacing", &content_spacing,
+ NULL);
+
+ /* we put the dashboard inside an event box, so that it gets its own window,
+ * which reduces the overhead of updating the ui, since it gets updated
+ * frequently. unfortunately, this means that the dashboard's background
+ * color may be a bit off for some themes.
+ */
+ box = dashboard->box = gtk_event_box_new ();
+ gtk_box_pack_start (GTK_BOX (dashboard), box, TRUE, TRUE, 0);
+ gtk_widget_show (box);
+
+ /* main vbox */
+ vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2 * content_spacing);
+ gtk_container_add (GTK_CONTAINER (box), vbox);
+ gtk_widget_show (vbox);
+
+
+ /* 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);
+
+ /* cache frame label */
+ box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+ gtk_frame_set_label_widget (GTK_FRAME (frame), box);
+ gtk_widget_show (box);
+
+ 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);
+
+ 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) {0.8, 0.4, 0.4, 1.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);
+
+ /* 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
+ * the main thread is busy
+ */
+ dashboard->thread = g_thread_new ("dashboard",
+ (GThreadFunc) gimp_dashboard_sample,
+ dashboard);
+}
+
+static void
+gimp_dashboard_docked_iface_init (GimpDockedInterface *iface)
+{
+ parent_docked_iface = g_type_interface_peek_parent (iface);
+
+ if (! parent_docked_iface)
+ parent_docked_iface = g_type_default_interface_peek (GIMP_TYPE_DOCKED);
+
+ iface->set_aux_info = gimp_dashboard_set_aux_info;
+ iface->get_aux_info = gimp_dashboard_get_aux_info;
+}
+
+static void
+gimp_dashboard_finalize (GObject *object)
+{
+ GimpDashboard *dashboard = GIMP_DASHBOARD (object);
+
+ if (dashboard->timeout_id)
+ {
+ g_source_remove (dashboard->timeout_id);
+ dashboard->timeout_id = 0;
+ }
+
+ if (dashboard->low_swap_space_idle_id)
+ {
+ g_source_remove (dashboard->low_swap_space_idle_id);
+ dashboard->low_swap_space_idle_id = 0;
+ }
+
+ if (dashboard->thread)
+ {
+ g_mutex_lock (&dashboard->mutex);
+
+ dashboard->quit = TRUE;
+ g_cond_signal (&dashboard->cond);
+
+ g_mutex_unlock (&dashboard->mutex);
+
+ g_clear_pointer (&dashboard->thread, g_thread_join);
+ }
+
+ g_mutex_clear (&dashboard->mutex);
+ g_cond_clear (&dashboard->cond);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gimp_dashboard_map (GtkWidget *widget)
+{
+ GimpDashboard *dashboard = GIMP_DASHBOARD (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);
+ }
+}
+
+static void
+gimp_dashboard_unmap (GtkWidget *widget)
+{
+ GimpDashboard *dashboard = GIMP_DASHBOARD (widget);
+
+ if (dashboard->timeout_id)
+ {
+ g_source_remove (dashboard->timeout_id);
+ dashboard->timeout_id = 0;
+ }
+
+ GTK_WIDGET_CLASS (parent_class)->unmap (widget);
+}
+
+#define AUX_INFO_UPDATE_INTERVAL "update-interval"
+#define AUX_INFO_HISTORY_DURATION "history-duration"
+#define AUX_INFO_LOW_SWAP_SPACE_WARNING "low-swap-space-warning"
+
+static void
+gimp_dashboard_set_aux_info (GimpDocked *docked,
+ GList *aux_info)
+{
+ GimpDashboard *dashboard = GIMP_DASHBOARD (docked);
+ GList *list;
+
+ parent_docked_iface->set_aux_info (docked, aux_info);
+
+ for (list = aux_info; list; list = g_list_next (list))
+ {
+ GimpSessionInfoAux *aux = list->data;
+
+ if (! strcmp (aux->name, AUX_INFO_UPDATE_INTERVAL))
+ {
+ gint value = atoi (aux->value);
+ GimpDashboardUpdateInteval update_interval;
+
+ for (update_interval = GIMP_DASHBOARD_UPDATE_INTERVAL_0_25_SEC;
+ update_interval < value &&
+ update_interval < GIMP_DASHBOARD_UPDATE_INTERVAL_4_SEC;
+ update_interval *= 2);
+
+ gimp_dashboard_set_update_interval (dashboard, update_interval);
+ }
+ else if (! strcmp (aux->name, AUX_INFO_HISTORY_DURATION))
+ {
+ gint value = atoi (aux->value);
+ GimpDashboardHistoryDuration history_duration;
+
+ for (history_duration = GIMP_DASHBOARD_HISTORY_DURATION_15_SEC;
+ history_duration < value &&
+ history_duration < GIMP_DASHBOARD_HISTORY_DURATION_240_SEC;
+ history_duration *= 2);
+
+ gimp_dashboard_set_history_duration (dashboard, history_duration);
+ }
+ else if (! strcmp (aux->name, AUX_INFO_LOW_SWAP_SPACE_WARNING))
+ {
+ gimp_dashboard_set_low_swap_space_warning (dashboard,
+ ! strcmp (aux->value, "yes"));
+ }
+ }
+}
+
+static GList *
+gimp_dashboard_get_aux_info (GimpDocked *docked)
+{
+ GimpDashboard *dashboard = GIMP_DASHBOARD (docked);
+ GList *aux_info;
+ GimpSessionInfoAux *aux;
+ gchar *value;
+
+ aux_info = parent_docked_iface->get_aux_info (docked);
+
+ 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);
+
+ 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);
+
+ 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);
+
+ return aux_info;
+}
+
+static gboolean
+gimp_dashboard_update (GimpDashboard *dashboard)
+{
+ /* 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);
+ }
+
+ /* swap */
+ {
+ guint64 swap_occupied;
+ guint64 swap_size;
+ guint64 swap_limit;
+ gboolean swap_busy;
+
+ g_mutex_lock (&dashboard->mutex);
+
+ 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);
+
+ g_mutex_unlock (&dashboard->mutex);
+
+ 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);
+
+ 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 (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"));
+ }
+ }
+
+ return G_SOURCE_CONTINUE;
+}
+
+static gboolean
+gimp_dashboard_low_swap_space (GimpDashboard *dashboard)
+{
+ if (dashboard->gimp)
+ {
+ GdkScreen *screen;
+ gint monitor;
+
+ monitor = gimp_get_monitor_at_pointer (&screen);
+
+ 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");
+
+ g_mutex_lock (&dashboard->mutex);
+
+ dashboard->low_swap_space_idle_id = 0;
+
+ g_mutex_unlock (&dashboard->mutex);
+ }
+
+ return G_SOURCE_REMOVE;
+}
+
+static gpointer
+gimp_dashboard_sample (GimpDashboard *dashboard)
+{
+ GimpDashboardUpdateInteval update_interval;
+ gint64 end_time;
+ gboolean seen_low_swap_space = FALSE;
+
+ g_mutex_lock (&dashboard->mutex);
+
+ update_interval = dashboard->update_interval;
+ end_time = g_get_monotonic_time ();
+
+ while (! dashboard->quit)
+ {
+ if (! g_cond_wait_until (&dashboard->cond, &dashboard->mutex, end_time))
+ {
+ /* cache */
+ {
+ guint64 cache_occupied;
+ gdouble sample[1];
+
+ g_object_get (gegl_stats (),
+ "tile-cache-total", &cache_occupied,
+ NULL);
+
+ sample[0] = cache_occupied;
+ gimp_meter_add_sample (GIMP_METER (dashboard->cache_meter), sample);
+ }
+
+ /* swap */
+ {
+ guint64 swap_occupied;
+ guint64 swap_size;
+ gdouble sample[2];
+
+ g_object_get (gegl_stats (),
+ "swap-total", &swap_occupied,
+ "swap-file-size", &swap_size,
+ NULL);
+
+ sample[0] = swap_size;
+ sample[1] = swap_occupied;
+ gimp_meter_add_sample (GIMP_METER (dashboard->swap_meter), sample);
+
+ if (dashboard->low_swap_space_warning)
+ {
+ guint64 swap_limit = gimp_dashboard_get_swap_limit (swap_size);
+
+ 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);
+
+ dashboard->low_swap_space_idle_id = 0;
+ }
+
+ seen_low_swap_space = FALSE;
+ }
+ }
+ }
+
+ end_time = g_get_monotonic_time () +
+ update_interval * G_TIME_SPAN_SECOND / 1000;
+ }
+ else if (dashboard->update_interval != update_interval)
+ {
+ update_interval = dashboard->update_interval;
+ end_time = g_get_monotonic_time () +
+ update_interval * G_TIME_SPAN_SECOND / 1000;
+ }
+ }
+
+ g_mutex_unlock (&dashboard->mutex);
+
+ return NULL;
+}
+
+static void
+gimp_dashboard_label_set_text (GtkLabel *label,
+ const gchar *text)
+{
+ /* 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);
+}
+
+static void
+gimp_dashboard_label_set_size (GtkLabel *label,
+ guint64 size,
+ guint64 limit)
+{
+ gchar *text;
+
+ text = g_format_size_full (size, G_FORMAT_SIZE_IEC_UNITS);
+
+ if (limit)
+ {
+ gchar *temp;
+
+ temp = g_strdup_printf ("%s (%d%%)", text, ROUND (100.0 * size / limit));
+ g_free (text);
+
+ text = temp;
+ }
+
+ gimp_dashboard_label_set_text (label, text);
+
+ g_free (text);
+}
+
+static guint64
+gimp_dashboard_get_swap_limit (guint64 swap_size)
+{
+ 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
+ */
+
+ time = g_get_monotonic_time ();
+
+ if (time - last_check_time >= G_TIME_SPAN_SECOND)
+ {
+ gchar *swap_dir;
+
+ g_object_get (gegl_config (),
+ "swap", &swap_dir,
+ NULL);
+
+ free_space = 0;
+ has_free_space = FALSE;
+
+ if (swap_dir)
+ {
+ GFile *file;
+ GFileInfo *info;
+
+ file = g_file_new_for_path (swap_dir);
+
+ info = g_file_query_filesystem_info (file,
+ G_FILE_ATTRIBUTE_FILESYSTEM_FREE,
+ NULL, NULL);
+
+ if (info)
+ {
+ free_space =
+ g_file_info_get_attribute_uint64 (info,
+ G_FILE_ATTRIBUTE_FILESYSTEM_FREE);
+ has_free_space = TRUE;
+
+ g_object_unref (info);
+ }
+
+ g_object_unref (file);
+
+ g_free (swap_dir);
+ }
+
+ 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;
+}
+
+
+/* public functions */
+
+
+GtkWidget *
+gimp_dashboard_new (Gimp *gimp,
+ GimpMenuFactory *menu_factory)
+{
+ GimpDashboard *dashboard;
+
+ dashboard = g_object_new (GIMP_TYPE_DASHBOARD,
+ "menu-factory", menu_factory,
+ "menu-identifier", "",
+ "ui-path", "/dashboard-popup",
+ NULL);
+
+ dashboard->gimp = gimp;
+
+ return GTK_WIDGET (dashboard);
+}
+
+void
+gimp_dashboard_set_update_interval (GimpDashboard *dashboard,
+ GimpDashboardUpdateInteval update_interval)
+{
+ g_return_if_fail (GIMP_IS_DASHBOARD (dashboard));
+
+ if (update_interval != dashboard->update_interval)
+ {
+ g_mutex_lock (&dashboard->mutex);
+
+ dashboard->update_interval = update_interval;
+
+ 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);
+
+ if (dashboard->timeout_id)
+ {
+ g_source_remove (dashboard->timeout_id);
+
+ dashboard->timeout_id = g_timeout_add (update_interval,
+ (GSourceFunc) gimp_dashboard_update,
+ dashboard);
+ }
+
+ g_cond_signal (&dashboard->cond);
+
+ g_mutex_unlock (&dashboard->mutex);
+ }
+}
+
+void
+gimp_dashboard_set_history_duration (GimpDashboard *dashboard,
+ GimpDashboardHistoryDuration history_duration)
+{
+ g_return_if_fail (GIMP_IS_DASHBOARD (dashboard));
+
+ if (history_duration != dashboard->history_duration)
+ {
+ dashboard->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);
+ }
+}
+
+void
+gimp_dashboard_set_low_swap_space_warning (GimpDashboard *dashboard,
+ gboolean low_swap_space_warning)
+{
+ g_return_if_fail (GIMP_IS_DASHBOARD (dashboard));
+
+ if (low_swap_space_warning != dashboard->low_swap_space_warning)
+ {
+ g_mutex_lock (&dashboard->mutex);
+
+ dashboard->low_swap_space_warning = low_swap_space_warning;
+
+ g_mutex_unlock (&dashboard->mutex);
+ }
+}
diff --git a/app/widgets/gimpdashboard.h b/app/widgets/gimpdashboard.h
new file mode 100644
index 0000000000..dae7d42e05
--- /dev/null
+++ b/app/widgets/gimpdashboard.h
@@ -0,0 +1,90 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpdashboard.h
+ * Copyright (C) 2017 Ell
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef __GIMP_DASHBOARD_H__
+#define __GIMP_DASHBOARD_H__
+
+
+#include "gimpeditor.h"
+
+
+#define GIMP_TYPE_DASHBOARD (gimp_dashboard_get_type ())
+#define GIMP_DASHBOARD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_DASHBOARD, GimpDashboard))
+#define GIMP_DASHBOARD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_DASHBOARD, GimpDashboardClass))
+#define GIMP_IS_DASHBOARD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_DASHBOARD))
+#define GIMP_IS_DASHBOARD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_DASHBOARD))
+#define GIMP_DASHBOARD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_DASHBOARD, GimpDashboardClass))
+
+
+typedef struct _GimpDashboardClass GimpDashboardClass;
+
+struct _GimpDashboard
+{
+ GimpEditor parent_instance;
+
+ Gimp *gimp;
+
+ GtkWidget *box;
+
+ GtkWidget *cache_meter;
+ GtkWidget *cache_occupied_label;
+ GtkWidget *cache_occupied_pct_label;
+ GtkWidget *cache_limit_label;
+
+ GtkWidget *swap_meter;
+ GtkWidget *swap_occupied_label;
+ GtkWidget *swap_occupied_pct_label;
+ GtkWidget *swap_size_label;
+ GtkWidget *swap_size_pct_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;
+};
+
+struct _GimpDashboardClass
+{
+ GimpEditorClass parent_class;
+};
+
+
+GType gimp_dashboard_get_type (void) G_GNUC_CONST;
+
+GtkWidget * gimp_dashboard_new (Gimp *gimp,
+ GimpMenuFactory *menu_factory);
+
+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);
+
+
+#endif /* __GIMP_DASHBOARD_H__ */
diff --git a/app/widgets/gimphelp-ids.h b/app/widgets/gimphelp-ids.h
index b3b8aeec08..f8cec3142e 100644
--- a/app/widgets/gimphelp-ids.h
+++ b/app/widgets/gimphelp-ids.h
@@ -662,6 +662,11 @@
#define GIMP_HELP_SAMPLE_POINT_DIALOG "gimp-sample-point-dialog"
#define GIMP_HELP_SAMPLE_POINT_SAMPLE_MERGED "gimp-sample-point-sample-merged"
+#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_LOW_SWAP_SPACE_WARNING "gimp-dashboard-low-swap-space-warning"
+
#define GIMP_HELP_DOCK "gimp-dock"
#define GIMP_HELP_DOCK_CLOSE "gimp-dock-close"
#define GIMP_HELP_DOCK_IMAGE_MENU "gimp-dock-image-menu"
diff --git a/app/widgets/widgets-enums.h b/app/widgets/widgets-enums.h
index 3443a6d72f..74ae105379 100644
--- a/app/widgets/widgets-enums.h
+++ b/app/widgets/widgets-enums.h
@@ -306,5 +306,23 @@ typedef enum /*< skip >*/
GIMP_DIALOGS_HIDDEN_WITH_DISPLAY /* dialogs are hidden with the display */
} GimpDialogsState;
+typedef enum /*< skip >*/
+{
+ GIMP_DASHBOARD_UPDATE_INTERVAL_0_25_SEC = 250,
+ GIMP_DASHBOARD_UPDATE_INTERVAL_0_5_SEC = 500,
+ GIMP_DASHBOARD_UPDATE_INTERVAL_1_SEC = 1000,
+ GIMP_DASHBOARD_UPDATE_INTERVAL_2_SEC = 2000,
+ GIMP_DASHBOARD_UPDATE_INTERVAL_4_SEC = 4000
+} GimpDashboardUpdateInteval;
+
+typedef enum /*< skip >*/
+{
+ GIMP_DASHBOARD_HISTORY_DURATION_15_SEC = 15000,
+ GIMP_DASHBOARD_HISTORY_DURATION_30_SEC = 30000,
+ GIMP_DASHBOARD_HISTORY_DURATION_60_SEC = 60000,
+ GIMP_DASHBOARD_HISTORY_DURATION_120_SEC = 120000,
+ GIMP_DASHBOARD_HISTORY_DURATION_240_SEC = 240000
+} GimpDashboardHistoryDuration;
+
#endif /* __WIDGETS_ENUMS_H__ */
diff --git a/app/widgets/widgets-types.h b/app/widgets/widgets-types.h
index 63a6fe5ca0..30f79c5c2f 100644
--- a/app/widgets/widgets-types.h
+++ b/app/widgets/widgets-types.h
@@ -57,6 +57,7 @@ typedef struct _GimpDeviceStatus GimpDeviceStatus;
typedef struct _GimpEditor GimpEditor;
typedef struct _GimpErrorConsole GimpErrorConsole;
typedef struct _GimpToolOptionsEditor GimpToolOptionsEditor;
+typedef struct _GimpDashboard GimpDashboard;
/* GimpDataEditor widgets */
diff --git a/icons/Color/16/gimp-dashboard.png b/icons/Color/16/gimp-dashboard.png
new file mode 100644
index 0000000000..2c2981b382
Binary files /dev/null and b/icons/Color/16/gimp-dashboard.png differ
diff --git a/icons/Color/24/gimp-dashboard.png b/icons/Color/24/gimp-dashboard.png
new file mode 100644
index 0000000000..e4e6af1b35
Binary files /dev/null and b/icons/Color/24/gimp-dashboard.png differ
diff --git a/icons/Color/color-scalable.svg b/icons/Color/color-scalable.svg
index 678fca92a9..df03c1e982 100644
--- a/icons/Color/color-scalable.svg
+++ b/icons/Color/color-scalable.svg
@@ -61,8 +61,8 @@
inkscape:window-maximized="1"
inkscape:window-y="24"
inkscape:window-x="65"
- inkscape:cy="181.50558"
- inkscape:cx="960.06476"
+ inkscape:cy="117.27625"
+ inkscape:cx="757.84583"
inkscape:zoom="1"
showgrid="true"
id="namedview88"
@@ -40418,7 +40418,7 @@
inkscape:r_cy="true"
inkscape:r_cx="true"
id="path4926"
- d="M 7.8738374,1044.3622 C 6.8302869,1044.4246 6,1045.2489 6,1046.2491 c 0,0.039 0.00388,0.075 0.00629,0.1131 h 3.9874254 c 0.00241,-0.038 0.00629,-0.074 0.00629,-0.1131 0,-1.0409 -0.8967429,-1.8869 -2.0000024,-1.8869 -0.043099,0 -0.083767,0 -0.1261851,0 z"
+ d="M 7.8738374,1044.3622 C 6.8302869,1044.4246 6,1045.2489 6,1046.2491 c 0,0.039 0.00388,0.075 0.00629,0.1131 h 3.9874254 c 0.00241,-0.038 0.00629,-0.074 0.00629,-0.1131 0,-1.0409 -0.8967381,-1.8869 -1.9999976,-1.8869 -0.043099,0 -0.083767,0 -0.1261851,0 z"
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:1;fill:#fffbd7;fill-opacity:0.55681817;fill-rule:evenodd;stroke:none;stroke-width:1.01903164;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
inkscape:connector-curvature="0" />
@@ -50746,6 +50746,48 @@
id="rect52867"
style="fill:none;fill-rule:evenodd;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/icons/Symbolic/16/gimp-dashboard.png b/icons/Symbolic/16/gimp-dashboard.png
new file mode 100644
index 0000000000..8767fa952b
Binary files /dev/null and b/icons/Symbolic/16/gimp-dashboard.png differ
diff --git a/icons/Symbolic/24/gimp-dashboard.png b/icons/Symbolic/24/gimp-dashboard.png
new file mode 100644
index 0000000000..02885cb261
Binary files /dev/null and b/icons/Symbolic/24/gimp-dashboard.png differ
diff --git a/icons/Symbolic/scalable/gimp-dashboard.svg b/icons/Symbolic/scalable/gimp-dashboard.svg
new file mode 100644
index 0000000000..1a4116d921
--- /dev/null
+++ b/icons/Symbolic/scalable/gimp-dashboard.svg
@@ -0,0 +1,102 @@
+
+
+
+
diff --git a/icons/Symbolic/symbolic-scalable.svg b/icons/Symbolic/symbolic-scalable.svg
index b3beafd493..cd1daa6a9c 100644
--- a/icons/Symbolic/symbolic-scalable.svg
+++ b/icons/Symbolic/symbolic-scalable.svg
@@ -49,13 +49,13 @@
inkscape:window-height="876"
id="namedview88"
showgrid="true"
- inkscape:zoom="2"
- inkscape:cx="1093.8358"
- inkscape:cy="133.58911"
+ inkscape:zoom="1"
+ inkscape:cx="713.21137"
+ inkscape:cy="113.29003"
inkscape:window-x="65"
inkscape:window-y="24"
inkscape:window-maximized="1"
- inkscape:current-layer="stock"
+ inkscape:current-layer="svg7384"
showborder="false"
inkscape:snap-nodes="true"
inkscape:snap-bbox="true"
@@ -25937,7 +25937,7 @@
y="1036.3622" />
@@ -28400,19 +28400,19 @@
inkscape:connector-curvature="0" />
@@ -28434,7 +28434,7 @@
inkscape:connector-curvature="0"
id="rect6886"
transform="translate(241.0002,217)"
- d="m -179,283 0,14 14,0 0,-14 z m 1,1 12,0 0,12 -12,0 z"
+ d="m -179,283 v 14 h 14 v -14 z m 1,1 h 12 v 12 h -12 z"
style="fill:url(#linearGradient7639);fill-opacity:1;stroke:none" />
@@ -29316,16 +29316,16 @@
inkscape:connector-curvature="0"
id="path8303"
transform="translate(241.0002,217)"
- d="m -96.5,389 c -1.933,0 -3.5,1.567 -3.5,3.5 0,1.933 1.567,3.5 3.5,3.5 1.765268,0 3.228659,-1.301 3.46875,-3 0.01078,3.4e-4 0.02039,0 0.03125,0 l 2,0 c 0.01086,0 0.02047,3.4e-4 0.03125,0 0.240091,1.699 1.703482,3 3.46875,3 1.933,0 3.5,-1.567 3.5,-3.5 0,-1.933 -1.567,-3.5 -3.5,-3.5 -1.424592,0 -2.641241,0.84103 -3.1875,2.0625 C -90.789453,391.02764 -90.885941,391 -91,391 l -2,0 c -0.114059,0 -0.210547,0.0276 -0.3125,0.0625 C -93.858759,389.84103 -95.075408,389 -96.5,389 Z m 0.0625,1.40625 c 1.17613,0 2.125,0.93497 2.125,2.09375 0,1.15878 -0.94887,2.09375 -2.125,2.09375 -1.17613,0 -2.125,-0.93497 -2.125,-2.09375 0,-1.15878 0.94887,-2.09375 2.125,-2.09375 z m 9,0 c 1.17613,0 2.125,0.93497 2.125,2.09375 0,1.15878 -0.94887,2.09375 -2.125,2.09375 -1.17613,0 -2.125,-0.93497 -2.125,-2.09375 0,-1.15878 0.94887,-2.09375 2.125,-2.09375 z"
+ d="m -96.5,389 c -1.933,0 -3.5,1.567 -3.5,3.5 0,1.933 1.567,3.5 3.5,3.5 1.765268,0 3.228659,-1.301 3.46875,-3 0.01078,3.4e-4 0.02039,0 0.03125,0 h 2 c 0.01086,0 0.02047,3.4e-4 0.03125,0 0.240091,1.699 1.703482,3 3.46875,3 1.933,0 3.5,-1.567 3.5,-3.5 0,-1.933 -1.567,-3.5 -3.5,-3.5 -1.424592,0 -2.641241,0.84103 -3.1875,2.0625 C -90.789453,391.02764 -90.885941,391 -91,391 h -2 c -0.114059,0 -0.210547,0.0276 -0.3125,0.0625 C -93.858759,389.84103 -95.075408,389 -96.5,389 Z m 0.0625,1.40625 c 1.17613,0 2.125,0.93497 2.125,2.09375 0,1.15878 -0.94887,2.09375 -2.125,2.09375 -1.17613,0 -2.125,-0.93497 -2.125,-2.09375 0,-1.15878 0.94887,-2.09375 2.125,-2.09375 z m 9,0 c 1.17613,0 2.125,0.93497 2.125,2.09375 0,1.15878 -0.94887,2.09375 -2.125,2.09375 -1.17613,0 -2.125,-0.93497 -2.125,-2.09375 0,-1.15878 0.94887,-2.09375 2.125,-2.09375 z"
style="fill:url(#linearGradient7105);fill-opacity:1;stroke:none" />
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:Sans;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient7107);fill-opacity:1;stroke:none;stroke-width:1.00960875;marker:none;enable-background:accumulate" />
@@ -30007,24 +30007,24 @@
id="rect9174"
style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:1.78100002;marker:none;enable-background:new" />
@@ -30055,7 +30055,7 @@
inkscape:connector-curvature="0"
id="rect5523"
transform="translate(719.96895,404)"
- d="m -156,-22 c 0,0 0,0 0,2 l 0,12 c 0,2 -1,2 -1,2 l 1,0 c 0,0 1,0 1,-1 l 1,0 c 0,1 -1,1 -1,1 l 1,0 c 0,0 1,0 1,-1 l 6,0 c 0,1 -0.67515,1 -1,1 l 1,0 c 0,0 1,0 1,-1 l 1,0 c 0,1 -1,1 -1,1 l 1,0 c 0,0 1,0 1,-2 l 0,-12 c 0,-2 0,-2 0,-2 l -3,0 c 0,0 0,0 0,2 l 0,2 -6,0 0,-2 c 0,-2 0,-2 0,-2 z m 1,1 1,0 0,1 -1,0 z m 9,0 1,0 0,1 -1,0 z m -9,2 1,0 0,1 -1,0 z m 9,0 1,0 0,1 -1,0 z m -9,2 1,0 0,1 -1,0 z m 2,0 6,0 0,4 -6,0 z m 7,0 1,0 0,1 -1,0 z m -9,2 1,0 0,1 -1,0 z m 9,0 1,0 0,1 -1,0 z m -9,2 1,0 0,1 -1,0 z m 9,0 1,0 0,1 -1,0 z m -7,1 6,0 0,4 -6,0 z m -2,1 1,0 0,1 -1,0 z m 9,0 1,0 0,1 -1,0 z m -9,2 1,0 0,1 -1,0 z m 9,0 1,0 0,1 -1,0 z"
+ d="m -156,-22 c 0,0 0,0 0,2 v 12 c 0,2 -1,2 -1,2 h 1 c 0,0 1,0 1,-1 h 1 c 0,1 -1,1 -1,1 h 1 c 0,0 1,0 1,-1 h 6 c 0,1 -0.67515,1 -1,1 h 1 c 0,0 1,0 1,-1 h 1 c 0,1 -1,1 -1,1 h 1 c 0,0 1,0 1,-2 v -12 c 0,-2 0,-2 0,-2 h -3 c 0,0 0,0 0,2 v 2 h -6 v -2 c 0,-2 0,-2 0,-2 z m 1,1 h 1 v 1 h -1 z m 9,0 h 1 v 1 h -1 z m -9,2 h 1 v 1 h -1 z m 9,0 h 1 v 1 h -1 z m -9,2 h 1 v 1 h -1 z m 2,0 h 6 v 4 h -6 z m 7,0 h 1 v 1 h -1 z m -9,2 h 1 v 1 h -1 z m 9,0 h 1 v 1 h -1 z m -9,2 h 1 v 1 h -1 z m 9,0 h 1 v 1 h -1 z m -7,1 h 6 v 4 h -6 z m -2,1 h 1 v 1 h -1 z m 9,0 h 1 v 1 h -1 z m -9,2 h 1 v 1 h -1 z m 9,0 h 1 v 1 h -1 z"
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient7027);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.50793636;marker:none;enable-background:new" />
@@ -30090,7 +30090,7 @@
inkscape:connector-curvature="0"
id="rect6573-9"
transform="translate(241.0002,217)"
- d="m -59,263 0,14 14,0 0,-14 z m 1,1 12,0 0,12 -12,0 z"
+ d="m -59,263 v 14 h 14 v -14 z m 1,1 h 12 v 12 h -12 z"
style="fill:#bebebe;fill-opacity:1;stroke:url(#linearGradient7611)" />
@@ -30188,19 +30188,19 @@
sodipodi:nodetypes="csssssssc"
inkscape:connector-curvature="0"
id="rect3940-5"
- d="m 87.355,510.36221 202.14715,0 c 0.19667,0 0.355,0.15833 0.355,0.355 l 0,211.29 c 0,0.19667 -0.15833,0.355 -0.355,0.355 l -202.14715,0 c -0.19667,0 -0.227971,-0.24605 -0.355,-0.355 -53.380966,-45.78312 -59.452394,-145.14974 0,-211.29 0.111874,-0.12446 0.515473,-10.71214 0.355,-0.355 z"
+ d="m 87.355,510.36221 h 202.14715 c 0.19667,0 0.355,0.15833 0.355,0.355 v 211.29 c 0,0.19667 -0.15833,0.355 -0.355,0.355 H 87.355 c -0.19667,0 -0.227971,-0.24605 -0.355,-0.355 -53.380966,-45.78312 -59.452394,-145.14974 0,-211.29 0.111874,-0.12446 0.515473,-10.71214 0.355,-0.355 z"
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.13499999;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
@@ -30208,7 +30208,7 @@
sodipodi:nodetypes="cssssccacc"
inkscape:connector-curvature="0"
id="rect3956"
- d="m 244.06687,58.36454 6.61554,0 c 0.0327,0 0.0591,0.026 0.0591,0.059 l 0,0.2705 c 0,0.033 -0.0264,0.059 -0.0591,0.059 l -6.4577,0.063 c 1.55084,0.036 0.0988,-0.059 0.0988,-0.059 0,0 -0.8257,-0.1199 -0.75762,-0.3967 0.0399,-0.1622 1.28905,0.099 0.50103,0 z"
+ d="m 244.06687,58.36454 h 6.61554 c 0.0327,0 0.0591,0.026 0.0591,0.059 v 0.2705 c 0,0.033 -0.0264,0.059 -0.0591,0.059 l -6.4577,0.063 c 1.55084,0.036 0.0988,-0.059 0.0988,-0.059 0,0 -0.8257,-0.1199 -0.75762,-0.3967 0.0399,-0.1622 1.28905,0.099 0.50103,0 z"
style="opacity:1;fill:#464646;fill-opacity:1;stroke:none;stroke-width:0.12168574;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
@@ -31622,7 +31622,7 @@
@@ -31630,7 +31630,7 @@
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path5241-1"
- d="m 9,1049.3622 0,-6 -6,3 z"
+ d="m 9,1049.3622 v -6 l -6,3 z"
style="fill:url(#linearGradient7915);fill-opacity:1;stroke:none;stroke-width:0.95650649" />
@@ -31657,7 +31657,7 @@
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path5241-2"
- d="m 9,1049.3622 0,-6 -6,3 z"
+ d="m 9,1049.3622 v -6 l -6,3 z"
style="fill:url(#linearGradient7819);fill-opacity:1;stroke:none;stroke-width:0.95650649" />
@@ -31805,7 +31805,7 @@
transform="matrix(0.85714286,0,0,0.79876989,-35.143029,529.1679)">
@@ -31813,14 +31813,14 @@
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path6938-4"
- d="m 41.0002,643.99184 4.666667,-4.01491 0,7.51155 z"
+ d="m 41.0002,643.99184 4.666667,-4.01491 v 7.51155 z"
style="fill:url(#linearGradient7813);fill-opacity:1;stroke:none;stroke-width:0.9689911" />
+ d="m 10.1,1041.2122 v -3.85 H 5.9 v 3.85 l 2.1,2.1 z m -5.25,1.05 H 1 v 4.2 h 3.85 l 2.1,-2.1 z m 1.05,5.25 v 3.85 h 4.2 v -3.85 l -2.1,-2.1 z m 5.25,-5.25 -2.1,2.1 2.1,2.1 H 15 v -4.2 z" />
+ transform="rotate(-90,-408.42234,362.03324)">
+ transform="rotate(90,660.93004,650.67506)">
+ transform="rotate(90,631.9265,679.0817)">
+ transform="rotate(180,160.09574,521.0536)">
@@ -34312,7 +34312,7 @@
inkscape:connector-curvature="0"
id="rect6791-5"
transform="matrix(0,0.6666668,-0.6666668,0,77.000215,619.33333)"
- d="M 7,3 C 5.3380003,3 4,4.3380003 4,6 L 3.996488,9.9999947 H 6.9938647 L 7,7.5 C 7.0020394,6.6690027 7.6690002,6 8.5,6 h 6 C 15.331,6 16,6.6690002 16,7.5 l -0.014,2.4999947 h 2.997377 L 19,6 C 19.006909,4.3380147 17.662,3 16,3 Z M 3.996488,13.999995 4,18 c 0.00146,1.661999 1.3380003,3 3,3 h 9 c 1.662,0 3,-1.338 3,-3 l -0.01663,-4.000005 H 15.985995 L 16,16.5 c 0.0047,0.830987 -0.669,1.5 -1.5,1.5 h -6 C 7.6690002,18 7,17.331 7,16.5 l -0.00614,-2.500005 z"
+ d="M 7,3 C 5.3380003,3 4,4.3380003 4,6 L 3.996488,9.9999947 H 6.9938647 L 7,7.5 C 7.0020394,6.6690027 7.6690002,6 8.5,6 h 6 C 15.331,6 16,6.6690002 16,7.5 l -0.014,2.4999947 h 2.997377 L 19,6 C 19.006909,4.3380147 17.662,3 16,3 Z M 3.996488,13.999995 4,18 c 0.00146,1.661999 1.3380003,3 3,3 h 9 c 1.662,0 3,-1.338 3,-3 L 18.98337,13.999995 H 15.985995 L 16,16.5 c 0.0047,0.830987 -0.669,1.5 -1.5,1.5 h -6 C 7.6690002,18 7,17.331 7,16.5 L 6.99386,13.999995 Z"
style="fill:url(#linearGradient9944);fill-opacity:1;stroke:none;stroke-width:1.49999964"
sodipodi:nodetypes="ssccssssccssscssssccsssscc" />
@@ -34357,7 +34357,7 @@
transform="matrix(1.4999997,0,0,1.4999997,-91.500275,99.36239)">
@@ -34370,7 +34370,7 @@
sodipodi:nodetypes="cccccccc"
inkscape:connector-curvature="0"
id="path12078-82"
- d="m 14,1039.3622 5,6.0352 -5,5.9648 0,-4.041 c -1.332094,-0.029 -9,0.041 -9,0.041 l 0,-4 c 0,0 7.667576,0.01 9,0.019 z"
+ d="m 14,1039.3622 5,6.0352 -5,5.9648 v -4.041 c -1.332094,-0.029 -9,0.041 -9,0.041 v -4 c 0,0 7.667576,0.01 9,0.019 z"
style="fill:url(#linearGradient9998);fill-opacity:1;stroke:none;stroke-width:1.20939934" />
@@ -34448,7 +34448,7 @@
Use the swatch paletteto change color globally
+ d="m 0.79999995,1037.16 v 14.4 H 15.2 v -14.4 H 0.79999995 m 1.02857145,1.0286 H 14.171429 v 12.3428 H 1.8285714 v -12.3428" />
+ d="m 3,1039.36 h 10 v 10 H 3 Z" />
+ d="m 4,1040.36 h 8 v 8 H 4 Z" />
+ d="m 5,1041.36 h 6 v 6 H 5 Z" />
+ d="m 6,1042.36 h 4 v 4 H 6 Z" />
+ d="m 7,1043.36 h 2 v 2 H 7 Z" />
+ d="m 7.5,1043.86 h 1 v 1 h -1 z" />
@@ -34724,13 +34724,13 @@
sodipodi:nodetypes="sccscsccsccccs"
inkscape:connector-curvature="0"
id="rect33604-9"
- d="m 20,1048.3682 c 0,0.8275 -0.566618,1.494 -1.394165,1.494 l 0,0 c -0.827546,0 -1.577479,-0.2327 -1.577479,-1.0603 l -0.02799,-13.423 L 3.5,1035.3455 c -0.8275538,0 -1.3582674,-1.1199 -1.3582674,-1.9474 L 2.1,1034.5788 c 0,-0.8275 0.5724523,-2.2151 1.4,-2.2166 l 15.105835,-0.027 0,0.027 c 0.827547,0 1.494165,0.2083 1.494165,1.0359 l -0.1,0 z"
+ d="m 20,1048.3682 c 0,0.8275 -0.566618,1.494 -1.394165,1.494 v 0 c -0.827546,0 -1.577479,-0.2327 -1.577479,-1.0603 l -0.02799,-13.423 L 3.5,1035.3455 c -0.8275538,0 -1.3582674,-1.1199 -1.3582674,-1.9474 L 2.1,1034.5788 c 0,-0.8275 0.5724523,-2.2151 1.4,-2.2166 l 15.105835,-0.027 v 0.027 c 0.827547,0 1.494165,0.2083 1.494165,1.0359 H 20 Z"
style="opacity:1;fill:url(#linearGradient8049);fill-opacity:1;stroke:none;stroke-width:1.4970088" />
@@ -34839,7 +34839,7 @@
sodipodi:nodetypes="sccccsccccccccccccccccccssccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
inkscape:connector-curvature="0"
id="path2-5"
- d="m 10.580078,1042.3661 c -0.318412,-10e-5 -1.0595543,0 -1.580078,0 l 0,1.9643 2,0 0,-1.9682 c -0.06781,0 -0.353208,0 -0.419922,0 z m 2.419922,0.01 0,1.9623 2,0 0,-1.9584 c -0.390555,-7e-4 -1.629665,0 -2,0 z m -6,0 c -0.7571058,0 -1.3966717,0 -2,0.01 l 0,1.9545 2,0 z m 10,0.01 0,1.9545 2,0 0,-1.9506 c -0.442413,-9e-4 -1.523571,0 -2,0 z m -14,0.01 c -1.2278557,0 -1.0749419,0 -3,0.01 l 0.00390625,7.9627 c 4.8801e-4,1.095 -0.14951124,1.9975 1.49999995,1.9975 l 20.9921878,0 c 1.649511,0 1.499512,-0.9022 1.5,-1.9975 L 24,1042.3934 c -1.940993,0 -2.066277,0 -3,-0.01 l 0,1.9467 2,0 0,2.0268 -2,0 0,-1.9975 -2,0 0,1.9975 -2,0 0,-1.9975 -2,0 0,1.9975 -2,0 0,-1.9975 -2,0 0,1.9975 -2,0 0,-1.9975 -2,0 0,1.9975 -2,0 0,-1.9975 -2,0 0,1.9975 -2,0 0,-2.0268 2,0 z m 0,4.9742 2,0 0,1.9975 -2,0 z m 4,0 2,0 0,1.9975 -2,0 z m 4,0 2,0 0,1.9975 -2,0 z m 4,0 2,0 0,1.9975 -2,0 z m 4,0 2,0 0,1.9975 -2,0 z"
+ d="m 10.580078,1042.3661 c -0.318412,-10e-5 -1.0595543,0 -1.580078,0 v 1.9643 h 2 v -1.9682 c -0.06781,0 -0.353208,0 -0.419922,0 z M 13,1042.3761 v 1.9623 h 2 v -1.9584 c -0.390555,-7e-4 -1.629665,0 -2,0 z m -6,0 c -0.7571058,0 -1.3966717,0 -2,0.01 v 1.9545 h 2 z m 10,0.01 v 1.9545 h 2 v -1.9506 c -0.442413,-9e-4 -1.523571,0 -2,0 z m -14,0.01 c -1.2278557,0 -1.0749419,0 -3,0.01 l 0.00390625,7.9627 c 4.8801e-4,1.095 -0.14951124,1.9975 1.49999995,1.9975 H 22.496094 c 1.649511,0 1.499512,-0.9022 1.5,-1.9975 L 24,1042.3934 c -1.940993,0 -2.066277,0 -3,-0.01 v 1.9467 h 2 v 2.0268 h -2 v -1.9975 h -2 v 1.9975 h -2 v -1.9975 h -2 v 1.9975 h -2 v -1.9975 h -2 v 1.9975 H 9 v -1.9975 H 7 v 1.9975 H 5 v -1.9975 H 3 v 1.9975 H 1 v -2.0268 h 2 z m 0,4.9742 h 2 v 1.9975 H 3 Z m 4,0 h 2 v 1.9975 H 7 Z m 4,0 h 2 v 1.9975 h -2 z m 4,0 h 2 v 1.9975 h -2 z m 4,0 h 2 v 1.9975 h -2 z"
style="fill:url(#linearGradient8248);fill-opacity:1;stroke-width:1.22178757" />
+ transform="rotate(44.999999)" />
@@ -35513,7 +35513,7 @@
id="gimp-tool-rotate-24">
@@ -35556,7 +35556,7 @@
style="fill:none;stroke:none;stroke-width:1.5" />
@@ -35564,13 +35564,13 @@
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path11889-0"
- d="m 15,1038.8622 -6,-4.5 0,9 z"
+ d="m 15,1038.8622 -6,-4.5 v 9 z"
style="fill:url(#linearGradient7924-7);fill-opacity:1;stroke:none;stroke-width:1.5" />
@@ -35775,7 +35775,7 @@
sodipodi:nodetypes="cccccccc"
inkscape:connector-curvature="0"
style="fill:url(#linearGradient8868);fill-opacity:1;stroke-width:1.22687316"
- d="m 3.8515434,1041.7655 8.6774936,0 0,2.5967 3.47095,-3.0296 -3.47095,-3.0295 0,2.5968 -8.6774936,0 z"
+ d="m 3.8515434,1041.7655 h 8.6774936 v 2.5967 l 3.47095,-3.0296 -3.47095,-3.0295 v 2.5968 H 3.8515434 Z"
id="path15603-2" />
@@ -35833,12 +35833,12 @@
transform="matrix(-0.99633454,0,0,0.99853616,77.670479,383.24872)">
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:Sans;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient8922);fill-opacity:1;stroke:none;stroke-width:2;marker:none;enable-background:new" />
@@ -35848,14 +35848,14 @@
transform="matrix(1.1428571,0,0,1.1347519,-155.28595,604.26997)">
@@ -35881,14 +35881,14 @@
@@ -36040,20 +36040,20 @@
@@ -36077,14 +36077,14 @@
y="1028.3622" />
@@ -36164,7 +36164,7 @@
transform="matrix(1.5,0,0,1.4998125,6.922215,-1558.8431)">
@@ -36174,7 +36174,7 @@
transform="matrix(-1.5,0,0,1.4998125,17.077785,-1558.8431)">
@@ -36184,7 +36184,7 @@
transform="matrix(0,1.5,-1.4998125,0,1582.8431,6.922215)">
@@ -36194,7 +36194,7 @@
transform="matrix(0,-1.5,-1.4998125,0,1582.8431,17.077785)">
@@ -36718,7 +36718,7 @@
sodipodi:nodetypes="cccccccccc"
inkscape:connector-curvature="0"
id="rect13095-4"
- d="m -6e-6,1028.3622 0,11 11,0 0,-11 z m 1.000006,1 9,0 0,9 -9,0 z"
+ d="m -6e-6,1028.3622 v 11 h 11 v -11 z m 1.000006,1 h 9 v 9 H 1 Z"
style="fill:url(#linearGradient10124-6);fill-opacity:1;stroke:none;stroke-width:1.57142842" />
@@ -36980,13 +36980,13 @@
+ d="M 0,1 V 1.5 2 H 1 V 1 Z M 2,1 V 2 H 3 V 1 Z M 4,1 V 2 H 5 V 1 Z M 6,1 V 2 H 7 V 1 Z M 8,1 V 2 H 9 V 1 Z m 2,0 v 1 h 1 V 1 Z m 2,0 v 1 h 1 V 1 Z m 2,0 v 1 h 1 V 1 Z m 2,0 v 1 h 1 V 1 Z m 2,0 v 1 h 1 V 1 Z m 2,0 v 1 h 1 V 1 Z m 2,0 v 1 h 1 V 1 Z M 0,3 V 4 H 1 V 3 Z m 22,0 v 1 h 1 V 3 Z M 0,5 V 6 H 1 V 5 Z m 22,0 v 1 h 1 V 5 Z M 0,7 V 8 H 1 V 7 Z m 22,0 v 1 h 1 V 7 Z M 0,9 v 1 H 1 V 9 Z m 22,0 v 1 h 1 V 9 Z M 0,11 v 1 h 1 v -1 z m 22,0 v 1 h 1 V 11 Z M 0,13 v 1 h 1 v -1 z m 22,0 v 1 h 1 V 13 Z M 0,15 v 1 h 1 v -1 z m 22,0 v 1 h 1 V 15 Z M 0,17 v 1 h 1 v -1 z m 22,0 v 1 h 1 V 17 Z M 0,19 v 1 h 1 v -1 z m 22,0 v 1 h 1 V 19 Z M 0,21 v 1 h 1 v -1 z m 22,0 v 1 h 1 V 21 Z M 0,23 v 1 h 1 v -1 z m 2,0 v 1 h 1 v -1 z m 2,0 v 1 h 1 v -1 z m 2,0 v 1 h 1 v -1 z m 2,0 v 1 h 1 v -1 z m 2,0 v 1 h 1 v -1 z m 2,0 v 1 h 1 v -1 z m 2,0 v 1 h 1 v -1 z m 2,0 v 1 h 1 v -1 z m 2,0 v 1 h 1 v -1 z m 2,0 v 1 h 1 v -1 z m 2,0 v 1 h 1 v -1 z"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#linearGradient9137);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.99992293;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
@@ -37098,17 +37098,17 @@
sodipodi:nodetypes="cccccccccccccc"
inkscape:connector-curvature="0"
id="path35057-7"
- d="m 14.389178,1028.3633 c -0.151229,-0.01 -0.303679,0.047 -0.459719,0.1826 -6.5592873,5.3793 -12.458361,11.509 -12.458361,14.4319 0.241569,1.3007 -0.3272751,0.8141 -0.3677745,2.1009 0.06973,0.4759 0.4610274,0.8117 0.8734645,0.7308 0.3265249,-0.064 1.3773744,-0.3168 1.471098,-0.9592 2.0884002,0.056 2.8378805,-2.4674 4.4592659,-4.4757 l 6.9877161,-10.8696 c 0.285128,-0.548 -0.05193,-1.1235 -0.50569,-1.1417 z m -8.5047859,8.7687 1.4710981,0 -2.9421961,4.3844 -1.471098,0 z"
+ d="m 14.389178,1028.3633 c -0.151229,-0.01 -0.303679,0.047 -0.459719,0.1826 -6.5592873,5.3793 -12.458361,11.509 -12.458361,14.4319 0.241569,1.3007 -0.3272751,0.8141 -0.3677745,2.1009 0.06973,0.4759 0.4610274,0.8117 0.8734645,0.7308 0.3265249,-0.064 1.3773744,-0.3168 1.471098,-0.9592 2.0884002,0.056 2.8378805,-2.4674 4.4592659,-4.4757 l 6.9877161,-10.8696 c 0.285128,-0.548 -0.05193,-1.1235 -0.50569,-1.1417 z m -8.5047859,8.7687 h 1.4710981 l -2.9421961,4.3844 h -1.471098 z"
style="display:inline;fill:url(#linearGradient7802-1);fill-opacity:1;stroke:none;stroke-width:1.46627092" />
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:Sans;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient8971);fill-opacity:1;stroke:none;stroke-width:1.00960875;marker:none;enable-background:accumulate" />
@@ -37492,7 +37492,7 @@
y="-2.6074218e-05" />
@@ -37510,7 +37510,7 @@
sodipodi:nodetypes="ssssssssssssssssss"
inkscape:connector-curvature="0"
id="rect18257-7"
- d="m 2.4843707,10.000007 c -1.3771948,0 -2.4843747,1.607175 -2.4843747,2.98437 l 0,8.531249 C -4e-6,22.892821 1.1071759,24 2.4843707,24 l 19.0312473,0 c 1.377195,0 2.484375,-1.107179 2.484375,-2.484374 l 0,-8.531249 c 0,-1.377195 -1.10718,-2.98437 -2.484375,-2.98437 z m 0.5156283,0.99999 18,0 c 1.377195,0 1.999999,0.622808 2,2.000003 l 4e-6,8 c 1e-6,1.377195 -0.622809,1.999996 -2.000004,1.999996 l -18,0 C 1.6228042,22.999996 1.0000009,22.377195 1.0000009,21 l 0,-8 c 0,-1.377195 0.6228033,-2.000003 1.9999981,-2.000003 z"
+ d="m 2.4843707,10.000007 c -1.3771948,0 -2.4843747,1.607175 -2.4843747,2.98437 v 8.531249 C -4e-6,22.892821 1.1071759,24 2.4843707,24 H 21.515618 c 1.377195,0 2.484375,-1.107179 2.484375,-2.484374 v -8.531249 c 0,-1.377195 -1.10718,-2.98437 -2.484375,-2.98437 z m 0.5156283,0.99999 h 18 c 1.377195,0 1.999999,0.622808 2,2.000003 l 4e-6,8 c 1e-6,1.377195 -0.622809,1.999996 -2.000004,1.999996 h -18 C 1.6228042,22.999996 1.0000009,22.377195 1.0000009,21 v -8 c 0,-1.377195 0.6228033,-2.000003 1.9999981,-2.000003 z"
style="fill:url(#linearGradient7818-5);fill-opacity:1;stroke:none" />
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:Sans;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient7816-5);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;marker:none;enable-background:accumulate"
+ d="m 8.5781217,5.9999994 h 4.2336223 0.688252 v 0 c 0.964114,0 3,-0.5218799 3,2.9999996 v 1.5 h 1.499999 V 7.4999992 c 0,0 0,-2.9999996 -2.999999,-2.9999996 -0.405765,0.012 -0.931872,-7.5e-4 -1.078125,0 H 11.999996 8.1960552 c -0.3674924,0 -2.5606602,0.349425 -1.4082013,-1.4999998 L 8.3953332,2.0000004e-7 6.3977444,0.0010502 4.8867751,2.9999998 c -0.8591473,2.0946447 0.3648945,2.9999996 1.9252063,2.9999996 0.4057649,-0.012 1.6198873,7.5e-4 1.7661403,0" />
@@ -37690,7 +37690,7 @@
y="599" />
@@ -37706,12 +37706,12 @@
@@ -37756,7 +37756,7 @@
y="-24.000004"
ry="1.4999998" />
+ d="m 11.9997,0.5 c -4.1243625,0 -7.5,3.37563 -7.5,7.5 0,2.37933 1.266882,4.35504 3,5.71875 V 17 H 7.5 9 h 6 1.5 -3e-4 v -3.28125 c 1.733118,-1.36371 3,-3.33942 3,-5.71875 0,-4.12437 -3.375638,-7.5 -7.5,-7.5 z m 0,3 c 2.503027,0 4.5,1.99698 4.5,4.5 0,1.673775 -0.892601,3.05682 -2.25,3.84375 l -0.75,0.46875 v 0.84375 L 13.5,14 h -3 l -3e-4,-0.84375 V 12.3125 l -0.75,-0.46875 C 8.3923005,11.05682 7.4997,9.673775 7.4997,8 c 0,-2.50302 1.9969725,-4.5 4.5,-4.5 z"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:Sans;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient10236-7);fill-opacity:1;stroke:none;stroke-width:2.00000024;marker:none;enable-background:accumulate" />
+ d="m 9,22 v 1 h 6 v -1 z"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:Sans;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient10230-3);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" />
+ d="m 7.5,18 v 3 h 9 v -3 z"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:Sans;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient10232-6);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" />
+ d="m 9.999999,23 v 1 h 4 v -1 z"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:Sans;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient10230-7);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;enable-background:accumulate" />
@@ -37877,7 +37877,7 @@
style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:2;marker:none;enable-background:accumulate" />
@@ -37899,20 +37899,20 @@
@@ -37991,8 +37991,8 @@
transform="translate(241.0002,217)" />
+ d="m 602.0002,301.99999 v 12 l 12.66667,10e-6 3.33333,-3.33333 v 0 -8.66668 z m 0.66667,0.66668 h 14.66666 V 310 h -3.33333 v 3.33333 h -11.33333 z"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:Sans;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;display:inline;overflow:visible;visibility:visible;fill:url(#linearGradient7901-6);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;enable-background:new" />
@@ -38149,7 +38149,7 @@
@@ -39072,6 +39072,22 @@
id="rect51745"
style="fill:none;fill-rule:evenodd;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/menus/dialogs-menuitems.xml b/menus/dialogs-menuitems.xml
index f7608bf45c..ad3c1c7021 100644
--- a/menus/dialogs-menuitems.xml
+++ b/menus/dialogs-menuitems.xml
@@ -31,4 +31,5 @@
+
diff --git a/po/POTFILES.in b/po/POTFILES.in
index fe15ef3c75..7cf35216d2 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -24,6 +24,7 @@ app/actions/colormap-commands.c
app/actions/context-actions.c
app/actions/context-commands.c
app/actions/cursor-info-actions.c
+app/actions/dashboard-actions.c
app/actions/data-commands.c
app/actions/debug-actions.c
app/actions/dialogs-actions.c
@@ -512,6 +513,7 @@ app/widgets/gimpcontrollerkeyboard.c
app/widgets/gimpcontrollerlist.c
app/widgets/gimpcontrollermouse.c
app/widgets/gimpcontrollerwheel.c
+app/widgets/gimpdashboard.c
app/widgets/gimpdataeditor.c
app/widgets/gimpdeviceeditor.c
app/widgets/gimpdeviceinfo.c