From fb31765cbe33890f325a87015507364156741321 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:59:44 +0200 Subject: Adding upstream version 42.0. Signed-off-by: Daniel Baumann --- src/legacy/e_date.c | 215 +++++++++++ src/legacy/e_date.h | 15 + src/legacy/gsm_color_button.c | 859 ++++++++++++++++++++++++++++++++++++++++++ src/legacy/gsm_color_button.h | 77 ++++ src/legacy/meson.build | 16 + src/legacy/treeview.c | 289 ++++++++++++++ src/legacy/treeview.h | 43 +++ 7 files changed, 1514 insertions(+) create mode 100644 src/legacy/e_date.c create mode 100644 src/legacy/e_date.h create mode 100644 src/legacy/gsm_color_button.c create mode 100644 src/legacy/gsm_color_button.h create mode 100644 src/legacy/meson.build create mode 100644 src/legacy/treeview.c create mode 100644 src/legacy/treeview.h (limited to 'src/legacy') diff --git a/src/legacy/e_date.c b/src/legacy/e_date.c new file mode 100644 index 0000000..2697e89 --- /dev/null +++ b/src/legacy/e_date.c @@ -0,0 +1,215 @@ +/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +#include + +#include +#include + +#include + +#include "e_date.h" + +/* + all this code comes from evolution + - e-util.c + - message-list.c +*/ + + +static size_t e_strftime(char *s, size_t max, const char *fmt, const struct tm *tm) +{ +#ifdef HAVE_LKSTRFTIME + return strftime(s, max, fmt, tm); +#else + char *c, *ffmt, *ff; + size_t ret; + + ffmt = g_strdup(fmt); + ff = ffmt; + while ((c = strstr(ff, "%l")) != NULL) { + c[1] = 'I'; + ff = c; + } + + ff = ffmt; + while ((c = strstr(ff, "%k")) != NULL) { + c[1] = 'H'; + ff = c; + } + + ret = strftime(s, max, ffmt, tm); + g_free(ffmt); + return ret; +#endif +} + + +/** + * Function to do a last minute fixup of the AM/PM stuff if the locale + * and gettext haven't done it right. Most English speaking countries + * except the USA use the 24 hour clock (UK, Australia etc). However + * since they are English nobody bothers to write a language + * translation (gettext) file. So the locale turns off the AM/PM, but + * gettext does not turn on the 24 hour clock. Leaving a mess. + * + * This routine checks if AM/PM are defined in the locale, if not it + * forces the use of the 24 hour clock. + * + * The function itself is a front end on strftime and takes exactly + * the same arguments. + * + * TODO: Actually remove the '%p' from the fixed up string so that + * there isn't a stray space. + **/ + +static size_t e_strftime_fix_am_pm(char *s, size_t max, const char *fmt, const struct tm *tm) +{ + char buf[10]; + char *sp; + char *ffmt; + size_t ret; + + if (strstr(fmt, "%p")==NULL && strstr(fmt, "%P")==NULL) { + /* No AM/PM involved - can use the fmt string directly */ + ret=e_strftime(s, max, fmt, tm); + } else { + /* Get the AM/PM symbol from the locale */ + e_strftime (buf, 10, "%p", tm); + + if (buf[0]) { + /** + * AM/PM have been defined in the locale + * so we can use the fmt string directly + **/ + ret=e_strftime(s, max, fmt, tm); + } else { + /** + * No AM/PM defined by locale + * must change to 24 hour clock + **/ + ffmt=g_strdup(fmt); + for (sp=ffmt; (sp=strstr(sp, "%l")); sp++) { + /** + * Maybe this should be 'k', but I have never + * seen a 24 clock actually use that format + **/ + sp[1]='H'; + } + for (sp=ffmt; (sp=strstr(sp, "%I")); sp++) { + sp[1]='H'; + } + ret=e_strftime(s, max, ffmt, tm); + g_free(ffmt); + } + } + return(ret); +} + +static size_t +e_utf8_strftime_fix_am_pm(char *s, size_t max, const char *fmt, const struct tm *tm) +{ + size_t sz, ret; + char *locale_fmt, *buf; + + locale_fmt = g_locale_from_utf8(fmt, -1, NULL, &sz, NULL); + if (!locale_fmt) + return 0; + + ret = e_strftime_fix_am_pm(s, max, locale_fmt, tm); + if (!ret) { + g_free (locale_fmt); + return 0; + } + + buf = g_locale_to_utf8(s, ret, NULL, &sz, NULL); + if (!buf) { + g_free (locale_fmt); + return 0; + } + + if (sz >= max) { + char *tmp = buf + max - 1; + tmp = g_utf8_find_prev_char(buf, tmp); + if (tmp) + sz = tmp - buf; + else + sz = 0; + } + memcpy(s, buf, sz); + s[sz] = '\0'; + g_free(locale_fmt); + g_free(buf); + return sz; +} + + +static char * +filter_date (time_t date) +{ + time_t nowdate = time(NULL); + time_t yesdate; + struct tm then, now, yesterday; + char buf[26]; + gboolean done = FALSE; + + if (date == 0) + // xgettext: ? stands for unknown + return g_strdup (_("?")); + + localtime_r (&date, &then); + localtime_r (&nowdate, &now); + if (then.tm_mday == now.tm_mday && + then.tm_mon == now.tm_mon && + then.tm_year == now.tm_year) { + e_utf8_strftime_fix_am_pm (buf, 26, _("Today %l∶%M %p"), &then); + done = TRUE; + } + if (!done) { + yesdate = nowdate - 60 * 60 * 24; + localtime_r (&yesdate, &yesterday); + if (then.tm_mday == yesterday.tm_mday && + then.tm_mon == yesterday.tm_mon && + then.tm_year == yesterday.tm_year) { + e_utf8_strftime_fix_am_pm (buf, 26, _("Yesterday %l∶%M %p"), &then); + done = TRUE; + } + } + if (!done) { + int i; + for (i = 2; i < 7; i++) { + yesdate = nowdate - 60 * 60 * 24 * i; + localtime_r (&yesdate, &yesterday); + if (then.tm_mday == yesterday.tm_mday && + then.tm_mon == yesterday.tm_mon && + then.tm_year == yesterday.tm_year) { + e_utf8_strftime_fix_am_pm (buf, 26, _("%a %l∶%M %p"), &then); + done = TRUE; + break; + } + } + } + if (!done) { + if (then.tm_year == now.tm_year) { + e_utf8_strftime_fix_am_pm (buf, 26, _("%b %d %l∶%M %p"), &then); + } else { + e_utf8_strftime_fix_am_pm (buf, 26, _("%b %d %Y"), &then); + } + } +#if 0 +#ifdef CTIME_R_THREE_ARGS + ctime_r (&date, buf, 26); +#else + ctime_r (&date, buf); +#endif +#endif + + return g_strdup (buf); +} + + + + +char * +procman_format_date_for_display(time_t d) +{ + return filter_date(d); +} diff --git a/src/legacy/e_date.h b/src/legacy/e_date.h new file mode 100644 index 0000000..05ab097 --- /dev/null +++ b/src/legacy/e_date.h @@ -0,0 +1,15 @@ +/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +#ifndef _GSM_E_DATE_H_ +#define _GSM_E_DATE_H_ + +#include +#include + +G_BEGIN_DECLS + +char * +procman_format_date_for_display(time_t d); + +G_END_DECLS + +#endif /* _GSM_E_DATE_H_ */ diff --git a/src/legacy/gsm_color_button.c b/src/legacy/gsm_color_button.c new file mode 100644 index 0000000..02a8ad3 --- /dev/null +++ b/src/legacy/gsm_color_button.c @@ -0,0 +1,859 @@ +/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Gnome system monitor colour pickers + * Copyright (C) 2007 Karl Lattimer + * All rights reserved. + * + * This Library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This software 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 the software; see the file COPYING. If not, + * see . + */ + +#include + +#include +#include +#include + +#include "gsm_color_button.h" + +typedef struct +{ + GtkColorChooserDialog *cc_dialog; /* Color chooser dialog */ + + gchar *title; /* Title for the color selection window */ + + GdkRGBA color; + gdouble fraction; /* Only used by GSMCP_TYPE_PIE */ + guint type; + cairo_surface_t *image_buffer; + gdouble highlight; + gboolean button_down; + gboolean in_button; +} GsmColorButtonPrivate; + +G_DEFINE_TYPE_WITH_PRIVATE (GsmColorButton, gsm_color_button, GTK_TYPE_DRAWING_AREA); + +/* Properties */ +enum +{ + PROP_0, + PROP_PERCENTAGE, + PROP_TITLE, + PROP_COLOR, + PROP_TYPE, +}; + +/* Signals */ +enum +{ + COLOR_SET, + LAST_SIGNAL +}; + +#define GSMCP_MIN_WIDTH 15 +#define GSMCP_MIN_HEIGHT 15 + +static void gsm_color_button_class_init (GsmColorButtonClass * klass); +static void gsm_color_button_init (GsmColorButton * color_button); +static void gsm_color_button_finalize (GObject * object); +static void gsm_color_button_set_property (GObject * object, guint param_id, + const GValue * value, + GParamSpec * pspec); +static void gsm_color_button_get_property (GObject * object, guint param_id, + GValue * value, + GParamSpec * pspec); +static gboolean gsm_color_button_draw (GtkWidget *widget, + cairo_t *cr); +static void gsm_color_button_get_preferred_width (GtkWidget * widget, + gint * minimum, + gint * natural); +static void gsm_color_button_get_preferred_height (GtkWidget * widget, + gint * minimum, + gint * natural); +static gint gsm_color_button_pressed (GtkWidget * widget, + GdkEventButton * event); +static gint gsm_color_button_released (GtkWidget * widget, + GdkEventButton * event); +static gboolean gsm_color_button_enter_notify (GtkWidget * widget, + GdkEventCrossing * event); +static gboolean gsm_color_button_leave_notify (GtkWidget * widget, + GdkEventCrossing * event); +/* source side drag signals */ +static void gsm_color_button_drag_begin (GtkWidget * widget, + GdkDragContext * context, + gpointer data); +static void gsm_color_button_drag_data_get (GtkWidget * widget, + GdkDragContext * context, + GtkSelectionData * selection_data, + guint info, guint time, + GsmColorButton * color_button); + +/* target side drag signals */ +static void gsm_color_button_drag_data_received (GtkWidget * widget, + GdkDragContext * context, + gint x, + gint y, + GtkSelectionData * + selection_data, guint info, + guint32 time, + GsmColorButton * + color_button); + + +static guint color_button_signals[LAST_SIGNAL] = { 0 }; + +static const GtkTargetEntry drop_types[] = { {"application/x-color", 0, 0} }; + +static void +gsm_color_button_class_init (GsmColorButtonClass * klass) +{ + GObjectClass *gobject_class; + GtkWidgetClass *widget_class; + + gobject_class = G_OBJECT_CLASS (klass); + widget_class = GTK_WIDGET_CLASS (klass); + + gobject_class->get_property = gsm_color_button_get_property; + gobject_class->set_property = gsm_color_button_set_property; + gobject_class->finalize = gsm_color_button_finalize; + widget_class->draw = gsm_color_button_draw; + widget_class->get_preferred_width = gsm_color_button_get_preferred_width; + widget_class->get_preferred_height = gsm_color_button_get_preferred_height; + widget_class->button_release_event = gsm_color_button_released; + widget_class->button_press_event = gsm_color_button_pressed; + widget_class->enter_notify_event = gsm_color_button_enter_notify; + widget_class->leave_notify_event = gsm_color_button_leave_notify; + + g_object_class_install_property (gobject_class, + PROP_PERCENTAGE, + g_param_spec_double ("fraction", + _("Fraction"), + // TRANSLATORS: description of the pie color picker's (mem, swap) filled percentage property + _("Percentage full for pie color pickers"), + 0, 1, 0.5, + G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, + PROP_TITLE, + g_param_spec_string ("title", + _("Title"), + _("The title of the color selection dialog"), + _("Pick a Color"), + G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, + PROP_COLOR, + g_param_spec_boxed ("color", + _("Current Color"), + _("The selected color"), + GDK_TYPE_RGBA, + G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, + PROP_TYPE, + g_param_spec_uint ("type", _("Type"), + _("Type of color picker"), + 0, 4, 0, + G_PARAM_READWRITE)); + + color_button_signals[COLOR_SET] = g_signal_new ("color-set", + G_TYPE_FROM_CLASS + (gobject_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + + +static cairo_surface_t * +fill_image_buffer_from_resource (cairo_t *cr, const char *path) +{ + GBytes *bytes; + const guint8 *data; + gsize len; + GError *error = NULL; + RsvgHandle *handle; + cairo_surface_t *tmp_surface; + cairo_t *tmp_cr; + + bytes = g_resources_lookup_data (path, 0 , NULL); + data = g_bytes_get_data (bytes, &len); + + handle = rsvg_handle_new_from_data (data, len, &error); + + if (handle == NULL) { + g_warning("rsvg_handle_new_from_data(\"%s\") failed: %s", + path, (error ? error->message : "unknown error")); + if (error) + g_error_free(error); + g_bytes_unref(bytes); + return NULL; + } + + tmp_surface = cairo_surface_create_similar (cairo_get_target (cr), + CAIRO_CONTENT_COLOR_ALPHA, + 32, 32); + tmp_cr = cairo_create (tmp_surface); + rsvg_handle_render_cairo (handle, tmp_cr); + cairo_destroy (tmp_cr); + g_object_unref (handle); + g_bytes_unref(bytes); + return tmp_surface; +} + +static gboolean +gsm_color_button_draw (GtkWidget *widget, cairo_t * cr) +{ + GsmColorButton *color_button = GSM_COLOR_BUTTON (widget); + GsmColorButtonPrivate *priv = gsm_color_button_get_instance_private (color_button); + GdkRGBA *color = gdk_rgba_copy(&priv->color); + cairo_path_t *path = NULL; + gint width, height; + gdouble radius, arc_start, arc_end; + gdouble highlight_factor; + gboolean sensitive = gtk_widget_get_sensitive (widget); + + if (sensitive && priv->highlight > 0) { + highlight_factor = 0.125 * priv->highlight; + + color->red = MIN (1.0, color->red + highlight_factor); + + color->blue = MIN (1.0, color->blue + highlight_factor) ; + + color->green = MIN (1.0, color->green + highlight_factor); + } else if (!sensitive) { + GtkStyleContext *context = gtk_widget_get_style_context (widget); + gtk_style_context_get_color (context, gtk_widget_get_state_flags (widget), color); + } + gdk_cairo_set_source_rgba (cr, color); + gdk_rgba_free(color); + width = gdk_window_get_width (gtk_widget_get_window (widget)); + height = gdk_window_get_height(gtk_widget_get_window (widget)); + + switch (priv->type) + { + case GSMCP_TYPE_CPU: + //gtk_widget_set_size_request (widget, GSMCP_MIN_WIDTH, GSMCP_MIN_HEIGHT); + cairo_paint (cr); + cairo_set_line_width (cr, 1); + cairo_set_source_rgba (cr, 0, 0, 0, 0.5); + cairo_rectangle (cr, 0.5, 0.5, width - 1, height - 1); + cairo_stroke (cr); + cairo_set_line_width (cr, 1); + cairo_set_source_rgba (cr, 1, 1, 1, 0.4); + cairo_rectangle (cr, 1.5, 1.5, width - 3, height - 3); + cairo_stroke (cr); + break; + case GSMCP_TYPE_PIE: + if (width < 32) // 32px minimum size + gtk_widget_set_size_request (widget, 32, 32); + if (width < height) + radius = width / 2; + else + radius = height / 2; + + arc_start = -G_PI_2 + 2 * G_PI * priv->fraction; + arc_end = -G_PI_2; + + cairo_set_line_width (cr, 1); + + // Draw external stroke and fill + if (priv->fraction < 0.01) { + cairo_arc (cr, (width / 2) + .5, (height / 2) + .5, 4.5, + 0, 2 * G_PI); + } else if (priv->fraction > 0.99) { + cairo_arc (cr, (width / 2) + .5, (height / 2) + .5, radius - 2.25, + 0, 2 * G_PI); + } else { + cairo_arc_negative (cr, (width / 2) + .5, (height / 2) + .5, radius - 2.25, + arc_start, arc_end); + cairo_arc_negative (cr, (width / 2) + .5, (height / 2) + .5, 4.5, + arc_end, arc_start); + cairo_arc_negative (cr, (width / 2) + .5, (height / 2) + .5, radius - 2.25, + arc_start, arc_start); + } + cairo_fill_preserve (cr); + cairo_set_source_rgba (cr, 0, 0, 0, 0.7); + cairo_stroke (cr); + + // Draw internal highlight + cairo_set_source_rgba (cr, 1, 1, 1, 0.45); + cairo_set_line_width (cr, 1); + + if (priv->fraction < 0.03) { + cairo_arc (cr, (width / 2) + .5, (height / 2) + .5, 3.25, + 0, 2 * G_PI); + } else if (priv->fraction > 0.99) { + cairo_arc (cr, (width / 2) + .5, (height / 2) + .5, radius - 3.5, + 0, 2 * G_PI); + } else { + cairo_arc_negative (cr, (width / 2) + .5, (height / 2) + .5, radius - 3.5, + arc_start + (1 / (radius - 3.75)), + arc_end - (1 / (radius - 3.75))); + cairo_arc_negative (cr, (width / 2) + .5, (height / 2) + .5, 3.25, + arc_end - (1 / (radius - 3.75)), + arc_start + (1 / (radius - 3.75))); + cairo_arc_negative (cr, (width / 2) + .5, (height / 2) + .5, radius - 3.5, + arc_start + (1 / (radius - 3.75)), + arc_start + (1 / (radius - 3.75))); + } + cairo_stroke (cr); + + // Draw external shape + cairo_set_line_width (cr, 1); + cairo_set_source_rgba (cr, 0, 0, 0, 0.2); + cairo_arc (cr, (width / 2) + .5, (height / 2) + .5, radius - 1.25, 0, + G_PI * 2); + cairo_stroke (cr); + + break; + case GSMCP_TYPE_NETWORK_IN: + if (priv->image_buffer == NULL) + priv->image_buffer = + fill_image_buffer_from_resource (cr, "/org/gnome/gnome-system-monitor/pixmaps/download.svg"); + gtk_widget_set_size_request (widget, 32, 32); + cairo_move_to (cr, 8.5, 1.5); + cairo_line_to (cr, 23.5, 1.5); + cairo_line_to (cr, 23.5, 11.5); + cairo_line_to (cr, 29.5, 11.5); + cairo_line_to (cr, 16.5, 27.5); + cairo_line_to (cr, 15.5, 27.5); + cairo_line_to (cr, 2.5, 11.5); + cairo_line_to (cr, 8.5, 11.5); + cairo_line_to (cr, 8.5, 1.5); + cairo_close_path (cr); + path = cairo_copy_path (cr); + cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE); + cairo_set_line_join (cr, CAIRO_LINE_JOIN_MITER); + cairo_set_line_width (cr, 1); + cairo_fill_preserve (cr); + cairo_set_miter_limit (cr, 5.0); + cairo_stroke (cr); + cairo_set_source_rgba (cr, 0, 0, 0, 0.5); + cairo_append_path (cr, path); + cairo_path_destroy(path); + cairo_stroke (cr); + cairo_set_source_surface (cr, priv->image_buffer, 0.0, + 0.0); + cairo_paint (cr); + + break; + case GSMCP_TYPE_NETWORK_OUT: + if (priv->image_buffer == NULL) + priv->image_buffer = + fill_image_buffer_from_resource (cr, "/org/gnome/gnome-system-monitor/pixmaps/upload.svg"); + gtk_widget_set_size_request (widget, 32, 32); + cairo_move_to (cr, 16.5, 1.5); + cairo_line_to (cr, 29.5, 17.5); + cairo_line_to (cr, 23.5, 17.5); + cairo_line_to (cr, 23.5, 27.5); + cairo_line_to (cr, 8.5, 27.5); + cairo_line_to (cr, 8.5, 17.5); + cairo_line_to (cr, 2.5, 17.5); + cairo_line_to (cr, 15.5, 1.5); + cairo_line_to (cr, 16.5, 1.5); + cairo_close_path (cr); + path = cairo_copy_path (cr); + cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE); + cairo_set_line_join (cr, CAIRO_LINE_JOIN_MITER); + cairo_set_line_width (cr, 1); + cairo_fill_preserve (cr); + cairo_set_miter_limit (cr, 5.0); + cairo_stroke (cr); + cairo_set_source_rgba (cr, 0, 0, 0, 0.5); + cairo_append_path (cr, path); + cairo_path_destroy(path); + cairo_stroke (cr); + cairo_set_source_surface (cr, priv->image_buffer, 0.0, + 0.0); + cairo_paint (cr); + + break; + } + + return FALSE; +} + +static void +gsm_color_button_get_preferred_width (GtkWidget * widget, + gint * minimum, + gint * natural) +{ + if (minimum) + *minimum = GSMCP_MIN_WIDTH; + if (natural) + *natural = GSMCP_MIN_WIDTH; +} + +static void +gsm_color_button_get_preferred_height (GtkWidget * widget, + gint * minimum, + gint * natural) +{ + if (minimum) + *minimum = GSMCP_MIN_HEIGHT; + if (natural) + *natural = GSMCP_MIN_HEIGHT; +} + +static void +gsm_color_button_drag_data_received (GtkWidget * widget, + GdkDragContext * context, + gint x, + gint y, + GtkSelectionData * selection_data, + guint info, + guint32 time, + GsmColorButton * color_button) +{ + GsmColorButtonPrivate *priv = gsm_color_button_get_instance_private (color_button); + + gint length; + guint16 *dropped; + + length = gtk_selection_data_get_length (selection_data); + + if (length < 0) + return; + + /* We accept drops with the wrong format, since the KDE color + * chooser incorrectly drops application/x-color with format 8. + */ + if (length != 8) + { + g_warning (_("Received invalid color data\n")); + return; + } + + + dropped = (guint16 *) gtk_selection_data_get_data (selection_data); + + priv->color.red = (gdouble)dropped[0] / 0xffff; + priv->color.green = (gdouble)dropped[1] / 0xffff; + priv->color.blue = (gdouble)dropped[2] / 0xffff; + + gtk_widget_queue_draw (GTK_WIDGET (color_button)); + + g_signal_emit (color_button, color_button_signals[COLOR_SET], 0); + + g_object_freeze_notify (G_OBJECT (color_button)); + g_object_notify (G_OBJECT (color_button), "color"); + g_object_thaw_notify (G_OBJECT (color_button)); +} + + +static void +set_color_icon (GdkDragContext * context, GdkRGBA * color) +{ + GdkPixbuf *pixbuf; + guint32 pixel; + + pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, 48, 32); + + pixel = ((guint32)(color->red * 0xff) << 24) | + ((guint32)(color->green * 0xff) << 16) | + ((guint32)(color->blue * 0xff) << 8); + + gdk_pixbuf_fill (pixbuf, pixel); + + gtk_drag_set_icon_pixbuf (context, pixbuf, -2, -2); + g_object_unref (pixbuf); +} + +static void +gsm_color_button_drag_begin (GtkWidget * widget, + GdkDragContext * context, gpointer data) +{ + GsmColorButtonPrivate *priv = gsm_color_button_get_instance_private (GSM_COLOR_BUTTON (data)); + set_color_icon (context, &priv->color); +} + +static void +gsm_color_button_drag_data_get (GtkWidget * widget, + GdkDragContext * context, + GtkSelectionData * selection_data, + guint info, + guint time, GsmColorButton * color_button) +{ + GsmColorButtonPrivate *priv = gsm_color_button_get_instance_private (color_button); + guint16 dropped[4]; + + dropped[0] = priv->color.red * 0xffff; + dropped[1] = priv->color.green * 0xffff; + dropped[2] = priv->color.blue * 0xffff; + dropped[3] = 65535; // This widget doesn't care about alpha + + gtk_selection_data_set (selection_data, gtk_selection_data_get_target (selection_data), + 16, (guchar *) dropped, 8); +} + + +static void +gsm_color_button_init (GsmColorButton * color_button) +{ + GsmColorButtonPrivate *priv = gsm_color_button_get_instance_private (color_button); + + priv->color.red = 0; + priv->color.green = 0; + priv->color.blue = 0; + priv->fraction = 0.5; + priv->type = GSMCP_TYPE_CPU; + priv->image_buffer = NULL; + priv->title = g_strdup (_("Pick a Color")); /* default title */ + priv->in_button = FALSE; + priv->button_down = FALSE; + + gtk_drag_dest_set (GTK_WIDGET (color_button), + GTK_DEST_DEFAULT_MOTION | + GTK_DEST_DEFAULT_HIGHLIGHT | + GTK_DEST_DEFAULT_DROP, drop_types, 1, GDK_ACTION_COPY); + gtk_drag_source_set (GTK_WIDGET (color_button), + GDK_BUTTON1_MASK | GDK_BUTTON3_MASK, + drop_types, 1, GDK_ACTION_COPY); + g_signal_connect (color_button, "drag_begin", + G_CALLBACK (gsm_color_button_drag_begin), color_button); + g_signal_connect (color_button, "drag_data_received", + G_CALLBACK (gsm_color_button_drag_data_received), + color_button); + g_signal_connect (color_button, "drag_data_get", + G_CALLBACK (gsm_color_button_drag_data_get), + color_button); + + gtk_widget_add_events (GTK_WIDGET(color_button), GDK_ENTER_NOTIFY_MASK + | GDK_LEAVE_NOTIFY_MASK); + + gtk_widget_set_tooltip_text (GTK_WIDGET(color_button), _("Click to set graph colors")); +} + +static void +gsm_color_button_finalize (GObject * object) +{ + GsmColorButton *color_button = GSM_COLOR_BUTTON (object); + GsmColorButtonPrivate *priv = gsm_color_button_get_instance_private (color_button); + + if (priv->cc_dialog != NULL) + gtk_widget_destroy (GTK_WIDGET (priv->cc_dialog)); + priv->cc_dialog = NULL; + + g_free (priv->title); + priv->title = NULL; + + cairo_surface_destroy (priv->image_buffer); + priv->image_buffer = NULL; + + G_OBJECT_CLASS (gsm_color_button_parent_class)->finalize (object); +} + +GsmColorButton * +gsm_color_button_new (const GdkRGBA * color, guint type) +{ + return g_object_new (GSM_TYPE_COLOR_BUTTON, "color", color, "type", type, + "visible", TRUE, NULL); +} + +static void +dialog_response (GtkWidget * widget, GtkResponseType response, gpointer data) +{ + GsmColorButton *color_button = GSM_COLOR_BUTTON (data); + GsmColorButtonPrivate *priv = gsm_color_button_get_instance_private (color_button); + GtkColorChooser *color_chooser; + + if (response == GTK_RESPONSE_OK) { + color_chooser = GTK_COLOR_CHOOSER (priv->cc_dialog); + + gtk_color_chooser_get_rgba (color_chooser, &priv->color); + + gtk_widget_hide (GTK_WIDGET (priv->cc_dialog)); + + gtk_widget_queue_draw (GTK_WIDGET (color_button)); + + g_signal_emit (color_button, color_button_signals[COLOR_SET], 0); + + g_object_freeze_notify (G_OBJECT (color_button)); + g_object_notify (G_OBJECT (color_button), "color"); + g_object_thaw_notify (G_OBJECT (color_button)); + } + else /* (response == GTK_RESPONSE_CANCEL) */ + gtk_widget_hide (GTK_WIDGET (priv->cc_dialog)); +} + +static gboolean +dialog_destroy (GtkWidget * widget, gpointer data) +{ + GsmColorButtonPrivate *priv = gsm_color_button_get_instance_private (GSM_COLOR_BUTTON (data)); + + priv->cc_dialog = NULL; + + return FALSE; +} + +static gint +gsm_color_button_clicked (GtkWidget * widget, GdkEventButton * event) +{ + GsmColorButton *color_button = GSM_COLOR_BUTTON (widget); + GsmColorButtonPrivate *priv = gsm_color_button_get_instance_private (color_button); + + /* if dialog already exists, make sure it's shown and raised */ + if (!priv->cc_dialog) + { + /* Create the dialog and connects its buttons */ + GtkColorChooserDialog *cc_dialog; + GtkWidget *parent; + + parent = gtk_widget_get_toplevel (GTK_WIDGET (color_button)); + if (!gtk_widget_is_toplevel (parent)) + parent = NULL; + + cc_dialog = GTK_COLOR_CHOOSER_DIALOG (gtk_color_chooser_dialog_new (priv->title, GTK_WINDOW (parent))); + + gtk_window_set_modal (GTK_WINDOW (cc_dialog), TRUE); + + g_signal_connect (cc_dialog, "response", + G_CALLBACK (dialog_response), color_button); + + g_signal_connect (cc_dialog, "destroy", + G_CALLBACK (dialog_destroy), color_button); + + priv->cc_dialog = cc_dialog; + } + + gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (priv->cc_dialog), + &priv->color); + + gtk_window_present (GTK_WINDOW (priv->cc_dialog)); + return 0; +} + +static gint +gsm_color_button_pressed (GtkWidget * widget, GdkEventButton * event) +{ + GsmColorButtonPrivate *priv = gsm_color_button_get_instance_private (GSM_COLOR_BUTTON (widget)); + + if ((event->type == GDK_BUTTON_PRESS) && (event->button == 1)) + priv->button_down = TRUE; + return 0; +} + +static gint +gsm_color_button_released (GtkWidget * widget, GdkEventButton * event) +{ + GsmColorButtonPrivate *priv = gsm_color_button_get_instance_private (GSM_COLOR_BUTTON (widget)); + if (priv->button_down && priv->in_button) + gsm_color_button_clicked (widget, event); + priv->button_down = FALSE; + return 0; +} + + +static gboolean +gsm_color_button_enter_notify (GtkWidget * widget, GdkEventCrossing * event) +{ + GsmColorButtonPrivate *priv = gsm_color_button_get_instance_private (GSM_COLOR_BUTTON (widget)); + priv->highlight = 1.0; + priv->in_button = TRUE; + gtk_widget_queue_draw(widget); + return FALSE; +} + +static gboolean +gsm_color_button_leave_notify (GtkWidget * widget, GdkEventCrossing * event) +{ + GsmColorButtonPrivate *priv = gsm_color_button_get_instance_private (GSM_COLOR_BUTTON (widget)); + priv->highlight = 0; + priv->in_button = FALSE; + gtk_widget_queue_draw(widget); + return FALSE; +} + +guint +gsm_color_button_get_cbtype (GsmColorButton * color_button) +{ + GsmColorButtonPrivate *priv; + + g_return_val_if_fail (GSM_IS_COLOR_BUTTON (color_button), 0); + + priv = gsm_color_button_get_instance_private (color_button); + return priv->type; +} + +void +gsm_color_button_set_cbtype (GsmColorButton * color_button, guint type) +{ + GsmColorButtonPrivate *priv; + + g_return_if_fail (GSM_IS_COLOR_BUTTON (color_button)); + + priv = gsm_color_button_get_instance_private (color_button); + priv->type = type; + + gtk_widget_queue_draw (GTK_WIDGET (color_button)); + + g_object_notify (G_OBJECT (color_button), "type"); +} + +gdouble +gsm_color_button_get_fraction (GsmColorButton * color_button) +{ + GsmColorButtonPrivate *priv; + + g_return_val_if_fail (GSM_IS_COLOR_BUTTON (color_button), 0); + + priv = gsm_color_button_get_instance_private (color_button); + return priv->fraction; +} + +void +gsm_color_button_set_fraction (GsmColorButton * color_button, + gdouble fraction) +{ + GsmColorButtonPrivate *priv; + + g_return_if_fail (GSM_IS_COLOR_BUTTON (color_button)); + + priv = gsm_color_button_get_instance_private (color_button); + + priv->fraction = fraction; + + gtk_widget_queue_draw (GTK_WIDGET (color_button)); + + g_object_notify (G_OBJECT (color_button), "fraction"); +} + +void +gsm_color_button_get_color (GsmColorButton * color_button, GdkRGBA * color) +{ + GsmColorButtonPrivate *priv; + + g_return_if_fail (GSM_IS_COLOR_BUTTON (color_button)); + + priv = gsm_color_button_get_instance_private (color_button); + + color->red = priv->color.red; + color->green = priv->color.green; + color->blue = priv->color.blue; + color->alpha = priv->color.alpha; +} + +void +gsm_color_button_set_color (GsmColorButton * color_button, + const GdkRGBA * color) +{ + GsmColorButtonPrivate *priv; + + g_return_if_fail (GSM_IS_COLOR_BUTTON (color_button)); + g_return_if_fail (color != NULL); + + priv = gsm_color_button_get_instance_private (color_button); + + priv->color.red = color->red; + priv->color.green = color->green; + priv->color.blue = color->blue; + priv->color.alpha = color->alpha; + + gtk_widget_queue_draw (GTK_WIDGET (color_button)); + + g_object_notify (G_OBJECT (color_button), "color"); +} + +void +gsm_color_button_set_title (GsmColorButton * color_button, + const gchar * title) +{ + GsmColorButtonPrivate *priv; + gchar *old_title; + + g_return_if_fail (GSM_IS_COLOR_BUTTON (color_button)); + + priv = gsm_color_button_get_instance_private (color_button); + + old_title = priv->title; + priv->title = g_strdup (title); + g_free (old_title); + + if (priv->cc_dialog) + gtk_window_set_title (GTK_WINDOW (priv->cc_dialog), + priv->title); + + g_object_notify (G_OBJECT (color_button), "title"); +} + +gchar * +gsm_color_button_get_title (GsmColorButton * color_button) +{ + GsmColorButtonPrivate *priv; + + g_return_val_if_fail (GSM_IS_COLOR_BUTTON (color_button), NULL); + + priv = gsm_color_button_get_instance_private (color_button); + return priv->title; +} + +static void +gsm_color_button_set_property (GObject * object, + guint param_id, + const GValue * value, GParamSpec * pspec) +{ + GsmColorButton *color_button = GSM_COLOR_BUTTON (object); + + switch (param_id) + { + case PROP_PERCENTAGE: + gsm_color_button_set_fraction (color_button, + g_value_get_double (value)); + break; + case PROP_TITLE: + gsm_color_button_set_title (color_button, g_value_get_string (value)); + break; + case PROP_COLOR: + gsm_color_button_set_color (color_button, g_value_get_boxed (value)); + break; + case PROP_TYPE: + gsm_color_button_set_cbtype (color_button, g_value_get_uint (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + +static void +gsm_color_button_get_property (GObject * object, + guint param_id, + GValue * value, GParamSpec * pspec) +{ + GsmColorButton *color_button = GSM_COLOR_BUTTON (object); + GdkRGBA color; + + switch (param_id) + { + case PROP_PERCENTAGE: + g_value_set_double (value, + gsm_color_button_get_fraction (color_button)); + break; + case PROP_TITLE: + g_value_set_string (value, gsm_color_button_get_title (color_button)); + break; + case PROP_COLOR: + gsm_color_button_get_color (color_button, &color); + g_value_set_boxed (value, &color); + break; + case PROP_TYPE: + g_value_set_uint (value, gsm_color_button_get_cbtype (color_button)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} diff --git a/src/legacy/gsm_color_button.h b/src/legacy/gsm_color_button.h new file mode 100644 index 0000000..385dd14 --- /dev/null +++ b/src/legacy/gsm_color_button.h @@ -0,0 +1,77 @@ +/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Gnome system monitor colour pickers + * Copyright (C) 2007 Karl Lattimer + * All rights reserved. + * + * This Library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This software 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 the software; see the file COPYING. If not, + * see . + */ + +#ifndef _GSM_COLOR_BUTTON_H_ +#define _GSM_COLOR_BUTTON_H_ + +#include + +G_BEGIN_DECLS + +/* The GtkColorSelectionButton widget is a simple color picker in a button. + * The button displays a sample of the currently selected color. When + * the user clicks on the button, a color selection dialog pops up. + * The color picker emits the "color_set" signal when the color is set. + */ +#define GSM_TYPE_COLOR_BUTTON (gsm_color_button_get_type ()) +#define GSM_COLOR_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSM_TYPE_COLOR_BUTTON, GsmColorButton)) +#define GSM_COLOR_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSM_TYPE_COLOR_BUTTON, GsmColorButtonClass)) +#define GSM_IS_COLOR_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSM_TYPE_COLOR_BUTTON)) +#define GSM_IS_COLOR_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSM_TYPE_COLOR_BUTTON)) +#define GSM_COLOR_BUTTON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSM_TYPE_COLOR_BUTTON, GsmColorButtonClass)) + +typedef struct _GsmColorButton GsmColorButton; +typedef struct _GsmColorButtonClass GsmColorButtonClass; + +struct _GsmColorButton +{ + GtkDrawingArea parent_instance; +}; + +/* Widget types */ +enum +{ + GSMCP_TYPE_CPU, + GSMCP_TYPE_PIE, + GSMCP_TYPE_NETWORK_IN, + GSMCP_TYPE_NETWORK_OUT, + GSMCP_TYPES +}; + +struct _GsmColorButtonClass +{ + GtkDrawingAreaClass parent_class; +}; + +GType gsm_color_button_get_type (void); +GsmColorButton * gsm_color_button_new (const GdkRGBA * color, guint type); +void gsm_color_button_set_color (GsmColorButton * color_button, const GdkRGBA * color); +void gsm_color_button_set_fraction (GsmColorButton * color_button, const gdouble fraction); +void gsm_color_button_set_cbtype (GsmColorButton * color_button, guint type); +void gsm_color_button_get_color (GsmColorButton * color_button, GdkRGBA * color); +gdouble gsm_color_button_get_fraction (GsmColorButton * color_button); +guint gsm_color_button_get_cbtype (GsmColorButton * color_button); +void gsm_color_button_set_title (GsmColorButton * color_button, const gchar * title); +gchar * gsm_color_button_get_title (GsmColorButton * color_button); + +G_END_DECLS + +#endif /* _GSM_COLOR_BUTTON_H_ */ diff --git a/src/legacy/meson.build b/src/legacy/meson.build new file mode 100644 index 0000000..a66c863 --- /dev/null +++ b/src/legacy/meson.build @@ -0,0 +1,16 @@ + +libgsm_legacy_sources = [ + 'e_date.c', + 'gsm_color_button.c', + 'treeview.c', +] + +libgsm_legacy = static_library('gsm_legacy', + libgsm_legacy_sources, + include_directories: rootInclude, + dependencies: [ + glib, + gtk3, + librsvg, + ], +) diff --git a/src/legacy/treeview.c b/src/legacy/treeview.c new file mode 100644 index 0000000..b50393d --- /dev/null +++ b/src/legacy/treeview.c @@ -0,0 +1,289 @@ +/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +#include + +#include "treeview.h" + +typedef struct +{ + GSettings *settings; + gboolean store_column_order; + GHashTable *excluded_columns; +} GsmTreeViewPrivate; + +G_DEFINE_TYPE_WITH_PRIVATE (GsmTreeView, gsm_tree_view, GTK_TYPE_TREE_VIEW) + +static void +gsm_tree_view_finalize (GObject *object) +{ + GsmTreeViewPrivate *priv = gsm_tree_view_get_instance_private (GSM_TREE_VIEW (object)); + + g_hash_table_destroy (priv->excluded_columns); + priv->excluded_columns = NULL; + + G_OBJECT_CLASS (gsm_tree_view_parent_class)->finalize (object); +} + +static void +gsm_tree_view_class_init (GsmTreeViewClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->finalize = gsm_tree_view_finalize; +} + +static void +gsm_tree_view_init (GsmTreeView *self) +{ + GsmTreeViewPrivate *priv = gsm_tree_view_get_instance_private (self); + + priv->excluded_columns = g_hash_table_new (g_direct_hash, g_direct_equal); +} + +void +gsm_tree_view_save_state (GsmTreeView *tree_view) +{ + GsmTreeViewPrivate *priv; + + g_return_if_fail (GSM_IS_TREE_VIEW (tree_view)); + + priv = gsm_tree_view_get_instance_private (tree_view); + GtkTreeModel *model; + gint sort_col; + GtkSortType sort_type; + + model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view)); + g_settings_delay (priv->settings); + if (gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (model), + &sort_col, + &sort_type)) { + g_settings_set_int (priv->settings, "sort-col", sort_col); + g_settings_set_int (priv->settings, "sort-order", sort_type); + } + + if (priv->store_column_order) { + GList *columns = gtk_tree_view_get_columns (GTK_TREE_VIEW (tree_view)); + GList *iter; + GVariantBuilder builder; + + g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY); + + for (iter = columns; iter != NULL; iter = iter->next) { + gint id = gtk_tree_view_column_get_sort_column_id (GTK_TREE_VIEW_COLUMN (iter->data)); + g_variant_builder_add (&builder, "i", id); + } + + g_settings_set_value (priv->settings, "columns-order", + g_variant_builder_end (&builder)); + + g_list_free (columns); + } + + g_settings_apply (priv->settings); +} + +GtkTreeViewColumn * +gsm_tree_view_get_column_from_id (GsmTreeView *tree_view, gint sort_id) +{ + GList *columns; + GList *iter; + GtkTreeViewColumn *col = NULL; + + g_return_val_if_fail (GSM_IS_TREE_VIEW (tree_view), NULL); + + columns = gtk_tree_view_get_columns (GTK_TREE_VIEW (tree_view)); + + for (iter = columns; iter != NULL; iter = iter->next) { + col = GTK_TREE_VIEW_COLUMN (iter->data); + if (gtk_tree_view_column_get_sort_column_id (col) == sort_id) + break; + } + + g_list_free (columns); + + return col; +} + +static gboolean +cb_column_header_clicked (GtkTreeViewColumn *column, GdkEventButton *event, gpointer data) +{ + GtkMenu *menu = GTK_MENU (data); + + if (event->button == GDK_BUTTON_SECONDARY) { + gtk_menu_popup_at_pointer (menu, (GdkEvent*)event); + return TRUE; + } + + return FALSE; +} + +void +gsm_tree_view_load_state (GsmTreeView *tree_view) +{ + GsmTreeViewPrivate *priv; + GtkTreeModel *model; + gint sort_col; + GtkSortType sort_type; + + g_return_if_fail (GSM_IS_TREE_VIEW (tree_view)); + + priv = gsm_tree_view_get_instance_private (tree_view); + model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view)); + + sort_col = g_settings_get_int (priv->settings, "sort-col"); + sort_type = g_settings_get_int (priv->settings, "sort-order"); + + gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model), + sort_col, + sort_type); + + if (priv->store_column_order) { + GtkMenu *header_menu = GTK_MENU (gtk_menu_new ()); + GList *columns = gtk_tree_view_get_columns (GTK_TREE_VIEW (tree_view)); + GList *iter; + GVariantIter *var_iter; + GtkTreeViewColumn *col, *last; + gint sort_id; + + for (iter = columns; iter != NULL; iter = iter->next) { + const char *title; + char *key; + GtkButton *button; + GtkCheckMenuItem *column_item; + + col = GTK_TREE_VIEW_COLUMN (iter->data); + sort_id = gtk_tree_view_column_get_sort_column_id (col); + + if (priv->excluded_columns && + g_hash_table_contains (priv->excluded_columns, GINT_TO_POINTER (sort_id))) { + gtk_tree_view_column_set_visible (col, FALSE); + continue; + } + + title = gtk_tree_view_column_get_title (col); + + button = GTK_BUTTON (gtk_tree_view_column_get_button (col)); + g_signal_connect (button, "button-press-event", + G_CALLBACK (cb_column_header_clicked), + header_menu); + + column_item = GTK_CHECK_MENU_ITEM (gtk_check_menu_item_new_with_label (title)); + g_object_bind_property (col, "visible", + column_item, "active", + G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); + + gtk_menu_shell_append (GTK_MENU_SHELL (header_menu), GTK_WIDGET (column_item)); + + key = g_strdup_printf ("col-%d-width", sort_id); + gtk_tree_view_column_set_fixed_width (col, g_settings_get_int (priv->settings, key)); + gtk_tree_view_column_set_min_width (col, 30); + g_free (key); + + key = g_strdup_printf ("col-%d-visible", sort_id); + gtk_tree_view_column_set_visible (col, g_settings_get_boolean (priv->settings, key)); + g_free (key); + } + + g_list_free (columns); + + gtk_widget_show_all (GTK_WIDGET (header_menu)); + + g_settings_get (priv->settings, "columns-order", "ai", &var_iter); + last = NULL; + while (g_variant_iter_loop (var_iter, "i", &sort_id)) { + col = gsm_tree_view_get_column_from_id (tree_view, sort_id); + + if (col != NULL && col != last) { + gtk_tree_view_move_column_after (GTK_TREE_VIEW (tree_view), + col, last); + last = col; + } + } + g_variant_iter_free (var_iter); + } +} + +void +gsm_tree_view_add_excluded_column (GsmTreeView *tree_view, gint column_id) +{ + GsmTreeViewPrivate *priv; + + g_return_if_fail (GSM_IS_TREE_VIEW (tree_view)); + + priv = gsm_tree_view_get_instance_private (tree_view); + g_hash_table_add (priv->excluded_columns, GINT_TO_POINTER (column_id)); +} + +static guint timeout_id = 0; +static GtkTreeViewColumn *current_column; + +static gboolean +save_column_state (gpointer data) +{ + GSettings *settings = G_SETTINGS (data); + gint column_id = gtk_tree_view_column_get_sort_column_id (current_column); + gint width = gtk_tree_view_column_get_width (current_column); + gboolean visible = gtk_tree_view_column_get_visible (current_column); + + gchar *key; + g_settings_delay (settings); + + key = g_strdup_printf ("col-%d-width", column_id); + g_settings_set_int (settings, key, width); + g_free (key); + + key = g_strdup_printf ("col-%d-visible", column_id); + g_settings_set_boolean (settings, key, visible); + g_free (key); + timeout_id = 0; + g_settings_apply (settings); + + return FALSE; +} + +static void +cb_update_column_state (GObject *object, GParamSpec *pspec, gpointer data) +{ + GtkTreeViewColumn *column = GTK_TREE_VIEW_COLUMN (object); + + current_column = column; + + if (timeout_id > 0) + g_source_remove (timeout_id); + + timeout_id = g_timeout_add_seconds (1, save_column_state, data); +} + +void +gsm_tree_view_append_and_bind_column (GsmTreeView *tree_view, GtkTreeViewColumn *column) +{ + GsmTreeViewPrivate *priv; + + g_return_if_fail (GSM_IS_TREE_VIEW (tree_view)); + g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (column)); + + priv = gsm_tree_view_get_instance_private (tree_view); + + gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), + column); + + g_signal_connect (column, "notify::fixed-width", + G_CALLBACK (cb_update_column_state), + priv->settings); + + g_signal_connect (column, "notify::visible", + G_CALLBACK (cb_update_column_state), + priv->settings); +} + + +GsmTreeView * +gsm_tree_view_new (GSettings *settings, gboolean store_column_order) +{ + GsmTreeView *self = g_object_new (GSM_TYPE_TREE_VIEW, NULL); + GsmTreeViewPrivate *priv = gsm_tree_view_get_instance_private (self); + + priv->settings = settings; + priv->store_column_order = store_column_order; + + return self; +} diff --git a/src/legacy/treeview.h b/src/legacy/treeview.h new file mode 100644 index 0000000..7223ab1 --- /dev/null +++ b/src/legacy/treeview.h @@ -0,0 +1,43 @@ +/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +#ifndef _GSM_TREE_VIEW_H_ +#define _GSM_TREE_VIEW_H_ + +#include + +G_BEGIN_DECLS + +#define GSM_TYPE_TREE_VIEW (gsm_tree_view_get_type ()) +#define GSM_TREE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSM_TYPE_TREE_VIEW, GsmTreeView)) +#define GSM_TREE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSM_TYPE_TREE_VIEW, GsmTreeViewClass)) +#define GSM_IS_TREE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSM_TYPE_TREE_VIEW)) +#define GSM_IS_TREE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSM_TYPE_TREE_VIEW)) +#define GSM_TREE_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSM_TYPE_TREE_VIEW, GsmTreeViewClass)) + +typedef struct _GsmTreeView GsmTreeView; +typedef struct _GsmTreeViewClass GsmTreeViewClass; + +struct _GsmTreeView +{ + GtkTreeView parent_instance; +}; + +struct _GsmTreeViewClass +{ + GtkTreeViewClass parent_class; +}; + +GType gsm_tree_view_get_type (void) G_GNUC_CONST; +GsmTreeView * gsm_tree_view_new (GSettings *settings, + gboolean store_column_order); +void gsm_tree_view_save_state (GsmTreeView *tree_view); +void gsm_tree_view_load_state (GsmTreeView *tree_view); +GtkTreeViewColumn * gsm_tree_view_get_column_from_id (GsmTreeView *tree_view, + gint sort_id); +void gsm_tree_view_add_excluded_column (GsmTreeView *tree_view, + gint column_id); +void gsm_tree_view_append_and_bind_column (GsmTreeView *tree_view, + GtkTreeViewColumn *column); + +G_END_DECLS + +#endif /* _GSM_TREE_VIEW_H_ */ -- cgit v1.2.3