Affichage dynamique des étapes d'un éditeur¶
Solution proposée pour adapter le chemin disponible de navigation dans l'éditeur aux widgets dont on souhaite la présence
Mon éditeur est un QStackedWidget, avec un premier widget "Texte", qui contient le texte, et des cases à cocher (checkBox) correspondant aux exercices qu'on souhaite, et un widget différent par type d'exercice. L'éditeur contient aussi entre les boutons précédent et suivant une rangée de labels, un pour chaque widget.
Je donne une property ("widgetLie",...) aux checkBox
ui->GEcbTexteTrous->setProperty("widgetLie",ui->wClosure->objectName());
Je connecte leur signal toogle(bool), qui indique si le checkBox est coché ou non, à un slot displayWidget(bool) - il faut la même signature.
connect(ui->GEcbTexteTrous, SIGNAL(toggled(bool)),this, SLOT(displayWidget(bool))); ui->twEditor->removeWidget(ui->wClosure); ui->lblTTR->hide();
(on remarque que par défaut, j'enlève les widgets et je cache les labels)
Dans ce slot, je caste mon sender en prenant la précaution (sinon erreur de segmentation) de vérifier que le cast a réussi:
QCheckBox* chBox = qobject_cast<QCheckBox*>(sender()); if (qobject_cast<QCheckBox*>(sender()) == 0) { qDebug()<<"Echec conversion"; return; } else { qDebug()<<chBox->property("widgetLie").toString(); }
La propriété me permet de trouver le widget lié
QWidget* widgetTraite = findChild<QWidget*>(chBox->property("widgetLie").toString());
Comme j'avais donné aux widgets inclus dans le QStackedWidget une property "label",
ui->twEditor->widget(1)->setProperty("labelAssocie","lblTTR");
je peux aussi retrouver le label du chemin de navigation correspondant au widget lié
QLabel* labelLie = findChild<QLabel*>(widgetTraite->property("labelAssocie").toString());
Je peux d'ores et déjà enlever le widget du chemin si on décoche le checkBox, en ajoutant dans displayWidget(bool yesNo)
if (yesNo == false) { ui->twEditor->removeWidget(widgetTraite); labelLie->hide(); qDebug()<<"J'ai enlevé "<<widgetTraite<<" et caché "<<labelLie; }
Par contre pour l'ajouter si on coche, il faut que j'indique où à la méthode "insertWidget"
j'ajoute donc à mes widget une property("rang"), qui correspond à leur place s'ils sont tous présents
Je peux alors ajouter un widget si on coche en mettant dans displayWidget(bool yesNo) un "else" à mon "if" du dessus, c'est à dire si yesNo vaut true :
else { int i = 0; bool trouvePlace = false; while (i<ui->twEditor->count() && trouvePlace == false) { if (ui->twEditor->widget(i)->property("rang").toInt() < widgetTraite->property("rang").toInt()) { qDebug()<<"je passe "<<ui->twEditor->widget(i); i++; } else { ui->twEditor->insertWidget(i,widgetTraite); labelLie->show(); qDebug()<<"J'ai ajouté "<<widgetTraite<<"à l'index "<<i<<" et montré "<<labelLie; trouvePlace = true; } } }
où je parcours les rangs des widgets présents jusqu'à ce que j'ai trouvé ma place.
En ce qui concerne l'affichage du chemin, qui dans mon cas est déjà long et risque de s'allonger encore, je vais donner à mes widgets un nom complet et un nom abrégé
ui->twEditor->widget(1)->setProperty("titre",m_nameTabs.value("texteATrous")); ui->twEditor->widget(1)->setProperty("abrege","TTR");
remarque : m_nameTabs est une QMap qui permettra de faire la correspondance lors de traductions futures
m_nameTabs.insert("texteATrous", trUtf8("Texte à trous"));
Je crée un slot updateLabelWidgetName(int index) que je connecte au changement de widget
connect(ui->twEditor, SIGNAL(currentChanged(int)),this, SLOT(updateLabelWidgetName(int)));
dans ce slot, je vais donner à tous les labels de navigation le nom abrégé et un style gris et petit,
ui->lblTTR->setText(ui->wClosure->property("abrege").toString()); ui->lblTTR->setStyleSheet("font-size:1em; font-weight:100; color:Gray; padding:0 1px 0 1px");
sauf au widget courant, au précédent et au suivant à qui je vais donner le nom complet, une fonte plus grosse et grasse. Le précédent et le suivant seront en gris, le courant en noir.
if (index > 0)
{
QLabel* labelPrecedent = findChild<QLabel*>(ui->twEditor->widget(index-1)->property("labelAssocie").toString());
labelPrecedent->setText(ui->twEditor->widget(index-1)->property("titre").toString());
labelPrecedent->setStyleSheet("font-size:2em; font-weight:700; color:Gray; padding:0 1px 0 1px");
}
QLabel* labelCourant = findChild<QLabel*>(ui->twEditor->widget(index)->property("labelAssocie").toString());
labelCourant->setText(ui->twEditor->widget(index)->property("titre").toString());
labelCourant->setStyleSheet("font-size:2em; font-weight:700; color:black; padding:0 1px 0 1px");
if(index < ui->twEditor->count()-1)
{
QLabel* labelSuivant = findChild<QLabel*>(ui->twEditor->widget(index+1)->property("labelAssocie").toString());
labelSuivant->setText(ui->twEditor->widget(index+1)->property("titre").toString());
labelSuivant->setStyleSheet("font-size:2em; font-weight:700; color:Gray; padding:0 1px 0 1px");
}
En plus d'avoir connecté ce slot au changement d'item, je l'appelle explicitement au début et dans mon slot displayWidget(bool yesNo) quand j'ajoute ou j'enlève un widget.