Merge lp:~autopilot/autopilot-gtk/experimental into lp:autopilot-gtk

Proposed by Thomi Richards
Status: Merged
Approved by: Martin Pitt
Approved revision: 68
Merged at revision: 53
Proposed branch: lp:~autopilot/autopilot-gtk/experimental
Merge into: lp:autopilot-gtk
Diff against target: 957 lines (+425/-133)
13 files modified
debian/changelog (+7/-0)
debian/control (+4/-4)
debian/rules (+2/-1)
lib/GtkNode.cpp (+147/-60)
lib/GtkNode.h (+18/-8)
lib/GtkRootNode.cpp (+24/-16)
lib/GtkRootNode.h (+5/-3)
lib/Introspection.cpp (+3/-3)
lib/Variant.cpp (+168/-22)
lib/Variant.h (+3/-1)
lib/autopilot_types.h (+34/-0)
tests/autopilot/tests/test_widget_tree.py (+2/-6)
tests/autopilot/tests/test_xpath_query.py (+8/-9)
To merge this branch: bzr merge lp:~autopilot/autopilot-gtk/experimental
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Approve
Martin Pitt (community) Approve
Review via email: mp+185845@code.launchpad.net

Commit message

Version 1.4 wire protocol changes.

Description of the change

Version 1.4 protocol changes.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Martin Pitt (pitti) wrote :

This mostly looks okay visually, except that this needs to grow a

  Breaks: autopilot (<< 1.4)

to avoid trying to install an 1.4 version of libautopilot-gtk with an 1.3 version of autopilot.

Also, actually approving this branch needs to wait for the PS jenkins tests to succeed, which requires landing xpathselect first.

review: Needs Fixing
Revision history for this message
Martin Pitt (pitti) wrote :

Err, of course not "Breaks: autpilot", but "Breaks: python-autopilot (<< 1.4), python3-autopilot (<< 1.4)"

The latter is not strictly necessary as we did'nt yet have p3-ap for 1.3, but it'll provide a nice template for bumping to 1.5 in the future.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Francis Ginther (fginther) wrote :

Autopilot is now in the local archive, re-approve.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Thomi Richards (thomir-deactivatedaccount) wrote :

Above i386 failure was xvfb failing to start, trying again, since it seems like an intermittent failure.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Martin Pitt (pitti) wrote :

The requested Breaks: got added, so changing my vote to approved.

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/changelog'
2--- debian/changelog 2013-06-28 00:01:10 +0000
3+++ debian/changelog 2013-09-17 13:46:39 +0000
4@@ -1,3 +1,10 @@
5+autopilot-gtk (1.4-0ubuntu1) saucy; urgency=low
6+
7+ [ Thomi Richards ]
8+ * Version bump, updatedx to new xpathselect API.
9+
10+ -- Thomi Richards <thomi.richards@canonical.com> Thu, 15 Aug 2013 15:12:39 +1200
11+
12 autopilot-gtk (1.3+13.10.20130628-0ubuntu1) saucy; urgency=low
13
14 [ Martin Pitt ]
15
16=== modified file 'debian/control'
17--- debian/control 2013-06-25 15:35:28 +0000
18+++ debian/control 2013-09-17 13:46:39 +0000
19@@ -7,14 +7,13 @@
20 pkg-config,
21 libglib2.0-dev,
22 libgtk-3-dev,
23- libxpathselect-dev (>= 1.3),
24+ libxpathselect-dev (>= 1.4),
25 xvfb,
26 dbus-x11,
27- python-autopilot,
28- python-xlib,
29+ autopilot-desktop,
30+ bamfdaemon,
31 python-evdev,
32 python-gi,
33- gir1.2-gtk-3.0,
34 gsettings-desktop-schemas,
35 gnome-system-log,
36 Standards-Version: 3.9.4
37@@ -33,6 +32,7 @@
38 Pre-Depends: ${misc:Pre-Depends},
39 Depends: ${shlibs:Depends},
40 ${misc:Depends},
41+Breaks: python-autopilot (<< 1.4), python3-autopilot (<< 1.4)
42 Replaces: autopilot-gtk, libautopilot-gtk0, libautopilot-gtk-dev
43 Conflicts: autopilot-gtk, libautopilot-gtk0, libautopilot-gtk-dev
44 Provides: autopilot-gtk, libautopilot-gtk0
45
46=== modified file 'debian/rules'
47--- debian/rules 2013-06-26 06:05:38 +0000
48+++ debian/rules 2013-09-17 13:46:39 +0000
49@@ -9,7 +9,8 @@
50 override_dh_auto_test:
51 mkdir -p debian/tmp/home/run
52 env HOME=$(CURDIR)/debian/tmp/home XDG_RUNTIME_DIR=$(CURDIR)/debian/tmp/home/run \
53- xvfb-run dh_auto_test
54+ xvfb-run -a -e $(CURDIR)/debian/tmp/X.log dh_auto_test || \
55+ { echo "==== X.org log ===="; cat $(CURDIR)/debian/tmp/X.log; false; }
56
57 override_dh_install:
58 dh_install --fail-missing
59
60=== modified file 'lib/GtkNode.cpp'
61--- lib/GtkNode.cpp 2013-06-27 17:02:58 +0000
62+++ lib/GtkNode.cpp 2013-09-17 13:46:39 +0000
63@@ -25,11 +25,40 @@
64 #include "Variant.h"
65
66 const std::string GtkNode::AP_ID_NAME = "id";
67+static guint32 cur_obj_id = 2; // start at 2 since 1 is reserved for the root node
68
69-GtkNode::GtkNode(GObject* obj, std::string const& parent_path)
70- : object_(obj) {
71+GtkNode::GtkNode(GObject* obj, GtkNode::Ptr const& parent)
72+ : object_(obj)
73+ , parent_(parent)
74+{
75+ std::string parent_path = parent ? parent->GetPath() : "";
76 full_path_ = parent_path + "/" + GetName();
77- if (object_ != NULL) g_object_ref(object_);
78+ if (object_ != NULL)
79+ {
80+ g_object_ref(object_);
81+ GQuark OBJ_ID = g_quark_from_static_string("AUTOPILOT_OBJECT_ID");
82+ gpointer val = g_object_get_qdata (object_, OBJ_ID);
83+ if (val == NULL)
84+ {
85+ g_object_set_qdata (object_, OBJ_ID, reinterpret_cast<gpointer>(cur_obj_id++));
86+ }
87+ }
88+}
89+
90+GtkNode::GtkNode(GObject* obj)
91+ : object_(obj)
92+{
93+ full_path_ = "/" + GetName();
94+ if (object_ != NULL)
95+ {
96+ g_object_ref(object_);
97+ GQuark OBJ_ID = g_quark_from_static_string("AUTOPILOT_OBJECT_ID");
98+ gpointer val = g_object_get_qdata (object_, OBJ_ID);
99+ if (val == NULL)
100+ {
101+ g_object_set_qdata (object_, OBJ_ID, reinterpret_cast<gpointer>(cur_obj_id++));
102+ }
103+ }
104 }
105
106 GtkNode::~GtkNode()
107@@ -109,7 +138,7 @@
108 g_value_init(&value, param_spec->value_type);
109 g_object_get_property(object_, g_param_spec_get_name(param_spec), &value);
110 convert_value(param_spec, &value);
111- builder_wrapper.add(param_spec->name, &value);
112+ builder_wrapper.add_gvalue(param_spec->name, &value);
113 g_value_unset(&value); //Free the memory accquired by the value object. Absence of this was causig the applications to crash.
114 }
115 } else {
116@@ -119,7 +148,7 @@
117 g_free(properties);
118
119 // add our unique autopilot-id
120- builder_wrapper.add(AP_ID_NAME.c_str(), GetObjectId());
121+ builder_wrapper.add(AP_ID_NAME.c_str(), GetId());
122
123 // add the names of our children
124 builder_wrapper.add("Children", GetChildNodeNames());
125@@ -136,9 +165,7 @@
126 if (GDK_IS_WINDOW(gdk_window)) {
127 GdkRectangle rect;
128 GetGlobalRect(&rect);
129- //g_debug("Rect coords %d, %d, %d, %d", rect.x, rect.y, rect.width, rect.height);
130- GVariant *rect_gvariant = ComposeRectVariant(rect.x, rect.y, rect.width, rect.height);
131- builder_wrapper.add("globalRect", rect_gvariant);
132+ builder_wrapper.add("globalRect", rect);
133 }
134 } else if (ATK_IS_COMPONENT(object_)) {
135 AddAtkComponentProperties(builder_wrapper, ATK_COMPONENT(object_));
136@@ -146,18 +173,6 @@
137 return g_variant_builder_end(&builder);
138 }
139
140-GVariant* GtkNode::ComposeRectVariant(gint x, gint y, gint height, gint width) const
141-{
142- //g_debug("composing a rect variant");
143- GVariantBuilder builder;
144- g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
145- g_variant_builder_add(&builder, "i", x);
146- g_variant_builder_add(&builder, "i", y);
147- g_variant_builder_add(&builder, "i", height);
148- g_variant_builder_add(&builder, "i", width);
149- return g_variant_builder_end(&builder);
150-}
151-
152 void GtkNode::AddAtkComponentProperties(variant::BuilderWrapper &builder_wrapper,
153 AtkComponent *atk_component) const
154 {
155@@ -171,8 +186,12 @@
156 x = y = width = height = -1;
157 atk_component_get_extents(atk_component, &x, &y, &width, &height,
158 ATK_XY_SCREEN);
159- GVariant *rect_gvariant = ComposeRectVariant(x, y, width, height);
160- builder_wrapper.add("globalRect", rect_gvariant);
161+ GdkRectangle r;
162+ r.x = x;
163+ r.y = y;
164+ r.width = width;
165+ r.height = height;
166+ builder_wrapper.add("globalRect", r);
167 }
168
169 builder_wrapper.add("active",
170@@ -196,10 +215,6 @@
171 g_object_unref(G_OBJECT(states));
172 }
173
174-intptr_t GtkNode::GetObjectId() const {
175- return reinterpret_cast<intptr_t>(object_);
176-}
177-
178 void GtkNode::GetGlobalRect(GdkRectangle* rect) const
179 {
180 GtkWidget *widget = GTK_WIDGET(object_);
181@@ -233,11 +248,24 @@
182 return full_path_;
183 }
184
185-bool GtkNode::MatchProperty(const std::string& name,
186- const std::string& value) const {
187- if (name == "id")
188- return value == std::to_string(GetObjectId());
189+int32_t GtkNode::GetId() const
190+{
191+ GQuark OBJ_ID = g_quark_from_static_string("AUTOPILOT_OBJECT_ID");
192+ gpointer val = g_object_get_qdata (object_, OBJ_ID);
193+ // this uglyness is required in order to stop the compiler complaining about the fact
194+ // that we're casting a 64 bit type (gpointer) down to a 32 bit type (gint32) and may
195+ // be truncating the value. It's safe to do, however, since we control what values are
196+ // set in this quark, and they were initial gint32 values anyway.
197+ guint32 id = static_cast<gint32>(reinterpret_cast<intptr_t>(val));
198+ return id;
199+}
200
201+xpathselect::Node::Ptr GtkNode::GetParent() const
202+{
203+ return parent_;
204+}
205+bool GtkNode::MatchStringProperty(const std::string& name,
206+ const std::string& value) const {
207 if (name == "BuilderName" && GTK_IS_BUILDABLE(object_)) {
208 const gchar* name = gtk_buildable_get_name(GTK_BUILDABLE (object_));
209 return name != NULL && std::string(name) == value;
210@@ -258,41 +286,100 @@
211 convert_value(pspec, &dest_value);
212 std::string dest_string;
213
214- // convert it to a string; always doing string comparison avoids having to do
215- // type comparison, conversion and error handling on value
216- switch (G_VALUE_TYPE(&dest_value)) {
217- case G_TYPE_INT:
218- dest_string = std::to_string(g_value_get_int(&dest_value));
219- break;
220- case G_TYPE_UINT:
221- dest_string = std::to_string(g_value_get_uint(&dest_value));
222- break;
223- case G_TYPE_DOUBLE:
224- dest_string = std::to_string(g_value_get_double(&dest_value));
225- break;
226- case G_TYPE_STRING: {
227+ if (G_VALUE_TYPE(&dest_value) == G_TYPE_STRING) {
228 const gchar *str = g_value_get_string(&dest_value);
229 dest_string = (str != NULL) ? str : "";
230- break;
231- }
232- default:
233- g_debug("Unhandled type %s for matching property %s",
234- g_type_name(G_VALUE_TYPE(&dest_value)), g_param_spec_get_name(pspec));
235- g_value_unset(&dest_value);
236- return false;
237- }
238-
239- g_value_unset(&dest_value);
240- return dest_string == value;
241-}
242-
243-xpathselect::NodeList GtkNode::Children() const {
244+ g_value_unset(&dest_value);
245+ return dest_string == value;
246+ }
247+ else {
248+ g_debug("Property %s exists, but is not a string (is %s).",
249+ g_param_spec_get_name(pspec),
250+ g_type_name(G_VALUE_TYPE(&dest_value))
251+ );
252+ g_value_unset(&dest_value);
253+ return false;
254+ }
255+
256+}
257+
258+bool GtkNode::MatchIntegerProperty(const std::string& name,
259+ int32_t value) const {
260+ if (name == "id")
261+ return value == GetId();
262+
263+ GObjectClass* klass = G_OBJECT_GET_CLASS(object_);
264+ GParamSpec* pspec = g_object_class_find_property(klass, name.c_str());
265+ if (pspec == NULL)
266+ return false;
267+
268+ // read the property into a GValue
269+ g_debug("Matching property %s of type (%s).", g_param_spec_get_name(pspec),
270+ g_type_name(G_PARAM_SPEC_VALUE_TYPE(pspec)));
271+
272+ GValue dest_value = G_VALUE_INIT;
273+ g_value_init(&dest_value, G_PARAM_SPEC_VALUE_TYPE(pspec));
274+ g_object_get_property(object_, name.c_str(), &dest_value);
275+ convert_value(pspec, &dest_value);
276+
277+ if (G_VALUE_TYPE(&dest_value) == G_TYPE_INT) {
278+ int v = g_value_get_int(&dest_value);
279+ g_value_unset(&dest_value);
280+ return value == v;
281+ }
282+ else if (G_VALUE_TYPE(&dest_value) == G_TYPE_UINT) {
283+ int v = g_value_get_uint(&dest_value);
284+ g_value_unset(&dest_value);
285+ return value == v;
286+ }
287+ else {
288+ g_debug("Property %s exists, but is not an integer (is %s).",
289+ g_param_spec_get_name(pspec),
290+ g_type_name(G_VALUE_TYPE(&dest_value))
291+ );
292+ g_value_unset(&dest_value);
293+ return false;
294+ }
295+}
296+
297+bool GtkNode::MatchBooleanProperty(const std::string& name,
298+ bool value) const {
299+ GObjectClass* klass = G_OBJECT_GET_CLASS(object_);
300+ GParamSpec* pspec = g_object_class_find_property(klass, name.c_str());
301+ if (pspec == NULL)
302+ return false;
303+
304+ // read the property into a GValue
305+ g_debug("Matching property %s of type (%s).", g_param_spec_get_name(pspec),
306+ g_type_name(G_PARAM_SPEC_VALUE_TYPE(pspec)));
307+
308+ GValue dest_value = G_VALUE_INIT;
309+ g_value_init(&dest_value, G_PARAM_SPEC_VALUE_TYPE(pspec));
310+ g_object_get_property(object_, name.c_str(), &dest_value);
311+ convert_value(pspec, &dest_value);
312+
313+ if (G_VALUE_TYPE(&dest_value) == G_TYPE_BOOLEAN) {
314+ bool v = g_value_get_boolean(&dest_value);
315+ g_value_unset(&dest_value);
316+ return value == v;
317+ }
318+ else {
319+ g_debug("Property %s exists, but is not a boolean (is %s).",
320+ g_param_spec_get_name(pspec),
321+ g_type_name(G_VALUE_TYPE(&dest_value))
322+ );
323+ g_value_unset(&dest_value);
324+ return false;
325+ }
326+}
327+
328+xpathselect::NodeVector GtkNode::Children() const {
329 //g_debug("getting the children of a node");
330- xpathselect::NodeList children;
331+ xpathselect::NodeVector children;
332 if (GTK_IS_CONTAINER(object_)) {
333 GList* gtk_children = gtk_container_get_children(GTK_CONTAINER(object_));
334 for (GList* elem = gtk_children; elem; elem = elem->next) {
335- children.push_back(std::make_shared<GtkNode>(G_OBJECT(elem->data), GetPath()));
336+ children.push_back(std::make_shared<GtkNode>(G_OBJECT(elem->data), shared_from_this()));
337 }
338 g_list_free(gtk_children);
339 } else if (ATK_IS_OBJECT(object_)) {
340@@ -300,7 +387,7 @@
341 int n_children = atk_object_get_n_accessible_children(atk_object);
342 for (int i = 0; i < n_children; i++) {
343 AtkObject *child = atk_object_ref_accessible_child(atk_object, i);
344- children.push_back(std::make_shared<GtkNode>(G_OBJECT(child), GetPath()));
345+ children.push_back(std::make_shared<GtkNode>(G_OBJECT(child), shared_from_this()));
346 }
347 }
348
349
350=== modified file 'lib/GtkNode.h'
351--- lib/GtkNode.h 2013-04-21 23:04:43 +0000
352+++ lib/GtkNode.h 2013-09-17 13:46:39 +0000
353@@ -25,33 +25,43 @@
354 #include <xpathselect/node.h>
355 #include <xpathselect/xpathselect.h>
356 #include <string>
357+#include <cstdint>
358 #include "Variant.h"
359
360-class GtkNode: public xpathselect::Node {
361+// #include <memory>
362+
363+class GtkNode: public xpathselect::Node, public std::enable_shared_from_this<GtkNode>
364+{
365 public:
366- typedef std::shared_ptr<GtkNode> Ptr;
367+ typedef std::shared_ptr<const GtkNode> Ptr;
368
369- GtkNode(GObject* object, std::string const& parent_name);
370+ GtkNode(GObject* object, Ptr const& parent);
371+ GtkNode(GObject* object);
372 virtual ~GtkNode();
373
374 virtual GVariant* Introspect() const;
375
376 virtual std::string GetName() const;
377 virtual std::string GetPath() const;
378- virtual bool MatchProperty(const std::string& name,
379- const std::string& value) const;
380- virtual xpathselect::NodeList Children() const;
381+ virtual int32_t GetId() const;
382+ virtual xpathselect::Node::Ptr GetParent() const;
383+ virtual bool MatchStringProperty(const std::string& name,
384+ const std::string& value) const;
385+ virtual bool MatchIntegerProperty(const std::string& name,
386+ int32_t value) const;
387+ virtual bool MatchBooleanProperty(const std::string& name,
388+ bool value) const;
389+ virtual xpathselect::NodeVector Children() const;
390
391 static const std::string AP_ID_NAME;
392
393 private:
394 GObject *object_;
395 std::string full_path_;
396+ Ptr parent_;
397
398 virtual GVariant* GetChildNodeNames() const;
399- virtual intptr_t GetObjectId() const;
400 virtual void GetGlobalRect(GdkRectangle* rect) const;
401- virtual GVariant* ComposeRectVariant(gint x, gint y, gint height, gint width) const;
402 void AddAtkComponentProperties(variant::BuilderWrapper &builder_wrapper,
403 AtkComponent *atk_component) const;
404 };
405
406=== modified file 'lib/GtkRootNode.cpp'
407--- lib/GtkRootNode.cpp 2013-04-21 23:04:43 +0000
408+++ lib/GtkRootNode.cpp 2013-09-17 13:46:39 +0000
409@@ -27,7 +27,7 @@
410 #include "Variant.h"
411
412 GtkRootNode::GtkRootNode()
413- : GtkNode(NULL, std::string()) {
414+ : GtkNode(NULL) {
415 }
416
417 GVariant* GtkRootNode::Introspect() const {
418@@ -35,14 +35,13 @@
419 g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}"));
420 variant::BuilderWrapper builder_wrapper(&builder);
421 // add our unique autopilot-id
422- builder_wrapper.add(AP_ID_NAME.c_str(), GetObjectId());
423+ builder_wrapper.add(AP_ID_NAME.c_str(), GetId());
424 // add the names of our children
425 builder_wrapper.add("Children", GetChildNodeNames());
426 return g_variant_builder_end(&builder);
427 }
428
429-intptr_t GtkRootNode::GetObjectId() const {
430- // FIXME: we could be consistent and return the memory address
431+int32_t GtkRootNode::GetId() const {
432 return 1;
433 }
434
435@@ -54,30 +53,39 @@
436 return "/" + GetName();
437 }
438
439-bool GtkRootNode::MatchProperty(const std::string& name,
440- const std::string& value) const {
441- //g_debug("matching a property for the root node");
442+bool GtkRootNode::MatchIntegerProperty(const std::string& name, int32_t value) const
443+{
444+ // Root node only matches one property - id:
445 if (name == "id")
446- // yes we just compare as a string; use of intptr_t makes casting tricky
447- return value == std::to_string(GetObjectId());
448- return false;
449-}
450-
451-xpathselect::NodeList GtkRootNode::Children() const {
452+ return value == GetId();
453+ return false;
454+}
455+
456+bool GtkRootNode::MatchBooleanProperty(const std::string& name, bool value) const
457+{
458+ return false;
459+}
460+
461+bool GtkRootNode::MatchStringProperty(const std::string& name, const std::string& value) const
462+{
463+ return false;
464+}
465+
466+xpathselect::NodeVector GtkRootNode::Children() const {
467 //g_debug("getting the children of a node");
468- xpathselect::NodeList children;
469+ xpathselect::NodeVector children;
470
471 // add all the toplevel nodes as children to the root node
472 GList* toplevels_list = gtk_window_list_toplevels();
473 GList* elem;
474 for (elem = toplevels_list; elem; elem = elem->next) {
475 GObject *node = reinterpret_cast<GObject*>(elem->data);
476- children.push_back(std::make_shared<GtkNode>(node, GetPath()));
477+ children.push_back(std::make_shared<GtkNode>(node, shared_from_this()));
478
479 // if the AtkObjects are available, expose the Atk hierarchy as well
480 AtkObject *atk_object = gtk_widget_get_accessible(GTK_WIDGET(node));
481 if (atk_object != NULL)
482- children.push_back(std::make_shared<GtkNode>(G_OBJECT(atk_object), GetPath()));
483+ children.push_back(std::make_shared<GtkNode>(G_OBJECT(atk_object), shared_from_this()));
484 }
485 g_list_free(toplevels_list);
486 return children;
487
488=== modified file 'lib/GtkRootNode.h'
489--- lib/GtkRootNode.h 2013-04-18 05:10:07 +0000
490+++ lib/GtkRootNode.h 2013-09-17 13:46:39 +0000
491@@ -33,12 +33,14 @@
492 GtkRootNode();
493
494 virtual GVariant* Introspect() const;
495- virtual intptr_t GetObjectId() const;
496
497 virtual std::string GetName() const;
498 virtual std::string GetPath() const;
499- virtual bool MatchProperty(const std::string& name, const std::string& value) const;
500- virtual xpathselect::NodeList Children() const;
501+ virtual int32_t GetId() const;
502+ virtual bool MatchIntegerProperty(const std::string& name, int32_t value) const;
503+ virtual bool MatchBooleanProperty(const std::string& name, bool value) const;
504+ virtual bool MatchStringProperty(const std::string& name, const std::string& value) const;
505+ virtual xpathselect::NodeVector Children() const;
506
507 private:
508 virtual GVariant* GetChildNodeNames() const;
509
510=== modified file 'lib/Introspection.cpp'
511--- lib/Introspection.cpp 2013-05-08 02:52:12 +0000
512+++ lib/Introspection.cpp 2013-09-17 13:46:39 +0000
513@@ -82,7 +82,7 @@
514 {
515 autopilot_introspection_complete_get_version(introspection_service,
516 invocation,
517- "1.3");
518+ "1.4");
519 return TRUE;
520 }
521
522@@ -110,12 +110,12 @@
523
524 //g_debug("selecting nodes");
525 std::list<GtkNode::Ptr> node_list;
526- xpathselect::NodeList selected_nodes_list;
527+ xpathselect::NodeVector selected_nodes_list;
528 selected_nodes_list = xpathselect::SelectNodes(root, query_string);
529 //g_debug("finished selecting nodes");
530 for (auto node : selected_nodes_list) {
531 // node may be our root node wrapper *or* an ordinary GObject wrapper
532- auto object_ptr = std::static_pointer_cast<GtkNode>(node);
533+ auto object_ptr = std::static_pointer_cast<const GtkNode>(node);
534 if (object_ptr)
535 node_list.push_back(object_ptr);
536 }
537
538=== modified file 'lib/Variant.cpp'
539--- lib/Variant.cpp 2013-02-13 02:38:30 +0000
540+++ lib/Variant.cpp 2013-09-17 13:46:39 +0000
541@@ -17,9 +17,12 @@
542 * Authored by: Tim Penhey <tim.penhey@canonical.com>
543 */
544
545+#include <gdk/gdk.h>
546+
547 #include <iostream>
548 #include "Variant.h"
549
550+#include "autopilot_types.h"
551 namespace variant
552 {
553
554@@ -29,82 +32,210 @@
555
556 BuilderWrapper& BuilderWrapper::add(char const* name, bool value)
557 {
558- g_variant_builder_add(builder_, "{sv}", name, g_variant_new_boolean(value));
559+ GVariantBuilder b;
560+ g_variant_builder_init(&b, G_VARIANT_TYPE("av"));
561+
562+ g_variant_builder_add(&b, "v", g_variant_new_int32(TYPE_PLAIN));
563+ g_variant_builder_add(&b, "v", g_variant_new_boolean(value));
564+
565+ g_variant_builder_add(
566+ builder_,
567+ "{sv}",
568+ name,
569+ g_variant_builder_end(&b)
570+ );
571 return *this;
572 }
573
574 BuilderWrapper& BuilderWrapper::add(char const* name, char const* value)
575 {
576+ GVariantBuilder b;
577+ g_variant_builder_init(&b, G_VARIANT_TYPE("av"));
578+
579+ g_variant_builder_add(&b, "v", g_variant_new_int32(TYPE_PLAIN));
580 if (value)
581- g_variant_builder_add(builder_, "{sv}", name, g_variant_new_string(value));
582+ g_variant_builder_add(&b, "v", g_variant_new_string(value));
583 else
584- g_variant_builder_add(builder_, "{sv}", name, g_variant_new_string(""));
585+ g_variant_builder_add(&b, "v", g_variant_new_string(""));
586+
587+ g_variant_builder_add(
588+ builder_,
589+ "{sv}",
590+ name,
591+ g_variant_builder_end(&b)
592+ );
593
594 return *this;
595 }
596
597 BuilderWrapper& BuilderWrapper::add(char const* name, std::string const& value)
598 {
599- g_variant_builder_add(builder_, "{sv}", name,
600- g_variant_new_string(value.c_str()));
601+ GVariantBuilder b;
602+ g_variant_builder_init(&b, G_VARIANT_TYPE("av"));
603+
604+ g_variant_builder_add(&b, "v", g_variant_new_int32(TYPE_PLAIN));
605+ g_variant_builder_add(&b, "v", g_variant_new_string(value.c_str()));
606+
607+ g_variant_builder_add(
608+ builder_,
609+ "{sv}",
610+ name,
611+ g_variant_builder_end(&b)
612+ );
613 return *this;
614 }
615
616 BuilderWrapper& BuilderWrapper::add(char const* name, int value)
617 {
618- g_variant_builder_add(builder_, "{sv}", name, g_variant_new_int32(value));
619+ GVariantBuilder b;
620+ g_variant_builder_init(&b, G_VARIANT_TYPE("av"));
621+
622+ g_variant_builder_add(&b, "v", g_variant_new_int32(TYPE_PLAIN));
623+ g_variant_builder_add(&b, "v", g_variant_new_int32(value));
624+
625+ g_variant_builder_add(
626+ builder_,
627+ "{sv}",
628+ name,
629+ g_variant_builder_end(&b)
630+ );
631 return *this;
632 }
633
634 BuilderWrapper& BuilderWrapper::add(char const* name, long int value)
635 {
636- g_variant_builder_add(builder_, "{sv}", name, g_variant_new_int64(value));
637+ GVariantBuilder b;
638+ g_variant_builder_init(&b, G_VARIANT_TYPE("av"));
639+
640+ g_variant_builder_add(&b, "v", g_variant_new_int32(TYPE_PLAIN));
641+ g_variant_builder_add(&b, "v", g_variant_new_int64(value));
642+ g_variant_builder_add(
643+ builder_,
644+ "{sv}",
645+ name,
646+ g_variant_builder_end(&b)
647+ );
648 return *this;
649 }
650
651 BuilderWrapper& BuilderWrapper::add(char const* name, long long int value)
652 {
653- g_variant_builder_add(builder_, "{sv}", name, g_variant_new_int64(value));
654+ GVariantBuilder b;
655+ g_variant_builder_init(&b, G_VARIANT_TYPE("av"));
656+
657+ g_variant_builder_add(&b, "v", g_variant_new_int32(TYPE_PLAIN));
658+ g_variant_builder_add(&b, "v", g_variant_new_int64(value));
659+ g_variant_builder_add(
660+ builder_,
661+ "{sv}",
662+ name,
663+ g_variant_builder_end(&b)
664+ );
665 return *this;
666 }
667
668 BuilderWrapper& BuilderWrapper::add(char const* name, unsigned int value)
669 {
670- g_variant_builder_add(builder_, "{sv}", name, g_variant_new_uint32(value));
671+ GVariantBuilder b;
672+ g_variant_builder_init(&b, G_VARIANT_TYPE("av"));
673+
674+ g_variant_builder_add(&b, "v", g_variant_new_int32(TYPE_PLAIN));
675+ g_variant_builder_add(&b, "v", g_variant_new_uint32(value));
676+ g_variant_builder_add(
677+ builder_,
678+ "{sv}",
679+ name,
680+ g_variant_builder_end(&b)
681+ );
682 return *this;
683 }
684
685 BuilderWrapper& BuilderWrapper::add(char const* name, long unsigned int value)
686 {
687- g_variant_builder_add(builder_, "{sv}", name, g_variant_new_uint64(value));
688+ GVariantBuilder b;
689+ g_variant_builder_init(&b, G_VARIANT_TYPE("av"));
690+
691+ g_variant_builder_add(&b, "v", g_variant_new_int32(TYPE_PLAIN));
692+ g_variant_builder_add(&b, "v", g_variant_new_uint64(value));
693+
694+ g_variant_builder_add(
695+ builder_,
696+ "{sv}",
697+ name,
698+ g_variant_builder_end(&b)
699+ );
700 return *this;
701 }
702
703 BuilderWrapper& BuilderWrapper::add(char const* name, long long unsigned int value)
704 {
705- g_variant_builder_add(builder_, "{sv}", name, g_variant_new_uint64(value));
706+ GVariantBuilder b;
707+ g_variant_builder_init(&b, G_VARIANT_TYPE("av"));
708+
709+ g_variant_builder_add(&b, "v", g_variant_new_int32(TYPE_PLAIN));
710+ g_variant_builder_add(&b, "v", g_variant_new_uint64(value));
711+ g_variant_builder_add(
712+ builder_,
713+ "{sv}",
714+ name,
715+ g_variant_builder_end(&b)
716+ );
717 return *this;
718 }
719
720 BuilderWrapper& BuilderWrapper::add(char const* name, float value)
721 {
722- g_variant_builder_add(builder_, "{sv}", name, g_variant_new_double(value));
723+ GVariantBuilder b;
724+ g_variant_builder_init(&b, G_VARIANT_TYPE("av"));
725+
726+ g_variant_builder_add(&b, "v", g_variant_new_int32(TYPE_PLAIN));
727+ g_variant_builder_add(&b, "v", g_variant_new_double(value));
728+ g_variant_builder_add(
729+ builder_,
730+ "{sv}",
731+ name,
732+ g_variant_builder_end(&b)
733+ );
734 return *this;
735 }
736
737 BuilderWrapper& BuilderWrapper::add(char const* name, double value)
738 {
739- g_variant_builder_add(builder_, "{sv}", name, g_variant_new_double(value));
740+ GVariantBuilder b;
741+ g_variant_builder_init(&b, G_VARIANT_TYPE("av"));
742+
743+ g_variant_builder_add(&b, "v", g_variant_new_int32(TYPE_PLAIN));
744+ g_variant_builder_add(&b, "v", g_variant_new_double(value));
745+
746+ g_variant_builder_add(
747+ builder_,
748+ "{sv}",
749+ name,
750+ g_variant_builder_end(&b)
751+ );
752 return *this;
753 }
754
755 BuilderWrapper& BuilderWrapper::add(char const* name, GVariant* value)
756 {
757- g_variant_builder_add(builder_, "{sv}", name, value);
758+ if (value)
759+ {
760+ GVariantBuilder b;
761+ g_variant_builder_init(&b, G_VARIANT_TYPE("av"));
762+
763+ g_variant_builder_add(&b, "v", g_variant_new_int32(TYPE_PLAIN));
764+ g_variant_builder_add(&b, "v", value);
765+ g_variant_builder_add(
766+ builder_,
767+ "{sv}",
768+ name,
769+ g_variant_builder_end(&b)
770+ );
771+ }
772 return *this;
773 }
774
775-BuilderWrapper& BuilderWrapper::add(char const* name, GValue* value)
776+BuilderWrapper& BuilderWrapper::add_gvalue(char const* name, GValue* value)
777 {
778 switch (G_VALUE_TYPE(value)) {
779 case G_TYPE_CHAR:
780@@ -119,7 +250,7 @@
781 break;
782 case G_TYPE_BOOLEAN:
783 {
784- add(name, g_value_get_boolean(value));
785+ add(name, (bool) g_value_get_boolean(value));
786 }
787 break;
788 case G_TYPE_INT:
789@@ -197,17 +328,32 @@
790 add(name, g_value_get_object(value));
791 }
792 break;
793- case G_TYPE_VARIANT:
794- {
795- add(name, g_value_get_variant(value));
796- }
797- break;
798 default:
799- //g_warning("unsupported type: %s", g_type_name(G_VALUE_TYPE(value)));
800+ g_warning("unsupported type: %s", g_type_name(G_VALUE_TYPE(value)));
801 {}
802 break;
803 }
804 return *this;
805 }
806
807+BuilderWrapper& BuilderWrapper::BuilderWrapper::add(char const* name, GdkRectangle value)
808+{
809+ GVariantBuilder b;
810+ g_variant_builder_init(&b, G_VARIANT_TYPE("av"));
811+
812+ g_variant_builder_add(&b, "v", g_variant_new_int32(TYPE_RECT));
813+ g_variant_builder_add(&b, "v", g_variant_new_int32(value.x));
814+ g_variant_builder_add(&b, "v", g_variant_new_int32(value.y));
815+ g_variant_builder_add(&b, "v", g_variant_new_int32(value.width));
816+ g_variant_builder_add(&b, "v", g_variant_new_int32(value.height));
817+
818+ g_variant_builder_add(
819+ builder_,
820+ "{sv}",
821+ name,
822+ g_variant_builder_end(&b)
823+ );
824+ return *this;
825+}
826+
827 }
828
829=== modified file 'lib/Variant.h'
830--- lib/Variant.h 2013-02-13 02:38:30 +0000
831+++ lib/Variant.h 2013-09-17 13:46:39 +0000
832@@ -46,7 +46,9 @@
833 BuilderWrapper& add(char const* name, float value);
834 BuilderWrapper& add(char const* name, double value);
835 BuilderWrapper& add(char const* name, GVariant* value);
836- BuilderWrapper& add(char const* name, GValue* value);
837+ BuilderWrapper& add_gvalue(char const* name, GValue* value);
838+
839+ BuilderWrapper& add(char const* name, GdkRectangle value);
840
841 private:
842 GVariantBuilder* builder_;
843
844=== added file 'lib/autopilot_types.h'
845--- lib/autopilot_types.h 1970-01-01 00:00:00 +0000
846+++ lib/autopilot_types.h 2013-09-17 13:46:39 +0000
847@@ -0,0 +1,34 @@
848+/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
849+ * Copyright (C) 2013 Canonical Ltd
850+ *
851+ * This program is free software: you can redistribute it and/or modify
852+ * it under the terms of the GNU General Public License version 3 as
853+ * published by the Free Software Foundation.
854+ *
855+ * This program is distributed in the hope that it will be useful,
856+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
857+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
858+ * GNU General Public License for more details.
859+ *
860+ * You should have received a copy of the GNU General Public License
861+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
862+ *
863+ */
864+
865+#ifndef AUTOPILOT_TYPES_H
866+#define AUTOPILOT_TYPES_H
867+
868+/// IMPORTANT: THese constants are taken from the autopilot XPathSelect protocol document.
869+/// Only add options here if the support has been added for them in autopilot itself.
870+enum autopilot_type_id
871+{
872+ TYPE_PLAIN = 0,
873+ TYPE_RECT = 1,
874+ TYPE_POINT = 2,
875+ TYPE_SIZE = 3,
876+ TYPE_COLOR = 4,
877+ TYPE_DATETIME = 5,
878+ TYPE_TIME = 6,
879+};
880+
881+#endif
882
883=== modified file 'tests/autopilot/tests/test_widget_tree.py'
884--- tests/autopilot/tests/test_widget_tree.py 2013-06-26 09:31:14 +0000
885+++ tests/autopilot/tests/test_widget_tree.py 2013-09-17 13:46:39 +0000
886@@ -79,7 +79,7 @@
887
888 # qualified: visible property is not unique
889 self.assertRaises(ValueError,
890- self.app.select_single, 'GtkButton', visible=1)
891+ self.app.select_single, 'GtkButton', visible=True)
892
893 # qualified: label property is unique within GtkButton
894 w = self.app.select_single('GtkButton', label='gtk-quit')
895@@ -98,7 +98,7 @@
896 self.assertRaises(ValueError, self.app.select_single, label='gtk-quit')
897
898 # ... but it is unique for focussable widgets (menus don't allow that)
899- w = self.app.select_single(label='gtk-quit', can_focus=1)
900+ w = self.app.select_single(label='gtk-quit', can_focus=True)
901 self.assertIn('.GtkButton', str(type(w)))
902 self.assertEqual(w.label, 'gtk-quit')
903
904@@ -141,8 +141,6 @@
905 # button and menu item
906 self.assertEqual(len(res), 2)
907
908- # https://launchpad.net/bugs/1194763
909- @unittest.expectedFailure
910 def test_select_int(self):
911 """select_*() with int properties"""
912
913@@ -158,8 +156,6 @@
914
915 self.assertNotEqual(self.app.select_single(border_width=2), None)
916
917- # https://launchpad.net/bugs/1194763
918- @unittest.expectedFailure
919 def test_select_bool(self):
920 """select_*() with boolean properties"""
921
922
923=== modified file 'tests/autopilot/tests/test_xpath_query.py'
924--- tests/autopilot/tests/test_xpath_query.py 2013-06-25 12:58:00 +0000
925+++ tests/autopilot/tests/test_xpath_query.py 2013-09-17 13:46:39 +0000
926@@ -83,23 +83,22 @@
927 def test_select_by_attribute(self):
928 """Select widgets with attribute pattern"""
929
930- state = self.app.get_state_by_path('//*[label=gtk-delete]')
931+ state = self.app.get_state_by_path('//*[label="gtk-delete"]')
932 self.assertEqual(len(state), 1, state)
933- self.assertEqual(state[0][1]['label'], 'gtk-delete')
934+ self.assertEqual(state[0][1]['label'], [0, 'gtk-delete'])
935 self.assertTrue(state[0][0].endswith('/GtkButton'), state[0][0])
936
937 # https://launchpad.net/bugs/1179806
938+ # TODO: Make this pass!
939 @unittest.expectedFailure
940 def test_select_by_attribute_spaces(self):
941 """Select widgets with attribute pattern containing spaces"""
942
943- # none of these work ATM, but are supposed to:
944- #state = self.app.get_state_by_path('//*[label=Hello&#x20;Color!]')
945- #state = self.app.get_state_by_path('//*[label=Hello&#x0020;Color!]')
946- state = self.app.get_state_by_path('//*[label="Hello Color!"]')
947- self.assertEqual(len(state), 1, str(state))
948- self.assertEqual(state[0][1]['label'], 'Hello Color!')
949- self.assertTrue(state[0][0].endswith('/GtkLabel'), state[0][0])
950+ for state_str in ('//*[label="Hello\\x20Color!"]', '//*[label="Hello Color!"]'):
951+ state = self.app.get_state_by_path(state_str)
952+ self.assertEqual(len(state), 1, str(state))
953+ self.assertEqual(state[0][1]['label'], 'Hello Color!')
954+ self.assertTrue(state[0][0].endswith('/GtkLabel'), state[0][0])
955
956 @classmethod
957 def _get_widgets(klass, obj, widget_set):

Subscribers

People subscribed via source and target branches

to all changes: