Dept. of incomplete documentation: what if BufDelay* needs to be multichannel?
[supercollider.git] / SCClassLibrary / QtCollider / QView.sc
blob812c87408b83da594b2486d448196ef42ecc6838
1 QView : QObject {
2   classvar <globalKeyDownAction, <globalKeyUpAction;
3   classvar <hSizePolicy;
4   classvar <vSizePolicy;
5   // drag-and-drop
6   classvar <currentDrag, <currentDragString;
8   var wasRemoved = false;
9   // general props
10   var <font, <resize = 1, <alpha = 1.0;
11   // container props
12   var <decorator, <layout;
13   // top window props
14   var <>userCanClose=true, <>deleteOnClose = true;
15   // actions
16   var <action;
17   var <mouseDownAction, <mouseUpAction, <mouseEnterAction, <mouseLeaveAction;
18   var <mouseMoveAction, <mouseOverAction, <mouseWheelAction;
19   var <keyDownAction, <keyUpAction, <keyModifiersChangedAction;
20   var <>keyTyped;
21   // focus
22   var <focusGainedAction, <focusLostAction;
23   // drag-and-drop
24   var <>dragLabel;
25   var <beginDragAction, <canReceiveDragHandler, <receiveDragHandler;
26   // window actions
27   var <toFrontAction, <endFrontAction;
28   // hooks
29   var <onClose, <onResize, <onMove;
31   *initClass {
32     hSizePolicy = [1,2,3,1,2,3,1,2,3];
33     vSizePolicy = [1,1,1,2,2,2,3,3,3];
34   }
36   *new { arg parent, bounds;
37     var p = parent.asView;
38     ^super.new( [p, bounds.asRect] ).initQView( p );
39   }
41   *newCustom { arg customArgs;
42     ^super.new( customArgs ).initQView( nil );
43   }
45   *qtClass { ^'QcDefaultWidget' }
47   asView { ^this }
49   refresh {
50     _QWidget_Refresh
51     ^this.primitiveFailed;
52   }
54   remove {
55     this.destroy;
56     wasRemoved = true;
57     this.children.do { |child| child.remove };
58   }
60   mapToGlobal { arg point;
61     _QWidget_MapToGlobal
62     ^this.primitiveFailed;
63   }
65   // ----------------- properties --------------------------
66   font_ { arg f;
67     font = f;
68     this.setProperty( \font, f );
69   }
71   toolTip { ^this.getProperty(\toolTip) }
72   toolTip_ { arg t; this.setProperty( \toolTip, t ) }
74   palette {
75     ^this.getProperty( \palette );
76   }
78   palette_ { arg p;
79     this.setProperty( \palette, p );
80   }
82   background {
83     ^this.palette.window;
84   }
86   background_ { arg color;
87     this.palette = this.palette.window_(color);
88     this.setProperty( \autoFillBackground, true );
89   }
91   // NOTE: only for backwards compatibility
92   backColor_ { arg color;
93     this.background = color;
94   }
96   absoluteBounds {
97     ^this.bounds.moveToPoint( this.mapToGlobal( 0@0 ) );
98   }
100   bounds {
101     ^this.getProperty(\geometry)
102   }
104   bounds_ { arg rect;
105     this.setProperty(\geometry, rect.asRect )
106   }
108   sizeHint { ^this.getProperty(\sizeHint) }
110   minSizeHint { ^this.getProperty(\minimumSizeHint) }
112   // a Point can be passed instead of a Size
113   maxSize_ { arg size;
114     var max = QLimits(\maxWidgetSize);
115     size = size.asSize;
116     this.setProperty( \maximumSize, Size( min(max,size.width), min(max,size.height) ) );
117   }
119   // a Point can be passed instead of a Size
120   minSize_ { arg size; this.setProperty( \minimumSize, size.asSize ); }
122   fixedSize_ { arg size;
123     size = size.asSize;
124     this.setProperty( \minimumSize, size );
125     this.setProperty( \maximumSize, size );
126   }
128   fixedWidth_ { arg width;
129     this.setProperty( \minimumWidth, width );
130     this.setProperty( \maximumWidth, width );
131    }
133   fixedHeight_ { arg height;
134     this.setProperty( \minimumHeight, height );
135     this.setProperty( \maximumHeight, height );
136   }
138   maxWidth_ { arg width;
139     this.setProperty( \maximumWidth, min( width, QLimits(\maxWidgetSize) ) );
140   }
142   minWidth_ { arg width; this.setProperty( \minimumWidth, width ); }
144   maxHeight_ { arg height;
145     this.setProperty( \maximumHeight, min( height, QLimits(\maxWidgetSize) ) );
146   }
148   minHeight_ { arg height; this.setProperty( \minimumHeight, height ); }
150   // backwards compatibility
151   relativeOrigin { ^true }
153   moveTo { arg x, y;
154     this.bounds_( this.bounds.moveTo( x, y ) );
155   }
157   resizeTo { arg width, height;
158     this.bounds_( this.bounds.resizeTo( width, height ) );
159   }
161   visible {
162     ^this.getProperty(\visible)
163   }
164   visible_ { arg bool;
165     this.setProperty(\visible, bool, false)
166   }
168   enabled {
169     ^this.getProperty(\enabled)
170   }
171   enabled_ { arg bool;
172     this.setProperty(\enabled, bool)
173   }
175   resize_ { arg anInt;
176     this.setProperty(\_qc_hSizePolicy, hSizePolicy[anInt-1]);
177     this.setProperty(\_qc_vSizePolicy, vSizePolicy[anInt-1]);
178     resize = anInt;
179   }
181   canFocus {
182     var policy = this.getProperty(\focusPolicy);
183     ^( policy > 0 )
184   }
186   canFocus_ { arg bool;
187     var policy;
188     if( bool ) { policy = 16r1 | 16r2 | 16r8 } { policy = 0 };
189     this.setProperty(\focusPolicy, policy);
190   }
192   focus { arg flag=true;
193     _QWidget_SetFocus
194     ^this.primitiveFailed;
195   }
197   hasFocus {
198     ^this.getProperty( \focus );
199   }
201   acceptsMouse {
202     _QWidget_AcceptsMouse
203     ^this.primitiveFailed;
204   }
206   acceptsMouse_ { arg bool;
207     _QWidget_SetAcceptsMouse
208     ^this.primitiveFailed;
209   }
211   focusColor_ { arg color;
212     this.setProperty(\focusColor, color);
213   }
215   focusColor {
216     ^try { this.getProperty(\focusColor) } { Color() };
217   }
219   // ------------------ container stuff ----------------------------
221   children { arg class = QView;
222     var ch = super.children( class );
223     ^ch.select { |v| (v.tryPerform(\isClosed) ? false).not };
224   }
226   parent { arg class = QView;
227     if (wasRemoved) { ^nil } { ^super.parent(class) };
228   }
230   parents {
231     var allParents;
232     var p;
233     if (wasRemoved.not) {
234       p = this.parent;
235       while { p.notNil } {
236         allParents = allParents.add( p );
237         p = p.parent;
238       };
239     };
240     ^allParents;
241   }
243   getParents {
244     ^this.parents;
245   }
247   removeAll {
248     var childWidgets = this.children( QView );
249     childWidgets.do { |child| child.remove };
250   }
252   layout_ { arg newLayout;
253     if( newLayout.notNil && (newLayout != layout) ) {
254       this.prSetLayout( newLayout );
255       layout = newLayout;
256     };
257   }
259   addFlowLayout { arg margin, gap;
260     this.decorator_( FlowLayout( this.bounds.moveTo(0, 0), margin, gap ) );
261     ^this.decorator;
262   }
264   decorator_ { arg decor;
265     decor.bounds = decor.bounds.moveTo(0, 0);
266     decor.reset;
267     decorator = decor;
268   }
270   // ................. top window stuff ............................
272   name {
273     ^this.getProperty( \windowTitle );
274   }
276   name_ { arg string;
277     this.setProperty( \windowTitle, string );
278   }
280   front {
281     _QWidget_BringFront
282     ^this.primitiveFailed;
283   }
285   minimize {
286     if( this.visible ) { this.invokeMethod( \showMinimized, synchronous:false ) };
287   }
289   unminimize {
290     if( this.getProperty( \minimized ) ) { this.invokeMethod( \showNormal, synchronous:false ) };
291   }
293   fullScreen {
294     this.invokeMethod( \showFullScreen, synchronous:false );
295   }
297   endFullScreen {
298     if( this.getProperty( \fullScreen ) ) { this.invokeMethod( \showNormal, synchronous:false ) };
299   }
301   alpha_ { arg aFloat;
302     alpha = aFloat;
303     this.setProperty( \windowOpacity, aFloat );
304   }
306   alwaysOnTop {
307     _QWidget_GetAlwaysOnTop
308     ^this.primitiveFailed;
309   }
311   alwaysOnTop_ { arg boolean;
312     _QWidget_SetAlwaysOnTop
313     ^this.primitiveFailed;
314   }
316   close {
317     if( deleteOnClose )
318       { this.remove; }
319       { this.visible_( false ); }
320   }
322   isClosed {
323     if (wasRemoved) {^true} {^this.isValid.not};
324   }
326   notClosed { ^this.isClosed.not }
328   // TODO: deprecate acceptsMouseOver and expose 'mouseTracking' property directly
329   acceptsMouseOver { ^this.getProperty(\_qc_win_mouse_tracking) == true }
330   acceptsMouseOver_ { arg flag; this.setProperty(\_qc_win_mouse_tracking, flag == true) }
332   // ----------------- actions .....................................
334   action_ { arg func;
335     // NOTE: not all widgets have action() signal
336     try {
337       this.manageMethodConnection( action, func, 'action()', \doAction );
338     };
339     action = func;
340   }
342   addAction { arg func, selector=\action;
343     this.perform(selector.asSetter, this.perform(selector).addFunc(func));
344   }
346   removeAction { arg func, selector=\action;
347     this.perform(selector.asSetter, this.perform(selector).removeFunc(func));
348   }
350   *globalKeyDownAction_ { arg action;
351     globalKeyDownAction = action;
352     this.setGlobalEventEnabled( 16r01 /* KeyPress */, true );
353   }
356   *globalKeyUpAction_ { arg action;
357     globalKeyUpAction = action;
358     this.setGlobalEventEnabled( 16r02 /* KeyRelease */, true );
359   }
361   keyDownAction_ { arg aFunction;
362     keyDownAction = aFunction;
363     this.setEventHandlerEnabled( QObject.keyDownEvent, true );
364   }
366   keyUpAction_ { arg aFunction;
367     keyUpAction = aFunction;
368     this.setEventHandlerEnabled( QObject.keyUpEvent, true );
369   }
371   keyModifiersChangedAction_ { arg aFunction;
372     keyModifiersChangedAction = aFunction;
373     this.setEventHandlerEnabled( QObject.keyDownEvent, true );
374     this.setEventHandlerEnabled( QObject.keyUpEvent, true );
375   }
377   mouseDownAction_ { arg aFunction;
378     mouseDownAction = aFunction;
379     this.setEventHandler( QObject.mouseDownEvent, \mouseDownEvent, true );
380     this.setEventHandler( QObject.mouseDblClickEvent, \mouseDownEvent, true );
381   }
383   mouseUpAction_ { arg aFunction;
384     mouseUpAction = aFunction;
385     this.setEventHandler( QObject.mouseUpEvent, \mouseUpEvent, true );
386   }
388   mouseMoveAction_ { arg aFunction;
389     mouseMoveAction = aFunction;
390     this.setEventHandler( QObject.mouseMoveEvent, \mouseMoveEvent, true );
391   }
393   // mouseOverAction responds to same Qt event as mouseMoveAction,
394   // but on different conditions.
395   // See QView:-mouseMoveEvent method.
396   mouseOverAction_ { arg aFunction;
397     mouseOverAction = aFunction;
398     this.setEventHandler( QObject.mouseMoveEvent, \mouseMoveEvent, true );
399     this.setProperty(\mouseTracking, true);
400   }
402   mouseEnterAction_ { arg aFunction;
403     mouseEnterAction = aFunction;
404     this.setEventHandler( QObject.mouseEnterEvent, \mouseEnterEvent, true );
405   }
407   mouseLeaveAction_ { arg aFunction;
408     mouseLeaveAction = aFunction;
409     this.setEventHandler( QObject.mouseLeaveEvent, \mouseLeaveEvent, true );
410   }
412   mouseWheelAction_ { arg aFunction;
413     mouseWheelAction = aFunction;
414     this.setEventHandler( QObject.mouseWheelEvent, \mouseWheelEvent, true );
415   }
417   beginDragAction_ { arg handler;
418     beginDragAction = handler;
419     this.setEventHandler( QObject.mouseDownEvent, \mouseDownEvent, true )
420   }
422   canReceiveDragHandler_ { arg handler;
423     canReceiveDragHandler = handler;
424     this.setDragEventsEnabled( true );
425   }
427   receiveDragHandler_ { arg handler;
428     receiveDragHandler = handler;
429     this.setDragEventsEnabled( true );
430   }
432   toFrontAction_ { arg aFunction;
433     toFrontAction = aFunction;
434     this.setEventHandler( QObject.windowActivateEvent,
435                                \onWindowActivateEvent );
436   }
438   endFrontAction_ { arg aFunction;
439     endFrontAction = aFunction;
440     this.setEventHandler( QObject.windowDeactivateEvent,
441                                \onWindowDeactivateEvent );
442   }
444   focusGainedAction_ { arg handler;
445     focusGainedAction = handler;
446     this.setEventHandler( 8 /* QEvent::FocusIn */, \focusInEvent );
447   }
449   focusLostAction_ { arg handler;
450     focusLostAction = handler;
451     this.setEventHandler( 9 /* QEvent::FocusOut */, \focusOutEvent );
452   }
454   onMove_ { arg aFunction;
455     onMove = aFunction;
456     this.setEventHandler( 13 /* QEvent::Move */, \moveEvent );
457   }
459   onResize_ { arg aFunction;
460     onResize = aFunction;
461     this.setEventHandler( 14 /* QEvent::Resize */, \resizeEvent );
462   }
464   onClose_ { arg func;
465     this.manageFunctionConnection( onClose, func, 'destroyed()', false );
466     onClose = func;
467   }
469   doAction {
470     action.value(this);
471   }
473   defaultKeyDownAction { arg char, modifiers, unicode, keycode; }
475   defaultKeyUpAction { arg char, modifiers, unicode, keycode; }
477   keyDown { arg char, modifiers, unicode, keycode;
478     if( keyDownAction.notNil ) {
479       ^keyDownAction.value( this, char, modifiers, unicode, keycode );
480     } {
481       ^this.defaultKeyDownAction( char, modifiers, unicode, keycode );
482     };
483   }
485   keyUp { arg char, modifiers, unicode, keycode;
486     keyTyped = char;
487     if( keyUpAction.notNil ) {
488       ^keyUpAction.value( this, char, modifiers, unicode, keycode );
489     } {
490       ^this.defaultKeyUpAction( char, modifiers, unicode, keycode );
491     };
492   }
494   keyModifiersChanged { arg modifiers;
495     keyModifiersChangedAction.value( this, modifiers);
496   }
498   mouseDown { arg x, y, modifiers, buttonNumber, clickCount;
499     ^mouseDownAction.value( this, x, y, modifiers, buttonNumber, clickCount );
500   }
502   mouseUp { arg x, y, modifiers, buttonNumber;
503     ^mouseUpAction.value( this, x, y, modifiers, buttonNumber );
504   }
506   mouseMove { arg x, y, modifiers;
507     ^mouseMoveAction.value( this, x, y, modifiers );
508   }
510   mouseOver { arg x, y;
511     ^mouseOverAction.value( this, x, y );
512   }
514   mouseEnter {
515     ^mouseEnterAction.value(this);
516   }
518   mouseLeave {
519     ^mouseLeaveAction.value(this);
520   }
522   mouseWheel { arg x, y, modifiers, xDelta, yDelta;
523     ^mouseWheelAction.value( this, x, y, modifiers, xDelta, yDelta );
524   }
526   /* ---------------- private ----------------------- */
528   *prSetCurrentDrag { arg obj; currentDrag = obj; currentDragString = obj.asCompileString; }
529   *prClearCurrentDrag { currentDrag = nil; currentDragString = nil; }
531   *setGlobalEventEnabled { arg event, enabled;
532     _QWidget_SetGlobalEventEnabled
533   }
535   initQView { arg parent;
537     var handleKeyDown, handleKeyUp, overridesMouseDown, handleDrag;
539     if (parent.notNil) {
540         if( parent.decorator.notNil ) { parent.decorator.place(this) }
541     };
543     this.setEventHandler( QObject.closeEvent, \onCloseEvent, true );
545     // key events
546     handleKeyDown = handleKeyUp = this.overrides( \keyModifiersChanged );
547     if( handleKeyDown.not )
548       { handleKeyDown = this.overrides( \defaultKeyDownAction ) };
549     if( handleKeyUp.not )
550       { handleKeyUp = this.overrides( \defaultKeyUpAction )};
552     this.setEventHandler( QObject.keyDownEvent, \keyDownEvent, true, enabled: handleKeyDown );
553     this.setEventHandler( QObject.keyUpEvent, \keyUpEvent, true, enabled: handleKeyUp );
555     // mouse events
556     overridesMouseDown = this.overrides( \mouseDown );
557     if( this.respondsTo(\defaultGetDrag) || overridesMouseDown )
558       {this.setEventHandler( QObject.mouseDownEvent, \mouseDownEvent, true )};
559     if( overridesMouseDown )
560       {this.setEventHandler( QObject.mouseDblClickEvent, \mouseDownEvent, true )};
561     if( this.overrides( \mouseUp ) )
562       {this.setEventHandler( QObject.mouseUpEvent, \mouseUpEvent, true )};
563     if( this.overrides( \mouseMove ) || this.overrides( \mouseOver ) )
564       {this.setEventHandler( QObject.mouseMoveEvent, \mouseMoveEvent, true )};
565     if( this.overrides( \mouseEnter ) )
566       {this.setEventHandler( QObject.mouseEnterEvent, \mouseEnterEvent, true )};
567     if( this.overrides( \mouseLeave ) )
568       {this.setEventHandler( QObject.mouseLeaveEvent, \mouseLeaveEvent, true )};
569     if( this.overrides( \mouseWheel ) )
570       {this.setEventHandler( QObject.wheelEvent, \mouseWheelEvent, true )};
572     // DnD events
573     handleDrag = this.respondsTo(\defaultCanReceiveDrag) or: {this.respondsTo(\defaultReceiveDrag)};
574     this.setEventHandler( 60, \dragEnterEvent, true, enabled:handleDrag );
575     this.setEventHandler( 61, \dragMoveEvent, true, enabled:handleDrag );
576     this.setEventHandler( 63, \dropEvent, true, enabled:handleDrag );
577   }
579   onCloseEvent {
580     if( userCanClose != false ) {
581         if( deleteOnClose != false ) { this.remove; ^true };
582     }{
583         ^false;
584     };
585   }
587   onWindowActivateEvent {
588     toFrontAction.value(this);
589   }
591   onWindowDeactivateEvent {
592     endFrontAction.value(this);
593   }
595   focusInEvent { focusGainedAction.value(this) }
596   focusOutEvent { focusLostAction.value(this) }
598   moveEvent { onMove.value(this) }
599   resizeEvent { onResize.value(this) }
601   keyDownEvent { arg char, modifiers, unicode, keycode, spontaneous;
602     modifiers = QKeyModifiers.toCocoa(modifiers);
604     if( char.size > 0 ) {char = char[0]} {char = 0.asAscii};
606     if( spontaneous ) {
607       // this event has never been propagated to parent yet
608       QView.globalKeyDownAction.value( this, char, modifiers, unicode, keycode );
609     };
611     if( (keycode == 16r1000020) || (keycode == 16r1000021) ||
612         (keycode == 16r1000022) || (keycode == 16r1000023 ) )
613       { this.keyModifiersChanged( modifiers ) };
615     ^this.keyDown( char, modifiers, unicode, keycode );
616   }
618   keyUpEvent { arg char, modifiers, unicode, keycode, spontaneous;
619     modifiers = QKeyModifiers.toCocoa(modifiers);
621     if( char.size > 0 ) {char = char[0]} {char = 0.asAscii};
623     if( spontaneous ) {
624       // this event has never been propagated to parent yet
625       QView.globalKeyUpAction.value( this, char, modifiers, unicode, keycode );
626     };
628     if( (keycode == 16r1000020) || (keycode == 16r1000021) ||
629         (keycode == 16r1000022) || (keycode == 16r1000023 ) )
630       { this.keyModifiersChanged( modifiers ) };
632     ^this.keyUp( char, modifiers, unicode, keycode );
633   }
635   mouseDownEvent { arg x, y, modifiers, buttonNumber, clickCount;
636     // WARNING: QDragView and QListView override this method!
638     if( (modifiers & QKeyModifiers.control) > 0 ) { // if Ctrl / Cmd mod
639       // Try to get drag obj and start a drag.
640       // If successful, block further processing of this event.
641       if( this.beginDrag( x, y ) ) { ^false };
642     };
644     // else continue to handle mouse down event
645     modifiers = QKeyModifiers.toCocoa(modifiers);
646     ^this.mouseDown( x, y, modifiers, buttonNumber, clickCount );
647   }
649   mouseUpEvent { arg x, y, modifiers, buttonNumber;
650     modifiers = QKeyModifiers.toCocoa(modifiers);
651     ^this.mouseUp(  x, y, modifiers, buttonNumber );
652   }
654   mouseMoveEvent { arg x, y, modifiers, buttons;
655     if( buttons != 0 ) {
656       modifiers = QKeyModifiers.toCocoa(modifiers);
657       ^this.mouseMove( x, y, modifiers );
658     }{
659       ^this.mouseOver( x, y )
660     }
661   }
663   mouseEnterEvent {
664     var dummy = 0; // prevent this method from being optimized away
665     ^this.mouseEnter;
666   }
668   mouseLeaveEvent {
669     var dummy = 0; // prevent this method from being optimized away
670     ^this.mouseLeave;
671   }
673   mouseWheelEvent { arg x, y, modifiers, xDelta, yDelta;
674     modifiers = QKeyModifiers.toCocoa(modifiers);
675     ^this.mouseWheel( x, y, modifiers, xDelta, yDelta );
676   }
678   beginDrag { arg x, y;
679     var obj, str;
680     if( beginDragAction.notNil )
681       { obj = beginDragAction.value( this, x, y ) }
682       { obj = this.tryPerform( \defaultGetDrag, x, y ) };
683     if( obj.notNil ) {
684       QView.prSetCurrentDrag( obj );
685       str = obj.asString;
686       this.prStartDrag( dragLabel ?? str, obj, str );
687       ^true;
688     };
689     ^false;
690   }
692   canReceiveDrag { arg x, y;
693     if( canReceiveDragHandler.notNil )
694       { ^this.canReceiveDragHandler.value( this, x, y ) }
695       { ^( this.tryPerform( \defaultCanReceiveDrag, x, y ) ? false ) };
696   }
698   receiveDrag { arg x, y;
699     if( receiveDragHandler.notNil )
700       { this.receiveDragHandler.value( this, x, y ) }
701       { this.tryPerform( \defaultReceiveDrag, x, y ) };
702   }
704   prStartDrag { arg label, data, dataAsString;
705     _QWidget_StartDrag
706     ^this.primitiveFailed;
707   }
709   dragEnterEvent {
710     // always accept the event
711     ^true;
712   }
714   dragMoveEvent { arg x, y;
715     // make sure the event is always consumed
716     ^this.canReceiveDrag( x, y ).switch (
717       true, true,
718       false, false,
719       false
720     )
721   }
723   dropEvent { arg x, y;
724     this.receiveDrag( x, y );
725     // always accept the event
726     ^true
727   }
729   setDragEventsEnabled { arg enabled;
730     this.setEventHandlerEnabled( 60, enabled );
731     this.setEventHandlerEnabled( 61, enabled );
732     this.setEventHandlerEnabled( 63, enabled );
733   }
735   prSetLayout { arg layout;
736     _QWidget_SetLayout
737     ^this.primitiveFailed;
738   }
740   manageMethodConnection { arg oldAction, newAction, signal, method, sync=false;
741     if( newAction !== oldAction ) {
742       case
743         { oldAction.isNil && newAction.notNil } {this.connectMethod (signal, method, sync)}
744         { oldAction.notNil && newAction.isNil } {this.disconnectMethod (signal, method)}
745       ;
746     };
747   }
749   manageFunctionConnection { arg oldAction, newAction, signal, sync=false;
750     if( newAction !== oldAction ) {
751       if( oldAction.notNil ) {this.disconnectFunction (signal, oldAction)};
752       if( newAction.notNil ) {this.connectFunction (signal, newAction, sync)};
753     };
754   }
756   overrides { arg symMethod;
757     ^ ( this.class.findRespondingMethodFor(symMethod) !=
758         QView.findRespondingMethodFor(symMethod) );
759   }
761   nonimpl { arg methodName;
762     this.class.nonimpl( methodName );
763   }
765   *nonimpl { arg methodName;
766     this.debug( msg: methodName.asString ++ " is not implemented yet" )
767   }
769   *debug { arg level = 1, msg = "";
770     if( QtGUI.debugLevel >= level ) { ("Qt: " ++ this.asString ++ ": " ++ msg).postln }
771   }