Commit bfef8307494346155ef070b85c6b57437e50e330

Authored by Perry Werneck
1 parent 76737a9e

Implementing v3270 property based action.

src/include/pw3270/actions.h
... ... @@ -70,6 +70,8 @@
70 70 /// @brief Get State method.
71 71 GVariant * (*get_state_property)(GAction *action, GtkWidget *terminal);
72 72  
  73 + /// @brief Get state hint.
  74 + GVariant * (*get_state_hint)(GAction *action, GtkWidget *terminal);
73 75  
74 76 } pw3270Action;
75 77  
... ... @@ -209,7 +211,7 @@
209 211  
210 212 GType v3270PropertyAction_get_type(void) G_GNUC_CONST;
211 213  
212   - v3270PropertyAction * v3270_property_action_new(GtkWidget *widget, const gchar *property_name);
  214 + GAction * v3270_property_action_new(GtkWidget *widget, const gchar *property_name);
213 215  
214 216 G_END_DECLS
215 217  
... ...
src/objects/actions/abstract.c
... ... @@ -49,6 +49,7 @@
49 49 static GVariant * internal_get_state_property(GAction *action, GtkWidget *terminal);
50 50 static gboolean internal_get_enabled(GAction *action, GtkWidget *terminal);
51 51 static void internal_activate(GAction *action, GVariant *parameter, GtkWidget *terminal);
  52 + static GVariant * internal_get_state_hint(GAction *action, GtkWidget *terminal);
52 53  
53 54 static const GVariantType * get_parameter_type(GAction *action);
54 55 static GVariant * get_state_hint(GAction *action);
... ... @@ -176,6 +177,7 @@
176 177  
177 178 action->activate = internal_activate;
178 179 action->get_state_property = internal_get_state_property;
  180 + action->get_state_hint = internal_get_state_hint;
179 181  
180 182 }
181 183  
... ... @@ -266,6 +268,10 @@
266 268  
267 269 }
268 270  
  271 + GVariant * internal_get_state_hint(GAction G_GNUC_UNUSED(*action), GtkWidget G_GNUC_UNUSED(*terminal)) {
  272 + return NULL;
  273 + }
  274 +
269 275 GVariant * internal_get_state_property(GAction *object, GtkWidget G_GNUC_UNUSED(*terminal)) {
270 276  
271 277 pw3270Action * action = PW3270_ACTION(object);
... ... @@ -300,11 +306,12 @@
300 306 return PW3270_ACTION(object)->types.state;
301 307 }
302 308  
303   - GVariant * get_state_hint(GAction G_GNUC_UNUSED(*action)) {
304   - return NULL;
  309 + GVariant * get_state_hint(GAction *object) {
  310 + pw3270Action *action = PW3270_ACTION(object);
  311 + return action->get_state_hint(object,action->terminal);
305 312 }
306 313  
307   - void change_state(GAction *object, GVariant *value) {
  314 + void change_state(GAction G_GNUC_UNUSED(*object), GVariant G_GNUC_UNUSED(*value)) {
308 315 debug("%s",__FUNCTION__)
309 316 }
310 317  
... ...
src/objects/actions/v3270/property.c
... ... @@ -37,18 +37,19 @@
37 37 */
38 38  
39 39 #include "../private.h"
  40 + #include <stdlib.h>
40 41 #include <pw3270/window.h>
41 42 #include <v3270.h>
42 43  
43 44 static void v3270PropertyAction_class_init(v3270PropertyActionClass *klass);
44 45 static void v3270PropertyAction_init(v3270PropertyAction *action);
45 46 static GVariant * get_state(GAction *action, GtkWidget *terminal);
46   -
  47 + static void change_widget(GAction *object, GtkWidget *from, GtkWidget *to);
47 48  
48 49 G_DEFINE_TYPE(v3270PropertyAction, v3270PropertyAction, PW3270_TYPE_ACTION);
49 50  
50 51 void v3270PropertyAction_class_init(v3270PropertyActionClass *klass) {
51   -
  52 + klass->parent_class.change_widget = change_widget;
52 53 }
53 54  
54 55 static void v3270PropertyAction_init(v3270PropertyAction *action) {
... ... @@ -57,22 +58,25 @@
57 58  
58 59 }
59 60  
60   - GVariant * get_state(GAction *action, GtkWidget *terminal) {
61   -
62   - if(!terminal)
63   - return NULL;
64   -
65   - debug("%s",__FUNCTION__);
  61 + GVariant * get_state(GAction *object, GtkWidget *terminal) {
66 62  
67   - v3270PropertyAction * paction = V3270_PROPERTY_ACTION(action);
  63 + v3270PropertyAction * action = V3270_PROPERTY_ACTION(object);
68 64  
  65 + GVariant * result = NULL;
69 66 GValue value = G_VALUE_INIT;
70   - GVariant *result = NULL;
71 67  
72   - g_value_init(&value, paction->pspec->value_type);
73   - g_object_get_property(G_OBJECT(terminal), paction->pspec->name, &value);
  68 + g_value_init(&value, action->pspec->value_type);
  69 + g_object_get_property(G_OBJECT(terminal), action->pspec->name, &value);
74 70  
75   - switch(paction->pspec->value_type) {
  71 + switch(action->pspec->value_type) {
  72 + case G_TYPE_UINT:
  73 + result = g_variant_new_take_string(g_strdup_printf("%d",g_value_get_uint(&value)));
  74 + break;
  75 +
  76 + case G_TYPE_STRING:
  77 + result = g_variant_new_string(g_value_get_string(&value));
  78 + break;
  79 + /*
76 80 case G_TYPE_BOOLEAN:
77 81 result = g_variant_new_boolean(g_value_get_boolean(&value));
78 82 break;
... ... @@ -81,11 +85,6 @@
81 85 result = g_variant_new_int32(g_value_get_int(&value));
82 86 break;
83 87  
84   - case G_TYPE_UINT:
85   - result = g_variant_new_uint32(g_value_get_uint(&value));
86   - debug("state of %s is %u",g_action_get_name(action),g_value_get_uint(&value));
87   - break;
88   -
89 88 case G_TYPE_DOUBLE:
90 89 result = g_variant_new_double(g_value_get_double(&value));
91 90 break;
... ... @@ -94,85 +93,133 @@
94 93 result = g_variant_new_double(g_value_get_float(&value));
95 94 break;
96 95  
97   - case G_TYPE_STRING:
98   - result = g_variant_new_string(g_value_get_string(&value));
99   - break;
100   -
  96 + */
  97 + default:
  98 + g_warning("Unexpected value type getting state for action \"%s\"",g_action_get_name(object));
101 99 }
102 100  
103 101 g_value_unset (&value);
104 102  
105   - return result;
106   -
107   - }
108   -
109   - static void activate(GAction *action, GVariant *parameter, GtkWidget *terminal) {
  103 +#ifdef DEBUG
  104 + if(result)
  105 + {
  106 + debug("Action %s set to \"%s\"",g_action_get_name(object),g_variant_get_string(result,NULL));
  107 + }
  108 + else
  109 + {
  110 + debug("Action %s set to \"%s\"",g_action_get_name(object),"NULL");
  111 + }
  112 +#endif // DEBUG
110 113  
111   - debug("%s(%s,%p,%p)",__FUNCTION__,g_action_get_name(action),parameter,terminal);
  114 + return result;
112 115  
113 116 }
114 117  
115   - v3270PropertyAction * v3270_property_action_new(GtkWidget *widget, const gchar *property_name) {
  118 + static void activate(GAction *object, GVariant *parameter, GtkWidget *terminal) {
116 119  
117   - GParamSpec *pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(widget), property_name);
  120 + debug("%s(%s,%s,%p)",__FUNCTION__,g_action_get_name(object),g_variant_get_string(parameter,NULL),terminal);
118 121  
119   - if(~pspec->flags & G_PARAM_READABLE || ~pspec->flags & G_PARAM_WRITABLE || pspec->flags & G_PARAM_CONSTRUCT_ONLY) {
  122 + v3270PropertyAction * action = V3270_PROPERTY_ACTION(object);
120 123  
121   - g_warning(
122   - "Property '%s::%s' must be readable, writable, and not construct-only",
123   - G_OBJECT_TYPE_NAME(G_OBJECT(widget)),
124   - property_name
125   - );
126   -
127   - return NULL;
128   - }
  124 + GValue value = G_VALUE_INIT;
  125 + g_value_init(&value, action->pspec->value_type);
129 126  
130   - // Get state type
131   - const GVariantType * type;
  127 + switch(action->pspec->value_type)
  128 + {
  129 + case G_TYPE_UINT:
  130 + g_value_set_uint(&value,atoi(g_variant_get_string(parameter,NULL)));
  131 + break;
132 132  
133   - switch(pspec->value_type) {
  133 + /*
134 134 case G_TYPE_BOOLEAN:
135   - type = G_VARIANT_TYPE_BOOLEAN;
136   - debug("%s: Type of \"%s\" is %s",__FUNCTION__,property_name,"boolean");
137 135 break;
138 136  
139 137 case G_TYPE_INT:
140   - type = G_VARIANT_TYPE_INT32;
141   - debug("%s: Type of \"%s\" is %s",__FUNCTION__,property_name,"int32");
142 138 break;
143 139  
144   - case G_TYPE_UINT:
145   - type = G_VARIANT_TYPE_UINT32;
146   - debug("%s: Type of \"%s\" is %s",__FUNCTION__,property_name,"uint32");
  140 + case G_TYPE_DOUBLE:
147 141 break;
148 142  
149   - case G_TYPE_DOUBLE:
150 143 case G_TYPE_FLOAT:
151   - type = G_VARIANT_TYPE_DOUBLE;
152 144 break;
153 145  
154 146 case G_TYPE_STRING:
155   - type = G_VARIANT_TYPE_STRING;
156 147 break;
  148 + */
157 149  
158 150 default:
  151 + g_warning("Can't activate action \"%s\"",g_action_get_name(object));
  152 + g_value_unset(&value);
  153 + return;
  154 + }
  155 +
  156 + g_object_set_property(G_OBJECT(terminal),action->pspec->name,&value);
  157 +
  158 + g_value_unset(&value);
  159 +
  160 + }
  161 +
  162 + static void on_notify(GtkWidget G_GNUC_UNUSED(*terminal), GParamSpec G_GNUC_UNUSED(*pspec), GAction *action) {
  163 +
  164 + debug("%s: State of action %s has changed",__FUNCTION__, g_action_get_name(G_ACTION(action)));
  165 + pw3270_action_notify_state(action);
  166 +
  167 + }
  168 +
  169 + GAction * v3270_property_action_new(GtkWidget *widget, const gchar *property_name) {
  170 +
  171 + GParamSpec *pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(widget), property_name);
  172 +
  173 + if(~pspec->flags & G_PARAM_READABLE || ~pspec->flags & G_PARAM_WRITABLE || pspec->flags & G_PARAM_CONSTRUCT_ONLY) {
  174 +
159 175 g_warning(
160   - "Unable to create action for property '%s::%s' of type '%s'",
161   - g_type_name(pspec->owner_type),
162   - pspec->name,
163   - g_type_name(pspec->value_type)
164   - );
  176 + "Property '%s::%s' must be readable, writable, and not construct-only",
  177 + G_OBJECT_TYPE_NAME(G_OBJECT(widget)),
  178 + property_name
  179 + );
  180 +
165 181 return NULL;
166 182 }
167 183  
168 184 v3270PropertyAction * action = (v3270PropertyAction *) g_object_new(V3270_TYPE_PROPERTY_ACTION, NULL);
169 185  
170 186 action->parent.name = pspec->name;
171   - action->parent.types.state = type;
172   - action->parent.types.parameter = type;
  187 + action->parent.types.state = G_VARIANT_TYPE_STRING;
  188 + action->parent.types.parameter = G_VARIANT_TYPE_STRING;
173 189 action->parent.activate = activate;
174 190 action->pspec = pspec;
175 191  
176 192 pw3270_action_set_terminal_widget(G_ACTION(action), widget);
177   - return action;
  193 +
  194 + return G_ACTION(action);
  195 + }
  196 +
  197 + void change_widget(GAction *object, GtkWidget *from, GtkWidget *to) {
  198 +
  199 + v3270PropertyAction * action = V3270_PROPERTY_ACTION(object);
  200 + g_autofree gchar * signal_name = g_strconcat("notify::", action->pspec->name,NULL);
  201 +
  202 + if(from) {
  203 + gulong handler = g_signal_handler_find(
  204 + from,
  205 + G_SIGNAL_MATCH_FUNC|G_SIGNAL_MATCH_DATA,
  206 + 0,
  207 + 0,
  208 + NULL,
  209 + G_CALLBACK(on_notify),
  210 + action
  211 + );
  212 +
  213 + if(handler)
  214 + g_signal_handler_disconnect(from, handler);
  215 +
  216 + }
  217 +
  218 + PW3270_ACTION_CLASS(v3270PropertyAction_parent_class)->change_widget(object,from,to);
  219 +
  220 + if(to) {
  221 + g_signal_connect(G_OBJECT(to),signal_name,G_CALLBACK(on_notify),action);
  222 + }
  223 +
178 224 }
  225 +
... ...
src/objects/application/application.c
... ... @@ -245,6 +245,15 @@
245 245 .name = "open.window",
246 246 .activate = pw3270_application_generic_activated,
247 247 },
  248 +
  249 + /*
  250 + {
  251 + .name = "model-number",
  252 + .activate = model_cb,
  253 + .parameter_type = "s"
  254 + }
  255 + */
  256 +
248 257 };
249 258  
250 259 g_action_map_add_action_entries(
... ... @@ -276,12 +285,35 @@
276 285 // Create terminal widget & associated widget
277 286 GtkWidget * terminal = pw3270_terminal_new(window);
278 287  
  288 + /*
279 289 GAction * action = G_ACTION(v3270_property_action_new(terminal,"model_number"));
280   -
281 290 if(action) {
282 291 debug("Adding window action \"%s\"",g_action_get_name(action));
283 292 g_action_map_add_action(G_ACTION_MAP(window),action);
284 293 }
  294 + */
  295 +
  296 + // https://developer.gnome.org/gnome-devel-demos/stable/menubar.vala.html.en
  297 +
  298 + /*
  299 + static const GActionEntry actions[] = {
  300 +
  301 + {
  302 + .name = "model-number",
  303 + .activate = model_cb,
  304 + .parameter_type = "s",
  305 + .state = "2"
  306 + }
  307 +
  308 + };
  309 +
  310 + g_action_map_add_action_entries(G_ACTION_MAP(window),actions,G_N_ELEMENTS(actions),NULL);
  311 + */
  312 +
  313 + g_action_map_add_action(
  314 + G_ACTION_MAP(window),
  315 + v3270_property_action_new(terminal,"model-number")
  316 + );
285 317  
286 318 // Present the new window
287 319 pw3270_window_set_current_page(window,0);
... ...
src/objects/window/private.h
... ... @@ -70,6 +70,9 @@
70 70 GAction * pw3270_session_preferences_action_new(void);
71 71 GAction * pw3270_file_transfer_action_new(void);
72 72  
  73 + // Terminal actions.
  74 + GAction * pw3270_model_number_action_new(GtkWidget *terminal);
  75 +
73 76 G_GNUC_INTERNAL void pw3270_window_open_activated(GSimpleAction * action, GVariant *parameter, gpointer application);
74 77 G_GNUC_INTERNAL void pw3270_window_close_activated(GSimpleAction * action, GVariant *parameter, gpointer application);
75 78  
... ...
ui/application.xml
... ... @@ -242,23 +242,30 @@
242 242 </item>
243 243  
244 244 <submenu>
  245 +
245 246 <attribute name="label" translatable="yes">Screen size</attribute>
  247 +
  248 + <!-- https://developer.gnome.org/gnome-devel-demos/stable/menubar.vala.html.en -->
  249 +
246 250 <item>
247 251 <attribute name="label" translatable="yes">Model 2 - 80x24</attribute>
248 252 <attribute name="action">win.model-number</attribute>
249   - <attribute name="state">2</attribute>
  253 + <attribute name="target">2</attribute>
250 254 </item>
251 255 <item>
252 256 <attribute name="label" translatable="yes">Model 3 - 80x32</attribute>
253 257 <attribute name="action">win.model-number</attribute>
  258 + <attribute name="target">3</attribute>
254 259 </item>
255 260 <item>
256 261 <attribute name="label" translatable="yes">Model 4 - 80x43</attribute>
257 262 <attribute name="action">win.model-number</attribute>
  263 + <attribute name="target">4</attribute>
258 264 </item>
259 265 <item>
260 266 <attribute name="label" translatable="yes">Model 5 - 132x27</attribute>
261 267 <attribute name="action">win.model-number</attribute>
  268 + <attribute name="target">5</attribute>
262 269 </item>
263 270  
264 271 </submenu>
... ...