/***********************************************************************
 *
 * Copyright (C) 2010-2017 Innocent De Marchi <tangram.peces@gmail.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 ***********************************************************************/
//#include <QAction>
#include <QApplication>
//#include <QtGui>
//#include <QtCore>
#include <QtWidgets/QMessageBox>
#include <QtWidgets/QStatusBar>
#include <QtWidgets/QMenuBar>
#include <QtWidgets/QProgressDialog>

#include "frmprincipal.h"
#include "constants.h"
#include "funcions.h"
#include "moviment.h"

/*
  * Per actualitzar les cadenes de traducció
  * lupdate -verbose peg-solitaire.pro
  * al terminal
  */

extern QTranslator *qt_translator;
extern QTranslator *appTranslator;

const int numeroLiniesDadesJoc=4;

const int alcadaMenuBarraTasques=60;

QString localePrograma;

int jocResolt;

//Contador dels intents de trobar una solució
//Evita els casos en què no es troba la solució
//d'un problema que en té
int intentsSolucio=0;
/* Controla si s'està cercant una solució a partir
 * d'uns moviments inicials ja fets*/
bool cercaSolucioAPartirDeMovimentsInicials=false;


/****************************************
*
*16/12/10: canviat el sistema per mostrar les
* marques personals (void veureRecordsPersonals())
* Ara es fa amb un diàleg per evitar els problemes
* de la finestra flotant.
*
*16/12/10: canviat el sistema per mostrar les
*solucions. Ara es fa a un Tab i s'ha eliminat
*l'opció de menú
*****************************************/


frmPrincipal::frmPrincipal()
{
  localePrograma=QLocale::system().name();
  qsrand(QTime::currentTime().msec());
  //jocResolt=false;

  setWindowIcon(QIcon(":/peg-solitaire.png"));
  setWindowTitle( tr("Solitari"));
  setMinimumSize (QSize(600,330+alcadaMenuBarraTasques));
  this->move(300,100);
  //Recuperam les dimensions del formulari
  restoreGeometry(QSettings().value(QString("General/geometry")).toByteArray());

   jocFram=new QFrame(this);
   jocFram->setGeometry(0,alcadaMenuBarraTasques,300,300);
   jocFram->setFrameStyle(QFrame::WinPanel | QFrame::Raised);
   jocFram->setMinimumSize(QSize(300,300));

    //rellotge
    rellotgeLabel = new Rellotge(jocFram);
    rellotgeLabel->setMinimumSize(QSize(300,10));
    rellotgeLabel->move(QPoint(0,10));
    rellotgeLabel->setAlignment(Qt::AlignHCenter);
    rellotgeLabel->estableixTemps("00:00:00");



    //Tabs
    tabArbres= new QTabWidget(jocFram);
    tabArbres->setMinimumSize(QSize(290,250));
    tabArbres->move(QPoint(0,50));
    connect(tabArbres,SIGNAL(currentChanged(int)),
          this,SLOT(canviTabSeleccionat( int)));
    //arbre dels jocs
    arbreModalitatsJocTreeWidget= new QTreeWidget(jocFram);
    arbreModalitatsJocTreeWidget->setMinimumSize(QSize(280,210));
   // arbreModalitatsJocTreeWidget->move(QPoint(0,70));
    arbreModalitatsJocTreeWidget->expandAll();
   // connect(arbreModalitatsJocTreeWidget,SIGNAL(itemClicked(QTreeWidgetItem*, int)),
     //      this,SLOT(seleccioModalitatJoc(QTreeWidgetItem*, int)));
    connect(arbreModalitatsJocTreeWidget,SIGNAL(itemSelectionChanged()),
          this,SLOT(seleccioModalitatJoc()));
    connect(arbreModalitatsJocTreeWidget, SIGNAL(itemClicked ( QTreeWidgetItem *, int)),
            this, SLOT(seleccioModalitatJoc()));
    connect(arbreModalitatsJocTreeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
            this, SLOT(canviItemArbreJoc(QTreeWidgetItem*,QTreeWidgetItem*)));
    connect(arbreModalitatsJocTreeWidget, SIGNAL(itemDoubleClicked ( QTreeWidgetItem*, int)),
            this, SLOT(dobleClickArbreJoc(QTreeWidgetItem*, int)));

    //S'afegeix a un tab
    tabArbres->addTab(arbreModalitatsJocTreeWidget,"");
    tabArbres->setTabToolTip(0,tr("Modalitats del joc"));
    tabArbres->setTabIcon(0,
       QIcon(directoriLinux()+QDir().separator()+DIRECTORI_IMATGES+"/peg-solitaire.png"));

    //Visualitzador de solucions
    arbreSolucionsTreeWidget= new QTreeWidget(this);
    arbreSolucionsTreeWidget->setMinimumSize(QSize(280,220));
    arbreSolucionsTreeWidget->setColumnCount(2) ;
    arbreSolucionsTreeWidget->setColumnHidden(1,true);
    connect(arbreSolucionsTreeWidget,SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)),
           this,SLOT(carregaSolucio(QTreeWidgetItem*, int)));
    /*
    solucionsDockWidget = new QDockWidget(tr("Solucions"));
    solucionsDockWidget->setWidget(arbreSolucionsTreeWidget);
    */
   //S'afegeix a un tab
    tabArbres->addTab(arbreSolucionsTreeWidget, "");
    tabArbres->setTabToolTip(1,tr("Solucions"));
    tabArbres->setTabIcon(1,
       QIcon(directoriLinux()+QDir().separator()+DIRECTORI_IMATGES+"/soluciona.png"));


    arbreModalitatsJocPersonalitzatsTreeWidget= new QTreeWidget(jocFram);
    arbreModalitatsJocPersonalitzatsTreeWidget->setMinimumSize(QSize(280,210));
    arbreModalitatsJocPersonalitzatsTreeWidget->expandAll();
    connect(arbreModalitatsJocPersonalitzatsTreeWidget,
            SIGNAL(itemSelectionChanged()),this,SLOT(seleccioModalitatJocPersonalitzat()));
    connect(arbreModalitatsJocPersonalitzatsTreeWidget, SIGNAL(itemClicked ( QTreeWidgetItem *, int)),
            this, SLOT(seleccioModalitatJocPersonalitzat()));
    //S'afegeix a un tab
    tabArbres->addTab(arbreModalitatsJocPersonalitzatsTreeWidget,"");
    tabArbres->setTabToolTip(2,tr("Jocs personalitzats"));
    tabArbres->setTabIcon(2,
       QIcon(directoriLinux()+QDir().separator()+DIRECTORI_IMATGES+"/peg-solitaire-per.png"));



   movimentsUndoStack = new QUndoStack(this);
   taulerJoc= new Tauler (movimentsUndoStack,rellotgeLabel,this,this);
   /* 26/12/12 S'ha afegit el +8 per evitar que les fitxes
    * s'aferrin als marges
    */
   taulerJoc->move(QPoint(300,alcadaMenuBarraTasques+8));

   //Rellotge per a les eleccions a l'atzar
   /* 21/08/16 Eliminada la següent linia:
    * l'objecte ja està declarat a .h
    * S'ha afegit la llavors a tots els qrand
    * (llevat dels de la generació de jocs a l'atzar)
    */
    //QTime rellotgeQTime (0,0,0);
    rellotgeQTime.currentTime();
    rellotgeQTime.start();
    qsrand((QTime::currentTime().msecsSinceStartOfDay()));

    comprovaDirectoriHome();
    actualitzaCodisArxiusDeSolucio();
    //inicialment, el tipus de joc serà del programa
    tipusJocActual=0;
    creaAcccions();
    creaMenus();
    creaBarraTasques();

    /* 19/01/13 Incorporat al procediment
     * de càrrega dels jocs
     */
    //llegeixArxiuData();
    /* 17/08/16
     * Eliminats degut a què ja estan a tradueixGUI() i
     * s'executaven dues vegades
     */
   // carregaArbreModalitatsJoc();
    setArbreJocsActual(0);
    //carregaArbreModalitatsJocPersonalitzats();
    /* 18/01/11
       Eliminat (a Debian) per considerar-ho contrari a les
       "llibertats"
      */
    comprovaRegistre();
}


/*
  Carrega el contingut de l'arxiu data.sol a la
  llista dadesArxiuData
  */
void  frmPrincipal::llegeixArxiuData(){
    //obrim l'arxiu de jocs
    QString nomArxiu=directoriLinux()+DIRECTORI_ARXIU_GAMES_SOL;
    QFile arxiuData(nomArxiu);
    if (!arxiuData.open(QIODevice::ReadOnly | QIODevice::Text)){
        QMessageBox::critical(this,  tr("Solitari"),
                                QString(tr("No s'ha trobat l'arxiu %1")).arg(nomArxiu) );
         return ;
     }
     QTextStream entrada(&arxiuData);
     QString linia0 = entrada.readLine();
     dadesArxiuData.clear();
     while (!linia0.isNull()) {
         if ( ! (linia0.mid(0,1)=="#") ){
            dadesArxiuData.append(linia0); //tipus de joc
            for(int dades=0 ; dades<numeroLiniesDadesJoc-1;++dades){
            dadesArxiuData.append(entrada.readLine());
          }
         }
       linia0 = entrada.readLine();
     } //final del while de la lectura de l'arxiu
}

void frmPrincipal::carregaArbreModalitatsJoc(){

QApplication::setOverrideCursor(Qt::WaitCursor);
    /* 19/01/13 Amb els joc personalitzats, ara això és
     * impresindible per actualitzar les dades dels jocs
     */
    llegeixArxiuData();
     if (dadesArxiuData.size()>0){
         //netejam
         arbreModalitatsJocTreeWidget->clear();
         arbreModalitatsJocTreeWidget->setColumnCount(numeroLiniesDadesJoc+1);
         //Codi del joc, tipus de moviment
         arbreModalitatsJocTreeWidget->setColumnHidden(1,true);
         //files i columnes
         arbreModalitatsJocTreeWidget->setColumnHidden(2,true);
         //dades de les fitxes
         arbreModalitatsJocTreeWidget->setColumnHidden(3,true);
         //Codi de la cadena amb el nom del solitari
         arbreModalitatsJocTreeWidget->setColumnHidden(4,true);

         //posam la capçalera de l'arbre
         QTreeWidgetItem *item=new QTreeWidgetItem();
         //07/01/12 Això no serveix per res!
         //item->setIcon(0,QIcon(directoriLinux()+QDir().separator()+DIRECTORI_IMATGES+"/hi_q.png"));
        // item->setText(0,tr(nomModalitatsJoc[0]));
         item->setText(0,nomDelJoc(0));
         arbreModalitatsJocTreeWidget->setHeaderItem(item);

         //Això per controlar la numeració dels jocs que tenen
         //la mateixa cadena de nom
         QSettings *controlArxiu;
         controlArxiu=new QSettings(
                     QSettings::IniFormat,
                     QSettings::UserScope,"De Marchi", "nomsSol");
         controlArxiu->clear();
         int numSolMateixNom;

         QList<QTreeWidgetItem *> itemsArbre;
         for(int llista=0 ; llista<dadesArxiuData.size()/numeroLiniesDadesJoc;++llista){
               QTreeWidgetItem *item=new QTreeWidgetItem();

              /* QString nomJoc=(tr(nomModalitatsJoc[
                                 dadesArxiuData.value(
                                 llista*numeroLiniesDadesJoc+3).toInt()]));*/


               QStringList codi=dadesArxiuData.value(llista*numeroLiniesDadesJoc).split(" ");
               QString nomJoc=nomDelJoc(
                                 dadesArxiuData.value(
                                 llista*numeroLiniesDadesJoc+3))+
                       afageixTipusMovimentNomJoc(QString(" %1 ").arg(codi.value(1)));

               numSolMateixNom=controlArxiu->value(nomJoc,"1").toInt();
               QString cadenaNomNumero;
               cadenaNomNumero=QString::number(numSolMateixNom);
               while (cadenaNomNumero.length()<3){cadenaNomNumero=" "+cadenaNomNumero;}
               //Comprovam si és una modalitat amb final marcat
               //per afegir un * al nom
               //12/01/13 Nova funció
               //if( (dadesArxiuData.value(llista*numeroLiniesDadesJoc+2).contains("11"))
                 // ||(dadesArxiuData.value(llista*numeroLiniesDadesJoc+2).contains("10")) ){
               if(esSolitariAmbFinalMarcat(
                   dadesArxiuData.value(llista*numeroLiniesDadesJoc+2))){
                   cadenaNomNumero=cadenaNomNumero+" *" ;
               }
             //  cadenaNomNumero=cadenaNomNumero+" ("+codi.value(0)+")";
               /* 16/01/13 Nova funció que retorna el nom
                * del tipus de moviment (diagonal/invers) per
                * simplificar les cadenes de traducció
                */
               item->setText(0,nomJoc+cadenaNomNumero);
               item->setToolTip(0,item->text(0));
               //linea 0: codi joc, tipus moviment
               item->setText(1,dadesArxiuData.value(llista*numeroLiniesDadesJoc));
               //linea 1: files i columnes
               item->setText(2,dadesArxiuData.value(llista*numeroLiniesDadesJoc+1));
               //linea 2: estat de les fitxes
               if(solitariPersonalitzat_esPersonalitzat(dadesArxiuData.value(llista*numeroLiniesDadesJoc))){
                   QString dadesFitxes;
                   while(dadesFitxes.length()<144*2){
                       dadesFitxes=dadesFitxes+"6 ";
                   }
                   dadesFitxes.simplified();
                   item->setText(3,dadesFitxes);
               }
               else item->setText(3,dadesArxiuData.value(llista*numeroLiniesDadesJoc+2));
               //Codi del nom del solitari
               item->setText(4,dadesArxiuData.value(
                                 llista*numeroLiniesDadesJoc+3) );
               //posam l'icone OK si hi ha un rècord
               item->setIcon(0,QIcon(posaIconeOK(codi.value(0))));

            //   item->setText(4,dadesArxiuData.value(llista*numeroLiniesDadesJoc+3));
               numSolMateixNom++;
               controlArxiu->setValue(nomJoc,numSolMateixNom++);
               itemsArbre.append(item);
         }
      arbreModalitatsJocTreeWidget->insertTopLevelItems(0,itemsArbre);
      arbreModalitatsJocTreeWidget->expandAll();
      arbreModalitatsJocTreeWidget->sortItems(0,Qt::AscendingOrder);
      //Seleccionam el darrer joc jugat en tancar el programa
     QSettings tipusJoc;
     bool trobat=false;
     int modalidadJoc=tipusJoc.value( QString("General/modalidadJoc"),1).toInt();
      for(int i=0 ; i<arbreModalitatsJocTreeWidget->topLevelItemCount();++i){
          QStringList  modJoc= arbreModalitatsJocTreeWidget->topLevelItem(i)->text(1).split(" ");
          if (modJoc.value(0).toInt()==modalidadJoc){
              arbreModalitatsJocTreeWidget->topLevelItem(i)->setSelected(true);
              //Aquesta linia posa en marxa la càrrega de les solucions a l'arbre de solucions
              arbreModalitatsJocTreeWidget->setCurrentItem(arbreModalitatsJocTreeWidget->topLevelItem(i));
              trobat=true;
              break;
          }
      }
      if ((! trobat) && ( arbreModalitatsJocTreeWidget->topLevelItemCount()>0)) {
          arbreModalitatsJocTreeWidget->topLevelItem(0)->setSelected(true);
          tipusJocActual=0;
          arbreModalitatsJocTreeWidget->setCurrentItem(arbreModalitatsJocTreeWidget->topLevelItem(0));
      }
     item->setText(0,item->text(0)+" ("+QString::number(
                arbreModalitatsJocTreeWidget->topLevelItemCount()) +")");
     }
QApplication::setOverrideCursor(Qt::ArrowCursor);
}

/* Gestiona a quin arbre de jocs
 * (del programa o personalitzats)
 * cal seleccionar
 */
void frmPrincipal::gestioTipusDeJocASeleccionar(){
 solucionsTrobades.clear();
 switch (tipusJocActual) {
  case 0: //joc del programa
   seleccioModalitatJoc();
   break;
 case 1: //joc personalitzat
  //primer eliminan els arxius .sol i .txt de joc anterior
  //solitariPersonalitzat_eliminaArxiuSolucio();
  seleccioModalitatJocPersonalitzat();
  break;
 }

}

/*
Gestiona la selecció de la modalitat de joc
quan es clica sobre l'arbre de modalitats
*/
void  frmPrincipal::seleccioModalitatJoc(){
   statusBar()->clearMessage();
   /*Necessari per controlar les solucions distintes*/
   retrocedeixMoviment=0;
   if (arbreModalitatsJocTreeWidget->selectedItems().count()==1){
       QTreeWidgetItem *item;
       item=arbreModalitatsJocTreeWidget->selectedItems().first();
       //No s'ha clicat el nus arrel
       if (item->childCount()==0){
           movimentsUndoStack->clear();
           iniciSolucioAction->setEnabled(movimentsUndoStack->canUndo());
           //Reinciam el número d'intents de trobar
           //la solució
           intentsSolucio=0;
           jocResolt=0;
           /* Tractament de la modalitat
            * generació a l'atzar
            */
           if(item->text(3).length()==1){
           //És l'ítem de solitari a l'atzar
             solitariAtzar_generaJoc();
             //06/02/13 nou prod.
             actualitzaConfiguracionsInicials();
             //solucioJocActual_configuracioInicial.clear();
             //solucioJocActual_configuracioInicial.append(taulerJoc->configuracioActual(true));
           }
           else {
           taulerJoc->joc_CarregaJoc(item->text(1),item->text(2),item->text(3));
           taulerJoc->setCodiNomJocActual(item->text(4));
           setArbreJocsActual(0);
           taulerJoc->setSolitariModificat(false);
           taulerJoc->setSolitariPersonalitzat(false);
           //es tracta d'un joc del programa
           tipusJocActual=0;
           //30/12/12 Nova funció hihaRecord()
          // QSettings records;
           QStringList  tipusJoc = item->text(1).split(" ");
           QString record=hihaRecordJoc(tipusJoc.value(0));
           //    records.value( QString("%1/record").arg(tipusJoc.value(0)) ,
           //                                                QString("0")).toString();
           //No mostrarem els records en els solitaris generats a l'atzar
           if ( (record != "0") &&
                !(solitariAtzar_esAtzar(item->text(1))) ){
               statusBar()->showMessage(
               QString(tr("Joc carregat. El vostre record actual és:  %1")).arg(record));
               }
           else statusBar()->clearMessage();

           seguentCodiSolitariPersonalitzat.clear();
           seguentCodiSolitariPersonalitzat.append(
                     solitariPersonalitzat_nouCodiJoc(false));
           //06/02/13 nou prod.
           actualitzaConfiguracionsInicials();
           //Comprovam l'arxiu de solucions
           comprovaArxiuSolucions();
           }
           qApp->processEvents();
           //Si les solucions estan visibles, actualitzam
           veureSolucionsSlot();
           taulerJoc->numeroDeMovimentsJoc();
           mostraMissatge(4);
       }
   }
}

/* Retorna la cadena de la ruta de l'arxiu d'imatge OK
 * per marcar els joc que ja ha resolt l'usuari
 */
QString frmPrincipal::posaIconeOK(QString codiJoc){
 //Comprovam si hi ha un rècord
    if(hihaRecordJoc(codiJoc) != "0"){
    return directoriLinux()+QDir().separator()+"images"+QDir().separator()+"ok.png";}
    else return "";
}
/* Comprova si hi ha un record pel joc
 * i el retorna
 */
QString frmPrincipal::hihaRecordJoc(QString codiJoc){
 QSettings records;
 return records.value( QString("%1/record").arg(codiJoc) ,
                                  QString("0")).toString();
}

void frmPrincipal:: tradueixGUI(){
     surtAction->setText(tr("&Surt"));
     veureRecordsPersonalsAction->setText(tr("Veure records"));
     ajudaAction->setText(tr("Ajuda"));
     creditsPrograma->setText(tr("Credits"));
     agraiment->setText(tr("Agraïments"));
     webProgramaAction->setText(tr("Web del programa"));
     webProgramaPecesAction->setText(tr("Web del tangram"));

     //undoAction->setToolTip(tr("Retrocedeix"));
     undoAction->setText(tr("Retrocedeix"));
     redoAction->setText(tr("Avança"));

     solucionaJocActual->setText(tr("Resol"));
     //29/05/17 Només per estudiat el joc
//     solucionaJocActualForcaBruta->setText(tr("Calcula el joc complet"));


     aplicacioMenu->setTitle(tr("Programa"));
     movimentsMenu->setTitle(tr("&Moviments joc"));
     idiomaMenu->setTitle(tr("Idioma"));
     ajudaMenu->setTitle(tr("Ajuda"));

    setWindowTitle( tr("Solitari"));

    veureRecordsPersonalsAction->setText(tr("Veure marques personals"));
    eliminaRecordsPersonalsAction->setText(tr("Elimina marques personals"));
    reiniciaJocActual->setText(tr("Reinicia el joc actual"));
     iniciSolucioAction->setText(tr("Inici solució"));
     solucionaJocActual->setText(tr("Resol"));
     /* 16/10/12 Eliminats
     veureSolucions->setText(tr("Veure solucions"));
     */

   //  tabArbres->setTabText(0,"");//tr("Modalitats del joc"));
   //  tabArbres->setTabText(1,tr("Solucions"));
     tabArbres->setTabToolTip(0,tr("Modalitats del joc"));
     tabArbres->setTabToolTip(1,tr("Solucions"));
     tabArbres->setTabToolTip(2,tr("Jocs personalitzats"));
     //Això és necessari per eliminar l'arxiu de
     //solucions de les modalitats generades a l'atzar
     solitariAtzar_eliminaArxiuSolucio();
     carregaArbreModalitatsJoc();
     carregaArbreModalitatsJocPersonalitzats();
     tabArbres->setCurrentIndex(0);
}


void frmPrincipal::creaAcccions()
{
 /* Les noves accions que tenguin text, cal posar-les
  * a tradueixGUI().
  */
    surtAction = new QAction(tr("&Surt"), this);
    surtAction->setShortcut(tr("Ctrl+S"));
    surtAction->setIcon(QIcon(directoriLinux()+QDir().separator()+DIRECTORI_IMATGES+"/quit.png"));
    connect(surtAction, SIGNAL(triggered()), this, SLOT(close()));

    veureRecordsPersonalsAction = new QAction(tr("Veure marques personals"), this);
    connect(veureRecordsPersonalsAction, SIGNAL(triggered()), this, SLOT(veureRecordsPersonals()));

    eliminaRecordsPersonalsAction = new QAction(tr("Elimina marques personals"), this);
    connect(eliminaRecordsPersonalsAction, SIGNAL(triggered()), this, SLOT(eliminaRecordsPersonals()));

    reiniciaJocActual = new QAction(tr("Reinicia el joc actual"), this);
    reiniciaJocActual->setShortcut(tr("Ctrl+R"));
    reiniciaJocActual->setIcon(QIcon(directoriLinux()+QDir().separator()+DIRECTORI_IMATGES+"/view-refresh.png"));
    connect(reiniciaJocActual, SIGNAL(triggered()), this, SLOT(gestioTipusDeJocASeleccionar()));

    pausaAction= new QAction(tr("Pausa"), this);
    pausaAction->setShortcut(tr("Ctrl+P"));
    pausaAction->setIcon(QIcon(directoriLinux()+QDir().separator()+DIRECTORI_IMATGES+"/atura.png"));
    connect(pausaAction, SIGNAL(triggered()), this, SLOT(pausaJocSlot()));

/* 07/02/11  Per ara, aixó queda aturat. Cal tenir més garanties
   sobre la seva efectivitat
    sugereixMovimentAction= new QAction(tr("Suggereix moviment"), this);
    sugereixMovimentAction->setShortcut(tr("Ctrl+M"));
    sugereixMovimentAction->setIcon(QIcon(directoriLinux()+QDir().separator()+DIRECTORI_IMATGES+"/sugereix.png"));
    connect(sugereixMovimentAction, SIGNAL(triggered()), this, SLOT(sugereixMovimentSlot()));
    */



   //Això és degut al tema de les traduccions
    //25/07/12
    //Quan carrega moviments, torna la traducció enrera!!
    //undoAction=movimentsUndoStack->createUndoAction(this,tr("Retrocedeix"));
    undoAction=movimentsUndoStack->createUndoAction(this);
   // undoAction->setText(tr("Retrocedeix"));
  //  undoAction->setToolTip(tr("Retrocedeix"));
    undoAction->setShortcut(tr("Ctrl+Z"));
    undoAction->setIcon(QIcon(directoriLinux()+QDir().separator()+DIRECTORI_IMATGES+"/edit-undo.png"));

    //redoAction=movimentsUndoStack->createRedoAction(this,tr("Avança"));
    redoAction=movimentsUndoStack->createRedoAction(this);
    redoAction->setShortcut(tr("Shift+Ctrl+Z"));
    redoAction->setIcon(QIcon(directoriLinux()+QDir().separator()+DIRECTORI_IMATGES+"/edit-redo.png"));

    iniciSolucioAction= new QAction(tr("Inici solució"), this);
    connect(iniciSolucioAction, SIGNAL(triggered()), this, SLOT(iniciSolucioSlot()));
    iniciSolucioAction->setIcon(QIcon(directoriLinux()+QDir().separator()+DIRECTORI_IMATGES+"/go-first.png"));
    iniciSolucioAction->setEnabled(false);


     creditsPrograma= new QAction(tr("Credits"), this);
     connect(creditsPrograma, SIGNAL(triggered()), this, SLOT(creditsProgramaSlot()));

     ajudaAction= new QAction(tr("Ajuda"), this);
     connect(ajudaAction, SIGNAL(triggered()), this, SLOT(ajudaSlot()));

     webProgramaAction= new QAction(tr("Web del programa"), this);
     connect(webProgramaAction, SIGNAL(triggered()), this, SLOT(webProgramaSlot()));

     webProgramaPecesAction= new QAction(tr("Web del tangram"), this);
     connect(webProgramaPecesAction, SIGNAL(triggered()), this, SLOT(webProgramaPecesSlot()));

     solucionaJocActual = new QAction(tr("Resol"), this);
     solucionaJocActual->setIcon(QIcon(directoriLinux()+QDir().separator()+DIRECTORI_IMATGES+"/soluciona.png"));
     //connect(solucionaJocActual, SIGNAL(triggered()), this, SLOT(solucionaJocActual_Inicia()));
     connect(solucionaJocActual, SIGNAL(triggered()), this, SLOT(solucionaJocRapid()));

     //29/05/17
     //Només per analitzar el joc
//     solucionaJocActualForcaBruta = new QAction(tr("Calcula el joc complet"), this);
//     solucionaJocActualForcaBruta->setIcon(QIcon(directoriLinux()+QDir().separator()+
//                                                 DIRECTORI_IMATGES+"/forca-bruta.png"));
//     connect(solucionaJocActualForcaBruta, SIGNAL(triggered()), this, SLOT(solucionaJoc_ForcaBruta()));

     agraiment= new QAction(tr("Agraïments"), this);
     connect(agraiment, SIGNAL(triggered()), this, SLOT(agraimentSlot()));


/* 16/10/12 Eliminats
     veureSolucions= new QAction(tr("Veure solucions"), this);
     connect(veureSolucions, SIGNAL(triggered()), this, SLOT(veureSolucionsSlot()));
    */
}


void frmPrincipal::creaBarraTasques()
{

    aplicacioToolBar = addToolBar("Solitari");
    aplicacioToolBar->setIconSize(QSize(22,22));
    aplicacioToolBar->addAction(surtAction);

    aplicacioToolBar->addAction(reiniciaJocActual);
    aplicacioToolBar->addAction(pausaAction);
    /* 07/02/11
    aplicacioToolBar->addAction(sugereixMovimentAction);
    */
    aplicacioToolBar->addSeparator();
    aplicacioToolBar->addAction(iniciSolucioAction);
    aplicacioToolBar->addAction(undoAction);
    aplicacioToolBar->addAction(redoAction);
    aplicacioToolBar->addSeparator();
    aplicacioToolBar->addAction(solucionaJocActual);
    aplicacioToolBar->addSeparator();
    //29/05/17 El métode de força bruta només es fa servir
    //per analitzar el joc
//    aplicacioToolBar->addAction(solucionaJocActualForcaBruta);
   // aplicacioToolBar->addAction(solucionaJocActualRapid);
}


void frmPrincipal::creaMenus()
{
    aplicacioMenu = menuBar()->addMenu(tr("Programa"));
    aplicacioMenu->addAction(veureRecordsPersonalsAction);
    aplicacioMenu->addAction(eliminaRecordsPersonalsAction);

    /* 16/10/12 Eliminats
    aplicacioMenu->addSeparator();
    aplicacioMenu->addAction(veureSolucions);
    */

    aplicacioMenu->addSeparator();
    aplicacioMenu->addAction(surtAction);

    movimentsMenu= menuBar()->addMenu(tr("&Moviments joc"));
    movimentsMenu->addAction(undoAction);
    movimentsMenu->addAction(redoAction);

    idiomaMenu = new QMenu(tr("Idioma"));
    menuBar()->addMenu(idiomaMenu);

     ajudaMenu= new QMenu(tr("Ajuda"));
     menuBar()->addMenu(ajudaMenu);
     ajudaMenu->addAction(ajudaAction);
     ajudaMenu->addAction(creditsPrograma);
     ajudaMenu->addAction(agraiment);
     ajudaMenu->addAction(webProgramaAction);
     ajudaMenu->addAction(webProgramaPecesAction);


    creaIdiomaMenu();
}


 /*
Suggereix el següent moviment a l'usuari
No es fa servir!! És només una idea
*/
void  frmPrincipal::sugereixMovimentSlot(){
   // if(rellotgeLabel->rellotgeEnMarxa()){
        QStringList movimentsAnteriors;
        QString darrerMoviment;
        QStringList  movimentsSuggerits;
      /*  for(int j=0;j<movimentsUndoStack->count();j++){
            movimentsAnteriors.append(QString("%1 %2").
                                arg(j+1).
                                arg(coordenadesAMoviment(movimentsUndoStack->text(j)))) ;
        }*/
        darrerMoviment.append(coordenadesAMoviment(movimentsUndoStack->text(
                movimentsUndoStack->index()-1)));
        carregaConfiguracionsEliminades();
        //Cal carregar els moviments possibles de les fitxes
       taulerJoc->solucionaJocActual_CalculaMovimentsPosibles();
        movimentsSuggerits.append(
                taulerJoc->solucionaJocActual_CarregaMovimentsArbre1(solucioJocActual_configuracionsEliminades,
                                                         darrerMoviment));
        /*
        qDebug("movimentsSuggerits %d", movimentsSuggerits.count());
        qDebug("darrerMoviment %d", darrerMoviment.length());
        qCritical("darrerMoviment %s", qPrintable(darrerMoviment));

 qDebug("movimentsSuggerits.count() %d", movimentsSuggerits.count());
        qCritical("movimentsSuggerits.value(0) %s", qPrintable(movimentsSuggerits.value(0)));
        */
        qDebug("Moviments suggerits %d",movimentsSuggerits.count());
        for (int i = 0; i < movimentsSuggerits.count(); ++i) {
          qCritical("%s", qPrintable(movimentsSuggerits.value(i)));
        }
        if (movimentsSuggerits.count()>0){
            darrerMoviment.clear();
            darrerMoviment.append(movimentsSuggerits.value(qrand() % movimentsSuggerits.count()));
            //Marcam el moviment seleccionat en el tauler de joc
            taulerJoc->marcaMoviment(darrerMoviment);
            qCritical("darrerMoviment %s", qPrintable(darrerMoviment));
        }
    //}
}


/*
  Manté el joc en pausa
  */
void frmPrincipal::pausaJocSlot(){
    //Si s'està jugant, s'atura el joc
    if(rellotgeLabel->rellotgeEnMarxa()){
        QProgressDialog pausaProgres(tr("Pausa"), tr("Continua"),0,0 ,this);
        rellotgeLabel->aturaRellotge();
        pausaProgres.setWindowModality(Qt::WindowModal);
        pausaProgres.setVisible(true);

//        QString configuracioJoc= taulerJoc->configuracioActual();
        qApp->processEvents();
        bool continua=true;
        taulerJoc->setVisible(false);
        /*18/03/17 Canviat degut als problemes dels fotosensibles*/
        while (continua){
//            taulerJoc->estatFitxesAtzar();
            if (pausaProgres.wasCanceled()){
                continua=false;
                taulerJoc->setVisible(true);
//                taulerJoc->carregaConfiguracio(configuracioJoc);
            }
            qApp->processEvents();
        }
        pausaProgres.close();
        rellotgeLabel->iniciaRellotge();
}
}

/*
 * Retorna totes les fitxes a la posició inicial del joc
 * (o fins el moviment passat per paràmetre)
 */
void frmPrincipal::iniciSolucioSlot(int pmoviment){
/*qDebug("movimentsUndoStack.count() %d",movimentsUndoStack->count());
qDebug("Reinicia*******");*/
    if (pmoviment>0){
        int contador=0;
        //while (movimentsUndoStack->canUndo() && movimentsUndoStack->index()> pmoviment ){
       while (movimentsUndoStack->canUndo() && contador<= pmoviment ){
        movimentsUndoStack->undo();
        contador++;
    }       
    qDebug("retroces iniciSolucio %d",contador);
   }
    else{
        while (movimentsUndoStack->canUndo() ){
        movimentsUndoStack->undo();
     }
    }
//Cal assegurar-se que totes les fitxes actives
//queden en color blau.
taulerJoc->eliminaFitxesVerdes();
taulerJoc->eliminaFitxesVermelles();
statusBar()->clearMessage();
//qDebug("Numero moviments %d", movimentsUndoStack->count());
//iniciSolucioAction->setEnabled(movimentsUndoStack->canUndo());
}

void frmPrincipal::iniciSolucioSlotIndex(int index){

       while (movimentsUndoStack->canUndo() && movimentsUndoStack->index()> index){
        movimentsUndoStack->undo();
       }

//Cal assegurar-se que totes les fitxes actives
//queden en color blau.
taulerJoc->eliminaFitxesVerdes();
taulerJoc->eliminaFitxesVermelles();
statusBar()->clearMessage();
//qDebug("Numero moviments %d", movimentsUndoStack->count());
//iniciSolucioAction->setEnabled(movimentsUndoStack->canUndo());
}


/* Carrega una solució a partir de la
 * pila de moviments
 * (es fa servir en els solitaris personalitzats)
 */
void frmPrincipal::finalSolucioSlot(bool marcaFinal){
    while (movimentsUndoStack->canRedo() ){
    movimentsUndoStack->redo();}
    taulerJoc->marcaFinalDeJoc(taulerJoc->p_tipusMoviment,marcaFinal);
   // if (marcaFinal){taulerJoc->marcaFinalDeJoc(taulerJoc->p_tipusMoviment,marcaFinal);}
}


/* Genera el menú de selecció d'idioma de l'aplicació */
void frmPrincipal::creaIdiomaMenu(){

    idiomaActionGroup = new QActionGroup(this);
    connect(idiomaActionGroup, SIGNAL(triggered(QAction *)), this, SLOT(canviaIdioma(QAction *)));

    QDir dir(directoriLinux()+QDir().separator()+DIRECTORI_LOCALES);
    QStringList arxiusIdioma = dir.entryList(QStringList("solitari_*.qm"));
    /* 02/06/12 v. 1.3
     * Afegit la càrrega del idioma ja seleccionat
     */
    QString localeSys=
        QSettings().value("General/idioma",QLocale::system().name()).toString();

for (int i = 0; i < arxiusIdioma.size(); ++i) {
    QString locale = arxiusIdioma[i];
    locale.remove(0, locale.indexOf('_') + 1);
    locale.truncate(locale.lastIndexOf('.'));

    QTranslator translator;
    translator.load(arxiusIdioma[i], directoriLinux()+QDir().separator()+DIRECTORI_LOCALES);
    QString language =translator.translate("Traduccio","English");
   // QAction *action = new QAction(QString("&%1 %2").arg(i + 1).arg(language), this);
    QAction *action = new QAction(tr("&%1 %2").arg(i + 1).arg(language), this);
    action->setCheckable(true);
    action->setData(locale);

    idiomaMenu->addAction(action);
    idiomaActionGroup->addAction(action);

    //if (locale == QLocale::system().name()){
    if (locale == localeSys){
        action->setChecked(true);
        //a debian, sense això es carregan les cadenes
        //originals enlloc de les traduïdes
        canviaIdioma(action);
       }
  }
}


void frmPrincipal::canviaIdioma(QAction *action){
    localePrograma = action->data().toString();
    appTranslator->load("solitari_" + localePrograma, directoriLinux()+QDir().separator()+DIRECTORI_LOCALES);
    qt_translator->load(QLatin1String("qt_") + localePrograma, QLibraryInfo::location(QLibraryInfo::TranslationsPath));

    tradueixGUI();
    /* 1.3
     * Desam el idioma seleccionat
     */
    QSettings().setValue("General/idioma",localePrograma);
}

void frmPrincipal::resizeEvent ( QResizeEvent * event ){
    QSize augment=this->size()-this->minimumSize();
    jocFram->resize(QSize(jocFram->minimumSize().width(), jocFram->minimumSize().height()+augment.height()));
    tabArbres->resize(QSize(tabArbres->minimumSize().width(),
                           tabArbres->minimumSize().height()+augment.height()));
    arbreModalitatsJocTreeWidget->resize(
            QSize(arbreModalitatsJocTreeWidget->minimumSize().width(),
            arbreModalitatsJocTreeWidget->minimumSize().height()+augment.height()));
    taulerJoc->resize(QSize(taulerJoc->minimumSize()+augment));
}

void frmPrincipal::closeEvent(QCloseEvent* event){
   QStringList  tipusJoc =   arbreModalitatsJocTreeWidget->selectedItems().first()->text(1).split(" ");
   QSettings().setValue("General/modalidadJoc",tipusJoc.value(0));
   /*12/03/12
     Desam la disposició del formulari
     */
   QSettings().setValue(QString("General/geometry"),saveGeometry());
   //Eliminan els arxius de solucions dels solitaris
   //generats a l'atzar
   solitariAtzar_eliminaArxiuSolucio();
   event->accept();
}

void frmPrincipal::creditsProgramaSlot(){
    QDate avui=QDate::currentDate () ;
    QString missatge=QString("<h2>"+tr("Solitari")+
                         QString(" v. %1</h2>").arg(qApp->applicationVersion()));
    if (avui.year()==2010){
        missatge.append(QString("<p> &copy;  "+QString("2010")+"  I. De Marchi <br/>" ));
    }
    else {
    missatge.append(QString("<p> &copy;  "+QString("2010-%1").arg(avui.year())+"  I. De Marchi<br/>" ));
    }
    missatge.append(QString(tr("Sota llicència GPL 2.0 o posterior")+"<br/>"));

    missatge.append(QString("<a href=\"%1\">%1</a><br/>").arg(ADRECA_WEB_PROGRAMA_1));
    missatge.append(QString("<a href=\"%1\">%1</a><br/>").arg(ADRECA_WEB_PROGRAMA_2));
    missatge.append(QString("<a href=mailto:%1>%1</a><br/>").arg(ADRECA_CORREU));

    QMessageBox::about(this,
            QString(tr("Credits del %1").arg(qApp->applicationName())),missatge);
}

void frmPrincipal::webProgramaSlot(){
   QDesktopServices::openUrl(ADRECA_WEB_PROGRAMA_1);
}

void frmPrincipal::webProgramaPecesSlot(){
   QDesktopServices::openUrl(ADRECA_WEB_PROGRAMA_PECES);
}


void frmPrincipal::veureRecordsPersonals(){
  if (arbreModalitatsJocTreeWidget->topLevelItemCount()==0){ return;}
  /* 08/12/2012
   *Substituït per un arxiu html: els rècords no hi cabem en
   *un formulari about
   *

    QString missatge=QString("<h2>"+ tr("Marques personals")+"</h2>");
    QSettings records;
    for(int i=0;i<=arbreModalitatsJocTreeWidget->topLevelItemCount()-1;i++){
        QStringList  tipusJoc = arbreModalitatsJocTreeWidget->topLevelItem(i)->text(1).split(" ");
        QString record=records.value( QString("%1/record").
                                  arg(tipusJoc.value(0)) ,
                                  QString("--")).toString();
        if( !(record.compare("--")==0)){
          missatge.append(QString("<br>"+arbreModalitatsJocTreeWidget->topLevelItem(i)->text(0)+
                                            "    -> "+record));
         }
       //   missatge.append(QString("<p>"+arbreModalitatsJocTreeWidget->topLevelItem(i)->text(0)+
         //                 "    -> "+record  ))  ;
        }
    QMessageBox::about(this,QString(tr("Marques personals")),missatge);
    */

/* Versió HTML
 * 08/12/12
 */
    comprovaDirectoriHome();
    QString nomArxiu=QDir::homePath ();
    nomArxiu.append (QDir().separator());
    nomArxiu.append (qApp->applicationName());
    nomArxiu.append (QDir().separator());
    nomArxiu.append (QString("records.html"));
    QFile arxiu(nomArxiu);
    QTextStream entrada(&arxiu);
    //capçalera de l'arxiu
    if (!arxiu.open(QIODevice::WriteOnly)){return;}
    entrada<<(QString("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">"));
    entrada<<(QString("\n"));
    entrada<<(QString("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />"));
    entrada<<(QString("\n"));
    entrada<<(QString("<html><head><br>"));
    entrada<<(QString("\n"));
    entrada<<(QString("<title>%1</title>").arg(tr("Marques personals")));
    entrada<<(QString("\n"));
    entrada<<(QString("</head>"));
    entrada<<(QString("\n"));
    entrada<<(QString("<body>"));
    entrada<<(QString("\n"));
    entrada<<(QString("<h2>"+ tr("Marques personals")+"</h2>"));
    //Ara començam a escriure els rècords
    QSettings records;
    int contador=1;
    for(int i=0;i<=arbreModalitatsJocTreeWidget->topLevelItemCount()-1;i++){
        QStringList  tipusJoc = arbreModalitatsJocTreeWidget->topLevelItem(i)->text(1).split(" ");
        QString record=records.value( QString("%1/record").
                                  arg(tipusJoc.value(0)) ,
                                  QString("--")).toString();
        if( !(record.compare("--")==0)){
          entrada<<(QString("<br> %1 &nbsp; &nbsp; &nbsp; "+arbreModalitatsJocTreeWidget->topLevelItem(i)->text(0)+
                            "    -> "+record).arg(contador));
          contador++;
          entrada<<(QString("\n"));
         }
     }

    for(int j=0;j<=arbreModalitatsJocPersonalitzatsTreeWidget->topLevelItemCount()-1;j++){
        QStringList  tipusJoc = arbreModalitatsJocPersonalitzatsTreeWidget->topLevelItem(j)->text(1).split(" ");
        QString record=records.value( QString("%1/record").
                                  arg(tipusJoc.value(0)) ,
                                  QString("--")).toString();
        if( !(record.compare("--")==0)){
          entrada<<(QString("<br> %1 &nbsp; &nbsp; &nbsp; "+arbreModalitatsJocPersonalitzatsTreeWidget->topLevelItem(j)->text(0)+
                            "    -> "+record).arg(contador));
          contador++;
          entrada<<(QString("\n"));
         }
     }
    //tancam l'arxiu
    entrada<<(QString("</div>"));
    entrada<<(QString("</body></html>"));
    arxiu.close();
    //Mostram l'arxiu
    QDesktopServices::openUrl(QUrl("file:///"+nomArxiu, QUrl::TolerantMode));


/*
QTextEdit  *texte = new QTextEdit (missatge );
texte->setReadOnly(true);
QDockWidget *recordsPersonalsDockWidget = new QDockWidget(tr("Marques personals"));
recordsPersonalsDockWidget->setWidget(texte);
recordsPersonalsDockWidget->setMinimumSize(400,300);
recordsPersonalsDockWidget->move(QPoint(this->pos().x()+50,this->pos().y()+200));
//solucionsDockWidget->setAllowedAreas(Qt::NoDockWidgetArea);
addDockWidget(Qt::BottomDockWidgetArea, recordsPersonalsDockWidget);
//addDockWidget(Qt::NoDockWidgetArea, solucionsDockWidget);
recordsPersonalsDockWidget->setFloating(false);
*/
}

/*
  Elimina tots els records personals
  */
void frmPrincipal::eliminaRecordsPersonals(){
        QMessageBox missatgeBox;
        missatgeBox.setText(tr("Elimina les marques personals"));
        missatgeBox.setInformativeText(tr("De debó voleu eliminar les vostres marques?"));
        missatgeBox.setIcon(QMessageBox::Question);
        missatgeBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
        missatgeBox.setDefaultButton(QMessageBox::No);
        if(missatgeBox.exec()==QMessageBox::Yes){
            /* 21/09/16 Aqui es mantenia el sistema antic amb els rècords
             * a l'arxiu .ini i eliminava tota la informació de l'arxiu
             * No estava actualitzat al nou sistema amb l'arxiu .html
             */
            comprovaDirectoriHome();
            QString nomArxiu=QDir::homePath ();
            nomArxiu.append (QDir().separator());
            nomArxiu.append (qApp->applicationName());
            nomArxiu.append (QDir().separator());
            nomArxiu.append (QString("records.html"));
            QFile arxiu(nomArxiu);
            arxiu.remove();
            qApp->processEvents();
            /* Eliminan les marques de l'arxiu de configuració
               El 100000 és una mica passat */
            for(int i=0 ; i<50000;++i){
              QSettings records;
              records.remove(QString("%1/record").arg(i));
            }
            /*Recarregam els arbres de jocs per eliminar els
             *icones de marques*/
            carregaArbreModalitatsJoc();
            carregaArbreModalitatsJocPersonalitzats();
        }
}



void frmPrincipal::ajudaSlot(){
 QDir dirArxiu;
 QString directori=directoriLinux()+
                            QDir().separator()+
                            DIR_HELP+
                            QDir().separator()+
                            "index.html";//això no funciona "#es_ES";//+QLocale::system().name();
 //qCritical("%s", qPrintable(directori));
    if (dirArxiu.exists(directori)){
     //Això evita problemes amb els espais als noms dels directoris
        QDesktopServices::openUrl(QUrl("file:///"+directori+"#"+localePrograma, QUrl::TolerantMode));
    }
   else  QDesktopServices::openUrl(QUrl("file:///"+directoriLinux()+
                            QDir().separator()+
                            DIR_HELP+
                            QDir().separator()+
                            "index.html", QUrl::TolerantMode));
}


/* 01/12/12
   Mostra l'arxiu html amb els agraïments
  */
void frmPrincipal::agraimentSlot(){
    QDesktopServices::openUrl(QUrl("file:///"+directoriLinux()+
                                   QDir().separator()+
                                   DIR_HELP+
                                   QDir().separator()+
                                "index.html", QUrl::TolerantMode));
}

/* Comprova si existeixen moviments possibles */
bool frmPrincipal::comprovaExisteixenMovimentsPossibles(){

taulerJoc->solucionaJocActual_CalculaMovimentsPosibles();
solucionaJocActual_movimentsPosiblesActuals.clear();
solucionaJocActual_movimentsPosiblesActuals.append(
  taulerJoc->solucionaJocActual_CarregaMovimentsArbre1(solucionaJocActual_movimentsEliminats,
                                                      solucionaJocActual_darrerMoviment));
return solucionaJocActual_movimentsPosiblesActuals.count()>0;
}

void frmPrincipal::solucionaJocActual_Inicia(){
    /*if (!rellotgeLabel->rellotgeEnMarxa()){
       rellotgeLabel->estableixTemps(QString("00:00:00"));
       rellotgeLabel->iniciaRellotge();
    }*/
    QApplication::setOverrideCursor(Qt::WaitCursor);
    statusBar()->clearMessage();
    solucionaJocActual_ControlJocPersonalitzatModificat();

       jocResolt=0;
       taulerJoc->solucionaJocActual_CalculaMovimentsPosibles();
       if(taulerJoc->solucionaJocActual_MovimentsPosiblesActuals()<0){
         return;
       }
       /*Si ja hi ha moviments fets, llavors es "conservan" i es busca
         la solució a partir de la situació actual*/
       if(movimentsUndoStack->count()>0){
          retrocedeixMoviment=movimentsUndoStack->index();
          //cercaSolucioAPartirDeMovimentsInicials=true;
          solucionaJocActual_movimentsJaRealitzats.clear();
          iniciSolucioSlot();
         // solucioJocActual_configuracioInicial.append(taulerJoc->configuracioActual(true));
          while (movimentsUndoStack->canRedo()){               
               solucionaJocActual_darrerMoviment=QString("%1 ").arg(movimentsUndoStack->index()+1);
               solucionaJocActual_darrerMoviment.append(
                       coordenadesAMoviment(movimentsUndoStack->text(movimentsUndoStack->index())));
               solucionaJocActual_movimentsJaRealitzats.append(solucionaJocActual_darrerMoviment);
               movimentsUndoStack->redo();
          }
       }
       else {
           //06/02/13 nou prod.
           actualitzaConfiguracionsInicials();
           //solucioJocActual_configuracioInicial.clear();
           //solucioJocActual_configuracioInicial.append(
           //            taulerJoc->configuracioActual(true));
           retrocedeixMoviment=0;
           movimentsUndoStack->clear();
       }
   //    solucioJocActual_configuracioInicial.append(taulerJoc->configuracioActual(true));

       solucioJocActual_configuracionsEliminades.clear();
       solucioJocActual_configuracionsEliminadesPerDesar.clear();
       solucionaJocActual_movimentsPosiblesActuals.clear();
       carregaConfiguracionsEliminades();
    //   movimentsUndoStack->clear();
       solucionaJocActual_CarregaMovimentsInicialsArbre();
      // qApp->processEvents();
   }


void frmPrincipal::solucionaJocActual_ControlJocPersonalitzatModificat(){
    if( (taulerJoc->solitariPersonalitzat() ) ||
        (taulerJoc->solitariModificat() )){
        /* S'eliminen les solucions de l'arbre per evitar que
         * s'afegeixin a l'arxiu de solucions del nou
         * solitari (personal o modificat)
         */
       // arbreSolucionsTreeWidget->clear();
        solucionsTrobades.clear();
        carregaSolucions();
//        veureSolucionsSlot();
        taulerJoc->setModalitatJocActual(seguentCodiSolitariPersonalitzat);
    }
}

void frmPrincipal::solucionaJocActual_CarregaMovimentsInicialsArbre(){
    rellotgeLabel->iniciaRellotge();
    solucionaJocActual_comencaRecerca();
    QApplication::setOverrideCursor(Qt::ArrowCursor);
}


void frmPrincipal::solucionaJocActual_comencaRecerca(){
//   qDebug("sistema versio 2.1");
    /*Això és pel problema a windows en què si es mou
    * la finestra de diàleg, llavors s'atura la cerca però
    * no el rellotge*/
   //int numeroDeMovimentsJocInicial=taulerJoc->numeroDeMovimentsJoc();
   //qDebug("numeroDeMovimentsJocInicial %d", numeroDeMovimentsJocInicial);

    //11/06/17 Eliminat tot i què quan es mou el diàleg a windows
    //s'atura el joc però no el rellotge
//    #if defined(Q_OS_WIN32)
//        QProgressDialog progres(tr("Cercant solució"), tr("Atura"), 0,
//                                taulerJoc->numeroDeMovimentsJoc(),this,
//                                Qt::FramelessWindowHint);
//    #else
    //S'ha posat aquest +1 al num.màx. per evitar problemes amb
    //els jocs que tenen el final marcat
        QProgressDialog progres(tr("Cercant solució"), tr("Atura"), 0,
                                //taulerJoc->numeroDeMovimentsJoc(),this);
                                taulerJoc->numeroDeMovimentsJoc()+1,this);
                                //taulerJoc->comptadorFitxesJoc,this);
        /* 21/06/12
         * Posar això altra (per les modalitats amb final marcat)
         * causa problemes amb el progress
         */
         //  taulerJoc->numeroDeMovimentsJoc() ,this);
//    #endif
        progres.setWindowModality(Qt::WindowModal);
             //Això quasi sempre és cert degut a què
             //s'ha carregat (parcialment) alguna solució
             if (movimentsUndoStack->index()>0){
             progres.setValue(movimentsUndoStack->index()-1);}
             //qDebug("movimentsUndoStack if %d",movimentsUndoStack->index()-1);}
             //return;}
             //qDebug("movimentsUndoStack inici %d",movimentsUndoStack->index()-1);
             //progres.setValue(0);
             progres.setVisible(true);
             progres.setLabelText(missatgeNumeroMoviments());
             qApp->processEvents();

             int numMovimentsPerReiniciar=taulerJoc->numeroDeMovimentsJoc()*3;
             int numeroFitxesMajorConfigEliminada=0;
             int numeroMovimentsProvats=0;

             int contadorSenseMoviments=0;
             int maximNombreIntentsSenseMoviment=400;//qMin(taulerJoc->numeroDeMovimentsJoc()*4,200);
             bool reinicia=false;
        //int contador=0;
          while (jocResolt !=2){
              /*Calcul i selecció dels moviments que es poden realitzar
               * segons la seva prioritat i els conserva a solucionaJocActual_movimentsPosiblesActuals */
              if (comprovaExisteixenMovimentsPossibles()){
                // qDebug("Hi ha moviments possibles");
              }
              //contador++;
              //qDebug("contador %d", contador);
              QString configAct=taulerJoc->configuracioActual();
              /*Aquesta condició és decisiva en el sistema de recerca de sol.
               *Afegida la condició del número de moviments del joc
               *degut a les modalitats amb un número de fitxes finals
               *major a 1
               */
              if (solucionaJocActual_movimentsPosiblesActuals.count()==0){contadorSenseMoviments++;
              //qDebug("contadorSenseMoviments %d",contadorSenseMoviments);
              }
              /* Si es compleixen les condicions per fer un moviment, es fa*/
              if ((solucionaJocActual_movimentsPosiblesActuals.count()>0) && (jocResolt ==0)
                  && !(solucioJocActual_configuracionsEliminades.contains(configAct))
                    /*aquest procediment no és eficient
                   amb les modalitats inverses. Es retorna sempre false en aquestes
                   modalitats 25/01/13 */
                   && !(taulerJoc->solucionaJocActual_FitxesAillades2())
                   && ( (movimentsUndoStack->index()-1)<taulerJoc->numeroDeMovimentsJoc())
                   && ( taulerJoc->ocuparFitxesFinalJoc() )
                   ){
                  int numeroItem=0;
                 // qDebug("solucionaJocActual_movimentsPosiblesActuals %d",solucionaJocActual_movimentsPosiblesActuals.count());
                  /*Si hi ha més d'un moviment propossat, elegim un a l'atzar*/
                  if (solucionaJocActual_movimentsPosiblesActuals.count()>1){
                    //rellotgeQTime s'ha posat al principi del programa. És vigent per cada fil!
                    qsrand(rellotgeQTime.msecsTo(QTime::currentTime()));
                    numeroItem=qrand() % (solucionaJocActual_movimentsPosiblesActuals.count());
                  }
                  /*Executam el moviment seleccionat*/
                  QStringList  movimentsItem=
                       QStringList(solucionaJocActual_movimentsPosiblesActuals.value(
                                   numeroItem).split(" "));
                  taulerJoc->ferMoviment(movimentsItem.value(0).toInt()
                                         ,movimentsItem.value(1).toInt(),movimentsItem.value(2).toInt());
                 // qDebug("executat moviment! %d", numeroMovimentsProvats);
                  ++numeroMovimentsProvats;
                  progres.setValue(movimentsUndoStack->index()-1);
                  progres.setLabelText(missatgeNumeroMoviments(taulerJoc->numeroDeMovimentsJoc()));
                  qApp->processEvents();

                  solucionaJocActual_darrerMoviment=QString("%1 ").arg(movimentsUndoStack->index());
                  solucionaJocActual_darrerMoviment.append(
                              solucionaJocActual_movimentsPosiblesActuals.value(numeroItem));
                  solucionaJocActual_movimentsJaRealitzats.append(
                                    solucionaJocActual_darrerMoviment);
                  //qCritical("%s", qPrintable(solucionaJocActual_darrerMoviment));

               }
              /* No es compleixen les condicions per fer un moviment*/
              else {
                  /* Hi ha moviments fets*/
                  if (movimentsUndoStack->index() !=0 ){
                      jocResolt=0;
                       taulerJoc->eliminaFitxesVermelles();
                     // QString configAct=taulerJoc->configuracioActual();
                        numeroFitxesMajorConfigEliminada=qMax(numeroFitxesMajorConfigEliminada,
                                                              numeroConfiguracio(configAct));
                        /* 09/02/13 Afegida la condició del 5 degut a què
                         * s'afegien configuracions de final de joc
                         */
                        /* S'afageix la posició  actual de les fitxes en les configuracions eliminades
                         * i es farà reiniciar el joc */
                        if ( (!solucioJocActual_configuracionsEliminades.contains(configAct)) &&
                              !configAct.contains("5")){
                          /* Aqui cal eliminar les configuracions posteriors de
                           * solucioJocActual_configuracionsEliminades */
                          solucionaJocActual_eliminaConfiguracionsPosteriors(configAct);
                          if( !solucioJocActual_configuracionsEliminadesPerDesar.contains(configAct)){
                             solucioJocActual_configuracionsEliminadesPerDesar.append(configAct);
                          }
                          solucioJocActual_configuracionsEliminades.prepend(configAct);
                          reinicia=true;
                        }

                      if ( (solucionaJocActual_movimentsEliminats.indexOf(solucionaJocActual_darrerMoviment)==-1 ) &&
                           !(solucionaJocActual_darrerMoviment.isEmpty()) ){
                          solucionaJocActual_eliminaMovimentsPosteriors();
                          solucionaJocActual_movimentsEliminats.append(solucionaJocActual_darrerMoviment);
                      }

                      /* Es tornen enrrera el nombre de moviments seleccionats a l'atzar */
                      int contadorMovimentsRevertits=0;
                      int movimentsARevertir=qrand() % 4; //(qMin(taulerJoc->comptadorFitxesJoc,4));
                             // qrand() % 5;
                      while (contadorMovimentsRevertits< movimentsARevertir){
                       movimentsUndoStack->undo();
                       contadorMovimentsRevertits++;
                      /* qDebug("contadorMovimentsRevertits %d", contadorMovimentsRevertits);*/
                      /* qDebug("movimentsUndoStack %d", movimentsUndoStack->count());*/
                      progres.setValue(movimentsUndoStack->index()-1);
                      progres.setLabelText(missatgeNumeroMoviments(taulerJoc->numeroDeMovimentsJoc()));
                      if (solucionaJocActual_movimentsJaRealitzats.size()>0){
                          solucionaJocActual_movimentsJaRealitzats.removeAt
                                  (solucionaJocActual_movimentsJaRealitzats.size()-1);
                        }
                      qApp->processEvents();
                      }
                      solucionaJocActual_darrerMoviment=solucionaJocActual_movimentsJaRealitzats.value(
                              solucionaJocActual_movimentsJaRealitzats.size()-contadorMovimentsRevertits);

                      /* S'aplica el procediment més lent de la versió 2.0*/
                          if (cercaSolucioAPartirDeMovimentsInicials &&
                             // (contadorSenseMoviments>maximNombreIntentsSenseMoviment) &&
                              ( reinicia ) &&
                               retrocedeixMoviment != 0
                              && ((numeroMovimentsProvats % numMovimentsPerReiniciar) == 0)
                                  ){
                              contadorSenseMoviments=0;
                              maximNombreIntentsSenseMoviment--;
                              /* Es retorna a la posició de fitxes inicials*/
                              int contadorRetroces=0;
                              while (movimentsUndoStack->canRedo() && contadorRetroces<retrocedeixMoviment){
                                  movimentsUndoStack->undo();
                                  contadorRetroces++;
                                 progres.setValue(movimentsUndoStack->index()-1);
                                 progres.setLabelText(missatgeNumeroMoviments(taulerJoc->numeroDeMovimentsJoc()));
                                 if (solucionaJocActual_movimentsJaRealitzats.size()>0){
                                     solucionaJocActual_movimentsJaRealitzats.removeAt
                                             (solucionaJocActual_movimentsJaRealitzats.size()-1);
                                   }
                                 qApp->processEvents();
                              }
                             /* iniciSolucioSlot();
                              solucionaJocActual_movimentsJaRealitzats.clear();
                              solucionaJocActual_darrerMoviment.clear();*/
                              progres.setValue(0);
                              progres.setLabelText(missatgeNumeroMoviments(taulerJoc->numeroDeMovimentsJoc()));
                              reinicia=false;
                             // qDebug("procediment 2.0");
                          }
                          /*S'aplica el nou procediment més ràpid de la versió 2.1
                           *(que no conserva els moviments inicials)*/
                          else if ((!cercaSolucioAPartirDeMovimentsInicials)
                                   && (contadorSenseMoviments>maximNombreIntentsSenseMoviment)
                                   ){
                          //qDebug("/* Càrrega de nova solució */");
                          contadorSenseMoviments=0;
                          /* Cada vegada que es carregui de nou una solució,
                           * la pròxima es farà més aviat*/
                          maximNombreIntentsSenseMoviment--;
                          maximNombreIntentsSenseMoviment=qMax(maximNombreIntentsSenseMoviment,30);
                         // qDebug("maximNombreIntentsSenseMoviment %d", maximNombreIntentsSenseMoviment);
                             iniciSolucioSlot();
                             solucionaJocActual_movimentsJaRealitzats.clear();
                             solucionaJocActual_darrerMoviment.clear();
                             progres.setValue(0);
                             progres.setLabelText(missatgeNumeroMoviments(taulerJoc->numeroDeMovimentsJoc()));
                             /* carrega d'una nova solució*/
                             solucionaJocActual_carregaSolucio1();
                            // qDebug("procediment 2.1");
                             //reinicia=false;
                          }
                         //}
                 }//final if movimentsUndoStack->index() !=0
                 else{ //movimentsUndoStack->index() ==0
                      progres.cancel();
                      //27/01/11
                      //Això pot ésser que millori el tema dels problemes
                      //en què el programa no aconsegueix trobar la solució
                     solucionaJocActual_movimentsEliminats.clear();
                     statusBar()->showMessage(tr("No ha estat possible trobar una solució!"));
                     /*04/02/11
                       Pareix que això disminueix la freqüència en què el programa
                       no aconsegueix trobar la solució al joc
                       */
                     eliminaArxiuConfgEliminades();
                     // desaConfiguracionsEliminades();

                     /* 06/02/11
                        Això evita que no es trobi una solució
                        Continuam amb la recerca de solució
                        */
                     if (intentsSolucio<4){
                         //qDebug("Intents de solució %d",intentsSolucio );
                         //Algunes vegades, el rellotge es queda aturat
                         //Això ho soluciona?
                         rellotgeLabel->reIniciaRellotge();
                         //qDebug("intentsSolucio %d", intentsSolucio);
                         intentsSolucio++;
                         movimentsUndoStack->clear();
                         //iniciSolucioSlot();
                         solucionaJocActual_movimentsEliminats.clear();
                         solucionaJocActual_Inicia();
                         }
                     /*En el cas del solitaris generats a l'atzar
                      *si no troba solució, forçam la càrrega de la solució
                      *(la condició és necessària degut al plantejament de "problemes"
                      *d'altres modalitats de solitari)
                      */
                     else if ( solitariAtzar_esAtzar(
                          arbreModalitatsJocTreeWidget->selectedItems().first()->text(1)) ){
                         //Seleccionam un ítem de solució a l'atzar
                         qsrand(rellotgeQTime.msecsTo(QTime::currentTime()));
                         int itemSeleccionat=
                             qrand() % arbreSolucionsTreeWidget->topLevelItemCount();
                         QTreeWidgetItem *item= arbreSolucionsTreeWidget->
                                         topLevelItem(itemSeleccionat);
                         arbreSolucionsTreeWidget->setCurrentItem(item);
                         carregaSolucio1();
                         rellotgeLabel->aturaRellotge();
                       }

                rellotgeLabel->aturaRellotge();
                return;
                  }
              }
              if (progres.wasCanceled()){
                   rellotgeLabel->aturaRellotge();
                   desaConfiguracionsEliminades(1);
                   solucionaJocActual_movimentsJaRealitzats.clear();
                   solucionaJocActual_movimentsEliminats.clear();
                  break;}
             }//final while inicial


                /* S'ha trobat una solució*/
                if (jocResolt==2){
                    rellotgeLabel->aturaRellotge();
                    //qDebug("contadorSenseMoviments %d",contadorSenseMoviments);
                    progres.cancel();
                    desaSolucions();
                 //   qDebug("num conf eliminades %d", solucioJocActual_configuracionsEliminades.count());
                 //   qCritical("temps %s ", qPrintable(rellotgeLabel->retornaTemps(1)));
                    desaConfiguracionsEliminades(1);
                    solucionaJocActual_movimentsJaRealitzats.clear();
                    solucionaJocActual_movimentsEliminats.clear();
                    retrocedeixMoviment=0;
                    veureSolucionsSlot();
                    intentsSolucio=0;
                    /* Si es tracta d'un solitari personalitzat
                     * o bé és un joc modificat (de l'arbre de jocs
                     * del programa o de l'arbre de jocs personalitzats)
                     * es desen les dades
                     */
                    solucioJocActual_desarJocPersonalitzat();
//                    if( (solitariPersonalitzat_esPersonalitzat(
//                        arbreModalitatsJocTreeWidget->selectedItems().first()->text(1))
//                        && arbreJocsActual()==0 )
//                        || ( taulerJoc->solitariPersonalitzat() ) ||
//                            ( taulerJoc->solitariModificat() ) ){
//                        //){
//                       // && (tipusJocActual==0 || arbreJocsActual()==1 ) ){
//                       solitariPersonalitzat_desarSolitari();
//                    }

                  //Comentar les 3 següents linies per evitar la repetició de recerca de solució
                   /*   iniciSolucioSlot();
                         if(taulerJoc->estatDelJoc()==solucio){movimentsUndoStack->clear();}
                         solucionaJocActual_Inicia();*/
                     return;
                }//final if jocResolt==2
}

//Desa les dades del joc personalitzat/modificat a l'arxiu games_per.dat
//i l'afageix a l'arbre de jocs personalitzats
void frmPrincipal::solucioJocActual_desarJocPersonalitzat(){
    if( (solitariPersonalitzat_esPersonalitzat(
        arbreModalitatsJocTreeWidget->selectedItems().first()->text(1))
        && arbreJocsActual()==0 )
        || ( taulerJoc->solitariPersonalitzat() ) ||
            ( taulerJoc->solitariModificat() ) ){
        //){
       // && (tipusJocActual==0 || arbreJocsActual()==1 ) ){
       solitariPersonalitzat_desarSolitari();
    }
}

void frmPrincipal::solucionaJocActual_eliminaMovimentsPosteriors(){
    QStringList  *darrerMoviment =new QStringList(solucionaJocActual_darrerMoviment.split(" "));
    QStringList  *darrerMovimentEliminat=new QStringList(solucionaJocActual_movimentsEliminats.value(
            solucionaJocActual_movimentsEliminats.size()-1).split(" "));
    while (darrerMovimentEliminat->value(0).toInt()>darrerMoviment->value(0).toInt()){
        solucionaJocActual_movimentsEliminats.removeAt(solucionaJocActual_movimentsEliminats.size()-1);
        darrerMovimentEliminat->clear();
        darrerMovimentEliminat->append(solucionaJocActual_movimentsEliminats.value(
            solucionaJocActual_movimentsEliminats.size()-1).split(" "));
    }
    delete(darrerMoviment);
    delete(darrerMovimentEliminat);
}

void frmPrincipal::solucionaJocActual_eliminaConfiguracionsPosteriors(QString config){

   if (solucioJocActual_configuracionsEliminadesPerDesar.count()==0){
        return;}
  int numConfiguracio=numeroConfiguracio(config);
  if(taulerJoc->p_tipusMoviment !=2){
    while ( (numeroConfiguracio(solucioJocActual_configuracionsEliminadesPerDesar.value(
            solucioJocActual_configuracionsEliminadesPerDesar.count()-1))<numConfiguracio) &&
            (solucioJocActual_configuracionsEliminadesPerDesar.count()>0) ){
    solucioJocActual_configuracionsEliminadesPerDesar.removeLast();} 
  }
  else{
      while ( (numeroConfiguracio(solucioJocActual_configuracionsEliminadesPerDesar.value(
            solucioJocActual_configuracionsEliminadesPerDesar.count()-1))>numConfiguracio) &&
            (solucioJocActual_configuracionsEliminadesPerDesar.count()>0) ){
    solucioJocActual_configuracionsEliminadesPerDesar.removeLast();}
  }
}

/*Retorna el nombre de fitxes del joc*/
int frmPrincipal::solucionaJocActual_numeroDeFitxesDelJoc(){
    QString configActual=taulerJoc->configuracioActual(true);
    int numeroFitxesJoc;
    if (taulerJoc->p_tipusMoviment==2){
     numeroFitxesJoc=configActual.count("0")+movimentsUndoStack->count();
    }
    else numeroFitxesJoc=configActual.count("1")+movimentsUndoStack->count();
    return numeroFitxesJoc;
}

void frmPrincipal::solucionaJocActual_RecercaIterativa_ExhaustivaInici(int numFitxesInicialsJoc,
                                                                       int mantenirMoviment){
//   qDebug("RecercaIterativa_ExhaustivaInici 2.1");

//Cal saber si és un joc personalitzat
solucionaJocActual_ControlJocPersonalitzatModificat();

    /*eliminam l'arxiu de moviments .movi per fer el seguiment del joc*/
    //eliminaArxiuMovimentsJoc();
    qApp->processEvents();
    QProgressDialog *progresRecercaExahustiva =new QProgressDialog(this);;
    progresRecercaExahustiva->setLabelText(tr("Cercant solució"));
    progresRecercaExahustiva->setCancelButtonText(tr("Atura"));
    progresRecercaExahustiva->setMinimum(0);
//    progresRecercaExahustiva->setMaximum(taulerJoc->numeroDeMovimentsJoc()+retrocedeixMoviment);
    progresRecercaExahustiva->setMaximum(numFitxesInicialsJoc);
    progresRecercaExahustiva->setParent(this);
    qApp->processEvents();
    progresRecercaExahustiva->setWindowModality(Qt::WindowModal);
    progresRecercaExahustiva->setVisible(true);    
    rellotgeLabel->iniciaRellotge();
    qApp->processEvents();
    int intentsSolucio=0;
    int numeroMaximDeIntents=500;


    while( (jocResolt !=2)  && (!progresRecercaExahustiva->wasCanceled()) &&
           (intentsSolucio<numeroMaximDeIntents) ){
        intentsSolucio++;
//        qDebug("intentsSolucio++ %d", intentsSolucio);
        iniciSolucioSlotIndex(retrocedeixMoviment);
        //Jocs en diagonal
        if( taulerJoc->p_tipusMoviment==3){
           //Especial Solitari Estrella
           if(numFitxesInicialsJoc==23 || numFitxesInicialsJoc<15){
//               qDebug("diagonal");
             progresRecercaExahustiva->setMaximum(numFitxesInicialsJoc);
             taulerJoc->solucionaJocActual_CalculaArbreJoc(progresRecercaExahustiva, numFitxesInicialsJoc,
                                                           mantenirMoviment);}
           else {
               //Això és una mica estrany, però evita un problema amb el joc Anglès Antic
               //amb final marcat
//               qDebug("sdsds");
               progresRecercaExahustiva->setMaximum(numFitxesInicialsJoc);
               solucionaJocActual_RecercaIterativa_Exhaustiva1(progresRecercaExahustiva,
                                                                numFitxesInicialsJoc);
           }
        }
        //Jocs amb final marcat que no es poden resoldre sense carregar solucions
        //(només son un parell jocs!)
        else if (taulerJoc->jocAmbFinalMarcat()>10){
//            qDebug("aqui 2");
           taulerJoc->maximNombreDeProves=1000;
           progresRecercaExahustiva->setMaximum(numFitxesInicialsJoc);
           taulerJoc->solucionaJocActual_CalculaArbreJocComplet_Selectiu(progresRecercaExahustiva,
                                                                           numFitxesInicialsJoc,
                                                                           mantenirMoviment);
           taulerJoc->jocsRealitzats=0;
           taulerJoc->continuar=true;
        }
        //Jocs amb final marcat amb menys de 10 fitxes finals
        //i més d'una (no es fa servir)
        else if (taulerJoc->jocAmbFinalMarcat()<=10 &&
                taulerJoc->jocAmbFinalMarcat()>1 ){
//            qDebug("aqui 1");
            progresRecercaExahustiva->setMaximum(numFitxesInicialsJoc);
            solucionaJocActual_RecercaIterativa_Exhaustiva1(progresRecercaExahustiva,
                                                              numFitxesInicialsJoc);
        }
        else if (
                ((numFitxesInicialsJoc>20 && numFitxesInicialsJoc<=28) //28
                 || (numFitxesInicialsJoc<16))
                 && (taulerJoc->jocAmbFinalMarcat()==0)
                 ){
            //això funciona!
//            qDebug("sense final marcat");
            progresRecercaExahustiva->setMaximum(numFitxesInicialsJoc);
            taulerJoc->solucionaJocActual_CalculaArbreJoc(progresRecercaExahustiva, numFitxesInicialsJoc,
                                                          mantenirMoviment);
        }
        //La majoria de jocs de tipus clàssic i europeu
        //Inclou els jocs amb 1 fitxa final marcada
        else if ( (numFitxesInicialsJoc>15 && numFitxesInicialsJoc<40)
                 || (taulerJoc->jocAmbFinalMarcat()>0)){
//            qDebug("aqui");
            if(numFitxesInicialsJoc<=35){//25
             taulerJoc->maximNombreDeProves=1000;}
             progresRecercaExahustiva->setMaximum(numFitxesInicialsJoc);
             taulerJoc->solucionaJocActual_CalculaArbreJocComplet_Selectiu(progresRecercaExahustiva,
                                                                           numFitxesInicialsJoc,
                                                                           mantenirMoviment);
//            qDebug("jocsRealitzats %d", taulerJoc->jocsRealitzats);
            taulerJoc->jocsRealitzats=0;
            taulerJoc->continuar=true;
        }
        //Jocs amb més de 40 moviments
        else solucionaJocActual_RecercaIterativa_Exhaustiva1(progresRecercaExahustiva,
                                                             numFitxesInicialsJoc);
    }//final while

    if (jocResolt==2){
        progresRecercaExahustiva->cancel();
        progresRecercaExahustiva->setVisible(false);
        rellotgeLabel->aturaRellotge();
//        qCritical("%s",qPrintable(rellotgeLabel->retornaTemps(1)));
        qApp->processEvents();
        desaSolucions1();
       // retrocedeixMoviment=0;
        veureSolucionsSlot();
        /* Si es tracta d'un solitari personalitzat
         * o bé és un joc modificat (de l'arbre de jocs
         * del programa o de l'arbre de jocs personalitzats)
         * es desen les dades
         */
        solucioJocActual_desarJocPersonalitzat();
    }
    else {
      if(retrocedeixMoviment>0){
      //Retorna las fitxes a la posició inicial
       movimentsUndoStack->setIndex(retrocedeixMoviment);
      }
      //Un darrer intent de resoldre el joc carregant solucions
      if(!progresRecercaExahustiva->wasCanceled()){
         progresRecercaExahustiva->cancel();
         if(comprovaArxiuDeSolucions()){
            retrocedeixMoviment=0;
            solucionaJocActual_carregaSolucio();
            solucionaJocActual_Inicia();
        }
        else {
           rellotgeLabel->aturaRellotge();
           statusBar()->showMessage(tr("No ha estat possible trobar una solució!"));
         }
      }
      else {
        rellotgeLabel->aturaRellotge();
        progresRecercaExahustiva->cancel();
        statusBar()->showMessage(tr("No ha estat possible trobar una solució!"));
      }

    }
}

// Finalment, no es fa servir
//void frmPrincipal::solucionaJocActual_RecercaIterativa_Exhaustiva(QProgressDialog *progres, int profunditat,
//                                                                  int numeroInicialFitxesJoc,
//                                                                  variables_recerca_solucio variablesSolucio){
//  /* Carregam els moviments inicials*/
//  profunditat++;
////  taulerJoc->solucionaJocActual_CalculaMovimentsPosibles();
//  QStringList solucionaJocActual_movimentsPosiblesActuals1;
//  /* Carregam els moviments seleccionats per la posició actual de les fitxes*/
//  if(taulerJoc->p_tipusMoviment==3 && taulerJoc->numeroDeMovimentsJoc()>30){
//  solucionaJocActual_movimentsPosiblesActuals1.append(
//    taulerJoc->solucionaJocActual_CarregaMovimentsArbre4(numeroInicialFitxesJoc));
////    taulerJoc->solucionaJocActual_CarregaMovimentsArbre2(numeroInicialFitxesJoc,variablesSolucio));
//  }
//  /*Solitari estrella*/
//  else if(taulerJoc->p_tipusMoviment==3 && taulerJoc->numeroDeMovimentsJoc()<=30){
//  solucionaJocActual_movimentsPosiblesActuals1.append(
//    taulerJoc->solucionaJocActual_CarregaMovimentsArbre3(numeroInicialFitxesJoc,variablesSolucio));
//  }
//  else if (taulerJoc->numeroDeMovimentsJoc()<15){
//      solucionaJocActual_movimentsPosiblesActuals1.append(
//      taulerJoc->solucionaJocActual_CarregaMovimentsArbre2(numeroInicialFitxesJoc,variablesSolucio));
//  }
//  else solucionaJocActual_movimentsPosiblesActuals1.append(
//              taulerJoc->solucionaJocActual_CarregaMovimentsArbre2(numeroInicialFitxesJoc,variablesSolucio));

//  if(jocResolt == 2){
//    qDebug("El joc està resolt");
//    progres->cancel();
//  }
//  else {
//  /*Fins que el joc no estigui resolt o bé s'aturi la recerca, es repeteix el mateix
//   * procediment*/
//  while ( (jocResolt != 2)
//        && (solucionaJocActual_movimentsPosiblesActuals1.count()>0)
//        && (!progres->wasCanceled())
//        ){

//   bool fetMoviment=false;
//   int contadorMoviments=0;
//   for(int i=0;i<solucionaJocActual_movimentsPosiblesActuals1.count();i++){
////   for(int i=0;i<nombreDeMoviments;i++){
//      /*Seleccionam un dels moviments i el realitzam*/
//      int movimentSeleccionat=qrand() % solucionaJocActual_movimentsPosiblesActuals1.count();
//      QStringList movimentsItem=QStringList(solucionaJocActual_movimentsPosiblesActuals1
//       .value((movimentSeleccionat+i) % solucionaJocActual_movimentsPosiblesActuals1.count()).split(" "));

//      fetMoviment=false;
//      if ((jocResolt != 2) && (!progres->wasCanceled()) ){
//          if  (i==0 ){
//          fetMoviment=taulerJoc->ferMoviment2(movimentsItem.value(0).toInt()
//                        ,movimentsItem.value(1).toInt(),movimentsItem.value(2).toInt());
//          }
//          else if (
//           (taulerJoc->numeroDeMovimentsJoc()>15 && movimentsUndoStack->index()<40) //movimentsUndoStack->index()<28)
//                   ){
//           fetMoviment=taulerJoc->ferMoviment2(movimentsItem.value(0).toInt()
//                     ,movimentsItem.value(1).toInt(),movimentsItem.value(2).toInt());
//          }
//      /*Eliminam el moviment que no funciona (per evitar la repetició)*/
//        if(fetMoviment ){
//           contadorMoviments++;
//           if  (i==0 ){
//           solucionaJocActual_movimentsPosiblesActuals1.
//             removeAt((movimentSeleccionat+i) % solucionaJocActual_movimentsPosiblesActuals1.count());
//           }
//           else if (taulerJoc->numeroDeMovimentsJoc()>15 && movimentsUndoStack->index()<40)
//                  {
//           solucionaJocActual_movimentsPosiblesActuals1.
//             removeAt((movimentSeleccionat+i) % solucionaJocActual_movimentsPosiblesActuals1.count());
//           }
//        }
//      }
//   progres->setValue(movimentsUndoStack->count());
//   progres->setLabelText(missatgeNumeroMoviments(progres->maximum()));
//   qApp->processEvents();
//   }
//   //qDebug("contador %d", contadorMoviments);
//   /*Si el joc segueix sense està resolt i no s'ha cancel·lat la recerca
//    * es segueix amb la recerca iterativa*/
//   if( (jocResolt != 2) && (!progres->wasCanceled()) ){
//     solucionaJocActual_RecercaIterativa_Exhaustiva(progres, profunditat,numeroInicialFitxesJoc,variablesSolucio);
//   }


//   /*Si el codi torna aquí, llavors tornam enrera el moviment*/
//   if( (jocResolt != 2) && (!progres->wasCanceled())){
//      for(int i=0;i<contadorMoviments;i++){
//        movimentsUndoStack->undo();
//      }
////     movimentsUndoStack->undo();
//     progres->setValue(movimentsUndoStack->index());
//     progres->setLabelText(missatgeNumeroMoviments(progres->maximum()));
//     qApp->processEvents();
//    }

//   /*Si no queden més moviments per provar, cancel·lam la recerca*/
////   if(solucionaJocActual_movimentsPosiblesActuals1.count()<1){
////     //qDebug("Joc cancelat per manca de moviments*****");
////     //progres->cancel();
////   }
//   if (progres->wasCanceled()){
//        rellotgeLabel->aturaRellotge();
//        qApp->processEvents();
//       break;}
//  }//final del while

///*El joc està resolt. Asseguram que el progres queda tancat*/
//  if(jocResolt == 2){
//    //qDebug("El joc està resolt");
//    progres->cancel();
//  }
// }
//}

void frmPrincipal::solucionaJocActual_RecercaIterativa_Exhaustiva1(QProgressDialog *progres,
                                                                   int numeroFitxesJoc){

  /* Carregam els moviments inicials*/
  QStringList solucionaJocActual_movimentsPosiblesActuals1;
  /* Carregam els moviments seleccionats per la posició actual de les fitxes*/
  solucionaJocActual_movimentsPosiblesActuals1.append(
    taulerJoc->solucionaJocActual_CarregaMovimentsArbre4(numeroFitxesJoc));

  /*Fins que el joc no estigui resolt o bé s'aturi la recerca, es repeteix el mateix
   * procediment*/
  while ( (jocResolt != 2)
        && (solucionaJocActual_movimentsPosiblesActuals1.count()>0)
        && (!progres->wasCanceled()
        /*&& taulerJoc->ocuparFitxesFinalJoc()*/)
        ){
   /*Seleccionam un dels moviments i el realitzam*/
//   int movimentSeleccionat=0;
   int movimentSeleccionat=qrand() % solucionaJocActual_movimentsPosiblesActuals1.count();
   QStringList movimentsItem=QStringList(solucionaJocActual_movimentsPosiblesActuals1
               .value((movimentSeleccionat) % solucionaJocActual_movimentsPosiblesActuals1.count()).split(" "));
   bool movimentFet=taulerJoc->ferMoviment2(movimentsItem.value(0).toInt()
                           ,movimentsItem.value(1).toInt(),movimentsItem.value(2).toInt());
//   if(movimentFet){
   solucionaJocActual_movimentsPosiblesActuals1.
               removeAt((movimentSeleccionat) % solucionaJocActual_movimentsPosiblesActuals1.count());/*}*/
//   progres->setValue(movimentsUndoStack->count());
   if(movimentsUndoStack->index()<progres->maximum()){
   progres->setValue(movimentsUndoStack->index());
   progres->setLabelText(missatgeNumeroMoviments(progres->maximum()));
   }
//   progres->setLabelText(missatgeNumeroMoviments(numeroFitxesJoc-1));
   qApp->processEvents();
   /*Si el joc segueix sense estar resolt i no s'ha cancel·lat la recerca
    * es segueix amb la recerca iterativa*/
   if( (jocResolt != 2) && (!progres->wasCanceled()) ){
     solucionaJocActual_RecercaIterativa_Exhaustiva1(progres,
                                                     numeroFitxesJoc);
   }

   /*Si el codi torna aquí, llavors tornam enrera el moviment*/
   if( (jocResolt != 2) && (!progres->wasCanceled()) && movimentFet){
     movimentsUndoStack->undo();
//     progres->setValue(movimentsUndoStack->count());
//     progres->setValue(movimentsUndoStack->index());
//     progres->setLabelText(missatgeNumeroMoviments(progres->maximum()));
     qApp->processEvents();
   }

   if (progres->wasCanceled()){
//       progres->setVisible(false);
       rellotgeLabel->aturaRellotge();
       qApp->processEvents();
       break;}
  }//final del while

/*El joc està resolt. Asseguram que el progrés queda tancat*/
  if(jocResolt == 2){
    //qDebug("El joc està resolt");
//    progres->setVisible(false);
    progres->cancel();
  }
}


//variables_recerca_solucio frmPrincipal::solucioJocActual_carregaVariablesCercaSolucio(int numeroInicialFitxesJoc){
// variables_recerca_solucio variablesRecercaSolucio;
// if(taulerJoc->p_tipusMoviment==3){ //moviment diagonal
//   variablesRecercaSolucio.maximNumeroDeConjunts=6;
//   variablesRecercaSolucio.maximNumeroDeFitxesAillades=2;//2
//   variablesRecercaSolucio.minimIndexDeMoviments=40;//15
//   variablesRecercaSolucio.minimNumeroDeConjuntsActual=3;//3
//   variablesRecercaSolucio.minimNumeroDeFitxesAilladesActual=2;//2
//   variablesRecercaSolucio.minimIndexMovimentsPerFiltrarMovimentsSeleccionats=40;
//   variablesRecercaSolucio.valorMinimIndexDeMovimentsPerMovimentsMassius=60;//60
//   variablesRecercaSolucio.valorMinimMovimentsJoc=15;
//   if(numeroInicialFitxesJoc<33){
//       variablesRecercaSolucio.maximNumeroDeConjunts=2;
//       variablesRecercaSolucio.maximNumeroDeFitxesAillades=1;
//       variablesRecercaSolucio.minimNumeroDeConjuntsActual=2;
//       variablesRecercaSolucio.minimNumeroDeFitxesAilladesActual=1;
//   }
// }
// else if(taulerJoc->p_tipusMoviment==1){ //moviment directe
//   if(numeroInicialFitxesJoc<18){//amb poques fitxes
//   variablesRecercaSolucio.maximNumeroDeConjunts=3;//<=
//   variablesRecercaSolucio.maximNumeroDeFitxesAillades=3;
//   variablesRecercaSolucio.minimIndexDeMoviments=0;//valor a partir del qual s'intenta trobar moviments
//   //que disminueixin el nombre de conjunts i/o de fitxes aïllades 5
//   variablesRecercaSolucio.minimNumeroDeConjuntsActual=1;//>3
//   variablesRecercaSolucio.minimNumeroDeFitxesAilladesActual=0;//>5
//   variablesRecercaSolucio.minimIndexMovimentsPerFiltrarMovimentsSeleccionats=20;//28
//   variablesRecercaSolucio.valorMinimIndexDeMovimentsPerMovimentsMassius=18;
//   variablesRecercaSolucio.valorMinimMovimentsJoc=0;
//   }
//   else if(numeroInicialFitxesJoc>40){//Wiegleb
//   variablesRecercaSolucio.maximNumeroDeConjunts=2;
//   variablesRecercaSolucio.maximNumeroDeFitxesAillades=1;
//   variablesRecercaSolucio.minimIndexDeMoviments=30;//valor a partir del qual s'intenta trobar moviments
//   //que disminueixin el nombre de conjunts i/o de fitxes aïllades 5
//   variablesRecercaSolucio.minimNumeroDeConjuntsActual=1;
//   variablesRecercaSolucio.minimNumeroDeFitxesAilladesActual=0;
//   variablesRecercaSolucio.minimIndexMovimentsPerFiltrarMovimentsSeleccionats=20;
//   variablesRecercaSolucio.valorMinimIndexDeMovimentsPerMovimentsMassius=0;//60
//   variablesRecercaSolucio.valorMaximIndexDeMovimentsPerMovimentsMassius=10;
//   variablesRecercaSolucio.valorMinimMovimentsJoc=15;
//   }

//   else if (numeroInicialFitxesJoc>38){// Diamant
//       variablesRecercaSolucio.maximNumeroDeConjunts=1;
//       variablesRecercaSolucio.maximNumeroDeFitxesAillades=1;//2
//       variablesRecercaSolucio.minimIndexDeMoviments=35;
//       variablesRecercaSolucio.minimNumeroDeConjuntsActual=3;//3
//       variablesRecercaSolucio.minimNumeroDeFitxesAilladesActual=2;//2
//       variablesRecercaSolucio.minimIndexMovimentsPerFiltrarMovimentsSeleccionats=10;//15
//       variablesRecercaSolucio.valorMinimIndexDeMovimentsPerMovimentsMassius=0;//60;
//       variablesRecercaSolucio.valorMinimMovimentsJoc=15;
////   variablesRecercaSolucio.maximNumeroDeConjunts=3;
////   variablesRecercaSolucio.maximNumeroDeFitxesAillades=2;
////   variablesRecercaSolucio.minimIndexDeMoviments=0;
////   variablesRecercaSolucio.minimNumeroDeConjuntsActual=2;
////   variablesRecercaSolucio.minimNumeroDeFitxesAilladesActual=0;
////   variablesRecercaSolucio.minimIndexMovimentsPerFiltrarMovimentsSeleccionats=40;
////   variablesRecercaSolucio.valorMinimIndexDeMovimentsPerMovimentsMassius=40;//30
////   variablesRecercaSolucio.valorMinimMovimentsJoc=15;
//   }
//   else if (numeroInicialFitxesJoc>33){// Europeu
//   variablesRecercaSolucio.maximNumeroDeConjunts=1;//2
//   variablesRecercaSolucio.maximNumeroDeFitxesAillades=0;//3
//   variablesRecercaSolucio.minimIndexDeMoviments=30;// 30 o 36
//   variablesRecercaSolucio.minimNumeroDeConjuntsActual=1;//>3
//   variablesRecercaSolucio.minimNumeroDeFitxesAilladesActual=0;
//   variablesRecercaSolucio.minimIndexMovimentsPerFiltrarMovimentsSeleccionats=30;
//   variablesRecercaSolucio.valorMinimIndexDeMovimentsPerMovimentsMassius=0;//30
//   variablesRecercaSolucio.valorMinimMovimentsJoc=15;
////   variablesRecercaSolucio.maximNumeroDeConjunts=2;//2
////   variablesRecercaSolucio.maximNumeroDeFitxesAillades=2;
////   variablesRecercaSolucio.minimIndexDeMoviments=15;//15 30
////   variablesRecercaSolucio.minimNumeroDeConjuntsActual=1;//>3
////   variablesRecercaSolucio.minimNumeroDeFitxesAilladesActual=0;
////   variablesRecercaSolucio.minimIndexMovimentsPerFiltrarMovimentsSeleccionats=0;
////   variablesRecercaSolucio.valorMinimIndexDeMovimentsPerMovimentsMassius=30;
////   variablesRecercaSolucio.valorMinimMovimentsJoc=15;
//    }
//   else{
//   variablesRecercaSolucio.maximNumeroDeConjunts=qMax(2,1+taulerJoc->solucionaJocActual_numeroFitxesAillades());
//   variablesRecercaSolucio.maximNumeroDeFitxesAillades=qMax(1,taulerJoc->solucionaJocActual_numeroFitxesAillades());
//   variablesRecercaSolucio.minimIndexDeMoviments=15;//valor a partir del qual s'intenta trobar moviments
//   //que disminueixin el nombre de conjunts i/o de fitxes aïllades 5
//   variablesRecercaSolucio.minimNumeroDeConjuntsActual=1;//>3
//   variablesRecercaSolucio.minimNumeroDeFitxesAilladesActual=qMax(0,taulerJoc->solucionaJocActual_numeroFitxesAillades());
//   variablesRecercaSolucio.minimIndexMovimentsPerFiltrarMovimentsSeleccionats=10;
//   if(numeroInicialFitxesJoc<30){
//     variablesRecercaSolucio.minimIndexMovimentsPerFiltrarMovimentsSeleccionats=10;
//   }
//   variablesRecercaSolucio.valorMinimIndexDeMovimentsPerMovimentsMassius=15;
//   variablesRecercaSolucio.valorMinimMovimentsJoc=15;
//   }
// }

//// qDebug("maximNumeroDeConjunts %d", variablesRecercaSolucio.maximNumeroDeConjunts);
//// qDebug("maximNumeroDeFitxesAillades %d", variablesRecercaSolucio.maximNumeroDeFitxesAillades);
//// qDebug("minimIndexDeMoviments %d", variablesRecercaSolucio.minimIndexDeMoviments);
//// qDebug("minimNumeroDeConjuntsActual %d", variablesRecercaSolucio.minimNumeroDeConjuntsActual);
//// qDebug("minimNumeroDeFitxesAilladesActual %d", variablesRecercaSolucio.minimNumeroDeFitxesAilladesActual);
//// qDebug("minimIndexMovimentsPerFiltrarMovimentsSeleccionats %d", variablesRecercaSolucio.minimIndexMovimentsPerFiltrarMovimentsSeleccionats);
//// qDebug("valorMaximIndexDeMovimentsPerMovimentsMassius %d", variablesRecercaSolucio.valorMaximIndexDeMovimentsPerMovimentsMassius);
//// qDebug("valorMinimIndexDeMovimentsPerMovimentsMassius %d", variablesRecercaSolucio.valorMinimIndexDeMovimentsPerMovimentsMassius);
//// qDebug("valorMinimMovimentsJoc %d", variablesRecercaSolucio.valorMinimMovimentsJoc);
// return variablesRecercaSolucio;
//}

/* Escriu el moviment realitzat en la recerca a un arxiu i a la finestra de sortides
 * del programa per facilitar el seguiment del joc
   No es fa servir però pot ésser útil */
void frmPrincipal::solucioJocActual_RecercaIterativa_escriuDesaMovimentRealitzat(int tabulacio,QString cadenaMoviment){
    QString buits;
    int contador=0;
    while(contador< tabulacio){
        buits.append(" ");
        contador++;
    }
    qCritical("%s",qPrintable(buits+cadenaMoviment));
    desaMovimentsJoc(buits+cadenaMoviment+QString("  %1").arg(tabulacio));
}

/* Retorna el nombre de 1 de la configuració de fitxes del joc
 * passada pel paràmetre*/
int frmPrincipal::numeroFitxesConfiguracioActualJoc(QString configuracioActual){
 return configuracioActual.count("1");
}

/*
  Busca una solució ha partir d'una altra solució
  */
void frmPrincipal::solucionaJocRapid(){

solitariPersonalitzat_dadesFitxes();

  /* Amb la modalitat de joc personalitzat, cal preveure
  *  la possibilitat que no hi hagi cap fitxa activa
  *   L'opció de jocResolt està afegida per evitar que no es pugui
  *   tornar a cercar una solució quan ja s'ha trobat una
  */
// if( (taulerJoc->numeroDeMovimentsJoc()<1) &&
//      (jocResolt==0)){
//     //No hi ha moviments
//     mostraMissatge(5);
//    // qDebug("numeroDeMovimentsJoc %d",taulerJoc->numeroDeMovimentsJoc());
//     return;
//   }
// else if(jocResolt==2){
//     iniciSolucioSlot();
//  }
// //sense això, el programa fracasa si s'ha aturat la cerca
// //en una situació sense moviments i es torna a intentar cercar
// else if (taulerJoc->numeroDeMovimentsJoc()<1 ){
//     //No hi ha moviments
//     mostraMissatge(5);
//   return;

// }
/* Controlam l'estat actual del joc:
   si ja està resolt (fitxes verdes), està finalitzat,
   sens moviments o és un joc personalitzat sense
   moviments, reiniciam el joc */
if(jocResolt==2
   ||
  (taulerJoc->numeroDeMovimentsJoc()<1 ||
    taulerJoc->jocFinalitzat())
  ||
  (taulerJoc->solitariPersonalitzat() &&
   taulerJoc->numeroDeMovimentsJoc()<1)
        ){
  iniciSolucioSlot();
  movimentsUndoStack->clear();
  iniciSolucioAction->setEnabled(movimentsUndoStack->canUndo());
}

//És possible que el joc no tengui moviments
//El jugador pot haver deixat una situació sense moviments
//o bé es un joc personalitzat/modificat que no te moviments
 taulerJoc->configuracioActual(true);
 if (taulerJoc->numeroDeMovimentsJoc()<1 ){
     //No hi ha moviments
     mostraMissatge(5);
   return;
 }

    solucionaJocActual_movimentsJaRealitzats.clear();
    solucionaJocActual_darrerMoviment.clear();
    //reiniciam els intents
    intentsSolucio=0;
    taulerJoc->setEstatDelJoc(solucio);
    jocResolt=0;
    /*Posa a zero el rellotge 01/01/11
      Si es clicava una segona vegada desprès d'obtenir
      una solució, llavors s'acumulava el temps*/
    if (!rellotgeLabel->rellotgeEnMarxa()){
      rellotgeLabel->estableixTemps(QString("00:00:00"));
      }

 cercaSolucioAPartirDeMovimentsInicials=false;

 qApp->processEvents();
 //Actualitzam el comptador de les fitxes del joc
 taulerJoc->configuracioActual(true);
 int numeroFitxesJoc=taulerJoc->numeroDeMovimentsJoc();
// int numeroFitxesJoc=solucionaJocActual_numeroDeFitxesDelJoc()-1;
// qDebug("numeroFitxesJoc %d", numeroFitxesJoc);

 if(comprovaExisteixenMovimentsPossibles()==0){
//  qDebug("sense moviments");
  //No hi ha moviments
  mostraMissatge(5);
  return;
 }

 /*Seleccionam el tipus de recerca a executar*/
 /* Si no hi ha moviments fets*/
 if(movimentsUndoStack->count()<1 ){
        //La majoria dels jocs amb final marcat i generats a l'atzar
        //només es resoldran amb el sistema
        //de la versió 2.1 (que intenta fer servir solucions ja trobades)
        //comprovaDadesSolucions() indica si es fa servir la versió 2.1
        //o la versió actual (poques modalitats es resolen amb aquesta opció)
        if(
           (taulerJoc->jocAmbFinalMarcat() && comprovaDadesSolucions()
           && taulerJoc->p_tipusMoviment != 3)
           ||
           (solitariAtzar_esAtzar(
              arbreModalitatsJocTreeWidget->selectedItems().first()->text(1)))
            ){
            retrocedeixMoviment=0;
            solucionaJocActual_carregaSolucio();
            solucionaJocActual_Inicia();
        }
         /*Si hi ha solucions anteriors*/
        else if(comprovaArxiuDeSolucions() && !taulerJoc->jocAmbFinalMarcat()){
          /*seleccionam a l'atzar el tipus de recerca*/
          int atzar= qrand() % 10;
          //Encara no hi ha un procediment eficaç per a moltes fitxes!
          if (atzar<5 || (numeroFitxesJoc>40 && taulerJoc->p_tipusMoviment != 3)
              ){
              /* Carrega i executa part dels moviments d'una solució */
              retrocedeixMoviment=0;
              solucionaJocActual_carregaSolucio();
              solucionaJocActual_Inicia();
          }
          else {
              solucionaJocActual_RecercaIterativa_ExhaustivaInici(numeroFitxesJoc);
          }
        }
        else {
            //No hi ha dades (de solucions) o és un joc personalitzat o modificat
            solucionaJocActual_RecercaIterativa_ExhaustivaInici(numeroFitxesJoc);
        }
    // }
   }//if(movimentsUndoStack->index()<1)

//Hi ha moviments fets i el joc està iniciat
else if((rellotgeLabel->rellotgeEnMarxa()) ){
   /*conservam l'índex del darrer moviment*/
//   qDebug("movimentsUndoStack->count() %d", movimentsUndoStack->count());
   retrocedeixMoviment=movimentsUndoStack->index();
   solucionaJocActual_RecercaIterativa_ExhaustivaInici(
               numeroFitxesJoc+retrocedeixMoviment,retrocedeixMoviment);
 }
/*Aqui no hauria d'arribat mai*/
else {
 gestioTipusDeJocASeleccionar();
 solucionaJocRapid();
 }
}

/* Soluciona el joc actual pel métode de la força
 * bruta. Deixa el resultat a un arxiu de tipus .arbre*/
void frmPrincipal::solucionaJoc_ForcaBruta(){

mostraMissatge(100);
//Eliminam l'arxiu arbre anterior
eliminaArxiu(5);
solucionsTrobades.clear();
carregaSolucions();

taulerJoc->setEstatDelJoc(solucio);
jocResolt=0;
int numFitxesInicialsJoc=taulerJoc->numeroDeMovimentsJoc();
//int numFitxesInicialsJoc=solucionaJocActual_numeroDeFitxesDelJoc();

qApp->processEvents();
QProgressDialog *progresRecercaExahustiva =new QProgressDialog(this);;
progresRecercaExahustiva->setLabelText(tr("Cercant solució"));
progresRecercaExahustiva->setCancelButtonText(tr("Atura"));
progresRecercaExahustiva->setMinimum(0);
//    progresRecercaExahustiva->setMaximum(taulerJoc->numeroDeMovimentsJoc()+retrocedeixMoviment);
progresRecercaExahustiva->setMaximum(numFitxesInicialsJoc);
progresRecercaExahustiva->setParent(this);
qApp->processEvents();
progresRecercaExahustiva->setWindowModality(Qt::WindowModal);
progresRecercaExahustiva->setVisible(true);
rellotgeLabel->iniciaRellotge();
qApp->processEvents();

//sistema de recerca exhaustiva
//taulerJoc->p_movimentsUndoStack->undo();
progresRecercaExahustiva->setMaximum(numFitxesInicialsJoc);
taulerJoc->jocsRealitzats=0;
taulerJoc->jocsAmbSolucio=0;
taulerJoc->solucionaJocActual_CalculaArbreJocComplet_Inici(progresRecercaExahustiva, numFitxesInicialsJoc);/*}*/
progresRecercaExahustiva->cancel();
rellotgeLabel->aturaRellotge();
iniciSolucioSlot();
QString missatge=QString("%1 %2 %3 %4").arg(rellotgeLabel->retornaTemps(1)+" ")
        .arg(taulerJoc->jocsRealitzats).
        arg(taulerJoc->jocsAmbSolucio).
        arg((double)taulerJoc->jocsAmbSolucio*100/taulerJoc->jocsRealitzats);
qCritical("%s",qPrintable(missatge));
//Finalment, es carregan totes les solucions. Les solucions
//no es carregan continuament degut a què el mètode
//no trobarà solucions repetides
//veureSolucionsSlot();
}

//void frmPrincipal::solucionaJoc_ForcaBruta(){

//mostraMissatge(100);
////Eliminam l'arxiu arbre anterior
//eliminaArxiu(5);
//solucionsTrobades.clear();
//carregaSolucions();

//taulerJoc->setEstatDelJoc(solucio);
//jocResolt=0;
//int numFitxesInicialsJoc=taulerJoc->numeroDeMovimentsJoc();
////int numFitxesInicialsJoc=solucionaJocActual_numeroDeFitxesDelJoc();

//qApp->processEvents();
//QProgressDialog *progresRecercaExahustiva =new QProgressDialog(this);;
//progresRecercaExahustiva->setLabelText(tr("Cercant solució"));
//progresRecercaExahustiva->setCancelButtonText(tr("Atura"));
//progresRecercaExahustiva->setMinimum(0);
////    progresRecercaExahustiva->setMaximum(taulerJoc->numeroDeMovimentsJoc()+retrocedeixMoviment);
//progresRecercaExahustiva->setMaximum(numFitxesInicialsJoc);
//progresRecercaExahustiva->setParent(this);
//qApp->processEvents();
//progresRecercaExahustiva->setWindowModality(Qt::WindowModal);
//progresRecercaExahustiva->setVisible(true);
//rellotgeLabel->iniciaRellotge();
//qApp->processEvents();

////sistema de recerca exhaustiva
////taulerJoc->p_movimentsUndoStack->undo();
//progresRecercaExahustiva->setMaximum(numFitxesInicialsJoc);
//taulerJoc->jocsRealitzats=0;
//taulerJoc->jocsAmbSolucio=0;
//taulerJoc->solucionaJocActual_CalculaArbreJocComplet_Inici(progresRecercaExahustiva, numFitxesInicialsJoc);/*}*/
//progresRecercaExahustiva->cancel();
//rellotgeLabel->aturaRellotge();
//iniciSolucioSlot();
//QString missatge=QString("%1 %2 %3").arg(taulerJoc->jocsRealitzats).
//        arg(taulerJoc->jocsAmbSolucio).
//        arg((double)taulerJoc->jocsAmbSolucio*100/taulerJoc->jocsRealitzats);
//qCritical("%s",qPrintable(missatge));
////Finalment, es carregan totes les solucions. Les solucions
////no es carregan continuament degut a què el mètode
////no trobarà solucions repetides
////veureSolucionsSlot();
//}

void frmPrincipal::solucionaJocActual_carregaSolucio(){
    if(movimentsUndoStack->index()==0){
        movimentsUndoStack->clear();
        //Primer carregam les solucions disponibles
        //06/02/13 nou prod.
        actualitzaConfiguracionsInicials();
        comprovaArxiuSolucions();
        carregaSolucions();
        /*Carregam la solució*/
        if  (solucionsTrobades.count()>0) {
            //Seleccionam una solució a l'atzar
            qsrand(rellotgeQTime.msecsTo(QTime::currentTime()));
            int selec=qrand() % (solucionsTrobades.count());
           /* qDebug("qrand() %d",qrand());
            qDebug("solució seleccionada %d",selec);
            qDebug("solucionsTrobades.count() %d",solucionsTrobades.count());*/
            QStringList movimentsSolucio=solucionsTrobades.value(selec).split(" ");
            /*02/02/11 Això és per controlar les solucions incorrectes
              (que no tenen el nombre de moviments corresponents al joc
              10/02/13 Pareix que això ja no passa mai
              21/08/16 Eliminat
              */
           /* while (movimentsSolucio.count() !=
              taulerJoc->numeroDeMovimentsJoc()*4){
              qCritical("%s", qPrintable(solucionsTrobades.value(selec)));
              solucionsTrobades.removeOne(solucionsTrobades.value(selec));
                //solucionsTrobades.removeAt(selec);
              desaSolucions();
             // qDebug("eliminada %d", selec);
              qsrand(rellotgeQTime.msecsTo(QTime::currentTime()));
              int selec=qrand() % (solucionsTrobades.count());
              movimentsSolucio=solucionsTrobades.value(selec).split(" ");
            }*/

            /*Ara seleccinam a l'atzar un número
             i es fan els moviments corresponents a la solució
             fins al número seleccionat
            */
            /* 02/01/13
             * Abans dividia per 8: si el joc tenia menys moviments,llavors
             * fallava (això pot passar en els jocs personalitzats
             * 21/08/16
             * Ara es reinicia el joc  de zero i taulerJoc->p_numMoviments
             * sempre es 0.
             * A més, s'ha eliminat la divisió per 4
             */
           // selec=qrand() % ((movimentsSolucio.count()/8));
            qsrand(rellotgeQTime.msecsTo(QTime::currentTime()));
            //selec=qrand() % ((movimentsSolucio.count()/4));
            selec=qrand() % ((movimentsSolucio.count()/4));
            //qDebug("selec %d",selec);
            //qDebug("taulerJoc->p_numMoviments %d",taulerJoc->p_numMoviments);
            selec=qMax(selec,taulerJoc->p_numMoviments);
            /*qDebug("movimentsSolucio.count() %d",movimentsSolucio.count()/4);
            qDebug("moviment seleccionat %d",selec);
            qDebug("****************************");*/
            QString mov;
            rellotgeLabel->iniciaRellotge();
           // qDebug("taulerJoc->p_numMoviments %d",taulerJoc->p_numMoviments);
            for(int i=0;i<(movimentsSolucio.count()/4);i++){
                if(i<(movimentsSolucio.count()/4)-selec){
                    taulerJoc->ferMoviment(movimentsSolucio.value(i*4+1).toInt(),
                                           movimentsSolucio.value(i*4+2).toInt(),
                                           movimentsSolucio.value(i*4+3).toInt());}

                if(i>taulerJoc->p_numMoviments){
                    mov=QString("%1 %2 %3 %4").
                            arg(movimentsSolucio.value(i*4)).
                            arg(movimentsSolucio.value(i*4+1)).
                            arg(movimentsSolucio.value(i*4+2)).
                            arg((movimentsSolucio.value(i*4+3)));
                    solucionaJocActual_movimentsEliminats.append(mov);
                 }
            }
        solucionaJocActual_darrerMoviment.append(mov);
        } /*Final de carregam la solució*/
    }//if inicial movimentsUndoStack->index()==0
    else cercaSolucioAPartirDeMovimentsInicials=true;
}

/* Carrega una solució i fa un nombre determinat de moviments
 * de la solució (tot seleccionat a l'atzar)
 * Es fa servir quan es supera el màxim de vegades que no
 * hi ha moviments possibles
 */
void frmPrincipal::solucionaJocActual_carregaSolucio1(){
    //if(movimentsUndoStack->index()==0){
        movimentsUndoStack->clear();
        //Primer carregam les solucions disponibles
        actualitzaConfiguracionsInicials();
       //21/04/17
       //Eliminades les dues linies següents per evitar que el progress
       //forci el focus en el programa
//        comprovaArxiuSolucions();
//        carregaSolucions();
        /*Carregam la solució*/
        if  (solucionsTrobades.count()>0) {
            //Seleccionam una solució a l'atzar
            qsrand(rellotgeQTime.msecsTo(QTime::currentTime()));
            int selec=qrand() % (solucionsTrobades.count());
            /*qDebug("qrand() %d",qrand());
            qDebug("solució seleccionada %d",selec);
            qDebug("solucionsTrobades.count() %d",solucionsTrobades.count());*/
            QStringList movimentsSolucio=solucionsTrobades.value(selec).split(" ");
            /*Ara seleccinam a l'atzar un número
             i es fan els moviments corresponents a la solució
             fins al número seleccionat*/
            selec=(qrand() % ((movimentsSolucio.count()/4)));
            /*Aquest valor mínim de selec és per evitar que es repeteixin
            //massa les solucions trobades (que no es carraguin molts
            moviments de la solució*/
            //qDebug("moviment seleccionat %d",selec);
            //qDebug("movimentsSolucio.count() %d",movimentsSolucio.count()/4);
            /*El 0.10 és empíric: pareix que quantes més fitxes hi ha,
             *és millor que el nombre sigui més petit*/
            while (selec<(movimentsSolucio.count()/4)*0.10){
              selec=qrand() % (movimentsSolucio.count()/4);
              //qDebug("selec %d",selec);
            }
            //qDebug("selec %d",selec);
            //qDebug("taulerJoc->p_numMoviments %d",taulerJoc->p_numMoviments);
            //selec=qMax(selec,taulerJoc->p_numMoviments);
            //qDebug("movimentsSolucio.count() %d",movimentsSolucio.count()/4);
           // qDebug("moviment seleccionat %d",selec);
           // qDebug("****************************");
            QString mov;
           // qDebug("taulerJoc->p_numMoviments %d",taulerJoc->p_numMoviments);
                for(int i=0;i<(movimentsSolucio.count()/4);i++){
                   if(i<(movimentsSolucio.count()/4)-selec){
                    taulerJoc->ferMoviment(movimentsSolucio.value(i*4+1).toInt(),
                                           movimentsSolucio.value(i*4+2).toInt(),
                                           movimentsSolucio.value(i*4+3).toInt());


                    solucionaJocActual_darrerMoviment=QString("%1 ").arg(movimentsUndoStack->index());
                    mov=QString("%1 %2 %3").
                            arg(movimentsSolucio.value(i*4+1)).
                            arg(movimentsSolucio.value(i*4+2)).
                            arg((movimentsSolucio.value(i*4+3)));
                    solucionaJocActual_darrerMoviment.append(mov);
                    solucionaJocActual_movimentsJaRealitzats.append(
                                      solucionaJocActual_darrerMoviment);
                   // qDebug("Solucio: moviment %d",i);
                }


                if(i>taulerJoc->p_numMoviments){
                    mov=QString("%1 %2 %3 %4").
                            arg(movimentsSolucio.value(i*4)).
                            arg(movimentsSolucio.value(i*4+1)).
                            arg(movimentsSolucio.value(i*4+2)).
                            arg((movimentsSolucio.value(i*4+3)));
                    solucionaJocActual_movimentsEliminats.append(mov);
                 }
            }
       // solucionaJocActual_darrerMoviment.append(mov);
        } /*Final de carregam la solució*/
   // }//if inicial movimentsUndoStack->index()==0
}

/*
  Elimina l'arxiu de configuracions eliminades. Es fa servir
  quan el programa no aconsegueix trobar una solucuió al joc
  */
void frmPrincipal::eliminaArxiuConfgEliminades(){
  comprovaDirectoriHome();
  QString nomArxiu=nomArxiuJoc(1);
  QFile arxiu(nomArxiu);
  arxiu.remove(nomArxiu);
}

void frmPrincipal::desaConfiguracionsEliminades(int tipus){

    if (solucioJocActual_configuracionsEliminadesPerDesar.count()==0){
        return;}

    int numero=0;

    QProgressDialog progres(tr("Desant dades"), tr("Atura"), 0,solucioJocActual_configuracionsEliminadesPerDesar.count() ,this);
    progres.setWindowModality(Qt::WindowModal);
    progres.setValue(numero);
    //progres.setVisible(true);
    qApp->processEvents();

    comprovaDirectoriHome();

   QString nomArxiu=nomArxiuJoc(1);

    QFile arxiu(nomArxiu);
    bool arxiuObert=false;
    if (tipus==0){
        if (arxiu.open(QIODevice::Append)){arxiuObert=true;}
    }
    else if (arxiu.open(QIODevice::WriteOnly)){arxiuObert=true;}

      if (arxiuObert){
         QTextStream entrada(&arxiu);
         for(int j=0;j<solucioJocActual_configuracionsEliminadesPerDesar.count();j++){
                 entrada<<(QString("%1\n").arg(solucioJocActual_configuracionsEliminadesPerDesar.value(j) )) ;
                 progres.setValue(++numero);
                 progres.setLabelText(QString(tr("Desant dades: %1 de %2")).arg(numero).
                                      arg(solucioJocActual_configuracionsEliminadesPerDesar.count()));
                 if (progres.wasCanceled()) { break;  }
        qApp->processEvents();
          }
        }
      arxiu.close();
     }


void frmPrincipal::carregaConfiguracionsEliminades(){
    int numero=0;

    QString nomArxiu=nomArxiuJoc(1);

    QFile arxiu(nomArxiu);
    /*23/01/2011
      Aqui hi havia una divisió per zero!
      Quan es fa un joc invers amb modificació de l'usuari
      */
    int divisor=taulerJoc->numeroDeMovimentsJoc();
    //Xapussa per evitar les divisions per zero
    if (divisor<0){divisor=1;}
    qint64 tamanyArxiu=arxiu.size()/divisor;
  /*  if (taulerJoc->numeroDeMovimentsJoc()>0){
        tamanyArxiu =1+arxiu.size()/(1+taulerJoc->numeroDeMovimentsJoc());}
    else tamanyArxiu =arxiu.size();*/

    QProgressDialog progres(tr("Carregant dades"), tr("Atura"), 0,tamanyArxiu ,this);


    progres.setWindowModality(Qt::WindowModal);
    progres.setValue(numero);
    progres.setVisible(true);
    qApp->processEvents();

   solucioJocActual_configuracionsEliminades.clear();
     if (arxiu.open(QIODevice::ReadOnly)){
         QTextStream entrada(&arxiu);
         QString linia0 = entrada.readLine();
     while (!linia0.isNull()) {
         if ( ! solucioJocActual_configuracionsEliminadesPerDesar.contains(linia0)){
             solucioJocActual_configuracionsEliminades.append(linia0);
             solucioJocActual_configuracionsEliminadesPerDesar.append(linia0);
             progres.setValue(++numero);
             progres.setLabelText(QString("Carregant dades: %1 de %2").arg(numero).arg(tamanyArxiu));
            }
            linia0 = entrada.readLine();            
            if (progres.wasCanceled())  break;
        qApp->processEvents();
         }
      arxiu.close();
      progres.cancel();
      /*07/09/16 Eliminat. Això es farà
       * en desar les dades
      desaConfiguracionsEliminades(1);*/
     }
}

/* Escriu a un arxiu el moviment passat
 * per paràmetre. Serveix per seguir els moviments
 * provats de la recerca iterativa de solució*/

void frmPrincipal::desaMovimentsJoc(QString moviment){

   comprovaDirectoriHome();

   QString nomArxiu=nomArxiuJoc(4);

    QFile arxiu(nomArxiu);
    bool arxiuObert=false;
    if (arxiu.open(QIODevice::Append)){arxiuObert=true;}
      if (arxiuObert){
         QTextStream entrada(&arxiu);
         entrada<<moviment ;
         entrada<<"\n";
        }
      arxiu.close();
     }

/*
  Elimina l'arxiu de moviments provats en la recerca
  de iterativa de solució.
  */
void frmPrincipal::eliminaArxiuMovimentsJoc(){
  comprovaDirectoriHome();
  QString nomArxiu=nomArxiuJoc(4);
  QFile arxiu(nomArxiu);
  arxiu.remove(nomArxiu);
}

/* Elimina l'arxiu adequat segons el codi passat
  1 ".txt"
  2 ".sol"
  4 ".movi"
  5 ".arbre"*/
void frmPrincipal::eliminaArxiu(int codi){
  comprovaDirectoriHome();
  QString nomArxiu=nomArxiuJoc(codi);
  QFile arxiu(nomArxiu);
  arxiu.remove(nomArxiu);
}


/*Comprova si hi ha una arxiu de solucions del joc
 * actual*/
bool frmPrincipal::comprovaArxiuDeSolucions(){
    QString nomArxiu=nomArxiuJoc(2);
    QFile arxiu(nomArxiu);
    return arxiu.exists();
}

/* Carrega les solucions del joc actual
 * a la llista solucionsTrobades
 */
void frmPrincipal::carregaSolucions(){
//    qDebug("carrega solucions");
    QString nomArxiu=nomArxiuJoc(2);
    QFile arxiu(nomArxiu);
    solucionsTrobades.clear();
    QProgressDialog progres(tr("Carregant dades"), tr("Atura"), 0,100 ,this);
    int contador=0;
    progres.setWindowModality(Qt::WindowModal);
    progres.setVisible(true);
//int liniesLlegides=0;
    if (arxiu.open(QIODevice::ReadOnly)){
         QTextStream entrada(&arxiu);
         QString linia0 = entrada.readLine();
     while (!linia0.isNull()) {
            QStringList movimentsSolucio=linia0.split(" ");
            //La segona condició és una xapussa per a què
            //funcioni la càrrega de la solució dels solitaris
            //generats a l'atzar
//            qDebug("taulerJoc->numeroDeMovimentsJoc() %d",taulerJoc->numeroDeMovimentsJoc());
//            qDebug("retrocedeixMoviment %d", retrocedeixMoviment);
            if ( (movimentsSolucio.count() ==
                (taulerJoc->numeroDeMovimentsJoc()+retrocedeixMoviment)*4)
                 || (movimentsSolucio.count() == solitariAtzar_solucio.count(" ")+1)
                 ){
                if (!solucionsTrobades.contains(linia0)){
                    solucionsTrobades.append(linia0);
                    progres.setValue(contador++);
                    if(contador>progres.maximum()-30){
                     progres.setMaximum(progres.maximum()*10);
                    }
                   // qDebug("carregada solucio");
                   }
                else {
                  qCritical("Sol. rep. %s", qPrintable(linia0));
                  }
                 }
                linia0 = entrada.readLine();
                qApp->processEvents();
                if(progres.wasCanceled()){
                    arxiu.close();
                    break;}
//                liniesLlegides++;
//                qDebug("liniesLlegides %d", liniesLlegides);
            /* 13/01/11
               Aquesta linea provocava un error en la càrrrega de les
               dades de les solucions quan es feia un canvi ràpid en la
               selecció de la modalitar de joc*/
            //qApp->processEvents();
         }
      //qDebug("Items in list: %d", solucionsTrobades.size());
      arxiu.close();
     }
//    else qDebug("No s'obri l'arxiu!!");
 //qDebug("Items in list: %d", solucionsTrobades.size());
}

void frmPrincipal::desaSolucions(){
     if (solucionaJocActual_movimentsJaRealitzats.count()==0){
         qDebug("No hi ha solucions per desar!");
        return;}
    /* 02/02/11  A vegades s'escriu malament la solució (no s'afageixen tots
      els moviments). Això evita aquest problema
      10/02/13 Això pareix que ja no passa mai
     */
      if(solucionaJocActual_movimentsJaRealitzats.count()  != taulerJoc->numeroDeMovimentsJoc() ){
       qDebug("problemes amb la solució %d",solucionaJocActual_movimentsJaRealitzats.count() );
       qDebug("taulerJoc->numeroDeMovimentsJoc() %d",taulerJoc->numeroDeMovimentsJoc() );
       return;
     }

   comprovaDirectoriHome();
   QString nomArxiu;
   if( (taulerJoc->solitariPersonalitzat() )||
      (taulerJoc->solitariModificat()) ){
     /* Eliminam les solucions que hi pugui haver a l'arbre
      * de solucions per evitar que es carreguin solucions
      * del solitari sense modificar.
      */
    // arbreSolucionsTreeWidget->clear();
    // solucionsTrobades.clear();
     veureSolucionsSlot();
   }
   nomArxiu=nomArxiuJoc(2);
   //carregaSolucions();
    QString solucioActual;
         for(int j=0;j<solucionaJocActual_movimentsJaRealitzats.count()-1;j++){
            solucioActual.append(QString("%1 ").arg(solucionaJocActual_movimentsJaRealitzats.value(j) )) ;
        }
    /*04/02/11  Eliminats els espais buits del final
       */
    solucioActual.append(QString("%1").arg(solucionaJocActual_movimentsJaRealitzats.value(
            solucionaJocActual_movimentsJaRealitzats.count()-1) )) ;
    //if( !solucionsTrobades.contains(solucioActual)){
    if( solucionsTrobades.indexOf(solucioActual)<0){
    QFile arxiu(nomArxiu);
      if (arxiu.open(QIODevice::Append)){         
         QTextStream entrada(&arxiu);
         entrada<<(QString("%1\n").arg(solucioActual )) ;
         statusBar()->showMessage(tr("S'ha trobat una nova solució!"));
         //qDebug("desaSolucions()");
        // solucionsTrobades.append(solucioActual);
        // qDebug("S'ha trobat una nova solució!");
         arxiu.close();
        }
      else qDebug("No es pot obrir l'arxiu de solucions per desar");
     }
}

/*
  Desa la solució actual continguda a movimentsUndoStack
  Es fa servir des de taulerJoc
  */
void frmPrincipal::desaSolucions1(){
     /*if (movimentsUndoStack->count()==0){
        return;
     }*/
   comprovaDirectoriHome();
   QString nomArxiu;
   /* ?????? */
   if(taulerJoc->solitariPersonalitzat()){
      nomArxiu=nomArxiuJoc(2);}
   else nomArxiu=nomArxiuJoc(2);
//   qCritical("desaSolucions1 %s", qPrintable(nomArxiu));
   // carregaSolucions();
    QString solucioActual;
         for(int j=0;j<movimentsUndoStack->count()-1;j++){
            solucioActual.append(QString("%1 %2 ").
                                arg(j+1).
                                arg(coordenadesAMoviment(movimentsUndoStack->text(j)))) ;
        }
     /*04/02/11  Eliminats els espais buits del final
       */
    solucioActual.append(QString("%1 %2").
                                arg(movimentsUndoStack->count()).
                                arg(coordenadesAMoviment(movimentsUndoStack->text(
                                       movimentsUndoStack->count()-1)))) ;
    /* 10/12/16
     * Aqui no s'afegia la nova solució a la llista de solucions.
     * Hi ha solucions repetides als arxius de solucions*/
    //if( !solucionsTrobades.contains(solucioActual)){

//    qCritical("%s", qPrintable(solucioActual));
    if( solucionsTrobades.indexOf(solucioActual)<0){
//    qDebug("solucionsTrobades.indexOf(solucioActual) %d", solucionsTrobades.indexOf(solucioActual));
    QFile arxiu(nomArxiu);
      if (arxiu.open(QIODevice::Append)){
         QTextStream entrada(&arxiu);
         entrada<<(QString("%1\n").arg(solucioActual)) ;
         statusBar()->showMessage(tr("S'ha trobat una nova solució!"));

        }
      arxiu.close();
     }
}

/* Carrega les solucions del joc actual
 * a l'arbre de solucions
 */
void frmPrincipal::veureSolucionsSlot(){

//while(!this->isVisible()){
//this->show();
//}
QApplication::setOverrideCursor(Qt::WaitCursor);


qApp->processEvents();

arbreSolucionsTreeWidget->clear();

//Carregam les solucions
//solucionsTrobades.clear();
carregaSolucions();
qApp->processEvents();
int numeroSolucio=1;
//qDebug("solucionsTrobades %d",solucionsTrobades.count());
if (solucionsTrobades.count()>0){

    QProgressDialog progres(tr("Carregant dades"), tr("Atura"), 0,solucionsTrobades.count() ,this);
    progres.setWindowModality(Qt::WindowModal);
    progres.setVisible(true);
//qDebug("Items in list: %d", solucionsTrobades.size());
//arbreSolucionsTreeWidget->clear();
for(int i=0;i<solucionsTrobades.count();i++){
    if ( ! solucionsTrobades.value(i).mid(0,1).contains("#")){
    //afegim un item arrel a l'arbre
    QTreeWidgetItem *itemSolucio=new QTreeWidgetItem();
    QList<QTreeWidgetItem *> itemsArbre;
    QStringList movimentsSolucio=solucionsTrobades.value(i).split(" ");
         for(int moviment=0 ; moviment<movimentsSolucio.count()/4;++moviment){
               QTreeWidgetItem *item=new QTreeWidgetItem();
               item->setText(0,
                        movimentACoordenades(movimentsSolucio.value(4*moviment+1),movimentsSolucio.value(4*moviment+3)));
               item->setText(1,QString("%1 %2 %3").arg(movimentsSolucio.value(4*moviment+1)).
                             arg(movimentsSolucio.value(4*moviment+2)).
                             arg(movimentsSolucio.value(4*moviment+3)) );
               itemsArbre.append(item);
         }
      itemSolucio->insertChildren(0,itemsArbre);
      itemSolucio->setText(0,tr("Solució %1").arg(numeroSolucio));
      arbreSolucionsTreeWidget->insertTopLevelItem(numeroSolucio-1,itemSolucio);
      qApp->processEvents();
      progres.setValue(i);
      ++numeroSolucio;
//      qDebug("numeroSolucio",numeroSolucio);
      arbreModalitatsJocTreeWidget->expandAll();
      if (progres.wasCanceled()) { break;  }
    }
  }
progres.close();
}
else {
    //qDebug("No s'ha trobat les solucions");
    QTreeWidgetItem *itemSolucio=new QTreeWidgetItem();
    itemSolucio->setText(0,tr("No hi ha solucions"));
    //arbreSolucionsTreeWidget->clear();
    arbreSolucionsTreeWidget->insertTopLevelItem(numeroSolucio-1,itemSolucio);
}
QTreeWidgetItem *itemCapcalera=new QTreeWidgetItem();

QString textCapcalera;
if(tipusJocActual==0){
textCapcalera=arbreModalitatsJocTreeWidget->selectedItems().first()->text(0);}
else if (tipusJocActual ==1){
textCapcalera=arbreModalitatsJocPersonalitzatsTreeWidget->selectedItems().first()->text(0);}

textCapcalera.append(" ("+QString("%1").arg(numeroSolucio-1)+")");
itemCapcalera->setText(0,textCapcalera);
arbreSolucionsTreeWidget->setHeaderItem(itemCapcalera);
tabArbres->setTabText(1," ("+QString("%1").arg(numeroSolucio-1)+")");
tabArbres->setTabToolTip(1,tr("Solucions")+" ("+QString("%1").arg(numeroSolucio-1)+")");

qApp->processEvents();
 QApplication::setOverrideCursor(Qt::ArrowCursor);
}

void frmPrincipal::carregaSolucio(QTreeWidgetItem*, int){
    if(arbreSolucionsTreeWidget->selectedItems().first()->childCount()>0){
        QMessageBox missatgeBox;
        missatgeBox.setText(tr("Carregar ")+arbreSolucionsTreeWidget->selectedItems().first()->text(0));
        missatgeBox.setInformativeText(tr("De debó voleu carregar la solució? Perdreu els moviments que heu fet!"));
        missatgeBox.setIcon(QMessageBox::Question);
        missatgeBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
        missatgeBox.setDefaultButton(QMessageBox::No);
        if(missatgeBox.exec()==QMessageBox::Yes){
          carregaSolucio1();
          statusBar()->showMessage(tr("S'ha carregat la ")+arbreSolucionsTreeWidget->selectedItems().first()->text(0)+
                                   tr(". Feu servir els botons Avança i Retrocedeix per veure la solució. "));
        }
}
}

/* Carrega una solució seleccionada de l'arbre de solucions
 */
void frmPrincipal::carregaSolucio1(){
    taulerJoc->setEstatDelJoc(solucio);
    iniciSolucioSlot();

    //06/02/13 nou prod.
    actualitzaConfiguracionsInicials();
   // solucioJocActual_configuracioInicial.clear();
   // solucioJocActual_configuracioInicial.append(taulerJoc->configuracioActual(true));
   // QStringList llista;
   // QString cadena;
    for(int i=0;i<arbreSolucionsTreeWidget->selectedItems().first()->childCount();i++){
       QStringList movimentsSolucio=
              arbreSolucionsTreeWidget->selectedItems().first()->child(i)->text(1).split(" ");
              taulerJoc->ferMoviment(movimentsSolucio.value(0).toInt(),
                                              movimentsSolucio.value(1).toInt(),
                                              movimentsSolucio.value(2).toInt());
    }
}

/*
  Converteix les dades d'un moviment en número
  a coordenades
  */
QString frmPrincipal::movimentACoordenades(QString inici,QString final){
    int numero_inici=inici.toInt();
    int numero_final=final.toInt();
    return QString("(%1,%2) -> (%3,%4)").arg(numero_inici/100).arg(numero_inici % 100).
                                arg(numero_final/100).arg(numero_final % 100);
}

/*
  Converteix les dades d'un moviment en coordenades
  a números
  */
QString frmPrincipal::coordenadesAMoviment(QString coordenades){
  QRegExp coord(".(\\d+),(\\d+). -> .(\\d+),(\\d+).");
  if (coord.exactMatch(coordenades)){
      int fitxaBotada=((coord.cap(1).toInt()+coord.cap(3).toInt())/2)*100+
                      ((coord.cap(2).toInt()+coord.cap(4).toInt())/2);
      return QString("%1 %2 %3").arg(coord.cap(1).toInt()*100+coord.cap(2).toInt()).
          arg(fitxaBotada).
          arg(coord.cap(3).toInt()*100+coord.cap(4).toInt());
  }
  else {
      return   QString("");}
}

/*
  Retorna el nom i directori de l'arxiu de dades/solucions del
  joc actual.
  tipus=1 -> arxiu amb les configuracions eliminades
  tipus=2 -> arxiu amb les solucions
  tipus=3 -> arxiu temporal de joc personalitzat
  tipus=4 -> arxiu de moviments provats en la recerca de solució .movi
   */
QString frmPrincipal::nomArxiuJoc(int tipus){
   comprovaDirectoriHome();
   QString nomArxiu=QDir::homePath ();
   QString extensio;
   if (tipus==1){ extensio=".txt";}
   else if (tipus==2){extensio=".sol";}
   else if (tipus==4){extensio=".movi";}
   else if (tipus==5){extensio=".arbre";}

    nomArxiu.append (QDir().separator());
    nomArxiu.append (qApp->applicationName());
    nomArxiu.append (QDir().separator());
   // qCritical("codi joc actual desar arxiu %s",qPrintable(taulerJoc->modalitatJocActual()));
    if ( (taulerJoc->solitariPersonalitzat()) ||
        (taulerJoc->solitariModificat()) ){
      //  qDebug("nomArxiuJoc solitari personalizat");
        nomArxiu.append(QString(solucioJocActual_configuracioInicial+"_"+
              QString("%1").arg(seguentCodiSolitariPersonalitzat)+extensio));
    }
    else {
      //  qDebug("nomArxiuJoc solitari NO personalizat");
        nomArxiu.append (QString(solucioJocActual_configuracioInicial+"_"+
                   QString("%1").arg(taulerJoc->modalitatJocActual())+extensio));
    }
    //qCritical("nomArxiu %s", qPrintable(nomArxiu));
    return nomArxiu;
}

/*
  Comprova que existeix el directori /Solitari
  en el directori d'usuari
  */
void frmPrincipal::comprovaDirectoriHome(){
    QDir dirArxiu(QDir::homePath ());
    if (!dirArxiu.exists(qApp->applicationName())){
         dirArxiu.mkdir(qApp->applicationName());
      }
}

void frmPrincipal::comprovaRegistre(){
     QSettings registre;
    // int reg=registre.value( QString("General/Registre"),0).toInt();
    if (registre.value( QString("General/Registre"),0).toInt()==0){
     if(QDesktopServices::openUrl(ADRECA_WEB_REGISTRE)){
        QSettings().setValue("General/Registre",1);
     };
  }
}

/*
  Retorna la cadena amb el missatge del número de moviments realitzats
  i total.
  Cal que s'hagi executat taulerJoc->numeroDeMovimentsJoc() per tenir
  acutalitzades les dades del nombre de fitxes del joc
  */
QString frmPrincipal::missatgeNumeroMoviments(int maxim){
QString numMovAct=QString("%1").arg(movimentsUndoStack->index());
//QString totalMovJoc=QString("%1").arg(taulerJoc->numeroDeMovimentsJoc());
QString totalMovJoc=QString("%1").arg(maxim);
//qCritical("numMovAct %s", qPrintable(numMovAct));
//qCritical("totalMovJoc %s", qPrintable(totalMovJoc));
//if(movimentsUndoStack->index()>=maxim){
//    qDebug("Problema!!!!!");
//}

while (numMovAct.length()<totalMovJoc.length() && numMovAct !="0"){numMovAct.prepend("0");}
return QString(tr("Moviment ")+numMovAct+tr(" de %1").arg(totalMovJoc));
//return QString(tr("Moviment ")+numMovAct+tr(" de %1").arg(maxim));
}

/*
  Copia l'arxiu de solucions en el directori
  de l'usuari
  */
void frmPrincipal::comprovaArxiuSolucions(){
//    return;
    comprovaDirectoriHome();
    QString nomArxiuDesti=QDir::homePath ();
    nomArxiuDesti.append (QDir().separator());
    nomArxiuDesti.append (qApp->applicationName());
    nomArxiuDesti.append (QDir().separator());
    nomArxiuDesti.append(QString(solucioJocActual_configuracioInicial+"_"+
                        QString("%1").arg(taulerJoc->modalitatJocActual())+".sol"));

    QString nomArxiuInicial=directoriLinux();
    nomArxiuInicial.append(QDir().separator());
    nomArxiuInicial.append(DIRECTORI_DADES);
    nomArxiuInicial.append(QDir().separator());
    nomArxiuInicial.append(QString(solucioJocActual_configuracioInicial+"_"+
                        QString("%1").arg(taulerJoc->modalitatJocActual())+".sol"));
   // qDebug("Directori Linux %s",qPrintable(nomArxiuInicial));

    QFile arxiu(nomArxiuInicial);
    arxiu.copy(nomArxiuDesti);
}

/* Comprova si hi ha un arxiu amb solucions del joc actual
 * en el directorio /games
 * Es fa servir per saber si el programa aconsegueix resoldre
 * el joc sense fer servir dades de solucions prèvies*/
bool frmPrincipal::comprovaDadesSolucions(){
    QString nomArxiuInicial=directoriLinux();
    nomArxiuInicial.append(QDir().separator());
    nomArxiuInicial.append(DIRECTORI_DADES);
    nomArxiuInicial.append(QDir().separator());
    nomArxiuInicial.append(QString(solucioJocActual_configuracioInicial+"_"+
                        QString("%1").arg(taulerJoc->modalitatJocActual())+".sol"));
//    qCritical("%s",qPrintable(nomArxiuInicial));
    QDir dirArxiu(QDir::homePath ());
    if (!dirArxiu.exists(nomArxiuInicial)){
//        qDebug("No existeix");
        return false;
      }
    else return true;
}

/* Comprova si les dades de les fitxes es corresponen
 * amb una modalitat de final marcat
 */
bool frmPrincipal::esSolitariAmbFinalMarcat(QString dadesFitxes){
return ( dadesFitxes.contains("11"))
       ||(dadesFitxes.contains("10"));
}

/* Comprova si hi ha alguna solució a l'arbre
 * de solucions
 */
bool frmPrincipal::noHiHaSolucionsArbreSolucions(){
 if(arbreSolucionsTreeWidget->topLevelItemCount()>0){
 return arbreSolucionsTreeWidget->topLevelItem(0)->text(0).
                contains(tr("No hi ha solucions")) ;}
 else return true;
}

 //Mostra un missatge passat pel tauler del joc
void frmPrincipal::mostraMissatge(int codi){
    switch (codi) {
     case 0:
         statusBar()->showMessage(tr("No hi ha més moviments: el joc ha finalitzat!"));
         break;
     case 1:
         statusBar()->showMessage(tr("Joc resolt!"));
         break;
     case 2:
         QMessageBox::information(this,tr("Nova marca personal"),
                                 tr("Heu establert un nou record personal en aquesta modalitat de joc"));
         if(arbreModalitatsJocTreeWidget->selectedItems().count()==1){
            QTreeWidgetItem *item=arbreModalitatsJocTreeWidget->selectedItems().first();
            QStringList dades=item->text(1).split(" ");
            item->setIcon(0,QIcon(posaIconeOK(dades.value(0))));
         }
         break;
     case 3:
         statusBar()->showMessage(/*
                 missatgeNumeroMoviments(0));*/
                 QString(tr("Moviment %1 de %2 ")).arg(movimentsUndoStack->index()).
                 arg(taulerJoc->numeroDeMovimentsJoc()));
         break;
    case 4:
        statusBar()->showMessage(/*missatgeNumeroMoviments(0));*/
                QString(tr("Moviment %1 de %2 "))
                .arg(movimentsUndoStack->index())
                .arg(taulerJoc->numeroDeMovimentsJoc()));
//                .arg(solucionaJocActual_numeroDeFitxesDelJoc()-1));
        break;
    case 5:
        statusBar()->showMessage(tr("No hi ha moviments!"));
        break;
    case 100:
        statusBar()->showMessage(" ");
        break;
     }
//    if(codi>3){
//    statusBar()->showMessage(
//                QString(tr("jocsRealitzats %1 ")).arg(codi));//}
}

/* Procediments dels solitaris a l'atzar
*/
void frmPrincipal::solitariAtzar_generaJoc(){

   solitariAtzar_eliminaArxiuSolucio();

   //Primer cal generar les dades per construir un joc a l'atzar

   //Tipus de moviment del solitari final
   int tipus_MovimentGenerat = (qrand() % 3);
   //tipus_MovimentGenerat=2;
   //Tipus de moviment en el procés de generació del joc
   int tipusMovimentGenerador;
   //Tipus de fitxa en l'inici de la generació del solitari
   QString tipusFitxa="10";
   if (tipus_MovimentGenerat==0){tipus_MovimentGenerat=3;}
   //qDebug("tipus_MovimentGenerat %d",tipus_MovimentGenerat);
   //Retorna el tipus de moviment per generar el solitari
   //i el tipus de fitxa
   tipusMovimentGenerador=
       solitariAtzar_tipusMovimentGenerador(tipus_MovimentGenerat,tipusFitxa);
   //Assegurem que hi haurà un nombre mínim de files i columnes
   int minimFilesColumnes=5;
   int maximFilesColumnes=30;
   int maximNumeroFitxes=50;
   int num_Files= 0;
   while (num_Files<minimFilesColumnes){
     num_Files=(qrand() % maximFilesColumnes)+1;
   }
   int num_Columnes=0;
   while ( (num_Columnes<minimFilesColumnes) ||
           (num_Columnes>num_Files+4) ){
     num_Columnes=(qrand() % maximFilesColumnes)+1;
   }
   //Seleccionam la fitxa inicial per jugar
   int fitxa_Inicial=(qrand() % (num_Files*num_Columnes))+1;
   QString dades_Fitxes;
   bool fitxa=false;
   //generam les dades de les fitxes per al tauler de joc
   for(int j=0 ; j<num_Files;j++){
      for(int i=1 ; i<=num_Columnes;i++){
          if( (j*num_Columnes+i==fitxa_Inicial) && !fitxa){
              dades_Fitxes=dades_Fitxes+tipusFitxa.mid(0,1)+" ";
              fitxa=true;
          }
          else dades_Fitxes=dades_Fitxes+tipusFitxa.mid(1,1)+" ";
     }
   }

   //Fem invisible el tauler de joc per evitar
   //el molest "parpadeig" mentre es genera el joc
   taulerJoc->setVisible(false);
   //Carregam el joc
   taulerJoc->joc_CarregaJoc(QString("1000 %1 100 0").arg(tipusMovimentGenerador),
                                QString("%1 %2").arg(num_Files).arg(num_Columnes),
                                dades_Fitxes.simplified());

   //Aqui es comença a jugar per generar el solitari
   QStringList llistaMoviments;
   //Seleccionam a l'atzar el número de fitxes actives que tendrà el solitari
   //(garantint que hi haurà un mínim de fitxes! 14)
   int numeroFitxes=0;
   while ( (numeroFitxes<minimFilesColumnes*minimFilesColumnes*0.2) ||
           (numeroFitxes>maximNumeroFitxes)){
     numeroFitxes=(qrand() % qRound(num_Files*num_Columnes*0.3));
   }
   //Ara es juga fins a assolir el nombre de fitxes actives
   for(int j=0 ; j<numeroFitxes;j++){
   taulerJoc->solucionaJocActual_CalculaMovimentsPosibles();
   llistaMoviments=
       taulerJoc->solucionaJocActual_CarregaMovimentsArbre1(llistaMoviments,QString(""));
   //qDebug("llistaMoviments %d",llistaMoviments.count());
   if (llistaMoviments.count()>0){
       QStringList moviment=llistaMoviments
               .value(qrand() % llistaMoviments.count()).split(" ");
       taulerJoc->ferMoviment(moviment.value(0).toInt(),
                              moviment.value(1).toInt(),
                              moviment.value(2).toInt(),false);
       /* Si el tipus de moviment del joc és directe o diagonal,
        * és el primer moviment
        * i una vegada de cada 2, es marca la fitxa inicial com
        * a fitxa final de joc
        */
       if ( (tipus_MovimentGenerat != 2) &&
            ( (qrand() % 2) == 1) &&
              (j==0) ){
       taulerJoc->solitariAtzar_MarcaFitxaUsada(moviment.value(0).toInt(),true);
       }
       else taulerJoc->solitariAtzar_MarcaFitxaUsada(moviment.value(0).toInt());
       taulerJoc->solitariAtzar_MarcaFitxaUsada(moviment.value(1).toInt());
       taulerJoc->solitariAtzar_MarcaFitxaUsada(moviment.value(2).toInt());
    }
   }

   //Generam les dades de les fitxes del solitari generat
   dades_Fitxes=taulerJoc->solitariAtzar_dadesEstatFitxes(num_Files,num_Columnes);
   statusBar()->showMessage("");
   //qCritical("%s", qPrintable(dades_Fitxes));
   //solitariAtzar_generaImatge();

   //Carregam les dades a l'ítem de l'arbre del joc
   /*num_Files=8;
   num_Columnes=6;
   dades_Fitxes="-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 -1 -1 0 -1 -1 0 -1 0 0 1 1 1 0 -1 0 0 1 0 -1";
   */
   solitariAtzar_carregaDadesArbreJoc(
               QString("1000 %1 10 1").arg(tipus_MovimentGenerat),
               QString("%1 %2").arg(num_Files).arg(num_Columnes),
               dades_Fitxes);
   //qDebug("Files %d *****",num_Files);
   //qDebug("Columnes %d *****\n",num_Columnes);
   //qCritical("%s", qPrintable(dades_Fitxes));
   //qDebug("*****");
   solitariAtzar_solucio.clear();
   solitariAtzar_solucio=solitariAtzar_inverteixSolucioJocGenerat();
   //Carregam el joc
   seleccioModalitatJoc();
   taulerJoc->setVisible(true);
   //desam la solució a un arxiu
   solitariAtzar_desaSolucio();
   //La carregam a l'arbre de solucions
   veureSolucionsSlot();
}

/* Retorna el tipus de moviment del joc
 * en el procés de generació del solitaria l'atzar
 * El paràmetre té els codis de les fitxes a l'inici
 * de la generació del solitari
 */
int frmPrincipal::solitariAtzar_tipusMovimentGenerador(
        int tipusMoviementGenerat, QString &tipusFitxa){
 int tipusRetorn=1;
 switch (tipusMoviementGenerat) {
 case 1:
     tipusRetorn=2;
     tipusFitxa="10";
     break;
 case 2:
     tipusRetorn=1;
     tipusFitxa="01";
     break;
 case 3:
     tipusRetorn=5;
     tipusFitxa="10";
     break;
 }
 return tipusRetorn;
}

/* Carrega les dades del solitari generat a l'ítem de l'arbre
 */
void frmPrincipal::solitariAtzar_carregaDadesArbreJoc(QString codi,QString FilesColumnes,
                                        QString dadesFitxes){
    QTreeWidgetItem *item;
    item=arbreModalitatsJocTreeWidget->selectedItems().first();
    item->setText(1,codi);
    item->setText(2,FilesColumnes);
    item->setText(3,dadesFitxes);
}

/* Abans de posar en marxa el procés de cercar solució
 * es comprova si estem en un solitari generat a l'atzar
 * En aquest cas, la solució ja és coneguda i, simplement
 * es carrega
 */
bool frmPrincipal::solitariAtzar_CarregaSolucio(){
    bool retorn=false;
    QTreeWidgetItem *item;
    item=arbreModalitatsJocTreeWidget->selectedItems().first();
    if(solitariAtzar_esAtzar(item->text(1))){
      solucionsTrobades.clear();
      solucionsTrobades.append(solitariAtzar_solucio);
      retorn=true;
    }
 return retorn;
}

/* En haver generat un joc, es transforma els moviments de
 * movimentsUndoStack en al solució del joc
 * (invertint els moviments)
 */
QString frmPrincipal::solitariAtzar_inverteixSolucioJocGenerat(){
//La pila de moviments està en el final de tot
//Llegim la informació de la pila del final al principi
QString movimentsSolucio;
for(int j=0 ; j<movimentsUndoStack->count();j++){
  movimentsSolucio.append(QString("%1 ").arg(j+1));
  movimentsSolucio.append(
              solitariAtzar_coordenadesAMoviment(
                movimentsUndoStack->text(movimentsUndoStack->count()-j-1)));
}
return movimentsSolucio.simplified();
}

/* Converteix les coordenades de un moviment a dades
 * però invertint el moviment
 * (simplement s'inverteixen les fitxes final i inicial
 */
QString frmPrincipal::solitariAtzar_coordenadesAMoviment(QString coordenades){
    QRegExp coord(".(\\d+),(\\d+). -> .(\\d+),(\\d+).");
    if (coord.exactMatch(coordenades)){
        int fitxaBotada=((coord.cap(1).toInt()+coord.cap(3).toInt())/2)*100+
                        ((coord.cap(2).toInt()+coord.cap(4).toInt())/2);
        return QString("%1 %2 %3 ").arg(coord.cap(3).toInt()*100+coord.cap(4).toInt()).
            arg(fitxaBotada).
            arg(coord.cap(1).toInt()*100+coord.cap(2).toInt())
            ;
    }
    else {
        return   QString("");}
}

/* Desa a un arxiu la solució del solitari
 * generat a l'atzar
 */
void frmPrincipal::solitariAtzar_desaSolucio(){
    comprovaDirectoriHome();
    QString nomArxiu=nomArxiuJoc(2);
     carregaSolucions();
     QFile arxiu(nomArxiu);
       if (arxiu.open(QIODevice::Append)){
          QTextStream entrada(&arxiu);
          entrada<<(QString("%1\n").arg(solitariAtzar_solucio)) ;
         }
       arxiu.close();
}

/* Gestiona el canvi de la selecció de joc per controlar
 * el tipus de joc de generació a l'atzar
 * elimina les dades del ítem a l'atzar per permetre la
 * generació en tornar a seleccionar
 */
void frmPrincipal::canviItemArbreJoc(QTreeWidgetItem *actual,
                                     QTreeWidgetItem *anterior){

  if(anterior != NULL){
    if(solitariAtzar_esAtzar(anterior->text(1))){
        anterior->setText(3,"0");
        //eliminam la solució anterior
        solitariAtzar_solucio.clear();
        //eliminam l'arxiu de solucions i els
        //de suport
        solitariAtzar_eliminaArxiuSolucio();
     }
    else if(solitariPersonalitzat_esPersonalitzat(anterior->text(1))){
        //eliminam la solució anterior
        solitariAtzar_solucio.clear();
        solitariPersonalitzat_eliminaArxiuSolucio();
        }
   }
}

/* Gestiona el doble clic sobre l'ítem de la generació
 * a l'atzar de solitaris
 */
void frmPrincipal::dobleClickArbreJoc(QTreeWidgetItem *item, int columne){
    //estem fent doble clic al node de generacíó
    //a l'atzar
    if(solitariAtzar_esAtzar(item->text(1))){
      solitariAtzar_generaJoc();
    }
    /* en cas contrari, carregam el joc
     * Això és necessari per als jocs
     * personalitzats
     */
    else seleccioModalitatJoc();
}

/* genera una imatge del primer pas del procés de generació
 * d'un joc a l'atzar
 */
void frmPrincipal::solitariAtzar_generaImatge(){
    QPixmap pixMap = QPixmap::grabWidget(taulerJoc);
    pixMap.createMaskFromColor(Qt::white,Qt::MaskInColor);
    QString nomArxiuImatge="solitariAtzar.png";
    pixMap.save(nomArxiuImatge);
}

/* Elimina l'arxiu de la solució del solitari actual
 */
void frmPrincipal::solitariAtzar_eliminaArxiuSolucio(){
 if(arbreModalitatsJocTreeWidget->selectedItems().count()>0){
    if(solitariAtzar_esAtzar(
       arbreModalitatsJocTreeWidget->selectedItems().first()->text(1))){
    comprovaDirectoriHome();
    QString nomArxiu=nomArxiuJoc(2);
   //Això és necessari per evitar eliminar arxius d'altres
   //jocs que tenguin solucions noves
    if(solitariAtzar_esAtzar(nomArxiu)){
    QFile arxiu(nomArxiu);
    if (arxiu.exists()){
        arxiu.remove();
        qApp->processEvents();
        nomArxiu=nomArxiuJoc(1);
        QFile arxiu1(nomArxiu);
        arxiu1.remove();
        qApp->processEvents();
     }
     }
    }//if arbre-text
   }//if arbre-count
}

/* Determina si el solitari actual és o no
 * a l'atzar
 */
bool frmPrincipal::solitariAtzar_esAtzar(QString joc){
 /* La segona condició s'ha afegit per evitar errors
  * quan es fa la comprovació amb el nom de l'arxiu
  * de solucions
  */
    return (joc.contains("1000") || joc.contains(" _1000") );
}

/* Jocs personalitzats
 * Són els jocs inventats per l'usuari amb els ítems
 * Personalitzat (diagonal/invers) o bé modificaNT
 * un joc del programa.
 * Una vegada l'usuari ha generat les fitxes, en
 * començar a jugar o clicar el sistema de cerca de
 * solució, es recalculen les dades del nou joc.
 * Es controla si el joc és personalitzat amb els
 * codis de joc de l'arbreModalitatsJocTreeWidget, la
 * funció solitariPersonalitzat_esPersonalitzat,
 * la propietat taulerJoc.solitariPersonalitzat(), la
 * propietat taulerJoc.solitariModificat() i la propietat
 * fitxa.p_fitxaSolitariPersonalitzat.
 * Si s'aconseguix trobar una solució, llavors les dades
 * del nou joc s'afegeixen a l'arbre de jocs personalitzats
 * i a l'arxiu de dades /Solitari/game-per.dat
 * A cada nou joc personalitzat se li assigna un codi que
 * es va actualitzant a l'arxiu ini de conf (i comença amb 10000).
 * S'ha fet bastant complexe conservar les dades a l'arxiu de solucions
 */

/* Calcula les dades de les fitxes del solitari personalitzat
 * i carrega el joc
 */
void frmPrincipal::solitariPersonalitzat_dadesFitxes(){
//Cal actualitzar això primer
taulerJoc->configuracioActual(true);
/* Si ja hi ha una solució a l'arbre de solucions,
 * llavors no és necessari res de tot això
 */
if ( !noHiHaSolucionsArbreSolucions() && taulerJoc->solitariPersonalitzat()){
    return;}
/* 13/02/13 no pareix que això sigui necessari
 * S'ha eliminat
 */
/*else if ( (tipusJocActual==1) //|| (!taulerJoc->solitariModificat())
         || (taulerJoc->solitariPersonalitzat()) ){
    //Això és necessari per poder jugar
    taulerJoc->marcaFitxesSolitariPersonalitzat(false);
    return;
}*/
else if (taulerJoc->numeroDeMovimentsJoc()<1){
    return;
}
/*primer comprovam si es tracte d'un joc
 *personalitzat/mod.*/
     if( (taulerJoc->solitariPersonalitzat()) ||
             (taulerJoc->solitariModificat()) ){
    //Això per si ja s'ha intentat trobar una solució per al solitari
    iniciSolucioSlot();
    //obtenim les dades del solitari
    QStringList dadesFitxes=taulerJoc->solitariPersonalitzat_dadesFitxes();
    //carregam el joc
    QString dades;
    if(p_arbreJocsActual==0){ //és un joc del programa
      dades=arbreModalitatsJocTreeWidget->selectedItems().first()->text(1);}
    else if (p_arbreJocsActual==1){ //és un joc de l'arbre de personalitzats/mod
      dades=arbreModalitatsJocPersonalitzatsTreeWidget->selectedItems().first()->text(1);
    }
    seguentCodiSolitariPersonalitzat.clear();
    seguentCodiSolitariPersonalitzat.append(solitariPersonalitzat_nouCodiJoc(false));
    taulerJoc->joc_CarregaJoc(
              dades,
              dadesFitxes.value(0),
              dadesFitxes.value(1));
    taulerJoc->configuracioActual(true);

    //06/02/13 nou prod.
    actualitzaConfiguracionsInicials();
    }
   //}//if arbreModalitatsJocTreeWidget
}

/* Quan es resol un solitari personalitzat
 * es desa a l'arbre de jocs personalitzats
 * (prèvia comprovació de que no està repetit)
 */
void frmPrincipal::solitariPersonalitzat_desarSolitari(){
 /* Primer comprovam si el solitari ja està a l'arbre de solitaris
  * personalitzats
  */
 solitariPersonalitzat_comprovaArbre();
}

/* Comprova si el solitari personalitzat ja està
 * a l'arbre de solitaris personalitzats
 */
void frmPrincipal::solitariPersonalitzat_comprovaArbre(){
 bool jocTrobat=false;
 //Capturam les dades del joc personalitzat actual
 //Primer cal tornar a l'inici del joc
 iniciSolucioSlot();
 QStringList dadesFitxes=taulerJoc->solitariPersonalitzat_dadesFitxes();

 if(arbreModalitatsJocPersonalitzatsTreeWidget->topLevelItemCount()>0){
   for(int i=0 ; i<arbreModalitatsJocPersonalitzatsTreeWidget->topLevelItemCount();++i){
       QString tipusJoc=arbreModalitatsJocPersonalitzatsTreeWidget
               ->topLevelItem(i)->text(1).split(" ").value(1);
       tipusJoc=" "+tipusJoc+" ";
       if( (arbreModalitatsJocPersonalitzatsTreeWidget->
            topLevelItem(i)->text(3)==dadesFitxes.value(1)) &&
            (taulerJoc->p_tipusMoviment==tipusJoc.toInt()) ){
          jocTrobat=true;
       }
   }
 }
 if(!jocTrobat){
     QString nouCodi=solitariPersonalitzat_afegeixJoc(dadesFitxes);    
     //renomenam l'arxiu de solucions
     solitariPersonalitzat_renomenaArxiuSolucio(nouCodi);
     //Eliminan els arxius .sol i .txt que hi pugui haver
     //de la modalitat de generació de solitaris
     solitariPersonalitzat_eliminaArxiuSolucio();
     taulerJoc->setModalitatJocActual(nouCodi);
     //Tornam la situació al final de la solució
     finalSolucioSlot(true);
 }
 //Si el joc ja existeix, no té cap sentit conservar els arxius
 else {solitariPersonalitzat_eliminaArxiuSolucio();
     //Tornam la situació al final de la solució
     //sense marcar el final del joc
     finalSolucioSlot(false);}
}

/* Afegeix un joc personalitzat a l'arbre
 */
QString frmPrincipal::solitariPersonalitzat_afegeixJoc(QStringList dadesJocList){

  QTreeWidgetItem *item=new QTreeWidgetItem();
  QString nouCodiSolitari=solitariPersonalitzat_nouCodiJoc(true);
  /* Capturam el nom del joc original
   * sense afegitons
   */
 /*QString nomSolitari=nomDelJoc(
              arbreModalitatsJocTreeWidget->selectedItems().first()->text(4),false)+
          afageixTipusMovimentNomJoc(
            arbreModalitatsJocTreeWidget->selectedItems().first()->text(1))
          +" "+nouCodiSolitari;*/
 QString nomSolitari=nomDelJoc(
              taulerJoc->nomJocActual(),false)+
              afageixTipusMovimentNomJoc(
              QString(" %1 ").arg(taulerJoc->p_tipusMoviment))
             // arbreModalitatsJocTreeWidget->selectedItems().first()->text(1))
              +" "+nouCodiSolitari;
  if(esSolitariAmbFinalMarcat(dadesJocList.value(1))) {
              nomSolitari=nomSolitari+" *" ;}

  item->setText(0,nomSolitari);
  item->setToolTip(0,item->text(0));
  //linea 0: codi joc, tipus moviment
 // QStringList dadesAntigues=
   //     arbreModalitatsJocTreeWidget->selectedItems().first()->text(1).split(" ");

  //El codi del joc es reemplaça pel nou
  item->setText(1,
        QString("%1 %2 5 0").arg(nouCodiSolitari).
                arg(taulerJoc->p_tipusMoviment) );
                //Actualitzat per els nous jocs
                //que són modificació d'altres ja existents
               // arg(dadesAntigues.value(1)) );
  //linea 1: files i columnes
  item->setText(2,dadesJocList.value(0));
  //linea 2: estat de les fitxes
  item->setText(3,dadesJocList.value(1));
  //item->setText(4,arbreModalitatsJocTreeWidget->selectedItems().first()->text(4));
  item->setText(4,taulerJoc->nomJocActual());
  arbreModalitatsJocPersonalitzatsTreeWidget->addTopLevelItem(item);
  arbreModalitatsJocPersonalitzatsTreeWidget->expandAll();
  arbreModalitatsJocPersonalitzatsTreeWidget->sortItems(0,Qt::AscendingOrder);


  //Actualitzam la capçalera
  QTreeWidgetItem *itemCapcalera=new QTreeWidgetItem();
  QString textCapcalera;
  textCapcalera.append(tr("Jocs personalitzats")+" ("+
                QString("%1").arg(
                arbreModalitatsJocPersonalitzatsTreeWidget->topLevelItemCount())+")");
  itemCapcalera->setText(0,textCapcalera);
  arbreModalitatsJocPersonalitzatsTreeWidget->setHeaderItem(itemCapcalera);

  //Ara ho afegim a l'arxiu de dades
  solitariPersonalitzat_desaJocArxiu(item->text(1),dadesJocList,
                                     item->text(4));
  return nouCodiSolitari;
}

/* Afegeix les dades del joc personalitzat a l'arxiu
 * de dades /home/Solitari/game-per.dat
 */
void frmPrincipal::solitariPersonalitzat_desaJocArxiu(QString codi,
                                 QStringList dadesFitxes, QString codiNom){
 comprovaDirectoriHome();
 QString nomArxiu=QDir::homePath ();
 nomArxiu.append (QDir().separator());
 nomArxiu.append (qApp->applicationName());
 nomArxiu.append (QDir().separator());
 nomArxiu.append ("game-per.dat");
    QFile arxiu(nomArxiu);
      if (arxiu.open(QIODevice::Append)){
         QTextStream entrada(&arxiu);
         entrada<<("######\n") ;
         entrada<<(codi+"\n") ;
         entrada<<(dadesFitxes.value(0)+"\n") ;
         entrada<<(dadesFitxes.value(1)+"\n") ;
         entrada<<(codiNom+"\n") ;
        }
      arxiu.close();
     }

/* Renomena l'arxiu amb la solució del solitari
 * personalitzat nou
 */
void frmPrincipal::solitariPersonalitzat_renomenaArxiuSolucio(QString nouCodi){
 return;
    QString nomArxiu=nomArxiuJoc(2);
    QString nomArxiuModificat=nomArxiuJoc(2);
    nomArxiuModificat.replace("_"+taulerJoc->modalitatJocActual(),"_"+nouCodi);
    QFile::copy(nomArxiu,nomArxiuModificat);
}


/* Llegeix i carrega les dades dels jocs personalitzats
 * de l'arxiu /home/Solitari/games-per.dat a la llista
 * dadesArxiuData
 */
bool frmPrincipal::llegeixArxiuDataPersonalitzats(){
    bool resultat=false;
    comprovaDirectoriHome();
    QString arxiuData=QDir::homePath ();
    arxiuData.append (QDir().separator());
    arxiuData.append (qApp->applicationName());
    arxiuData.append (QDir().separator());
    arxiuData.append ("game-per.dat");
    QFile arxiu(arxiuData);
    if(arxiu.exists()){
     if (arxiu.open(QIODevice::ReadOnly | QIODevice::Text)){
     QTextStream entrada(&arxiu);
     QString linia0 = entrada.readLine();
     dadesArxiuData.clear();
     while (!linia0.isNull()) {
         if ( ! (linia0.mid(0,1)=="#") ){
            dadesArxiuData.append(linia0); //tipus de joc
            for(int dades=0 ; dades<numeroLiniesDadesJoc-1;++dades){
            dadesArxiuData.append(entrada.readLine());
          }
         }
       linia0 = entrada.readLine();
     } //final del while de la lectura de l'arxiu
    resultat=true;
     }
    }//final if exists
 return resultat;
}

/* Gestiona la selecció dels jocs
 * personalitzats
 */
void  frmPrincipal::seleccioModalitatJocPersonalitzat(){
    statusBar()->clearMessage();
    /*Necessari per controlar les solucions distintes*/
    retrocedeixMoviment=0;
    /*Això per preveure que es canvii dels jocs del programa
     *als jocs personalitzats sense haver eliminat
     *els arxius del joc personalitzat
     */
    if( (tipusJocActual==0) && (noHiHaSolucionsArbreSolucions()) ){
     solitariPersonalitzat_eliminaArxiuSolucio();
    }
   // if (!arbreModalitatsJocTreeWidget->selectedItems().isEmpty()){
    if (arbreModalitatsJocPersonalitzatsTreeWidget->selectedItems().count()==1){
       QTreeWidgetItem *item;
       item=arbreModalitatsJocPersonalitzatsTreeWidget->selectedItems().first();
       //No s'ha clicat el nus arrel
       if (item->childCount()==0){
           movimentsUndoStack->clear();
           iniciSolucioAction->setEnabled(movimentsUndoStack->canUndo());
           //Reinciam el número d'intents de trobar
           //la solució
           intentsSolucio=0;
           jocResolt=0;
           //es tracta d'un joc personalitzat/modificat
           tipusJocActual=1;
           taulerJoc->joc_CarregaJoc(item->text(1),item->text(2),item->text(3));
           taulerJoc->setCodiNomJocActual(item->text(4));
           taulerJoc->setSolitariModificat(false);
           taulerJoc->setSolitariPersonalitzat(false);
           setArbreJocsActual(1);
           //30/12/12 Nova funció hihaRecord()
           QStringList  tipusJoc = item->text(1).split(" ");
           QString record=hihaRecordJoc(tipusJoc.value(0));
           if ( record != "0") {
           statusBar()->showMessage(
               QString(tr("Joc carregat. El vostre record actual és:  %1")).arg(record));
           }
           //06/02/13 nou prod.
           actualitzaConfiguracionsInicials();
           //06/02/13 Innecessari!
           //comprovaArxiuSolucions();
           veureSolucionsSlot();
       }
   }
}


/*Carrega les dades dels solitaris personalitzats
 */
void frmPrincipal::carregaArbreModalitatsJocPersonalitzats(){

//Si no hi ha arxiu, no cal fer res!
if ( !llegeixArxiuDataPersonalitzats()){
    QTreeWidgetItem *item=new QTreeWidgetItem();
    item->setText(0,tr("Cap joc personalitzat"));
    arbreModalitatsJocPersonalitzatsTreeWidget->setHeaderItem(item);
    return;}
if (dadesArxiuData.size()>0){
   QApplication::setOverrideCursor(Qt::WaitCursor);
   //netejam
   arbreModalitatsJocPersonalitzatsTreeWidget->clear();
   arbreModalitatsJocPersonalitzatsTreeWidget->setColumnCount(numeroLiniesDadesJoc+1);
   arbreModalitatsJocPersonalitzatsTreeWidget->setColumnHidden(1,true);
   arbreModalitatsJocPersonalitzatsTreeWidget->setColumnHidden(2,true);
   arbreModalitatsJocPersonalitzatsTreeWidget->setColumnHidden(3,true);
   arbreModalitatsJocPersonalitzatsTreeWidget->setColumnHidden(4,true);

   //posam la capçalera de l'arbre
   QTreeWidgetItem *item=new QTreeWidgetItem();
   item->setText(0,tr("Jocs personalitzats"));
   arbreModalitatsJocPersonalitzatsTreeWidget->setHeaderItem(item);

   QList<QTreeWidgetItem *> itemsArbre;
     for(int llista=0 ; llista<dadesArxiuData.size()/(numeroLiniesDadesJoc);++llista){
       QTreeWidgetItem *item=new QTreeWidgetItem();
       /*QStringList nomJocOrig=(tr(nomModalitatsJoc[
                         dadesArxiuData.value(
                              llista*numeroLiniesDadesJoc+3).toInt()])).split(" - ");*/
       //QString nomJoc=nomJocOrig.value(0);
       QString nomJoc=nomDelJoc(dadesArxiuData.value(
                                    llista*numeroLiniesDadesJoc+3),false);
       //Afegim el codi del joc
       QStringList codi=dadesArxiuData.value(llista*(numeroLiniesDadesJoc)).split(" ");

       nomJoc=nomJoc+
              afageixTipusMovimentNomJoc(dadesArxiuData.value(llista*(numeroLiniesDadesJoc)))
               +" "+codi.value(0);
       //Comprovam si és una modalitat amb final marcat
       //per afegir un * al nom
       //12/01/13 Nova funció
       //if( (dadesArxiuData.value(llista*(numeroLiniesDadesJoc-1)+2).contains("11"))
         //   ||(dadesArxiuData.value(llista*(numeroLiniesDadesJoc-1)+2).contains("10")) ){
       if(esSolitariAmbFinalMarcat(
             dadesArxiuData.value(llista*(numeroLiniesDadesJoc)+2))) {
          nomJoc=nomJoc+" *" ;}
       item->setText(0,nomJoc);
       item->setToolTip(0,item->text(0));
       //linea 0: codi joc, tipus moviment
       item->setText(1,dadesArxiuData.value(llista*(numeroLiniesDadesJoc)));
       //linea 1: files i columnes
       item->setText(2,dadesArxiuData.value(llista*(numeroLiniesDadesJoc)+1));
       //linea 2: estat de les fitxes
       item->setText(3,dadesArxiuData.value(llista*(numeroLiniesDadesJoc)+2));
       //linea 3: codi del nom del joc
       item->setText(4,dadesArxiuData.value(llista*(numeroLiniesDadesJoc)+3));
       //posam l'icone OK si hi ha un rècord
       item->setIcon(0,QIcon(posaIconeOK(codi.value(0))));
       itemsArbre.append(item);
       }
     arbreModalitatsJocPersonalitzatsTreeWidget->insertTopLevelItems(0,itemsArbre);
     arbreModalitatsJocPersonalitzatsTreeWidget->expandAll();
     arbreModalitatsJocPersonalitzatsTreeWidget->sortItems(0,Qt::AscendingOrder);
     //Afegim el nombre de jocs de l'arbre al ròtul
     item->setText(0,tr("Jocs personalitzats")+" ("+QString::number(
          arbreModalitatsJocPersonalitzatsTreeWidget->topLevelItemCount()) +")");
         }
QApplication::setOverrideCursor(Qt::ArrowCursor);
}


/* Elimina l'arxiu de la solució del solitari personalitzat
 * actual
 */
void frmPrincipal::solitariPersonalitzat_eliminaArxiuSolucio(){
 return;
 if(arbreModalitatsJocTreeWidget->selectedItems().count()>0){
    if( (solitariPersonalitzat_esPersonalitzat(
       arbreModalitatsJocTreeWidget->selectedItems().first()->text(1)))
       || (taulerJoc->solitariPersonalitzat()) ){
    comprovaDirectoriHome();
    QString nomArxiu=nomArxiuJoc(2);
   /*Això és necessari per evitar eliminar arxius d'altres
   jocs que tenguin solucions noves*/
    if(solitariPersonalitzat_esPersonalitzat(nomArxiu) ){
    QFile arxiu(nomArxiu);
    if (arxiu.exists()){
        arxiu.remove();
        qApp->processEvents();
        nomArxiu=nomArxiuJoc(1);
        QFile arxiu1(nomArxiu);
        arxiu1.remove();
        qApp->processEvents();
     }
     }
    }//if arbre-text
   }//if arbre-count
}

/* Retorna el nou codi del solitari personalitzat
 */
QString frmPrincipal::solitariPersonalitzat_nouCodiJoc(bool nou){
    QSettings codiJocPersonalitzat;
    int codi=codiJocPersonalitzat.value( QString("General/codiJocPer"),10000).toInt();
    codi++;
    if(nou){
    QSettings().setValue("General/codiJocPer",QString("%1").arg(codi));}
    return QString("%1").arg(codi);
}

/* Determina si el solitari actual és o no
 * personalitzat
 */
bool frmPrincipal::solitariPersonalitzat_esPersonalitzat(QString joc){
  return (joc.contains("1001"))
  || (joc.contains("1002"))
  || (joc.contains("1003"));
}


/* Gestiona el canvi de selecció
 * de la fulla del tab amb els arbres de jocs
 * i solucions
 */
void frmPrincipal::canviTabSeleccionat( int tabSeleccionat){
    if(tabSeleccionat==0) {
     //tab dels jocs del programa
      seleccioModalitatJoc();}
    else if (tabSeleccionat==2) {
     //Forçam que hi hagi un ítem seleccionat
     if(arbreModalitatsJocPersonalitzatsTreeWidget->children().count()>0){
     if(arbreModalitatsJocPersonalitzatsTreeWidget->selectedItems().empty()){
        arbreModalitatsJocPersonalitzatsTreeWidget->setCurrentItem(
                    arbreModalitatsJocPersonalitzatsTreeWidget->topLevelItem(0));}
      //tab dels jocs personalitzats
      seleccioModalitatJocPersonalitzat();}}
}

/* Retorna el tipus de moviment en text
 * (invers/diagonal)
 */
QString frmPrincipal::afageixTipusMovimentNomJoc(QString tipus){
    if(tipus.contains(" 2 ")){
        return tr(" - invers");
    }
    else if (tipus.contains(" 3 ")){
        return tr(" - diagonal");
    }
    else return "";
}

/* Retorna el nom del joc
 * (sense afegitons segons el paràmetre)
 */
QString frmPrincipal::nomDelJoc(QString codi, bool complet){
    //Cadenes amb els noms de les modalitats de joc per a la traducció
    //El codi de joc de data.sol cal que coincideixi amb l'index a l'array
    //El primer és el ròtul de l'arbre amb les modalitats del joc
        /* 17/06/12 v. 1.3
         * S'ha modificat tot el sistema de traducció per evitar haver de posar
         * totes les cadenes que només es diferencien en el número d'ordre
         * Ara, cada cadena única està a la matriu següent, i desprès
         * s'assigna un numero d'ordre segons les repeticions
         * (amb un arxiu ini)
         */
    static const char *const nomModalitatsJoc[] = {
        QT_TR_NOOP("Modalitats del joc"),
        QT_TR_NOOP("Clàssic"), // 1
        QT_TR_NOOP("Clàssic - simetria"), // 2
        QT_TR_NOOP("Clàssic - pentàgon"), //3
        QT_TR_NOOP("Clàssic - creu petita"), //4
        QT_TR_NOOP("Clàssic - creu gran"), //5
        //  QT_TR_NOOP("Clàssic - invers"), // 6->1
        QT_TR_NOOP("Solitari estrella 7x7"), //6
        QT_TR_NOOP("Clàssic - superior"), // 7
        QT_TR_NOOP("Clàssic - inferior"), //8
        QT_TR_NOOP("Clàssic - fletxa"), //9
        QT_TR_NOOP("Clàssic - piràmide"), //10
        QT_TR_NOOP("Clàssic - diamant"), //11
        QT_TR_NOOP("Clàssic - rombe"), //12
        QT_TR_NOOP("Solitari 3x5"), //13
        QT_TR_NOOP("Triangular 4x7"), //14
        QT_TR_NOOP("Europeu"), //15
        QT_TR_NOOP("Asimètric 8x8"), //16
        //  QT_TR_NOOP("Clàssic - diagonal"), //17->1
        QT_TR_NOOP("Solitari 6x7"), //107->17
        QT_TR_NOOP("Asimètric - superior"), //18
        QT_TR_NOOP("Asimètric 8x8"), //19
        QT_TR_NOOP("Clàssic - central"), //20
        // QT_TR_NOOP("Europeu - diagonal"), //21->15
        QT_TR_NOOP("Solitari OK"), //106->21
        QT_TR_NOOP("Quadrat 5x5"), //22
        QT_TR_NOOP("Clàssic - quadrat central"), //23
        QT_TR_NOOP("Clàssic - rectangle central"), //24
        QT_TR_NOOP("Clàssic - arbre"), //25
        QT_TR_NOOP("Quadrat 5x5 - central"), //26
        QT_TR_NOOP("Quadrat 5x5 - H"), //27
        QT_TR_NOOP("Wiegleb"), //28
        QT_TR_NOOP("Diamant 9x9"), //29
        QT_TR_NOOP("Europeu - creu"), //30
        QT_TR_NOOP("Wiegleb - clàssic"), //31
        //   QT_TR_NOOP("Europeu diagonal"), //32->15
        QT_TR_NOOP("Solitari 6x6"), //104->32
        QT_TR_NOOP("Quadrat 6x6"), //33
        QT_TR_NOOP("Diamant 5x5"), //34
        QT_TR_NOOP("Diamant 7x7"), //35
        QT_TR_NOOP("Anglès antic"), //36
        QT_TR_NOOP("Incomplet 6x6"), //37
        QT_TR_NOOP("Incomplet 7x7"), //38
        QT_TR_NOOP("Wiegleb reduit"), //39
        QT_TR_NOOP("Solitari 8x9"), //40
        QT_TR_NOOP("Solitari 5x6"), //41
        QT_TR_NOOP("Wiegleb - fletxa"), //42
        QT_TR_NOOP("Clàssic - E"), //43
        QT_TR_NOOP("Clàssic - R"), //44
        QT_TR_NOOP("Clàssic - T"), //45
        QT_TR_NOOP("Solitari 5x6"), //46
        QT_TR_NOOP("Quadrat 6x6"), //47
        QT_TR_NOOP("Quadrat 5x5 - quadrats"), //48
        QT_TR_NOOP("Triangular 4x7"), //49
        QT_TR_NOOP("Triangular 4x7 - quadrat"), // 50
        QT_TR_NOOP("Triangular 4x7 - piràmide"), //51
        QT_TR_NOOP("Quadrat 5x5 - piràmide"), //52
        QT_TR_NOOP("Solitari 7x5"), //53
        QT_TR_NOOP("Asimètric 6x6"), //54
        QT_TR_NOOP("Quadrat 9x9"), //55
        QT_TR_NOOP("Anglès antic - diamant"), //56
        QT_TR_NOOP("Triangular 5"), // 57
        QT_TR_NOOP("Triangular 4"), //58
        QT_TR_NOOP("Triangular 6"), //59
        QT_TR_NOOP("Wiegleb - creu petita"), //60
        QT_TR_NOOP("Wiegleb - simetria"), //61
        //   QT_TR_NOOP("Wiegleb diagonal"), //62->28
        QT_TR_NOOP("Clàssic - quadrat"), //102->62
        QT_TR_NOOP("Asimètric 6x6"), //63
        QT_TR_NOOP("Asimètric 8x8"), //64
        //    QT_TR_NOOP("Europeu invers"), //65->15
        QT_TR_NOOP("Clàssic - cúpula"), //101->65
        //    QT_TR_NOOP("Wiegleb invers"), //66->28
        QT_TR_NOOP("Clàssic - Cabana"), //100->66
        QT_TR_NOOP("Wiegleb reduit"), // 67
        QT_TR_NOOP("Solitari 3x5 bis"), //68
        QT_TR_NOOP("Solitari 4x4"), //69
        QT_TR_NOOP("Solitari 6x5"),//70
        QT_TR_NOOP("Solitari 4x5"),//71
        QT_TR_NOOP("Triangular 7"), //72
        QT_TR_NOOP("Triangular 8"), //73
        QT_TR_NOOP("Triangular 9"), //74
        QT_TR_NOOP("Europeu - quadrat"), //75
        QT_TR_NOOP("Clàssic - molinet"), //76
        QT_TR_NOOP("Triangular 10"), //77
        QT_TR_NOOP("Quadrat 8x8"), //78
        QT_TR_NOOP("Solitari 7x5"), //79
        QT_TR_NOOP("Clàssic - quadrat central"), //80
        QT_TR_NOOP("Clàssic - O"), //81
        //nous versió 1.2
        QT_TR_NOOP("Dos quadrats 10x10"), //82
        QT_TR_NOOP("Dos quadrats 11x11"), //83
        QT_TR_NOOP("Tres quadrats 16x16"), //84
        QT_TR_NOOP("Dos quadrats 9x9"), //85
        QT_TR_NOOP("Tres quadrats 13x13"), //86
        QT_TR_NOOP("Quatre quadrats 13x13"), //87
        QT_TR_NOOP("Clàssic ampliat"), //88
        QT_TR_NOOP("Diamant 9x9"), //89
        QT_TR_NOOP("Rombe 36"), //90
        // Nous versió 2.0
        QT_TR_NOOP("Hexagonal inclinat"), //91
        QT_TR_NOOP("Clàssic - 4 forquilles"), //92
        QT_TR_NOOP("Pentagonal"), //93
        QT_TR_NOOP("Hexagonal 7x11"), //94
        QT_TR_NOOP("Clàssic - Dos quadrats"), //95
        QT_TR_NOOP("Clàssic - Banyes"), //96
        QT_TR_NOOP("Clàssic - X"), //97
        QT_TR_NOOP("Clàssic - Torxa"), //98
        QT_TR_NOOP("Clàssic - Palau"), //99
        //   QT_TR_NOOP("Clàssic - quadrat"), //102->28
        QT_TR_NOOP("Personalitzat"), //105->100
        QT_TR_NOOP("Solitari a l'atzar"), //103->101
        //   QT_TR_NOOP("Personalitzat - diagonal"), //109->105
        //   QT_TR_NOOP("Personalitzat - invers"), //110->105
        QT_TR_NOOP("Solo"), //102
        QT_TR_NOOP("Solitari 8x3"), //103
        QT_TR_NOOP("Solitari 8x6"), //104
        0
    };

    QString nom=tr(nomModalitatsJoc[codi.toInt()]);
    if (!complet){
        QStringList nomList=nom.split(" - ");
       nom=nomList.value(0);
    }
    return nom;
}

/* Arbre del joc actual.
 * Es fa servir per saber quin tipus de joc
 * està actiu
 * 0: arbre dels jocs del programa
 * 1: arbre dels jocs personalitzats
 */
void frmPrincipal::setArbreJocsActual(int valor){
    p_arbreJocsActual=valor;
}

/* Actualitza les cadenes que conservan la configuració
 * de les fitxes a l'inici del joc
 */
void frmPrincipal::actualitzaConfiguracionsInicials(){
//qCritical("solucioJocActual_configuracioInicial %s",qPrintable(solucioJocActual_configuracioInicial));
solucioJocActual_configuracioInicial.clear();
solucioJocActual_configuracioInicial.append(taulerJoc->configuracioActual(true));
//jocActual_configuracioInicialFitxesMarcades.clear();
//jocActual_configuracioInicialFitxesMarcades.append(
//            taulerJoc->configuracioInicialAmbFitxesMarcades());
//qCritical("jocActual_configuracioInicialFitxesMarcades %s",qPrintable(jocActual_configuracioInicialFitxesMarcades));
}



/* Versió 2.1
 * Degut als canvis de QHash a QMap a la migració a Qt5,
 * cal canviar els noms dels arxius de solucions anteriors
 * a aquesta versió. No és possible fer el canvi dels arxius
 * de solitaris personalitzats
 */
void frmPrincipal::actualitzaCodisArxiusDeSolucio(){
//Si no existeix el directori $home/Solitari
// o ja s'ha fet la migració, no feim res.
QDir dirArxiu(QDir::homePath ());
if ((dirArxiu.exists(qApp->applicationName())) && (QSettings().value("General/migracio")<"2.1") ){
  bool migracio=false;
  //Camviam el nom del directori Solitari a Solitari_seg
  QApplication::setOverrideCursor(Qt::WaitCursor);
  QDir dirSolitari(QDir::homePath ()+QDir().separator()+qApp->applicationName());
  dirSolitari.rename(QDir::homePath ()+QDir().separator()+qApp->applicationName(),
                QDir::homePath ()+QDir().separator()+qApp->applicationName()+"_seg");
  //tornam a generar el direcotri Solitari
  comprovaDirectoriHome();
 //Primer carregam els noms dels arxius antics i nous de l'arxiu codis.txt
 QStringList nomsArxius;
 QString nomArxiu=directoriLinux()+QDir().separator()+"games/codis.txt";
 QFile arxiuData(nomArxiu);
 if (!arxiuData.open(QIODevice::ReadOnly | QIODevice::Text)){
     QMessageBox::critical(this,  tr("Solitari"),
                             QString(tr("No s'ha trobat l'arxiu %1")).arg(nomArxiu) );
      return ;
  }
  QTextStream entrada(&arxiuData);
  QString linia0 = entrada.readLine();
  nomsArxius.clear();
  while (!linia0.isNull()) {
         nomsArxius.append(linia0);
         linia0 = entrada.readLine();
       }//final del while de la lectura de l'arxiu
 // qDebug("noms arxius %d",nomsArxius.count());
  /* Per cada nom a un lloc senar de la llista, cal comprovar
   * si existeix l'arxiu en el directori /Solitari
   * i, en cas positiu, canviar el nom de l'arxiu pel nom nou i
   * eliminar l'arxiu de posicions eliminades (amb el mateix nom
   * però extensió .txt
   */
   for(int i=0 ; i<nomsArxius.count()/2;++i){
     //Els arxius de solucions originals estan en el directori Solitari_seg
     QString nomArxiuSolucionsAntic=QDir::homePath ()+QDir().separator()+
             qApp->applicationName()+"_seg"+QDir().separator()+nomsArxius.value(i*2)+".sol";
     QString nomArxiuSolucionsNou=QDir::homePath ()+QDir().separator()+
             qApp->applicationName()+QDir().separator()+nomsArxius.value(i*2+1)+".sol";
     QFile arxiuSolucions(nomArxiuSolucionsAntic);
     //Renomenam l'arxiu de solucions
     if (arxiuSolucions.exists()){
       // qCritical("Existeix l'arxiu %s", qPrintable(nomArxiuSolucionsAntic));
        (arxiuSolucions.copy(nomArxiuSolucionsNou));
        migracio=true;
     }

    //Copiam l'arxiu game-per.data (si existeix)
     QString nomarxiuSolitarisPersonalitzats=QDir::homePath ()+QDir().separator()+
             qApp->applicationName()+"_seg"+QDir().separator()+"game-per.dat";
     QFile arxiuSolitarisPersonalitzats(nomarxiuSolitarisPersonalitzats);
     if (arxiuSolitarisPersonalitzats.exists()){
        arxiuSolitarisPersonalitzats.copy(QDir::homePath ()+QDir().separator()+
                                          qApp->applicationName()+QDir().separator()+"game-per.dat");
        migracio=true;
     }
    }
   if (migracio){
   QDesktopServices::openUrl(QUrl("file:///"+directoriLinux()+
                                  QDir().separator()+
                                  DIR_HELP+
                                  QDir().separator()+
                                  "migracio.html", QUrl::TolerantMode));
   //Desam a la configuració que s'ha fet la migració
   QSettings().setValue(QString("General/migracio"),"2.1");
   }
 QApplication::setOverrideCursor(Qt::ArrowCursor);
 }
}
