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" /> + + + + + + + + + + + + + + + + + GIMP Dashboard + + + + + + + + + + + + + + + image/svg+xml + + GIMP Dashboard + + + Ell + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + GIMP Dashboard + + + + + + + + image/svg+xml + + GIMP Dashboard + + + Ell + + + + + + + + + + + + + + + + + + + + + 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