Sur cette page

QOpenGLDebugLogger Class

QOpenGLDebugLogger permet la journalisation des messages de débogage OpenGL. En savoir plus...

En-tête : #include <QOpenGLDebugLogger>
CMake : find_package(Qt6 REQUIRED COMPONENTS OpenGL)
target_link_libraries(mytarget PRIVATE Qt6::OpenGL)
qmake : QT += opengl
Hérite de : QObject

Types publics

enum LoggingMode { AsynchronousLogging, SynchronousLogging }

Propriétés

Fonctions publiques

QOpenGLDebugLogger(QObject *parent = nullptr)
virtual ~QOpenGLDebugLogger()
void disableMessages(QOpenGLDebugMessage::Sources sources = QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::Types types = QOpenGLDebugMessage::AnyType, QOpenGLDebugMessage::Severities severities = QOpenGLDebugMessage::AnySeverity)
void disableMessages(const QList<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 QList<GLuint> &ids, QOpenGLDebugMessage::Sources sources = QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::Types types = QOpenGLDebugMessage::AnyType)
bool initialize()
bool isLogging() const
QList<QOpenGLDebugMessage> loggedMessages() const
QOpenGLDebugLogger::LoggingMode loggingMode() const
qint64 maximumMessageLength() const
void popGroup()
void pushGroup(const QString &name, GLuint id = 0, QOpenGLDebugMessage::Source source = QOpenGLDebugMessage::ApplicationSource)

Emplacements publics

void logMessage(const QOpenGLDebugMessage &debugMessage)
void startLogging(QOpenGLDebugLogger::LoggingMode loggingMode = AsynchronousLogging)
void stopLogging()

Signaux

void messageLogged(const QOpenGLDebugMessage &debugMessage)

Description détaillée

Introduction

La programmation OpenGL peut être source de nombreuses erreurs. La plupart du temps, un seul appel OpenGL qui échoue peut entraîner l'arrêt complet d'une partie de l'application, sans qu'aucun élément ne s'affiche à l'écran.

La seule façon de s'assurer qu'aucune erreur n'est renvoyée par l'implémentation OpenGL est de vérifier avec ` glGetError ` après chaque appel à l'API. De plus, les erreurs OpenGL s'accumulent ; il faut donc toujours utiliser `glGetError` dans une boucle comme celle-ci :

GLenum error = GL_NO_ERROR;
do {
    error = glGetError();
    if (error != GL_NO_ERROR) {
        // handle the error
    }
} while (error != GL_NO_ERROR);

Si vous essayez de vider la pile d’erreurs, veillez non seulement à ne pas continuer jusqu’à ce que GL_NO_ERROR soit renvoyé, mais aussi à interrompre l’exécution en cas de GL_CONTEXT_LOST, car cette valeur d’erreur se répète indéfiniment.

Il existe également de nombreuses autres informations qui nous intéressent (en tant que développeurs d’applications), par exemple les problèmes de performances ou les avertissements concernant l’utilisation d’API obsolètes. Ce type de messages n’est pas signalé par les mécanismes habituels de signalement des erreurs OpenGL.

QOpenGLDebugLogger vise à résoudre ces problèmes en donnant accès au journal de débogage OpenGL. Si votre implémentation OpenGL le prend en charge (en exposant l’extension GL_KHR_debug ), les messages provenant du serveur OpenGL seront soit consignés dans un journal OpenGL interne, soit transmis en « temps réel » aux écouteurs au fur et à mesure de leur génération par OpenGL.

QOpenGLDebugLogger prend en charge ces deux modes de fonctionnement. Reportez-vous aux sections suivantes pour découvrir leurs différences.

Création d’un contexte de débogage OpenGL

Pour des raisons d’efficacité, les implémentations OpenGL sont autorisées à ne générer aucune sortie de débogage, sauf si le contexte OpenGL est un contexte de débogage. Pour créer un contexte de débogage à partir de Qt, vous devez définir l’option de format « QSurfaceFormat::DebugContext » sur l’ QSurfaceFormat utilisé pour créer l’objet ` QOpenGLContext ` :

QSurfaceFormat format;
// asks for a OpenGL 3.2 debug context using the Core profile
format.setMajorVersion(3);
format.setMinorVersion(2);
format.setProfile(QSurfaceFormat::CoreProfile);
format.setOption(QSurfaceFormat::DebugContext);

QOpenGLContext *context = new QOpenGLContext;
context->setFormat(format);
context->create();

Notez que la demande d’un profil OpenGL Core 3.2 n’est qu’à titre d’exemple ; cette classe n’est liée à aucune version spécifique d’OpenGL ou d’OpenGL ES, car elle repose sur la disponibilité de l’extension « GL_KHR_debug » (voir ci-dessous).

Création et initialisation d’un QOpenGLDebugLogger

QOpenGLDebugLogger est une classe simple dérivée de ` QObject`. À l’instar de toutes les sous-classes de ` QObject `, vous créez une instance (et spécifiez éventuellement un objet parent) et, comme pour les autres fonctions OpenGL de Qt, vous devez l’initialiser avant utilisation en appelant ` initialize()` tant qu’un contexte OpenGL est actif :

QOpenGLContext *ctx = QOpenGLContext::currentContext();
QOpenGLDebugLogger *logger = new QOpenGLDebugLogger(this);

logger->initialize(); // initializes in the current context, i.e. ctx

Notez que l’extension GL_KHR_debug doit être disponible dans le contexte pour pouvoir accéder aux messages enregistrés par OpenGL. Vous pouvez vérifier la présence de cette extension en appelant :

ctx->hasExtension(QByteArrayLiteral("GL_KHR_debug"));

où ctx est une valeur valide de type QOpenGLContext. Si l'extension n'est pas disponible, la fonction initialize() renverra la valeur false.

Lecture du journal de débogage interne d'OpenGL

Les implémentations OpenGL tiennent un journal interne des messages de débogage. Les messages stockés dans ce journal peuvent être récupérés à l’aide de la fonction loggedMessages() :

const QList<QOpenGLDebugMessage> messages = logger->loggedMessages();
for (const QOpenGLDebugMessage&message: messages)
    qDebug() << message;

Le journal interne a une taille limitée ; lorsqu’il est plein, les messages les plus anciens sont supprimés pour faire de la place aux nouveaux messages entrants. Lorsque vous appelez la fonction ` loggedMessages()`, le journal interne est également vidé.

Si vous souhaitez vous assurer de ne perdre aucun message de débogage, vous devez utiliser la journalisation en temps réel plutôt que d'appeler cette fonction. Cependant, des messages de débogage peuvent tout de même être générés pendant le laps de temps entre la création du contexte et l'activation de la journalisation en temps réel (ou, de manière générale, lorsque la journalisation en temps réel est désactivée).

Journalisation en temps réel des messages

Il est également possible de recevoir un flux de messages de débogage provenant du serveur OpenGL au fur et à mesure qu’ils sont générés par l’implémentation. Pour ce faire, vous devez connecter un slot approprié au signal ` messageLogged()` et démarrer la journalisation en appelant ` startLogging()` :

connect(logger, &QOpenGLDebugLogger::messageLogged, receiver, &LogHandler::handleLoggedMessage);
logger->startLogging();

De même, la journalisation peut être désactivée à tout moment en appelant la fonction ` stopLogging()`.

La journalisation en temps réel peut être asynchrone ou synchrone, selon le paramètre passé à ` startLogging()`. En mode asynchrone (mode par défaut, car il n’entraîne qu’une très faible surcharge), l’implémentation OpenGL peut générer des messages à tout moment et/ou dans un ordre différent de celui des commandes OpenGL à l’origine de ces messages. Les messages peuvent également être générés par un thread différent de celui auquel le contexte est actuellement lié. En effet, les implémentations OpenGL sont généralement hautement multithreadées et asynchrones ; par conséquent, aucune garantie n’est donnée quant à l’ordre relatif et au timing des messages de débogage.

En revanche, la journalisation en mode synchrone implique une surcharge importante, mais l’implémentation OpenGL garantit que tous les messages générés par une commande donnée sont reçus dans l’ordre, avant que la commande ne renvoie une valeur, et à partir du même thread auquel le contexte OpenGL est lié.

Cela signifie que lorsque vous effectuez un journalisation en mode synchrone, vous pourrez exécuter votre application OpenGL dans un débogueur, placer un point d’arrêt sur un slot connecté au signal messageLogged(), et voir dans la trace de pile l’appel exact qui a généré le message journalisé. Cela peut s’avérer extrêmement utile pour déboguer un problème OpenGL. Notez que si le rendu OpenGL s’effectue dans un autre thread, vous devez forcer le type de connexion signal/slot à « Qt::DirectConnection » afin de pouvoir voir la trace de pile réelle.

Reportez-vous à la documentation sur l’énumération LoggingMode pour plus d’informations sur les modes de journalisation.

Remarque : lorsque la journalisation en temps réel est activée, les messages de débogage ne sont plus insérés dans le journal de débogage interne d’OpenGL ; les messages déjà présents dans ce journal ne sont pas supprimés, et ne sont pas non plus émis via le signal ` messageLogged()`. Étant donné que certains messages peuvent être générés avant le démarrage de la journalisation en temps réel (et donc conservés dans le journal OpenGL interne), il est important de toujours vérifier si celui-ci contient des messages après avoir appelé ` startLogging()`.

Insertion de messages dans le journal de débogage

Les applications et les bibliothèques ont la possibilité d’insérer des messages personnalisés dans le journal de débogage, par exemple pour marquer un groupe de commandes OpenGL associées et pouvoir ainsi identifier les messages éventuels provenant de celles-ci.

Pour ce faire, vous pouvez créer un objet ` QOpenGLDebugMessage ` en appelant ` createApplicationMessage()` ou ` createThirdPartyMessage()`, puis l’insérer dans le journal en appelant ` logMessage()` :

QOpenGLDebugMessage message =
    QOpenGLDebugMessage::createApplicationMessage(QStringLiteral("Custom message"));

logger->logMessage(message);

Notez que les implémentations OpenGL imposent une limite, propre à chaque éditeur, quant à la longueur des messages pouvant être insérés dans le journal de débogage. Vous pouvez récupérer cette longueur en appelant la méthode maximumMessageLength() ; les messages dépassant cette limite seront automatiquement tronqués.

Contrôle de la sortie de débogage

QOpenGLDebugMessage Il est également possible d'appliquer des filtres aux messages de débogage, et donc de limiter le nombre de messages enregistrés. Vous pouvez activer ou désactiver l'enregistrement des messages en appelant respectivement enableMessages() et disableMessages(). Par défaut, tous les messages sont enregistrés.

Il est possible d’activer ou de désactiver des messages en les sélectionnant selon :

  • source, type et niveau de gravité (en incluant tous les identifiants dans la sélection) ;
  • ID, source et type (en incluant tous les niveaux de gravité dans la sélection).

Notez que le statut « activé » d’un message donné est une propriété du tuple (ID, source, type, gravité) ; les attributs du message ne forment aucune hiérarchie. Vous devez faire attention à l’ordre des appels à enableMessages() et disableMessages(), car cela modifie les messages qui seront activés ou désactivés.

Il n’est pas possible de filtrer en fonction du texte du message lui-même ; les applications doivent le faire elles-mêmes (dans des slots connectés au signal messageLogged() ou après avoir récupéré les messages dans le journal de débogage interne via loggedMessages()).

Afin de simplifier la gestion des états activés/désactivés, QOpenGLDebugMessage prend également en charge le concept de debug groups. Un groupe de débogage regroupe les configurations d’activation/désactivation des messages de débogage. De plus, les groupes de débogage sont organisés en pile : il est possible d’ajouter et de retirer des groupes en appelant respectivement pushGroup() et popGroup(). (Lorsqu’un contexte OpenGL est créé, un groupe se trouve déjà dans la pile).

Les fonctions ` enableMessages()` et ` disableMessages()` modifient la configuration du groupe de débogage actuel, c'est-à-dire celui qui se trouve au sommet de la pile des groupes de débogage.

Lorsqu’un nouveau groupe est ajouté à la pile des groupes de débogage, il hérite de la configuration du groupe qui se trouvait auparavant en haut de la pile. Inversement, le retrait d’un groupe de débogage rétablit la configuration du groupe de débogage qui devient alors le nouveau groupe en tête de pile.

L'ajout (ou le retrait) de groupes de débogage génère également automatiquement un message de débogage de type « QOpenGLDebugMessage::GroupPushType » (ou « GroupPopType »).

Voir également QOpenGLDebugMessage.

Documentation sur les types de membres

enum QOpenGLDebugLogger::LoggingMode

L'énumération `LoggingMode` définit le mode de journalisation de l'objet `logger`.

ConstanteValeurDescription
QOpenGLDebugLogger::AsynchronousLogging0Les messages provenant du serveur OpenGL sont consignés de manière asynchrone. Cela signifie que les messages peuvent être consignés quelque temps après les actions OpenGL correspondantes qui les ont générés, et même être reçus dans un ordre aléatoire, selon l’implémentation d’OpenGL. Ce mode n’entraîne qu’une très faible perte de performances, car les implémentations OpenGL sont, par nature, fortement multithreadées et asynchrones.
QOpenGLDebugLogger::SynchronousLogging1Les messages provenant du serveur OpenGL sont consignés de manière synchrone et séquentielle. Cela entraîne une perte de performances importante, car les implémentations OpenGL sont par nature très asynchrones ; mais cela s’avère très utile pour déboguer les problèmes OpenGL, car OpenGL garantit que les messages générés par une commande OpenGL seront consignés avant que l’exécution de la commande correspondante ne soit terminée. Vous pouvez donc placer un point d’arrêt sur le signal ` messageLogged()` et voir dans la trace de pile quelle commande OpenGL l’a déclenché ; la seule mise en garde est que si vous utilisez OpenGL à partir de plusieurs threads, vous devrez peut-être forcer une connexion directe lors de la connexion au signal ` messageLogged()`.

Documentation des propriétés

[read-only] loggingMode : LoggingMode

Cette propriété contient le mode de journalisation transmis à la fonction ` startLogging()`.

Notez que la journalisation doit avoir été lancée, sinon la valeur de cette propriété n'aura aucun sens.

Fonctions d'accès :

QOpenGLDebugLogger::LoggingMode loggingMode() const

Voir également startLogging() et isLogging().

Documentation des fonctions membres

[explicit] QOpenGLDebugLogger::QOpenGLDebugLogger(QObject *parent = nullptr)

Crée un nouvel objet « logger » avec l'parent on fournie.

Remarque : l'objet doit être initialisé avant que la journalisation puisse avoir lieu.

Voir aussi initialize().

[virtual noexcept] QOpenGLDebugLogger::~QOpenGLDebugLogger()

Supprime l'objet « logger ».

void QOpenGLDebugLogger::disableMessages(QOpenGLDebugMessage::Sources sources = QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::Types types = QOpenGLDebugMessage::AnyType, QOpenGLDebugMessage::Severities severities = QOpenGLDebugMessage::AnySeverity)

Désactive la journalisation des messages dont l'sources, l'types et l'severities sont les suivantes, ainsi que pour tout identifiant de message.

La journalisation sera désactivée dans le groupe de contrôle actuel.

Voir également enableMessages(), pushGroup() et popGroup().

void QOpenGLDebugLogger::disableMessages(const QList<GLuint> &ids, QOpenGLDebugMessage::Sources sources = QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::Types types = QOpenGLDebugMessage::AnyType)

Désactive la journalisation des messages présentant l'ids spécifiée, provenant de l'sources spécifiée et ayant l'types spécifiée, quel que soit leur niveau de gravité.

La journalisation sera désactivée dans le groupe de contrôle actuel.

Voir également enableMessages(), pushGroup() et popGroup().

void QOpenGLDebugLogger::enableMessages(QOpenGLDebugMessage::Sources sources = QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::Types types = QOpenGLDebugMessage::AnyType, QOpenGLDebugMessage::Severities severities = QOpenGLDebugMessage::AnySeverity)

Active la journalisation des messages provenant de l'sources indiquée, de l'types indiquée, avec le severities indiqué et pour tout identifiant de message.

La journalisation sera activée dans le groupe de contrôle actuel.

Voir également disableMessages(), pushGroup() et popGroup().

void QOpenGLDebugLogger::enableMessages(const QList<GLuint> &ids, QOpenGLDebugMessage::Sources sources = QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::Types types = QOpenGLDebugMessage::AnyType)

Active la journalisation des messages présentant l'ids spécifiée, provenant de l'sources spécifiée et ayant l'types spécifiée, quel que soit leur niveau de gravité.

La journalisation sera activée dans le groupe de contrôle actuel.

Voir également disableMessages(), pushGroup() et popGroup().

bool QOpenGLDebugLogger::initialize()

Initialise l'objet dans le contexte OpenGL actuel. Pour que l'initialisation aboutisse, le contexte doit prendre en charge l'extension « GL_KHR_debug ». L'objet doit être initialisé avant que toute opération de journalisation puisse avoir lieu.

Vous pouvez appeler cette fonction plusieurs fois à partir du même contexte en toute sécurité.

Cette fonction peut également être utilisée pour modifier le contexte d’un objet précédemment initialisé ; notez que dans ce cas, l’objet ne doit pas être en cours d’enregistrement lorsque vous appelez cette fonction.

Renvoie ` true ` si le logger est initialisé avec succès ; `false` dans le cas contraire.

Voir également QOpenGLContext.

bool QOpenGLDebugLogger::isLogging() const

Renvoie « true » si cet objet est en cours d'enregistrement, « false » dans le cas contraire.

Voir aussi startLogging().

[slot] void QOpenGLDebugLogger::logMessage(const QOpenGLDebugMessage &debugMessage)

Insère le message « debugMessage » dans le journal de débogage OpenGL. Cela permet aux applications ou aux bibliothèques d’insérer des messages personnalisés susceptibles de faciliter le débogage des applications OpenGL.

Remarque : debugMessage doit avoir pour source QOpenGLDebugMessage::ApplicationSource ou QOpenGLDebugMessage::ThirdPartySource, ainsi qu’un type et un niveau de gravité valides, sinon il ne sera pas inséré dans le journal.

Remarque : l’objet doit être initialisé avant que l’enregistrement dans le journal puisse avoir lieu.

Voir aussi initialize().

QList<QOpenGLDebugMessage> QOpenGLDebugLogger::loggedMessages() const

Lit tous les messages disponibles dans le journal de débogage interne d'OpenGL et les renvoie. De plus, cette fonction efface le journal de débogage interne, de sorte que les appels suivants ne renvoient pas de messages déjà renvoyés.

Voir également startLogging().

QOpenGLDebugLogger::LoggingMode QOpenGLDebugLogger::loggingMode() const

Renvoie le mode de journalisation de l'objet.

Remarque : fonctiongetter pour la propriété loggingMode.

Voir aussi startLogging().

qint64 QOpenGLDebugLogger::maximumMessageLength() const

Renvoie la longueur maximale prise en charge, en octets, pour le texte des messages transmis à la fonction logMessage(). Il s'agit également de la longueur maximale d'un nom de groupe de débogage, car l'ajout ou la suppression de groupes entraîne automatiquement l'enregistrement d'un message dont le texte correspond au nom du groupe de débogage.

Si le texte d’un message est trop long, il sera automatiquement tronqué par la fonction ` QOpenGLDebugLogger()`.

Remarque : les textesdes messages sont encodés en UTF-8 lorsqu’ils sont transmis à OpenGL ; leur taille en octets ne correspond donc généralement pas au nombre d’unités de code UTF-16, tel que renvoyé, par exemple, par la fonction QString::length(). (C’est le cas si le message contient uniquement des données ASCII 7 bits, ce qui est courant pour les messages de débogage.)

[signal] void QOpenGLDebugLogger::messageLogged(const QOpenGLDebugMessage &debugMessage)

Ce signal est émis lorsqu'un message de débogage (encadré par l'argument ` debugMessage `) est consigné par le serveur OpenGL.

Selon l’implémentation d’OpenGL, ce signal peut être émis depuis d’autres threads que celui ou ceux dans lesquels se trouvent le ou les récepteurs, et même depuis un thread différent de celui dans lequel se trouve l’ QOpenGLContext dans laquelle cet objet a été initialisé. De plus, le signal peut être émis simultanément par plusieurs threads. Cela ne pose généralement pas de problème, car Qt utilise une connexion en file d’attente pour les émissions de signaux inter-threads, mais si vous forcez le type de connexion à « Direct », vous devez alors être conscient des conflits d’accès potentiels dans les slots connectés à ce signal.

Si la journalisation a été lancée en mode « SynchronousLogging », OpenGL garantit que ce signal sera émis depuis le même thread que celui auquel l’ QOpenGLContext a été lié, et qu’aucun appel concurrent ne se produira jamais.

Remarque : la journalisation doit avoir été lancée, sinon ce signal ne sera pas émis.

Voir également startLogging().

void QOpenGLDebugLogger::popGroup()

Retire le groupe de débogage situé tout en haut de la pile des groupes de débogage. Si le retrait s'effectue correctement, OpenGL enregistrera automatiquement un message dont le texte, l'identifiant et la source correspondent à ceux du groupe retiré, avec le type QOpenGLDebugMessage::GroupPopType et le niveau de gravité QOpenGLDebugMessage::NotificationSeverity.

Le retrait d’un groupe de débogage rétablit les paramètres de filtrage des messages du groupe qui devient alors le premier de la pile des groupes de débogage.

Remarque : l’objet doit être initialisé avant de pouvoir gérer les groupes de débogage.

Voir également pushGroup().

void QOpenGLDebugLogger::pushGroup(const QString &name, GLuint id = 0, QOpenGLDebugMessage::Source source = QOpenGLDebugMessage::ApplicationSource)

Ajoute un groupe de débogage nommé « name », dont l'identifiant est « id » et la source « source », à la pile des groupes de débogage. Si l'ajout du groupe aboutit, OpenGL enregistrera automatiquement un message avec le message « name », l'identifiant « id », la source « source », le type « QOpenGLDebugMessage::GroupPushType » et le niveau de gravité « QOpenGLDebugMessage::NotificationSeverity ».

Le groupe nouvellement ajouté héritera des mêmes paramètres de filtrage que le groupe qui se trouvait en haut de la pile ; en d’autres termes, le filtrage ne sera pas modifié par l’ajout d’un nouveau groupe.

Remarque : l’ source e doit être soit QOpenGLDebugMessage::ApplicationSource, soit QOpenGLDebugMessage::ThirdPartySource; dans le cas contraire, le groupe ne sera pas ajouté.

Remarque : l’objet doit être initialisé avant de gérer les groupes de débogage.

Voir également popGroup(), enableMessages() et disableMessages().

[slot] void QOpenGLDebugLogger::startLogging(QOpenGLDebugLogger::LoggingMode loggingMode = AsynchronousLogging)

Lance la journalisation des messages provenant du serveur OpenGL. Lorsqu'un nouveau message est reçu, le signal messageLogged() est émis, avec le message journalisé comme argument.

loggingMode Spécifie si la journalisation doit être asynchrone (par défaut) ou synchrone.

QOpenGLDebugLogger Enregistre les valeurs de ` GL_DEBUG_OUTPUT ` et ` GL_DEBUG_OUTPUT_SYNCHRONOUS ` au démarrage de la journalisation, et les rétablit lorsque celle-ci est arrêtée. De plus, tout callback de débogage OpenGL défini par l’utilisateur et installé lors de l’appel de cette fonction sera restauré à l’arrêt de la journalisation ; ` QOpenGLDebugLogger ` garantit que le callback préexistant continuera d’être appelé pendant la journalisation.

Remarque : il n’est pas possible de modifier le mode de journalisation sans arrêter puis redémarrer la journalisation. Cela pourrait changer dans une future version de Qt.

Remarque : l’objet doit être initialisé avant que la journalisation puisse avoir lieu.

Voir également stopLogging() et initialize().

[slot] void QOpenGLDebugLogger::stopLogging()

Arrête la journalisation des messages provenant du serveur OpenGL.

Voir également startLogging().

© 2026 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.