Qt Slot Call Order
In Qt v4.5 and earlier: No, the order is undefined as can be seen in the documentation here: If several slots are connected to one signal, the slots will be executed one after the other, in an arbitrary order, when the signal is emitted. Edit: From version 4.6 onwards this is no longer true. Now the slots will run in the order they are connected. If I’m about to modify a slot function I might take an extra minute to look around since most IDEs can’t tell syntactically where it’s used in a SLOT macro. In this case you have to search for it textually.) Thanks to C11 lambdas and Qt’s ongoing evolution, these short slots can be replaced by a more succinct syntax.
Signals and slots are used for communication between objects. The signals and slots mechanism is a central feature of Qt and probably the part that differs most from the features provided by other frameworks. Signals and slots are made possible by Qt's meta-object system.
Introduction
In GUI programming, when we change one widget, we often want another widget to be notified. More generally, we want objects of any kind to be able to communicate with one another. For example, if a user clicks a Close button, we probably want the window's close() function to be called.
Other toolkits achieve this kind of communication using callbacks. A callback is a pointer to a function, so if you want a processing function to notify you about some event you pass a pointer to another function (the callback) to the processing function. The processing function then calls the callback when appropriate. While successful frameworks using this method do exist, callbacks can be unintuitive and may suffer from problems in ensuring the type-correctness of callback arguments.
Signals and Slots
In Qt, we have an alternative to the callback technique: We use signals and slots. A signal is emitted when a particular event occurs. Qt's widgets have many predefined signals, but we can always subclass widgets to add our own signals to them. A slot is a function that is called in response to a particular signal. Qt's widgets have many pre-defined slots, but it is common practice to subclass widgets and add your own slots so that you can handle the signals that you are interested in.
The signals and slots mechanism is type safe: The signature of a signal must match the signature of the receiving slot. (In fact a slot may have a shorter signature than the signal it receives because it can ignore extra arguments.) Since the signatures are compatible, the compiler can help us detect type mismatches when using the function pointer-based syntax. The string-based SIGNAL and SLOT syntax will detect type mismatches at runtime. Signals and slots are loosely coupled: A class which emits a signal neither knows nor cares which slots receive the signal. Qt's signals and slots mechanism ensures that if you connect a signal to a slot, the slot will be called with the signal's parameters at the right time. Signals and slots can take any number of arguments of any type. They are completely type safe.
All classes that inherit from QObject or one of its subclasses (e.g., QWidget) can contain signals and slots. Signals are emitted by objects when they change their state in a way that may be interesting to other objects. This is all the object does to communicate. It does not know or care whether anything is receiving the signals it emits. This is true information encapsulation, and ensures that the object can be used as a software component.
Slots can be used for receiving signals, but they are also normal member functions. Just as an object does not know if anything receives its signals, a slot does not know if it has any signals connected to it. This ensures that truly independent components can be created with Qt.
You can connect as many signals as you want to a single slot, and a signal can be connected to as many slots as you need. It is even possible to connect a signal directly to another signal. (This will emit the second signal immediately whenever the first is emitted.)
Together, signals and slots make up a powerful component programming mechanism.
Signals
Signals are emitted by an object when its internal state has changed in some way that might be interesting to the object's client or owner. Signals are public access functions and can be emitted from anywhere, but we recommend to only emit them from the class that defines the signal and its subclasses.
When a signal is emitted, the slots connected to it are usually executed immediately, just like a normal function call. When this happens, the signals and slots mechanism is totally independent of any GUI event loop. Execution of the code following the emit
statement will occur once all slots have returned. The situation is slightly different when using queued connections; in such a case, the code following the emit
keyword will continue immediately, and the slots will be executed later.
If several slots are connected to one signal, the slots will be executed one after the other, in the order they have been connected, when the signal is emitted.
Signals are automatically generated by the moc and must not be implemented in the .cpp
file. They can never have return types (i.e. use void
).
A note about arguments: Our experience shows that signals and slots are more reusable if they do not use special types. If QScrollBar::valueChanged() were to use a special type such as the hypothetical QScrollBar::Range, it could only be connected to slots designed specifically for QScrollBar. Connecting different input widgets together would be impossible.
Slots
A slot is called when a signal connected to it is emitted. Slots are normal C++ functions and can be called normally; their only special feature is that signals can be connected to them.
Since slots are normal member functions, they follow the normal C++ rules when called directly. However, as slots, they can be invoked by any component, regardless of its access level, via a signal-slot connection. This means that a signal emitted from an instance of an arbitrary class can cause a private slot to be invoked in an instance of an unrelated class.
You can also define slots to be virtual, which we have found quite useful in practice.
Qt Signal Slot Call Order
Compared to callbacks, signals and slots are slightly slower because of the increased flexibility they provide, although the difference for real applications is insignificant. In general, emitting a signal that is connected to some slots, is approximately ten times slower than calling the receivers directly, with non-virtual function calls. This is the overhead required to locate the connection object, to safely iterate over all connections (i.e. checking that subsequent receivers have not been destroyed during the emission), and to marshall any parameters in a generic fashion. While ten non-virtual function calls may sound like a lot, it's much less overhead than any new
or delete
operation, for example. As soon as you perform a string, vector or list operation that behind the scene requires new
or delete
, the signals and slots overhead is only responsible for a very small proportion of the complete function call costs. The same is true whenever you do a system call in a slot; or indirectly call more than ten functions. The simplicity and flexibility of the signals and slots mechanism is well worth the overhead, which your users won't even notice.
Note that other libraries that define variables called signals
or slots
may cause compiler warnings and errors when compiled alongside a Qt-based application. To solve this problem, #undef
the offending preprocessor symbol.
A Small Example
A minimal C++ class declaration might read:
A small QObject-based class might read:
The QObject-based version has the same internal state, and provides public methods to access the state, but in addition it has support for component programming using signals and slots. This class can tell the outside world that its state has changed by emitting a signal, valueChanged()
, and it has a slot which other objects can send signals to.
All classes that contain signals or slots must mention Q_OBJECT at the top of their declaration. They must also derive (directly or indirectly) from QObject.
Slots are implemented by the application programmer. Here is a possible implementation of the Counter::setValue()
slot:
The emit
line emits the signal valueChanged()
from the object, with the new value as argument.
In the following code snippet, we create two Counter
objects and connect the first object's valueChanged()
signal to the second object's setValue()
slot using QObject::connect():
Calling a.setValue(12)
makes a
emit a valueChanged(12)
signal, which b
will receive in its setValue()
slot, i.e. b.setValue(12)
is called. Then b
emits the same valueChanged()
signal, but since no slot has been connected to b
's valueChanged()
signal, the signal is ignored.
Note that the setValue()
function sets the value and emits the signal only if value != m_value
. This prevents infinite looping in the case of cyclic connections (e.g., if b.valueChanged()
were connected to a.setValue()
).
By default, for every connection you make, a signal is emitted; two signals are emitted for duplicate connections. You can break all of these connections with a single disconnect() call. If you pass the Qt::UniqueConnectiontype, the connection will only be made if it is not a duplicate. If there is already a duplicate (exact same signal to the exact same slot on the same objects), the connection will fail and connect will return false
.
This example illustrates that objects can work together without needing to know any information about each other. To enable this, the objects only need to be connected together, and this can be achieved with some simple QObject::connect() function calls, or with uic's automatic connections feature.
A Real Example
The following is an example of the header of a simple widget class without member functions. The purpose is to show how you can utilize signals and slots in your own applications.
LcdNumber
inherits QObject, which has most of the signal-slot knowledge, via QFrame and QWidget. It is somewhat similar to the built-in QLCDNumber widget.
The Q_OBJECT macro is expanded by the preprocessor to declare several member functions that are implemented by the moc
; if you get compiler errors along the lines of 'undefined reference to vtable for LcdNumber
', you have probably forgotten to run the moc or to include the moc output in the link command.
After the class constructor and public
members, we declare the class signals
. The LcdNumber
class emits a signal, overflow()
, when it is asked to show an impossible value.
If you don't care about overflow, or you know that overflow cannot occur, you can ignore the overflow()
signal, i.e. don't connect it to any slot.
If on the other hand you want to call two different error functions when the number overflows, simply connect the signal to two different slots. Qt will call both (in the order they were connected).
A slot is a receiving function used to get information about state changes in other widgets. LcdNumber
uses it, as the code above indicates, to set the displayed number. Since display()
is part of the class's interface with the rest of the program, the slot is public.
Several of the example programs connect the valueChanged() signal of a QScrollBar to the display()
slot, so the LCD number continuously shows the value of the scroll bar.
Note that display()
is overloaded; Qt will select the appropriate version when you connect a signal to the slot. With callbacks, you'd have to find five different names and keep track of the types yourself.
Signals And Slots With Default Arguments
The signatures of signals and slots may contain arguments, and the arguments can have default values. Consider QObject::destroyed():
When a QObject is deleted, it emits this QObject::destroyed() signal. We want to catch this signal, wherever we might have a dangling reference to the deleted QObject, so we can clean it up. A suitable slot signature might be:
To connect the signal to the slot, we use QObject::connect(). There are several ways to connect signal and slots. The first is to use function pointers:
There are several advantages to using QObject::connect() with function pointers. First, it allows the compiler to check that the signal's arguments are compatible with the slot's arguments. Arguments can also be implicitly converted by the compiler, if needed.
You can also connect to functors or C++11 lambdas:
In both these cases, we provide this as context in the call to connect(). The context object provides information about in which thread the receiver should be executed. This is important, as providing the context ensures that the receiver is executed in the context thread.
The lambda will be disconnected when the sender or context is destroyed. You should take care that any objects used inside the functor are still alive when the signal is emitted.
The other way to connect a signal to a slot is to use QObject::connect() and the SIGNAL
and SLOT
macros. The rule about whether to include arguments or not in the SIGNAL()
and SLOT()
macros, if the arguments have default values, is that the signature passed to the SIGNAL()
macro must not have fewer arguments than the signature passed to the SLOT()
macro.
All of these would work:
But this one won't work:
...because the slot will be expecting a QObject that the signal will not send. This connection will report a runtime error.
Note that signal and slot arguments are not checked by the compiler when using this QObject::connect() overload.
Advanced Signals and Slots Usage
For cases where you may require information on the sender of the signal, Qt provides the QObject::sender() function, which returns a pointer to the object that sent the signal.
Lambda expressions are a convenient way to pass custom arguments to a slot:
Using Qt with 3rd Party Signals and Slots
It is possible to use Qt with a 3rd party signal/slot mechanism. You can even use both mechanisms in the same project. Just add the following line to your qmake project (.pro) file.
It tells Qt not to define the moc keywords signals
, slots
, and emit
, because these names will be used by a 3rd party library, e.g. Boost. Then to continue using Qt signals and slots with the no_keywords
flag, simply replace all uses of the Qt moc keywords in your sources with the corresponding Qt macros Q_SIGNALS (or Q_SIGNAL), Q_SLOTS (or Q_SLOT), and Q_EMIT.
See also QLCDNumber, QObject::connect(), Digital Clock Example, Tetrix Example, Meta-Object System, and Qt's Property System.
© 2020 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.
The QOpenGLDebugLogger enables logging of OpenGL debugging messages. More...
Header: | #include <QOpenGLDebugLogger> |
qmake: | QT += gui |
Since: | Qt 5.1 |
Inherits: | QObject |
Public Types
enum | LoggingMode { AsynchronousLogging, SynchronousLogging } |
Properties
- loggingMode : const LoggingMode
- 1 property inherited from QObject
Public Functions
QOpenGLDebugLogger(QObject *parent = Q_NULLPTR) | |
~QOpenGLDebugLogger() | |
void | disableMessages(QOpenGLDebugMessage::Sources sources = QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::Types types = QOpenGLDebugMessage::AnyType, QOpenGLDebugMessage::Severities severities = QOpenGLDebugMessage::AnySeverity) |
void | disableMessages(const QVector<GLuint> &ids, QOpenGLDebugMessage::Sources sources = QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::Types types = QOpenGLDebugMessage::AnyType) |
void | enableMessages(QOpenGLDebugMessage::Sources sources = QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::Types types = QOpenGLDebugMessage::AnyType, QOpenGLDebugMessage::Severities severities = QOpenGLDebugMessage::AnySeverity) |
void | enableMessages(const QVector<GLuint> &ids, QOpenGLDebugMessage::Sources sources = QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::Types types = QOpenGLDebugMessage::AnyType) |
bool | initialize() |
bool | isLogging() const |
QList<QOpenGLDebugMessage> | loggedMessages() const |
LoggingMode | loggingMode() const |
qint64 | maximumMessageLength() const |
void | popGroup() |
void | pushGroup(const QString &name, GLuint id = 0, QOpenGLDebugMessage::Source source = QOpenGLDebugMessage::ApplicationSource) |
- 31 public functions inherited from QObject
Public Slots
void | logMessage(const QOpenGLDebugMessage &debugMessage) |
void | startLogging(LoggingMode loggingMode = AsynchronousLogging) |
void | stopLogging() |
- 1 public slot inherited from QObject
Signals
void | messageLogged(const QOpenGLDebugMessage &debugMessage) |
- 2 signals inherited from QObject
Additional Inherited Members
- 1 public variable inherited from QObject
- 10 static public members inherited from QObject
- 9 protected functions inherited from QObject
- 2 protected variables inherited from QObject
Detailed Description
The QOpenGLDebugLogger enables logging of OpenGL debugging messages.
Introduction
OpenGL programming can be very error prone. Most of the time, a single failing call to OpenGL can cause an entire portion of an application to stop working, with nothing being drawn on the screen.
The only way to be sure that no errors are being returned from the OpenGL implementation is checking with glGetError
after each and every API call. Moreover, OpenGL errors stack up, therefore glGetError should always be used in a loop like this:
There are also many other information we are interested in (as application developers), for instance performance issues, or warnings about using deprecated APIs. Those kind of messages are not reported through the ordinary OpenGL error reporting mechanisms.
QOpenGLDebugLogger aims at addressing these issues by providing access to the OpenGL debug log. If your OpenGL implementation supports it (by exposing the GL_KHR_debug
extension), messages from the OpenGL server will be either logged in an internal OpenGL log, or passed in 'real-time' to listeners as they're generated from OpenGL.
QOpenGLDebugLogger supports both these modes of operation. Refer to the following sections to find out the differences between them.
Creating an OpenGL Debug Context
For efficiency reasons, OpenGL implementations are allowed not to create any debug output at all, unless the OpenGL context is a debug context. In order to create a debug context from Qt, you must set the QSurfaceFormat::DebugContext format option on the QSurfaceFormat used to create the QOpenGLContext object:
Note that requesting a 3.2 OpenGL Core Profile is just for the example's purposes; this class is not tied to any specific OpenGL or OpenGL ES version, as it relies on the availability of the GL_KHR_debug
extension (see below).
Creating and Initializing a QOpenGLDebugLogger
QOpenGLDebugLogger is a simple QObject-derived class. Just like all QObject subclasses, you create an instance (and optionally specify a parent object), and like the other OpenGL functions in Qt you must initialize it before usage by calling initialize() whilst there is a current OpenGL context:
Note that the GL_KHR_debug
extension must be available in the context in order to access the messages logged by OpenGL. You can check the presence of this extension by calling:
where ctx
is a valid QOpenGLContext. If the extension is not available, initialize() will return false.
Reading the Internal OpenGL Debug Log
OpenGL implementations keep an internal log of debug messages. Messages stored in this log can be retrieved by using the loggedMessages() function:
The internal log has a limited size; when it fills up, older messages will get discarded to make room for the new incoming messages. When you call loggedMessages(), the internal log will be emptied as well.
If you want to be sure not to lose any debug message, you must use real-time logging instead of calling this function. However, debug messages might still be generated in the timespan between context creation and activation of real-time logging (or, in general, when the real-time logging is disabled).
Real-time logging of messages
It is also possible to receive a stream of debug messages from the OpenGL server as they are generated by the implementation. In order to do so, you need to connect a suitable slot to the messageLogged() signal, and start logging by calling startLogging():
Similarly, logging can be disabled at any time by calling the stopLogging() function.
Real-time logging can be either asynchronous or synchronous, depending on the parameter passed to startLogging(). When logging in asynchronous mode (the default, as it has a very small overhead), the OpenGL implementation can generate messages at any time, and/or in an order which is different from the order of the OpenGL commands which caused those messages to be logged. The messages could also be generated from a thread that it's different from the thread the context is currently bound to. This is because OpenGL implementations are usually highly threaded and asynchronous, and therefore no warranties are made about the relative order and the timings of the debug messages.
On the other hand, logging in synchronous mode has a high overhead, but the OpenGL implementation guarantees that all the messages caused by a certain command are received in order, before the command returns, and from the same thread the OpenGL context is bound to.
This means that when logging in synchronous mode you will be able to run your OpenGL application in a debugger, put a breakpoint on a slot connected to the messageLogged() signal, and see in the backtrace the exact call that caused the logged message. This can be extremely useful to debug an OpenGL problem. Note that if OpenGL rendering is happening in another thread, you must force the signal/slot connection type to Qt::DirectConnection in order to be able to see the actual backtrace.
Refer to the LoggingMode enum documentation for more information about logging modes.
Note: When real-time logging is enabled, debug messages will not be inserted in the internal OpenGL debug log any more; messages already present in the internal log will not be deleted, nor they will be emitted through the messageLogged() signal. Since some messages might be generated before real-time logging is started (and therefore be kept in the internal OpenGL log), it is important to always check if it contains any message after calling startLogging().
Inserting Messages in the Debug Log
It is possible for applications and libraries to insert custom messages in the debug log, for instance for marking a group of related OpenGL commands and therefore being then able to identify eventual messages coming from them.
In order to do so, you can create a QOpenGLDebugMessage object by calling createApplicationMessage() or createThirdPartyMessage(), and then inserting it into the log by calling logMessage():
Note that OpenGL implementations have a vendor-specific limit to the length of the messages that can be inserted in the debug log. You can retrieve this length by calling the maximumMessageLength() method; messages longer than the limit will automatically get truncated.
Controlling the Debug Output
QOpenGLDebugMessage is also able to apply filters to the debug messages, and therefore limit the amount of messages logged. You can enable or disable logging of messages by calling enableMessages() and disableMessages() respectively. By default, all messages are logged.
It is possible to enable or disable messages by selecting them by:
- source, type and severity (and including all ids in the selection);
- id, source and type (and including all severities in the selection).
Note that the 'enabled' status for a given message is a property of the (id, source, type, severity) tuple; the message attributes do not form a hierarchy of any kind. You should be careful about the order of the calls to enableMessages() and disableMessages(), as it will change which messages will are enabled / disabled.
It's not possible to filter by the message text itself; applications have to do that on their own (in slots connected to the messageLogged() signal, or after fetching the messages in the internal debug log through loggedMessages()).
In order to simplify the management of the enabled / disabled statuses, QOpenGLDebugMessage also supports the concept of debug groups
. A debug group contains the group of enabled / disabled configurations of debug messages. Moreover, debug groups are organized in a stack: it is possible to push and pop groups by calling pushGroup() and popGroup() respectively. (When an OpenGL context is created, there is already a group in the stack).
The enableMessages() and disableMessages() functions will modify the configuration in the current debug group, that is, the one at the top of the debug groups stack.
When a new group is pushed onto the debug groups stack, it will inherit the configuration of the group that was previously on the top of the stack. Vice versa, popping a debug group will restore the configuration of the debug group that becomes the new top.
Pushing (respectively popping) debug groups will also automatically generate a debug message of type QOpenGLDebugMessage::GroupPushType (respectively GroupPopType).
See also QOpenGLDebugMessage.
Member Type Documentation
enum QOpenGLDebugLogger::LoggingMode
The LoggingMode enum defines the logging mode of the logger object.
Constant | Value | Description |
---|---|---|
QOpenGLDebugLogger::AsynchronousLogging | 0 | Messages from the OpenGL server are logged asynchronously. This means that messages can be logged some time after the corresponding OpenGL actions that caused them, and even be received in an out-of-order fashion, depending on the OpenGL implementation. This mode has a very low performance penalty, as OpenGL implementations are heavily threaded and asynchronous by nature. |
QOpenGLDebugLogger::SynchronousLogging | 1 | Messages from the OpenGL server are logged synchronously and sequentially. This has a severe performance hit, as OpenGL implementations are very asynchronous by nature; but it's very useful to debug OpenGL problems, as OpenGL guarantees that the messages generated by a OpenGL command will be logged before the corresponding command execution has returned. Therefore, you can install a breakpoint on the messageLogged() signal and see in the backtrace which OpenGL command caused it; the only caveat is that if you are using OpenGL from multiple threads you may need to force direct connection when connecting to the messageLogged() signal. |
Property Documentation
loggingMode : const LoggingMode
This property holds the logging mode passed to startLogging().
Note that logging must have been started or the value of this property will be meaningless.
Access functions:
See also startLogging() and isLogging().
Member Function Documentation
QOpenGLDebugLogger::QOpenGLDebugLogger(QObject *parent = Q_NULLPTR)
Constructs a new logger object with the given parent.
Note: The object must be initialized before logging can happen.
See also initialize().
QOpenGLDebugLogger::~QOpenGLDebugLogger()
Destroys the logger object.
void QOpenGLDebugLogger::disableMessages(QOpenGLDebugMessage::Sourcessources = QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::Typestypes = QOpenGLDebugMessage::AnyType, QOpenGLDebugMessage::Severitiesseverities = QOpenGLDebugMessage::AnySeverity)
Disables the logging of messages with the given sources, of the given types and with the given severities and any message id.
The logging will be disabled in the current control group.
See also enableMessages(), pushGroup(), and popGroup().
void QOpenGLDebugLogger::disableMessages(const QVector<GLuint> &ids, QOpenGLDebugMessage::Sourcessources = QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::Typestypes = QOpenGLDebugMessage::AnyType)
Disables the logging of messages with the given ids, from the given sources and of the given types and any severity.
The logging will be disabled in the current control group.
See also enableMessages(), pushGroup(), and popGroup().
void QOpenGLDebugLogger::enableMessages(QOpenGLDebugMessage::Sourcessources = QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::Typestypes = QOpenGLDebugMessage::AnyType, QOpenGLDebugMessage::Severitiesseverities = QOpenGLDebugMessage::AnySeverity)
Enables the logging of messages from the given sources, of the given types and with the given severities and any message id.
The logging will be enabled in the current control group.
See also disableMessages(), pushGroup(), and popGroup().
void QOpenGLDebugLogger::enableMessages(const QVector<GLuint> &ids, QOpenGLDebugMessage::Sourcessources = QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::Typestypes = QOpenGLDebugMessage::AnyType)
Enables the logging of messages with the given ids, from the given sources and of the given types and any severity.
The logging will be enabled in the current control group.
See also disableMessages(), pushGroup(), and popGroup().
bool QOpenGLDebugLogger::initialize()
Initializes the object in the current OpenGL context. The context must support the GL_KHR_debug
extension for the initialization to succeed. The object must be initialized before any logging can happen.
It is safe to call this function multiple times from the same context.
This function can also be used to change the context of a previously initialized object; note that in this case the object must not be logging when you call this function.
Returns true
if the logger is successfully initialized; false otherwise.
See also QOpenGLContext.
bool QOpenGLDebugLogger::isLogging() const
Returns true
if this object is currently logging, false otherwise.
See also startLogging().
[slot]
void QOpenGLDebugLogger::logMessage(const QOpenGLDebugMessage &debugMessage)
Inserts the message debugMessage into the OpenGL debug log. This provides a way for applications or libraries to insert custom messages that can ease the debugging of OpenGL applications.
Note: debugMessage must have QOpenGLDebugMessage::ApplicationSource or QOpenGLDebugMessage::ThirdPartySource as its source, and a valid type and severity, otherwise it will not be inserted into the log.
Note: The object must be initialized before logging can happen.
See also initialize().
QList<QOpenGLDebugMessage> QOpenGLDebugLogger::loggedMessages() const
Reads all the available messages in the OpenGL internal debug log and returns them. Moreover, this function will clear the internal debug log, so that subsequent invocations will not return messages that were already returned.
See also startLogging().
LoggingMode QOpenGLDebugLogger::loggingMode() const
Returns the logging mode of the object.
Note: Getter function for property loggingMode.
See also startLogging().
qint64 QOpenGLDebugLogger::maximumMessageLength() const
Returns the maximum supported length, in bytes, for the text of the messages passed to logMessage(). This is also the maximum length of a debug group name, as pushing or popping groups will automatically log a message with the debug group name as the message text.
If a message text is too long, it will be automatically truncated by QOpenGLDebugLogger.
Note: Message texts are encoded in UTF-8 when they get passed to OpenGL, so their size in bytes does not usually match the amount of UTF-16 code units, as returned f.i. by QString::length(). (It does if the message contains 7-bit ASCII only data, which is typical for debug messages.)
[signal]
void QOpenGLDebugLogger::messageLogged(const QOpenGLDebugMessage &debugMessage)
This signal is emitted when a debug message (wrapped by the debugMessage argument) is logged from the OpenGL server.
Depending on the OpenGL implementation, this signal can be emitted from other threads than the one(s) the receiver(s) lives in, and even different from the thread the QOpenGLContext in which this object has been initialized lives in. Moreover, the signal could be emitted from multiple threads at the same time. This is normally not a problem, as Qt will utilize a queued connection for cross-thread signal emissions, but if you force the connection type to Direct then you must be aware of the potential races in the slots connected to this signal.
If logging have been started in SynchronousLogging mode, OpenGL guarantees that this signal will be emitted from the same thread the QOpenGLContext has been bound to, and no concurrent invocations will ever happen.
Note: Logging must have been started, or this signal will not be emitted.
See also startLogging().
void QOpenGLDebugLogger::popGroup()
Pops the topmost debug group from the debug groups stack. If the group is successfully popped, OpenGL will automatically log a message with message, id and source matching those of the popped group, type QOpenGLDebugMessage::GroupPopType and severity QOpenGLDebugMessage::NotificationSeverity.
Popping a debug group will restore the message filtering settings of the group that becomes the top of the debug groups stack.
Note: The object must be initialized before managing debug groups.
See also pushGroup().
void QOpenGLDebugLogger::pushGroup(const QString &name, GLuintid = 0, QOpenGLDebugMessage::Sourcesource = QOpenGLDebugMessage::ApplicationSource)
Pushes a debug group with name name, id id, and source source onto the debug groups stack. If the group is successfully pushed, OpenGL will automatically log a message with message name, id id, source source, type QOpenGLDebugMessage::GroupPushType and severity QOpenGLDebugMessage::NotificationSeverity.
The newly pushed group will inherit the same filtering settings of the group that was on the top of the stack; that is, the filtering will not be changed by pushing a new group.
Note: The source must either be QOpenGLDebugMessage::ApplicationSource or QOpenGLDebugMessage::ThirdPartySource, otherwise the group will not be pushed.
Note: The object must be initialized before managing debug groups.
See also popGroup(), enableMessages(), and disableMessages().
[slot]
void QOpenGLDebugLogger::startLogging(LoggingModeloggingMode = AsynchronousLogging)
Starts logging messages coming from the OpenGL server. When a new message is received, the signal messageLogged() is emitted, carrying the logged message as argument.
Qt Slot Call Ordering
loggingMode specifies whether the logging must be asynchronous (the default) or synchronous.
QOpenGLDebugLogger will record the values of GL_DEBUG_OUTPUT
and GL_DEBUG_OUTPUT_SYNCHRONOUS
when logging is started, and set them back when logging is stopped. Moreover, any user-defined OpenGL debug callback installed when this function is invoked will be restored when logging is stopped; QOpenGLDebugLogger will ensure that the pre-existing callback will still be invoked when logging.
Note: It's not possible to change the logging mode without stopping and starting logging again. This might change in a future version of Qt.
Note: The object must be initialized before logging can happen.
See also stopLogging() and initialize().
[slot]
void QOpenGLDebugLogger::stopLogging()
Stops logging messages from the OpenGL server.
See also startLogging().