Commit 5dbf7ce4e1d4f06f29609cf174bd2d332bd13e53

Authored by Perry Werneck
1 parent ca9152f4
Exists in master and in 1 other branch develop

Moving property based actions to terminal library.

src/include/v3270/actions.h
... ... @@ -229,6 +229,12 @@
229 229 /// @brief Create a dialog action.
230 230 V3270SimpleAction * v3270_dialog_action_new(GtkWidget * (*factory)(V3270SimpleAction *, GtkWidget *));
231 231  
  232 + /// @brief Create an action from property name.
  233 + V3270SimpleAction * v3270_property_action_new(GtkWidget *widget, const gchar *property_name);
  234 +
  235 + /// @brief Create an action with the "enable" property binded with terminal property.
  236 + V3270SimpleAction * v3270_conditional_action_new(GtkWidget *widget, const gchar *property_name);
  237 +
232 238 G_END_DECLS
233 239  
234 240 #endif // V3270_ACTIONS_H_INCLUDED
... ...
src/terminal/actions/conditional.c 0 → 100644
... ... @@ -0,0 +1,198 @@
  1 +/*
  2 + * "Software pw3270, desenvolvido com base nos códigos fontes do WC3270 e X3270
  3 + * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a
  4 + * aplicativos mainframe. Registro no INPI sob o nome G3270.
  5 + *
  6 + * Copyright (C) <2008> <Banco do Brasil S.A.>
  7 + *
  8 + * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob
  9 + * os termos da GPL v.2 - Licença Pública Geral GNU, conforme publicado pela
  10 + * Free Software Foundation.
  11 + *
  12 + * Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER
  13 + * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou de ADEQUAÇÃO
  14 + * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para
  15 + * obter mais detalhes.
  16 + *
  17 + * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este
  18 + * programa; se não, escreva para a Free Software Foundation, Inc., 51 Franklin
  19 + * St, Fifth Floor, Boston, MA 02110-1301 USA
  20 + *
  21 + * Este programa está nomeado como - e possui - linhas de código.
  22 + *
  23 + * Contatos:
  24 + *
  25 + * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck)
  26 + * erico.mendonca@gmail.com (Erico Mascarenhas Mendonça)
  27 + *
  28 + */
  29 +
  30 + /**
  31 + * @brief Implement GAction who enables/disable based on a v3270 boolean property.
  32 + *
  33 + * Reference:
  34 + *
  35 + * <https://github.com/GNOME/glib/blob/master/gio/gpropertyaction.c>
  36 + *
  37 + */
  38 +
  39 + #include <internals.h>
  40 + #include <stdlib.h>
  41 + #include <v3270.h>
  42 + #include <v3270/actions.h>
  43 + #include <lib3270/properties.h>
  44 +
  45 + typedef struct _V3270ConditionalAction {
  46 +
  47 + V3270SimpleAction parent;
  48 +
  49 + GParamSpec *pspec;
  50 +
  51 + } V3270ConditionalAction;
  52 +
  53 + typedef struct _V3270CopyActionClass {
  54 +
  55 + V3270SimpleActionClass parent_class;
  56 +
  57 + } V3270ConditionalActionClass;
  58 +
  59 + #define V3270_TYPE_CONDITIONAL_ACTION (V3270ConditionalAction_get_type())
  60 + #define V3270_CONDITIONAL_ACTION(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), V3270_TYPE_CONDITIONAL_ACTION, V3270ConditionalAction))
  61 + #define V3270_CONDITIONAL_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), V3270_TYPE_CONDITIONAL_ACTION, V3270ConditionalActionClass))
  62 + #define V3270_IS_CONDITIONAL_ACTION(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), V3270_TYPE_CONDITIONAL_ACTION))
  63 + #define V3270_IS_CONDITIONAL_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), V3270_TYPE_CONDITIONAL_ACTION))
  64 + #define V3270_CONDITIONAL_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), V3270_TYPE_CONDITIONAL_ACTION, V3270ConditionalActionClass))
  65 +
  66 + static gboolean get_enabled(GAction *action, GtkWidget *terminal);
  67 + static void change_widget(GAction *object, GtkWidget *from, GtkWidget *to);
  68 +
  69 + G_DEFINE_TYPE(V3270ConditionalAction, V3270ConditionalAction, V3270_TYPE_SIMPLE_ACTION);
  70 +
  71 + void V3270ConditionalAction_class_init(V3270ConditionalActionClass *klass) {
  72 +
  73 + klass->parent_class.parent_class.change_widget = change_widget;
  74 + klass->parent_class.parent_class.get_enabled = get_enabled;
  75 +
  76 + }
  77 +
  78 + static void V3270ConditionalAction_init(V3270ConditionalAction G_GNUC_UNUSED(*action)) {
  79 + }
  80 +
  81 + static void on_notify(GtkWidget G_GNUC_UNUSED(*terminal), GParamSpec G_GNUC_UNUSED(*pspec), GAction *action) {
  82 + debug("%s: Enabled of action %s has changed",__FUNCTION__, g_action_get_name(G_ACTION(action)));
  83 + v3270_action_notify_enabled(action);
  84 + }
  85 +
  86 + V3270SimpleAction * v3270_conditional_action_new(GtkWidget *widget, const gchar *property_name) {
  87 +
  88 + GParamSpec *pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(widget), property_name);
  89 +
  90 + if(!pspec) {
  91 +
  92 + g_warning(
  93 + "Can't find property '%s::%s'",
  94 + G_OBJECT_TYPE_NAME(G_OBJECT(widget)),
  95 + property_name
  96 + );
  97 +
  98 + return NULL;
  99 +
  100 + }
  101 +
  102 + debug("%s: pspec(%s)=%p",__FUNCTION__,property_name,pspec);
  103 +
  104 + if(~pspec->flags & G_PARAM_READABLE || pspec->flags & G_PARAM_CONSTRUCT_ONLY) {
  105 +
  106 + g_warning(
  107 + "Property '%s::%s' must be readable and not construct-only",
  108 + G_OBJECT_TYPE_NAME(G_OBJECT(widget)),
  109 + property_name
  110 + );
  111 +
  112 + return NULL;
  113 + }
  114 +
  115 + V3270ConditionalAction * action = (V3270ConditionalAction *) g_object_new(V3270_TYPE_CONDITIONAL_ACTION, NULL);
  116 +
  117 + action->parent.name = g_param_spec_get_name(pspec);
  118 + action->pspec = pspec;
  119 +
  120 + const LIB3270_PROPERTY * lProperty = lib3270_property_get_by_name(pspec->name);
  121 + if(lProperty) {
  122 + action->parent.label = lib3270_property_get_label(lProperty);
  123 + action->parent.tooltip = lib3270_property_get_summary(lProperty);
  124 +// action->group.id = lProperty->group;
  125 + }
  126 +
  127 + if(!action->parent.tooltip)
  128 + action->parent.tooltip = g_param_spec_get_blurb(pspec);
  129 +
  130 + v3270_action_set_terminal_widget(G_ACTION(action), widget);
  131 +
  132 + return V3270_SIMPLE_ACTION(action);
  133 + }
  134 +
  135 + void change_widget(GAction *object, GtkWidget *from, GtkWidget *to) {
  136 +
  137 + V3270ConditionalAction * action = V3270_CONDITIONAL_ACTION(object);
  138 + g_autofree gchar * signal_name = g_strconcat("notify::", action->pspec->name,NULL);
  139 +
  140 + if(from) {
  141 + gulong handler = g_signal_handler_find(
  142 + from,
  143 + G_SIGNAL_MATCH_FUNC|G_SIGNAL_MATCH_DATA,
  144 + 0,
  145 + 0,
  146 + NULL,
  147 + G_CALLBACK(on_notify),
  148 + action
  149 + );
  150 +
  151 + if(handler)
  152 + g_signal_handler_disconnect(from, handler);
  153 +
  154 + }
  155 +
  156 + V3270_ACTION_CLASS(V3270ConditionalAction_parent_class)->change_widget(object,from,to);
  157 +
  158 + if(to) {
  159 + g_signal_connect(G_OBJECT(to),signal_name,G_CALLBACK(on_notify),action);
  160 + }
  161 +
  162 + v3270_action_notify_enabled(G_ACTION(object));
  163 +
  164 + }
  165 +
  166 + gboolean get_enabled(GAction *object, GtkWidget *terminal) {
  167 +
  168 + gboolean enabled = V3270_ACTION_CLASS(V3270ConditionalAction_parent_class)->get_enabled(object,terminal);
  169 +
  170 + if(enabled && terminal) {
  171 +
  172 + // The action is enabled, check property to confirm.
  173 + V3270ConditionalAction * action = V3270_CONDITIONAL_ACTION(object);
  174 +
  175 + GValue value = G_VALUE_INIT;
  176 + g_value_init(&value, action->pspec->value_type);
  177 + g_object_get_property(G_OBJECT(terminal), action->pspec->name, &value);
  178 +
  179 + switch(action->pspec->value_type) {
  180 + case G_TYPE_UINT:
  181 + enabled = g_value_get_uint(&value) != 0;
  182 + break;
  183 +
  184 + case G_TYPE_BOOLEAN:
  185 + enabled = g_value_get_boolean(&value);
  186 + break;
  187 +
  188 + default:
  189 + enabled = FALSE;
  190 + }
  191 +
  192 + g_value_unset (&value);
  193 +
  194 + }
  195 +
  196 + return enabled;
  197 +
  198 + }
... ...
src/terminal/actions/property.c 0 → 100644
... ... @@ -0,0 +1,308 @@
  1 +/*
  2 + * "Software pw3270, desenvolvido com base nos códigos fontes do WC3270 e X3270
  3 + * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a
  4 + * aplicativos mainframe. Registro no INPI sob o nome G3270.
  5 + *
  6 + * Copyright (C) <2008> <Banco do Brasil S.A.>
  7 + *
  8 + * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob
  9 + * os termos da GPL v.2 - Licença Pública Geral GNU, conforme publicado pela
  10 + * Free Software Foundation.
  11 + *
  12 + * Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER
  13 + * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou de ADEQUAÇÃO
  14 + * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para
  15 + * obter mais detalhes.
  16 + *
  17 + * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este
  18 + * programa; se não, escreva para a Free Software Foundation, Inc., 51 Franklin
  19 + * St, Fifth Floor, Boston, MA 02110-1301 USA
  20 + *
  21 + * Este programa está nomeado como - e possui - linhas de código.
  22 + *
  23 + * Contatos:
  24 + *
  25 + * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck)
  26 + * erico.mendonca@gmail.com (Erico Mascarenhas Mendonça)
  27 + *
  28 + */
  29 +
  30 + /**
  31 + * @brief Implement GAction "wrapper" for v3270 properties.
  32 + *
  33 + * Reference:
  34 + *
  35 + * <https://github.com/GNOME/glib/blob/master/gio/gpropertyaction.c>
  36 + *
  37 + */
  38 +
  39 + #include <internals.h>
  40 + #include <stdlib.h>
  41 + #include <v3270.h>
  42 + #include <v3270/actions.h>
  43 + #include <lib3270/properties.h>
  44 +
  45 + //
  46 + // V3270 Property Action
  47 + //
  48 + #define V3270_TYPE_PROPERTY_ACTION (v3270PropertyAction_get_type())
  49 + #define V3270_PROPERTY_ACTION(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), V3270_TYPE_PROPERTY_ACTION, v3270PropertyAction))
  50 + #define V3270_PROPERTY_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), V3270_TYPE_PROPERTY_ACTION, v3270PropertyActionClass))
  51 + #define V3270_IS_PROPERTY_ACTION(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), V3270_TYPE_PROPERTY_ACTION))
  52 + #define V3270_IS_PROPERTY_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), V3270_TYPE_PROPERTY_ACTION))
  53 + #define V3270_PROPERTY_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), V3270_TYPE_PROPERTY_ACTION, v3270PropertyActionClass))
  54 +
  55 + typedef struct _v3270PropertyAction {
  56 +
  57 + V3270SimpleAction parent;
  58 +
  59 + GParamSpec *pspec;
  60 +
  61 + } v3270PropertyAction;
  62 +
  63 + typedef struct _v3270PropertyActionClass {
  64 +
  65 + V3270SimpleActionClass parent_class;
  66 +
  67 + } v3270PropertyActionClass;
  68 +
  69 +// static void v3270PropertyAction_class_init(v3270PropertyActionClass *klass);
  70 +// static void v3270PropertyAction_init(v3270PropertyAction *action);
  71 +
  72 + static GVariant * get_state(GAction *action, GtkWidget *terminal);
  73 + static const GVariantType * get_state_type(GAction *object);
  74 + static const GVariantType * get_parameter_type(GAction *object);
  75 +
  76 + static void change_widget(GAction *object, GtkWidget *from, GtkWidget *to);
  77 +
  78 + G_DEFINE_TYPE(v3270PropertyAction, v3270PropertyAction, V3270_TYPE_SIMPLE_ACTION);
  79 +
  80 + void v3270PropertyAction_class_init(v3270PropertyActionClass *klass) {
  81 + klass->parent_class.parent_class.change_widget = change_widget;
  82 + klass->parent_class.parent_class.get_parameter_type = get_parameter_type;
  83 + klass->parent_class.parent_class.get_state = get_state;
  84 + klass->parent_class.parent_class.get_state_type = get_state_type;
  85 + }
  86 +
  87 + static void v3270PropertyAction_init(v3270PropertyAction G_GNUC_UNUSED(*action)) {
  88 + }
  89 +
  90 + GVariant * get_state(GAction *object, GtkWidget *terminal) {
  91 +
  92 + v3270PropertyAction * action = V3270_PROPERTY_ACTION(object);
  93 +
  94 + GVariant * result = NULL;
  95 + GValue value = G_VALUE_INIT;
  96 +
  97 + g_value_init(&value, action->pspec->value_type);
  98 + g_object_get_property(G_OBJECT(terminal), action->pspec->name, &value);
  99 +
  100 + switch(action->pspec->value_type) {
  101 + case G_TYPE_UINT:
  102 + result = g_variant_new_take_string(g_strdup_printf("%d",g_value_get_uint(&value)));
  103 + break;
  104 +
  105 + case G_TYPE_STRING:
  106 + result = g_variant_new_string(g_value_get_string(&value));
  107 + debug("Action %s is on state \"%s\"",g_action_get_name(object),g_value_get_string(&value));
  108 + break;
  109 +
  110 + case G_TYPE_BOOLEAN:
  111 + result = g_variant_new_boolean(g_value_get_boolean(&value));
  112 + break;
  113 + /*
  114 +
  115 + case G_TYPE_INT:
  116 + result = g_variant_new_int32(g_value_get_int(&value));
  117 + break;
  118 +
  119 + case G_TYPE_DOUBLE:
  120 + result = g_variant_new_double(g_value_get_double(&value));
  121 + break;
  122 +
  123 + case G_TYPE_FLOAT:
  124 + result = g_variant_new_double(g_value_get_float(&value));
  125 + break;
  126 +
  127 + */
  128 + default:
  129 + g_warning("Unexpected value type getting state for action \"%s\"",g_action_get_name(object));
  130 + }
  131 +
  132 + g_value_unset (&value);
  133 +
  134 + return result;
  135 +
  136 + }
  137 +
  138 + static void activate(GAction *object, GVariant *parameter, GtkWidget *terminal) {
  139 +
  140 + v3270PropertyAction * action = V3270_PROPERTY_ACTION(object);
  141 +
  142 + GValue value = G_VALUE_INIT;
  143 + g_value_init(&value, action->pspec->value_type);
  144 +
  145 + switch(action->pspec->value_type)
  146 + {
  147 + case G_TYPE_UINT:
  148 + debug("%s(%s,%s,%p)",__FUNCTION__,g_action_get_name(object),g_variant_get_string(parameter,NULL),terminal);
  149 + g_value_set_uint(&value,atoi(g_variant_get_string(parameter,NULL)));
  150 + break;
  151 +
  152 + case G_TYPE_BOOLEAN:
  153 +
  154 + if(parameter) {
  155 +
  156 + debug("%s(%s,%s,%p)",__FUNCTION__,g_action_get_name(object),g_variant_get_string(parameter,NULL),terminal);
  157 +
  158 + if(g_variant_is_of_type(parameter,G_VARIANT_TYPE_BOOLEAN))
  159 + g_value_set_boolean(&value,g_variant_get_boolean(parameter));
  160 + else
  161 + g_value_set_boolean(&value,atoi(g_variant_get_string(parameter,NULL)) != 0);
  162 +
  163 + } else {
  164 +
  165 + g_object_get_property(G_OBJECT(terminal), action->pspec->name, &value);
  166 + g_value_set_boolean(&value,!g_value_get_boolean(&value));
  167 +
  168 + }
  169 +
  170 + break;
  171 +
  172 + case G_TYPE_STRING:
  173 + g_value_set_string(&value,g_variant_get_string(parameter,NULL));
  174 + break;
  175 +
  176 + /*
  177 + case G_TYPE_INT:
  178 + break;
  179 +
  180 + case G_TYPE_DOUBLE:
  181 + break;
  182 +
  183 + case G_TYPE_FLOAT:
  184 + break;
  185 +
  186 + */
  187 +
  188 + default:
  189 + g_warning("Can't activate action \"%s\"",g_action_get_name(object));
  190 + g_value_unset(&value);
  191 + return;
  192 + }
  193 +
  194 + g_object_set_property(G_OBJECT(terminal),action->pspec->name,&value);
  195 +
  196 + g_value_unset(&value);
  197 +
  198 + }
  199 +
  200 + static void on_notify(GtkWidget G_GNUC_UNUSED(*terminal), GParamSpec G_GNUC_UNUSED(*pspec), GAction *action) {
  201 +
  202 + debug("%s: State of action %s has changed",__FUNCTION__, g_action_get_name(G_ACTION(action)));
  203 + v3270_action_notify_state(action);
  204 +
  205 + }
  206 +
  207 + V3270SimpleAction * v3270_property_action_new(GtkWidget *widget, const gchar *property_name) {
  208 +
  209 + GParamSpec *pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(widget), property_name);
  210 +
  211 + if(!pspec) {
  212 +
  213 + g_warning(
  214 + "Can't find property '%s::%s'",
  215 + G_OBJECT_TYPE_NAME(G_OBJECT(widget)),
  216 + property_name
  217 + );
  218 +
  219 + return NULL;
  220 +
  221 + }
  222 +
  223 + debug("%s: pspec(%s)=%p",__FUNCTION__,property_name,pspec);
  224 +
  225 + if(~pspec->flags & G_PARAM_READABLE || ~pspec->flags & G_PARAM_WRITABLE || pspec->flags & G_PARAM_CONSTRUCT_ONLY) {
  226 +
  227 + g_warning(
  228 + "Property '%s::%s' must be readable, writable, and not construct-only",
  229 + G_OBJECT_TYPE_NAME(G_OBJECT(widget)),
  230 + property_name
  231 + );
  232 +
  233 + return NULL;
  234 + }
  235 +
  236 + v3270PropertyAction * action = (v3270PropertyAction *) g_object_new(V3270_TYPE_PROPERTY_ACTION, NULL);
  237 +
  238 + action->parent.name = g_param_spec_get_name(pspec);
  239 +
  240 + const LIB3270_PROPERTY * lProperty = lib3270_property_get_by_name(pspec->name);
  241 + if(lProperty) {
  242 + action->parent.label = lib3270_property_get_label(lProperty);
  243 + action->parent.tooltip = lib3270_property_get_summary(lProperty);
  244 +// action->group.id = lProperty->group;
  245 + }
  246 +
  247 + if(!action->parent.tooltip)
  248 + action->parent.tooltip = g_param_spec_get_blurb(pspec);
  249 +
  250 + action->parent.parent.activate = activate;
  251 + action->pspec = pspec;
  252 +
  253 + v3270_action_set_terminal_widget(G_ACTION(action), widget);
  254 +
  255 + return V3270_SIMPLE_ACTION(action);
  256 + }
  257 +
  258 + const GVariantType * get_state_type(GAction *object) {
  259 +
  260 + v3270PropertyAction * action = V3270_PROPERTY_ACTION(object);
  261 +
  262 + if(action->pspec->value_type == G_TYPE_BOOLEAN)
  263 + return G_VARIANT_TYPE_BOOLEAN;
  264 +
  265 + return G_VARIANT_TYPE_STRING;
  266 +
  267 + }
  268 +
  269 + const GVariantType * get_parameter_type(GAction *object) {
  270 +
  271 + v3270PropertyAction * action = V3270_PROPERTY_ACTION(object);
  272 +
  273 + if(action->pspec->value_type == G_TYPE_BOOLEAN)
  274 + return G_VARIANT_TYPE_BOOLEAN;
  275 +
  276 + return G_VARIANT_TYPE_STRING;
  277 +
  278 + }
  279 +
  280 + void change_widget(GAction *object, GtkWidget *from, GtkWidget *to) {
  281 +
  282 + v3270PropertyAction * action = V3270_PROPERTY_ACTION(object);
  283 + g_autofree gchar * signal_name = g_strconcat("notify::", action->pspec->name,NULL);
  284 +
  285 + if(from) {
  286 + gulong handler = g_signal_handler_find(
  287 + from,
  288 + G_SIGNAL_MATCH_FUNC|G_SIGNAL_MATCH_DATA,
  289 + 0,
  290 + 0,
  291 + NULL,
  292 + G_CALLBACK(on_notify),
  293 + action
  294 + );
  295 +
  296 + if(handler)
  297 + g_signal_handler_disconnect(from, handler);
  298 +
  299 + }
  300 +
  301 + V3270_ACTION_CLASS(v3270PropertyAction_parent_class)->change_widget(object,from,to);
  302 +
  303 + if(to) {
  304 + g_signal_connect(G_OBJECT(to),signal_name,G_CALLBACK(on_notify),action);
  305 + }
  306 +
  307 + }
  308 +
... ...
v3270.cbp
... ... @@ -233,6 +233,9 @@
233 233 <Unit filename="src/terminal/actions/clipboard.c">
234 234 <Option compilerVar="CC" />
235 235 </Unit>
  236 + <Unit filename="src/terminal/actions/conditional.c">
  237 + <Option compilerVar="CC" />
  238 + </Unit>
236 239 <Unit filename="src/terminal/actions/dialog.c">
237 240 <Option compilerVar="CC" />
238 241 </Unit>
... ... @@ -249,6 +252,9 @@
249 252 <Option compilerVar="CC" />
250 253 </Unit>
251 254 <Unit filename="src/terminal/actions/private.h" />
  255 + <Unit filename="src/terminal/actions/property.c">
  256 + <Option compilerVar="CC" />
  257 + </Unit>
252 258 <Unit filename="src/terminal/actions/save.c">
253 259 <Option compilerVar="CC" />
254 260 </Unit>
... ...