Revision 50d91bdfc94cb9d3aa01634ac0b003d76e799bf1 authored by Tobias Ellinghaus on 04 May 2017, 21:56:48 UTC, committed by Tobias Ellinghaus on 04 May 2017, 21:56:48 UTC
1 parent c2e0a27
generate_prefs.xsl
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" omit-xml-declaration="yes" indent="no" />
<xsl:strip-space elements="*"/>
<xsl:variable name="lowercase" select="'abcdefghijklmnopqrstuvwxyz'" />
<xsl:variable name="uppercase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" />
<!-- The start of the gui generating functions -->
<xsl:variable name="tab_start"> (GtkWidget *dialog, GtkWidget *tab, void (*hardcoded_part)(GtkWidget *grid))
{
GtkWidget *widget, *label, *labelev, *viewport;
GtkWidget *grid = gtk_grid_new();
gtk_grid_set_row_spacing(GTK_GRID(grid), DT_PIXEL_APPLY_DPI(5));
gtk_grid_set_column_spacing(GTK_GRID(grid), DT_PIXEL_APPLY_DPI(5));
gtk_grid_set_row_homogeneous(GTK_GRID(grid), TRUE);
gtk_widget_set_valign(grid, GTK_ALIGN_START);
int line = 0;
char tooltip[1024];
GtkWidget *scroll = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
gtk_widget_set_margin_top(scroll, DT_PIXEL_APPLY_DPI(20));
gtk_widget_set_margin_bottom(scroll, DT_PIXEL_APPLY_DPI(20));
gtk_widget_set_margin_start(scroll, DT_PIXEL_APPLY_DPI(20));
gtk_widget_set_margin_end(scroll, DT_PIXEL_APPLY_DPI(20));
viewport = gtk_viewport_new(NULL, NULL);
gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE); // doesn't seem to work from gtkrc
gtk_container_add(GTK_CONTAINER(scroll), viewport);
gtk_container_add(GTK_CONTAINER(viewport), grid);
</xsl:variable>
<xsl:variable name="tab_end">
if(hardcoded_part)
(*hardcoded_part)(grid);
gtk_widget_show_all(tab);
}
</xsl:variable>
<xsl:param name="HAVE_OPENCL">1</xsl:param>
<!-- The basic structure of the generated file -->
<xsl:template match="/">
<xsl:text><![CDATA[/** generated file, do not edit! */
#ifndef DT_PREFERENCES_H
#define DT_PREFERENCES_H
#include <gtk/gtk.h>
#include "control/conf.h"
]]></xsl:text>
<!-- reset callbacks -->
<xsl:for-each select="./dtconfiglist/dtconfig[@prefs]">
<xsl:if test="name != 'opencl' or $HAVE_OPENCL=1">
<xsl:text>static gboolean
reset_widget_</xsl:text><xsl:value-of select="generate-id(.)"/><xsl:text> (GtkWidget *label, GdkEventButton *event, GtkWidget *widget)
{
 if(event->type == GDK_2BUTTON_PRESS)
 {
</xsl:text>
<xsl:apply-templates select="." mode="reset"/>
<xsl:text>
 return TRUE;
 }
 return FALSE;
}

</xsl:text>
</xsl:if>
</xsl:for-each>
<!-- change callbacks -->
<xsl:for-each select="./dtconfiglist/dtconfig[@prefs]">
<xsl:if test="name != 'opencl' or $HAVE_OPENCL=1">
<xsl:text>static void
preferences_callback_</xsl:text><xsl:value-of select="generate-id(.)"/><xsl:text> (GtkWidget *widget, gpointer user_data)
{
</xsl:text>
<xsl:apply-templates select="." mode="change"/>
<xsl:text>
}

</xsl:text>
</xsl:if>
</xsl:for-each>
<!-- response callbacks (on dialog close) -->
<xsl:for-each select="./dtconfiglist/dtconfig[@prefs]">
<xsl:if test="name != 'opencl' or $HAVE_OPENCL=1">
<xsl:text>static void
preferences_response_callback_</xsl:text><xsl:value-of select="generate-id(.)"/><xsl:text> (GtkDialog *dialog, gint response_id, GtkWidget *widget)
{
 if(response_id != GTK_RESPONSE_ACCEPT)
 return;
</xsl:text>
<xsl:apply-templates select="." mode="change"/>
<xsl:text>
}

</xsl:text>
</xsl:if>
</xsl:for-each>
<!-- preferences tabs -->
<!-- gui -->
<xsl:text>
static void
init_tab_gui</xsl:text><xsl:value-of select="$tab_start"/><xsl:text> gtk_notebook_append_page(GTK_NOTEBOOK(tab), scroll, gtk_label_new(_("GUI options")));
</xsl:text>
<xsl:for-each select="./dtconfiglist/dtconfig[@prefs='gui']">
<xsl:apply-templates select="." mode="tab_block"/>
</xsl:for-each>
<xsl:value-of select="$tab_end" />
<!-- core -->
<xsl:text>
static void
init_tab_core</xsl:text><xsl:value-of select="$tab_start"/><xsl:text> gtk_notebook_append_page(GTK_NOTEBOOK(tab), scroll, gtk_label_new(_("core options")));
</xsl:text>
<xsl:for-each select="./dtconfiglist/dtconfig[@prefs='core']">
<xsl:if test="name != 'opencl' or $HAVE_OPENCL=1">
<xsl:apply-templates select="." mode="tab_block"/>
</xsl:if>
</xsl:for-each>
<xsl:value-of select="$tab_end" />
<!-- session -->
<xsl:text>
static void
init_tab_session</xsl:text><xsl:value-of select="$tab_start"/><xsl:text> gtk_notebook_append_page(GTK_NOTEBOOK(tab), scroll, gtk_label_new(_("session options")));
</xsl:text>
<xsl:for-each select="./dtconfiglist/dtconfig[@prefs='session']">
<xsl:apply-templates select="." mode="tab_block"/>
</xsl:for-each>
<xsl:value-of select="$tab_end" />
<!-- closing credits -->
<xsl:text>
#endif
</xsl:text>
</xsl:template>
<!-- The common blocks inside of the tabs -->
<xsl:template match="dtconfig" mode="tab_block">
<xsl:text>
{
label = gtk_label_new(_("</xsl:text><xsl:value-of select="shortdescription"/><xsl:text>"));
gtk_widget_set_halign(label, GTK_ALIGN_START);
labelev = gtk_event_box_new();
gtk_widget_add_events(labelev, GDK_BUTTON_PRESS_MASK);
gtk_container_add(GTK_CONTAINER(labelev), label);
</xsl:text>
<xsl:apply-templates select="." mode="tab"/>
<xsl:text> gtk_event_box_set_visible_window(GTK_EVENT_BOX(labelev), FALSE);</xsl:text>
<xsl:if test="longdescription != ''">
<xsl:text>
 g_object_set(widget, "tooltip-text", _("</xsl:text><xsl:value-of select="longdescription"/><xsl:text>"), (gchar *)0);</xsl:text>
</xsl:if>
<xsl:choose>
<xsl:when test="@capability">
<xsl:text>
GtkWidget *notavailable = gtk_label_new(_("not available"));
gtk_widget_set_halign(notavailable, GTK_ALIGN_START);
gtk_widget_set_sensitive(notavailable, FALSE);
g_object_set(notavailable, "tooltip-text", _("not available on this system"), (gchar *)0);
gtk_widget_set_sensitive(labelev, dt_capabilities_check("</xsl:text><xsl:value-of select="@capability"/><xsl:text>"));
gtk_widget_set_sensitive(widget, dt_capabilities_check("</xsl:text><xsl:value-of select="@capability"/><xsl:text>"));
if(!dt_capabilities_check("</xsl:text><xsl:value-of select="@capability"/><xsl:text>"))
g_object_set(labelev, "tooltip-text", _("not available on this system"), (gchar *)0);
gtk_grid_attach(GTK_GRID(grid), labelev, 0, line++, 1, 1);
gtk_grid_attach_next_to(GTK_GRID(grid), dt_capabilities_check("</xsl:text><xsl:value-of select="@capability"/><xsl:text>") ? widget : notavailable, labelev, GTK_POS_RIGHT, 1, 1);
g_signal_connect(G_OBJECT(labelev), "button-press-event", G_CALLBACK(reset_widget_</xsl:text><xsl:value-of select="generate-id(.)"/><xsl:text>), (gpointer)widget);
</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>
gtk_grid_attach(GTK_GRID(grid), labelev, 0, line++, 1, 1);
gtk_grid_attach_next_to(GTK_GRID(grid), widget, labelev, GTK_POS_RIGHT, 1, 1);
g_signal_connect(G_OBJECT(labelev), "button-press-event", G_CALLBACK(reset_widget_</xsl:text><xsl:value-of select="generate-id(.)"/><xsl:text>), (gpointer)widget);
</xsl:text>
</xsl:otherwise>
</xsl:choose>
<xsl:text>
}
</xsl:text>
</xsl:template>
<!-- Rules handling code specific for different types -->
<!-- RESET -->
<xsl:template match="dtconfig[type='string']" mode="reset">
<xsl:text> gtk_entry_set_text(GTK_ENTRY(widget), "</xsl:text><xsl:value-of select="default"/><xsl:text>");</xsl:text>
</xsl:template>
<xsl:template match="dtconfig[type='int']" mode="reset">
<xsl:text> </xsl:text><xsl:apply-templates select="type" mode="factor"/>
<xsl:text> gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), </xsl:text><xsl:value-of select="default"/><xsl:text> * factor);</xsl:text>
</xsl:template>
<xsl:template match="dtconfig[type='int64']" mode="reset">
<xsl:text> </xsl:text><xsl:apply-templates select="type" mode="factor"/>
<xsl:text> gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), </xsl:text><xsl:value-of select="default"/><xsl:text> * factor);</xsl:text>
</xsl:template>
<xsl:template match="dtconfig[type='float']" mode="reset">
<xsl:text> </xsl:text><xsl:apply-templates select="type" mode="factor"/>
<xsl:text> gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), </xsl:text><xsl:value-of select="default"/><xsl:text> * factor);</xsl:text>
</xsl:template>
<xsl:template match="dtconfig[type='bool']" mode="reset">
<xsl:text> gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), </xsl:text><xsl:value-of select="translate(default, $lowercase, $uppercase)"/><xsl:text>);</xsl:text>
</xsl:template>
<xsl:template match="dtconfig[type/enum]" mode="reset">
<xsl:variable name="default" select="default"/>
<xsl:for-each select="./type/enum/option">
<xsl:if test="$default = .">
<xsl:text> gtk_combo_box_set_active(GTK_COMBO_BOX(widget), </xsl:text><xsl:value-of select="position()-1"/><xsl:text>);</xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:template>
<!-- CALLBACK -->
<xsl:template match="dtconfig[type='string']" mode="change">
<xsl:text> dt_conf_set_string("</xsl:text><xsl:value-of select="name"/><xsl:text>", gtk_entry_get_text(GTK_ENTRY(widget)));</xsl:text>
</xsl:template>
<xsl:template match="dtconfig[type='int']" mode="change">
<xsl:apply-templates select="type" mode="factor"/>
<xsl:text> dt_conf_set_int("</xsl:text><xsl:value-of select="name"/><xsl:text>", gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget)) / factor);</xsl:text>
</xsl:template>
<xsl:template match="dtconfig[type='int64']" mode="change">
<xsl:apply-templates select="type" mode="factor"/>
<xsl:text> dt_conf_set_int64("</xsl:text><xsl:value-of select="name"/><xsl:text>", gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget)) / factor);</xsl:text>
</xsl:template>
<xsl:template match="dtconfig[type='float']" mode="change">
<xsl:apply-templates select="type" mode="factor"/>
<xsl:text> dt_conf_set_float("</xsl:text><xsl:value-of select="name"/><xsl:text>", gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget)) / factor);</xsl:text>
</xsl:template>
<xsl:template match="dtconfig[type='bool']" mode="change">
<xsl:text> dt_conf_set_bool("</xsl:text><xsl:value-of select="name"/><xsl:text>", gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));</xsl:text>
</xsl:template>
<xsl:template match="dtconfig[type/enum]" mode="change">
<xsl:text> GtkTreeIter iter;
if(gtk_combo_box_get_active_iter(GTK_COMBO_BOX(widget), &iter))
{
gchar *s = NULL;
gtk_tree_model_get(gtk_combo_box_get_model(GTK_COMBO_BOX(widget)), &iter, 0, &s, -1);
dt_conf_set_string("</xsl:text><xsl:value-of select="name"/><xsl:text>", s);
g_free(s);
}
</xsl:text>
</xsl:template>
<!-- TAB -->
<xsl:template match="dtconfig[type='string']" mode="tab">
<xsl:text> widget = gtk_entry_new();
gtk_widget_set_hexpand(widget, TRUE);
gtk_widget_set_halign(widget, GTK_ALIGN_FILL);
gchar *setting = dt_conf_get_string("</xsl:text><xsl:value-of select="name"/><xsl:text>");
gtk_entry_set_text(GTK_ENTRY(widget), setting);
g_free(setting);
g_signal_connect(G_OBJECT(widget), "activate", G_CALLBACK(preferences_callback_</xsl:text><xsl:value-of select="generate-id(.)"/><xsl:text>), NULL);
g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(preferences_response_callback_</xsl:text><xsl:value-of select="generate-id(.)"/><xsl:text>), widget);
snprintf(tooltip, 1024, _("double click to reset to `%s'"), "</xsl:text><xsl:value-of select="default"/><xsl:text>");
g_object_set(labelev, "tooltip-text", tooltip, (gchar *)0);
</xsl:text>
</xsl:template>
<xsl:template match="dtconfig[type='int']" mode="tab">
<xsl:text> gint min = 0;
 gint max = G_MAXINT;
</xsl:text>
<xsl:apply-templates select="type" mode="range"/>
<xsl:text> </xsl:text><xsl:apply-templates select="type" mode="factor"/>
<xsl:text> double tmp;
tmp = min * (double)factor; min = tmp;
tmp = max * (double)factor; max = tmp;
widget = gtk_spin_button_new_with_range(min, max, 1);
gtk_spin_button_set_digits(GTK_SPIN_BUTTON(widget), 0);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), dt_conf_get_int("</xsl:text><xsl:value-of select="name"/><xsl:text>") * factor);
g_signal_connect(G_OBJECT(widget), "value-changed", G_CALLBACK(preferences_callback_</xsl:text><xsl:value-of select="generate-id(.)"/><xsl:text>), NULL);
g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(preferences_response_callback_</xsl:text><xsl:value-of select="generate-id(.)"/><xsl:text>), widget);
snprintf(tooltip, 1024, _("double click to reset to `%d'"), (int)(</xsl:text><xsl:value-of select="default"/><xsl:text> * factor));
g_object_set(labelev, "tooltip-text", tooltip, (gchar *)0);
</xsl:text>
</xsl:template>
<xsl:template match="dtconfig[type='int64']" mode="tab">
<xsl:text> gint64 min = 0;
 gint64 max = G_MAXINT64;
</xsl:text>
<xsl:apply-templates select="type" mode="range"/>
<xsl:text> </xsl:text><xsl:apply-templates select="type" mode="factor"/>
<xsl:text> min *= factor; max *= factor;
widget = gtk_spin_button_new_with_range(min, max, 1);
gtk_spin_button_set_digits(GTK_SPIN_BUTTON(widget), 0);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), dt_conf_get_int64("</xsl:text><xsl:value-of select="name"/><xsl:text>") * factor);
g_signal_connect(G_OBJECT(widget), "value-changed", G_CALLBACK(preferences_callback_</xsl:text><xsl:value-of select="generate-id(.)"/><xsl:text>), NULL);
g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(preferences_response_callback_</xsl:text><xsl:value-of select="generate-id(.)"/><xsl:text>), widget);
char value[100];
snprintf(value, 100, "%"G_GINT64_FORMAT"",(gint64)(</xsl:text><xsl:value-of select="default"/><xsl:text> * factor));
snprintf(tooltip, 1024, _("double click to reset to `%s'"), value);
g_object_set(labelev, "tooltip-text", tooltip, (gchar *)0);
</xsl:text>
</xsl:template>
<xsl:template match="dtconfig[type='float']" mode="tab">
<xsl:text> float min = -1000000000.0f;
 float max = 1000000000.0f;
</xsl:text>
<xsl:apply-templates select="type" mode="range"/>
<xsl:text> </xsl:text><xsl:apply-templates select="type" mode="factor"/>
<xsl:text> min *= factor; max *= factor;
widget = gtk_spin_button_new_with_range(min, max, 0.001f);
gtk_spin_button_set_digits(GTK_SPIN_BUTTON(widget), 5);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(widget), dt_conf_get_float("</xsl:text><xsl:value-of select="name"/><xsl:text>") * factor);
g_signal_connect(G_OBJECT(widget), "value-changed", G_CALLBACK(preferences_callback_</xsl:text><xsl:value-of select="generate-id(.)"/><xsl:text>), NULL);
g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(preferences_response_callback_</xsl:text><xsl:value-of select="generate-id(.)"/><xsl:text>), widget);
snprintf(tooltip, 1024, _("double click to reset to `%.03f'"), </xsl:text><xsl:value-of select="default"/><xsl:text> * factor);
g_object_set(labelev, "tooltip-text", tooltip, (gchar *)0);
</xsl:text>
</xsl:template>
<xsl:template match="dtconfig[type='bool']" mode="tab">
<xsl:text> widget = gtk_check_button_new();
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), dt_conf_get_bool("</xsl:text><xsl:value-of select="name"/><xsl:text>"));
g_signal_connect(G_OBJECT(widget), "toggled", G_CALLBACK(preferences_callback_</xsl:text><xsl:value-of select="generate-id(.)"/><xsl:text>), NULL);
g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(preferences_response_callback_</xsl:text><xsl:value-of select="generate-id(.)"/><xsl:text>), widget);
snprintf(tooltip, 1024, _("double click to reset to `%s'"), C_("preferences", "</xsl:text><xsl:value-of select="translate(default, $lowercase, $uppercase)"/><xsl:text>"));
g_object_set(labelev, "tooltip-text", tooltip, (gchar *)0);
</xsl:text>
</xsl:template>
<xsl:template match="dtconfig[type/enum]" mode="tab">
<xsl:text> GtkTreeIter iter;
GtkListStore *store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
gchar *str = dt_conf_get_string("</xsl:text><xsl:value-of select="name"/><xsl:text>");
gint pos = -1;
</xsl:text>
<xsl:for-each select="./type/enum/option">
<xsl:if test="@capability">
<xsl:text>if(dt_capabilities_check("</xsl:text><xsl:value-of select="@capability"/><xsl:text>")) {</xsl:text>
</xsl:if>
<xsl:text>
gtk_list_store_append(store, &iter);
gtk_list_store_set(store, &iter, 0, "</xsl:text><xsl:value-of select="."/><xsl:text>", 1, C_("preferences", "</xsl:text><xsl:value-of select="."/><xsl:text>"), -1);
if(pos == -1 && strcmp(str, "</xsl:text><xsl:value-of select="."/><xsl:text>") == 0)
pos = </xsl:text><xsl:value-of select="position()-1" /><xsl:text>;
</xsl:text>
<xsl:if test="@capability">
<xsl:text>}
</xsl:text>
</xsl:if>
</xsl:for-each>
<xsl:text>
g_free(str);
widget = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store));
g_object_unref(store);
GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(widget), renderer, TRUE);
gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(widget), renderer, "text", 1, NULL);
gtk_combo_box_set_active(GTK_COMBO_BOX(widget), pos);
g_signal_connect(G_OBJECT(widget), "changed", G_CALLBACK(preferences_callback_</xsl:text><xsl:value-of select="generate-id(.)"/><xsl:text>), NULL);
g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(preferences_response_callback_</xsl:text><xsl:value-of select="generate-id(.)"/><xsl:text>), widget);
snprintf(tooltip, 1024, _("double click to reset to `%s'"), C_("preferences", "</xsl:text><xsl:value-of select="default"/><xsl:text>"));
g_object_set(labelev, "tooltip-text", tooltip, (gchar *)0);
</xsl:text>
</xsl:template>
<!-- Grab min/max from input. Is there a better way? -->
<xsl:template match="type[@min and @max]" mode="range" priority="5">
<xsl:text> min = </xsl:text><xsl:value-of select="@min"/><xsl:text>;
</xsl:text>
<xsl:text> max = </xsl:text><xsl:value-of select="@max"/><xsl:text>;
</xsl:text>
</xsl:template>
<xsl:template match="type[@min]" mode="range" priority="3">
<xsl:text> min = </xsl:text><xsl:value-of select="@min"/><xsl:text>;
</xsl:text>
</xsl:template>
<xsl:template match="type[@max]" mode="range" priority="3">
<xsl:text> max = </xsl:text><xsl:value-of select="@max"/><xsl:text>;
</xsl:text>
</xsl:template>
<xsl:template match="type" mode="range" priority="1"/>
<!-- Also look for the factor used in the GUI. -->
<xsl:template match="type[@factor]" mode="factor" priority="3">
<xsl:text> float factor = </xsl:text><xsl:value-of select="@factor"/><xsl:text>;
</xsl:text>
</xsl:template>
<xsl:template match="type" mode="factor" priority="1">
<xsl:text> float factor = 1.0f;
</xsl:text>
</xsl:template>
</xsl:stylesheet>
![swh spinner](/static/img/swh-spinner.gif)
Computing file changes ...