/*******************************************************************************
*                                                                              *
* Société de Transports de Montréal.                                    	   *
* 2012                                                                         *
*                                                                              *
* Projet Zones Tests                                                           *
*                                                                              *
*                                                                              *
*                                                                              *
*******************************************************************************/
/*
    Description:
	Page de visualisation des passages de train.  C'est cette classe qui gère
	la création et l'affichage des éléments graphiques ainsi que les événements
	de l'utilisateur.

*/

/* ************************************************************************** */
/* Revision:
### 20131024 JFM
    Verision d'origine.

### YYYMMDD Description du besoin ou du bug
    Description du changement.
 */

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


#include "LogViewPage.h"
#include <QGraphicsProxyWidget>
#include "Zonetest.h"
#include <QTextStream>


CLogViewPage::CLogViewPage(QGraphicsWidget *Parent)
{
	setParentItem(Parent);

	setAcceptsHoverEvents(true);



	mProgramHandle = 0;
	mZoomValue = 100;
	mStartTime = mStopTime = 0;
	mCurTimeSpan = 0;
	mMinTime = mMaxTime = 0;
	mCurPixelTickValue = 1;
	mMouseDragging = false;
    mViewType = UNKNOWN_LOG_TYPE;
	mPGTreshold = 0;
    mCtrlKeyDown = false;
    mShiftKeyDown = false;


	setFlag(QGraphicsItem::ItemIsFocusable);


	mStaticCursor1Pos =  mStaticCursor2Pos = 0;
	mCursorPos = 0;

	mBackgroundRect = new QGraphicsRectItem(boundingRect(), this);
	QPen rectpen;
	QBrush BackgroundBrush(QColor(245, 245, 255));
	mBackgroundRect->setBrush(BackgroundBrush);


	mCancelButton = new CTextButtonWidget("Fermer");
	mCancelButton->setParentItem(this);
	mCancelButton->setPos(850,700);
	connect(mCancelButton,SIGNAL(TxtButtonClicked(CTextButtonWidget*)),this,SLOT(ButtonClicked(CTextButtonWidget*)));

    //Setup ZT1 plots
    qreal PlotsHeight = ((GRAPH_ZONE_HEIGHT - 60) / (ZT1_DISCREET_PLOTTABLE_NB_PARAM + ZT1_ANALOG_PLOTTABLE_NB_PARAM + 1));//SDF analog plot is 3 units high, so add 2 units for this plot (hence the +2)
    PlotsHeight -= (20 + (10/(ZT1_DISCREET_PLOTTABLE_NB_PARAM + ZT1_ANALOG_PLOTTABLE_NB_PARAM))) ;  //space between plots
    int CurPlot = 0;
    for(int param = 0; param < ZT1_DISCREET_PLOTTABLE_NB_PARAM; param++)
	{
        mZT1DiscreetPlots[param].mParamID = param;
        mZT1DiscreetPlots[param].mDataSet = new QList<CGraphDiscreteDataPair*>;

		CGraphItem * NewGraph = new CGraphItem(this);
        //NewGraph->setPos(GRAPH_ZONE_X_OFFSET,param * (40 + 20)+10);
        NewGraph->setPos(GRAPH_ZONE_X_OFFSET,CurPlot++ * (PlotsHeight + 20) + 10);
		NewGraph->resize(GRAPH_ZONE_WIDTH,PlotsHeight);

        mZT1DiscreetPlots[param].mPlotGaph = NewGraph;
        mZT1DiscreetPlots[param].mPlotGaph->SetData(mZT1DiscreetPlots[param].mDataSet);
	}
    mZT1DiscreetPlots[ZT1_DISCREET_PLOTTABLE_S1_PARAM].mPlotGaph->SetLabel("S1",GRAPH_ZONE_X_OFFSET);
    mZT1DiscreetPlots[ZT1_DISCREET_PLOTTABLE_S2_PARAM].mPlotGaph->SetLabel("S2",GRAPH_ZONE_X_OFFSET);
    mZT1DiscreetPlots[ZT1_DISCREET_PLOTTABLE_PPINT_PARAM].mPlotGaph->SetLabel("PP Int",GRAPH_ZONE_X_OFFSET);
    mZT1DiscreetPlots[ZT1_DISCREET_PLOTTABLE_PPEXT_PARAM].mPlotGaph->SetLabel("PP Ext",GRAPH_ZONE_X_OFFSET);
    //mZT1DiscreetPlots[ZT1_DISCREET_PLOTTABLE_PG_PARAM].mPlotGaph->SetLabel("PG",GRAPH_ZONE_X_OFFSET);
    mZT1DiscreetPlots[ZT1_DISCREET_PLOTTABLE_FN_PARAM].mPlotGaph->SetLabel("FN",GRAPH_ZONE_X_OFFSET);
    mZT1DiscreetPlots[ZT1_DISCREET_PLOTTABLE_CI_PARAM].mPlotGaph->SetLabel("CI",GRAPH_ZONE_X_OFFSET);
    mZT1DiscreetPlots[ZT1_DISCREET_PLOTTABLE_ZT1_CDV_PARAM].mPlotGaph->SetLabel("CDV",GRAPH_ZONE_X_OFFSET);

    for(int param = 0; param < ZT1_ANALOG_PLOTTABLE_NB_PARAM; param++)
    {
        mZT1AnalogPlots[param].mParamID = param;
        mZT1AnalogPlots[param].mDataSet = new QList<CGraphAnalogDataPair*>;

        CAnalogGraphItem *NewGraph = new CAnalogGraphItem(this);
       // NewGraph->setPos(GRAPH_ZONE_X_OFFSET,(param+DISCREET_PLOTTABLE_NB_PARAM)*(40+20)+10);
         NewGraph->setPos(GRAPH_ZONE_X_OFFSET,CurPlot++ * (PlotsHeight + 20) + 10);
		NewGraph->resize(GRAPH_ZONE_WIDTH,PlotsHeight);

        mZT1AnalogPlots[param].mPlotGaph = NewGraph;
        mZT1AnalogPlots[param].mPlotGaph->SetData(mZT1AnalogPlots[param].mDataSet);
    }
    mZT1AnalogPlots[ZT1_ANALOG_PLOTTABLE_PGINT_PARAM].mPlotGaph->SetLabel("PG Int",GRAPH_ZONE_X_OFFSET);
    mZT1AnalogPlots[ZT1_ANALOG_PLOTTABLE_PGEXT_PARAM].mPlotGaph->SetLabel("PG Ext",GRAPH_ZONE_X_OFFSET);
    mZT1AnalogPlots[ZT1_ANALOG_PLOTTABLE_TRAIN_SPEED_PARAM].mPlotGaph->SetLabel("Vitesse",GRAPH_ZONE_X_OFFSET);
	mZT1AnalogPlots[ZT1_ANALOG_PLOTTABLE_PGCOMBINED_PARAM].mPlotGaph->SetLabel("Détection",GRAPH_ZONE_X_OFFSET);
	mZT1AnalogPlots[ZT1_ANALOG_PLOTTABLE_SDF_DATA_PARAM].mPlotGaph->SetLabel("SDF",GRAPH_ZONE_X_OFFSET);
    mZT1AnalogPlots[ZT1_ANALOG_PLOTTABLE_SDF_DATA_PARAM].mPlotGaph->resize(GRAPH_ZONE_WIDTH,PlotsHeight*3);  //JFM: make SDF plot 3 times higher to help visualization.

    //Setup ZT2 Plots
    PlotsHeight = ((GRAPH_ZONE_HEIGHT - 60) / (ZT2_DISCREET_PLOTTABLE_NB_PARAM + ZT2_ANALOG_PLOTTABLE_NB_PARAM));
    PlotsHeight -= (20 + (10/(ZT2_DISCREET_PLOTTABLE_NB_PARAM + ZT2_ANALOG_PLOTTABLE_NB_PARAM))) ;  //space between plots
    CurPlot = 0;
    for(int param = 0; param < ZT2_DISCREET_PLOTTABLE_NB_PARAM; param++)
    {
        mZT2DiscreetPlots[param].mParamID = param;
        mZT2DiscreetPlots[param].mDataSet = new QList<CGraphDiscreteDataPair*>;

        CGraphItem * NewGraph = new CGraphItem(this);
        //NewGraph->setPos(GRAPH_ZONE_X_OFFSET,param * (40 + 20)+10);
        NewGraph->setPos(GRAPH_ZONE_X_OFFSET,CurPlot++ * (PlotsHeight + 20) + 10);
        NewGraph->resize(900,PlotsHeight);

        mZT2DiscreetPlots[param].mPlotGaph = NewGraph;
        mZT2DiscreetPlots[param].mPlotGaph->SetData(mZT2DiscreetPlots[param].mDataSet);
    }
    mZT2DiscreetPlots[ZT2_DISCREET_PLOTTABLE_S1_PARAM].mPlotGaph->SetLabel("S1",GRAPH_ZONE_X_OFFSET);
    mZT2DiscreetPlots[ZT2_DISCREET_PLOTTABLE_PPEXT_PARAM].mPlotGaph->SetLabel("PP Ext",GRAPH_ZONE_X_OFFSET);
    mZT2DiscreetPlots[ZT2_DISCREET_PLOTTABLE_PPINT_PARAM].mPlotGaph->SetLabel("PP Int",GRAPH_ZONE_X_OFFSET);
    mZT2DiscreetPlots[ZT2_DISCREET_PLOTTABLE_CI_PARAM].mPlotGaph->SetLabel("CI",GRAPH_ZONE_X_OFFSET);
	mZT2DiscreetPlots[ZT2_DISCREET_PLOTTABLE_APPROACH_CDV_PARAM].mPlotGaph->SetLabel("CDV App.",GRAPH_ZONE_X_OFFSET);
    mZT2DiscreetPlots[ZT2_DISCREET_PLOTTABLE_CDV_PARAM].mPlotGaph->SetLabel("CDV",GRAPH_ZONE_X_OFFSET);

    mVCursor = new CVerticalGraphCursorWidget(GRAPH_ZONE_HEIGHT,this);
    mVCursor->setPos(0,0);
    mVCursor->resize(3,GRAPH_ZONE_HEIGHT);
    mVCursor->setZValue(2);

    mHCursor = new CHorizontalGraphCursorWidget(GRAPH_ZONE_WIDTH,this);
    mHCursor->setPos(0,0);
    mHCursor->resize(GRAPH_ZONE_WIDTH,3);
    mHCursor->setZValue(2);

//	mCursorPosTxt = new QGraphicsTextItem(this);
//    mCursorPosTxt->setPos(650,690);


	mCursorsZoomButton = new CTextButtonWidget("Zoom curseurs");
	mCursorsZoomButton->setParentItem(this);
	mCursorsZoomButton->setPos(10,700);
	connect(mCursorsZoomButton,SIGNAL(TxtButtonClicked(CTextButtonWidget*)),this,SLOT(ButtonClicked(CTextButtonWidget*)));

	mZoomInButton = new CTextButtonWidget(" +",0,25,25);
	mZoomInButton->setParentItem(this);
	mZoomInButton->setPos(95,730);
	connect(mZoomInButton,SIGNAL(TxtButtonClicked(CTextButtonWidget*)),this,SLOT(ButtonClicked(CTextButtonWidget*)));

	mZoomOutButton = new CTextButtonWidget(" -",0,25,25);
	mZoomOutButton->setParentItem(this);
	mZoomOutButton->setPos(10,730);
	connect(mZoomOutButton,SIGNAL(TxtButtonClicked(CTextButtonWidget*)),this,SLOT(ButtonClicked(CTextButtonWidget*)));

	mZoomResetButton = new CTextButtonWidget(" R",0,25,25);
	mZoomResetButton->setParentItem(this);
	mZoomResetButton->setPos(50,730);
	connect(mZoomResetButton,SIGNAL(TxtButtonClicked(CTextButtonWidget*)),this,SLOT(ButtonClicked(CTextButtonWidget*)));

    mStaticCursor1 = new CVerticalGraphCursorWidget(GRAPH_ZONE_HEIGHT,this);
    mStaticCursor1->setPos(0,0);
    mStaticCursor1->setZValue(1);
    mStaticCursor1->SetColor(QColor(Qt::red));
    mStaticCursor1->hide();

    mStaticCursor2 = new CVerticalGraphCursorWidget(GRAPH_ZONE_HEIGHT,this);
    mStaticCursor2->setPos(0,0);
    mStaticCursor2->setZValue(1);
    mStaticCursor2->SetColor(QColor(Qt::green));
    mStaticCursor2->hide();

    mStaticCursorDeltaTimeTxt = new QGraphicsTextItem(this);
	mStaticCursorDeltaTimeTxt->setPos(130,700);
	mStaticCursorDeltaTimeTxt->setPlainText("Delta curseurs: ?");

	mCursor1TimeTxt = new QGraphicsTextItem(this);
	mCursor1TimeTxt->setPlainText("Position curseur 1 : ?");
	mCursor1TimeTxt->setPos(130,720);
	mCursor2TimeTxt = new QGraphicsTextItem(this);
	mCursor2TimeTxt->setPlainText("Position curseur 2 : ?");
	mCursor2TimeTxt->setPos(130,740);
	mPassageStats1Txt = new QGraphicsTextItem(this);
	mPassageStats1Txt->setPos(350,700);
	mPassageStats1Txt->setPlainText("Date & heure: \nStation : \nPosition : ");
	mPassageStats2Txt = new QGraphicsTextItem(this);
	mPassageStats2Txt->setPos(600,700);
	mPassageStats2Txt->setPlainText("Vitesse Max :  Mph\nVitesse Min: Mph\nSeuil PG :  ");

    mRuler = new CGraphRulerWidget(GRAPH_ZONE_WIDTH,this);
    mRuler->setZValue(1);
    mRuler->setPos(GRAPH_ZONE_X_OFFSET,670);
	mRuler->resize(GRAPH_ZONE_WIDTH,20);

    mRankRuler = new CRankRulerWidget(GRAPH_ZONE_WIDTH,this);
    mRankRuler->setZValue(1);
    mRankRuler->resize(GRAPH_ZONE_WIDTH,10);
    mRankRuler->setPos(GRAPH_ZONE_X_OFFSET,655);
    mRankRuler->SetLabel("Rang:",GRAPH_ZONE_X_OFFSET);

    mEventRuler = new CEventRulerWidget(GRAPH_ZONE_WIDTH,this);
    mEventRuler->setZValue(1);
    mEventRuler->resize(GRAPH_ZONE_WIDTH,10);
    mEventRuler->setPos(GRAPH_ZONE_X_OFFSET,640);
    mEventRuler->SetLabel("Décl:",GRAPH_ZONE_X_OFFSET);

	DestroyData();

    mScrollRefreshTimer.start();
}

CLogViewPage::~CLogViewPage()
{
	DestroyData();
}

void CLogViewPage::resizeEvent(QGraphicsSceneResizeEvent *event)
{
	Q_UNUSED(event)
	mBackgroundRect->setRect(boundingRect());
}

void CLogViewPage::ButtonClicked(CTextButtonWidget *BtnPtr)
{
	if(BtnPtr == mCancelButton)
	{
        DestroyData();
        mProgramHandle->LogViewCloseRequest();
	}
    else if(BtnPtr == mCursorsZoomButton)
    {
        if(mStaticCursor1->IsCursorSet() && mStaticCursor2->IsCursorSet())
            ShowSpan(mStaticCursor1->GetPixelPos(),mStaticCursor2->GetPixelPos());
    }
	else if(BtnPtr == mZoomInButton)
	{
		ZoomIn(false);
	}
	else if(BtnPtr == mZoomOutButton)
	{
		ZoomOut(false);
	}
	else if(BtnPtr == mZoomResetButton)
	{
		ShowSpan(mMinTime,mMaxTime);
	}
}


void CLogViewPage::SetLogData(CLogElement *element)
{

    DestroyData();
    mLogElement = element;
    mViewType = mLogElement->mZTLogType;
	mStaticCursor1->ClearCursor();
	mStaticCursor2->ClearCursor();
	mStaticCursorDeltaTimeTxt->setPlainText("Delta : ?");


    if(mViewType == ZT1_LOG_TYPE)
    {
        CZT1LogElement *ZT1LogElement = (CZT1LogElement*)element;
        int CurRank = 0;
		quint64 mRankStartTime = 0;
        bool Done;
		mPassageStation = ZT1LogElement->mStationName;
		mPassageDateTime = ZT1LogElement->mPassageDateTime.toString("yyyy/MM/dd hh:mm:ss");
		qreal MaxTrainSpeed = 0, MinTrainSpeed = 10000;

        //Build all the datasets from the raw data.

        //JFM 2016-05-31
        //Check for invalid data in the last slot...
        if(ZT1LogElement->mZTLogData.at(ZT1LogElement->mZTLogData.size()-1)->mTimestamp < ZT1LogElement->mZTLogData.at(ZT1LogElement->mZTLogData.size()-2)->mTimestamp)
        {
            delete ZT1LogElement->mZTLogData.at(ZT1LogElement->mZTLogData.size()-1);
            ZT1LogElement->mZTLogData.remove(ZT1LogElement->mZTLogData.size()-1);
        }

        //Discreet signals
        for(int i = 0; i < ZT1LogElement->mZTLogData.size(); i++)
        {
            for(int param = 0; param < ZT1_DISCREET_PLOTTABLE_NB_PARAM; param++)
            {
                CGraphDiscreteDataPair *DataSet = new CGraphDiscreteDataPair(0,ZT1LogElement->mZTLogData.at(i)->mTimestamp);

                if(ZT1LogElement->mZTLogData.at(i)->mZT1ThreadData != 0)
                {
					if(ZT1LogElement->mZTLogData.at(i)->mZT1ThreadData->mRank > (unsigned int)CurRank)
                    {
                        if(CurRank == 0)
                        {
                            mRankStartTime = ZT1LogElement->mZTLogData.at(i)->mTimestamp;
                            CurRank = ZT1LogElement->mZTLogData.at(i)->mZT1ThreadData->mRank;
                        }
                        else
                        {
                            mRankRuler->AddRankItem(QString().sprintf("%d",CurRank),mRankStartTime,ZT1LogElement->mZTLogData.at(i)->mTimestamp);
                            mRankStartTime = ZT1LogElement->mZTLogData.at(i)->mTimestamp;
                            CurRank = ZT1LogElement->mZTLogData.at(i)->mZT1ThreadData->mRank;
                            mRankStartTime = ZT1LogElement->mZTLogData.at(i)->mTimestamp;

                        }
                    }


                    switch(param)
                    {
                        case ZT1_DISCREET_PLOTTABLE_S1_PARAM:
                        {
                            DataSet->mValue = ZT1LogElement->mZTLogData.at(i)->mZT1ThreadData->mS1;
                            break;
                        }
                        case ZT1_DISCREET_PLOTTABLE_S2_PARAM:
                        {
                            DataSet->mValue = ZT1LogElement->mZTLogData.at(i)->mZT1ThreadData->mS2;
                            break;
                        }
                        case ZT1_DISCREET_PLOTTABLE_PPINT_PARAM:
                        {
                            DataSet->mValue = ZT1LogElement->mZTLogData.at(i)->mZT1ThreadData->mPInt;
                            break;
                        }
                        case ZT1_DISCREET_PLOTTABLE_PPEXT_PARAM:
                        {
                            DataSet->mValue = ZT1LogElement->mZTLogData.at(i)->mZT1ThreadData->mPExt;
                            break;
                        }
//						case ZT1_DISCREET_PLOTTABLE_PG_PARAM:
//                        {
//							DataSet->mValue = ZT1LogElement->mZTLogData.at(i)->mZT1ThreadData->mPG;
//                            break;
//                        }
                        case ZT1_DISCREET_PLOTTABLE_FN_PARAM:
                        {
                            DataSet->mValue = ZT1LogElement->mZTLogData.at(i)->mZT1ThreadData->mFN;
                            break;
                        }
                        case ZT1_DISCREET_PLOTTABLE_CI_PARAM:
                        {
                            DataSet->mValue = ZT1LogElement->mZTLogData.at(i)->mZT1ThreadData->mFN;
                            break;
                        }
                        case ZT1_DISCREET_PLOTTABLE_ZT1_CDV_PARAM:
                        {
                            break;
                        }
                    }
                }
                else if(i > 0)	//if there is no data available, use the previous value...
                {
                    DataSet->mValue = mZT1DiscreetPlots[param].mDataSet->at(i-1)->mValue;

                    if(CurRank > 0 && Done == false)
                    {
                        Done = true;
                        mRankRuler->AddRankItem(QString().sprintf("%d",CurRank),mRankStartTime,ZT1LogElement->mZTLogData.at(i-1)->mTimestamp);
                    }
                }
                switch(param)
                {
                    case ZT1_DISCREET_PLOTTABLE_CI_PARAM:
                    {
                        DataSet->mValue = ZT1LogElement->mZTLogData.at(i)->mCIZT1;
                        break;
                    }
                    case ZT1_DISCREET_PLOTTABLE_ZT1_CDV_PARAM:
                    {
                        DataSet->mValue = ZT1LogElement->mZTLogData.at(i)->mCDVARM_ZT1;
                        break;
                    }
                }

                mZT1DiscreetPlots[param].mDataSet->append(DataSet);
            }

            for(int param = 0; param < ZT1_ANALOG_PLOTTABLE_NB_PARAM; param++)
            {
                CGraphAnalogDataPair *DataSet = new CGraphAnalogDataPair(0,ZT1LogElement->mZTLogData.at(i)->mTimestamp);

                if(ZT1LogElement->mZTLogData.at(i)->mZT1ThreadData != 0)
                {
                    switch(param)
                    {
                        case ZT1_ANALOG_PLOTTABLE_PGEXT_PARAM:
                        {
                            DataSet->mValue = (qreal)ZT1LogElement->mZTLogData.at(i)->mZT1ThreadData->mPGExtValue;
                            break;
                        }
                        case ZT1_ANALOG_PLOTTABLE_PGINT_PARAM:
                        {
                            DataSet->mValue = (qreal)ZT1LogElement->mZTLogData.at(i)->mZT1ThreadData->mPGIntValue;
                            break;
                        }
                        case ZT1_ANALOG_PLOTTABLE_TRAIN_SPEED_PARAM:
                        {

                            DataSet->mValue = ZT1LogElement->mZTLogData.at(i)->mZT1ThreadData->mTrainSpeed;
							if(DataSet->mValue > MaxTrainSpeed)
								MaxTrainSpeed = DataSet->mValue;

							if(DataSet->mValue != 0 && DataSet->mValue < MinTrainSpeed)
								MinTrainSpeed = DataSet->mValue;

                            break;
                        }
						case ZT1_ANALOG_PLOTTABLE_PGCOMBINED_PARAM:
						{
							qint32 PI = ZT1LogElement->mZTLogData.at(i)->mZT1ThreadData->mPGIntValue,PE = ZT1LogElement->mZTLogData.at(i)->mZT1ThreadData->mPGExtValue;

							qint32 offsetint = ZT1LogElement->mFlags.mIntPGOffset;
							qint32 offsetext = ZT1LogElement->mFlags.mExtPGOffset;
							qint32 tempint = (PI - offsetint);
							qint32 tempext = (PE - offsetext);
							qint32 Quadra = tempint*tempext;
							DataSet->mValue = (qreal)Quadra;
							//qDebug("%f",DataSet->mValue);

							break;
						}
						case ZT1_ANALOG_PLOTTABLE_SDF_DATA_PARAM:
						{
							if(ZT1LogElement->mFlags.mAnalogTracePresent == true)
							{
                                DataSet->mValue = (qreal)ZT1LogElement->mZTLogData.at(i)->mAnalogData/* * 10 / 4096*/; //JFM 20140821
							}
							break;
						}
                    }
                }
                else    //No analog data... set to 0
                {
                    DataSet->mValue = 0;
                }
                mZT1AnalogPlots[param].mDataSet->append(DataSet);
            }
        }

        for(int param = 0; param < ZT1_ANALOG_PLOTTABLE_NB_PARAM; param++)
        {
            mZT1AnalogPlots[param].mPlotGaph->SetAbsoluteLimits(ZT1LogElement->mThreadDataStartTime,ZT1LogElement->mThreadDataEndTime);
        }

		mZT1AnalogPlots[ZT1_ANALOG_PLOTTABLE_PGCOMBINED_PARAM].mPlotGaph->AddHorizontalLine(ZT1LogElement->mFlags.mPGTresholdValue);
		mPGTreshold = ZT1LogElement->mFlags.mPGTresholdValue;

 //       mRankRuler->AddRankItem(QString().sprintf("%d",CurRank),mRankStartTime,ZT1LogElement->mZTLogData.last()->mTimestamp);

        mMinTime = mStartTime = mZT1DiscreetPlots[0].mDataSet->first()->mTime;
        mMaxTime = mZT1DiscreetPlots[0].mDataSet->last()->mTime;

		if(ZT1LogElement->mZTDetections.size() == 0)
		{
			mEventRuler->ClearRuler();
		}
		else
		{
			for(int event = 0; event < ZT1LogElement->mZTDetections.size(); event++)
			{
				mEventRuler->AddEventItem(CZTData::GetShortErrorString(ZT1LogElement->mZTDetections.at(event)->mDetectionID),ZT1LogElement->mZTDetections.at(event)->mTimeStamp);
			}
		}

		mPassageStats2Txt->setPlainText(QString().sprintf("Vitesse Max : %.3f Mph\nVitesse Min: %.3f Mph\nSeuil PG : %d",MaxTrainSpeed,MinTrainSpeed,mPGTreshold));

    }
    else if(mViewType == ZT2_LOG_TYPE)
    {
        int CurRank = 0;
		quint64 mRankStartTime = 0;


        CZT2LogElement *ZT2LogElement = (CZT2LogElement*)element;
		mPassageDateTime = ZT2LogElement->mPassageDateTime.toString("yyyy/MM/dd hh:mm:ss");;
		mPassageStation = ZT2LogElement->mStationName;
		mPassageStats2Txt->setPlainText("Vitesse Max : N/A\nVitesse Min: N/A\nSeuil PG : N/A");

        for(int i = 0; i < ZT2LogElement->mZTLogData.size(); i++)
        {
            for(int param = 0; param < ZT2_DISCREET_PLOTTABLE_NB_PARAM; param++)
            {
                CGraphDiscreteDataPair *DataSet = new CGraphDiscreteDataPair(0,ZT2LogElement->mZTLogData.at(i)->mTimestamp);
                if(ZT2LogElement->mZTLogData.at(i)->mZT2ThreadData != 0)
                {                    
					if(ZT2LogElement->mZTLogData.at(i)->mZT2ThreadData->mRank > (unsigned int)CurRank)
                    {
                        if(CurRank == 0)
                        {
                            mRankStartTime = ZT2LogElement->mZTLogData.at(i)->mTimestamp;
                            CurRank = ZT2LogElement->mZTLogData.at(i)->mZT2ThreadData->mRank;
                        }
                        else
                        {
                            mRankRuler->AddRankItem(QString().sprintf("%d",CurRank),mRankStartTime,ZT2LogElement->mZTLogData.at(i)->mTimestamp);
                            mRankStartTime = ZT2LogElement->mZTLogData.at(i)->mTimestamp;
                            CurRank = ZT2LogElement->mZTLogData.at(i)->mZT2ThreadData->mRank;
                            mRankStartTime = ZT2LogElement->mZTLogData.at(i)->mTimestamp;

                        }
                    }


                    switch(param)
                    {
                        case ZT2_DISCREET_PLOTTABLE_S1_PARAM:
                        {
                            DataSet->mValue = ZT2LogElement->mZTLogData.at(i)->mZT2ThreadData->mS1;
                            break;
                        }
                        case ZT2_DISCREET_PLOTTABLE_PPEXT_PARAM:
                        {
                            DataSet->mValue = ZT2LogElement->mZTLogData.at(i)->mZT2ThreadData->mPPExt;
                            break;
                        }
                        case ZT2_DISCREET_PLOTTABLE_PPINT_PARAM:
                        {
                            DataSet->mValue = ZT2LogElement->mZTLogData.at(i)->mZT2ThreadData->mPPInt;
                            break;
                        }

                    }
                }
                else if(i > 0)	//if there is no data available, use the previous value...
                {
                    DataSet->mValue = mZT2DiscreetPlots[param].mDataSet->at(i-1)->mValue;
                }
                switch(param)
                {
                    case ZT2_DISCREET_PLOTTABLE_CI_PARAM:
                    {
                        DataSet->mValue = ZT2LogElement->mZTLogData.at(i)->mCIZT2;
                        break;
                    }
                    case ZT2_DISCREET_PLOTTABLE_CDV_PARAM:
                    {
                        DataSet->mValue = ZT2LogElement->mZTLogData.at(i)->mCDVARM_ZT2;
                        break;
                    }
					case ZT2_DISCREET_PLOTTABLE_APPROACH_CDV_PARAM:
					{
						DataSet->mValue = ZT2LogElement->mZTLogData.at(i)->mCDVApproach_ZT2;
					}
                }

                mZT2DiscreetPlots[param].mDataSet->append(DataSet);
            }

//            for(int param = 0; param < ZT1_ANALOG_PLOTTABLE_NB_PARAM; param++)
//            {
//                CGraphAnalogDataPair *DataSet = new CGraphAnalogDataPair(0,ZT1LogElement->mZTLogData.at(i)->mTimestamp);
//                if(ZT1LogElement->mZTLogData.at(i)->mZT1ThreadData != 0)
//                {
//                    switch(param)
//                    {
//                        case ZT1_ANALOG_PLOTTABLE_PGEXT_PARAM:
//                        {
//                            DataSet->mValue = (qreal)ZT1LogElement->mZTLogData.at(i)->mZT1ThreadData->mPGExtValue;
//                            break;
//                        }
//                        case ZT1_ANALOG_PLOTTABLE_PGINT_PARAM:
//                        {
//                            DataSet->mValue = (qreal)ZT1LogElement->mZTLogData.at(i)->mZT1ThreadData->mPGIntValue;
//                            break;
//                        }
//                        case ZT1_ANALOG_PLOTTABLE_TRAIN_SPEED_PARAM:
//                        {

//                            DataSet->mValue = ZT1LogElement->mZTLogData.at(i)->mZT1ThreadData->mTrainSpeed;
//                            //                        if(DataSet->mValue == 0)
//                            //                            DataSet->mValue = -1;
//                            break;
//                        }
//                    }
//                }
//                else    //No analog data... set to 0
//                {
//                    DataSet->mValue = 0;
//                }
//                mZT1AnalogPlots[param].mDataSet->append(DataSet);
//            }
        }

        mRankRuler->AddRankItem(QString().sprintf("%d",CurRank),mRankStartTime,ZT2LogElement->mZTLogData.last()->mTimestamp);

        mMinTime = mStartTime = mZT2DiscreetPlots[0].mDataSet->first()->mTime;
        mMaxTime = mZT2DiscreetPlots[0].mDataSet->last()->mTime;

		if(ZT2LogElement->mZTDetections.size() == 0)
		{
			mEventRuler->ClearRuler();
		}
		else
		{
			for(int event = 0; event < ZT2LogElement->mZTDetections.size(); event++)
			{
				mEventRuler->AddEventItem(CZTData::GetShortErrorString(ZT2LogElement->mZTDetections.at(event)->mDetectionID),ZT2LogElement->mZTDetections.at(event)->mTimeStamp);
			}
		}

    }
    else
    {
        return;
    }

	mStopTime = mMaxTime;
	mTotalTimeSpan = mMaxTime - mMinTime;
	mCurTimeSpan = mStopTime - mStartTime;

	mCurPixelTickValue = (qreal)GRAPH_ZONE_WIDTH/(qreal)mCurTimeSpan;	//pixels per microsecs
	mCursorPos = mStartTime;

	mPassageStats1Txt->setPlainText(QString().sprintf("Date & heure: %s\nStation : %s\nPosition : %s",mPassageDateTime.toUtf8().data(),mPassageStation.toUtf8().data()," "));

    ShowSpan(mStartTime,mStopTime);

    ShowPlots(mViewType);

//	for(int param = 0; param < DISCREET_PLOTTABLE_NB_PARAM; param++)
//	{
//		mZT1DiscreetPlots[param].mPlotGaph->DisplayData(mStartTime,mStopTime);
//	}
}

void CLogViewPage::ShowPlots(unsigned int ViewType)
{
    if(ViewType == ZT1_LOG_TYPE)
    {
        for(int param = 0; param < ZT1_DISCREET_PLOTTABLE_NB_PARAM; param++)
        {
            mZT1DiscreetPlots[param].mPlotGaph->show();
        }
        for(int param = 0; param < ZT1_ANALOG_PLOTTABLE_NB_PARAM; param++)
        {
            mZT1AnalogPlots[param].mPlotGaph->show();
        }
        for(int param = 0; param < ZT2_DISCREET_PLOTTABLE_NB_PARAM; param++)
        {
            mZT2DiscreetPlots[param].mPlotGaph->hide();
        }
        for(int param = 0; param < ZT2_ANALOG_PLOTTABLE_NB_PARAM; param++)
        {
           // mZT1AnalogPlots[param].mPlotGaph->show();
        }
    }
    else if(ViewType == ZT2_LOG_TYPE)
    {
        for(int param = 0; param < ZT1_DISCREET_PLOTTABLE_NB_PARAM; param++)
        {
            mZT1DiscreetPlots[param].mPlotGaph->hide();
        }
        for(int param = 0; param < ZT1_ANALOG_PLOTTABLE_NB_PARAM; param++)
        {
            mZT1AnalogPlots[param].mPlotGaph->hide();
        }
        for(int param = 0; param < ZT2_DISCREET_PLOTTABLE_NB_PARAM; param++)
        {
            mZT2DiscreetPlots[param].mPlotGaph->show();
        }
        for(int param = 0; param < ZT2_ANALOG_PLOTTABLE_NB_PARAM; param++)
        {
           // mZT1AnalogPlots[param].mPlotGaph->show();
        }
    }
}

void CLogViewPage::DestroyData()
{
    for(int item = 0; item < ZT1_DISCREET_PLOTTABLE_NB_PARAM; item++)
	{
        for(int i = 0; i < mZT1DiscreetPlots[item].mDataSet->size(); i++)
		{
            delete mZT1DiscreetPlots[item].mDataSet->at(i);
		}
        mZT1DiscreetPlots[item].mDataSet->clear();
	}

    for(int item = 0; item < ZT1_ANALOG_PLOTTABLE_NB_PARAM; item++)
    {
        for(int i = 0; i < mZT1AnalogPlots[item].mDataSet->size(); i++)
        {
            delete mZT1AnalogPlots[item].mDataSet->at(i);
        }
         mZT1AnalogPlots[item].mDataSet->clear();
    }

    for(int item = 0; item < ZT2_DISCREET_PLOTTABLE_NB_PARAM; item++)
    {
        for(int i = 0; i < mZT2DiscreetPlots[item].mDataSet->size(); i++)
        {
            delete mZT2DiscreetPlots[item].mDataSet->at(i);
        }
        mZT2DiscreetPlots[item].mDataSet->clear();
    }

    for(int item = 0; item < ZT2_ANALOG_PLOTTABLE_NB_PARAM; item++)
    {
//        for(int i = 0; i < mZT2AnalogPlots[item].mDataSet->size(); i++)
//        {
//            delete mZT1AnalogPlots[item].mDataSet->at(i);
//        }
//         mZT1AnalogPlots[item].mDataSet->clear();
    }

	mRankRuler->ClearRuler();
    mEventRuler->ClearRuler();
}

void CLogViewPage::ZoomIn(bool CenterOnCursor)
{

	//First, compute a zoom centered on the center of the area
	qint64 NewSpan = mCurTimeSpan - (mCurTimeSpan/5);
	if(NewSpan < 1000000)
	{
		NewSpan = mCurTimeSpan; //stop zooming
	}
	qint64 delta = mCurTimeSpan - NewSpan;
	quint64 StartTime = mStartTime + delta/2;
	quint64 StopTime = StartTime + NewSpan;
	if(StopTime > mMaxTime)
	{
		StopTime = mMaxTime;
		StartTime = StopTime - NewSpan;
	}

	if(CenterOnCursor)
	{
#ifdef ZOOM_CENTERED_ON_CURSOR

		//Now let's find how many pixels have moved from the cursor
		//by finding the position of the cursor time in the new timespan
		quint64 CursorTime = GetTimeForPixel(mCursorPos);

		//Convert time to pixels (in the new timespan)
		quint64 AbsoluteTime = CursorTime - StartTime;
		qreal PixelsPernSecs = (qreal)GRAPH_ZONE_WIDTH/(NewSpan);
		qreal Pixel = AbsoluteTime * PixelsPernSecs;

		Pixel +=  GRAPH_ZONE_X_OFFSET;

		//Find from how much pixels we have moved
		qreal DeltaX = Pixel - mCursorPos;

		//convert this to an amount of time
		qint64 DeltaTime = ((qint64)DeltaX * NewSpan)/GRAPH_ZONE_WIDTH;

		//Shift the timespan to center the zoom on the cursor.
		StartTime += DeltaTime;
		if(StartTime < mMinTime)
		{
			StartTime = mMinTime;
		}
		StopTime = StartTime + NewSpan;
		if(StopTime > mMaxTime)
		{
			StopTime = mMaxTime;
			StartTime = StopTime - NewSpan;
		}

#endif
	}

	ShowSpan(StartTime,StopTime);
}

void CLogViewPage::ZoomOut(bool CenterOnCursor)
{
	qint64 NewSpan = mCurTimeSpan + (mCurTimeSpan/5);
	if(NewSpan > (qint64)(mMaxTime - mMinTime))
	{
		ShowSpan(mMinTime,mMaxTime);
	}
	else
	{

		qint64 delta = NewSpan - mCurTimeSpan;

		qint64 StartTime = mStartTime - delta/2;

		if(StartTime < (qint64)mMinTime/* || StartTime < 0*/)
		{
			StartTime = mMinTime;
		}
		quint64 StopTime = StartTime + NewSpan;
		if(StopTime > mMaxTime)
		{
			StopTime = mMaxTime;
			StartTime = StopTime - NewSpan;
		}

		if(CenterOnCursor == true)
		{
#ifdef ZOOM_CENTERED_ON_CURSOR
			quint64 CursorTime = GetTimeForPixel(mCursorPos);

			//Convert time to pixels (in the new timespan)
			quint64 AbsoluteTime = CursorTime - StartTime;
			qreal PixelsPernSecs = (qreal)GRAPH_ZONE_WIDTH/(NewSpan);
			qreal Pixel = AbsoluteTime * PixelsPernSecs;

			Pixel +=  GRAPH_ZONE_X_OFFSET;

			//Find from how much pixels we have moved
			qreal DeltaX = Pixel - mCursorPos;

			//convert this to an amount of time
			qint64 DeltaTime = ((qint64)DeltaX * NewSpan)/GRAPH_ZONE_WIDTH;

			//Shift the timespan to center the zoom on the cursor.
			StartTime += DeltaTime;
			if(StartTime < (qint64)mMinTime/* || StartTime < 0*/)
			{
				StartTime = mMinTime;
			}
			StopTime = StartTime + NewSpan;
			if(StopTime > mMaxTime)
			{
				StopTime = mMaxTime;
				StartTime = StopTime - NewSpan;
			}
#endif
		}

		ShowSpan(StartTime,StopTime);
	}
}

void CLogViewPage::SetZoom(int ZoomValue)
{
	Q_UNUSED(ZoomValue)
}

//Grab the mouse if the user clicks outside buttons
void CLogViewPage::mousePressEvent(QGraphicsSceneMouseEvent *event)
{

    if(event->button() == Qt::LeftButton)
	{
		mMouseDragging = true;
        mMouseMoved = false;
	}
	event->accept();
}
void CLogViewPage::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{

	if(event->button() == Qt::LeftButton)
	{
		mMouseDragging = false;

        if(mMouseMoved == false)
        {
            mStaticCursor1->setPos(event->pos().x(),0);
            mStaticCursor1->SetTime(GetTimeForPixel(event->pos().x()));
            mStaticCursor1->SetCursor();
            mStaticCursor1->show();
            UpdateStaticCursorsDeltaTime();
			mCursor1TimeTxt->setPlainText(QString().sprintf("Position curseur 1 : %d ms",(int)(mStaticCursor1->GetTime()/1000000)));
        }
	}
    if(event->button() == Qt::RightButton)
    {
        mStaticCursor2->setPos(event->pos().x(),0);
        mStaticCursor2->SetTime(GetTimeForPixel(event->pos().x()));
        mStaticCursor2->SetCursor();
		mStaticCursor2->show();
		mCursor2TimeTxt->setPlainText(QString().sprintf("Position curseur 2 : %d ms",(int)(mStaticCursor2->GetTime()/1000000)));
        UpdateStaticCursorsDeltaTime();
    }

	event->accept();
}
void CLogViewPage::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    if(mMouseDragging)
	{

        DragPlots(event->lastPos().x() - event->pos().x());

//        mMouseMoved = true;
//		qreal Drag = event->lastPos().x() - event->pos().x();
//		//qreal Drag = 50;
//		if(Drag != 0)
//		{
//			qreal TickValue = (qreal)GRAPH_ZONE_WIDTH/(qreal)mCurTimeSpan;
//			qreal temp = TickValue/Drag;
//			//quint64 usecsDrag = 1/(mCurPixelTickValue/Drag);
//			qint64 usecsDrag = 1/temp;
//			ScrollGraphs(usecsDrag);
//		}
	}

    AdjustMouseCursorPos(event->pos().x(),event->pos().y());
	event->accept();

}

void CLogViewPage::DragPlots(qreal DragValue)
{
    mMouseMoved = true;
    qreal Drag = DragValue;
    //qreal Drag = 50;
    if(Drag != 0)
    {
        qreal TickValue = (qreal)GRAPH_ZONE_WIDTH/(qreal)mCurTimeSpan;
        qreal temp = TickValue/Drag;
        //quint64 usecsDrag = 1/(mCurPixelTickValue/Drag);
        qint64 usecsDrag = 1/temp;
        ScrollGraphs(usecsDrag);
    }
}


bool CLogViewPage::eventFilter(QObject *obj, QEvent *event)
{
	if(isVisible()) //Check if event is coming from us
	{
		if(event->type() == QEvent::KeyPress)
		{
			QKeyEvent *KeyEvent = static_cast<QKeyEvent*>(event);

			if(KeyEvent->key() == Qt::Key_Left)
			{
                AdjustMouseCursorPos(mVCursor->GetPixelPos() - 1,mHCursor->GetPixelPos());
				return true;	//keep the keystroke
			}
			if(KeyEvent->key() == Qt::Key_Right)
			{
                AdjustMouseCursorPos(mVCursor->GetPixelPos() + 1,mHCursor->GetPixelPos());
				return true;	//keep the keystroke
			}
            if(KeyEvent->key() == Qt::Key_Control)
            {
                mCtrlKeyDown = true;
                return true;
            }
            if(KeyEvent->key() == Qt::Key_Shift)
            {
                mShiftKeyDown = true;
                return true;
            }
		}
        else if(event->type() == QEvent::KeyRelease)
        {
            QKeyEvent *KeyEvent = static_cast<QKeyEvent*>(event);
            if(KeyEvent->key() == Qt::Key_Control)
            {
                mCtrlKeyDown = false;
                return true;
            }
            if(KeyEvent->key() == Qt::Key_Shift)
            {
                mShiftKeyDown = false;
                return true;
            }
        }
	}

	return QObject::eventFilter(obj,event);

}

void CLogViewPage::wheelEvent(QGraphicsSceneWheelEvent *event)
{

	//Zoom must be higher than 100 (100%)
	//That is full scale.
    //int Zoom;
	if(event-> delta() < 0)
	{
        ZoomOut();
//		Zoom = mZoomValue - ZOOM_TICK;
//		if(Zoom < 100)
//			Zoom = 100;
	}
	else
	{
        ZoomIn();
//		Zoom = mZoomValue + ZOOM_TICK;
	}

//	mZoomValue = Zoom;

//	SetZoom(Zoom);
    event->accept();
}

void CLogViewPage::ScrollGraphs(qint64 Delta)
{
	quint64 CurTimeSpan = mStopTime - mStartTime;


	if(Delta > 0)
	{


		if(mStopTime + Delta >= mMaxTime)
		{
			mStopTime = mMaxTime;
		}
		else
		{
			mStopTime += Delta;
		}

		mStartTime = mStopTime - CurTimeSpan;

	}
	else
	{
//		if(mStartTime == mMinTime)
//			return;

		//Delta is negative !!
		qint64 start = mStartTime + Delta;
		if(start <= (qint64)mMinTime)
		{
			mStartTime = mMinTime;
		}
		else
		{
			mStartTime += Delta;
		}
		mStopTime = mStartTime + CurTimeSpan;
	}

//	qDebug() << "StartTime = " << mStartTime << "StopTime = " << mStopTime << "delta= " << Delta;

    if(mScrollRefreshTimer.elapsed() > 33) //limit the scroll redraw to 30FPS
    {
        ShowSpan(mStartTime,mStopTime);
        mScrollRefreshTimer.start();
    }
//	for(int param = 0; param < DISCREET_PLOTTABLE_NB_PARAM; param++)
//	{
//		mZT1DiscreetPlots[param].mPlotGaph->DisplayData(mStartTime,mStopTime);
//	}
}


void CLogViewPage::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
{
    AdjustMouseCursorPos(event->pos().x(),event->pos().y());

    if(mShiftKeyDown)
    {
        qreal Drag = event->lastPos().x() - event->pos().x();
        DragPlots(Drag);
        AdjustMouseCursorPos(event->pos().x(),event->pos().y());
    }
    else if(mCtrlKeyDown)
    {
        qreal Drag = event->lastPos().y() - event->pos().y();
        if(Drag != 0)
        {
            if(Drag > 0)
            {
                ZoomIn();
            }
            else
            {
                ZoomOut();
            }

        }
    }

//	mCursorPos = event->pos().x();
//	if(mCursorPos < GRAPH_ZONE_X_OFFSET)
//		mCursorPos = GRAPH_ZONE_X_OFFSET;
//	else if(mCursorPos > GRAPH_ZONE_WIDTH + GRAPH_ZONE_X_OFFSET)
//		mCursorPos = GRAPH_ZONE_WIDTH + GRAPH_ZONE_X_OFFSET;

//	mCursor->setPos(mCursorPos,0);
//	int CursorTime = GetTimeForPixel(mCursorPos)/1000000;
//	mCursorPosTxt->setPlainText(QString().sprintf("%d ms",CursorTime));
}

qreal CLogViewPage::GetPixelForTime(quint64 Time)
{
	quint64 AbsoluteTime = Time - mStartTime;
    qreal PixelsPernSecs = (qreal)GRAPH_ZONE_WIDTH/(mStopTime - mStartTime);
	qreal Pixel = AbsoluteTime * PixelsPernSecs;

	return Pixel+GRAPH_ZONE_X_OFFSET;
}

quint64 CLogViewPage::GetTimeForPixel(qreal PixelPos)
{
	PixelPos -= GRAPH_ZONE_X_OFFSET;
	qreal nSecsPerPixels = (mStopTime - mStartTime)/GRAPH_ZONE_WIDTH;
	quint64 AbsoluteTimeForPixel = PixelPos*nSecsPerPixels;
	quint64 Time = mStartTime + AbsoluteTimeForPixel;

	return Time;
}

unsigned int CLogViewPage::ShowSpan(qreal PixelPos1, qreal PixelPos2)
{
    return ShowSpan(GetTimeForPixel(PixelPos1),GetTimeForPixel(PixelPos2));
}
unsigned int CLogViewPage::ShowSpan(quint64 TimePos1, quint64 TimePos2)
{
    if(TimePos1 > TimePos2)
    {
        mStartTime = TimePos2;
        mStopTime = TimePos1;
    }
    else
    {
        mStartTime = TimePos1;
        mStopTime = TimePos2;
    }

    mCurTimeSpan = mStopTime - mStartTime;
    mCurPixelTickValue = (qreal)GRAPH_ZONE_WIDTH/(qreal)mCurTimeSpan;	//pixels per microsecs

    if(mViewType == ZT1_LOG_TYPE)
    {
        for(int param = 0; param < ZT1_DISCREET_PLOTTABLE_NB_PARAM; param++)
        {
            mZT1DiscreetPlots[param].mPlotGaph->DisplayData(mStartTime,mStopTime);
        }
        for(int param = 0; param < ZT1_ANALOG_PLOTTABLE_NB_PARAM; param++)
        {
            mZT1AnalogPlots[param].mPlotGaph->DisplayData(mStartTime,mStopTime);
        }
    }
    else if(mViewType == ZT2_LOG_TYPE)
    {
        for(int param = 0; param < ZT2_DISCREET_PLOTTABLE_NB_PARAM; param++)
        {
            mZT2DiscreetPlots[param].mPlotGaph->DisplayData(mStartTime,mStopTime);
        }
        for(int param = 0; param < ZT2_ANALOG_PLOTTABLE_NB_PARAM; param++)
        {
          //  mZT2AnalogPlots[param].mPlotGaph->DisplayData(mStartTime,mStopTime);
        }
    }
    else
        return RET_ERROR;

    AdjustStaticCursorsPos();
    mRuler->SetRange(mStartTime,mStopTime);
    mRankRuler->SetRange(mStartTime,mStopTime);
    mEventRuler->SetRange(mStartTime,mStopTime);

    return RET_OK;
}

unsigned int CLogViewPage::AdjustStaticCursorsPos()
{
    if(mStaticCursor1->IsCursorSet())
    {
        quint64 CursorTime = mStaticCursor1->GetTime();
        if(CursorTime < mStartTime || CursorTime > mStopTime)
        {
            mStaticCursor1->hide();
        }
        else
        {
            qreal newpos = GetPixelForTime(CursorTime);
            mStaticCursor1->setPos(newpos,0);
            mStaticCursor1->show();
        }
    }
    if(mStaticCursor2->IsCursorSet())
    {
        quint64 CursorTime = mStaticCursor2->GetTime();
        if(CursorTime < mStartTime || CursorTime > mStopTime)
        {
            mStaticCursor2->hide();
        }
        else
        {
            qreal newpos = GetPixelForTime(CursorTime);
            mStaticCursor2->setPos(newpos,0);
            mStaticCursor2->show();
        }
    }
    return RET_OK;
}

unsigned int CLogViewPage::AdjustMouseCursorPos(qreal PosX, qreal PosY)
{
    mCursorPos = PosX;
    if(mCursorPos < GRAPH_ZONE_X_OFFSET)
        mCursorPos = GRAPH_ZONE_X_OFFSET;
    else if(mCursorPos > GRAPH_ZONE_WIDTH + GRAPH_ZONE_X_OFFSET)
        mCursorPos = GRAPH_ZONE_WIDTH + GRAPH_ZONE_X_OFFSET;

    qreal HCursorPos = PosY;
    if(HCursorPos > GRAPH_ZONE_HEIGHT)
        HCursorPos = GRAPH_ZONE_HEIGHT;


    mVCursor->setPos(mCursorPos,0);
    mHCursor->setPos(GRAPH_ZONE_X_OFFSET,HCursorPos);
  //  mCursor->update();
    int CursorTime = GetTimeForPixel(mCursorPos)/1000000;
	mPassageStats1Txt->setPlainText(QString().sprintf("Date & heure: %s\nStation : %s\nPosition : %d ms",mPassageDateTime.toUtf8().data(),mPassageStation.toUtf8().data(),CursorTime));
//    mCursorPosTxt->setPlainText(QString().sprintf("%d ms",CursorTime));

	for(int i = 0; i < ZT1_ANALOG_PLOTTABLE_NB_PARAM; i++)
		mZT1AnalogPlots[i].mPlotGaph->GetValueForTime(GetTimeForPixel(mCursorPos));

    update(mVCursor->boundingRect());
    update(mHCursor->boundingRect());
    return RET_OK;
}

unsigned int CLogViewPage::UpdateStaticCursorsDeltaTime()
{
    if(mStaticCursor1->IsCursorSet() == true && mStaticCursor2->IsCursorSet() == true)
    {
        QString Temp;
        quint64 Cur1,Cur2;
        qint64 Diff;
        Cur1 = mStaticCursor1->GetTime();
        Cur2 = mStaticCursor2->GetTime();
        Diff = Cur1 - Cur2;
        //qreal Delta = (qreal)(mStaticCursor1->GetTime() - mStaticCursor2->GetTime());
        qreal Delta = Diff;
        if(Delta < 0)
            Delta *= -1;

        if(Delta/1000000000 > 1)
        {
            QTextStream(&Temp) << "Delta: " << Delta/1000000000 << " s";
        }
        else if(Delta/1000000 > 1)
        {
            QTextStream(&Temp) << "Delta: " << Delta/1000000 << " ms";
        }
        else if(Delta/1000 > 1)
        {
            QTextStream(&Temp) << "Delta: " << Delta/1000 << " us";
        }
        else
        {
            QTextStream(&Temp) << "Delta: " << Delta << " ns";
        }

        mStaticCursorDeltaTimeTxt->setPlainText(Temp);
    }

    return RET_OK;

}
