From 40e417eaffdf1d2b90bb6673ab430693944d83a2 Mon Sep 17 00:00:00 2001 From: Riad Lezzar Date: Thu, 2 Apr 2015 11:17:29 +0200 Subject: [PATCH 1/2] At Widget creation, recursively iterate throught GItems data --- client/funq/models.py | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/client/funq/models.py b/client/funq/models.py index 1aa48c7..ee69686 100644 --- a/client/funq/models.py +++ b/client/funq/models.py @@ -76,9 +76,35 @@ def create(cls, client, data): Allow to create an instance of the class given some data coming from decoded json. """ + + def get_recursive_items(data): + """ + Recursively iterate throught the data to extract every item. + """ + if not data: + return [] + + return [ + x for subx in [ + [ + cls.ITEM_CLASS.create(client, v1) + for v1 in items['items'] + ] + get_recursive_items(items['items']) + for items in data + ] for x in subx + ] + + return [] + self = cls() self.client = client - self.items = [cls.ITEM_CLASS.create(client, v1) for v1 in data['items']] + + if cls.ITEM_CLASS == GItem: + self.items = get_recursive_items([data]) + else: + self.items = [ + cls.ITEM_CLASS.create(client, v1) for v1 in data['items'] + ] return self def iter(self): From f33f29a0f67e167dbbeb0d43c8822bc9140b598f Mon Sep 17 00:00:00 2001 From: Riad Lezzar Date: Thu, 2 Apr 2015 14:09:00 +0200 Subject: [PATCH 2/2] Add a mouse move feature --- client/funq/client.py | 25 ++++++++++++++++ client/funq/models.py | 43 +++++++++++----------------- server/libFunq/dragndropresponse.cpp | 2 +- server/libFunq/dragndropresponse.h | 3 ++ server/libFunq/player.cpp | 43 ++++++++++++++++++++++++++++ server/libFunq/player.h | 1 + 6 files changed, 89 insertions(+), 28 deletions(-) diff --git a/client/funq/client.py b/client/funq/client.py index 68d7624..eb9c9b3 100644 --- a/client/funq/client.py +++ b/client/funq/client.py @@ -313,6 +313,31 @@ def drag_n_drop(self, src_widget, src_pos=None, srcpos=src_pos, destpos=dest_pos) + def mouse_move(self, ref_widget, src_pos=None, dest_pos=None, + key_press=False): + """ + Simulate a mouse move event. + + :param ref_widget: widget source + :param src_pos: starting position for the drag. If None, the center + of `ref_widget` will be used, else it must be a + tuple (x, y) in widget coordinates. + :param dest_pos: ending position for the drop. If None, the center + of `ref_widget` will be used, else it must be a + tuple (x, y) in widget coordinates. + """ + + if src_pos is not None: + src_pos = ','.join(map(str, src_pos)) + if dest_pos is not None: + dest_pos = ','.join(map(str, dest_pos)) + + self.send_command("widget_mouse_move", + oid=ref_widget.oid, + srcpos=src_pos, + destpos=dest_pos, + keypress=key_press) + class ApplicationContext(object): # pylint: disable=R0903 """ This is the context of a tested application. diff --git a/client/funq/models.py b/client/funq/models.py index ee69686..97667da 100644 --- a/client/funq/models.py +++ b/client/funq/models.py @@ -76,35 +76,9 @@ def create(cls, client, data): Allow to create an instance of the class given some data coming from decoded json. """ - - def get_recursive_items(data): - """ - Recursively iterate throught the data to extract every item. - """ - if not data: - return [] - - return [ - x for subx in [ - [ - cls.ITEM_CLASS.create(client, v1) - for v1 in items['items'] - ] + get_recursive_items(items['items']) - for items in data - ] for x in subx - ] - - return [] - self = cls() self.client = client - - if cls.ITEM_CLASS == GItem: - self.items = get_recursive_items([data]) - else: - self.items = [ - cls.ITEM_CLASS.create(client, v1) for v1 in data['items'] - ] + self.items = [cls.ITEM_CLASS.create(client, v1) for v1 in data['items']] return self def iter(self): @@ -298,6 +272,21 @@ def drag_n_drop(self, src_pos=None, self.client.drag_n_drop(self, src_pos=src_pos, dest_widget=dest_widget, dest_pos=dest_pos) + def mouse_move(self, src_pos=None, dest_pos=None): + """ + + Simulate a mouse move event. + :param src_pos: starting position for the drag. If None, the center + of `self` will be used, else it must be a + tuple (x, y) in widget coordinates. + :param dest_pos: ending position for the drop. If None, the center + of `self` will be used, else it must be a + tuple (x, y) in widget coordinates. + """ + self.client.mouse_move(ref_widget=self, + src_pos=src_pos, + dest_pos=dest_pos) + def close(self): """ Ask to close a widget, using QWidget::close(). diff --git a/server/libFunq/dragndropresponse.cpp b/server/libFunq/dragndropresponse.cpp index 23456a9..59252e0 100644 --- a/server/libFunq/dragndropresponse.cpp +++ b/server/libFunq/dragndropresponse.cpp @@ -41,7 +41,7 @@ knowledge of the CeCILL v2.1 license and that you accept its terms. void calculate_drag_n_drop_moves(QList & moves, const QPoint & globalSourcePos, const QPoint & globalDestPos, - int deltaFactor=4) { + int deltaFactor) { QPoint delta = globalDestPos - globalSourcePos; delta /= deltaFactor; diff --git a/server/libFunq/dragndropresponse.h b/server/libFunq/dragndropresponse.h index 01ae9d4..c6e7657 100644 --- a/server/libFunq/dragndropresponse.h +++ b/server/libFunq/dragndropresponse.h @@ -38,6 +38,9 @@ knowledge of the CeCILL v2.1 license and that you accept its terms. #include "delayedresponse.h" #include +void calculate_drag_n_drop_moves(QList & moves, const QPoint & globalSourcePos, const QPoint & globalDestPos, int deltaFactor=4); +QPoint pointFromString(const QString & data); + class DragNDropResponse : public DelayedResponse { public: diff --git a/server/libFunq/player.cpp b/server/libFunq/player.cpp index 4a83e27..4a13c65 100644 --- a/server/libFunq/player.cpp +++ b/server/libFunq/player.cpp @@ -84,6 +84,23 @@ void mouse_dclick(QWidget * w, const QPoint & pos) { Qt::NoModifier)); } +void mouse_move(QWidget * w, const QPoint & srcpos, const QPoint & destpos) { + QList moves; + QPoint globalsrcpos = w->mapToGlobal(srcpos); + QPoint globaldestpos = w->mapToGlobal(destpos); + calculate_drag_n_drop_moves(moves, globalsrcpos, globaldestpos, 4); + foreach (const QPoint & move, moves) { + qApp->postEvent(w, + new QMouseEvent(QEvent::MouseMove, + w->mapFromGlobal(move), + move, + Qt::NoButton, + Qt::NoButton, + Qt::NoModifier)); + } + mouse_click(w, destpos); +} + void dump_properties(QObject * object, QtJson::JsonObject & out) { const QMetaObject * metaobject = object->metaObject(); for (int i = 0; i < metaobject->propertyCount(); ++i) { @@ -398,6 +415,32 @@ QtJson::JsonObject Player::widget_click(const QtJson::JsonObject & command) { return result; } +QtJson::JsonObject Player::widget_mouse_move(const QtJson::JsonObject & command) { + WidgetLocatorContext ctx(this, command, "oid"); + if (ctx.hasError()) { return ctx.lastError; } + + QPoint srcPos; + if (command.contains("srcpos") && ! command["srcpos"].isNull()) { + srcPos = pointFromString(command["srcpos"].toString()); + } else { + srcPos = ctx.widget->rect().center(); + } + + QPoint destPos; + if (command.contains("destpos") && ! command["destpos"].isNull()) { + destPos = pointFromString(command["destpos"].toString()); + destPos.setX(srcPos.x() + destPos.x()); + destPos.setY(srcPos.y() + destPos.y()); + } else { + destPos = ctx.widget->rect().center(); + } + + mouse_move(ctx.widget->viewport(), srcPos, destPos); + + QtJson::JsonObject result; + return result; +} + QtJson::JsonObject Player::widget_close(const QtJson::JsonObject & command) { WidgetLocatorContext ctx(this, command, "oid"); if (ctx.hasError()) { return ctx.lastError; } diff --git a/server/libFunq/player.h b/server/libFunq/player.h index 087b1b7..01c7f8f 100644 --- a/server/libFunq/player.h +++ b/server/libFunq/player.h @@ -82,6 +82,7 @@ public slots: QtJson::JsonObject object_set_properties(const QtJson::JsonObject & command); QtJson::JsonObject widgets_list(const QtJson::JsonObject & command); QtJson::JsonObject widget_click(const QtJson::JsonObject & command); + QtJson::JsonObject widget_mouse_move(const QtJson::JsonObject & command); QtJson::JsonObject widget_close(const QtJson::JsonObject & command); DelayedResponse * drag_n_drop(const QtJson::JsonObject & command); QtJson::JsonObject model_items(const QtJson::JsonObject & command);