The principle of implementation of signal and slot mechanism in Qt

xiaoxiao2021-03-06  39

[QT in the implementation principle of signal and groove mechanism.]

[Tan.zhenhua]

One: [Each object] has a corresponding record of the object of the object.

Class on the primary object:

QMetaObject class:

/ ****************************************** /

// class name

Const char * const class_name,

// Parent class name

QMetaObject * superclass,

// Record SLOT information

Const Qmetadata * const slot_data,

// number of records

INT N_SLOTS,

// Record Signal Information

Const Qmetadata * const signal_data,

// number of records

INT N_SIGNALS

/ ******************************************************************************************************************** ** /

INT Numslots (Bool Super = false) const; // Number of returns

INT NumSignals (Bool Super = false) const; // Returns the number of signals

INT FINDSLOT (Const Char *, Bool Super = false) const; // lookup slot

INT FINDSIGNAL (const char *, bool super = false) const; // lookup signal

/ / Return the slot of the specified position

Const Qmetadata * Slot (int index, bool super = false) const;

/ / Return the signal of the specified location

Const Qmetadata * Signal (int index, bool super = false) const;

// list of all slots names

Qstrlist slotnames (Bool Super = false) const;

// list of all signal names

Qstrlist SignalNames (Bool Super = False) Const;

// Slot start index

Int slotoffset () const;

// Signal start index

Int signaloffset () const;

/ ****************************************************************************************************** /

Static QmetaObject * MetaObject (const char * class_name);

Static Bool HasmetaObject (const char * class_name);

QMetadata class:

// Record meta-object data for signal and groove

Struct Qmetadata

{

Const char * name; // Name

const QUMETHOD * METHOD; / / Detailed Description Information

Enum access {private};

Access Access; // Access Permissions

}

Second: [QObject class implements signal and slot mechanism]

It uses the information record of the meta-object record to realize the signal and slot mechanism.

(1) Realization of signal and slot establishment connection

Interface function:

//connection

// Parameter (send object, signal, receiving object, signal / groove)

Static Bool Connect (Const Qobject * Sender, Const Char * Signal,

Const Qobject * Receiver, const char * member); BOOL Connect (const Qobject * sender, const char * signal,

Const char * member) const;

Static Bool Disconnect (const Qobject * sender, const char * signal,

Const Qobject * Receiver, const char * member;

Bool disconnect (const char * signal = 0,

Const Qobject * Receiver = 0, const char * member = 0);

Bool disconnect (const Qobject * receiver, const char * member = 0);

/ / Internal implementation

/ / (Send object, index, receiving object, type of processing signal, index of processing signal signal / groove)

Static Void Connectinternal (Const Qobject * Sender, int signal_index,

Const Qobject * Receiver, int event_index;

Static Bool Disconnectinternal (const Qobject * sender, int signal_index,

Const Qobject * Receiver, int event_index;

The principle of signaling and groove connection:

1 stage

Bool Qobject :: Connect (const QObject * sender, // send object

Const char * signal, // signal

Const Qobject * Receiver, // Receive object

Const char * member // slot

)

{

/ / Check the send object, signal, receive object, and the slot is not NULL

IF (sender == 0 || Receiver == 0 || signal == 0 || MEMBER == 0) {

Return False;

}

/ / Get the meta object of the send object

QmetaObject * smeta = sender-> metaObject ();

// check the signal

IF (! Check_Signal_Macro (Sender, Signal, "Connect", "Bind"))

Return False;

// Get the index of the signal

INT signal_index = Smeta-> FindSignal (Signal, True);

IF (Signal_index <0) {// Normalize and Retry

NW_SIGNAL = Qt_rmws (Signal-1); // Remove Whitespace

Signal = nw_signal.data () 1; // Skip MEMBER TYPE CODE

Signal_index = Smeta-> FindSignal (Signal, True);

}

// If the signal does not exist, exit

IF (Signal_index <0) {// No Such Signal

Return False;

}

/ / Get a metadata object of the signal

Const Qmetadata * SM = SMETA-> SIGNAL (Signal_INDEX, TRUE); // Get the signal name

Signal = SM-> Name;

/ / Get the type of processing signal (is the signal / slot)

INT MEMBCODE = MEMBER [0] - '0'; // Get Member Code

// Send a signal object

QObject * s = (QObject *) sender; // We need to change them

// Receive signal objects

QObject * r = (QObject *) received; // internally

/ / Get the meta-object that receives the object

QmetaObject * Rmeta = r-> metaobject ();

INT member_index = -1;

Switch (MEMBCODE) {// Get Receiver MEMBER

Case Qslot_code: // If it is a slot

// Get the slot index

MEMBER_INDEX = RMETA-> FINDSLOT (MEMBER, TRUE);

IF (MEMBER_INDEX <0) {// Normalize and Retry

NW_MEMBER = qt_rmws (member); // Remove Whitespace

MEMBER = NW_MEMBER;

MEMBER_INDEX = RMETA-> FINDSLOT (MEMBER, TRUE);

}

Break;

CASE Qsignal_code: // If it is a signal

// Get signal index

MEMBER_INDEX = RMeta-> FindSignal (Member, true);

IF (MEMBER_INDEX <0) {// Normalize and Retry

NW_MEMBER = qt_rmws (member); // Remove Whitespace

MEMBER = NW_MEMBER;

MEMBER_INDEX = RMeta-> FindSignal (Member, true);

}

Break;

}

/ Exit if there is no corresponding signal or slot,

IF (MEMBER_INDEX <0) {

Return False;

}

/ / Check the connected parameters (send signals, receiving the object, the slot or signal of the signal)

IF (! S-> Checkconnectargs (Signal, Receiver, MEMBER) {

Return False;

} else {

/ / Get the metadata object of the processing signal

Const Qmetadata * RM = MEMBCODE == Qslot_code?

RMeta-> slot (Member_index, true):

Rmeta-> Signal (Member_index, true);

IF (rm) {

//establish connection

/ / (Send the object, the index of the signal, the object of the received signal,

Treatment signal type, index of processing signals)

Connectinternal (Sender, Signal_index, Receiver, MEMBCODE, MEMBER_INDEX);

}

}

Return True;

}

2 stage

//establish connection

/ / (Send signal object, index of the signal, the object of the received signal, the type of processing signal, the index of the processing signal) VOID QOBJECT :: Connectinternal (const Qobject * sender, int signal_index,

Const Qobject * Receiver,

INT MEMBCODE, INT MEMBER_INDEX)

{

// Send a signal object

QObject * s = (QObject *) Sender;

// Receive the object of the signal

QObject * r = (QObject *) Receiver;

// If the connection query table of the send object is NULL, it is established.

IF (! S-> Connections) {// CREATE CONNECTIONOKUP TABLE

S-> Connections = New Qsignalvec (Signal_Index 1);

Q_Check_ptr (S-> Connections);

S-> Connections-> setAutodelete (true);

}

/ / Get a list of connection to the corresponding signal of the object

QCONNECTIONLIST * CLIST = S-> Connections-> At (Signal_index);

IF (! CLIST) {// CREATE Receiver List

Clist = new qConnectionList;

Q_Check_ptr (CLIST);

CLIST-> SetAutodelete (TRUE);

S-> Connections-> INSERT (Signal_Index, Clist);

}

QmetaObject * Rmeta = r-> metaobject ();

Const Qmetadata * RM = 0;

Switch (MEMBCODE) {// Get Receiver MEMBER

Case Qslot_code:

RM = RMeta-> slot (MEMBER_INDEX, TRUE);

Break;

Case Qsignal_code:

RM = RMeta-> Signal (Member_index, True);

Break;

}

//establish connection

QCONNECTION * C = New QCONNECTION (R, MEMBER_INDEX, RM? RM-> Name:

"qt_invoke", membcode);

Q_Check_PTR (c);

/ / Add the connection to the list of connected objects

CLIST-> APPEND (C);

/ / Deconed whether the list of send objects of the received object is NULL

IF (! r-> senderobjects) // CREATE LIST OF SENDERS

{

/ / Establish a list of send objects for receiving objects

R-> senderObjects = new qsenderObjectList;

}

/ / Add the send object to the list of send objects

R-> senderObjects-> append (s); // add sender to list

}

(2) Operation functions activated when the signal occurs

interface:

/ ************************************************** *************

** Method for activating Slot

*********************************************************** ************** / VOID Qobject :: Activate_Signal (int signal)

{

#ifndef qt_no_preliminary_signal_spy

IF (qt_preliminary_signal_spy) {

/ / The signal is not blocked

// signal> = 0

/ / The connection list is not empty, or the corresponding connection of the signal exists.

IF (! SignalsBlocked () && signal> = 0 &&

(! CONNECTIONS ||! Connections-> At (signal))) {

//

QuObject O [1];

Qt_SPY_SIGNAL (this, signal, o);

Return;

}

}

#ENDIF

IF (! connect || SignalsBlocked () || Signal <0)

Return;

// Get the list of connections corresponding to the signal

QCONNECTIONLIST * CLIST = Connections-> At (Signal);

IF (! cred)

Return;

QuObject O [1];

//

Activate_signal (Clist, O);

}

/ ************************************************** *************

** Method for activating Slot

*********************************************************** ************* /

Void Qobject :: Activate_Signal (QConnectionList * Clist, QuObject * O)

{

IF (! cred)

Return;

#ifndef qt_no_preliminary_signal_spy

IF (qt_preliminary_signal_spy)

Qt_SPY_SIGNAL (this, connections-> findref (clist), o);

#ENDIF

QObject * Object;

// Send a list of objects

QSenderObjectList * SOL;

// Old send object

QObject * oldsender = 0;

//connection

QCONNECTION * C;

IF (clist-> count () == 1) {// save iterator

// Get a connection

C = clist-> first ();

//

Object = C-> Object ();

// Get a list of send objects

Sol = Object-> senderObjects;

IF (SOL) {

/ / Get old send objects

Old Shender = SOL-> CurrentSender;

//

Sol-> Ref ();

/ / Set new send object

Sol-> CurrentSender = THIS;

}

IF (c-> membertype () == qsignal_code) // If it is a signal, send it out

Object-> qt_emit (C-> Member (), O);

Else

Object-> qt_invoke (C-> Member (), O); // If it is a slot, execute

//

IF (SOL) {

// Set the recovery to the old send object

Sol-> CurrentSender = Old Shender;

IF (Sol-> Deref ())

DELETE SOL;

}

} else {

QCONNECTION * CD = 0;

QConnectionListit it (* clist);

While ((c = it.current ())) {

IT;

IF (c == CD)

CONTINUE;

CD = C;

Object = C-> Object ();

// Set the current send object before operation

Sol = Object-> senderObjects;

IF (SOL) {

Old Shender = SOL-> CurrentSender;

Sol-> Ref ();

Sol-> CurrentSender = THIS;

}

// If it is a signal, send it out.

IF (c-> membertype () == qsignal_code) {

Object-> qt_emit (C-> Member (), O);

}

// If it is a slot, execute

Else {

Object-> qt_invoke (C-> Member (), O);

}

// Restore the current send object after operation

IF (SOL) {

Sol-> CurrentSender = Old Shender;

IF (Sol-> Deref ())

DELETE SOL;

}

}

}

}

转载请注明原文地址:https://www.9cbs.com/read-70393.html

New Post(0)