crategus / cl-cffi-gtk

cl-cffi-gtk is a Lisp binding to the GTK+ 3 library.
http://www.crategus.com/books/cl-cffi-gtk
146 stars 33 forks source link

Signal handler for "edited" signal of gtk-cell-renderer has insufficient parameter list #31

Open plops opened 9 years ago

plops commented 9 years ago

I'm trying to separate construction of a tree-view and its model as much as possible. When defining the "edited" signal for the text-renderer of text (in this case actually a spin-box showing double-float values) I don't have access to the treeview and therefore can not access the model to update its value.

The following code is working but I would prefer, if the signal for "edited" could be defined in the make-view function instead of inside view-update-model.

(eval-when (:compile-toplevel :load-toplevel :execute)
  (ql:quickload :cl-cffi-gtk))

(defpackage :tree-gui 
  (:use :gtk :gdk :gobject :glib :pango :cairo :cffi :iterate :cl))

(in-package :tree-gui)

(defun make-model ()
 (let* ((model (make-instance 'gtk-tree-store :column-types '("gchararray" "gdouble"))))
   (let ((parent (gtk-tree-store-set model
                     (gtk-tree-store-append model nil)
                     "fiber" 1d0)))
     (gtk-tree-store-set model (gtk-tree-store-append model parent) "Klaus-Dieter Mustermann" 51d0)
     (gtk-tree-store-set model (gtk-tree-store-append model parent) "Ulrike Langhals" 23d0))
   model))

(defun make-view ()
  (let ((view (make-instance 'gtk-tree-view)))
    (let* ((renderer (gtk-cell-renderer-text-new))
       (col (gtk-tree-view-column-new-with-attributes "name" renderer "text" 0)))
      (gtk-tree-view-append-column view col))
    (let* ((adj (make-instance 'gtk-adjustment
                   :value (* 1d0 100)
                   :lower 0d0
                   :upper (* 1d0 2000)
                   :step-increment 1d0
                   :page-increment 10d0
                   :page-size 0d0))
       (renderer (make-instance 'gtk-cell-renderer-spin :editable t :digits 0 :adjustment adj))
       (col (gtk-tree-view-column-new-with-attributes "value" renderer "text" 1)))
      (gtk-tree-view-append-column view col)
      (values view renderer))))

(defun view-update-model (view renderer model)
  (gtk-tree-view-set-model view model)    
  (g-signal-connect renderer "edited" (lambda (renderer path-string newtext) ;; 4th parameter should be GtkTreeView *treeview
                    (declare (ignore newtext))
                    ;; according to documentation the string in newtext should not be used,
                    ;; instead a double value obtained from the adjustemtn
                    (let* ((adj (g-object-get-property renderer "adjustment"))
                           (value (gtk-adjustment-get-value adj))
                           (path (gtk-tree-path-new-from-string path-string))
                           ;; (model (gtk-tree-view-get-model ))
                           (iter (gtk-tree-model-get-iter model path))
                           )
                      (gtk-tree-store-set-value model iter 1 value)))))

(defun run ()
  (sb-int:with-float-traps-masked (:divide-by-zero)
    (within-main-loop
      (let ((window (make-instance 'gtk-window :title "holography"
                   :default-width 320
                   :default-height 240
                   :border-width 12
                   :type :toplevel)))
    (g-signal-connect window "destroy" (lambda (widget)
                         (declare (ignorable widget))
                         (leave-gtk-main)))

    (let* ((model (make-model)))
      (multiple-value-bind (view renderer) (make-view)
        (view-update-model view renderer model)
        (gtk-container-add window view)))
    (gtk-widget-show-all window))))))
Ferada commented 8 years ago

AFAIK the library follows whatever GTKs API does, so since the edited signal doesn't have that parameter, it won't be put in here. In the C API you're kind of expected to supply whatever data you need with the user_data parameter - likewise you'd do what you've already written above in the Lisp binding instead.

I guess you could put some custom data on the renderer, but your current solution seems simple enough.