QFUN and lisp classes that encapsulate a Qt object.

28 views
Skip to first unread message

Mark Cox

unread,
Aug 30, 2012, 10:19:07 PM8/30/12
to eql-...@googlegroups.com
G'day,

Is it possible for QFUN to call a generic function on an object when
it is unable to use it? Alternatively, is there a predicate that I can
use to determine if QFUN can use an object?


For example

(defclass my-graphics-item ()
((graphics-item :reader graphics-item)
(on-paint :initarg :on-paint)))

;; this currently fails because QFUN does not know how to work with OBJECT.
(let ((object (make-instance 'my-graphics-item)))
(qfun object "setPos" '(0 0)))


;; introduce the generic function QFUNABLE-OBJECT

;; define a method for MY-GRAPHICS-ITEM
(defmethod qfunable-object ((object my-graphics-item))
(graphics-item object))


I find myself wanting to do the above very frequently.

QFUNABLE may not be a good name.

Thanks
Mark

Polos Ruetz

unread,
Aug 31, 2012, 7:08:34 AM8/31/12
to eql-...@googlegroups.com
2012/8/31, Mark Cox <mark...@gmail.com>:
> ;; introduce the generic function QFUNABLE-OBJECT
>
> ;; define a method for MY-GRAPHICS-ITEM
> (defmethod qfunable-object ((object my-graphics-item))
> (graphics-item object))

Please see the attached patch, I tested with an example similar to
yours and it worked.

I find the name QFUNABLE-OBJECT easy to remember, so why not?

(If there are no problems I will add the patch officially.)

Paul
QFUNABLE-OBJECT.patch

Mark Cox

unread,
Sep 1, 2012, 4:07:37 AM9/1/12
to eql-...@googlegroups.com
Hi Paul,

On 31/08/2012, at 9:08 PM, Polos Ruetz wrote:

> 2012/8/31, Mark Cox <mark...@gmail.com>:
>> ;; introduce the generic function QFUNABLE-OBJECT
>>
>> ;; define a method for MY-GRAPHICS-ITEM
>> (defmethod qfunable-object ((object my-graphics-item))
>> (graphics-item object))
>
> Please see the attached patch, I tested with an example similar to
> yours and it worked.
>
> I find the name QFUNABLE-OBJECT easy to remember, so why not?

Ok, if you like it. I honestly didn't spend much time thinking about it.

> (If there are no problems I will add the patch officially.)

Would you consider exporting it from the EQL package? I consider the pattern useful, but I am new to EQL.

I would also consider a more user friendly error message if an object cannot be used. Perhaps,

(defun qfunablep (object)
(not (null (compute-applicable-methods #'qfunable-object (list object)))))

(defun ensure-qt-object (object)
(or (when (qt-object-p object)
object)

(when (qfunablep object)
(qfunable-object object))

(error "EQL is unable to use object ~A. Consider specializing QFUNABLE-OBJECT." object)))

Thanks
Mark


Polos Ruetz

unread,
Sep 1, 2012, 5:02:12 AM9/1/12
to eql-...@googlegroups.com
2012/9/1, Mark Cox <mark...@gmail.com>:
> Would you consider exporting it from the EQL package? I consider the pattern
> useful, but I am new to EQL.

it seems that I didn't think hard enough -- I would like to extend
this even more:

After testing a little, I found that it would be useful to use these
Lisp objects (encapsulating a Qt object) everywhere a Qt object is
expected (e.g. as arguments to QFUN, with QSET, QCONNECT etc.).

Since its use would not be limited to QFUN, I would like to use
another name, like:

(defgeneric the-qt-object (object)
:documentation "Return the QT-OBJECT to be used whenever OBJECT is
used as argument to any EQL function."))


> I would also consider a more user friendly error message if an object cannot
> be used. Perhaps,

ok, I will add a better error message.

I never thought about encapsulation/CLOS, because I simply never use
CLOS (my projects are small), but I find your idea very convenient.

Paul

Polos Ruetz

unread,
Sep 1, 2012, 7:48:38 AM9/1/12
to eql-...@googlegroups.com
2012/9/1, Polos Ruetz <polos...@gmail.com>:
> (defgeneric the-qt-object (object)
> :documentation "Return the QT-OBJECT to be used whenever OBJECT is
> used as argument to any EQL function."))

Please see the new example "X-extras/CLOS-encapsulation.lisp" (should
be self-explaining).

(The only small thing that changed is passing a NULL value to e.g.
"QWidget*": you need to use NIL now, 0 will not be accepted).

Paul

Mark Cox

unread,
Sep 2, 2012, 2:37:51 AM9/2/12
to eql-...@googlegroups.com
Hi Paul,
Thanks for the patch.

I question the use of IGNORE-ERRORS in ENSURE-QT-OBJECT. e.g.

(defclass my-class ()
((widget
:initarg :widget))
(:default-initargs
:widget (qnew "QPushButton" "text" "Hello")))

(defmethod the-qt-object ((object my-class))
(error "Hello world"))

(defun main ()
(let ((w (make-instance 'my-class)))
(qfun w "show")
(qfun w "raise")))

This produces:
Condition of type: SIMPLE-ERROR
EQL is unable to use object #<a EQL-USER::MY-CLASS>. Consider specializing THE-QT-OBJECT.

Mark

Polos Ruetz

unread,
Sep 2, 2012, 6:27:30 PM9/2/12
to eql-...@googlegroups.com
2012/9/2, Mark Cox <mark...@gmail.com>:
> I question the use of IGNORE-ERRORS in ENSURE-QT-OBJECT. e.g.

ok thanks, I removed both IGNORE-ERRORS and the error message, because
the standard error message should be sufficient anyway (and I didn't
want to use COMPUTE-APPLICABLE-METHODS because it would be called
really often in some cases).

Paul
Reply all
Reply to author
Forward
0 new messages