connect QMetaObject connection

108 views
Skip to first unread message

Luigi Ferraris

unread,
May 17, 2017, 1:30:52 PM5/17/17
to QtContribs
Hi Pritpal,
first of all I hope text below will be clear because argument is complex and my English is not very good as my C knowledge.

Sometimes can be useful delay emitting signals (give me a cent for this).

Reading Qt docs related with QObject connect, can be used a numeric argument to informs Qt about "connection type"
(http://doc.qt.io/qt-5/qt.html#ConnectionType-enum)

I'm interested about Qt::QueuedConnection as Qt doc writes:
"The slot is invoked when control returns to the event loop of the receiver's thread. The slot is executed in the receiver's thread."
Perhaps, perhaps, ... this can solve the problem, but I need to do test

So, I read hbqt_misc.prg about :connect() method and than hbqt_hbqslots.cpp about hbqt_connect(...) function
In the last function, we have two situations
    Qt:  HBQT_CONNECT( object, signal, object, string ) related with hbqt_QtConnect
    HB:  HBQT_CONNECT( object, signal, codeblock ) related with hbConnect

both hbqt_QtConnect and hbConnect use Qt::AutoConnection by default (and this is right as per Qt doc).

But I'm not able to do test because this argument can't be used with HbQt.
The question: can be added this numeric argument?
eg hbqtObject:connect( <signal>, <block> [,<connectionType] )
Alternative: can you guide me to write (see below) right C code?

I have figured out a (skeleton) solution, but remember: I'm not C programmer

HB_FUNC( HBQT_CONNECT )
{
   int ret = -1;
   int iPCount = hb_pcount();
   int connectionType = Qt::AutoConnection

   if ( ( iPCount >= 3 && HB_ISBLOCK( 3 ) )  HB_ISBLOCK give us the ability to distinguish about Qt or HB call
   {

      // arguments for hbConnect

      connectionType = iPCount < 4 ? Qt::AutoConnection : hb_parni( 4 );
      // here check connectionType  >= Qt::AutoConnection && <= Qt::UniqueConnection by default Qt::AutoConnection
      // but I dont' know right C code

      // more or less your code but hbconnect with one more argument
      if( HB_ISCHAR( 2 ) && hbqt_par_isDerivedFrom( 1, "QOBJECT" ) )
      {
         HBQSlots * receiverSlots = hbqt_bindGetReceiverSlotsByHbObject( hb_param( 1, HB_IT_OBJECT ) );
         if( receiverSlots )
         {
            ret = receiverSlots->hbConnect( ....., connectionType );
            hb_retni( ret );
         }
      }
      // hbConnect failure
      hb_errRT_BASE( EG_ARG, 9999, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );

   }

   else

   {

      // arguments for hbqt_QtConnect OR general failure

      connectionType = iPCount < 5 ? Qt::AutoConnection : hb_parni( 5 );
      // here check connectionType  >= Qt::AutoConnection && <= Qt::UniqueConnection by default Qt::AutoConnection
      // but I dont' know right C code

      // more or less your code but hbqt_QtConnect with one more argument
      if( HB_ISCHAR( 2 ) && HB_ISCHAR( 4 ) && hbqt_par_isDerivedFrom( 1, "QOBJECT" ) && hbqt_par_isDerivedFrom( 3, "QOBJECT" ) )
      {
         ret =  hbqt_QtConnect( ....., connectionType );
         hb_retni( ret );
      }

      // hbqt_QtConnect OR general failure
      hb_errRT_BASE( EG_ARG, 9999, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );

}


Now hbConnect with one more argument "int connectionType" (probably we need to re-check argument if function can be called somewhere)

Instead of
if( QMetaObject::connect( object, signalId, this, slotId + QObject::staticMetaObject.methodCount(), Qt::AutoConnection ) )
we can call
if( QMetaObject::connect( object, signalId, this, slotId + QObject::staticMetaObject.methodCount(), connectionType ) )

Now hbqt_QtConnect with one more argument "int connectionType" (probably we need to re-check argument if function can be called somewhere)

Instead of
if( QMetaObject::connect( sender, signalId, receiver, slotId, Qt::AutoConnection ) )
we can call
if( QMetaObject::connect( sender, signalId, receiver, slotId, connectionType ) )

Best regards
Luigi Ferraris

Pritpal Bedi

unread,
May 17, 2017, 4:04:12 PM5/17/17
to QtContribs
Hi

>>> this can solve the problem

What problem ? And what you want to test ? Under what scenario ?

Note Qt GUI cannot be done in multi-thread model.



Pritpal Bedi
a student of software analysis & concepts

Luigi Ferraris

unread,
May 19, 2017, 12:42:37 PM5/19/17
to qtcon...@googlegroups.com
Il 17/05/2017 22.04, Pritpal Bedi ha scritto:
What problem ? And what you want to test ? Under what scenario ?

Note Qt GUI cannot be done in multi-thread model.



Hi Pritpal, sorry for later I was little busy.
The "problem" is more simple. A little hint before try to explain: I'm thinking to signals and not to events.

Take a look next code (only essential part):

WITH OBJECT oTextEdit := QTextEdit( ... )
    :setText( "goofy" )
    :connect( "textChanged()", { || udfChanged( oTextEdit ) } )
END WITH


The signal is not emitted because I set the text before using "connect".

Now take a look to the next

WITH OBJECT oTextEdit := QTextEdit( ... )
    :connect( "textChanged()", { || udfChanged( oTextEdit ) } )
    :setText( "goofy" )
END WITH


The signal is emitted because I set the text after using "connect".

Obviously, here (a simple program) the solution is simple: I can use the second one!

Now think a derived class where I connect signal[s] by default eg
METHOD init(...) CLASS myTextEdit
    ::connect( "textChanged()", { || yourBlockHere } )
RETURN Self


And now in my program I can code
WITH OBJECT oTextEdit := myTextEdit
    :setText( "goofy" )
END WITH


Signal is emitted but (in this scenario) I don't want signal to be emitted because "I'm building form".
This problem can be extended to other widgets / signals eg window, tablewidget, etc.

Reading Qt docs, in this context seems (repeat seems) useful to use queued signal because:

"The slot is invoked when control returns to the event loop of the receiver's thread. The slot is executed in the receiver's thread."

If I understood, when control returns (eg) to the QMainWindow event loop

oWnd := QMainWindow()
WITH OBJECT oTextEdit := myTextEdit( oWnd )
    :setText( "goofy" )
END WITH

oWnd:show()

QApplication():exec()    <--- in this moment signal is emitted


I hope is more clear what about I'm speaking: more simple than multi-thread

Regards
Luigi Ferraris

Pritpal Bedi

unread,
May 19, 2017, 12:59:04 PM5/19/17
to QtContribs, luigfe...@gmail.com
Hi


It is even simpler:

METHOD init(...) CLASS myTextEdit
  ::lFirstTime := .T.
 ::connect( "textChanged()", { || iif( ::lFirstTime, doNothong, yourBlockHere ), ::lFiratTime := .F. } )
RETURN Self


Why should we tax every user for nothing ?

Luigi Ferraris

unread,
May 19, 2017, 1:38:42 PM5/19/17
to Pritpal Bedi, QtContribs
Il 19/05/2017 18.59, Pritpal Bedi ha scritto:
t is even simpler:

METHOD init(...) CLASS myTextEdit
  ::lFirstTime := .T.
 ::connect( "textChanged()", { || iif( ::lFirstTime, doNothong, yourBlockHere ), ::lFiratTime := .F. } )
RETURN Self


Why should we tax every user for nothing ?

First of all: I don't want tax anyone for nothing!
My intention was to give a suggestion (an alternative to be checked) to improve your project for everyone using an existing option that perhaps is more simple
::connect( "textChanged()", { || block }, 2 )

Another way can be using QTimer as you know.

Anyway, I understood your pov.

Regards
Luigi Ferraris
Reply all
Reply to author
Forward
0 new messages