Commit bfef8307494346155ef070b85c6b57437e50e330

Authored by Perry Werneck
1 parent 76737a9e

Implementing v3270 property based action.

src/include/pw3270/actions.h
@@ -70,6 +70,8 @@ @@ -70,6 +70,8 @@
70 /// @brief Get State method. 70 /// @brief Get State method.
71 GVariant * (*get_state_property)(GAction *action, GtkWidget *terminal); 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 } pw3270Action; 76 } pw3270Action;
75 77
@@ -209,7 +211,7 @@ @@ -209,7 +211,7 @@
209 211
210 GType v3270PropertyAction_get_type(void) G_GNUC_CONST; 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 G_END_DECLS 216 G_END_DECLS
215 217
src/objects/actions/abstract.c
@@ -49,6 +49,7 @@ @@ -49,6 +49,7 @@
49 static GVariant * internal_get_state_property(GAction *action, GtkWidget *terminal); 49 static GVariant * internal_get_state_property(GAction *action, GtkWidget *terminal);
50 static gboolean internal_get_enabled(GAction *action, GtkWidget *terminal); 50 static gboolean internal_get_enabled(GAction *action, GtkWidget *terminal);
51 static void internal_activate(GAction *action, GVariant *parameter, GtkWidget *terminal); 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 static const GVariantType * get_parameter_type(GAction *action); 54 static const GVariantType * get_parameter_type(GAction *action);
54 static GVariant * get_state_hint(GAction *action); 55 static GVariant * get_state_hint(GAction *action);
@@ -176,6 +177,7 @@ @@ -176,6 +177,7 @@
176 177
177 action->activate = internal_activate; 178 action->activate = internal_activate;
178 action->get_state_property = internal_get_state_property; 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,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 GVariant * internal_get_state_property(GAction *object, GtkWidget G_GNUC_UNUSED(*terminal)) { 275 GVariant * internal_get_state_property(GAction *object, GtkWidget G_GNUC_UNUSED(*terminal)) {
270 276
271 pw3270Action * action = PW3270_ACTION(object); 277 pw3270Action * action = PW3270_ACTION(object);
@@ -300,11 +306,12 @@ @@ -300,11 +306,12 @@
300 return PW3270_ACTION(object)->types.state; 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 debug("%s",__FUNCTION__) 315 debug("%s",__FUNCTION__)
309 } 316 }
310 317
src/objects/actions/v3270/property.c
@@ -37,18 +37,19 @@ @@ -37,18 +37,19 @@
37 */ 37 */
38 38
39 #include "../private.h" 39 #include "../private.h"
  40 + #include <stdlib.h>
40 #include <pw3270/window.h> 41 #include <pw3270/window.h>
41 #include <v3270.h> 42 #include <v3270.h>
42 43
43 static void v3270PropertyAction_class_init(v3270PropertyActionClass *klass); 44 static void v3270PropertyAction_class_init(v3270PropertyActionClass *klass);
44 static void v3270PropertyAction_init(v3270PropertyAction *action); 45 static void v3270PropertyAction_init(v3270PropertyAction *action);
45 static GVariant * get_state(GAction *action, GtkWidget *terminal); 46 static GVariant * get_state(GAction *action, GtkWidget *terminal);
46 - 47 + static void change_widget(GAction *object, GtkWidget *from, GtkWidget *to);
47 48
48 G_DEFINE_TYPE(v3270PropertyAction, v3270PropertyAction, PW3270_TYPE_ACTION); 49 G_DEFINE_TYPE(v3270PropertyAction, v3270PropertyAction, PW3270_TYPE_ACTION);
49 50
50 void v3270PropertyAction_class_init(v3270PropertyActionClass *klass) { 51 void v3270PropertyAction_class_init(v3270PropertyActionClass *klass) {
51 - 52 + klass->parent_class.change_widget = change_widget;
52 } 53 }
53 54
54 static void v3270PropertyAction_init(v3270PropertyAction *action) { 55 static void v3270PropertyAction_init(v3270PropertyAction *action) {
@@ -57,22 +58,25 @@ @@ -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 GValue value = G_VALUE_INIT; 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 case G_TYPE_BOOLEAN: 80 case G_TYPE_BOOLEAN:
77 result = g_variant_new_boolean(g_value_get_boolean(&value)); 81 result = g_variant_new_boolean(g_value_get_boolean(&value));
78 break; 82 break;
@@ -81,11 +85,6 @@ @@ -81,11 +85,6 @@
81 result = g_variant_new_int32(g_value_get_int(&value)); 85 result = g_variant_new_int32(g_value_get_int(&value));
82 break; 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 case G_TYPE_DOUBLE: 88 case G_TYPE_DOUBLE:
90 result = g_variant_new_double(g_value_get_double(&value)); 89 result = g_variant_new_double(g_value_get_double(&value));
91 break; 90 break;
@@ -94,85 +93,133 @@ @@ -94,85 +93,133 @@
94 result = g_variant_new_double(g_value_get_float(&value)); 93 result = g_variant_new_double(g_value_get_float(&value));
95 break; 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 g_value_unset (&value); 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 case G_TYPE_BOOLEAN: 134 case G_TYPE_BOOLEAN:
135 - type = G_VARIANT_TYPE_BOOLEAN;  
136 - debug("%s: Type of \"%s\" is %s",__FUNCTION__,property_name,"boolean");  
137 break; 135 break;
138 136
139 case G_TYPE_INT: 137 case G_TYPE_INT:
140 - type = G_VARIANT_TYPE_INT32;  
141 - debug("%s: Type of \"%s\" is %s",__FUNCTION__,property_name,"int32");  
142 break; 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 break; 141 break;
148 142
149 - case G_TYPE_DOUBLE:  
150 case G_TYPE_FLOAT: 143 case G_TYPE_FLOAT:
151 - type = G_VARIANT_TYPE_DOUBLE;  
152 break; 144 break;
153 145
154 case G_TYPE_STRING: 146 case G_TYPE_STRING:
155 - type = G_VARIANT_TYPE_STRING;  
156 break; 147 break;
  148 + */
157 149
158 default: 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 g_warning( 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 return NULL; 181 return NULL;
166 } 182 }
167 183
168 v3270PropertyAction * action = (v3270PropertyAction *) g_object_new(V3270_TYPE_PROPERTY_ACTION, NULL); 184 v3270PropertyAction * action = (v3270PropertyAction *) g_object_new(V3270_TYPE_PROPERTY_ACTION, NULL);
169 185
170 action->parent.name = pspec->name; 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 action->parent.activate = activate; 189 action->parent.activate = activate;
174 action->pspec = pspec; 190 action->pspec = pspec;
175 191
176 pw3270_action_set_terminal_widget(G_ACTION(action), widget); 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,6 +245,15 @@
245 .name = "open.window", 245 .name = "open.window",
246 .activate = pw3270_application_generic_activated, 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 g_action_map_add_action_entries( 259 g_action_map_add_action_entries(
@@ -276,12 +285,35 @@ @@ -276,12 +285,35 @@
276 // Create terminal widget & associated widget 285 // Create terminal widget & associated widget
277 GtkWidget * terminal = pw3270_terminal_new(window); 286 GtkWidget * terminal = pw3270_terminal_new(window);
278 287
  288 + /*
279 GAction * action = G_ACTION(v3270_property_action_new(terminal,"model_number")); 289 GAction * action = G_ACTION(v3270_property_action_new(terminal,"model_number"));
280 -  
281 if(action) { 290 if(action) {
282 debug("Adding window action \"%s\"",g_action_get_name(action)); 291 debug("Adding window action \"%s\"",g_action_get_name(action));
283 g_action_map_add_action(G_ACTION_MAP(window),action); 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 // Present the new window 318 // Present the new window
287 pw3270_window_set_current_page(window,0); 319 pw3270_window_set_current_page(window,0);
src/objects/window/private.h
@@ -70,6 +70,9 @@ @@ -70,6 +70,9 @@
70 GAction * pw3270_session_preferences_action_new(void); 70 GAction * pw3270_session_preferences_action_new(void);
71 GAction * pw3270_file_transfer_action_new(void); 71 GAction * pw3270_file_transfer_action_new(void);
72 72
  73 + // Terminal actions.
  74 + GAction * pw3270_model_number_action_new(GtkWidget *terminal);
  75 +
73 G_GNUC_INTERNAL void pw3270_window_open_activated(GSimpleAction * action, GVariant *parameter, gpointer application); 76 G_GNUC_INTERNAL void pw3270_window_open_activated(GSimpleAction * action, GVariant *parameter, gpointer application);
74 G_GNUC_INTERNAL void pw3270_window_close_activated(GSimpleAction * action, GVariant *parameter, gpointer application); 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,23 +242,30 @@
242 </item> 242 </item>
243 243
244 <submenu> 244 <submenu>
  245 +
245 <attribute name="label" translatable="yes">Screen size</attribute> 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 <item> 250 <item>
247 <attribute name="label" translatable="yes">Model 2 - 80x24</attribute> 251 <attribute name="label" translatable="yes">Model 2 - 80x24</attribute>
248 <attribute name="action">win.model-number</attribute> 252 <attribute name="action">win.model-number</attribute>
249 - <attribute name="state">2</attribute> 253 + <attribute name="target">2</attribute>
250 </item> 254 </item>
251 <item> 255 <item>
252 <attribute name="label" translatable="yes">Model 3 - 80x32</attribute> 256 <attribute name="label" translatable="yes">Model 3 - 80x32</attribute>
253 <attribute name="action">win.model-number</attribute> 257 <attribute name="action">win.model-number</attribute>
  258 + <attribute name="target">3</attribute>
254 </item> 259 </item>
255 <item> 260 <item>
256 <attribute name="label" translatable="yes">Model 4 - 80x43</attribute> 261 <attribute name="label" translatable="yes">Model 4 - 80x43</attribute>
257 <attribute name="action">win.model-number</attribute> 262 <attribute name="action">win.model-number</attribute>
  263 + <attribute name="target">4</attribute>
258 </item> 264 </item>
259 <item> 265 <item>
260 <attribute name="label" translatable="yes">Model 5 - 132x27</attribute> 266 <attribute name="label" translatable="yes">Model 5 - 132x27</attribute>
261 <attribute name="action">win.model-number</attribute> 267 <attribute name="action">win.model-number</attribute>
  268 + <attribute name="target">5</attribute>
262 </item> 269 </item>
263 270
264 </submenu> 271 </submenu>