//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
// DBC Decriptor                                                              //
//                                                                            //
// Made by Pierre Hudelaine                                                   //
//                                                                            //
// Contact: pierre.hudelaine@hds.utc.fr                                       //
//                                                                            //
// Translate a DBC file to Pacpus code                                        //
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QString>
#include <QFileDialog>
#include <QTextStream>
#include <QDebug>
#include <QDate>


//----------------------------------------------------------------------------//
// Constructor                                                                //
//----------------------------------------------------------------------------//
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    connect(ui->actionOpen, SIGNAL(triggered()), this, SLOT(openDBCFile()));
    connect(ui->actionClose_all_files, SIGNAL(triggered()), this, SLOT(clearDBC()));
    connect(ui->actionQuitter, SIGNAL(triggered()), this, SLOT(close()));
    connect(ui->pushButton_open_file, SIGNAL(clicked()), this, SLOT(openDBCFile()));

    ui->label_file_error->setText("");
    ui->label_value_frame_id->setText("");
    ui->label_value_frame_name->setText("");
    ui->label_value_number_of_signals->setText("");
    ui->label_value_total_frames->setText("0");
    ui->label_value_total_signals->setText("0");
    ui->lineEdit_output_path->setText(QApplication::applicationDirPath());
}


//----------------------------------------------------------------------------//
// Destructor                                                                 //
//----------------------------------------------------------------------------//
MainWindow::~MainWindow()
{
    delete ui;
}


//----------------------------------------------------------------------------//
// Open the DBC file                                                          //
//----------------------------------------------------------------------------//
void MainWindow::openDBCFile()
{
    clearDBC();

    dbcFiles_.fileName = QFileDialog::getOpenFileName(this, "Open dbc file", "", "dbc files (*.dbc);;Text files (*.txt);;All files (*.*)");

    QFile file(dbcFiles_.fileName);

    if (!file.open(QIODevice::ReadOnly))
        ui->label_file_error->setText("<font color=\"#C80000\">Can not open the file</font>");
    else
    {
        QTextStream stream(&file);
        dbcFiles_.content = stream.readAll().split('\n');

        QStringList signalName;
        bool frameFound = false;
        StructFrame tmpFrame;
        tmpFrame.frameID = 0;
        tmpFrame.frameName = "";
        tmpFrame.numberOfSignals = 0;

        for (int i = 0; i < dbcFiles_.content.size(); i++)
        {
            if (frameFound)
            {
                // signalMnemo is the beginning if a line containing a signal information
                if (dbcFiles_.content[i].startsWith(signalMnemo))
                {
                    tmpFrame.numberOfSignals++;
                    getSignalParameters(dbcFiles_.content[i], &tmpFrame);
                }
                else
                    frameFound = false;
            }

            // "BO_" is the beginning of a line containing a frame information and all signals are following
            if (dbcFiles_.content[i].startsWith(signalInfoMnemo))
            {
                int numberOfSpace = 0, j = 0;
                QString tmp;

                frameFound = true;

                // Get the ID of the frame
                while(numberOfSpace != 2)
                {
                    if (dbcFiles_.content[i][j] == ' ')
                        numberOfSpace++;
                    if (numberOfSpace == 1)
                        tmp.append(dbcFiles_.content[i][j]);
                    j++;
                }

                tmpFrame.frameID = tmp.toInt();

                tmp = "";

                // Get the name of the frame
                while(dbcFiles_.content[i][j] != ':')
                {
                    tmp.append(dbcFiles_.content[i][j]);
                    j++;
                }

                tmpFrame.frameName = tmp;
            }
            else if (dbcFiles_.content[i].startsWith(commentMnemo))
                findComment(i); // Get the comment at the end of the DBC file
            else if (dbcFiles_.content[i].startsWith(valueInfoMnemo))                
                findValueDescription(i); // Get the value descritpion at the end of the DBC file

            // If a hole frame has been treated it's registered in the vector
            if (tmpFrame.numberOfSignals != 0 && !frameFound)
            {
                dbcFiles_.canFrames.append(tmpFrame);
                ui->label_value_total_frames->setText(QString().setNum(ui->label_value_total_frames->text().toInt() + 1));
                ui->label_value_total_signals->setText(QString().setNum(ui->label_value_total_signals->text().toInt() + tmpFrame.numberOfSignals));
                tmpFrame.frameID = 0;
                tmpFrame.frameName = "";
                tmpFrame.numberOfSignals = 0;
                tmpFrame.signalsVector.clear();
            }
        }

        // Frames are added in the list
        for (int i = 0; i < dbcFiles_.canFrames.size(); i++)
        {
            if (dbcFiles_.canFrames[i].frameID >= 255)
                signalName.append("0x" + QString().setNum(dbcFiles_.canFrames[i].frameID, 16).toUpper() + " " + dbcFiles_.canFrames[i].frameName);
            else
                signalName.append("0x0" + QString().setNum(dbcFiles_.canFrames[i].frameID, 16).toUpper() + " " + dbcFiles_.canFrames[i].frameName);
        }

        ui->listWidget_signals->addItems(signalName);
        file.close();

        //printAllFrames();
    }
}


//----------------------------------------------------------------------------//
// Print the parameters for a specific frame                                  //
//----------------------------------------------------------------------------//
void MainWindow::printFrame(int i, int j)
{
    qDebug() << dbcFiles_.canFrames[i].signalsVector[j].signalName << " "
             << dbcFiles_.canFrames[i].signalsVector[j].startBit << " "
             << dbcFiles_.canFrames[i].signalsVector[j].length << " "
             << ((dbcFiles_.canFrames[i].signalsVector[j].order) ? "Motorola" : "Intel")
             << " " << ((dbcFiles_.canFrames[i].signalsVector[j].valueType) ? "Signed" : "Unsigned")
             << " " << dbcFiles_.canFrames[i].signalsVector[j].gain << " "
             << dbcFiles_.canFrames[i].signalsVector[j].offset << " "
             << dbcFiles_.canFrames[i].signalsVector[j].min << " "
             << dbcFiles_.canFrames[i].signalsVector[j].max << " "
             << ((dbcFiles_.canFrames[i].signalsVector[j].unit != "") ? dbcFiles_.canFrames[i].signalsVector[j].unit : "")
             << dbcFiles_.canFrames[i].signalsVector[j].comment;
}


//----------------------------------------------------------------------------//
// Print the parameters of all frames                                         //
//----------------------------------------------------------------------------//
void MainWindow::printAllFrames()
{
    for (int i = 0; i < dbcFiles_.canFrames.size(); i++)
    {
        for (int j = 0; j < dbcFiles_.canFrames[i].signalsVector.size(); j++)
            printFrame(i, j);
    }
}


//----------------------------------------------------------------------------//
// Get the the signals informations in the DBC file                           //
//----------------------------------------------------------------------------//
void MainWindow::getSignalParameters(QString actualLine, StructFrame * actualCanFrame)
{
    StructSignal tmpSignal;

    tmpSignal.order = true;
    tmpSignal.gain = 0.0;
    tmpSignal.length = 0;
    tmpSignal.offset = 0.0;
    tmpSignal.signalName = "";
    tmpSignal.valueType = true;
    tmpSignal.startBit = 0;
    tmpSignal.unit = "";
    tmpSignal.comment = "";
    tmpSignal.description = "";

    // Removing the untreated and unsued caracters
    actualLine.remove('(');
    actualLine.remove(')');
    actualLine.remove('[');
    actualLine.remove(']');
    QStringList cutLine = actualLine.split(' ');

    // Get the name
    tmpSignal.signalName = cutLine.at(2);
    cutLine = actualLine.split(" : ");

    // Get the second part with the signal parameters for example : 63|8@0+ // 63 = startBit; 8 = length; 0 = Motorola order; + = Unsigned value
    QStringList cutLineValue = cutLine.at(1).split(' ');
    tmpSignal.startBit = cutLineValue.at(0).split('|').at(0).toInt();
    tmpSignal.length = cutLineValue.at(0).split('|').at(1).split('@').at(0).toInt();
    if (cutLineValue.at(0).split('|').at(1).split('@').at(1).at(0) == '1')
        tmpSignal.order = false;
    if (cutLineValue.at(0).split('|').at(1).split('@').at(1).at(1) == '+')
        tmpSignal.valueType = false;

    // Get the offset and the gain for example : (0.05,2) // 0.05 = gain; 2 = offset;
    tmpSignal.gain = cutLineValue.at(1).split(',').at(0).toDouble();
    tmpSignal.offset = cutLineValue.at(1).split(',').at(1).toDouble();

    // Get the max and min for exemple : [-6.4|6.35] // -6.4 = max; 6.35 = max;
    tmpSignal.min = cutLineValue.at(2).split('|').at(0).toDouble();
    tmpSignal.max = cutLineValue.at(2).split('|').at(1).toDouble();

    // Get the unit for example : "m/s" // m/s = unit
    tmpSignal.unit = cutLineValue.at(3);
    tmpSignal.unit.remove('"');

    actualCanFrame->signalsVector.append(tmpSignal);
}


//----------------------------------------------------------------------------//
// Find a comment and associate it to the signal                              //
//----------------------------------------------------------------------------//
void MainWindow::findComment(int k)
{
    for (int i = 0; i < dbcFiles_.canFrames.size(); i++)
    {
        for (int j = 0; j < dbcFiles_.canFrames[i].signalsVector.size(); j++)
        {
            if (dbcFiles_.content[k].contains(dbcFiles_.canFrames[i].signalsVector[j].signalName))
            {
                dbcFiles_.canFrames[i].signalsVector[j].comment = dbcFiles_.content[k].split('"').at(1);

                while (dbcFiles_.content[k].at(dbcFiles_.content[k].size() - 2) != ';')
                {
                    k++;
                    dbcFiles_.canFrames[i].signalsVector[j].comment += dbcFiles_.content[k];
                }
                return;
            }
        }
    }
}


//----------------------------------------------------------------------------//
// Find the value description and associate it to the signal                  //
//----------------------------------------------------------------------------//
void MainWindow::findValueDescription(int k)
{
    for (int i = 0; i < dbcFiles_.canFrames.size(); i++)
    {
        for (int j = 0; j < dbcFiles_.canFrames[i].signalsVector.size(); j++)
        {
            if (dbcFiles_.content[k].contains(dbcFiles_.canFrames[i].signalsVector[j].signalName))
            {
                dbcFiles_.canFrames[i].signalsVector[j].description = dbcFiles_.content[k].right(dbcFiles_.content[k].length() - (dbcFiles_.content[k].indexOf(dbcFiles_.canFrames[i].signalsVector[j].signalName) + dbcFiles_.canFrames[i].signalsVector[j].signalName.length()));
                return;
            }
        }
    }
}


//----------------------------------------------------------------------------//
// Called from the HMI to clear the last information                          //
//----------------------------------------------------------------------------//
void MainWindow::clearDBC()
{
    dbcFiles_.canFrames.clear();
    dbcFiles_.content.clear();
    dbcFiles_.fileName = "";
    ui->listWidget_signals->clear();

    ui->label_file_error->setText("");
    ui->label_value_frame_id->setText("");
    ui->label_value_frame_name->setText("");
    ui->label_value_number_of_signals->setText("");
    ui->label_value_total_frames->setText("0");
    ui->label_value_total_signals->setText("0");
}


//----------------------------------------------------------------------------//
// Actualize the HMI with the last information                                //
//----------------------------------------------------------------------------//
void MainWindow::on_listWidget_signals_currentRowChanged(int currentRow)
{
    if (currentRow >= 0)
    {
        if (dbcFiles_.canFrames[currentRow].frameID >= 255)
            ui->label_value_frame_id->setText("0x" + QString().setNum(dbcFiles_.canFrames[currentRow].frameID, 16).toUpper());
        else
            ui->label_value_frame_id->setText("0x0" + QString().setNum(dbcFiles_.canFrames[currentRow].frameID, 16).toUpper());

        ui->label_value_frame_name->setText(dbcFiles_.canFrames[currentRow].frameName);
        ui->label_value_number_of_signals->setText(QString().setNum(dbcFiles_.canFrames[currentRow].numberOfSignals));
    }
}


//----------------------------------------------------------------------------//
// Generate the c++ files from the dbc information previouly registered       //
//----------------------------------------------------------------------------//
void MainWindow::on_pushButton_generate_clicked()
{
    QDate date(QDate::currentDate());

    // Creating the beginnig of the structure file
    QString outputStructFile = templateStructFile;
    outputStructFile.insert(outputStructFile.indexOf("created:") + 8, "    " + QString().setNum(date.year()) + "/" + QString().setNum(date.month()) + "/" + QString().setNum(date.day()));
    outputStructFile.insert(outputStructFile.indexOf("#ifndef __STRUCTURECAN") + 22, ui->lineEdit_export_name->text().toUpper());
    outputStructFile.insert(outputStructFile.indexOf("#define __STRUCTURECAN") + 22, ui->lineEdit_export_name->text().toUpper());

    for (int i = 0; i < dbcFiles_.canFrames.size(); i++)
    {
        QString outputCPPFile = templateCPPFile;
        QString outputHFile = templateHFile;

        // Creating the beginning of each c++ files
        outputCPPFile.insert(outputCPPFile.indexOf("created:") + 8, "    " + QString().setNum(date.year()) + "/" + QString().setNum(date.month()) + "/" + QString().setNum(date.day()));
        outputCPPFile.insert(outputCPPFile.indexOf("#include \"CanFrame.h\"") + 18, dbcFiles_.canFrames[i].frameName);
        outputCPPFile.insert(outputCPPFile.indexOf("void CanFrame") + 13, dbcFiles_.canFrames[i].frameName);

        // Creating the beginning of each h files
        outputHFile.insert(outputHFile.indexOf("created:") + 8, "    " + QString().setNum(date.year()) + "/" + QString().setNum(date.month()) + "/" + QString().setNum(date.day()));
        outputHFile.insert(outputHFile.indexOf("#ifndef __CanFrame") + 18, dbcFiles_.canFrames[i].frameName);
        outputHFile.insert(outputHFile.indexOf("#define __CanFrame") + 18, dbcFiles_.canFrames[i].frameName);
        outputHFile.insert(outputHFile.indexOf("#include \"structureCan") + 22, ui->lineEdit_export_name->text());
        outputHFile.insert(outputHFile.indexOf("class CAN") + 9, ui->lineEdit_export_name->text().toUpper());
        outputHFile.insert(outputHFile.indexOf("_API CanFrame") + 13, dbcFiles_.canFrames[i].frameName);
        outputHFile.insert(outputHFile.indexOf("CanFrame()") + 8, dbcFiles_.canFrames[i].frameName);
        outputHFile.insert(outputHFile.indexOf("~CanFrame()") + 9, dbcFiles_.canFrames[i].frameName);
        outputHFile.insert(outputHFile.indexOf("Struct data_;") + 6, dbcFiles_.canFrames[i].frameName);
        outputHFile.insert(outputHFile.indexOf("return sizeof(Struct)") + 20, dbcFiles_.canFrames[i].frameName);

        // Adding the structure of frames
        outputStructFile.insert(outputStructFile.indexOf("#include \"Pacpus/kernel/road_time.h") + 36, "\n\ntypedef struct\n{\n} Struct" + dbcFiles_.canFrames[i].frameName + ";");

        for (int j = 0; j < dbcFiles_.canFrames[i].signalsVector.size(); j++)
        {
            QString tmpCpp = "\n";

            // If variables are bool
            if (dbcFiles_.canFrames[i].signalsVector[j].length == 1)
            {
                tmpCpp.append("	data_." + dbcFiles_.canFrames[i].signalsVector[j].signalName + " = mDecodeToBool(d_.frame.data, " + QString().setNum(dbcFiles_.canFrames[i].signalsVector[j].startBit) + ");");
                if (dbcFiles_.canFrames[i].signalsVector[j].description != "")
                    outputStructFile.insert(outputStructFile.indexOf("} Struct" + dbcFiles_.canFrames[i].frameName), "	bool " + dbcFiles_.canFrames[i].signalsVector[j].signalName + "; /// " + dbcFiles_.canFrames[i].signalsVector[j].description + "\n");
                else
                    outputStructFile.insert(outputStructFile.indexOf("} Struct" + dbcFiles_.canFrames[i].frameName), "	bool " + dbcFiles_.canFrames[i].signalsVector[j].signalName + ";\n");
            }
            else
            {
                // If variables are Motorola or Intel
                if (dbcFiles_.canFrames[i].signalsVector[j].order)
                    tmpCpp.append("	if (mDecodeTo");
                else
                    tmpCpp.append("	if (iDecodeTo");

                // If variables are signed...
                if (dbcFiles_.canFrames[i].signalsVector[j].valueType)
                {
                    if (dbcFiles_.canFrames[i].signalsVector[j].length <= 8)
                        tmpCpp.append("I8(&ctmp, ");
                    else if (dbcFiles_.canFrames[i].signalsVector[j].length <= 16)
                        tmpCpp.append("I16(&stmp, ");
                    else if (dbcFiles_.canFrames[i].signalsVector[j].length <= 32)
                        tmpCpp.append("I32(&ltmp, ");
                    else if (dbcFiles_.canFrames[i].signalsVector[j].length <= 64)
                        tmpCpp.append("I64(&lltmp, ");
                }
                else // ...Or not signed
                {
                    if (dbcFiles_.canFrames[i].signalsVector[j].length <= 8)
                        tmpCpp.append("UI8(&uctmp, ");
                    else if (dbcFiles_.canFrames[i].signalsVector[j].length <= 16)
                        tmpCpp.append("UI16(&ustmp, ");
                    else if (dbcFiles_.canFrames[i].signalsVector[j].length <= 32)
                        tmpCpp.append("UI32(&ultmp, ");
                    else if (dbcFiles_.canFrames[i].signalsVector[j].length <= 64)
                        tmpCpp.append("UI64(&ulltmp, ");
                }

                // Code c++ added in the QString
                tmpCpp.append("d_.frame.data, " + QString().setNum(dbcFiles_.canFrames[i].signalsVector[j].startBit) + ", " + QString().setNum(dbcFiles_.canFrames[i].signalsVector[j].length) + "))\n");
                tmpCpp.append("		data_." + dbcFiles_.canFrames[i].signalsVector[j].signalName + " = ");

                // Find the c++ type between double or integer
                if (floor(dbcFiles_.canFrames[i].signalsVector[j].gain) == dbcFiles_.canFrames[i].signalsVector[j].gain)
                {
                    // If it's need a brace in c++
                    if (dbcFiles_.canFrames[i].signalsVector[j].gain != 1 && dbcFiles_.canFrames[i].signalsVector[j].offset != 0)
                        tmpCpp.append("(");

                    // Define the type of the pointer which will store temporally the data
                    if (!dbcFiles_.canFrames[i].signalsVector[j].valueType)
                        tmpCpp.append("u");

                    if (dbcFiles_.canFrames[i].signalsVector[j].length <= 8)
                        tmpCpp.append("ctmp");
                    else if (dbcFiles_.canFrames[i].signalsVector[j].length <= 16)
                        tmpCpp.append("stmp");
                    else if (dbcFiles_.canFrames[i].signalsVector[j].length <= 32)
                        tmpCpp.append("ltmp");
                    else if (dbcFiles_.canFrames[i].signalsVector[j].length <= 64)
                        tmpCpp.append("lltmp");

                    // Setting the gain and the offset
                    if (dbcFiles_.canFrames[i].signalsVector[j].gain != 1 && dbcFiles_.canFrames[i].signalsVector[j].offset != 0)
                        tmpCpp.append(" * " + QString().setNum(dbcFiles_.canFrames[i].signalsVector[j].gain) + ") + " + QString().setNum(dbcFiles_.canFrames[i].signalsVector[j].offset) + ";");
                    else if (dbcFiles_.canFrames[i].signalsVector[j].gain != 1)
                        tmpCpp.append(" * " + QString().setNum(dbcFiles_.canFrames[i].signalsVector[j].gain) + ";");
                    else if (dbcFiles_.canFrames[i].signalsVector[j].offset != 0)
                        tmpCpp.append(" + " + QString().setNum(dbcFiles_.canFrames[i].signalsVector[j].offset) + ";");
                    else
                        tmpCpp.append(";");

                    // Adding the value in the structure
                    QString tmp;

                    // Find the c++ variable type /!\ May differ from the signal !!!!
                    if (dbcFiles_.canFrames[i].signalsVector[j].offset < 0 && !dbcFiles_.canFrames[i].signalsVector[j].valueType)
                        tmp.append("	int");
                    else
                        tmp.append("	uint");

                    if (dbcFiles_.canFrames[i].signalsVector[j].length <= 8)
                        tmp.append("8_t " + dbcFiles_.canFrames[i].signalsVector[j].signalName + ";");
                    else if (dbcFiles_.canFrames[i].signalsVector[j].length <= 16)
                        tmp.append("16_t " + dbcFiles_.canFrames[i].signalsVector[j].signalName + ";");
                    else if (dbcFiles_.canFrames[i].signalsVector[j].length <= 32)
                        tmp.append("32_t " + dbcFiles_.canFrames[i].signalsVector[j].signalName + ";");
                    else if (dbcFiles_.canFrames[i].signalsVector[j].length <= 64)
                        tmp.append("64_t " + dbcFiles_.canFrames[i].signalsVector[j].signalName + ";");

                    if (dbcFiles_.canFrames[i].signalsVector[j].description != "")
                        tmp.append(" /// " + dbcFiles_.canFrames[i].signalsVector[j].description);

                    outputStructFile.insert(outputStructFile.indexOf("} Struct" + dbcFiles_.canFrames[i].frameName), tmp + "\n");
                }
                else
                {
                    tmpCpp.append("static_cast<double>(");

                    if (dbcFiles_.canFrames[i].signalsVector[j].gain != 1 && dbcFiles_.canFrames[i].signalsVector[j].offset != 0)
                        tmpCpp.append("(");

                    if (!dbcFiles_.canFrames[i].signalsVector[j].valueType)
                        tmpCpp.append("u");

                    if (dbcFiles_.canFrames[i].signalsVector[j].length <= 8)
                        tmpCpp.append("ctmp");
                    else if (dbcFiles_.canFrames[i].signalsVector[j].length <= 16)
                        tmpCpp.append("stmp");
                    else if (dbcFiles_.canFrames[i].signalsVector[j].length <= 32)
                        tmpCpp.append("ltmp");
                    else if (dbcFiles_.canFrames[i].signalsVector[j].length <= 64)
                        tmpCpp.append("lltmp");

                    if (dbcFiles_.canFrames[i].signalsVector[j].gain != 1 && dbcFiles_.canFrames[i].signalsVector[j].offset != 0)
                        tmpCpp.append(" * " + QString().setNum(dbcFiles_.canFrames[i].signalsVector[j].gain) + ") + " + QString().setNum(dbcFiles_.canFrames[i].signalsVector[j].offset) + ");");
                    else if (dbcFiles_.canFrames[i].signalsVector[j].gain != 1)
                        tmpCpp.append(" * " + QString().setNum(dbcFiles_.canFrames[i].signalsVector[j].gain) + ");");
                    else if (dbcFiles_.canFrames[i].signalsVector[j].offset != 0)
                        tmpCpp.append(" + " + QString().setNum(dbcFiles_.canFrames[i].signalsVector[j].offset) + ");");
                    else
                        tmpCpp.append(");");

                    QString tmp = "";
                    if (dbcFiles_.canFrames[i].signalsVector[j].description != "")
                        tmp.append(" /// " + dbcFiles_.canFrames[i].signalsVector[j].description);

                    outputStructFile.insert(outputStructFile.indexOf("} Struct" + dbcFiles_.canFrames[i].frameName), "	double " + dbcFiles_.canFrames[i].signalsVector[j].signalName + "; " + tmp + "\n");
                }
            }
            if (dbcFiles_.canFrames[i].signalsVector[j].comment != "")
                tmpCpp.append(" /*" + dbcFiles_.canFrames[i].signalsVector[j].comment + "*/");
            outputCPPFile.insert(outputCPPFile.indexOf("unsigned char uctmp = 0") + 24, tmpCpp);
        }
        outputStructFile.insert(outputStructFile.indexOf("Struct" + dbcFiles_.canFrames[i].frameName + ";") + dbcFiles_.canFrames[i].frameName.size() + 7, "\n\ntypedef struct\n{\n	road_time_t time;\n	road_timerange_t timerange;\n	Struct" + dbcFiles_.canFrames[i].frameName + " d;\n} TimeStampedStruct" + dbcFiles_.canFrames[i].frameName + ";");

        QFile canFrameCpp(ui->lineEdit_output_path->text() + "/CanFrame" + dbcFiles_.canFrames[i].frameName + ".cpp");
        canFrameCpp.open(QIODevice::WriteOnly);
        QTextStream cppOut(&canFrameCpp);
        cppOut << outputCPPFile;
        canFrameCpp.close();

        QFile canFrameH(ui->lineEdit_output_path->text() + "/CanFrame" + dbcFiles_.canFrames[i].frameName + ".h");
        canFrameH.open(QIODevice::WriteOnly);
        QTextStream hOut(&canFrameH);
        hOut << outputHFile;
        canFrameH.close();
    }

    QFile struc(ui->lineEdit_output_path->text() + "/strucureCan" + ui->lineEdit_export_name->text() + ".h");
    struc.open(QIODevice::WriteOnly);
    QTextStream strucOut(&struc);
    strucOut << outputStructFile;
    struc.close();
}


//----------------------------------------------------------------------------//
// Unlock the pushButton "Generate" when a string is registerer               //
//----------------------------------------------------------------------------//
void MainWindow::on_lineEdit_export_name_textChanged(const QString &arg1)
{
    if (arg1 == "")
        ui->pushButton_generate->setEnabled(false);
    else
        ui->pushButton_generate->setEnabled(true);
}


//----------------------------------------------------------------------------//
// Select the output directory                                                //
//----------------------------------------------------------------------------//
void MainWindow::on_pushButton_output_path_clicked()
{
    QString tmp = "";
    if ((tmp = QFileDialog::getExistingDirectory(0, 0, ui->lineEdit_output_path->text())) != "")
        ui->lineEdit_output_path->setText(tmp);
}
