/**
© Florian Joncour, 2013-2018 florian@zetta-sys.com

Ce logiciel est un programme informatique faisant interface à la bibliothèque
Perspective3D, un outil de modélisation 3D à partir de vues orthographiques 2D.

Ce logiciel est régi par la licence CeCILL-C soumise au droit français et
respectant les principes de diffusion des logiciels libres. Vous pouvez
utiliser, modifier et/ou redistribuer ce programme sous les conditions
de la licence CeCILL-C telle que diffusée par le CEA, le CNRS et l'INRIA
sur le site "http://www.cecill.info".

En contrepartie de l'accessibilité au code source et des droits de copie,
de modification et de redistribution accordés par cette licence, il n'est
offert aux utilisateurs qu'une garantie limitée.  Pour les mêmes raisons,
seule une responsabilité restreinte pèse sur l'auteur du programme,  le
titulaire des droits patrimoniaux et les concédants successifs.

A cet égard  l'attention de l'utilisateur est attirée sur les risques
associés au chargement,  à l'utilisation,  à la modification et/ou au
développement et à la reproduction du logiciel par l'utilisateur étant
donné sa spécificité de logiciel libre, qui peut le rendre complexe à
manipuler et qui le réserve donc à des développeurs et des professionnels
avertis possédant  des  connaissances  informatiques approfondies.  Les
utilisateurs sont donc invités à charger  et  tester  l'adéquation  du
logiciel à leurs besoins dans des conditions permettant d'assurer la
sécurité de leurs systèmes et ou de leurs données et, plus généralement,
à l'utiliser et l'exploiter dans les mêmes conditions de sécurité.

Le fait que vous puissiez accéder à cet en-tête signifie que vous avez
pris connaissance de la licence CeCILL-C, et que vous en avez accepté les
termes.
**/

#include <QByteArray>
#include <QInputDialog>
#include <QPrinter>
#include <QMessageBox>
#include <QDateTime>
#include <QAudioDeviceInfo>

#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
#include <QStandardPaths>
#endif

#ifndef PARAMETRES_DOCK
#include "mainwindow.h"
#endif

#ifdef SUPPORT_DICTION
#include "qDicte.h"
#endif // SUPPORT_DICTION

#include "dialogactivation.h"
#include "parametres.h"
#include "style.h"
#include "API/Qt/Conversion.h"
#include "API/Qt/Utils.h"

#include "ui_parametres.h"

#include <cmath>
#include "API/perspective_api.h"

#ifdef DEBUG
#include <QDebug>
#endif // DEBUG

#include "version.h"
#define VERSION_ZETTA6 VERSION_Z6_STR

#define NOMBRE_SHADERS_PERSO 3

/********************** Variables par défaut: **********************/
const float ToleranceDessin = 0.2; /* Tolérance par défaut pour le lien entre les coordonnées du dessin */

const int ArrondiDessin = 4; /* Profondeur de l'arrondi pour les entités de dessin (en nombre de chiffres après la virgule). */

const int Taille_Scene2D = 1000000;

const int DivisionsCourbes = 28;

const int ActionDemarrage = RIEN_FAIRE_DEMARRAGE;

const Perspective3D::vues2D_t Projections = Perspective3D::vues2D_t::VUEFACE | Perspective3D::vues2D_t::VUECOTE | Perspective3D::vues2D_t::VUEHAUT;
const Perspective3D::infos3d_t Informations = Perspective3D::infos3d_t::INUL;

const int TailleTexte3D = 20;

const int OpaciteSolide = 100;

const int TypeInterface = 0;

const bool EclairageVersoFaces = true; /* Eclairage du verso des faces (ignore le sens des faces). */

const bool AfficheAccroche3D = false; /* Affichage des points d'accrochage sur les vues 3D. */

const bool PleinEcran = false;
const bool SavGeometrieFenetre = false;

const bool GenereModeleAuto = false; /* Génère le modèle dès l'ouverture du plan ? Possible de le modifier dans le fichier de config', mais inaccessible depuis l'interface. */
const bool RegenModele_MAJ = true;
const bool FilaireUniquement = false;
const Perspective3D::params_gen3d_t ParametresSolide3D = Perspective3D::params_gen3d_t::DIVISION_SURF |
                                                         Perspective3D::params_gen3d_t::CONTROLE_ENVELOPPE |
                                                         Perspective3D::params_gen3d_t::SUPPR_CHEVAUCHEMENT_LIGNES |
                                                         //Perspective3D::params_gen3d_t::SUPPR_CROISEMENT_LIGNES |
                                                         Perspective3D::params_gen3d_t::SUPPR_VOISINES_MEME_PLAN;

const unsigned int TypeAffichage3D = 0; /* Scène (voir l'enum MODES_AFFICHAGE dans Perspective_GL. */

const bool AutoriseControleMAJ = true;

const bool AutoriseAnimationScripts = true;
const unsigned int TempsReferenceAnimation = 300;
const unsigned int VitesseCurseurAnimation = 800;
const unsigned int VitesseClicAnimation = 800;

const bool IgnoreNonImprimableDXF = false;

const bool ActiveEchelleUniforme = false;
const unsigned int ValeurEchelleUniforme = 1000;

const unsigned int NbSommetsMaxSurfaces = 256;

const char *TypeExport3DDefaut = "STL";
const bool ExportFilaire_DXF = false;
//const bool ExportSolide_DXF = true;
//const bool ExportFaces_DXF = false;

const bool ExportCouleurCollada = false;
const bool CompressionZIPAMF = false;
const bool GroupeSolidesOBJ = false;

const int TypeExportSolideDXF = EXPORT_DXF_SOLIDE_MESH;

const bool RevolutionFixe = false;
const bool ExtrusionFixe = false;
const double HauteurExtrusion = 30;
const double AngleRevolution = 360.;

const char *TypeExport2DDefaut = "PNG";
const bool ModeVignetteExport2D = true;
const unsigned int TailleVignetteExport2D = 256;

const Perspective3D::normevues_t NormeVues = Perspective3D::normevues_t::NORME_VUES_ISO;

const char *R_Export3D = "";
const bool SepareSolidesSTL = false;

const char *NomDernierScript = "";

const int OngletDefaut = 0;
const int TypeConfigAffichage = 0;
const bool ActiveGLSL = true;
const int IdShader_Courant = NOMBRE_SHADERS_PERSO+1;
const int IdShader_CourantPost = NOMBRE_SHADERS_PERSO;
const int ContexteShader_Courant = 0;
const int TempoShadersPost = 25;

//const int EtatBarreOutils2D = 1; // Compactes, Horizontal, Verticale
//const int OrientationBarreOutils2D = 1;
//const QPoint PositionBarreOutils2D(20, 100);
//const QPoint PositionBarreOutils2D(200, 25);

const bool PremierLancement = true;
const bool Gen3DVuesAuto = true;
const bool AffichageOrthographique = false;
const bool AfficheZoneImpression3D = false;
const bool LissageAffichage3D = false;
const bool EclairageScene3D = true;
const bool MultiThreading = false;

const int TailleHistorique = 20;
const bool ExportConfig3DScripts = true; /* Lors de l'export de scripts, doit on inclure la configuration à destination de Perspective3D ? */

const QString CreditExport("Généré avec Zetta6");

enum { LANGUE_AUDIO_FR=0, LANGUE_AUDIO_EN };
const bool ActiveBruitagesAudio = false;
const bool ActiveSyntheseVocale = true;
int LangueAudio = LANGUE_AUDIO_FR; /* Pas const (la valeur sera changée en fonction de la langue du client) ! */
const int VolumeAudio = 75; // Entre 0 et 100

const bool AfficheProprietes3D = false;

/* Configuration de l'impression: */
const QPrinter::PaperSize TaillePapierImpression = QPrinter::A4;
const QPrinter::Orientation OrientationPapierImpression = QPrinter::Landscape;
const QPrinter::ColorMode CouleurImpression = QPrinter::Color;
const QPrinter::PrintRange RangImpression = QPrinter::AllPages;
const QPrinter::DuplexMode DuplexImpression = QPrinter::DuplexNone;
const QPrinter::PageOrder OrdreImpression = QPrinter::LastPageFirst;
const QPrinter::OutputFormat FormatImpression = QPrinter::NativeFormat;
const QPrinter::PaperSource SourcePapierImpression = QPrinter::Auto;
const char *NomImprimante = "";

/* Marge d'impression: */
const qreal MargeImpression_gauche = 3.5;
const qreal MargeImpression_droite = 3.5;
const qreal MargeImpression_haut = 3.5;
const qreal MargeImpression_bas = 3.5;

const QPoint PosFenParametres(100,50);

/* Couleurs modèle 3D. */
const unsigned int IdRAL3D = 9010; // Couleur des surfaces du modèle : RAL 9010 (Blanc Pur)
QRgb CouleurFond3D = qRgb(COULEUR_FOND_PGL_INT);
QRgb CouleurSommets3D = qRgb(COULEUR_POINTS);
//QRgb CouleurSegments3D = qRgb(20,20,20); // COULEUR_LIGNES
QRgb CouleurSegments3D = qRgb(74,74,74); // COULEUR_LIGNES
QRgb CouleurImprimante3D = qRgb(102, 102, 102);
QRgb CouleurReperesSommets3D = qRgb(COULEUR_SELECT_POINTS);
QRgb CouleurReperesSegments3D = qRgb(COULEUR_SELECT_LIGNES);
QRgb CouleurReperesFaces3D = qRgb(COULEUR_REP_SURFACES);

#ifdef SUPPORT_VISION2D
const bool Vision2D_AffichageMatrice = false; /* Affichage de la matrice Vision2D après un tracé manuel ? Possible de le modifier dans le fichier de configuration, mais inaccessible depuis l'interface. */
#endif // SUPPORT_VISION2D

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

struct DefShaderStatique
{
        const char *nom;
        const char *chemin_vshader;
        const char *chemin_fshader;
        const char *chemin_miniature;
};

/* Définition des shaders statiques: */
const int NombreVertexShadersStatique = 3;
const DefShaderStatique VertexShadersStatique[NombreVertexShadersStatique] = {
    { "Phong", ":/glsl/model/vshader_phong.glsl", ":/glsl/model/fshader_phong.glsl", ":/glsl/miniatures/model/shaders_phong.png" },
    { "Cel-shading", ":/glsl/model/vshader_cel.glsl", ":/glsl/model/fshader_cel.glsl", ":/glsl/miniatures/model/shaders_cel.png" },
    { "Gooch", ":/glsl/model/vshader_gooch.glsl", ":/glsl/model/fshader_gooch.glsl", ":/glsl/miniatures/model/shaders_gooch.png" }
};
const DefShaderStatique VertexShaderNul = { "Nul", "", "", ":/glsl/miniatures/model/shaders_nul.png" };

const int NombrePostShadersStatique = 5;
const DefShaderStatique PostShadersStatique[NombrePostShadersStatique] {
    { "Flou", ":/glsl/post/vshader_blur.glsl", ":/glsl/post/fshader_blur.glsl", ":/glsl/miniatures/post/shaders_post_blur.png" },
    { "Radial", ":/glsl/post/vshader_radial.glsl", ":/glsl/post/fshader_radial.glsl", ":/glsl/miniatures/post/shaders_post_radial.png" },
    { "Bruit", ":/glsl/post/vshader_bruit.glsl", ":/glsl/post/fshader_bruit.glsl", ":/glsl/miniatures/post/shaders_post_bruit.png" },
    { "Sobel", ":/glsl/post/vshader_sobel.glsl", ":/glsl/post/fshader_sobel.glsl", ":/glsl/miniatures/post/shaders_post_sobel.png" },
    { "Rayé", ":/glsl/post/vshader_rayure.glsl", ":/glsl/post/fshader_rayure.glsl", ":/glsl/miniatures/post/shaders_post_rayure.png" }
};
const DefShaderStatique PostShaderNul = { "Nul", "", "", ":/glsl/miniatures/post/shaders_post_nul.png" };

const char MiniatureShaderIndefini[] = ":/glsl/miniatures/shaders_indefini.png";

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

/* Nombre de divisions min et max en sous-lignes pour les ellipses */
#define DIVISION_MAX_ELLIPSES 64
#define DIVISION_MIN_ELLIPSES 4

template<typename T> void AnimCheckBoxMasque(QCheckBox *chk, const AnimationQt &animation, T val, T masque)
{
    if (!chk)
        return;
    if ( (chk->isChecked() && !(val&masque)) || (!chk->isChecked() && val&masque) )
    {
        animation.ClicWidget(chk);
    }
    chk->setChecked(val & masque);
}

inline void AlignementComboBox(QComboBox *cmb)
/* C'est pas beau, mais Qt ne gère par l'alignement centré du texte sur une QComboBox non éditable... */
{
    if (!cmb->isEditable())
    {
        cmb->setEditable(true);
        cmb->lineEdit()->setReadOnly(true);
    }

    cmb->lineEdit()->setAlignment(Qt::AlignCenter);
    for(int i = 0; i < cmb->count(); i++)
    {
        cmb->setItemData(i, Qt::AlignCenter, Qt::TextAlignmentRole);
    }
}

int ListePeripheriquesAudio_th::SelectionPeripheriqueDefaut()
/* Renvoi l'identifiant du périphérique audio par défaut.
    Attention, doit obligatoirement être appelé après le remplissage de la liste 'liste_perifs', donc après l'exécution de la fonction run(). */
{
#ifdef Q_OS_UNIX
    const QString default_qt = QAudioDeviceInfo::defaultOutputDevice().deviceName();

    int id_pulse = -1;
    int id_default = -1;
    int id_sys_default = -1;
    int id_defaut_qt = -1;

    for(int i=0; i<liste_perifs->size(); ++i)
    {
        const QString sx = liste_perifs->at(i).deviceName();

        if (sx.compare(QString("pulse"), Qt::CaseInsensitive) == 0)
        {
            id_pulse = i;
        }
        else if (sx.compare(QString("default"), Qt::CaseInsensitive) == 0)
        {
            id_default = i;
        }
        else if (sx.startsWith(QString("sysdefault:"), Qt::CaseInsensitive))
        {
            id_sys_default = i;
        }
        else if (sx.compare(default_qt, Qt::CaseInsensitive) == 0)
        {
            id_defaut_qt = i;
        }
    }

    int id_selection = -1;

    if (id_pulse != -1)
    {
        id_selection = id_pulse;
    }
    else if (id_sys_default != -1)
    {
        id_selection = id_sys_default;
    }
    else if (id_default != -1)
    {
        id_selection = id_default;
    }
    else if (id_defaut_qt != -1)
    {
        id_selection = id_defaut_qt;
    }

    if (id_selection != -1)
    {
#ifdef DEBUG
        qDebug() << "Sélection du périphérique audio : " << liste_perifs->at(id_selection).deviceName();
#endif // DEBUG
        return id_selection;
    }

    return -1; /* Erreur ?! */
#else
    const QString s0 = QAudioDeviceInfo::defaultOutputDevice().deviceName();
    for(int i=0; i<liste_perifs->size(); ++i)
    {
        const QString sx = liste_perifs->at(i).deviceName();
        if (sx.compare(s0, Qt::CaseInsensitive) == 0)
        {
            return i;
        }
    }
    return -1; /* Erreur ?! */
#endif // Q_OS_UNIX
}

void ListePeripheriquesAudio_th::run()
{
    etat_exec = true;
    if (cmb_liste_perifs)
    {
        cmb_liste_perifs->clear();
        int id_selection = -1;

//        QAudioDeviceInfo periph_defaut = QAudioDeviceInfo::defaultOutputDevice();

        liste_perifs->clear();
        *liste_perifs = QAudioDeviceInfo::availableDevices(QAudio::AudioOutput);
        const int n = liste_perifs->size();
        if (n)
        {
            for(int i=0; i<n; ++i)
            {
                const QString str = liste_perifs->at(i).deviceName();
                cmb_liste_perifs->addItem(str);

                if (!selection_perif.isEmpty())
                {
                    if (selection_perif.compare(str, Qt::CaseInsensitive) == 0)
                    {
                        id_selection = i;
                    }
                }
//                else if (id_selection == -1) /* Si aucun périphérique défini, on sélectionne le périphérique par défaut. */
//                {
//                    if (!periph_defaut.isNull() && periph_defaut.deviceName().compare(str, Qt::CaseInsensitive) == 0)
//                    {
//                        id_selection = i;
//                    }
//                }

                if (!etat_exec)
                {
                    break;
                }
            }
        }

        if (cmb_liste_perifs->count())
        {
            if (id_selection != -1)
            {
//                qDebug() << "ListePeripheriquesAudio_th :: Sélection : " << id_selection;
                cmb_liste_perifs->setCurrentIndex(id_selection);
            }
            else
            {
                id_selection = SelectionPeripheriqueDefaut();
                if (id_selection != -1)
                {
                    cmb_liste_perifs->setCurrentIndex(id_selection);
                }
                else
                {
                    cmb_liste_perifs->setCurrentIndex(0);
                }
            }
        }

        etat_exec = false;
    }
}

#ifdef PARAMETRES_DOCK
Parametres::Parametres(Documentation *doc, Perspective3D::i18n::lang_p3d_t langue, QWidget *parent) : QDockWidget(tr("Paramètres"), parent), ui(new Ui::Parametres),
    #ifdef SUPPORT_VISION2D
        conf_vision(),
    #endif // SUPPORT_VISION2D
    ignore_etat_onglets(false), etat_init(false), animation(anim), th_liste_peripheriques(nullptr), select_couleurs(0)
#else
Parametres::Parametres(const AnimationQt &anim, Documentation *doc, Perspective3D::i18n::lang_p3d_t langue, MainWindow *parent) : QDialog(0), ui(new Ui::Parametres),
    #ifdef SUPPORT_VISION2D
        conf_vision(),
    #endif // SUPPORT_VISION2D
    ignore_etat_onglets(false), etat_init(false), animation(anim), th_liste_peripheriques(nullptr), select_couleurs(false)
#endif // PARAMETRES_DOCK
{
#ifdef PARAMETRES_DOCK
    ui->setupUi(this->widget());
    setAllowedAreas(Qt::RightDockWidgetArea);
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
#else
    ui->setupUi(this);
    setWindowFlags(Qt::WindowStaysOnTopHint);
//    setWindowModality(Qt::WindowModal);
#endif // PARAMETRES_DOCK

    if (langue == Perspective3D::i18n::lang_p3d_t::P3D_LANG_FR)
    {
        LangueAudio = LANGUE_AUDIO_FR;
    }
    else if (langue == Perspective3D::i18n::lang_p3d_t::P3D_LANG_EN)
    {
        LangueAudio = LANGUE_AUDIO_EN;
    }
    else
    {
        LangueAudio = LANGUE_AUDIO_EN;
    }

//    ui->lbl_icone_p3d_activ->setPixmap(ConversionPImageQPixmap(Perspective3D::LogoPerspective3D(false)).scaledToHeight(28, Qt::SmoothTransformation));
//    ui->lbl_icone_p3d_activ->setPixmap(QPixmap(":/icones/cube_perspective.png").scaledToHeight(28, Qt::SmoothTransformation));
    ui->lbl_icone_p3d_activ->setPixmap(QPixmap(":/icones/exec.png").scaledToHeight(28, Qt::SmoothTransformation));

#ifdef SUPPORT_VISION2D
    ui->lbl_icone_v2d_activ->setPixmap(ConversionPImageQPixmap(Perspective3D::LogoVision2D(false)).scaledToHeight(28, Qt::SmoothTransformation));
    conf_vision.layout()->setSizeConstraint(QLayout::SetNoConstraint);
    conf_vision.layout()->setContentsMargins(0,0,0,0);
    ui->tabWidget->insertTab(int(PONGLET_VISION2D), &conf_vision, GenLogoVision2D(false), tr("Vision"));
    connect(&conf_vision, SIGNAL(SelectionDomaineParametres(int)), this, SLOT(SelectionDomaineParametresV2D(int)));
#endif // SUPPORT_VISION2D

    ui->lbl_logo_perspective3d->setPixmap(GenLogoPerspective3D(true));
    ui->tabWidget->setTabIcon(PONGLET_PRODUIT, GenLogoPerspective3D(false));

    documentation = doc;

    MaxArrondi = 6;
    MainApp = parent;

//    MaxArrondi = std::numeric_limits<pfloat>::digits10;
    ui->spb_arrondi->setMinimum(0);
    ui->spb_arrondi->setMaximum(MaxArrondi);

    change_shader = false;

    Settings = new QSettings(QString("Zetta6"), QString("Zetta6"));
    R_PositionParametres();

    ui->lbl_zetta6_description->setText(QString::fromLatin1(VER_PRODUCTNAME_STR " " VERSION_ZETTA6  " " VER_LEGALCOPYRIGHT_STR ". " VER_LEGALTRADEMARKS1_STR ".\n" VER_COMPANYDOMAIN_STR));

    QString txt_a_propos = tr("Plateforme") + " : " + libPerspective::Plateforme() + "\n";
    txt_a_propos += tr("Support du multithreading") + " : " + (libPerspective::SupportMultiThreading() ? tr("Oui") : tr("Non") ) + "\n\n";
    txt_a_propos += tr("Le présent logiciel est basé sur la bibliothèque Qt %1, droits d'auteurs 2008-2016 Digia Plc.\n\n    Les différents logiciels exploités appartiennent à leur auteur respectif:").arg(QT_VERSION_STR);
    ui->lbl_a_propos->setText(txt_a_propos);

    QString txt_a_propos_licences(libPerspective::APropos());
    txt_a_propos_licences += QString("\n- ") + tr("Qt") + " " QT_VERSION_STR ", " + "2016 The Qt Company Ltd";
#ifdef SUPPORT_DICTION
    txt_a_propos_licences += QString("\n- ") + tr("SVOX Pico") + ", " + "Copyright (C) 2008-2009 SVOX AG";
#endif // SUPPORT_DICTION
    ui->lbl_licence_p3d->setText(txt_a_propos_licences);

    for(unsigned int i=0; i<TailleCleActivation; ++i)
    {
        Licence[i] = 0;
    }

    liste_licences = new InterfaceTexte(tr("Liste des licences"), ":/licences/Licences.txt", true, this);
    detail_licence_cecill_c = (langue == Perspective3D::i18n::lang_p3d_t::P3D_LANG_FR) ?
                                  (new InterfaceTexte(QString("CeCILL-C"), ":/licences/Licence_CeCILL-C_V1-fr.txt", true, this)) :
                                  (new InterfaceTexte(QString("CeCILL-C"), ":/licences/Licence_CeCILL-C_V1-en.txt", true, this));


    detail_licence_p3d = new InterfaceTexte(QString(libPerspective::Nom()), libPerspective::TexteLicence(), false, this);
    InitLicence_P3D = InitLicence_V2D = false;
    LicenceValide_P3D = LicenceValide_V2D = false;

    if (documentation)
    {
        ForgeBoutonAide(ui->hl_modele_filaire, "FAQ.html#modelefilaire");
        ForgeBoutonAide(ui->hl_multithreading, "FAQ.html#multithreading");
        ForgeBoutonAide(ui->hl_suppr_lignes_orphelines, "FAQ.html#lignesorphelines");
        ForgeBoutonAide(ui->hl_suppr_lignes_croisement_plan, "FAQ.html#lignescroisementplan");
        ForgeBoutonAide(ui->hl_suppr_segments_alignes, "FAQ.html#alignementlignes");
        ForgeBoutonAide(ui->hl_suppr_chevauchement_lignes, "FAQ.html#chevauchementlignes");
        ForgeBoutonAide(ui->hl_suppr_croisement_lignes, "FAQ.html#croisementlignes");
        ForgeBoutonAide(ui->hl_division_surfaces, "FAQ.html#divisionsurfaces");
        ForgeBoutonAide(ui->hl_controle_coherence, "FAQ.html#interieursolides");
        ForgeBoutonAide(ui->hl_conservation_ents, "FAQ.html#conservationents");
        ForgeBoutonAide(ui->hl_ids_parametrage, "parametrage.html#ids_params_3d");
    }

    ui->tabWidget->setUsesScrollButtons(false);
    ui->tabWidget->tabBar()->setExpanding(true);
    ui->tabWidget->tabBar()->setDrawBase(false);

    ui->tabWidget->setFocusPolicy(Qt::NoFocus);
    ui->tabWidget->tabBar()->setFocusPolicy(Qt::NoFocus);

    ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Ok"));
    ui->buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Annuler"));
    ui->buttonBox->button(QDialogButtonBox::Apply)->setText(tr("Appliquer"));
    ui->buttonBox->button(QDialogButtonBox::Reset)->setText(tr("Réinitialiser"));
    ui->buttonBox->button(QDialogButtonBox::Help)->setText(tr("Aide"));

    ui->buttonBox->button(QDialogButtonBox::Ok)->setIcon(QIcon(":/icones/valide.png"));
    ui->buttonBox->button(QDialogButtonBox::Apply)->setIcon(QIcon(":/icones/applique_params.png"));
    ui->buttonBox->button(QDialogButtonBox::Cancel)->setIcon(QIcon(":/icones/invalide.png"));
    ui->buttonBox->button(QDialogButtonBox::Reset)->setIcon(QIcon(":/icones/reinit_params.png"));
    ui->buttonBox->button(QDialogButtonBox::Help)->setIcon(QIcon(":/icones/aide.png"));

    QHBoxLayout *layout_select_couleurs = new QHBoxLayout(ui->wselectcouleur);
    layout_select_couleurs->addWidget(&select_couleurs);
    ui->lw_couleurs_3d->setMaximumHeight(select_couleurs.HauteurWidget());
    connect(&select_couleurs, SIGNAL(NouvelleCouleur(QRgb)), this, SLOT(NouvelleCouleur3D(QRgb)));
    ui->lw_couleurs_3d->setCurrentRow(0);

#ifndef SUPPORT_DICTION
    ui->chk_autoriser_bruitages_audio->setEnabled(false);
    ui->chk_synthese_vocale->setEnabled(false);
    ui->cmb_langue_synthese_vocale->setEnabled(false);
    ui->vslide_volume_audio->setEnabled(false);
    ui->pled_test_synthese_vocale->setEnabled(false);
    ui->pb_test_audio->setEnabled(false);
    ui->lbl_langue_synthese->setEnabled(false);
    ui->lbl_volume_audio->setEnabled(false);
#endif // SUPPORT_DICTION

//    AlignementComboBox(ui->cmb_norme_vues);

    PeupleCmb_RAL(*(ui->cmb_RAL));
    InitVals();
}

Parametres::~Parametres()
{
    ignore_etat_onglets = true; /* Qt appelle on_tabWidget_currentChanged() lors de la destruction... */
    //Settings->sync(); // Au cas où...
    delete liste_licences;
    delete detail_licence_cecill_c;
    delete detail_licence_p3d;
    delete Settings;

    if (th_liste_peripheriques->enCours() || th_liste_peripheriques->isRunning())
    {
        th_liste_peripheriques->stop();
        th_liste_peripheriques->wait(1000);
    }
    delete th_liste_peripheriques;
    th_liste_peripheriques = 0;

    if (documentation)
    {
        for(unsigned int i=0; i<BoutonsAide.size(); ++i)
        {
            delete BoutonsAide[i];
        }
    }

    delete ui;
}

void Parametres::ForceOnglet(unsigned int id, bool force_animation)
{
    if (animation.Anime())
    {
        animation.ClicTabBar(ui->tabWidget, id, force_animation);
    }
    ui->tabWidget->setCurrentIndex(id);
}

void Parametres::ForceSousOngletAffichage(int id, bool force_animation)
{
    if (ui->tabWidget->currentIndex() != PONGLET_AFFICHAGE3D)
        ForceOnglet(PONGLET_AFFICHAGE3D);
    if (animation.Anime())
    {
        animation.ClicWidget(ui->cmb_type_config_affichage, id, force_animation);
    }
    ui->cmb_type_config_affichage->setCurrentIndex(id);
}

void Parametres::AnimeLicence()
{
    show();
    ForceOnglet(PONGLET_PRODUIT, true);
    animation.ClicWidget(ui->pb_entree_cle, -1, true);
    if (documentation)
    {
        documentation->OuvrePage("parametrage.html#licence");
    }
    on_pb_entree_cle_clicked();
}

void Parametres::InitVals() /* Initialise les paramètres d'après la configuration. */
{
    etat_init = false;
    /* Recupère la liste des périphériques audio (dans un thread pour pas bloquer l'interface). */

    th_liste_peripheriques = new ListePeripheriquesAudio_th(ui->cmb_peripheriques_audio, &liste_peripheriques_audio, R_NomPeripheriqueAudio(false));
    th_liste_peripheriques->start();

    ui->dspb_tolerance->setValue(R_ToleranceDessin());
    ui->spb_arrondi->setValue(R_ArrondiEntites());
    ui->spb_zonedess->setValue(R_ZoneDessin());

    Perspective3D::vues2D_t projections = R_Projections();
    Perspective3D::infos3d_t informations = R_Informations();
    Perspective3D::params_gen3d_t params3d = R_ParametresGen3D();

    ui->chk_autorise_contole_maj->setChecked(R_AutoriseControleMAJ());

    ui->chk_autorise_anim_scripts->setChecked(R_AutoriseAnimationScripts());
    ui->widget_conf_animation->setEnabled(ui->chk_autorise_anim_scripts->isChecked());

    ui->dspb_animation_temps_reference->setValue((R_TempsReferenceAnimation()) / 1000.);
    ui->spb_animation_vitesse_souris->setValue(R_VitesseCurseurAnimation());
    ui->dspb_animation_duree_clic->setValue(((float) R_VitesseClicAnimation()) / 1000.);

    ui->chk_proj_face->setChecked(projections & Perspective3D::vues2D_t::VUEFACE);
    ui->chk_proj_cote->setChecked(projections & Perspective3D::vues2D_t::VUECOTE);
    ui->chk_proj_haut->setChecked(projections & Perspective3D::vues2D_t::VUEHAUT);
    ui->chk_projections_vues->setChecked((ui->chk_proj_face->isChecked() || ui->chk_proj_cote->isChecked() || ui->chk_proj_haut->isChecked()));

    ui->chk_coords->setChecked(informations & Perspective3D::infos3d_t::ICOORDSPOINTS);
    ui->chk_rep_sommets->setChecked(informations & Perspective3D::infos3d_t::IDPOINTS);
    ui->chk_rep_courbes->setChecked(informations & Perspective3D::infos3d_t::IDCOURBES);
    ui->chk_rep_arretes->setChecked(informations & Perspective3D::infos3d_t::IDLIGNES);
    ui->chk_aff_norm->setChecked(informations & Perspective3D::infos3d_t::IVECTEURNORM);
    ui->chkl_rep_surfaces->setChecked(informations & Perspective3D::infos3d_t::IDSURFACES);
    ui->spb_tailletexte3d->setValue(R_TailleTexte3D());
    ui->spb_divisionsellipses->setValue(R_DivisionsCourbes());
    ui->spb_opacite_solide->setValue(R_OpaciteSolide());
    ui->chk_eclairage_verso_faces->setChecked(R_EclairageDeuxFaces());
    ui->chk_affiche_accroche->setChecked(R_AfficheAccrochage3D());

    ui->cmb_RAL->setCurrentIndex(R_IndexRAL());
    ui->cmb_type_affichage->setCurrentIndex(R_TypeAffichage3D());

    ui->chk_plein_ecran->setChecked(R_PleinEcran());
    ui->chk_sav_geometrie->setChecked(R_SavGeometrieFenetre());
    ui->chk_ignore_ents_non_imprimables->setChecked(R_IgnoreNonImprimableDXF());
    ui->cmb_demarrage->setCurrentIndex(R_ActionDemarrage());
    ui->chk_regen_maj->setChecked(R_RegenModeles_MAJ());
    ui->chk_uniquement_filaire->setChecked(R_FilaireUniquement());
    ui->chk_multithreading->setChecked(R_MultiThreading());
    ui->chk_export_config_gen3d_scripts->setChecked(R_ExportConfig3DScripts());

    ui->cmb_type_interface->setCurrentIndex(R_TypeInterface());
    on_cmb_type_interface_currentIndexChanged(ui->cmb_type_interface->currentIndex());

    ui->chk_division_surfaces->setChecked(params3d & Perspective3D::params_gen3d_t::DIVISION_SURF);
    ui->chk_controle_coherence->setChecked(params3d & Perspective3D::params_gen3d_t::CONTROLE_ENVELOPPE);
    ui->chk_suppr_lignes_orphelines->setChecked(params3d & Perspective3D::params_gen3d_t::SUPPR_LIGNES_ORPHELINES);
    ui->chk_suppr_lignes_croisement_plan->setChecked(params3d & Perspective3D::params_gen3d_t::SUPPR_CROISEMENT_LIGNES_PLAN);
    ui->chk_suppr_chevauchement_lignes->setChecked(params3d & Perspective3D::params_gen3d_t::SUPPR_CHEVAUCHEMENT_LIGNES);
    ui->chk_suppr_croisement_lignes->setChecked(params3d & Perspective3D::params_gen3d_t::SUPPR_CROISEMENT_LIGNES);
    ui->chk_suppr_segments_alignes->setChecked(params3d & Perspective3D::params_gen3d_t::SUPPR_ALIGNEMENT_LIGNES);
    ui->chk_suppr_surfaces_meme_plan->setChecked(params3d & Perspective3D::params_gen3d_t::SUPPR_VOISINES_MEME_PLAN);
    ui->chk_suppr_surfaces_col_lignes->setChecked(params3d & Perspective3D::params_gen3d_t::SUPPR_COLLISION_LIGNES_SURFACES);
    ui->chk_conservation_ents->setChecked(params3d & Perspective3D::params_gen3d_t::CONSERVATION_SUPPRS);
    MiseAJourIdsParams3D();

    select_couleurs.RestaureCouleur();

    ui->spb_nb_sommets_surfaces->setValue(R_TailleSurfaces());

    int id_exp = ui->cmb_typeexport->findText(R_TypeExport3DDefaut());
    if (id_exp != -1) ui->cmb_typeexport->setCurrentIndex(id_exp);

    /* Si dans la configuration on est sur le premier id (DXF), le widget des options d'export ne sera pas affiché car l'index n'a pas changé,
     * on force donc l'appel à l'initialisation: */
    if (ui->cmb_typeexport->currentIndex() == 0)
    {
        on_cmb_typeexport_currentIndexChanged(R_TypeExport3DDefaut());
    }

    ui->chk_exportfilaire->setChecked(R_Export3DFilaireDXF());
    ui->cb_type_exportDXF->setCurrentIndex(R_TypeExportSolideDXF());

    ui->chk_couleur_export_collada->setChecked(R_ExportCouleurCollada());
    ui->chk_groupes_export_obj->setChecked(R_GroupeSolidesOBJ());
    ui->chk_compression_zip_amf->setChecked(R_CompressionZIPAMF());

    ui->led_chemin_export->setText(R_CheminExport());

    ui->chk_fixe_extrusion->setChecked(R_ExtrusionFixe());
    if (ui->chk_fixe_extrusion->isChecked())
    {
        ui->dspb_ht_extrusion->setVisible(true);
        ui->dspb_ht_extrusion->setValue(R_HauteurExtrusion());
    }
    else
    {
        ui->dspb_ht_extrusion->setVisible(false);
    }

    ui->chk_fixe_revolution->setChecked(R_RevolutionFixe());
    if (ui->chk_fixe_revolution->isChecked())
    {
        ui->dspb_angle_revolution->setVisible(R_RevolutionFixe());
        ui->dspb_angle_revolution->setValue(R_AngleRevolution());
    }
    else
    {
        ui->dspb_angle_revolution->setVisible(false);
    }

    ui->chk_echelle_uniforme->setChecked(R_ActiveEchelleUniforme());
    ui->spb_echelle_uniforme->setValue(R_ValeurEchelleUniforme());
    ui->spb_echelle_uniforme->setEnabled(ui->chk_echelle_uniforme->isChecked());

    ui->cmb_norme_vues->setCurrentIndex(PENUM_CAST_INT(R_NormeVues2D())-1);
    ui->chk_genmod_vuesauto->setChecked(R_Gen3DVuesAuto());

    ui->chk_eclairage_scene->setChecked(R_EclairageScene());

    ui->chk_mode_ortho->setChecked(R_AffichageOrthographique());
    ui->chk_lissage3d->setChecked(R_LissageAffichage3D());
    ui->chk_zone_impression3d->setChecked(R_AfficheZoneImpression3D());
    ui->chk_export_stl_sep->setChecked(R_SepareSolidesSTL());
    ui->spb_imprimante_x->setValue(R_TailleZoneImpression3D_X());
    ui->spb_imprimante_y->setValue(R_TailleZoneImpression3D_Y());
    ui->spb_imprimante_z->setValue(R_TailleZoneImpression3D_Z());

    ui->spb_imprimante_x->setEnabled(ui->chk_zone_impression3d->isChecked());
    ui->spb_imprimante_y->setEnabled(ui->chk_zone_impression3d->isChecked());
    ui->spb_imprimante_z->setEnabled(ui->chk_zone_impression3d->isChecked());

    ui->chk_mode_vignette->setChecked(R_Export2DVignette());
    ui->spb_taille_vignette->setValue(R_TailleVignetteExport2D());

    ui->led_credit_export->setText(R_CreditExport());

    ui->chk_autoriser_bruitages_audio->setChecked(R_ActiveBruitagesAudio());
    ui->chk_synthese_vocale->setChecked(R_ActiveSyntheseVocale());
    ui->cmb_langue_synthese_vocale->setCurrentIndex(R_LangueAudio());
    on_cmb_langue_synthese_vocale_activated(R_LangueAudio());
    ui->vslide_volume_audio->setValue(R_VolumeAudio());

    on_chk_mode_vignette_stateChanged(ui->chk_mode_vignette->isChecked() ? Qt::Checked : Qt::Unchecked);

    on_cmb_norme_vues_currentIndexChanged(ui->cmb_norme_vues->currentIndex());

    R_Onglet_Parametres();
    R_TypeConfigAffichage_Parametres();
    ui->sw_affichage3d->setCurrentIndex(ui->cmb_type_config_affichage->currentIndex());
    ui->chk_glsl->setChecked(R_ActiveGLSL());
    ui->widget_glsl->setEnabled(ui->chk_glsl->isChecked());
    ui->cmb_contexte_glsl->setCurrentIndex(R_ContexteShader_Courant());
    PeupleCmbContexteGLSL(ui->cmb_contexte_glsl->currentIndex());
    ui->spb_chrono_shader_post->setValue(R_TempoShadersPost());
    ui->lw_liste_progs_glsl->setCurrentRow(R_IdShader_Courant(ui->cmb_contexte_glsl->currentIndex()));

    ui->pb_enregistre_shader->setEnabled(ui->lw_liste_progs_glsl->currentRow() < NOMBRE_SHADERS_PERSO);

#ifdef SUPPORT_VISION2D
    InitParametresVision();
#endif // SUPPORT_VISION2D

    ControleLicenceValide();

//    ui->chk_exportsolide->setChecked(R_ExportSolide());

    etat_init = true;
}

#ifdef SUPPORT_VISION2D
int Parametres::R_DernierDomaineVision2D() const
{
    return Settings->value("Vision2D/DernierDomaineV2D", QVariant(ConfigVision::DOMAINE_IMPORT)).toInt();
}
// SUPPORT_VISION2D...
void Parametres::defDernierDomaineVision2D()
{
    Settings->setValue("Vision2D/DernierDomaineV2D", QVariant(conf_vision.Domaine()));
}
// SUPPORT_VISION2D...
int Parametres::R_DernierParamV2D() const
{
    return Settings->value("Vision2D/DernierParamV2D", QVariant(0)).toInt();
}
// SUPPORT_VISION2D...
void Parametres::defDernierParamV2D()
{
    if (conf_vision.ValideDomaine())
    {
        Settings->setValue("Vision2D/DernierParamV2D", QVariant(conf_vision.PageCourante()));
    }
}
// SUPPORT_VISION2D...
QRgb Parametres::R_CouleurTraceVision2D() const
{
    const int domaine_configuration = ConfigVision::DOMAINE_MAIN_LEVEE;
    const Perspective3D::ParametresVision &parametres_defaut = conf_vision.ParametresDefauts(domaine_configuration);

    Settings->beginGroup(QString("Vision2D_") + QString::number(domaine_configuration));
    QRgb v = Settings->value("CouleurTrace2D", QVariant(qRgbP(parametres_defaut.CouleurTrace))).toUInt();
    Settings->endGroup();
    return v;
}
// SUPPORT_VISION2D...
double Parametres::R_TailleGrilleTraceVision2D() const
{
    const int domaine_configuration = ConfigVision::DOMAINE_MAIN_LEVEE;
    const Perspective3D::ParametresVision &parametres_defaut = conf_vision.ParametresDefauts(domaine_configuration);

    Settings->beginGroup(QString("Vision2D_") + QString::number(domaine_configuration));
    double v = Settings->value("TailleGrille", QVariant(parametres_defaut.TailleGrille)).toDouble();
    Settings->endGroup();
    return v;
}
// SUPPORT_VISION2D...
bool Parametres::AssigneParametresVision2D(Perspective3D::ParametresVision &parametres, int domaine_configuration)
{
    if (conf_vision.ValideDomaine(domaine_configuration))
    {
        const Perspective3D::ParametresVision &parametres_defaut = conf_vision.ParametresDefauts(domaine_configuration);
        Settings->beginGroup(QString("Vision2D_") + QString::number(domaine_configuration));
        parametres.SeuilActivation = Settings->value("SeuilActivation", QVariant(parametres_defaut.SeuilActivation)).toInt();
        parametres.ContourSegments = Settings->value("ContourSegments", QVariant(parametres_defaut.ContourSegments)).toBool();
        parametres.EpsilonCoords = Settings->value("EpsilonCoords", QVariant(parametres_defaut.EpsilonCoords)).toDouble();
        parametres.ToleranceCoords1 = Settings->value("ToleranceCoords1", QVariant(parametres_defaut.ToleranceCoords1)).toDouble();
        parametres.ToleranceCoords2 = Settings->value("ToleranceCoords2", QVariant(parametres_defaut.ToleranceCoords2)).toDouble();
        parametres.ToleranceJointures = Settings->value("ToleranceJointures", QVariant(parametres_defaut.ToleranceJointures)).toDouble();
        parametres.ToleranceCourbure = Settings->value("ToleranceCourbure", QVariant(parametres_defaut.ToleranceCourbure)).toDouble();
        parametres.DeltaCourbesMin = Settings->value("DeltaCourbesMin", QVariant(parametres_defaut.DeltaCourbesMin)).toDouble();
        parametres.DeltaCourbesMax = Settings->value("DeltaCourbesMax", QVariant(parametres_defaut.DeltaCourbesMax)).toDouble();
        parametres.DeltaAnglesCourbesMin = Settings->value("DeltaAnglesCourbesMin", QVariant(parametres_defaut.DeltaAnglesCourbesMin)).toDouble();
        parametres.DeltaAnglesCourbesMax = Settings->value("DeltaAnglesCourbesMax", QVariant(parametres_defaut.DeltaAnglesCourbesMax)).toDouble();
        parametres.TailleGrille = Settings->value("TailleGrille", QVariant(parametres_defaut.TailleGrille)).toDouble();
        parametres.ToleranceJointuresCentreCourbes = Settings->value("ToleranceJointuresCentreCourbes", QVariant(parametres_defaut.ToleranceJointuresCentreCourbes)).toDouble();
        parametres.ToleranceAngles = Settings->value("ToleranceAngles", QVariant(parametres_defaut.ToleranceAngles)).toDouble();
        parametres.ToleranceNorms = Settings->value("ToleranceNorms", QVariant(parametres_defaut.ToleranceNorms)).toDouble();

        const QRgb couleur_trace = Settings->value("CouleurTrace2D", QVariant(qRgbP(parametres_defaut.CouleurTrace))).toUInt();
        parametres.CouleurTrace = qPpixel(couleur_trace);
        Settings->endGroup();

        parametres.Licence = R_CleeActivation();
        parametres.SalageLicence = R_SalageActivation();

        return true;
    }
    return false;
}
// SUPPORT_VISION2D...
void Parametres::InitParametresVision(int domaine)
/* Charge les paramètres spécifiques à Vision2D. */
{
    const int id_domaine_params = (domaine == ConfigVision::DOMAINE_NUL) ? R_DernierDomaineVision2D() : domaine;
//    int id_dernier_param = R_DernierParamV2D();

    Perspective3D::ParametresVision params;
    if (AssigneParametresVision2D(params, id_domaine_params))
    {
        conf_vision.defParametres(params, id_domaine_params, -1);
//        conf_vision.ChangePageCourante(id_dernier_param);
    }
}
// SUPPORT_VISION2D...
bool Parametres::ReinitParametresVision(int domaine, int id_page_parametres)
{
//    const int domaine = R_DernierDomaineVision2D();
    if (conf_vision.ValideDomaine(domaine))
    {
        conf_vision.defParametres(ConfigVision::ParametresDefauts(domaine), domaine, id_page_parametres);
        return true;
    }
    return false;
}
// SUPPORT_VISION2D...
void Parametres::ValideParametresVision()
/* Enregistre les paramètres spécifiques à Vision2D sur le domaine actuellement en cours d'utilisation. */
{
    if (conf_vision.ValideDomaine())
    {
        defDernierDomaineVision2D();
        defDernierParamV2D();

        const Perspective3D::ParametresVision &parametres = conf_vision.Parametres();
        Settings->beginGroup(QString("Vision2D_") + QString::number(conf_vision.Domaine()));

        Settings->setValue("SeuilActivation", parametres.SeuilActivation);
        Settings->setValue("ContourSegments", parametres.ContourSegments);
        Settings->setValue("CouleurTrace2D", qRgbP(parametres.CouleurTrace));
        Settings->setValue("EpsilonCoords", parametres.EpsilonCoords);
        Settings->setValue("ToleranceCoords1", parametres.ToleranceCoords1);
        Settings->setValue("ToleranceCoords2", parametres.ToleranceCoords2);
        Settings->setValue("ToleranceAngles", parametres.ToleranceAngles);
        Settings->setValue("ToleranceJointures", parametres.ToleranceJointures);
        Settings->setValue("ToleranceCourbure", parametres.ToleranceCourbure);
        Settings->setValue("ToleranceJointuresCentreCourbes", parametres.ToleranceJointuresCentreCourbes);
        Settings->setValue("DeltaCourbesMin", parametres.DeltaCourbesMin);
        Settings->setValue("DeltaCourbesMax", parametres.DeltaCourbesMax);
        Settings->setValue("ToleranceNorms", parametres.ToleranceNorms);
        Settings->setValue("DeltaAnglesCourbesMin", parametres.DeltaAnglesCourbesMin);
        Settings->setValue("DeltaAnglesCourbesMax", parametres.DeltaAnglesCourbesMax);
        Settings->setValue("TailleGrille", parametres.TailleGrille);
        Settings->endGroup();
    }
}
// SUPPORT_VISION2D...
void Parametres::SelectionDomaineParametresV2D(int id)
{
    InitParametresVision(1+id);
}
// SUPPORT_VISION2D...
bool Parametres::R_AffichageMatriceVision() const
{
    return Settings->value("Vision2D/AffichageMatrice", QVariant(Vision2D_AffichageMatrice)).toBool();
}
// SUPPORT_VISION2D...
void Parametres::defAffichageMatriceVision(bool etat)
/* Définit si l'on doit afficher la matrice après génération du tracé manuel avec Vision2D. */
{
    Settings->setValue("Vision2D/AffichageMatrice", etat);
}
#endif // SUPPORT_VISION2D

void Parametres::ValideVals() /* Enregistre les paramètres */
{
    defOnglet_Parametres();
    defAutoriseControleMAJ();
    defTypeConfigAffichage_Parametres();
    defActiveGLSL();
    defContexteShader_Courant();
    defIdShader_Courant(ui->cmb_contexte_glsl->currentIndex());
    defVertexShader_Perso();
    defPixelShader_Perso();
    defAnimationScript();
    defTempsReferenceAnimation();
    defVitesseCurseurAnimation();
    defVitesseClicAnimation();
    defToleranceDessin(ui->dspb_tolerance->value());
    defArrondiEntites(ui->spb_arrondi->value());
    defZoneDessin(ui->spb_zonedess->value());
    defCheminExport(ui->led_chemin_export->text());
    defProjections();
    defInformations();
    defTailleTexte3D();
    defOpaciteSolide();
    defEclairageDeuxFaces();
    defAfficheAccrochage3D();
    defPleinEcran();
    defSavGeometrieFenetre();
    defIgnoreNonImprimableDXF();
    defActionDemarrage();
    defRegenModele_MAJ();
    defFilaireUniquement();
    defMultiThreading();
    defExportConfig3DScripts();
    defParametresGen3D();
    defTailleSurfaces();
    defDivisionsCourbes();
    defIdentRAL3D();
    defTypeAffichage3D();
    defTypeExport3DDefaut();
    defExport3DFilaireDXF();
    defTypeExportSolideDXF();
    defExportCouleurCollada();
    defGroupeSolidesOBJ();
    defCompressionZIPAMF();
    defExtrusionFixe();
    defRevolutionFixe();
    defNormeVues2D();
    defGen3DVuesAuto();
    defAffichageOrthographique();
    defLissageAffichage3D();
    defZoneParamsImprimable3D();
    DefSepareSolidesSTL();
    defEclairageScene();
    defTypeInterface();
    defCreditExport();

    defActiveBruitagesAudio();
    defActiveSyntheseVocale();
    defLangueAudio();
    defVolumeAudio();
    defNomPeripheriqueAudio();

    on_lw_couleurs_3d_currentRowChanged(ui->lw_couleurs_3d->currentRow()); /* Mettra à jour la couleur par défaut (pour la restauration) */

    defTempoShaderPost();

    defActiveEchelleUniforme();
    defValeurEchelleUniforme();

    defExport2DVignette();
    defTailleVignetteExport2D();

    /* Cas particuliers (non configurables depuis l'interface), on garde les valeurs du fichier de configuration. Si elle n'existent pas, elle sont créées. */
    defGenereModeleAuto(R_GenereModeleAuto());
    defTailleHistorique(R_TailleHistorique());
#ifdef SUPPORT_VISION2D
    defAffichageMatriceVision(R_AffichageMatriceVision());
#endif
    /* ***************************************************** */

#ifdef SUPPORT_VISION2D
    ValideParametresVision(); /* Uniquement sur le domaine de paramètres en cours d'utilisation. */
#endif

    Settings->sync();

    bool nouveaux_shaders = change_shader || ((ui->tabWidget->currentIndex() == PONGLET_AFFICHAGE3D) && (ui->cmb_type_config_affichage->currentIndex() == 1));
    change_shader = false;
    emit ValideParametres(nouveaux_shaders);
}

void Parametres::ReinitVals(bool general) /* Réinitialisation des paramètres par défaut. */
{
    unsigned int onglet = ui->tabWidget->currentIndex();
    if (onglet == PONGLET_ERGONOMIE || general)
    {
        ui->chk_autorise_anim_scripts->setChecked(AutoriseAnimationScripts);
        ui->widget_conf_animation->setEnabled(ui->chk_autorise_anim_scripts->isChecked());

        ui->dspb_animation_temps_reference->setValue(((float) TempsReferenceAnimation) /  1000.);
        ui->spb_animation_vitesse_souris->setValue(VitesseCurseurAnimation);
        ui->dspb_animation_duree_clic->setValue(((float) VitesseClicAnimation) / 1000.);
        ui->chk_plein_ecran->setChecked(PleinEcran);
        ui->chk_sav_geometrie->setChecked(SavGeometrieFenetre);
        ui->cmb_demarrage->setCurrentIndex(ActionDemarrage);
        ui->chk_regen_maj->setChecked(RegenModele_MAJ);

        ui->cmb_type_interface->setCurrentIndex(TypeInterface);
        on_cmb_type_interface_currentIndexChanged(ui->cmb_type_interface->currentIndex());

        ui->chk_genmod_vuesauto->setChecked(Gen3DVuesAuto);

        ui->chk_autoriser_bruitages_audio->setChecked(ActiveBruitagesAudio);
        ui->chk_synthese_vocale->setChecked(ActiveSyntheseVocale);
        ui->cmb_langue_synthese_vocale->setCurrentIndex(LangueAudio);
        on_cmb_langue_synthese_vocale_activated(LangueAudio);
        ui->vslide_volume_audio->setValue(VolumeAudio);
    }
    if (onglet == PONGLET_DESSIN || general)
    {
        ui->dspb_tolerance->setValue(ToleranceDessin);
        ui->spb_arrondi->setValue(ArrondiDessin);
        ui->spb_zonedess->setValue(Taille_Scene2D);
        ui->chk_ignore_ents_non_imprimables->setChecked(IgnoreNonImprimableDXF);
        ui->spb_divisionsellipses->setValue(DivisionsCourbes);

        ui->chk_echelle_uniforme->setChecked(ActiveEchelleUniforme);
        ui->spb_echelle_uniforme->setValue(ValeurEchelleUniforme);
        ui->spb_echelle_uniforme->setEnabled(ui->chk_echelle_uniforme->isChecked());

        ui->cmb_norme_vues->setCurrentIndex(PENUM_CAST_INT(NormeVues)-1);

        ui->chk_fixe_extrusion->setChecked(ExtrusionFixe);
        ui->dspb_ht_extrusion->setVisible(ExtrusionFixe);
        ui->chk_fixe_revolution->setChecked(RevolutionFixe);
        ui->dspb_angle_revolution->setVisible(RevolutionFixe);
    }
#ifdef SUPPORT_VISION2D
    if (onglet == PONGLET_VISION2D || general)
    {
        if (!conf_vision.ValideDomaine() || general)
        {
            ReinitParametresVision(ConfigVision::DOMAINE_NUL, -1);
        }
        else
        {
            ReinitParametresVision(conf_vision.Domaine(), conf_vision.PageCourante());
        }
    }
#endif // SUPPORT_VISION2D
    if (onglet == PONGLET_SOLIDE3D || general)
    {
        ui->chk_uniquement_filaire->setChecked(FilaireUniquement);
        ui->chk_multithreading->setChecked(MultiThreading);
        ui->spb_nb_sommets_surfaces->setValue(NbSommetsMaxSurfaces);

        ui->chk_division_surfaces->setChecked(ParametresSolide3D & Perspective3D::params_gen3d_t::DIVISION_SURF);
        ui->chk_controle_coherence->setChecked(ParametresSolide3D & Perspective3D::params_gen3d_t::CONTROLE_ENVELOPPE);
        ui->chk_suppr_lignes_orphelines->setChecked(ParametresSolide3D & Perspective3D::params_gen3d_t::SUPPR_LIGNES_ORPHELINES);
        ui->chk_suppr_lignes_croisement_plan->setChecked(ParametresSolide3D & Perspective3D::params_gen3d_t::SUPPR_CROISEMENT_LIGNES_PLAN);
        ui->chk_suppr_chevauchement_lignes->setChecked(ParametresSolide3D & Perspective3D::params_gen3d_t::SUPPR_CHEVAUCHEMENT_LIGNES);
        ui->chk_suppr_croisement_lignes->setChecked(ParametresSolide3D & Perspective3D::params_gen3d_t::SUPPR_CROISEMENT_LIGNES);
        ui->chk_suppr_segments_alignes->setChecked(ParametresSolide3D & Perspective3D::params_gen3d_t::SUPPR_ALIGNEMENT_LIGNES);
        ui->chk_suppr_surfaces_meme_plan->setChecked(ParametresSolide3D & Perspective3D::params_gen3d_t::SUPPR_VOISINES_MEME_PLAN);
        ui->chk_suppr_surfaces_col_lignes->setChecked(ParametresSolide3D & Perspective3D::params_gen3d_t::SUPPR_COLLISION_LIGNES_SURFACES);
        ui->chk_conservation_ents->setChecked(ParametresSolide3D & Perspective3D::params_gen3d_t::CONSERVATION_SUPPRS);

        MiseAJourIdsParams3D();
    }
    if (onglet == PONGLET_AFFICHAGE3D || general)
    {
        const int index_affichage_3d = ui->cmb_type_config_affichage->currentIndex();
        if (index_affichage_3d == 0 || general)
        {
            ui->chk_proj_face->setChecked(Projections & Perspective3D::vues2D_t::VUEFACE);
            ui->chk_proj_cote->setChecked(Projections & Perspective3D::vues2D_t::VUECOTE);
            ui->chk_proj_haut->setChecked(Projections & Perspective3D::vues2D_t::VUEHAUT);
            ui->chk_projections_vues->setChecked((ui->chk_proj_face->isChecked() || ui->chk_proj_cote->isChecked() || ui->chk_proj_haut->isChecked()));

            ui->chk_coords->setChecked(Informations & Perspective3D::infos3d_t::ICOORDSPOINTS);
            ui->chk_rep_sommets->setChecked(Informations & Perspective3D::infos3d_t::IDPOINTS);
            ui->chk_rep_courbes->setChecked(Informations & Perspective3D::infos3d_t::IDCOURBES);
            ui->chk_rep_arretes->setChecked(Informations & Perspective3D::infos3d_t::IDLIGNES);
            ui->chk_aff_norm->setChecked(Informations & Perspective3D::infos3d_t::IVECTEURNORM);
            ui->chkl_rep_surfaces->setChecked(Informations & Perspective3D::infos3d_t::IDSURFACES);

            ui->spb_tailletexte3d->setValue(TailleTexte3D);
            ui->spb_opacite_solide->setValue(OpaciteSolide);
            ui->chk_eclairage_verso_faces->setChecked(EclairageVersoFaces);
            ui->chk_affiche_accroche->setChecked(AfficheAccroche3D);

            ui->cmb_RAL->setCurrentIndex(Perspective3D::RAL::RechercheIndex(IdRAL3D));
            ui->cmb_type_affichage->setCurrentIndex(TypeAffichage3D);

            ui->chk_mode_ortho->setChecked(AffichageOrthographique);
            ui->chk_lissage3d->setChecked(LissageAffichage3D);
            ui->chk_zone_impression3d->setChecked(AfficheZoneImpression3D);
            ui->chk_eclairage_scene->setChecked(EclairageScene3D);

            if (general)
            {
                ui->chk_glsl->setChecked(ActiveGLSL);
                ui->cmb_contexte_glsl->setCurrentIndex(ContexteShader_Courant);
                PeupleCmbContexteGLSL(ContexteShader_Courant);
                ui->spb_chrono_shader_post->setValue(TempoShadersPost);
                ui->lw_liste_progs_glsl->setCurrentRow(IdShader_Courant);

                ui->lw_couleurs_3d->setCurrentRow(0);
                defCouleurFond3D(CouleurFond3D);
                select_couleurs.defCouleur(CouleurFond3D);
                defCouleurSommets3D(CouleurSommets3D);
                defCouleurSegments3D(CouleurSegments3D);
                defCouleurImprimante3D(CouleurImprimante3D);
                defCouleurReperesSommets3D(CouleurReperesSommets3D);
                defCouleurReperesSegments3D(CouleurReperesSegments3D);
                defCouleurReperesFaces3D(CouleurReperesFaces3D);
            }
        }
        else if (index_affichage_3d == 1)
        {
//            ui->cmb_type_config_affichage->setCurrentIndex(TypeConfigAffichage);

            ui->chk_glsl->setChecked(ActiveGLSL);
            const unsigned int contexte = ui->cmb_contexte_glsl->currentIndex();
            PeupleCmbContexteGLSL(contexte);
            ui->spb_chrono_shader_post->setValue(TempoShadersPost);

            if (contexte == CONTEXTE_GLSL_MODELE)
            {
                ui->lw_liste_progs_glsl->setCurrentRow(IdShader_Courant);
            }
            else if (contexte == CONTEXTE_GLSL_POST)
            {
                ui->lw_liste_progs_glsl->setCurrentRow(IdShader_CourantPost);
            }
            change_shader = true;
        }
        else if (index_affichage_3d == 2)
        {
            ui->lw_couleurs_3d->setCurrentRow(0);
            defCouleurFond3D(CouleurFond3D);
            select_couleurs.defCouleur(CouleurFond3D);
            defCouleurSommets3D(CouleurSommets3D);
            defCouleurSegments3D(CouleurSegments3D);
            defCouleurImprimante3D(CouleurImprimante3D);
            defCouleurReperesSommets3D(CouleurReperesSommets3D);
            defCouleurReperesSegments3D(CouleurReperesSegments3D);
            defCouleurReperesFaces3D(CouleurReperesFaces3D);

        }
    }
    if (onglet == PONGLET_EXPORT || general)
    {
        int id_exp = ui->cmb_typeexport->findText(TypeExport3DDefaut);
        if (id_exp != -1) ui->cmb_typeexport->setCurrentIndex(id_exp);

        ui->chk_export_config_gen3d_scripts->setChecked(ExportConfig3DScripts);

        ui->chk_exportfilaire->setChecked(ExportFilaire_DXF);
        ui->cb_type_exportDXF->setCurrentIndex(TypeExportSolideDXF);

        ui->chk_couleur_export_collada->setChecked(ExportCouleurCollada);
        ui->chk_groupes_export_obj->setChecked(GroupeSolidesOBJ);
        ui->chk_compression_zip_amf->setChecked(CompressionZIPAMF);
        ui->led_credit_export->setText(CreditExport);

        ui->chk_export_stl_sep->setChecked(SepareSolidesSTL);

        ui->chk_mode_vignette->setChecked(ModeVignetteExport2D);
        on_chk_mode_vignette_stateChanged(ui->chk_mode_vignette->isChecked() ? Qt::Checked : Qt::Unchecked);

        ui->spb_taille_vignette->setValue(TailleVignetteExport2D);
    }
    if (onglet == PONGLET_PRODUIT || general)
    {
    }
}

void Parametres::showEvent(QShowEvent *ev)
{
    InitVals();
    R_PositionParametres();

    if (ui->tabWidget->currentIndex() == PONGLET_PRODUIT)
    {
        GenCodeBarreCle();
    }

    ev->accept();
}

void Parametres::moveEvent(QMoveEvent *ev)
{
    defPositionParametres();
    Settings->sync();
    ev->accept();
}

bool Parametres::FermetureDocumentation()
/* Fermeture automatique de la doc si elle a trait au paramétrage... */
{
    if (documentation)
    {
        if (documentation->isVisible())
        {
            if (documentation->PageCourante().contains("parametrage.html"))
            {
                documentation->close();
                return true;
            }
        }
    }
    return false;
}

void Parametres::closeEvent(QCloseEvent *ev)
{
    FermetureDocumentation();
    emit FermetureParametres();
    ev->accept();
}

void Parametres::on_buttonBox_clicked(QAbstractButton *button)
{
    if (ui->buttonBox->buttonRole(button) == QDialogButtonBox::ResetRole) /* On demande la réinitialisation des paramètres. */
    {
        ReinitVals(false);
    }
    else if (ui->buttonBox->buttonRole(button) == QDialogButtonBox::AcceptRole)
    {
        MainApp->ArretAnimationsAutomate(); /* Si la validation est manuelle, on doit arrêter l'automate ! */
        ValideVals();
        FermetureDocumentation();
    }
    else if (ui->buttonBox->buttonRole(button) == QDialogButtonBox::ApplyRole)
    {
        MainApp->ArretAnimationsAutomate(); /* Si la validation est manuelle, on doit arrêter l'automate ! */
        ValideVals();
    }
    else if (ui->buttonBox->buttonRole(button) == QDialogButtonBox::RejectRole)
    {
        InitVals(); /* Annulation, restaure les paramètres précédents et ferme la fenêtre. */
        emit FermetureParametres();
        FermetureDocumentation();
    }
    Settings->sync();
}

void Parametres::defAnnule_PremierLancement()
{
    Settings->setValue("EtatApplication/PremierLancement", false);
}

bool Parametres::R_PremierLancement() const
{
    return Settings->value("EtatApplication/PremierLancement", QVariant(PremierLancement)).toBool();
}

void Parametres::defVersion()
{
    Settings->setValue("libPerspective3D/VersionP3D", QString::number(libPerspective::VersionInt()));
    Settings->setValue("VersionZetta6", VERSION_ZETTA6);
}

bool Parametres::ControleVersions() const
/* Contrôle la version de Perspective3D courante par rapport à celle de la configuration. */
{
    const int v1 = Settings->value("libPerspective3D/VersionP3D", QVariant(0)).toInt();
    QString v2 = Settings->value("VersionZetta6", QVariant("")).toString();

    if (!v1 || v2.isEmpty()) /* On ignore si aucune version n'a été définie pour le moment. */
    {
        return true;
    }
    return (v1 == libPerspective::VersionInt()) && (v2 == VERSION_ZETTA6);
}

void Parametres::defPositionParametres()
{
    Settings->setValue("EtatApplication/PosFenParametres", window()->pos());
}

void Parametres::R_PositionParametres()
{
    move(Settings->value("EtatApplication/PosFenParametres", QVariant(PosFenParametres)).toPoint());
}

void Parametres::defOnglet_Parametres()
{
    Settings->setValue("EtatApplication/Onglet_Parametres", ui->tabWidget->currentIndex());
}

void Parametres::R_Onglet_Parametres() const
{
    ui->tabWidget->setCurrentIndex(Settings->value("EtatApplication/Onglet_Parametres", QVariant(OngletDefaut)).toInt());
}

void Parametres::defTypeConfigAffichage_Parametres()
{
    Settings->setValue("EtatApplication/TypeConfigAffichage", ui->cmb_type_config_affichage->currentIndex());
}

void Parametres::R_TypeConfigAffichage_Parametres() const
{
    ui->cmb_type_config_affichage->setCurrentIndex(Settings->value("EtatApplication/TypeConfigAffichage", QVariant(TypeConfigAffichage)).toInt());
}

bool Parametres::R_AutoriseExport3DAutomate() const
{
#ifdef DEBUG
    return true;
#else
    return false;
#endif
}

void Parametres::defActiveGLSL()
{
    Settings->setValue("GL/ActiveGLSL", ui->chk_glsl->isChecked());
}

bool Parametres::R_ActiveGLSL() const
{
    return Settings->value("GL/ActiveGLSL", QVariant(ActiveGLSL)).toBool();
}

bool Parametres::R_ActiveGLSLPost() const
{
//    return false;
    return R_ActiveGLSL();
}

void Parametres::defIdShader_Courant(unsigned int contexte)
{
    if (contexte == CONTEXTE_GLSL_MODELE)
    {
        Settings->setValue("GL/IdShader_Courant", ui->lw_liste_progs_glsl->currentRow());
    }
    else if (contexte == CONTEXTE_GLSL_POST)
    {
        Settings->setValue("GL/IdShader_CourantPost", ui->lw_liste_progs_glsl->currentRow());
    }
}

int Parametres::R_IdShader_Courant(unsigned int contexte) const
{
    if (contexte == CONTEXTE_GLSL_MODELE)
    {
        return Settings->value("GL/IdShader_Courant", QVariant(IdShader_Courant)).toInt();
    }
    else if (contexte == CONTEXTE_GLSL_POST)
    {
        return Settings->value("GL/IdShader_CourantPost", QVariant(IdShader_CourantPost)).toInt();
    }
    return 0;
}

void Parametres::defContexteShader_Courant()
{
    Settings->setValue("GL/ContexteShader_Courant", ui->cmb_contexte_glsl->currentIndex());
}

int Parametres::R_ContexteShader_Courant() const
{
    return Settings->value("GL/ContexteShader_Courant", QVariant(ContexteShader_Courant)).toInt();
}

QByteArray Parametres::R_VertexShader_Courant(unsigned int contexte) const
{
    return VertexShader_Id(R_IdShader_Courant(contexte), contexte);
}

QByteArray Parametres::R_PixelShader_Courant(unsigned int contexte) const
{
    return PixelShader_Id(R_IdShader_Courant(contexte), contexte);
}

void Parametres::defVertexShader_Perso()
{
    const unsigned int contexte = ui->cmb_contexte_glsl->currentIndex();
    if (contexte == CONTEXTE_GLSL_MODELE)
    {
        if (ui->lw_liste_progs_glsl->currentRow() < NOMBRE_SHADERS_PERSO) /* Uniquement si l'on est dans un shader personnalisable. */
        {
            Settings->setValue(QString("GL/VertexShader_Perso") + QString::number(ui->lw_liste_progs_glsl->currentRow()), ui->pted_glsl_vertex->toPlainText().toUtf8());
        }
    }
    else if (contexte == CONTEXTE_GLSL_POST)
    {
        if (ui->lw_liste_progs_glsl->currentRow() < NOMBRE_SHADERS_PERSO) /* Uniquement si l'on est dans un shader personnalisable. */
        {
            Settings->setValue(QString("GL/VertexShaderPost_Perso") + QString::number(ui->lw_liste_progs_glsl->currentRow()), ui->pted_glsl_vertex->toPlainText().toUtf8());
        }
    }
}

void Parametres::defPixelShader_Perso()
{
    const unsigned int contexte = ui->cmb_contexte_glsl->currentIndex();

    if (contexte == CONTEXTE_GLSL_MODELE)
    {
        if (ui->lw_liste_progs_glsl->currentRow() < NOMBRE_SHADERS_PERSO) /* Uniquement si l'on est dans un shader personnalisable. */
        {
            Settings->setValue(QString("GL/PixelShader_Perso") + QString::number(ui->lw_liste_progs_glsl->currentRow()), ui->pted_glsl_frag->toPlainText().toUtf8());
        }
    }
    else if (contexte == CONTEXTE_GLSL_POST)
    {
        if (ui->lw_liste_progs_glsl->currentRow() < NOMBRE_SHADERS_PERSO) /* Uniquement si l'on est dans un shader personnalisable. */
        {
            Settings->setValue(QString("GL/PixelShaderPost_Perso") + QString::number(ui->lw_liste_progs_glsl->currentRow()), ui->pted_glsl_frag->toPlainText().toUtf8());
        }
    }
}

QByteArray Parametres::R_VertexShader_Perso(int id, unsigned int contexte) const
{
    if (contexte == CONTEXTE_GLSL_MODELE)
        return Settings->value(QString("GL/VertexShader_Perso") + QString::number(id), QVariant()).toByteArray();
    else if (contexte == CONTEXTE_GLSL_POST)
        return Settings->value(QString("GL/VertexShaderPost_Perso") + QString::number(id), QVariant()).toByteArray();
    return QByteArray();
}

QByteArray Parametres::R_PixelShader_Perso(int id, unsigned int contexte) const
{
    if (contexte == CONTEXTE_GLSL_MODELE)
        return Settings->value(QString("GL/PixelShader_Perso") + QString::number(id), QVariant()).toByteArray();
    else if (contexte == CONTEXTE_GLSL_POST)
        return Settings->value(QString("GL/PixelShaderPost_Perso") + QString::number(id), QVariant()).toByteArray();
    return QByteArray();
}

QByteArray Parametres::VertexShader_Id(int id, unsigned int contexte) const
{
    if (contexte == CONTEXTE_GLSL_MODELE)
    {
        if (id < NOMBRE_SHADERS_PERSO) /* Personnalisé */
        {
            return R_VertexShader_Perso(id, contexte);
        }
        else if (id == NOMBRE_SHADERS_PERSO) /* Nul */
        {
            return QByteArray(VertexShaderNul.chemin_vshader);
        }
        else
        {
            const int id_temp = id - (NOMBRE_SHADERS_PERSO+1);
            if (id_temp >= 0 && id_temp < NombreVertexShadersStatique)
            {
                return LectureFichier(VertexShadersStatique[id_temp].chemin_vshader);
            }
        }
    }
    else if (contexte == CONTEXTE_GLSL_POST)
    {
        if (id < NOMBRE_SHADERS_PERSO) /* Personnalisé */
        {
            return R_VertexShader_Perso(id, contexte);
        }
        else if (id == NOMBRE_SHADERS_PERSO) /* Nul (par défaut) */
        {
            return QByteArray(PostShaderNul.chemin_vshader);
        }
        else
        {
            const int id_temp = id - (NOMBRE_SHADERS_PERSO+1);
            if (id_temp >= 0 && id_temp < NombrePostShadersStatique)
            {
                return LectureFichier(PostShadersStatique[id_temp].chemin_vshader);
            }
        }
    }
    return QByteArray();
}

QByteArray Parametres::PixelShader_Id(int id, unsigned int contexte) const
{
    if (contexte == CONTEXTE_GLSL_MODELE)
    {
        if (id < NOMBRE_SHADERS_PERSO) /* Personnalisé */
        {
            return R_PixelShader_Perso(id, contexte);
        }
        else if (id == NOMBRE_SHADERS_PERSO) /* Nul */
        {
            return QByteArray(VertexShaderNul.chemin_fshader);
        }
        else
        {
            const int id_temp = id - (NOMBRE_SHADERS_PERSO+1);
            if (id_temp >= 0 && id_temp < NombreVertexShadersStatique)
            {
                return LectureFichier(VertexShadersStatique[id_temp].chemin_fshader);
            }
        }
    }
    else if (contexte == CONTEXTE_GLSL_POST)
    {
        if (id < NOMBRE_SHADERS_PERSO) /* Personnalisé */
        {
            return R_PixelShader_Perso(id, contexte);
        }
        else if (id == NOMBRE_SHADERS_PERSO) /* Nul (par défaut) */
        {
            return QByteArray(PostShaderNul.chemin_fshader);
        }
        else
        {
            const int id_temp = id - (NOMBRE_SHADERS_PERSO+1);
            if (id_temp >= 0 && id_temp < NombrePostShadersStatique)
            {
                return LectureFichier(PostShadersStatique[id_temp].chemin_fshader);
            }
        }
    }
    return QByteArray();
}

void Parametres::defTypeExport3DDefaut()
{
    Settings->setValue("Export3D/TypeExport3DDefaut", ui->cmb_typeexport->currentText());
}

QString Parametres::R_TypeExport3DDefaut() const
{
    return Settings->value("Export3D/TypeExport3DDefaut", QVariant(TypeExport3DDefaut)).toString();
}

void Parametres::defExport3DFilaireDXF()
{
    Settings->setValue("Export3D/ExportFilaire_DXF", ui->chk_exportfilaire->isChecked());
}

bool Parametres::R_Export3DFilaireDXF() const
{
    return Settings->value("Export3D/ExportFilaire_DXF", QVariant(ExportFilaire_DXF)).toBool();
}

void Parametres::defTypeExportSolideDXF()
{
    Settings->setValue("Export3D/TypeExportSolideDXF", ui->cb_type_exportDXF->currentIndex());
}

int Parametres::R_TypeExportSolideDXF() const
{
    return (Settings->value("Export3D/TypeExportSolideDXF", QVariant(TypeExportSolideDXF)).toInt());
}

void Parametres::defTypeExport2DDefaut(const char *nom)
{
    Settings->setValue("Export3D/TypeExport2DDefaut", nom);
}

QString Parametres::R_TypeExport2DDefaut() const
{
    return Settings->value("Export3D/TypeExport2DDefaut", QVariant(TypeExport2DDefaut)).toString();
}

Perspective3D::params_export_dxf_t Parametres::R_ParametresExportDXF() const
{
    Perspective3D::params_export_dxf_t params = Perspective3D::params_export_dxf_t::EXPORT_DXF_NUL;

    if (R_Export3DFilaireDXF())
    {
        params |= Perspective3D::params_export_dxf_t::EXPORT_DXF_FILAIRE;
    }

    int type_export = R_TypeExportSolideDXF();
    if (type_export == EXPORT_DXF_SOLIDE_NUL)
    {
        params |= Perspective3D::params_export_dxf_t::EXPORT_DXF_SOLIDE_NUL;
    }
    else if (type_export == EXPORT_DXF_SOLIDE_MESH)
    {
        params |= Perspective3D::params_export_dxf_t::EXPORT_DXF_SOLIDE_MESH;
    }
    else if (type_export == EXPORT_DXF_SOLIDE_MESH_GROUPE)
    {
        params |= Perspective3D::params_export_dxf_t::EXPORT_DXF_SOLIDE_MESH;
        params |= Perspective3D::params_export_dxf_t::EXPORT_DXF_SOLIDE_MESH_GROUPE;
    }
    else if (type_export == EXPORT_DXF_SOLIDE_FACES)
    {
        params |= Perspective3D::params_export_dxf_t::EXPORT_DXF_SOLIDE_FACES;
    }

    return params;
}

void Parametres::defExportCouleurCollada()
{
    Settings->setValue("Export3D/ExportCouleurCollada", ui->chk_couleur_export_collada->isChecked());
}

bool Parametres::R_ExportCouleurCollada() const
{
    return Settings->value("Export3D/ExportCouleurCollada", QVariant(ExportCouleurCollada)).toBool();
}

void Parametres::defGroupeSolidesOBJ()
{
    Settings->setValue("Export3D/GroupeSolidesOBJ", ui->chk_groupes_export_obj->isChecked());
}

bool Parametres::R_GroupeSolidesOBJ() const
{
    return Settings->value("Export3D/GroupeSolidesOBJ", QVariant(GroupeSolidesOBJ)).toBool();
}

void Parametres::defCompressionZIPAMF()
{
    Settings->setValue("Export3D/CompressionZIPAMF", ui->chk_compression_zip_amf->isChecked());
}

bool Parametres::R_CompressionZIPAMF() const
{
    return Settings->value("Export3D/CompressionZIPAMF", QVariant(CompressionZIPAMF)).toBool();
}

void Parametres::defIdentRAL3D(int force_valeur)
{
    if (force_valeur != -1)
    {
        int id = Perspective3D::RAL::RechercheIndex(force_valeur);
        if (animation.Anime())
        {
            if (((int) Perspective3D::RAL::Index(ui->cmb_RAL->currentIndex()).id) != force_valeur)
                animation.ClicWidget(ui->cmb_RAL);
        }
        ui->cmb_RAL->setCurrentIndex(id);
        Settings->setValue("Perspective3D/IdRAL3D", force_valeur);
    }
    else
    {
        const Perspective3D::PCouleur_RAL &ral = Perspective3D::RAL::Index(ui->cmb_RAL->currentIndex());
        Settings->setValue("Perspective3D/IdRAL3D", ral.id);
    }
}

unsigned int Parametres::R_IdentRAL3D() const
{
    return Settings->value("Perspective3D/IdRAL3D", QVariant(IdRAL3D)).toUInt();
}

unsigned int Parametres::R_IndexRAL() const
{
    unsigned int ident = R_IdentRAL3D();
    return Perspective3D::RAL::RechercheIndex(ident);
}

void Parametres::defCouleurFond3D(QRgb couleur)
{
//    qDebug() << "   defCouleurFond3D : " << qRed(couleur) << ":"  << qGreen(couleur) << ":" << qBlue(couleur);

    Settings->setValue("CouleursAffichage3D/CouleurFond3D", static_cast<unsigned int>(couleur));
}

QRgb Parametres::R_CouleurFond3D() const
{
    return Settings->value("CouleursAffichage3D/CouleurFond3D", QVariant(CouleurFond3D)).toUInt();
}

QRgb Parametres::R_CouleurFond2D() const
{
//    return qRgb(COULEUR_FOND_PGL_INT);
    return R_CouleurFond3D();
}

void Parametres::defCouleurSommets3D(QRgb couleur)
{
    Settings->setValue("CouleursAffichage3D/CouleurSommets3D", couleur);
}

QRgb Parametres::R_CouleurSommets3D() const
{
    return Settings->value("CouleursAffichage3D/CouleurSommets3D", QVariant(CouleurSommets3D)).toUInt();
}

void Parametres::defCouleurSegments3D(QRgb couleur)
{
    Settings->setValue("CouleursAffichage3D/CouleurSegments3D", couleur);
}

QRgb Parametres::R_CouleurSegments3D() const
{
    return Settings->value("CouleursAffichage3D/CouleurSegments3D", QVariant(CouleurSegments3D)).toUInt();
}

void Parametres::defCouleurImprimante3D(QRgb couleur)
{
    Settings->setValue("CouleursAffichage3D/CouleurImprimante3D", couleur);
}

QRgb Parametres::R_CouleurImprimante3D() const
{
    return Settings->value("CouleursAffichage3D/CouleurImprimante3D", QVariant(CouleurImprimante3D)).toUInt();
}

void Parametres::defCouleurReperesSommets3D(QRgb couleur)
{
    Settings->setValue("CouleursAffichage3D/CouleurReperesSommets3D", couleur);
}

QRgb Parametres::R_CouleurReperesSommets3D() const
{
    return Settings->value("CouleursAffichage3D/CouleurReperesSommets3D", QVariant(CouleurReperesSommets3D)).toUInt();
}

void Parametres::defCouleurReperesSegments3D(QRgb couleur)
{
    Settings->setValue("CouleursAffichage3D/CouleurReperesSegments3D", couleur);
}

QRgb Parametres::R_CouleurReperesSegments3D() const
{
    return Settings->value("CouleursAffichage3D/CouleurReperesSegments3D", QVariant(CouleurReperesSegments3D)).toUInt();
}

void Parametres::defCouleurReperesFaces3D(QRgb couleur)
{
    Settings->setValue("CouleursAffichage3D/CouleurReperesFaces3D", couleur);
}

QRgb Parametres::R_CouleurReperesFaces3D() const
{
    return Settings->value("CouleursAffichage3D/CouleurReperesFaces3D", QVariant(CouleurReperesFaces3D)).toUInt();
}

void Parametres::defTypeAffichage3D()
{
    Settings->setValue("Affichage3D/TypeAffichage3D", ui->cmb_type_affichage->currentIndex());
}

unsigned int Parametres::R_TypeAffichage3D()
{
    return Settings->value("Affichage3D/TypeAffichage3D", QVariant(TypeAffichage3D)).toUInt();
}

void Parametres::defPleinEcran(int force_valeur)
{
    if (force_valeur != -1)
    {
        ui->chk_plein_ecran->setChecked(force_valeur!=0);
    }

    Settings->setValue("Ergonomie/PleinEcran", ui->chk_plein_ecran->isChecked());
}

bool Parametres::R_PleinEcran() const
{
    return Settings->value("Ergonomie/PleinEcran", QVariant(PleinEcran)).toBool();
}

void Parametres::defSavGeometrieFenetre()
{
    Settings->setValue("Ergonomie/SavGeometrieFenetre", ui->chk_sav_geometrie->isChecked());
}

bool Parametres::R_SavGeometrieFenetre()
{
    return Settings->value("Ergonomie/SavGeometrieFenetre", QVariant(SavGeometrieFenetre)).toBool();
}

void Parametres::defGeometrie(const QString &nom, const QWidget *w)
{
    const QRect &geometrie = w->geometry();
    Settings->setValue(QString("EtatApplication/Geometrie_") + nom + QString("_x"), geometrie.x());
    Settings->setValue(QString("EtatApplication/Geometrie_") + nom + QString("_y"), geometrie.y());
    Settings->setValue(QString("EtatApplication/Geometrie_") + nom + QString("_lg"), geometrie.width());
    Settings->setValue(QString("EtatApplication/Geometrie_") + nom + QString("_ht"), geometrie.height());
}

bool Parametres::R_Geometrie(const QString &nom, QWidget *w)
{
    int x = Settings->value(QString("EtatApplication/Geometrie_") + nom + QString("_x"), QVariant(-1)).toInt();
    int y = Settings->value(QString("EtatApplication/Geometrie_") + nom + QString("_y"), QVariant(-1)).toInt();
    if ((x != -1) || (y != -1))
    {
        return false;
    }

    int lg = Settings->value(QString("EtatApplication/Geometrie_") + nom + QString("_lg"), QVariant(-1)).toInt();
    int ht = Settings->value(QString("EtatApplication/Geometrie_") + nom + QString("_ht"), QVariant(-1)).toInt();
    if ((lg == -1) || (ht == -1))
    {
        return false;
    }

    w->setGeometry(x, y, lg, ht);
    return true;
}

void Parametres::defIgnoreNonImprimableDXF()
{
    Settings->setValue("Export3D/IgnoreNonImprimableDXF", ui->chk_ignore_ents_non_imprimables->isChecked());
}

bool Parametres::R_IgnoreNonImprimableDXF() const
{
    return Settings->value("Export3D/IgnoreNonImprimableDXF", QVariant(IgnoreNonImprimableDXF)).toBool();
}

void Parametres::defHauteurExtrusion(double ht)
{
    Settings->setValue("Ergonomie/HauteurExtrusion", ht);
}

double Parametres::R_HauteurExtrusion() const
{
    return Settings->value("Ergonomie/HauteurExtrusion", QVariant(HauteurExtrusion)).toDouble();
}

void Parametres::defExtrusionFixe()
{
    Settings->setValue("Ergonomie/ExtrusionFixe", ui->chk_fixe_extrusion->isChecked());
    if (ui->chk_fixe_extrusion->isChecked())
    {
        defHauteurExtrusion(ui->dspb_ht_extrusion->value());
    }
}

double Parametres::R_ExtrusionFixe() const
{
    return Settings->value("Ergonomie/ExtrusionFixe", QVariant(ExtrusionFixe)).toBool();
}

void Parametres::defAngleRevolution(double angle)
{
    Settings->setValue("Ergonomie/AngleRevolution", angle);
}

double Parametres::R_AngleRevolution() const
{
    return Settings->value("Ergonomie/AngleRevolution", QVariant(AngleRevolution)).toDouble();
}

void Parametres::defRevolutionFixe()
{
    Settings->setValue("Ergonomie/RevolutionFixe", ui->chk_fixe_revolution->isChecked());
    if (ui->chk_fixe_revolution->isChecked())
    {
        defAngleRevolution(ui->dspb_angle_revolution->value());
    }
}

double Parametres::R_RevolutionFixe() const
{
    return Settings->value("Ergonomie/RevolutionFixe", QVariant(RevolutionFixe)).toBool();
}

void Parametres::defCreditExport()
{
    Settings->setValue("Export3D/CreditExport", ui->led_credit_export->text());
}

QString Parametres::R_CreditExport(bool ajout_date) const
{
    QString r = tr(Settings->value("Export3D/CreditExport", QVariant(CreditExport)).toString().toStdString().data());

    if (!r.isEmpty() && ajout_date)
    {
        QString date_c = QDateTime::currentDateTime().toString(tr("dd/MM/yyyy"));
        r += " - " + date_c;
    }
    return r;
}

void Parametres::defActionDemarrage()
{
    Settings->setValue("Ergonomie/ActionDemarrage", ui->cmb_demarrage->currentIndex());
}

int Parametres::R_ActionDemarrage() const
{
    return Settings->value("Ergonomie/ActionDemarrage", QVariant(ActionDemarrage)).toInt();
}

void Parametres::defGenereModeleAuto(bool etat)
/* Doit on générer le dernier solide dès l'ouverture d'un plan ?
    Cas particulier, l'option n'est pas dans l'interface à cause d'éventuels effets indésirables chez les utilisateurs.
*/
{
    Settings->setValue("Ergonomie/GenereModeleAuto", etat);
}

bool Parametres::R_GenereModeleAuto() const
/* Doit on générer le dernier solide à l'ouverture d'un plan ? */
{
    return Settings->value("Ergonomie/GenereModeleAuto", QVariant(GenereModeleAuto)).toBool();
}

void Parametres::defGen3DVuesAuto()
{
    Settings->setValue("Ergonomie/Gen3DVuesAuto", ui->chk_genmod_vuesauto->isChecked());
}

bool Parametres::R_Gen3DVuesAuto() const
/* Génération du solide après définition des vues ? */
{
    return Settings->value("Ergonomie/Gen3DVuesAuto", QVariant(Gen3DVuesAuto)).toBool();
}

void Parametres::defRegenModele_MAJ()
{
    Settings->setValue("Ergonomie/Regen_MAJ", ui->chk_regen_maj->isChecked());
}

bool Parametres::R_RegenModeles_MAJ() const
/* Re-génération du dernier solide après mise à jour du plan ? */
{
    return Settings->value("Ergonomie/Regen_MAJ", QVariant(RegenModele_MAJ)).toBool();
}

int Parametres::R_ZoneDessin() const
{
    return Settings->value("Ergonomie/Taille_Scene2D", QVariant(Taille_Scene2D)).toInt();
}

void Parametres::defZoneDessin(int i)
{
    Settings->setValue("Ergonomie/Taille_Scene2D", i);
}

void Parametres::defFichier_Precedent(const QString &d)
{
    if (!d.isEmpty())
    {
        defHistorique(d, TYPE_FICHIER); // A chaque fois qu'on assigne un nouveau fichier ouvert, on l'ajoute dans l'historique.
    }
    Settings->setValue("Historique/Fichier_Precedent", d);
}

QString Parametres::R_Fichier_Precedent() const
{
    return Settings->value("Historique/Fichier_Precedent", QVariant(QString())).toString();
}

void Parametres::defTailleHistorique(int n)
{
    Settings->setValue("Historique/TailleHistorique", n);
}

int Parametres::R_TailleHistorique() const
{
    return Settings->value("Historique/TailleHistorique", QVariant(TailleHistorique)).toInt();
}

QStringList Parametres::R_Historique(int type) const
{
    if (type == TYPE_FICHIER)
    {
        return Settings->value("Historique/Historique_F", QVariant(R_Fichier_Precedent())).toStringList(); // Fichiers
    }
    if (type == TYPE_DOSSIER)
    {
        return Settings->value("Historique/Historique_D", QVariant(R_DernierDossier_Ouverture())).toStringList(); // Dossiers
    }
    if (type == TYPE_DOSSIER_ENREG)
    {
        return Settings->value("Historique/Historique_Sv", QVariant(R_DernierDossier_Ouverture())).toStringList(); // Dossiers (enregistrement)
    }
    return QStringList("");
}

void Parametres::defHistorique(const QString &a, int type)
/* Ajout dans l'historique */
{
    if (a.isEmpty())
    {
        return;
    }

    const bool inverse_historique = (type == TYPE_DOSSIER);
    QStringList historique = R_Historique(type);

    if (!historique.contains(a, Qt::CaseSensitive)) /* Nouvelle entrée dans l'historique */
    {
        if (historique.size() == 1)
        {
            if (historique.back().isEmpty())
            {
                historique.back() = a;
            }
            else
            {
                if (inverse_historique)
                {
                    historique.push_back(a);
                }
                else
                {
                    historique.push_front(a);
                }
            }
        }
        else
        {
            if (inverse_historique)
            {
                historique.push_back(a);
            }
            else
            {
                historique.push_front(a);
            }
        }
    }
    else // On vient d'ouvrir une entrée déjà présente dans l'historique, on la fait repasser en tête...
    {
        int id_suppr = -1;
        for(int i=0; i<historique.size(); ++i)
        {
            if (historique[i] == a)
            {
                id_suppr = i;
                break;
            }
        }
        if (id_suppr != -1)
        {
            if (inverse_historique)
            {
                historique.removeAt(id_suppr);
                historique.push_back(a);
            }
            else
            {
                historique.removeAt(id_suppr);
                historique.push_front(a);
            }
        }
    }

    while (historique.size() > R_TailleHistorique())
    {
        if (inverse_historique)
        {
            historique.pop_front();
        }
        else
        {
            historique.pop_back();
        }
    }

    if (type == TYPE_FICHIER)
        { Settings->setValue("Historique/Historique_F", historique); }
    else if (type == TYPE_DOSSIER)
        { Settings->setValue("Historique/Historique_D", historique); }
    else if (type == TYPE_DOSSIER_ENREG)
        { Settings->setValue("Historique/Historique_Sv", historique); }
}

void Parametres::defDernierDossier_Ouverture(const QString &d)
{
    defHistorique(d, TYPE_DOSSIER); // A chaque fois qu'on assigne un nouveau fichier ouvert, on l'ajoute dans l'historique.
    Settings->setValue("Historique/Rep_o", d);
}

QString Parametres::R_DernierDossier_Ouverture() const
{
    return Settings->value("Historique/Rep_o", QVariant(QDir::homePath())).toString();
}

void Parametres::defDernierDossier_SauvegardeMod(const QString &d)
{
    defHistorique(d, TYPE_DOSSIER_ENREG);
    Settings->setValue("Historique/Rep_s", d);
}

QString Parametres::R_DernierDossier_SauvegardeMod() const
{
    return Settings->value("Historique/Rep_s", QVariant(R_CheminExport())).toString();
}

void Parametres::defDivisionsCourbes(int force_valeur)
{
    if (force_valeur != -1)
    {
        if (animation.Anime()) animation.ClicWidget(ui->spb_divisionsellipses);
        ui->spb_divisionsellipses->setValue(force_valeur);
    }

    Settings->setValue("Perspective3D/DivisionsCourbes", ui->spb_divisionsellipses->value());
}

int Parametres::R_DivisionsCourbes() const
{
    return Settings->value("Perspective3D/DivisionsCourbes", QVariant(DivisionsCourbes)).toInt();
}

void Parametres::defEtatApplication(const QByteArray &etat)
{
    Settings->setValue("EtatApplication/EtatApp", etat);
}

QByteArray Parametres::R_EtatApplication() const
{
    return Settings->value("EtatApplication/EtatApp", QVariant("")).toByteArray();
}

void Parametres::defGeometrieApplication(const QByteArray &etat)
{
    Settings->setValue("EtatApplication/GeometrieApp", etat);
}

QByteArray Parametres::R_GeometrieApplication() const
{
    return Settings->value("EtatApplication/GeometrieApp", QVariant("")).toByteArray();
}

void Parametres::defPageDocumentation()
{
    if (documentation)
    {
        Settings->setValue("Historique/PageDoc", documentation->PageCourante());
    }
}

bool Parametres::R_PageDocumentation() const
{
    if (documentation)
    {
        QString f = Settings->value("Historique/PageDoc", QVariant("")).toString();
        if (!f.isEmpty())
        {
            documentation->OuvrePage(f, false);
            return true;
        }
    }
    return false;
}

void Parametres::defTypeInterface()
{
    Settings->setValue("Ergonomie/TypeInterface", ui->cmb_type_interface->currentIndex());
}

void Parametres::defTypeInterface(int force_etat)
{
    ui->cmb_type_interface->setCurrentIndex(force_etat);
    defTypeInterface();
}

int Parametres::R_TypeInterface() const
{
    return Settings->value("Ergonomie/TypeInterface", QVariant(TypeInterface)).toInt();
}

bool Parametres::R_InterfaceStandard() const
{
    return R_TypeInterface() == 0;
}

bool Parametres::R_InterfacePanoramique() const
{
    return R_TypeInterface() == 1;
}

bool Parametres::R_InterfacePetitEcran() const
{
    return R_TypeInterface() == 2;
}

bool Parametres::R_ReductionBarreOnglets2D() const
{
    return (!R_PleinEcran()) && (!R_InterfacePanoramique());
//    return R_InterfacePetitEcran() || R_InterfacePanoramique();
}

bool Parametres::R_MenuContextuel2D() const
{
    return R_InterfacePanoramique();
}

unsigned int Parametres::R_TailleIconesOutils2D() const
{
    if (R_InterfacePetitEcran())
    {
        return 24;
    }
    return 36;
}

void Parametres::defRectSelection(QString nfichier, const char *nom_rect, double x, double y, double lg, double ht)
{
    Settings->beginGroup(nfichier.replace("/", "\\"));
    Settings->beginGroup(QString(nom_rect));
    Settings->setValue("x", x);
    Settings->setValue("y", y);
    Settings->setValue("ht", ht);
    Settings->setValue("lg", lg);
    Settings->endGroup();
    Settings->endGroup();
}

void Parametres::DefPointOrigine(QString nfichier, const char *nom_vue, double x, double y)
{
    Settings->beginGroup(nfichier.replace("/", "\\"));
    Settings->beginGroup(QString(nom_vue));
    Settings->setValue("x", x);
    Settings->setValue("y", y);
    Settings->endGroup();
    Settings->endGroup();
}

QRectF Parametres::R_RectSelection(QString nfichier, const char *nom_rect)
{
    QRectF ret;
    Settings->beginGroup(nfichier.replace("/", "\\"));
    Settings->beginGroup(QString(nom_rect));
    ret.setX(Settings->value("x", 0.).toDouble());
    ret.setY(Settings->value("y", 0.).toDouble());
    ret.setWidth(Settings->value("lg", 0.).toDouble());
    ret.setHeight(Settings->value("ht", 0.).toDouble());
    Settings->endGroup();
    Settings->endGroup();
    return ret;
}

QPointF Parametres::R_PointOrigine(QString nfichier, const char *nom_vue)
{
    QPointF ret;
    Settings->beginGroup(nfichier.replace("/", "\\"));
    Settings->beginGroup(QString(nom_vue));
    ret.setX(Settings->value("x", 0.).toDouble());
    ret.setY(Settings->value("y", 0.).toDouble());
    Settings->endGroup();
    Settings->endGroup();
    return ret;
}

void Parametres::SupprRectSelection(QString nfichier, const char *nom_vue)
{
    Settings->beginGroup(nfichier.replace("/", "\\"));
    Settings->remove(nom_vue);
    Settings->endGroup();
}

void Parametres::SupprPointOrigine(QString nfichier, const char *nom_vue)
{
    Settings->beginGroup(nfichier.replace("/", "\\"));
    Settings->remove(nom_vue);
    Settings->endGroup();
}

void Parametres::defProjections(int force_valeur)
{
    if (force_valeur != -1)
    {
        const Perspective3D::vues2D_t val = static_cast<Perspective3D::vues2D_t>(force_valeur);

        if (animation.Anime())
        {
            AnimCheckBoxMasque(ui->chk_proj_face, animation, val, Perspective3D::vues2D_t::VUEFACE);
            AnimCheckBoxMasque(ui->chk_proj_cote, animation, val, Perspective3D::vues2D_t::VUECOTE);
            AnimCheckBoxMasque(ui->chk_proj_haut, animation, val, Perspective3D::vues2D_t::VUEHAUT);
        }
        else
        {
            ui->chk_proj_face->setChecked(val & Perspective3D::vues2D_t::VUEFACE);
            ui->chk_proj_cote->setChecked(val & Perspective3D::vues2D_t::VUECOTE);
            ui->chk_proj_haut->setChecked(val & Perspective3D::vues2D_t::VUEHAUT);
        }
    }

    Perspective3D::vues2D_t proj = Perspective3D::vues2D_t::VUERREUR;
    if (ui->chk_proj_face->isChecked())
        { proj |= Perspective3D::vues2D_t::VUEFACE; }
    if (ui->chk_proj_cote->isChecked())
        { proj |= Perspective3D::vues2D_t::VUECOTE; }
    if (ui->chk_proj_haut->isChecked())
        { proj |= Perspective3D::vues2D_t::VUEHAUT; }

    Settings->setValue("Perspective3D/Projections", PENUM_CAST_INT(proj));
}

Perspective3D::vues2D_t Parametres::R_Projections() const
{
    return static_cast<Perspective3D::vues2D_t>(Settings->value("Perspective3D/Projections", QVariant(PENUM_CAST_INT(Projections))).toInt());
}

void Parametres::defInformations(int force_valeur)
{
    if (force_valeur != -1)
    {
        const Perspective3D::infos3d_t val = static_cast<Perspective3D::infos3d_t>(force_valeur);
        if (animation.Anime())
        {
            AnimCheckBoxMasque(ui->chk_coords, animation, val, Perspective3D::infos3d_t::ICOORDSPOINTS);
            AnimCheckBoxMasque(ui->chk_rep_sommets, animation, val, Perspective3D::infos3d_t::IDPOINTS);
            AnimCheckBoxMasque(ui->chk_rep_arretes, animation, val, Perspective3D::infos3d_t::IDLIGNES);
            AnimCheckBoxMasque(ui->chkl_rep_surfaces, animation, val, Perspective3D::infos3d_t::IDSURFACES);
            AnimCheckBoxMasque(ui->chk_aff_norm, animation, val, Perspective3D::infos3d_t::IVECTEURNORM);
            AnimCheckBoxMasque(ui->chk_rep_courbes, animation, val, Perspective3D::infos3d_t::IDCOURBES);
        }
        else
        {
            ui->chk_coords->setChecked(val & Perspective3D::infos3d_t::ICOORDSPOINTS);
            ui->chk_rep_sommets->setChecked(val & Perspective3D::infos3d_t::IDPOINTS);
            ui->chk_rep_arretes->setChecked(val & Perspective3D::infos3d_t::IDLIGNES);
            ui->chkl_rep_surfaces->setChecked(val & Perspective3D::infos3d_t::IDSURFACES);
            ui->chk_aff_norm->setChecked(val & Perspective3D::infos3d_t::IVECTEURNORM);
            ui->chk_rep_courbes->setChecked(val & Perspective3D::infos3d_t::IDCOURBES);
        }
    }

    Perspective3D::infos3d_t infos = Perspective3D::infos3d_t::INUL;
    if (ui->chk_coords->isChecked())
        { infos |= Perspective3D::infos3d_t::ICOORDSPOINTS ; }
    if (ui->chk_rep_sommets->isChecked())
        { infos |= Perspective3D::infos3d_t::IDPOINTS; }
    if (ui->chk_rep_arretes->isChecked())
        { infos |= Perspective3D::infos3d_t::IDLIGNES; }
    if (ui->chk_aff_norm->isChecked())
        { infos |= Perspective3D::infos3d_t::IVECTEURNORM; }
    if (ui->chkl_rep_surfaces->isChecked())
        { infos |= Perspective3D::infos3d_t::IDSURFACES; }
    if (ui->chk_rep_courbes->isChecked())
        { infos |= (Perspective3D::infos3d_t::IDCOURBES | Perspective3D::infos3d_t::IDSPHERES); } /* Pour l'instant l'affichage des informations des courbes et des sphères sont corrélés. */

    Settings->setValue("Perspective3D/Informations", PENUM_CAST_INT(infos));
}

Perspective3D::infos3d_t Parametres::R_Informations() const
{
    return static_cast<Perspective3D::infos3d_t>(Settings->value("Perspective3D/Informations", QVariant(PENUM_CAST_INT(Informations))).toInt());
}

void Parametres::defTailleTexte3D(int force_valeur)
{
    if (force_valeur != -1)
    {
        if (animation.Anime())
        {
            animation.ClicWidget(ui->spb_tailletexte3d);
        }
        ui->spb_tailletexte3d->setValue(force_valeur);
    }

    Settings->setValue("Perspective3D/TailleTexte3D", ui->spb_tailletexte3d->value());
}

int Parametres::R_TailleTexte3D() const
{
    return Settings->value("Perspective3D/TailleTexte3D", QVariant(TailleTexte3D)).toInt();
}

bool Parametres::R_FilaireUniquement() const
{
    return Settings->value("Perspective3D/FilaireUniquement", QVariant(FilaireUniquement)).toBool();
}

void Parametres::defFilaireUniquement()
{
    Settings->setValue("Perspective3D/FilaireUniquement", ui->chk_uniquement_filaire->isChecked());
}

void Parametres::defAfficheProprietes3D(bool etat)
{
    Settings->setValue("Ergonomie/AfficheProprietes3D", etat);
}

bool Parametres::R_AfficheProprietes3D() const
{
    return Settings->value("Ergonomie/AfficheProprietes3D", QVariant(AfficheProprietes3D)).toBool();
}

void Parametres::defFilaireUniquement(bool etat)
{
    if (animation.Anime())
    {
        if (etat != ui->chk_uniquement_filaire->isChecked())
        {
            animation.ClicWidget(ui->chk_uniquement_filaire);
        }
    }

    ui->chk_uniquement_filaire->setChecked(etat);
    MiseAJourIdsParams3D();

    defFilaireUniquement();
}

void Parametres::defMultiThreading()
{
    Settings->setValue("Perspective3D/MultiThreading", ui->chk_multithreading->isChecked());
}

bool Parametres::R_MultiThreading() const
{
    return Settings->value("Perspective3D/MultiThreading", QVariant(MultiThreading)).toBool();
}

bool Parametres::R_ExportConfig3DScripts() const
{
    return Settings->value("Export3D/ExportConfig3DScripts", QVariant(ExportConfig3DScripts)).toBool();
}

void Parametres::defExportConfig3DScripts()
{
    Settings->setValue("Export3D/ExportConfig3DScripts", ui->chk_export_config_gen3d_scripts->isChecked());
}

void Parametres::defMultiThreading(bool etat)
{
    if (animation.Anime())
    {
        if (etat != ui->chk_multithreading->isChecked())
        {
            animation.ClicWidget(ui->chk_multithreading);
        }
    }

    ui->chk_multithreading->setChecked(etat);
    MiseAJourIdsParams3D();

    defMultiThreading();
}

void Parametres::defParametresGen3D(int force_valeur)
{
    if (force_valeur != -1)
    {
        const Perspective3D::params_gen3d_t val = static_cast<Perspective3D::params_gen3d_t>(force_valeur);

        if (animation.Anime())
        {
            AnimCheckBoxMasque(ui->chk_suppr_lignes_orphelines, animation, val, Perspective3D::params_gen3d_t::SUPPR_LIGNES_ORPHELINES); MiseAJourIdsParams3D();
            AnimCheckBoxMasque(ui->chk_suppr_lignes_croisement_plan, animation, val, Perspective3D::params_gen3d_t::SUPPR_CROISEMENT_LIGNES_PLAN); MiseAJourIdsParams3D();
            AnimCheckBoxMasque(ui->chk_suppr_chevauchement_lignes, animation, val, Perspective3D::params_gen3d_t::SUPPR_CHEVAUCHEMENT_LIGNES); MiseAJourIdsParams3D();
            AnimCheckBoxMasque(ui->chk_suppr_segments_alignes, animation, val, Perspective3D::params_gen3d_t::SUPPR_ALIGNEMENT_LIGNES); MiseAJourIdsParams3D();
            AnimCheckBoxMasque(ui->chk_suppr_croisement_lignes, animation, val, Perspective3D::params_gen3d_t::SUPPR_CROISEMENT_LIGNES); MiseAJourIdsParams3D();

            AnimCheckBoxMasque(ui->chk_division_surfaces, animation, val, Perspective3D::params_gen3d_t::DIVISION_SURF); MiseAJourIdsParams3D();
            AnimCheckBoxMasque(ui->chk_controle_coherence, animation, val, Perspective3D::params_gen3d_t::CONTROLE_ENVELOPPE); MiseAJourIdsParams3D();
            AnimCheckBoxMasque(ui->chk_suppr_surfaces_meme_plan, animation, val, Perspective3D::params_gen3d_t::SUPPR_VOISINES_MEME_PLAN); MiseAJourIdsParams3D();
            AnimCheckBoxMasque(ui->chk_suppr_surfaces_col_lignes, animation, val, Perspective3D::params_gen3d_t::SUPPR_COLLISION_LIGNES_SURFACES); MiseAJourIdsParams3D();
            AnimCheckBoxMasque(ui->chk_conservation_ents, animation, val, Perspective3D::params_gen3d_t::CONSERVATION_SUPPRS); MiseAJourIdsParams3D();
        }
        else
        {
            ui->chk_controle_coherence->setChecked(val & Perspective3D::params_gen3d_t::CONTROLE_ENVELOPPE);
            ui->chk_division_surfaces->setChecked(val & Perspective3D::params_gen3d_t::DIVISION_SURF);
            ui->chk_suppr_lignes_orphelines->setChecked(val & Perspective3D::params_gen3d_t::SUPPR_LIGNES_ORPHELINES);
            ui->chk_suppr_lignes_croisement_plan->setChecked(val & Perspective3D::params_gen3d_t::SUPPR_CROISEMENT_LIGNES_PLAN);
            ui->chk_suppr_segments_alignes->setChecked(val & Perspective3D::params_gen3d_t::SUPPR_ALIGNEMENT_LIGNES);
            ui->chk_suppr_chevauchement_lignes->setChecked(val & Perspective3D::params_gen3d_t::SUPPR_CHEVAUCHEMENT_LIGNES);
            ui->chk_suppr_croisement_lignes->setChecked(val & Perspective3D::params_gen3d_t::SUPPR_CROISEMENT_LIGNES);
            ui->chk_suppr_surfaces_meme_plan->setChecked(val & Perspective3D::params_gen3d_t::SUPPR_VOISINES_MEME_PLAN);
            ui->chk_suppr_surfaces_col_lignes->setChecked(val & Perspective3D::params_gen3d_t::SUPPR_COLLISION_LIGNES_SURFACES);
            ui->chk_conservation_ents->setChecked(val & Perspective3D::params_gen3d_t::CONSERVATION_SUPPRS);
        }
         MiseAJourIdsParams3D();
    }

    Perspective3D::params_gen3d_t params = GenIdentifiantParams3d();

    Settings->setValue("Perspective3D/ParametresSolide3D", PENUM_CAST_INT(params));
}

Perspective3D::params_gen3d_t Parametres::R_ParametresGen3D() const
{
    return static_cast<Perspective3D::params_gen3d_t>(Settings->value("Perspective3D/ParametresSolide3D", QVariant(PENUM_CAST_INT(ParametresSolide3D))).toUInt());
}

void Parametres::defTailleSurfaces(int force_valeur)
{
    if (force_valeur != -1)
    {
        if (animation.Anime() && (ui->spb_nb_sommets_surfaces->value() != force_valeur))
        {
            animation.ClicWidget(ui->spb_nb_sommets_surfaces);
        }
        ui->spb_nb_sommets_surfaces->setValue(force_valeur);
        MiseAJourIdsParams3D();
    }
    Settings->setValue("Perspective3D/NbSommetsMaxSurfaces", ui->spb_nb_sommets_surfaces->value());
}


unsigned int Parametres::R_TailleSurfaces() const
{
    return Settings->value("Perspective3D/NbSommetsMaxSurfaces", QVariant(NbSommetsMaxSurfaces)).toUInt();
}

void Parametres::defValeurEchelleUniforme(int force_valeur)
{
    if (force_valeur != -1)
    {
        if (animation.Anime())
            animation.ClicWidget(ui->spb_echelle_uniforme);
        ui->spb_echelle_uniforme->setValue(force_valeur);

//        defActiveEchelleUniforme(force_valeur);
    }
    Settings->setValue("Perspective3D/ValeurEchelleUniforme", ui->spb_echelle_uniforme->value());
}

unsigned int Parametres::R_ValeurEchelleUniforme() const
{
    return Settings->value("Perspective3D/ValeurEchelleUniforme", QVariant(ValeurEchelleUniforme)).toUInt();
}

void Parametres::defActiveEchelleUniforme(int force_valeur)
{
    if (force_valeur != -1)
    {
        if (animation.Anime())
            animation.ClicWidget(ui->chk_echelle_uniforme);
        ui->chk_echelle_uniforme->setChecked(force_valeur > 0);
        ui->spb_echelle_uniforme->setEnabled(ui->chk_echelle_uniforme->isChecked());
    }
    Settings->setValue("Perspective3D/ActiveEchelleUniforme", ui->chk_echelle_uniforme->isChecked());
}

bool Parametres::R_ActiveEchelleUniforme() const
{
    return Settings->value("Perspective3D/ActiveEchelleUniforme", QVariant(ActiveEchelleUniforme)).toBool();
}

void Parametres::defOpaciteSolide()
{
    Settings->setValue("Affichage3D/OpaciteSolide", ui->spb_opacite_solide->value());
}

int Parametres::R_OpaciteSolide() const
{
    return Settings->value("Affichage3D/OpaciteSolide", QVariant(OpaciteSolide)).toInt();
}

void Parametres::defEclairageDeuxFaces()
{
    Settings->setValue("Affichage3D/EclairageVersoFaces", ui->chk_eclairage_verso_faces->isChecked());
}

bool Parametres::R_EclairageDeuxFaces() const
{
    return Settings->value("Affichage3D/EclairageVersoFaces", QVariant(EclairageVersoFaces)).toBool();
}

void Parametres::defAfficheAccrochage3D()
{
    Settings->setValue("Affichage3D/AfficheAccroche3D", ui->chk_affiche_accroche->isChecked());
}

bool Parametres::R_AfficheAccrochage3D() const
{
    return Settings->value("Affichage3D/AfficheAccroche3D", QVariant(AfficheAccroche3D)).toBool();
}

const QCheckBox *Parametres::Chk_FilaireUniquement()
{
    return ui->chk_uniquement_filaire;
}

double Parametres::R_ToleranceDessin() const
{
    return Settings->value("Perspective3D/ToleranceDessin", QVariant(ToleranceDessin)).toDouble();
}

void Parametres::defToleranceDessin(double d)
{
    if (animation.Anime())
    {
        animation.ClicWidget(ui->dspb_tolerance);
    }
    ui->dspb_tolerance->setValue(d);
    Settings->setValue("Perspective3D/ToleranceDessin", d);
}

void Parametres::defCheminExport(const QString &ch)
{
    Settings->setValue("Export3D/R_Export3D", ch);
}

QString Parametres::R_CheminExport() const
{
    QString r = Settings->value("Export3D/R_Export3D", QVariant(R_Export3D)).toString();

#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
    if (r.isEmpty())
    {
        QStringList lr = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation);
        if (lr.size())
        {
            return lr[0];
        }
        return QString("");
    }
#else
    if (r.isEmpty())
    {
        return QDir::homePath();
    }
#endif
    return r;
}

void Parametres::defNomDernierScript(const QString &n)
{
    Settings->setValue("Export3D/NomDernierScript", n);
}

QString Parametres::R_NomDernierScript() const
{
    return Settings->value("Export3D/NomDernierScript", QVariant(NomDernierScript)).toString();
}

int Parametres::R_ArrondiEntites() const
{
    return Settings->value("Perspective3D/ArrondiDessin", QVariant(ArrondiDessin)).toInt();
}

void Parametres::defArrondiEntites(int i)
{
    if (animation.Anime())
    {
        animation.ClicWidget(ui->spb_arrondi);
    }

//    if (!i)
//        i = 1;
    if (i > MaxArrondi)
        i = MaxArrondi;

    ui->spb_arrondi->setValue(i);
    Settings->setValue("Perspective3D/ArrondiDessin", i);
}

void Parametres::defNiveauTolerance(int niveau, int niveau_max)
/* Assigne un niveau de tolérance du dessin. */
{
    int niveau_i = niveau_max - niveau;
    if (niveau_i < 0)
        niveau_i = 1;

    const int arr_min = 3; /* Valeur d'Epsilon minimum en nombre de chiffres après la virgule. */
    const int arr_max = 6; /* Valeur d'Epsilon maximum en nombre de chiffres après la virgule. */

    const int diff_arr = arr_max - arr_min;
    float coef_arr = (float) niveau_max / (float) (diff_arr+1);
    int arr = arr_min + (niveau_i / coef_arr);
    if (arr <= 0)
        arr = 1;

    ui->spb_arrondi->setValue(arr);
    defArrondiEntites(arr);

    float val = niveau * .1;
    ui->dspb_tolerance->setValue(val);
    defToleranceDessin(val);

#ifdef DEBUG
    qDebug() << "DefTolerance: " << val << ", arrondi: " << arr;
#endif

//    int arr;
//    if ((niveau-1) > ui->spb_arrondi->maximum())
//        arr = ui->spb_arrondi->maximum();
//    else
//    {
////        arr = ui->spb_arrondi->maximum()-((niveau)/2);
//        arr = ui->spb_arrondi->maximum()-((niveau/3));
////        std::cout << "Test: " << arr << " (" << ui->spb_arrondi->maximum() << ")" << std::endl;
//        if (arr < 0)
//            arr = 1;
//    }
//    ui->spb_arrondi->setValue(arr);
//    defArrondiEntites(arr);

//    double val = (niveau) * .1;
//    ui->dspb_tolerance->setValue(val);
//#ifdef DEBUG
//    qDebug() << "DefTolerance: " << val << ", arrondi: " << arr;
//#endif
//    defToleranceDessin(val);
}

void Parametres::defEclairageScene()
{
    Settings->setValue("Affichage3D/EclairageScene3D", ui->chk_eclairage_scene->isChecked());
}

bool Parametres::R_EclairageScene() const
{
//    return ui->chk_eclairage_scene->isChecked();
    return Settings->value("Affichage3D/EclairageScene3D", QVariant(EclairageScene3D)).toBool();
}

void Parametres::defAffichageOrthographique()
{
    Settings->setValue("Affichage3D/AffichageOrthographique", ui->chk_mode_ortho->isChecked());
}

bool Parametres::R_AffichageOrthographique() const
{
    return Settings->value("Affichage3D/AffichageOrthographique", QVariant(AffichageOrthographique)).toBool();
}

void Parametres::defLissageAffichage3D()
{
    Settings->setValue("Affichage3D/LissageAffichage3D", ui->chk_lissage3d->isChecked());
}

bool Parametres::R_LissageAffichage3D() const
{
    return Settings->value("Affichage3D/LissageAffichage3D", QVariant(LissageAffichage3D)).toBool();
}

void Parametres::defZoneParamsImprimable3D()
{
    Settings->setValue("Affichage3D/AfficheZoneImpression3D", ui->chk_zone_impression3d->isChecked());
    Settings->setValue("Affichage3D/ZoneImpressionX", ui->spb_imprimante_x->value());
    Settings->setValue("Affichage3D/ZoneImpressionY", ui->spb_imprimante_y->value());
    Settings->setValue("Affichage3D/ZoneImpressionZ", ui->spb_imprimante_z->value());
}

bool Parametres::R_AfficheZoneImpression3D() const
{
    return Settings->value("Affichage3D/AfficheZoneImpression3D", QVariant(AfficheZoneImpression3D)).toBool();
}

unsigned int Parametres::R_TailleZoneImpression3D_X() const
{
    return Settings->value("Affichage3D/ZoneImpressionX", QVariant(ui->spb_imprimante_x->value())).toInt();
}

unsigned int Parametres::R_TailleZoneImpression3D_Y() const
{
    return Settings->value("Affichage3D/ZoneImpressionY", QVariant(ui->spb_imprimante_y->value())).toInt();
}

unsigned int Parametres::R_TailleZoneImpression3D_Z() const
{
    return Settings->value("Affichage3D/ZoneImpressionZ", QVariant(ui->spb_imprimante_z->value())).toInt();
}

void Parametres::defExport2DVignette()
{
    Settings->setValue("Export3D/ModeVignetteExport2D", ui->chk_mode_vignette->isChecked());
}

bool Parametres::R_Export2DVignette() const
{
    return Settings->value("Export3D/ModeVignetteExport2D", QVariant(ModeVignetteExport2D)).toBool();
}

void Parametres::defTailleVignetteExport2D()
{
    Settings->setValue("Export3D/TailleVignetteExport2D", ui->spb_taille_vignette->value());
}

unsigned int Parametres::R_TailleVignetteExport2D() const
{
    return Settings->value("Export3D/TailleVignetteExport2D", QVariant(TailleVignetteExport2D)).toInt();
}

void Parametres::DefSepareSolidesSTL()
{
    Settings->setValue("Export3D/SepareSolidesSTL", ui->chk_export_stl_sep->isChecked());
}

bool Parametres::R_SepareSolidesSTL() const
{
    return Settings->value("Export3D/SepareSolidesSTL", QVariant(SepareSolidesSTL)).toBool();
}

void Parametres::defConfigurationImprimante(const QPrinter *imprimante)
{
    Settings->beginGroup("Impression");

    Settings->setValue("NomImprimante", imprimante->printerName());

    const QString fichier_sortie = imprimante->outputFileName();

    if (fichier_sortie.isEmpty())
    {
        Settings->setValue("FormatImpression", QPrinter::NativeFormat);
    }
    else
    {
        Settings->setValue("FormatImpression", imprimante->outputFormat());
    }


    Settings->setValue("NomFichierImpression", fichier_sortie);
    Settings->setValue("SourcePapierImpression", imprimante->paperSource());
    Settings->setValue("TaillePapierImpression", imprimante->paperSize());
    Settings->setValue("OrientationPapierImpression", imprimante->orientation());
    Settings->setValue("CouleurImpression", imprimante->colorMode());
    Settings->setValue("RangImpression", imprimante->printRange());
    Settings->setValue("DuplexImpression", imprimante->duplex());
    Settings->setValue("OrdreImpression", imprimante->pageOrder());

    QPagedPaintDevice::Margins marges; // = imprimante->margins();
    imprimante->getPageMargins(&marges.left, &marges.right, &marges.top, &marges.bottom, QPrinter::Millimeter);

    Settings->setValue("MargeImpression_gauche", marges.left);
    Settings->setValue("MargeImpression_droite", marges.right);
    Settings->setValue("MargeImpression_haut", marges.top);
    Settings->setValue("MargeImpression_bas", marges.bottom);
    Settings->endGroup();
}

void Parametres::ConfigurationImprimante(QPrinter *imprimante) const
{
    const QString chemin_defaut_sortie = R_CheminExport() + (QDir::separator()) + tr("z6.pdf");

    Settings->beginGroup("Impression");

//    imprimante->setDocName(QString("Zetta6"));

    imprimante->setPrinterName(Settings->value("NomImprimante", QVariant(NomImprimante)).toString());
    imprimante->setOutputFormat(QPrinter::OutputFormat(Settings->value("FormatImpression", QVariant(FormatImpression)).toInt()));
    imprimante->setOutputFileName(Settings->value("NomFichierImpression", QVariant(chemin_defaut_sortie)).toString());
    imprimante->setPaperSize(QPrinter::PaperSize(Settings->value("TaillePapierImpression", QVariant(TaillePapierImpression)).toInt()));
    imprimante->setPaperSource(QPrinter::PaperSource(Settings->value("SourcePapierImpression", QVariant(SourcePapierImpression)).toInt()));
    imprimante->setOrientation(QPrinter::Orientation(Settings->value("OrientationPapierImpression", QVariant(OrientationPapierImpression)).toInt()));
    imprimante->setColorMode(QPrinter::ColorMode(Settings->value("CouleurImpression", QVariant(CouleurImpression)).toInt()));
    imprimante->setPrintRange(QPrinter::PrintRange(Settings->value("RangImpression", QVariant(RangImpression)).toInt()));
    imprimante->setDuplex(QPrinter::DuplexMode(Settings->value("DuplexImpression", QVariant(DuplexImpression)).toInt()));
    imprimante->setPageOrder(QPrinter::PageOrder(Settings->value("OrdreImpression", QVariant(OrdreImpression)).toInt()));


    QMarginsF marges(Settings->value("MargeImpression_gauche", QVariant(MargeImpression_gauche)).toReal(),
                     Settings->value("MargeImpression_droite", QVariant(MargeImpression_droite)).toReal(),
                     Settings->value("MargeImpression_haut", QVariant(MargeImpression_haut)).toReal(),
                     Settings->value("MargeImpression_bas", QVariant(MargeImpression_bas)).toReal());
    imprimante->setPageMargins(marges, QPageLayout::Millimeter);
    Settings->endGroup();
}

void Parametres::on_spb_arrondi_valueChanged(int arg1)
{
    double puissance_arrondi = pow (10., arg1);
    ui->lbl_epsilon->setText(QString::number(1./puissance_arrondi, 'f', ui->spb_arrondi->maximum()));
}

void Parametres::on_chk_exportfilaire_toggled(bool checked)
{
    if (checked)
    {
        if (!ui->chk_exportfilaire->isChecked())
            ui->chk_exportfilaire->setChecked(true);
    }
    else
    {
        if (!ui->cb_type_exportDXF->currentIndex())
            ui->cb_type_exportDXF->setCurrentIndex(TypeExportSolideDXF);
    }
}

void Parametres::on_pb_chemin_export_clicked()
{
//    QString dir = QFileDialog::getExistingDirectory(this, tr("Répertoire d'export..."), R_CheminExport());
//    if (!dir.isEmpty())
//        ui->led_chemin_export->setText(dir);

    QFileDialog dialog_dir(Q_NULLPTR, tr("Sélection du répertoire d'export..."), R_CheminExport());
    QStringList hist_d = R_Historique(TYPE_DOSSIER_ENREG);
    dialog_dir.setHistory(hist_d);
    dialog_dir.setWindowFlags(Qt::WindowStaysOnTopHint);
    dialog_dir.setFileMode(QFileDialog::Directory);
    dialog_dir.setViewMode(R_TypeAffichageOuvrir());
    dialog_dir.setAcceptMode(QFileDialog::AcceptOpen);
    dialog_dir.setLabelText(QFileDialog::Accept, tr("Choisir"));
    dialog_dir.setLabelText(QFileDialog::Reject, tr("Annuler"));

    if (!R_InterfacePetitEcran())
    {
        dialog_dir.window()->resize(906,560);
    }

    bool etat_dialog = dialog_dir.exec();
    defTypeAffichageOuvrir(dialog_dir.viewMode());

    if (etat_dialog != QDialog::Accepted)
    {
        return;
    }

    QStringList ls = dialog_dir.selectedFiles();
    if (ls.size())
    {
        if (!(ls[0].isEmpty()))
            ui->led_chemin_export->setText(ls[0]);
    }
}

void Parametres::on_chk_fixe_extrusion_clicked(bool checked)
{
    if (checked)
    {
        ui->dspb_ht_extrusion->setVisible(true);
        ui->dspb_ht_extrusion->setValue(R_HauteurExtrusion());
        ui->dspb_ht_extrusion->setFocus(Qt::TabFocusReason);
        ui->dspb_ht_extrusion->selectAll();
    }
    else
    {
        ui->dspb_ht_extrusion->setVisible(false);
    }
}

void Parametres::on_chk_fixe_revolution_clicked(bool checked)
{
    if (checked)
    {
        ui->dspb_angle_revolution->setVisible(true);
        ui->dspb_angle_revolution->setValue(R_AngleRevolution());
        ui->dspb_angle_revolution->setFocus(Qt::TabFocusReason);
        ui->dspb_angle_revolution->selectAll();
    }
    else
    {
        ui->dspb_angle_revolution->setVisible(false);
    }
}

void Parametres::on_spb_divisionsellipses_valueChanged(int arg1)
{
    if (arg1 > DIVISION_MAX_ELLIPSES)
    {
        ui->spb_divisionsellipses->setValue(DIVISION_MAX_ELLIPSES);
    }
}

void Parametres::on_spb_divisionsellipses_editingFinished()
{
    int val = ui->spb_divisionsellipses->value();

#ifndef DEBUG
    if (val & 0x1) /* Nombre impair ? */
    {
        ++val;
    }
#endif

    if (val > DIVISION_MAX_ELLIPSES)
    {
        val = DIVISION_MAX_ELLIPSES;
    }
    else if (val < DIVISION_MIN_ELLIPSES)
    {
        val = DIVISION_MIN_ELLIPSES;
    }

    ui->spb_divisionsellipses->setValue(val);
}

void Parametres::defCleeActivation(const pint8 *cle)
/* L'utilisateur vient d'entrer une nouvelle clé d'activation... */
{
    InitLicence_P3D = InitLicence_V2D = false;
    Settings->setValue("libPerspective3D/Licence", QByteArray(reinterpret_cast<const char *>(cle), TailleCleActivation));
    Settings->sync();
    ControleLicenceValide(true);
    GenCodeBarreCle();
}

const pint8 *Parametres::R_CleeActivation()
/* Renvoi la clé d'activation (chiffrée) */
{
    QByteArray l_ch = Settings->value("libPerspective3D/Licence", QVariant(QByteArray(32, '\0'))).toByteArray(); // 32 octets.

    int i;
    for(i=0; i<l_ch.size(); ++i)
    {
        Licence[i] = l_ch[i];
    }
    if (i < (TailleCleActivation-1)) // Il y a un truc qui va pas avec la clé...
    {
        for(int i2=i; i<TailleCleActivation; ++i)
        {
            Licence[i2] = '\0';
        }
    }

    Licence[TailleCleActivation] = '\0'; // Obligatoire, sinon la clé sera refusée.

//    ui->lbl_pix_cle->setGeometry(0, 0, pix_cle.width(), pix_cle.height());
    ui->lbl_pix_cle->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Maximum);

    return Licence;
}

void Parametres::defSalageActivation()
{
    /* Le paramètre est écrit une seule fois. Il n'aura pas à être modifié sous peine de devoir entrer à nouveau la clé de licence pour générer une nouvelle clé chiffré. */
    if (!Settings->contains("libPerspective3D/SalageLicence"))
    {
        Settings->setValue("libPerspective3D/SalageLicence", quint64(libPerspective::GenID()));
        Settings->sync();
    }
}

puint64 Parametres::R_SalageActivation()
{
    defSalageActivation(); /* On s'assure d'avoir une valeur pour le salage. */
    return Settings->value("libPerspective3D/SalageLicence", QVariant(0)).toULongLong();
}

void Parametres::GenCodeBarreCle()
{
    ui->lbl_pix_cle->clear();
    ui->lbl_pix_cle->setPixmap(ConversionPImageQPixmap(libPerspective::CodeBarreLicence(R_CleeActivation())));
}

QString Parametres::R_CleeActivationQStr()
{
    return QString(reinterpret_cast<const char *>(R_CleeActivation()));
}

bool Parametres::LicenceValideP3D()
{
    if (!InitLicence_P3D)
    {
        LicenceValide_P3D = Perspective3D::Perspective::ValideLicence(R_CleeActivation(), R_SalageActivation());
        InitLicence_P3D = true;
    }
    return LicenceValide_P3D;
}

#ifdef SUPPORT_VISION2D
bool Parametres::LicenceValideV2D()
{
    if (!InitLicence_V2D)
    {
        LicenceValide_V2D = Perspective3D::Vision::ValideLicence(R_CleeActivation(), R_SalageActivation());
        InitLicence_V2D = true;
    }
    return LicenceValide_V2D;
}
#endif // SUPPORT_VISION2D

void Parametres::defNormeVues2D(int force_valeur)
{
    if (force_valeur != -1)
    {
        const Perspective3D::normevues_t val = static_cast<Perspective3D::normevues_t>(force_valeur);
        if (animation.Anime())
        {
            animation.ClicWidget(ui->cmb_norme_vues);
        }
        if (val == Perspective3D::normevues_t::NORME_VUES_ISO)
            ui->cmb_norme_vues->setCurrentIndex(0);
        else if (val == Perspective3D::normevues_t::NORME_VUES_US)
            ui->cmb_norme_vues->setCurrentIndex(1);
    }
    Settings->setValue("Perspective3D/NormeVues", ui->cmb_norme_vues->currentIndex()+1);
}

Perspective3D::normevues_t Parametres::R_NormeVues2D() const
{
    return static_cast<Perspective3D::normevues_t>(Settings->value("Perspective3D/NormeVues", QVariant(PENUM_CAST_INT(NormeVues))).toInt());
}

void Parametres::on_cmb_norme_vues_currentIndexChanged(int index)
{
    const char *chemin_ico = ((index+1) == PENUM_CAST_INT(Perspective3D::normevues_t::NORME_VUES_US) ? ":/icones/vueUS.png" : ":/icones/vueISO.png");
    QPixmap ico(chemin_ico);
    const char *chemin_ico_2 = ((index+1) == PENUM_CAST_INT(Perspective3D::normevues_t::NORME_VUES_US) ? ":/icones/plan_virtuel_us.png" : ":/icones/plan_virtuel_iso.png");
    ui->lbl_dessin->setPixmap(QPixmap(chemin_ico_2));
    ui->tabWidget->setTabIcon(PONGLET_DESSIN, QIcon(chemin_ico_2));
    ui->lbl_norme_vues->setPixmap(ico.scaledToHeight(20, Qt::SmoothTransformation));
}

void Parametres::on_pb_aboutqt_clicked()
{
    QApplication::aboutQt();
}

void Parametres::on_pb_entree_cle_clicked()
{
    DialogActivation act(R_SalageActivation(), this);
    act.show();
    const pint8 *cle = act.CleCR();
    if (cle) // Si la clé est non nulle, elle est valide !
    {
        defCleeActivation(cle);
    }
}

void Parametres::on_pb_detail_licence_clicked()
{
    liste_licences->show();
}

void Parametres::on_pb_licenceCeCILL_C_clicked()
{
    detail_licence_cecill_c->show();
}

void Parametres::on_pb_licenceP3D_clicked()
{
    detail_licence_p3d->show();
}

void Parametres::on_buttonBox_helpRequested()
/* On demande l'aide ! */
{
    AfficheAide();
}

void Parametres::on_chk_zone_impression3d_clicked()
{
    ui->spb_imprimante_x->setEnabled(ui->chk_zone_impression3d->isChecked());
    ui->spb_imprimante_y->setEnabled(ui->chk_zone_impression3d->isChecked());
    ui->spb_imprimante_z->setEnabled(ui->chk_zone_impression3d->isChecked());
}

void Parametres::ParamsPerspective(Perspective3D::ParametresPerspective &parametres_p3d) const
/* Assigne les paramètres de la configuration actuelle pour la bibliothèque Perspective */
{
    parametres_p3d.Tolerance = R_ToleranceDessin();

    if (R_ActiveEchelleUniforme())
    {
        parametres_p3d.TailleDiagoUniforme = R_ValeurEchelleUniforme();
    }
    else
    {
        parametres_p3d.TailleDiagoUniforme = 0;
    }

    parametres_p3d.Arrondi_dessin = R_ArrondiEntites();
    parametres_p3d.Divisionscercles = R_DivisionsCourbes();
    parametres_p3d.Projections = R_Projections();
    parametres_p3d.Informations = R_Informations();
    parametres_p3d.Tailletexte3d = R_TailleTexte3D();
    parametres_p3d.Filaire_uniquement = R_FilaireUniquement();
    parametres_p3d.MultiThreading = R_MultiThreading();
    parametres_p3d.Parametres3d = R_ParametresGen3D();
    parametres_p3d.Taille_surfaces = R_TailleSurfaces();
    parametres_p3d.Norme_vues = R_NormeVues2D();
    parametres_p3d.Id_ral = Perspective3D::RAL::Index(R_IndexRAL()).id;
    parametres_p3d.Licence = nullptr;
    parametres_p3d.SalageLicence = 0;
}

bool Parametres::ForceConfigP3D(const Perspective3D::ParametresPerspective &parametres_p3d)
{
    if (animation.Anime())
    {
        show();
    }

    if (!CompareE(parametres_p3d.Tolerance, R_ToleranceDessin()) ||
            ((parametres_p3d.TailleDiagoUniforme > 0) != R_ActiveEchelleUniforme()) ||
            (parametres_p3d.TailleDiagoUniforme != R_ValeurEchelleUniforme()) ||
            (parametres_p3d.Arrondi_dessin != R_ArrondiEntites()) ||
            (parametres_p3d.Divisionscercles != R_DivisionsCourbes() ||
             (parametres_p3d.Norme_vues != R_NormeVues2D())) )
    {
        if (animation.Anime())
        {
            ForceOnglet(PONGLET_DESSIN);
            if (!isVisible()) return false; /* Contrôle si l'utilisateur a fermé la fenêtre. */
        }
        if (!CompareE(parametres_p3d.Tolerance, R_ToleranceDessin()))
        {
            defToleranceDessin(parametres_p3d.Tolerance);
            if (!isVisible()) return false;
        }

        if ((parametres_p3d.TailleDiagoUniforme > 0) != R_ActiveEchelleUniforme())
        {
            defActiveEchelleUniforme(parametres_p3d.TailleDiagoUniforme);
            if (!isVisible()) return false;
        }

        if (ui->spb_echelle_uniforme->isEnabled())
        {
            if (parametres_p3d.TailleDiagoUniforme != R_ValeurEchelleUniforme())
            {
                defValeurEchelleUniforme(parametres_p3d.TailleDiagoUniforme);
                if (!isVisible()) return false;
            }
        }

        if (parametres_p3d.Arrondi_dessin != R_ArrondiEntites())
        {
            defArrondiEntites(parametres_p3d.Arrondi_dessin);
            if (!isVisible()) return false;
        }

        if (parametres_p3d.Divisionscercles != R_DivisionsCourbes())
        {
            defDivisionsCourbes(parametres_p3d.Divisionscercles);
            if (!isVisible()) return false;
        }

        if (parametres_p3d.Norme_vues != R_NormeVues2D())
        {
            defNormeVues2D(PENUM_CAST_INT(parametres_p3d.Norme_vues));
            if (!isVisible()) return false;
        }
    }

    if ((parametres_p3d.Filaire_uniquement != R_FilaireUniquement()) ||
            (parametres_p3d.MultiThreading != R_MultiThreading()) ||
            (parametres_p3d.Parametres3d != R_ParametresGen3D()) ||
            (parametres_p3d.Taille_surfaces != R_TailleSurfaces()) )
    {
        if (animation.Anime())
        {
            ForceOnglet(PONGLET_SOLIDE3D);
            if (!isVisible()) return false;
        }
        if (parametres_p3d.Filaire_uniquement != R_FilaireUniquement())
        {
            defFilaireUniquement(parametres_p3d.Filaire_uniquement);
            if (!isVisible()) return false;
        }

        if (parametres_p3d.MultiThreading != R_MultiThreading())
        {
            defMultiThreading(parametres_p3d.MultiThreading);
            if (!isVisible()) return false;
        }

        if (parametres_p3d.Parametres3d != R_ParametresGen3D())
        {
            defParametresGen3D(PENUM_CAST_INT(parametres_p3d.Parametres3d));
            if (!isVisible()) return false;
        }

        if (parametres_p3d.Taille_surfaces != R_TailleSurfaces())
        {
            defTailleSurfaces(parametres_p3d.Taille_surfaces);
            if (!isVisible()) return false;
        }
    }

    if ((parametres_p3d.Id_ral != R_IdentRAL3D()) ||
            (parametres_p3d.Tailletexte3d != R_TailleTexte3D()) ||
            (parametres_p3d.Projections != R_Projections()) ||
            (parametres_p3d.Informations != R_Informations()) )
    {
        if (animation.Anime())
        {
            ForceOnglet(PONGLET_AFFICHAGE3D);
            ForceSousOngletAffichage(0);
            if (!isVisible()) return false;
        }
        if (parametres_p3d.Id_ral != R_IdentRAL3D())
        {
            defIdentRAL3D(parametres_p3d.Id_ral);
            if (!isVisible()) return false;
        }

        if (parametres_p3d.Tailletexte3d != R_TailleTexte3D())
        {
            defTailleTexte3D(parametres_p3d.Tailletexte3d);
            if (!isVisible()) return false;
        }

        if (parametres_p3d.Projections != R_Projections())
        {
            defProjections(PENUM_CAST_INT(parametres_p3d.Projections));
            if (!isVisible()) return false;
        }

        if (parametres_p3d.Informations != R_Informations())
        {
            defInformations(PENUM_CAST_INT(parametres_p3d.Informations));
            if (!isVisible()) return false;
        }
    }

    if (animation.Anime())
    {
        animation.Sommeil();
        animation.ClicWidget(ui->buttonBox->button(QDialogButtonBox::Ok));
        if (!isVisible()) return false;
        close();
    }
    return true;
}

void Parametres::AfficheAide()
{
    if (isVisible() && documentation)
    {
        unsigned int onglet = ui->tabWidget->currentIndex();
        if (onglet == PONGLET_ERGONOMIE)
            { documentation->OuvrePage("parametrage.html#ergonomie"); }
        else if (onglet == PONGLET_DESSIN)
            { documentation->OuvrePage("parametrage.html#dessin"); }
#ifdef SUPPORT_VISION2D
        else if (onglet == PONGLET_VISION2D)
            { documentation->OuvrePage("parametrage.html#vision2d"); }
#endif // SUPPORT_VISION2D
        else if (onglet == PONGLET_SOLIDE3D)
            { documentation->OuvrePage("parametrage.html#gen3d"); }
        else if (onglet == PONGLET_AFFICHAGE3D)
            { documentation->OuvrePage("parametrage.html#affichage3d"); }
        else if (onglet == PONGLET_EXPORT)
            { documentation->OuvrePage("parametrage.html#export"); }
        else if (onglet == PONGLET_PRODUIT)
            { documentation->OuvrePage("parametrage.html#licence"); }
        else
            { return; }
        documentation->show();
    }
}

void Parametres::AssigneParametresGL(PGL::Params_GL &params)
{
    params.ep_points = 8.f;
    params.ep_lignes = 2.5f;
    params.eclairage_dyn = R_EclairageScene();
    params.eclairage_uni = R_EclairageDeuxFaces();
    params.mode_ortho = R_AffichageOrthographique(); // mode_2d
    params.active_shaders = R_ActiveGLSL();
    params.active_fbo = R_ActiveGLSLPost();

    QRgb couleur_fond = R_CouleurFond3D();
    params.couleur_fond = PGL::PCouleur_GL( Perspective3D::PCouleur(qRed(couleur_fond), qGreen(couleur_fond), qBlue(couleur_fond)) );
}

void Parametres::AssigneParametresPerspectiveGL(PGL::Params_Perspective_GL &params, const Perspective3D::Perspective &perspective, bool mode_2d)
{
    params.opacite_solide = R_OpaciteSolide();
    params.idcouleur_solide = Perspective3D::RAL::RechercheIndex(perspective.SceneConst().CouleurRAL());
    params.mode_2d = mode_2d;
    params.lissage = R_LissageAffichage3D();
    params.defImprimante3D((R_AfficheZoneImpression3D() && !mode_2d), R_TailleZoneImpression3D_X(), R_TailleZoneImpression3D_Y(), R_TailleZoneImpression3D_Z());

    params.type_affichage = R_TypeAffichage3D();

    /* Modèle de couleurs : */
    QRgb couleur_sommets = R_CouleurSommets3D();
    QRgb couleur_segments = R_CouleurSegments3D();
    QRgb couleur_imprimante = R_CouleurImprimante3D();
    QRgb couleur_repere_sommets = R_CouleurReperesSommets3D();
    QRgb couleur_repere_segments = R_CouleurReperesSegments3D();
    QRgb couleur_repere_faces = R_CouleurReperesFaces3D();

    params.couleur_sommets = PGL::PCouleur_GL( Perspective3D::PCouleur(qRed(couleur_sommets), qGreen(couleur_sommets), qBlue(couleur_sommets)) );
    params.couleur_segments = PGL::PCouleur_GL( Perspective3D::PCouleur(qRed(couleur_segments), qGreen(couleur_segments), qBlue(couleur_segments)) );
    params.couleur_imprimante = PGL::PCouleur_GL( Perspective3D::PCouleur(qRed(couleur_imprimante), qGreen(couleur_imprimante), qBlue(couleur_imprimante)) );
    params.couleur_repere_sommets = PGL::PCouleur_GL( Perspective3D::PCouleur(qRed(couleur_repere_sommets), qGreen(couleur_repere_sommets), qBlue(couleur_repere_sommets)) );
    params.couleur_repere_segments = PGL::PCouleur_GL( Perspective3D::PCouleur(qRed(couleur_repere_segments), qGreen(couleur_repere_segments), qBlue(couleur_repere_segments)) );
    params.couleur_repere_faces = PGL::PCouleur_GL( Perspective3D::PCouleur(qRed(couleur_repere_faces), qGreen(couleur_repere_faces), qBlue(couleur_repere_faces)) );
}

void Parametres::AssigneParametresPerspectiveGL(PGL::Params_Perspective_GL &params)
{
    params.opacite_solide = R_OpaciteSolide();
    params.idcouleur_solide = Perspective3D::RAL::RechercheIndex(R_IdentRAL3D());
    params.mode_2d = false;
    params.lissage = R_LissageAffichage3D();
    params.defImprimante3D(R_AfficheZoneImpression3D(), R_TailleZoneImpression3D_X(), R_TailleZoneImpression3D_Y(), R_TailleZoneImpression3D_Z());

    params.type_affichage = R_TypeAffichage3D();

    /* Modèle de couleurs : */
    QRgb couleur_sommets = R_CouleurSommets3D();
    QRgb couleur_segments = R_CouleurSegments3D();
    QRgb couleur_imprimante = R_CouleurImprimante3D();
    QRgb couleur_repere_sommets = R_CouleurReperesSommets3D();
    QRgb couleur_repere_segments = R_CouleurReperesSegments3D();
    QRgb couleur_repere_faces = R_CouleurReperesFaces3D();

    params.couleur_sommets = PGL::PCouleur_GL( Perspective3D::PCouleur(qRed(couleur_sommets), qGreen(couleur_sommets), qBlue(couleur_sommets)) );
    params.couleur_segments = PGL::PCouleur_GL( Perspective3D::PCouleur(qRed(couleur_segments), qGreen(couleur_segments), qBlue(couleur_segments)) );
    params.couleur_imprimante = PGL::PCouleur_GL( Perspective3D::PCouleur(qRed(couleur_imprimante), qGreen(couleur_imprimante), qBlue(couleur_imprimante)) );
    params.couleur_repere_sommets = PGL::PCouleur_GL( Perspective3D::PCouleur(qRed(couleur_repere_sommets), qGreen(couleur_repere_sommets), qBlue(couleur_repere_sommets)) );
    params.couleur_repere_segments = PGL::PCouleur_GL( Perspective3D::PCouleur(qRed(couleur_repere_segments), qGreen(couleur_repere_segments), qBlue(couleur_repere_segments)) );
    params.couleur_repere_faces = PGL::PCouleur_GL( Perspective3D::PCouleur(qRed(couleur_repere_faces), qGreen(couleur_repere_faces), qBlue(couleur_repere_faces)) );
}

void Parametres::defAutoriseControleMAJ()
{
    Settings->setValue("AutoriseControleMAJ", ui->chk_autorise_contole_maj->isChecked());
}

bool Parametres::R_AutoriseControleMAJ() const
{
    return Settings->value("AutoriseControleMAJ", QVariant(AutoriseControleMAJ)).toBool();
}

bool Parametres::R_AutoriseAnimationScripts() const
{
    return Settings->value("Ergonomie/AutoriseAnimationScripts", QVariant(AutoriseAnimationScripts)).toBool();
}

void Parametres::defAnimationScript()
{
    Settings->setValue("Ergonomie/AutoriseAnimationScripts", ui->chk_autorise_anim_scripts->isChecked());
}

unsigned int Parametres::R_TempsReferenceAnimation() const
{
    return Settings->value("Ergonomie/TempsReferenceAnimation", QVariant(TempsReferenceAnimation)).toUInt();
}

void Parametres::defTempsReferenceAnimation()
{
    Settings->setValue("Ergonomie/TempsReferenceAnimation", (unsigned int) (ui->dspb_animation_temps_reference->value()*1000));
}

unsigned int Parametres::R_VitesseClicAnimation() const
{
    return Settings->value("Ergonomie/VitesseClicAnimation", QVariant(VitesseClicAnimation)).toUInt();
}

void Parametres::defVitesseClicAnimation()
{
    Settings->setValue("Ergonomie/VitesseClicAnimation", (unsigned int) (ui->dspb_animation_duree_clic->value()*1000));
}

unsigned int Parametres::R_VitesseCurseurAnimation() const
{
    return Settings->value("Ergonomie/VitesseCurseurAnimation", QVariant(VitesseCurseurAnimation)).toUInt();
}

void Parametres::defVitesseCurseurAnimation()
{
    Settings->setValue("Ergonomie/VitesseCurseurAnimation", (unsigned int) (ui->spb_animation_vitesse_souris->value()));
}

QFileDialog::ViewMode Parametres::R_TypeAffichageOuvrir() const
{
    return (QFileDialog::ViewMode) Settings->value("EtatApplication/TypeAffichageOuvrir", QVariant(QFileDialog::Detail)).toInt();
}

void Parametres::defTypeAffichageOuvrir(QFileDialog::ViewMode type)
{
    Settings->setValue("EtatApplication/TypeAffichageOuvrir", type);
}

void Parametres::defActiveBruitagesAudio()
{
    Settings->setValue("Ergonomie/ActiveBruitagesAudio", ui->chk_autoriser_bruitages_audio->isChecked());
}

bool Parametres::R_ActiveBruitagesAudio() const
{
    return Settings->value("Ergonomie/ActiveBruitagesAudio", QVariant(ActiveBruitagesAudio)).toBool();
}

void Parametres::defActiveSyntheseVocale()
{
    Settings->setValue("Ergonomie/ActiveSyntheseVocale", ui->chk_synthese_vocale->isChecked());
}

bool Parametres::R_ActiveSyntheseVocale() const
{
    return Settings->value("Ergonomie/ActiveSyntheseVocale", QVariant(ActiveSyntheseVocale)).toBool();
}

void Parametres::defLangueAudio()
{
    Settings->setValue("Ergonomie/LangueAudio", ui->cmb_langue_synthese_vocale->currentIndex());
}

int Parametres::R_LangueAudio() const
{
    return Settings->value("Ergonomie/LangueAudio", QVariant(LangueAudio)).toInt();
}

void Parametres::defVolumeAudio()
{
    Settings->setValue("Ergonomie/VolumeAudio", ui->vslide_volume_audio->value());
}

int Parametres::R_VolumeAudio() const
{
    return Settings->value("Ergonomie/VolumeAudio", QVariant(VolumeAudio)).toInt();
}

qreal Parametres::R_VolumeAudioD() const
{
    return qreal(Settings->value("Ergonomie/VolumeAudio", QVariant(VolumeAudio)).toInt()) * 0.01;
}

void Parametres::defNomPeripheriqueAudio()
{
    Settings->setValue("Ergonomie/NomPeripheriqueAudio", ui->cmb_peripheriques_audio->currentText());
}

QString Parametres::R_NomPeripheriqueAudio(bool fin_thread) const
{
    QString s0 = Settings->value("Ergonomie/NomPeripheriqueAudio", QVariant("")).toString();
    if (!s0.isEmpty())
    {
        return s0;
    }

    if (fin_thread) /* Si l'on est sûr que le thread soit terminé, on peut faire une recherche du meilleur périphérique. */
    {
        int id_selection = th_liste_peripheriques->SelectionPeripheriqueDefaut();
        if (id_selection != -1)
        {
            return liste_peripheriques_audio.at(id_selection).deviceName();
        }
    }

#ifdef Q_OS_UNIX
    return QString("");
#else
    return QAudioDeviceInfo::defaultOutputDevice().deviceName();
#endif
}

const QAudioDeviceInfo *Parametres::R_PeripheriqueAudio()
{
    while (th_liste_peripheriques->enCours() || th_liste_peripheriques->isRunning())
    {
        th_liste_peripheriques->wait(100); /* Attend un peu la liste des périphériques. */
    }

    QString s0 = R_NomPeripheriqueAudio(true);
    if (!s0.isEmpty() && liste_peripheriques_audio.size())
    {
        for(int i=0; i<liste_peripheriques_audio.size(); ++i)
        {
            if (s0.compare(liste_peripheriques_audio.at(i).deviceName(), Qt::CaseInsensitive) == 0)
            {
                peripherique_audio = (liste_peripheriques_audio.at(i));
                return &peripherique_audio;
            }
        }
    }

    peripherique_audio = QAudioDeviceInfo::defaultOutputDevice();
    return &peripherique_audio;
//    return 0;
}

void Parametres::defTempoShaderPost()
{
    Settings->setValue("GL/TempoShadersPost", ui->spb_chrono_shader_post->value());
}

int Parametres::R_TempoShadersPost() const
{
    return Settings->value("GL/TempoShadersPost", QVariant(TempoShadersPost)).toInt();
}

bool Parametres::ControleLicenceValide(bool reinit_params)
/* Adapte l'interface en fonction de l'état de la clé d'activation.
    Renvoi true si la clé d'activation (définie dans le paramétrage) est valide, sinon false. */
{
    const bool activ_3d = LicenceValideP3D();

#ifdef SUPPORT_VISION2D
    const bool activ_2d = LicenceValideV2D();
#else
    const bool activ_2d = false;
#endif // SUPPORT_VISION2D

    if (activ_3d || activ_2d) // Si au moins un clé d'activation est valide...
    {
#ifdef SUPPORT_VISION2D
        if (activ_2d)
        {
            ui->lbl_etat_activation2d->setPixmap(QPixmap(":/icones/valide.png"));
        }
        else
        {
            ui->lbl_etat_activation2d->setPixmap(QPixmap(":/icones/invalide.png"));
        }

        if (activ_3d)
        {
            ui->lbl_etat_activation3d->setPixmap(QPixmap(":/icones/valide.png"));
        }
        else
        {
            ui->lbl_etat_activation3d->setPixmap(QPixmap(":/icones/invalide.png"));
        }

#else
        ui->lbl_etat_activation3d->setPixmap(QPixmap(":/icones/valide.png"));
        ui->lbl_etat_activation2d->setPixmap(QPixmap(":/icones/invalide.png"));
#endif // SUPPORT_VISION2D

        ui->lbl_pix_cle->setStyleSheet(DialogActivation::StyleContourLicence(activ_2d, activ_3d));

        if (reinit_params) /* Si une clée d'activation valide vient d'être entrée, on restaure les paramètres par défaut: */
        {
            ValideVals(); /* Force l'enregistrement des paramètres */
            emit NouvelleLicence();
        }

#ifdef SUPPORT_VISION2D
        if (activ_2d && activ_3d)
#else
        if (activ_3d)
#endif // SUPPORT_VISION2D
        {
#ifdef DEBUG
            ui->widget_cle_activation->setVisible(false);
#else
            ui->pb_entree_cle->setVisible(false);
            ui->widget_cle_activation->setVisible(true);
#endif // DEBUG
        }

        setWindowTitle(tr("Zetta6 - Paramètres"));

        return true;
    }
    else /* Adapte l'interface si il n'y a pas de clé de licence valide. */
    {
        ui->lbl_etat_activation2d->setPixmap(QPixmap(":/icones/invalide.png"));
        ui->lbl_etat_activation3d->setPixmap(QPixmap(":/icones/invalide.png"));
        ui->lbl_pix_cle->setStyleSheet(DialogActivation::StyleContourLicence(activ_2d, activ_3d));

        ui->led_credit_export->setEnabled(false);

#ifndef DEBUG
        ui->pb_entree_cle->setVisible(true);
#endif // DEBUG

        ui->widget_cle_activation->setVisible(false);

        setWindowTitle(tr("Zetta6 - Paramètres") + " " + tr("(Démonstration)"));
    }
    return false;
}

void Parametres::on_tabWidget_currentChanged(int index)
{
    if (ignore_etat_onglets)
    {
        return;
    }
    if (index == PONGLET_PRODUIT)
    {
        GenCodeBarreCle();
        ui->pb_entree_cle->setDefault(true);
    }
    else
    {
        if (index == PONGLET_SOLIDE3D)
        {
            ControleLicenceValide();
        }
        ui->buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
    }
}

void Parametres::on_cmb_typeexport_currentIndexChanged(const QString &arg1)
{
    if (arg1 == "DXF")
    {
        ui->stackedWidget_export->setCurrentIndex(1);
    }
    else if (arg1 == "STL")
    {
        ui->stackedWidget_export->setCurrentIndex(2);
    }
    else if (arg1 == "DAE")
    {
        ui->stackedWidget_export->setCurrentIndex(3);
    }
    else if (arg1 == "AMF")
    {
        ui->stackedWidget_export->setCurrentIndex(4);
    }
    else if (arg1 == "OBJ")
    {
        ui->stackedWidget_export->setCurrentIndex(5);
    }
    else
    {
        ui->stackedWidget_export->setCurrentIndex(0);
    }

//    else if (arg1 == "PLY")
//    {
//    }
//    else if (arg1 == "3DS")
//    {
//    }
//    else if (arg1 == "OBJ")
//    {
//    }
//    else if (arg1 == "X3D")
//    {
//    }
}

void Parametres::on_chk_projections_vues_clicked(bool checked)
{
    ui->chk_proj_face->setChecked(checked);
    ui->chk_proj_cote->setChecked(checked);
    ui->chk_proj_haut->setChecked(checked);
}

void Parametres::on_chk_proj_face_clicked()
{
    ui->chk_projections_vues->setChecked((ui->chk_proj_face->isChecked() || ui->chk_proj_cote->isChecked() || ui->chk_proj_haut->isChecked()));
}

void Parametres::on_chk_proj_cote_clicked()
{
    ui->chk_projections_vues->setChecked((ui->chk_proj_face->isChecked() || ui->chk_proj_cote->isChecked() || ui->chk_proj_haut->isChecked()));
}

void Parametres::on_chk_proj_haut_clicked()
{
    ui->chk_projections_vues->setChecked((ui->chk_proj_face->isChecked() || ui->chk_proj_cote->isChecked() || ui->chk_proj_haut->isChecked()));
}

void Parametres::on_chk_autorise_anim_scripts_stateChanged(int arg1)
{
    ui->widget_conf_animation->setEnabled(arg1 == Qt::Checked);
}

void Parametres::on_dspb_animation_temps_reference_valueChanged(double arg1)
{
    ui->dspb_animation_temps_reference->setSuffix((arg1 < 2.) ? tr(" seconde") : tr(" secondes"));
}

void Parametres::on_dspb_animation_duree_clic_valueChanged(double arg1)
{
    ui->dspb_animation_duree_clic->setSuffix((arg1 < 2.) ? tr(" seconde") : tr(" secondes"));
}

void Parametres::on_chk_mode_vignette_stateChanged(int arg1)
{
    bool affiche = arg1 == Qt::Checked;

    if (affiche)
    {
        ui->widget_vide_export2d->setVisible(false);
        ui->widget_opts_vignette->setVisible(true);
    }
    else
    {
        ui->widget_opts_vignette->setVisible(false);
        ui->widget_vide_export2d->setVisible(true);
    }
}

void Parametres::on_chk_echelle_uniforme_clicked(bool checked)
{
    ui->spb_echelle_uniforme->setEnabled(checked);
}

void Parametres::on_cmb_langue_synthese_vocale_activated(int index)
{
    if (index == 0)
    {
        ui->pled_test_synthese_vocale->setPlainText(QString("Bienvenue dans Zetta6."));
    }
    else if (index == 1)
    {
        ui->pled_test_synthese_vocale->setPlainText(QString("Welcome on Zetta6."));
    }
    else
    {
        ui->pled_test_synthese_vocale->clear();
    }
}

void Parametres::on_pb_test_audio_clicked()
{
#ifdef SUPPORT_DICTION
    animation.ArretDiction();

    const int langue = ui->cmb_langue_synthese_vocale->currentIndex();
    qreal volume = qreal(ui->vslide_volume_audio->value()) * 0.01;

    int id_peripherique = ui->cmb_peripheriques_audio->currentIndex();
    if (liste_peripheriques_audio.size() && id_peripherique < liste_peripheriques_audio.size() && id_peripherique >= 0)
    {

    }
    else
    {
        QMessageBox::information(this, tr("Erreur"), tr("Sélection du périphérique invalide."));
        return;
    }

    const QAudioDeviceInfo *peripherique = &liste_peripheriques_audio.at(id_peripherique);

    bool valide = true;
    if (langue == LANGUE_AUDIO_FR)
    {
        valide = animation.ExecDiction(ui->pled_test_synthese_vocale->toPlainText(), qDicte::LANG_FR, volume, true, peripherique);
    }
    else if (langue == LANGUE_AUDIO_EN)
    {
        valide = animation.ExecDiction(ui->pled_test_synthese_vocale->toPlainText(), qDicte::LANG_EN_GB, volume, true, peripherique);
    }
    else
    {
        return; /* Erreur */
    }

    if (!valide) /* Erreure lors de la diction ?! */
    {
        QMessageBox::information(this, tr("Erreur"), tr("Erreur lors de la diction :") + "\n\n" + animation.ErreurDiction());
    }
#endif // SUPPORT_DICTION
}

void Parametres::on_vslide_volume_audio_valueChanged(int value)
{
    if (etat_init) /* Uniquement après l'initialisation */
    {
//        animation.LectureAudio("qrc:/audio/ding.wav", qreal(value) * 0.01, false);

        int id_peripherique = ui->cmb_peripheriques_audio->currentIndex();
        if (liste_peripheriques_audio.size() && id_peripherique < liste_peripheriques_audio.size() && id_peripherique >= 0)
        {

        }
        else
        {
//            QMessageBox::information(this, tr("Erreur"), tr("Sélection du périphérique invalide."));
            return;
        }

        const QAudioDeviceInfo *peripherique = &liste_peripheriques_audio.at(id_peripherique);

//        if (!animation.LectureAudio(":/audio/ding.wav", qreal(value) * 0.01, peripherique, false))
        if (!animation.TestAudio(qreal(value) * 0.01, peripherique))
        {
            QMessageBox::information(this, tr("Erreur"), tr("Erreur lors de l'audio :") + "\n" + animation.ErreurTestAudio());
        }
    }
}

void Parametres::on_cmb_type_config_affichage_currentIndexChanged(int index)
{
    ui->sw_affichage3d->setCurrentIndex(index);
}

void Parametres::on_chk_glsl_toggled(bool checked)
{
    ui->widget_glsl->setEnabled(checked);
    if (checked)
    {
        change_shader = true;
    }
}

void Parametres::on_lw_liste_progs_glsl_currentRowChanged(int currentRow)
{
    ui->pted_glsl_vertex->clear();
    ui->pted_glsl_frag->clear();
//    ui->lbl_apercu_glsl->clear();

    const unsigned int contexte = ui->cmb_contexte_glsl->currentIndex();

    if (contexte == CONTEXTE_GLSL_MODELE)
    {
        if (currentRow < NOMBRE_SHADERS_PERSO) /* Personnalisé */
        {
            ui->pted_glsl_vertex->setReadOnly(false);
            ui->pted_glsl_frag->setReadOnly(false);
            ui->lbl_apercu_glsl->setPixmap(QPixmap(MiniatureShaderIndefini));
            ui->pb_enregistre_shader->setEnabled(true);
            ui->pb_reinit_shaders->setEnabled(true);
        }
        else /* Autre */
        {
            if (currentRow == NOMBRE_SHADERS_PERSO)
            {
                ui->lbl_apercu_glsl->setPixmap(QPixmap(VertexShaderNul.chemin_miniature));
            }
            else
            {
                const int id = currentRow - (NOMBRE_SHADERS_PERSO+1);
                if (id >= 0 && id < NombreVertexShadersStatique)
                {
                    ui->lbl_apercu_glsl->setPixmap(QPixmap(VertexShadersStatique[id].chemin_miniature));
                }
                else
                {
                    ui->lbl_apercu_glsl->setPixmap(QPixmap(MiniatureShaderIndefini));
                }
            }

            ui->pted_glsl_vertex->setReadOnly(true);
            ui->pted_glsl_frag->setReadOnly(true);
            ui->pb_enregistre_shader->setEnabled(false);
            ui->pb_reinit_shaders->setEnabled(false);
        }
    }
    else if (contexte == CONTEXTE_GLSL_POST)
    {
        if (currentRow < NOMBRE_SHADERS_PERSO) /* Personnalisé */
        {
            ui->pted_glsl_vertex->setReadOnly(false);
            ui->pted_glsl_frag->setReadOnly(false);
            ui->lbl_apercu_glsl->setPixmap(QPixmap(MiniatureShaderIndefini));
            ui->pb_enregistre_shader->setEnabled(true);
            ui->pb_reinit_shaders->setEnabled(true);
        }
        else /* Autre */
        {
            if (currentRow == NOMBRE_SHADERS_PERSO) /* Nul */
            {
                ui->lbl_apercu_glsl->setPixmap(QPixmap(PostShaderNul.chemin_miniature));
            }
            else
            {
                const int id = currentRow - (NOMBRE_SHADERS_PERSO+1);
                if (id >= 0 && id < NombrePostShadersStatique)
                {
                    ui->lbl_apercu_glsl->setPixmap(QPixmap(PostShadersStatique[id].chemin_miniature));
                }
                else
                {
                    ui->lbl_apercu_glsl->setPixmap(QPixmap(MiniatureShaderIndefini));
                }
            }
            ui->pted_glsl_vertex->setReadOnly(true);
            ui->pted_glsl_frag->setReadOnly(true);
            ui->pb_enregistre_shader->setEnabled(false);
            ui->pb_reinit_shaders->setEnabled(false);
        }
    }

    ui->pted_glsl_vertex->setPlainText(VertexShader_Id(currentRow, contexte));
    ui->pted_glsl_frag->setPlainText(PixelShader_Id(currentRow, contexte));
    change_shader = true;
}

void Parametres::on_pted_glsl_vertex_cursorPositionChanged()
{
    const unsigned int taille_totale = 580;
    const unsigned int facteur = 6;
    ui->pted_glsl_frag->setMinimumWidth(taille_totale/facteur);
    ui->pted_glsl_frag->setMaximumWidth(taille_totale/facteur);
    ui->pted_glsl_vertex->setMinimumWidth(taille_totale - (taille_totale/facteur));
    ui->pted_glsl_vertex->setMaximumWidth(taille_totale - (taille_totale/facteur));
}

void Parametres::on_pted_glsl_frag_cursorPositionChanged()
{
    const unsigned int taille_totale = 580;
    const unsigned int facteur = 6;
    ui->pted_glsl_vertex->setMinimumWidth(taille_totale/facteur);
    ui->pted_glsl_vertex->setMaximumWidth(taille_totale/facteur);
    ui->pted_glsl_frag->setMinimumWidth(taille_totale - (taille_totale/facteur));
    ui->pted_glsl_frag->setMaximumWidth(taille_totale - (taille_totale/facteur));
}

void Parametres::on_pb_enregistre_shader_clicked()
{
    defVertexShader_Perso();
    defPixelShader_Perso();
    change_shader = true;
}

void Parametres::on_pb_reinit_shaders_clicked()
{
    const unsigned int contexte = ui->cmb_contexte_glsl->currentIndex();
    if (contexte == CONTEXTE_GLSL_MODELE)
    {
        if (ui->lw_liste_progs_glsl->currentRow() < NOMBRE_SHADERS_PERSO)
        {
            ui->pted_glsl_vertex->setPlainText(PGL::Shaders_GL::VShaderDefaut());
            ui->pted_glsl_frag->setPlainText(PGL::Shaders_GL::FShaderDefaut());
        }
    }
    else if (contexte == CONTEXTE_GLSL_POST)
    {
        if (ui->lw_liste_progs_glsl->currentRow() < NOMBRE_SHADERS_PERSO)
        {
            ui->pted_glsl_vertex->setPlainText(PGL::PFrameBuffer_GL::VShaderDefaut());
            ui->pted_glsl_frag->setPlainText(PGL::PFrameBuffer_GL::FShaderDefaut());
        }
    }
    change_shader = true;
}

void Parametres::PeupleCmbContexteGLSL(unsigned int contexte)
{
    ui->lw_liste_progs_glsl->clear();

    if (contexte == CONTEXTE_GLSL_MODELE) /* Modèle */
    {
        ui->lw_liste_progs_glsl->addItem(new QListWidgetItem(QIcon(":/icones/liste.png"), tr("Personnalisé") + " (1)"));
        ui->lw_liste_progs_glsl->addItem(new QListWidgetItem(QIcon(":/icones/liste.png"), tr("Personnalisé") + " (2)"));
        ui->lw_liste_progs_glsl->addItem(new QListWidgetItem(QIcon(":/icones/liste.png"), tr("Personnalisé") + " (3)"));
        ui->lw_liste_progs_glsl->addItem(new QListWidgetItem(QIcon(":/icones/verrou.png"), tr(VertexShaderNul.nom)));
        for(int i=0; i<NombreVertexShadersStatique; ++i)
        {
            ui->lw_liste_progs_glsl->addItem(new QListWidgetItem(QIcon(":/icones/verrou.png"), tr(VertexShadersStatique[i].nom)));
        }
        ui->widget_tempo_shader_post->setVisible(false);
    }
    else if (contexte == CONTEXTE_GLSL_POST) /* Post-traitement */
    {
        ui->lw_liste_progs_glsl->addItem(new QListWidgetItem(QIcon(":/icones/liste.png"), tr("Personnalisé") + " (1)"));
        ui->lw_liste_progs_glsl->addItem(new QListWidgetItem(QIcon(":/icones/liste.png"), tr("Personnalisé") + " (2)"));
        ui->lw_liste_progs_glsl->addItem(new QListWidgetItem(QIcon(":/icones/liste.png"), tr("Personnalisé") + " (3)"));
        ui->lw_liste_progs_glsl->addItem(new QListWidgetItem(QIcon(":/icones/verrou.png"), tr(PostShaderNul.nom)));

        for(int i=0; i<NombrePostShadersStatique; ++i)
        {
            ui->lw_liste_progs_glsl->addItem(new QListWidgetItem(QIcon(":/icones/verrou.png"), tr(PostShadersStatique[i].nom)));
        }
        ui->widget_tempo_shader_post->setVisible(true);
    }
    ui->lw_liste_progs_glsl->setCurrentRow(R_IdShader_Courant(contexte));
}

void Parametres::on_cmb_contexte_glsl_currentIndexChanged(int index)
{
    PeupleCmbContexteGLSL(index);
    ui->spb_chrono_shader_post->setValue(R_TempoShadersPost());
}

void Parametres::on_lw_couleurs_3d_currentRowChanged(int currentRow)
{
    switch (currentRow)
    {
        case COULEUR_3D_FOND:
        {
            select_couleurs.defCouleur(R_CouleurFond3D());
            break;
        }
        case COULEUR_3D_SOMMETS:
        {
            select_couleurs.defCouleur(R_CouleurSommets3D());
            break;
        }
        case COULEUR_3D_SEGMENTS:
        {
            select_couleurs.defCouleur(R_CouleurSegments3D());
            break;
        }
        case COULEUR_3D_IMPRIMANTE:
        {
            select_couleurs.defCouleur(R_CouleurImprimante3D());
            break;
        }
        case COULEUR_3D_REPERES_SOMMETS:
        {
            select_couleurs.defCouleur(R_CouleurReperesSommets3D());
            break;
        }
        case COULEUR_3D_REPERES_SEGMENTS:
        {
            select_couleurs.defCouleur(R_CouleurReperesSegments3D());
            break;
        }
        case COULEUR_3D_REPERES_SURFACES:
        {
            select_couleurs.defCouleur(R_CouleurReperesFaces3D());
            break;
        }
        default:
        {
            break;
        }
    }
}

void Parametres::NouvelleCouleur3D(QRgb couleur)
{
    const int currentRow = ui->lw_couleurs_3d->currentRow();
    switch (currentRow)
    {
        case COULEUR_3D_FOND:
        {
            defCouleurFond3D(couleur);
            break;
        }
        case COULEUR_3D_SOMMETS:
        {
            defCouleurSommets3D(couleur);
            break;
        }
        case COULEUR_3D_SEGMENTS:
        {
            defCouleurSegments3D(couleur);
            break;
        }
        case COULEUR_3D_IMPRIMANTE:
        {
            defCouleurImprimante3D(couleur);
            break;
        }
        case COULEUR_3D_REPERES_SOMMETS:
        {
            defCouleurReperesSommets3D(couleur);
            break;
        }
        case COULEUR_3D_REPERES_SEGMENTS:
        {
            defCouleurReperesSegments3D(couleur);
            break;
        }
        case COULEUR_3D_REPERES_SURFACES:
        {
            defCouleurReperesFaces3D(couleur);
            break;
        }
        default:
        {
            break;
        }
    }
}

void Parametres::on_led_ids_params_textEdited(const QString &arg1)
/* Assignation par l'utilisateur de paramètres prédéfinis. */
{
    bool valide_conv = false;
    Perspective3D::params_gen3d_t params3d = static_cast<Perspective3D::params_gen3d_t>(arg1.toUInt(&valide_conv));

    if (valide_conv)
    {
        ui->chk_division_surfaces->setChecked(params3d & Perspective3D::params_gen3d_t::DIVISION_SURF);
        ui->chk_controle_coherence->setChecked(params3d & Perspective3D::params_gen3d_t::CONTROLE_ENVELOPPE);
        ui->chk_suppr_lignes_orphelines->setChecked(params3d & Perspective3D::params_gen3d_t::SUPPR_LIGNES_ORPHELINES);
        ui->chk_suppr_lignes_croisement_plan->setChecked(params3d & Perspective3D::params_gen3d_t::SUPPR_CROISEMENT_LIGNES_PLAN);
        ui->chk_suppr_chevauchement_lignes->setChecked(params3d & Perspective3D::params_gen3d_t::SUPPR_CHEVAUCHEMENT_LIGNES);
        ui->chk_suppr_croisement_lignes->setChecked(params3d & Perspective3D::params_gen3d_t::SUPPR_CROISEMENT_LIGNES);
        ui->chk_suppr_segments_alignes->setChecked(params3d & Perspective3D::params_gen3d_t::SUPPR_ALIGNEMENT_LIGNES);
        ui->chk_suppr_surfaces_meme_plan->setChecked(params3d & Perspective3D::params_gen3d_t::SUPPR_VOISINES_MEME_PLAN);
        ui->chk_suppr_surfaces_col_lignes->setChecked(params3d & Perspective3D::params_gen3d_t::SUPPR_COLLISION_LIGNES_SURFACES);
        ui->chk_conservation_ents->setChecked(params3d & Perspective3D::params_gen3d_t::CONSERVATION_SUPPRS);
    }
}

Perspective3D::params_gen3d_t Parametres::GenIdentifiantParams3d() const
{
    Perspective3D::params_gen3d_t params = Perspective3D::params_gen3d_t::PGEN3DNUL;
    if (ui->chk_controle_coherence->isChecked())
        { params |= Perspective3D::params_gen3d_t::CONTROLE_ENVELOPPE; }
    if (ui->chk_division_surfaces->isChecked())
        { params |= Perspective3D::params_gen3d_t::DIVISION_SURF; }
    if (ui->chk_suppr_lignes_orphelines->isChecked())
        { params |= Perspective3D::params_gen3d_t::SUPPR_LIGNES_ORPHELINES; }
    if (ui->chk_suppr_lignes_croisement_plan->isChecked())
        { params |= Perspective3D::params_gen3d_t::SUPPR_CROISEMENT_LIGNES_PLAN; }
    if (ui->chk_suppr_segments_alignes->isChecked())
        { params |= Perspective3D::params_gen3d_t::SUPPR_ALIGNEMENT_LIGNES; }
    if (ui->chk_suppr_chevauchement_lignes->isChecked())
        { params |= Perspective3D::params_gen3d_t::SUPPR_CHEVAUCHEMENT_LIGNES; }
    if (ui->chk_suppr_croisement_lignes->isChecked())
        { params |= Perspective3D::params_gen3d_t::SUPPR_CROISEMENT_LIGNES; }
    if (ui->chk_suppr_surfaces_meme_plan->isChecked())
        { params |= Perspective3D::params_gen3d_t::SUPPR_VOISINES_MEME_PLAN; }
    if (ui->chk_suppr_surfaces_col_lignes->isChecked())
        { params |= Perspective3D::params_gen3d_t::SUPPR_COLLISION_LIGNES_SURFACES; }
    if (ui->chk_conservation_ents->isChecked())
        { params |= Perspective3D::params_gen3d_t::CONSERVATION_SUPPRS; }

    return params;
}

void Parametres::MiseAJourIdsParams3D()
{
    ui->led_ids_params->setText(QString::number(PENUM_CAST_INT(GenIdentifiantParams3d())));
}

void Parametres::on_chk_suppr_lignes_orphelines_clicked() { MiseAJourIdsParams3D(); }
void Parametres::on_chk_suppr_segments_alignes_clicked() { MiseAJourIdsParams3D(); }
void Parametres::on_chk_suppr_lignes_croisement_plan_clicked() { MiseAJourIdsParams3D(); }
void Parametres::on_chk_suppr_chevauchement_lignes_clicked() { MiseAJourIdsParams3D(); }
void Parametres::on_chk_suppr_croisement_lignes_clicked() { MiseAJourIdsParams3D(); }
void Parametres::on_chk_conservation_ents_clicked() { MiseAJourIdsParams3D(); }
void Parametres::on_chk_division_surfaces_clicked() { MiseAJourIdsParams3D(); }
void Parametres::on_chk_controle_coherence_clicked() { MiseAJourIdsParams3D(); }
void Parametres::on_chk_suppr_surfaces_meme_plan_clicked() { MiseAJourIdsParams3D(); }
void Parametres::on_chk_suppr_surfaces_col_lignes_clicked() { MiseAJourIdsParams3D(); }

void Parametres::on_cmb_type_interface_currentIndexChanged(int index)
{
    int largeur_max = 800;
#ifdef SUPPORT_VISION2D
    if (index == 2) /* Mode petit écran */
    {
//        largeur_max = 820;
        largeur_max = 840;
    }
    else
    {
//        largeur_max = 910;
        largeur_max = 900;
    }
#else
    if (index == 2) /* Mode petit écran */
    {
        largeur_max = 730;
    }
    else
    {
        largeur_max = 820;
    }
#endif // SUPPORT_VISION2D

    setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);

    ui->sp_largeur_fenetre->changeSize(largeur_max, 10, QSizePolicy::Fixed, QSizePolicy::Fixed);

    /* Compte 2 pour la bordure entre chaque onglets et 12 pour la marge de la fenêtre. */
    const int taille_titre_onglets = (ui->sp_largeur_fenetre->sizeHint().width() / ui->tabWidget->count()) - ((ui->tabWidget->count()*2)-12);
//    const int taille_titre_onglets = (ui->sp_largeur_fenetre->sizeHint().width() / ui->tabWidget->count()) - ((ui->tabWidget->count()*2)-22);
    ui->tabWidget->setStyleSheet(QString("QTabBar::tab{width : %1px;}").arg(taille_titre_onglets));
    ui->tabWidget->setMinimumHeight(480);

    setFixedSize(width(), height()); /* Vire le bouton pour maximiser la fenêtre. */

    update();
}

void Parametres::on_pted_glsl_frag_textChanged()
{
    change_shader = true;
}

void Parametres::on_pted_glsl_vertex_textChanged()
{
    change_shader = true;
}
