Gérer la modalité des fenêtres¶
C'est un vieux serpent de mer, j'essaye donc d'écrire ce qu'on a appris pour y voir plus clair, laisser une trace et garder un point commun central de documentation autour de cette histoire.
Contexte:¶
- une mainwindow qui ouvre une fenêtre, qui doit venir au dessus de l'autre ? réponse évidente: la 2° fenêtre. Solution moins évidente.
- un splashscreen pendant lequel certains tests sont fait (au pif, vérification d'une nouvelle version disponible) et on souhaite avoir une popup "au dessus" du splashscreen
- une mainwindows qui ouvre un éditeur au dessus, lequel ouvre une fenêtre mediathequeget pour télécharger des images, laquelle doit afficher une popup d'erreur ... ça se complique
- une mainwindows qui ouvre un éditeur au dessus, lequel ouvre une fenêtre mediathequepush pour publier le module créé, détection de la nécessité d'être authentifié par un objet "profond, caché dans abuleduapplication", lequel pousse donc une popup sso login tout au dessus de toutes les autres et enfin, un message d'alerte ...
Comment faire ?¶
Réponse: jouer avec la modalité des fenêtres mais attention il y a des collisions entre
- les systèmes d'exploitations qui n'interprètent pas tous tout à fait pareil les différentes commandes, lisez bien la doc de qt à ce sujet
- types d'objets
- QSplashScreen -> on ne l'utilise surtout pas, AbulEduSplashScreenV1 hérite uniquement de QWidget
- QWidget
- [...]
- modalité setWindowModality
- Qt::NonModal: aucune modalité, aucun moyen d'être sûr que la fenêtre sera "au dessus", même si on joue avec des raise()
- Qt::WindowModal: ne gère la modalité que par filiation
- Qt::ApplicationModal: c'est celle qu'on utilise, une fenêtre ApplicationModal qui ouvre une autre fenêtre ApplicationModal sera en dessous de la 2°, c'est le comportement qu'on cherche :)
- flags setWindowFlags
- Qt::SplashScreen
- Qt::SubWindow: surtout pas, cette fenêtre restera au dessus des autres ...
- Qt::WindowStaysOnTopHint: uniquement pour abuledusplashscreenv1 svp
Où le faire ?¶
Je vois souvent qu'on essaye d'appliquer la modalité dans le constructeur de nos objets, ça m'amène à la réflexion suivante:
- Si la fenêtre qu'on ouvre n'a pas de parent -> on lui applique la bonne modalité
- Si le widget est embarqué dans un autre -> il ne faut pas lui appliquer de modalité
Mais comme les développeurs sont parfois farceurs et créent un objet avec parent puis ensuite le rendent orphelin (sans parent donc) il me semble plus rusé d'appliquer la modalité de l'objet en surclassant la méthode showEvent, exemple:
void AbulEduSSOLoginV1::showEvent(QShowEvent *event) { if(m_localDebug) { qDebug() << __FILE__ << __LINE__ << __FUNCTION__; } if(parent() == 0) { setWindowModality(Qt::ApplicationModal); } }