#include <QtGui>
#include <iostream>

#include "Plot.h"

typedef unsigned int uint;
typedef unsigned long ul;

void Plot::setDefaults(){
	
	showGrid=true;
	showLines=false;
	zoomLock=false;
	analog=true;
	gridSpace=20;
	border=10;
	XStep=1;
	YStep=1;
	sDist=1;
	
	// Colors
	gridColor = new QColor(Qt::darkCyan);
	axesColor = new QColor(Qt::green);
	lineColor = new QColor(Qt::darkGray);
	bgColor = new QColor(Qt::black);
	fgColor = new QColor(Qt::red);
	
	//Animation
	animStatus=STOPED;
	animSleepTime=50;
	animationTimer=-1000;
	animPos=0;
	
	selStarted=false;
}

Plot::Plot(QWidget *parent) : QGraphicsView(parent){
	setDefaults();
	createUI();
	createMenus();
	drawGrid();
	drawAxes();
	connectSlots();
}

Plot::Plot(QString &filename, QWidget *parent) : QGraphicsView(parent){
	setDefaults();
	createUI();
	createMenus();
	drawGrid();
	drawAxes();

	loadSignal(filename);
	connectSlots();
}

Plot::~Plot(){

	/*
	 * Reject the dialog. If the dialog is running and the main window send close
	 * event, the dialog will hide... but the application will not terminate!!!!
	 * If the close event is sent by the Plot widget, reject is not needed...(???)
	 */
	propDlg->reject();
}

//-----Public Methods-----------------------------------------------------

// !!!! Color Changes do not redraw the scene... do it manually
void Plot::setFgColor(QColor c){*fgColor=c;}
void Plot::setBgColor(QColor c){
	*bgColor=c;
	scene->setBackgroundBrush(QBrush(*bgColor));
}
void Plot::setLinesColor(QColor c){*lineColor=c;}
void Plot::setGridColor(QColor c){*gridColor=c;}
void Plot::setAxesColor(QColor c){*axesColor=c;}

// Basic Items Of the Scene -> redraw or show/hide imediatelly
void Plot::setShowGrid(bool b){
	if (showGrid!=b) toggleGrid();
}

void Plot::setDrawAnalog(bool b){
	if (analog!=b) changeSignalType();
}

void Plot::setShowLines(bool b){
	if (showLines!=b) toggleLines();
}

void Plot::setSignal(const Signal &sig){
	signal.clear();
	signal.push(sig);

	redrawScene();

	
	actionStartStopAnim->setEnabled(true);
	actionSave->setEnabled(true);
	actionSaveAsImage->setEnabled(true);
	
	signalProp=SignalProperties();
}

void Plot::setSignalProperties(SignalProperties &sp){
	signalProp=sp;
}

void Plot::setGridSpace(int s){gridSpace=s;}
void Plot::setBorder(int b){border=b;}
void Plot::setAnimSleepTime(int time){
	if (animStatus == RUNNING){
		killTimer(animationTimer);
		animationTimer=startTimer(time);
	}
	animSleepTime=time;
}
void Plot::setSamplesDist(int d){sDist=d;}

QColor Plot::getFgColor() {return *fgColor;}
QColor Plot::getLinesColor() {return *lineColor;}
QColor Plot::getBgColor(){return *bgColor;}
QColor Plot::getGridColor(){return *gridColor;}
QColor Plot::getAxesColor(){return *axesColor;}
Signal & Plot::getSignal() {return signal.top();}
bool Plot::getShowGrid(){return showGrid;}
bool Plot::getDrawAnalog(){return analog;}
bool Plot::getShowLines(){return showLines;}
int Plot::getGridSpace(){return gridSpace;}
int Plot::getBorder(){return border;}
int Plot::getAnimSleepTime(){return animSleepTime;}
int Plot::getAnimStatus(){return animStatus;}
SignalProperties & Plot::getSignalProperties(){return signalProp;}
int Plot::getSamplesDist(){return sDist;}

bool Plot::loadSignal(QString &filename){
	
	// Init Signal
	Signal tmp=Signal(filename.toStdString().c_str());
	if (tmp.size()<1) return false;
	signal.push(tmp);

	// Init Signal Properties if there is any .cfg file
	QFileInfo sigfile(filename);
	QFileInfo propfile(sigfile.absolutePath()+"/"+sigfile.baseName()+".cfg");
	
	if (propfile.exists()){
		signalProp.loadSignalProp(propfile.filePath().toStdString().c_str());
		applySignalProperties();
	}

	redrawScene();
	
	actionSave->setEnabled(true);
	actionSaveAsImage->setEnabled(true);
	actionStartStopAnim->setEnabled(true);
	actionStartStopAnim->setEnabled(true);

	propDlg->setWindowTitle("Plot Properties - "+QString(signal.top().getFileName().c_str()));
	
	return true;
}

bool Plot::isEmpty(){return signal.isEmpty();}

/*
 * Redraw occurs only when the signal 
 * or plot vars are changed
 * so re-configure everything
 */
void Plot::redrawScene(){
	clearScene();

	// Set Scene Size
	if (!signal.isEmpty()) resizeRectCalcStep();

	drawGrid();
	drawAxes();

	if (analog) drawAnalogSignal();
	else {
		drawDigitalSignal();
		drawLines();
	}

	// Add Selection Point
	if (!signal.isEmpty()) {
		selPoint=scene->addPixmap(QPixmap(":frame_image.png"));
		selPoint->setZValue(IMAGE_Z);
		selPoint->setPos(scene->sceneRect().left()+5,scene->sceneRect().bottom()-selPoint->pixmap().height()-2);
	}

	// update Properties
	propDlg->updateContents();
}


void Plot::startAnimation(){
	if (animStatus==RUNNING) return;
	
	// No Line Drawing on Animation
	if (!analog) {
		if (showLines) toggleLines();
		actionToggleLines->setEnabled(false);
	}
	
	animPos=0;
	
	//Draw Basics
	clearScene();
	drawGrid();
	drawAxes();
	animStatus=RUNNING;
	actionPauseAnim->setEnabled(true);
	actionStartStopAnim->setText(QApplication::translate("MainWin", "Stop", 0, QApplication::UnicodeUTF8));
	
	animationTimer=startTimer(animSleepTime);
}

void Plot::pauseAnimation(){
	if (animStatus!=RUNNING) return;

	killTimer(animationTimer);
	animStatus=PAUSED;
	actionPauseAnim->setText(QApplication::translate("MainWin", "Resume", 0, QApplication::UnicodeUTF8));
}

void Plot::stopAnimation(){
	if (animStatus==STOPED) return;
	

	if (animStatus==PAUSED)
		actionPauseAnim->setText(QApplication::translate("MainWin", "Pause", 0, QApplication::UnicodeUTF8));


	killTimer(animationTimer);
	animPos=0;
	animStatus=STOPED;
	actionPauseAnim->setEnabled(false);
	actionStartStopAnim->setText(QApplication::translate("MainWin", "Start", 0, QApplication::UnicodeUTF8));
	redrawScene();
	
	if (!analog) actionToggleLines->setEnabled(true);
}

void Plot::resumeAnimation(){
	if (animStatus!=PAUSED) return;

	animationTimer=startTimer(animSleepTime);
	animStatus=RUNNING;
	actionPauseAnim->setText(QApplication::translate("MainWin", "Pause", 0, QApplication::UnicodeUTF8));
}


//----Private Methods-----------------------------------------------------
// Drawing -----------------------
void Plot::drawLines(){
	
	if (signal.isEmpty()) return;
	// Hold items in list
	
	linesList.clear();
	
	QRectF srect = scene->sceneRect();
	QPen linepen(*lineColor,1,Qt::DashLine);

	QPointF zero=signalToScene(Point(0,0));
	
	for (ul i=0; i<signal.top().size(); i++){
		QPointF current=signalToScene(signal.top()[i]);
		QLineF l;
		if (signal.top()[i].y > 0)
			l=QLineF(current.x(),current.y()+1,current.x(),zero.y()-1);
		else
			l=QLineF(current.x(),current.y()-1,current.x(),zero.y()+1);
			
		linesList.append(scene->addLine(l,linepen));
		linesList[i]->setZValue(LINE_Z);
		if (!showLines) linesList[i]->hide();
	}
	
}

void Plot::drawGrid(){
	
	gridLinesList.clear();
	int linecount=0;
	
	QRectF srect = scene->sceneRect();
	QPen pen(*gridColor,1);
	
	QPointF zero=signalToScene(Point(0,0));
	
	int leftStart=(int)zero.x()%gridSpace;
	int topStart=(int)zero.y()%gridSpace;
	//int topStart=(int)(srect.top()+(double) ((int)srect.top() % gridSpace));
	
	// VR
	for (int i=leftStart; i<scene->width(); i+=gridSpace){
		QLineF l(i,srect.top(),i,srect.bottom());
		gridLinesList.append(scene->addLine(l, pen));
		gridLinesList[linecount]->setZValue(GRID_Z);
		if (!showGrid) gridLinesList[linecount]->hide();
		linecount++;
	}

	// HR
	for (int i=topStart; i<scene->height(); i+=gridSpace){
		QLineF l(srect.left(),i,srect.right(),i);
		gridLinesList.append(scene->addLine(l, pen));
		gridLinesList[linecount]->setZValue(GRID_Z);
		if (!showGrid) gridLinesList[linecount]->hide();
		linecount++;
	}
		
}

void Plot::drawAxes(){

	if (isEmpty()) return;

	QRectF srect = scene->sceneRect();
	QPen pen(*axesColor,1);

	QPointF zero=signalToScene(Point(0,0));
	QLine y((int)zero.x(),0,(int)zero.x(),(int)srect.height());
	QLine x(0,(int)zero.y(),(int)srect.width(),(int)zero.y());

	// Zero in scene
	if (scene->sceneRect().contains(zero)){
		scene->addLine(y, pen)->setZValue(AXES_Z);
		scene->addLine(x, pen)->setZValue(AXES_Z);
		return;
	}

	//y'y
	if (signal.top().getMaxX()*signal.top().getMinX()<=0) {
		scene->addLine(y, pen)->setZValue(AXES_Z);
	}

	// x'x
	if (signal.top().getMaxY()*signal.top().getMinY()<=0) {
		QLine x(0,(int)zero.y(),(int)srect.width(),(int)zero.y());
	}
}


QPointF Plot::signalToScene(const Point & p){
	return QPointF(XStep*(p.x-signal.top().getMinX())+border,(signal.top().getMaxY()-p.y)*YStep+border);
}
Point Plot::sceneToSignal(const QPointF & p){
	double x=(p.x()-border)/XStep + signal.top().getMinX();
	double y=signal.top().getMaxY() - ( (p.y()-border ) / YStep );
	return Point(x,y);
}

void Plot::resizeRectCalcStep(){
	
	// Check for 0 (maxY==minY (ex. =0)) OR TOO CLOSE TO ZERO (epsilon)
	double amp=fabs(signal.top().getMaxY()-signal.top().getMinY());
	

	if (amp!=0) YStep=(scene->height()-2*border)/amp;
	else YStep=scene->height()/2;
	XStep=1/signal.top().getMinXdist();
	XStep*=sDist;

	// Resize Scene
	//qreal posx=signal.top().getMinX()*XStep-border;
	//qreal w=fabs(signal.top().getMaxX()-signal.top().getMinX())*XStep+2*border;
	
	qreal w=fabs(signal.top().getMaxX()-signal.top().getMinX())*XStep+2*border;
	
	//qreal posy=-signal.top().getMaxY()*YStep-border;

	// No need to make the scene smaller...(or bigger)
	// We just have to adjust posy o make our (full) signal visible
	//[qreal h=fabs(signal.top().getMaxY()-signal.top().getMinY())*YStep+2*border;]
	// If amp==0 and then we have a single line
	// and we must make the line appear at the middle of the scene
//	double posy=0;
//	if (amp==0){
//		posy=-signal.top().getMaxY()*YStep-DEFSCENE_H/2;
//	}


	QRectF newrect(0,0,w,DEFSCENE_H);
	scene->setSceneRect (newrect);
}

void Plot::drawAnalogSignal(){

	if (signal.isEmpty()) return;

	QPointF lastPoint=signalToScene(signal.top()[0]);

	
	QPen pen(*fgColor,1);
	
	ul stopPoint=animPos+1;
	if (animStatus==STOPED) stopPoint=signal.top().size();
	
	for (ul i=1; i<stopPoint; i++){

		QPointF nextPoint=signalToScene(signal.top()[i]);

		QLineF l(lastPoint,nextPoint);

		lastPoint=nextPoint;

		QGraphicsItem * item=scene->addLine(l,pen);
		item->setZValue(SIGNAL_Z);

		// Set Tool tip area
		char tip[50];
		tip[0]='\0';
		sprintf(tip,"x: %f\ny: %f",signal.top()[i].x,signal.top()[i].y);
		scene->addEllipse(
			QRectF(nextPoint.rx()-1,nextPoint.ry()-1,3,3),
			QPen(Qt::transparent,0)
			)->setToolTip(tip);
	}
}

void Plot::drawDigitalSignal(){

	if (signal.isEmpty()) return;

	
	QPen pen(*fgColor,1);
	
	ul stopPoint=animPos+1;
	if (animStatus==STOPED) stopPoint=signal.top().size();
	
	for (ul i=0; i<stopPoint; i++){

		QPointF curPoint=signalToScene(signal.top()[i]);

		// Create line/point
		QLineF l(curPoint,curPoint);

		scene->addLine(l,pen)->setZValue(SIGNAL_Z);

		// Set Tool tip area
		char tip[50];
		tip[0]='\0';
		sprintf(tip,"x: %f\ny: %f",signal.top()[i].x,signal.top()[i].y);
		scene->addEllipse(QRectF(curPoint.x()-1,curPoint.y()-1,3,3) , QPen(Qt::transparent,1) )->setToolTip(tip);
		
	}

}

void Plot::clearScene(){
	// Clear Everything
	QList<QGraphicsItem *> list =scene->items();
	
	QList<QGraphicsItem *>::Iterator it = list.begin();
	for (; it != list.end(); ++it) {
		if ( *it )
		delete *it;
	}
}

void Plot::animateAnalog(){

	if (signal.isEmpty()) return;

	if (animPos<signal.top().size()-1){
		QPointF lastPoint=signalToScene(signal.top()[animPos]);
		QPen pen(*fgColor,1);

	
		QPointF nextPoint=signalToScene(signal.top()[animPos+1]);
		QLineF l(lastPoint,nextPoint);
	
		QGraphicsItem *item=scene->addLine(l,pen);
		item->setZValue(SIGNAL_Z);
	
		ensureVisible(item,  50,  50 );
		animPos++;
	}else{
		clearScene();
		resetCachedContent();
		drawGrid();
		drawAxes();
		animPos=0;
		updateSceneRect (scene->sceneRect());
	}

}

void Plot::animateDigital(){

	if (signal.isEmpty()) return;

	if (animPos<signal.top().size()){

		QPen pen(*fgColor,1);

	
		QPointF nextPoint=signalToScene(signal.top()[animPos+1]);
		QPointF testPoint(nextPoint);
		QLineF l(nextPoint,testPoint);
	
		QGraphicsItem *item=scene->addLine(l,pen);
		item->setZValue(SIGNAL_Z);
	
		ensureVisible(item,  50,  50 );
		animPos++;
	}else{
		clearScene();
		resetCachedContent();
		drawGrid();
		drawAxes();
		animPos=0;
		updateSceneRect (scene->sceneRect());
	}

}
// End Of Drawing-----

//Private Methods
void Plot::applySignalProperties(){
	analog=signalProp.isAnalog();
}

void Plot::connectSlots(){
	
}

void Plot::createUI(){
	
	// View
	setInteractive(true);
	setMinimumSize(DEFSCENE_W+5,DEFSCENE_H+20);
	setSizePolicy(QSizePolicy::Ignored,QSizePolicy::Fixed);
	setResizeAnchor(QGraphicsView::AnchorViewCenter);
	setAlignment(Qt::AlignTop);
	setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
	setDragMode(QGraphicsView::RubberBandDrag);
	setAcceptDrops(true);
	setCacheMode(QGraphicsView::CacheBackground);	

	// Qt 4.3
	//setViewportUpdateMode (QGraphicsView::FullViewportUpdate);


	// Scene
	scene = new QGraphicsScene (0,0,DEFSCENE_W,DEFSCENE_H,this);
	scene->setBackgroundBrush(QBrush(*bgColor));
	scene->setItemIndexMethod(QGraphicsScene::NoIndex);

	setScene(scene);

	// Properties
	propDlg=new PlotProperties(this);
	
}


void Plot::createMenus(){
	// PopUp Menu
	PlotPopUp=new QMenu("Menu");
		// Actions    
	actionLoad = new QAction(this);
	actionLoad->setText(QApplication::translate("MainWin", "&Load Signal", 0, QApplication::UnicodeUTF8));
	connect(actionLoad,SIGNAL(triggered()),this,SLOT(load()));

	actionSave = new QAction(this);
	actionSave->setText(QApplication::translate("MainWin", "&Save Signal", 0, QApplication::UnicodeUTF8));
	actionSave->setEnabled(false);
	connect(actionSave,SIGNAL(triggered()),this,SLOT(save()));
	
	actionSaveAsImage = new QAction(this);
	actionSaveAsImage->setText(QApplication::translate("MainWin", "&Save As Image", 0, QApplication::UnicodeUTF8));
	actionSaveAsImage->setEnabled(false);
	connect(actionSaveAsImage,SIGNAL(triggered()),this,SLOT(saveAsImage()));
	
	actionToggleGrid = new QAction(this);
	actionToggleGrid->setCheckable(true);
	actionToggleGrid->setChecked(true);
	actionToggleGrid->setText(QApplication::translate("MainWin", "Show G&rid", 0, QApplication::UnicodeUTF8));
	connect(actionToggleGrid,SIGNAL(triggered()),this,SLOT(toggleGrid()) );

	actionDrawDigital = new QAction(this);
	actionDrawDigital->setText(QApplication::translate("MainWin", "Draw &Digital", 0, QApplication::UnicodeUTF8));
	connect(actionDrawDigital,SIGNAL(triggered()),this,SLOT(changeSignalType()) );
	
	actionToggleLines = new QAction(this);
	actionToggleLines->setText(QApplication::translate("MainWin", "Show L&ines", 0, QApplication::UnicodeUTF8));
	actionToggleLines->setEnabled(false);
	actionToggleLines->setCheckable(true);
	actionToggleLines->setChecked(false);
	connect(actionToggleLines,SIGNAL(triggered()),this,SLOT(toggleLines()) );
	
	actionProperties = new QAction(this);
	actionProperties->setText(QApplication::translate("MainWin", "&Properties", 0, QApplication::UnicodeUTF8));
	connect(actionProperties,SIGNAL(triggered()),this,SLOT(showPropDlg()) );
	
	actionBack=new QAction (this);
	actionBack->setText(QApplication::translate("MainWin", "&Back", 0, QApplication::UnicodeUTF8));
	//actionBack->setShortcut(tr("B"));
	actionBack->setEnabled(false);
	connect(actionBack,SIGNAL(triggered()),this,SLOT(zoomOut()));
	
	actionLockZoom= new QAction(this);
	actionLockZoom->setText(QApplication::translate("MainWin", "Lo&ck Zoom", 0, QApplication::UnicodeUTF8));
	actionLockZoom->setCheckable(true);
	actionLockZoom->setChecked(false);
	connect(actionLockZoom,SIGNAL(triggered()),this,SLOT(toggleZoomLock()));
	
	// Animation
	
	animationMenu=new QMenu("Animation");
	
	actionStartStopAnim = new QAction(this);
	actionStartStopAnim->setEnabled(false);
	actionStartStopAnim->setText(QApplication::translate("MainWin", "Start", 0, QApplication::UnicodeUTF8));
	connect(actionStartStopAnim,SIGNAL(triggered()),this,SLOT(startStopAnim()));
	
	actionPauseAnim = new QAction(this);
	actionPauseAnim->setEnabled(false);
	actionPauseAnim->setText(QApplication::translate("MainWin", "Pause", 0, QApplication::UnicodeUTF8));
	connect(actionPauseAnim,SIGNAL(triggered()),this,SLOT(pauseResumeAnim()));
	
	animationMenu->addAction(actionStartStopAnim);
	animationMenu->addAction(actionPauseAnim);

	PlotPopUp->addAction(actionLoad);
	PlotPopUp->addAction(actionSave);
	PlotPopUp->addAction(actionSaveAsImage);
	PlotPopUp->addSeparator();
	PlotPopUp->addAction(actionToggleGrid);
	PlotPopUp->addMenu(animationMenu);
	PlotPopUp->addSeparator();
	PlotPopUp->addAction(actionDrawDigital);
	PlotPopUp->addAction(actionToggleLines);
	PlotPopUp->addSeparator();
	PlotPopUp->addAction(actionBack);
	PlotPopUp->addAction(actionLockZoom);
	PlotPopUp->addSeparator();
	PlotPopUp->addAction(actionProperties);
}

void Plot::zoomIn(){
	if (zoomLock) return;
	if (signal.isEmpty()) return;
	if (animStatus!=STOPED) return;
	
	QPointF toSceneStart=mapToScene(selStart);
	QPointF toSceneStop=mapToScene(selStop);
	
	if (!scene->sceneRect().contains(toSceneStop) && !scene->sceneRect().contains(toSceneStart)) return;
		
	Point toSigStart=sceneToSignal(toSceneStart);
	Point toSigStop=sceneToSignal(toSceneStop);
		
		
	// find Bounds
	double maxX,maxY,minX,minY;
	
	if (toSigStart.x>toSigStop.x) {
		maxX=toSigStart.x;
		minX=toSigStop.x;
	}else{
		maxX=toSigStop.x;
		minX=toSigStart.x;
	}
	
	if (toSigStart.y>toSigStop.y) {
		maxY=toSigStart.y;
		minY=toSigStop.y;
	}else{
		maxY=toSigStop.y;
		minY=toSigStart.y;
	}
	
	Signal sig;
	
	//Hold if Y went out. If it get's in again ->ERROR
	bool wentOut=false;
	
	for (ul i=0; i<signal.top().size(); i++){
		// Check range
		if (signal.top()[i].x<minX) continue;
		if (signal.top()[i].x>=maxX) break;
		
		// Check amp
		if (signal.top()[i].y>maxY || signal.top()[i].y<minY){
			if (sig.size()>0) wentOut=true;
			continue;
		}
		
		//Point is in  bounds. Check if it was gone out
		if (wentOut){
			QMessageBox::critical(this,"ERROR","Amplitude (y) MUST not exceed selection area.");
			return;
		}
		
		// Accept point
		Point p=signal.top()[i];
		sig+=p;
	}
	
	// Not goot at pointing ...
	if (sig.size()<2) return;
	
	signal.push(sig);
	actionBack->setEnabled(true);
	redrawScene();
}

// Events Override
void Plot::timerEvent(QTimerEvent * event){
	if (event->timerId() == animationTimer) 
		if (analog) animateAnalog();
		else animateDigital();
}

void Plot::contextMenuEvent(QContextMenuEvent  * event){
	PlotPopUp->exec(event->globalPos());
}

void Plot::mousePressEvent(QMouseEvent *event){
	
	if (event->buttons() & Qt::LeftButton){
		// If empty no zoom neither drag n drop can be done
		if (isEmpty()) return;
		if (animStatus!=STOPED) return;
		
		if (selPoint->contains( selPoint->mapFromScene(mapToScene(event->pos())) ) ) {
			QDrag *drag = new QDrag(this);
			QMimeData *mimeData = new QMimeData;

			mimeData->setData("text/signal", 0 );
			drag->setMimeData(mimeData);

			drag->start();
		}else{
			selStarted=true;
			selStart=event->pos();
			selStop=event->pos();
			// Call Parent
			QGraphicsView::mousePressEvent(event);
		}
	}

}
void Plot::mouseMoveEvent(QMouseEvent *event){
	if (event->buttons() & Qt::LeftButton){
		selStop=event->pos();
		QGraphicsView::mouseMoveEvent(event);
	}
}

void Plot::mouseReleaseEvent(QMouseEvent *event){
	
		if (selStarted & (selStop-selStart).manhattanLength() > 3){
			zoomIn();
			QGraphicsView::mouseReleaseEvent(event);
			selStarted=false;
		}
}

// Move is needed else it is not working..
void Plot::dragLeaveEvent(QDragLeaveEvent *){}
void Plot::dragMoveEvent(QDragMoveEvent *){}

void Plot::dragEnterEvent( QDragEnterEvent * event){
	if ((Plot *)event->source() != this && event->mimeData()->hasFormat("text/signal")){
		event->accept();
	}
	else
		event->ignore();
}

void Plot::dropEvent(QDropEvent *event){
	event->accept();
	setSignal(((Plot *)event->source())->getSignal());
	setSignalProperties(((Plot *)event->source())->getSignalProperties());
	propDlg->setWindowTitle("Plot Properties - "+QString(signal.top().getFileName().c_str()));
	redrawScene();
}



// Public Slots
void Plot::startStopAnim(){
	
	if (animStatus==STOPED) startAnimation();
	else stopAnimation();

	
}

void Plot::pauseResumeAnim(){
	if (animStatus==RUNNING) pauseAnimation();
	else if (animStatus==PAUSED) resumeAnimation();
}

void Plot::showPropDlg(){
	propDlg->updateContents();
	propDlg->show();
}

void Plot::zoomOut(){
	if (zoomLock) return;
	if (signal.size()>2)
		signal.pop();
	else if (signal.size()==2){
		signal.pop();
		actionBack->setEnabled(false);
	}
	redrawScene();
}
void Plot::toggleZoomLock(){	
	zoomLock=!zoomLock;
}

void Plot::toggleGrid(){
	if (showGrid){
		for (int i=0; i<gridLinesList.size(); i++){
			gridLinesList[i]->hide();
		}
		actionToggleGrid->setChecked(false);
	}
	else {
		for (int i=0; i<gridLinesList.size(); i++){
			gridLinesList[i]->show();
		}
		actionToggleGrid->setChecked(true);
	}
	
	
	showGrid=!showGrid;
}

void Plot::toggleLines(){
	if (showLines){
		for (int i=0; i<linesList.size(); i++){
			linesList[i]->hide();
		}
		actionToggleLines->setChecked(false);
	}
	else {
		for (int i=0; i<linesList.size(); i++){
			linesList[i]->show();
		}
		actionToggleLines->setChecked(true);
	}
	
	showLines=!showLines;
}

void Plot::changeSignalType(){
	if (analog) {
		// draw digital clicked
		actionDrawDigital->setText(QApplication::translate("MainWin", "Draw &Analog", 0, QApplication::UnicodeUTF8));
		if (animStatus==STOPED) actionToggleLines->setEnabled(true);
	}else {
		// draw analog clicked
		actionDrawDigital->setText(QApplication::translate("MainWin", "Draw &Digital", 0, QApplication::UnicodeUTF8));
		actionToggleLines->setEnabled(false);
	}
	
	analog=!analog;
	signalProp.setAnalog(analog);
	redrawScene();
}


void Plot::load(){
	
	//File Dialog
	QFileDialog dialog(this,tr("Load Signal From File"));
	
	// Initial Directory
	QString dir=QDir::homePath();
	if (!isEmpty()) 
		if (signal.top().getFileName()!="") {
			QFileInfo curfile(signal.top().getFileName().c_str());
			dir=curfile.absolutePath();
		}
	
	dialog.setDirectory(dir);
	
	// File Extension Filters
	 QStringList filters;
		filters << "DAT Files (*.dat *.data)"
			<< "Sig Files (*.sig )"
			<< "Any files (*.*)";
	
	dialog.setFilters(filters);
	dialog.setFileMode(QFileDialog::ExistingFile);
	dialog.setViewMode(QFileDialog::Detail);
	dialog.setAcceptMode(QFileDialog::AcceptOpen);
	
	// Execute
	QString fileName;
	 if (dialog.exec()) 
	 	fileName = dialog.selectedFiles()[0];
	 else 
	 	return;

	loadSignal(fileName);
}
void Plot::save(){
	
	//File Dialog
	QFileDialog dialog(this,tr("Save Signal"));

	// Initial Directory
	QString dir;
	

	if (signal.top().getFileName()!=""){
		QFileInfo finfo(signal.top().getFileName().c_str());
		dir=finfo.path();
	}
	else
		dir=QDir::homePath();

	dialog.setDirectory(dir);

	dialog.setViewMode(QFileDialog::Detail);
	dialog.setAcceptMode(QFileDialog::AcceptSave);
	
	// Execute
	QString fileName;
	if (dialog.exec())
	 	fileName = dialog.selectedFiles()[0];
	else
		return;
	
	QFileInfo sigfile(fileName);
	QFileInfo propfile(sigfile.absolutePath()+"/"+sigfile.baseName()+".cfg");
	
	signal.top().save(fileName.toStdString().c_str());
	signalProp.save(propfile.filePath().toStdString().c_str());
}

void Plot::saveAsImage(){
	//File Dialog
	QFileDialog dialog(this,tr("Save Signal"));
	
	// Initial Directory
	QString dir;
	

	if (signal.top().getFileName()!=""){
		QFileInfo finfo(signal.top().getFileName().c_str());
		dir=finfo.path();
	}
	else
		dir=QDir::homePath();

	dialog.setDirectory(dir);

	dialog.setViewMode(QFileDialog::Detail);
	dialog.setAcceptMode(QFileDialog::AcceptSave);
	
	// Supported Image Extension Filters
	QStringList filters;
		filters << "PNG Image (*.png)";
	dialog.setFilters(filters);
	
	// Execute
	QString fileName;
	if (dialog.exec()){
		fileName = dialog.selectedFiles()[0];
		QFileInfo imginfo(fileName);
		if (imginfo.suffix()!="png")
			fileName+=".png";
 	}
	else
		return;
		
	QFile imgfile(fileName);
	if (imgfile.exists()) imgfile.remove();
	
	if (viewport()->rect().width()<scene->sceneRect().width()){
		// Get only viewed Items.
		
		QImage img(viewport()->rect().width(),viewport()->rect().height(),QImage::Format_ARGB32);
		QPainter painter(&img);
	
		// Background...
		painter.setBackground(QBrush(*bgColor));			// Set Color
		painter.setBackgroundMode(Qt::OpaqueMode);			// No Transparent Mode
		painter.fillRect(viewport()->rect(), painter.background());	// Now Draw it
	
		render(&painter);
	
		img.save(fileName,"PNG");
	}
	else{
		/* Get Only scene from the viewport (scene<viewport)
		 * DONT USE scene->render(...) it has bug and can't
		 * draw zoomed digital signals (no points on image..!?!?)
		 */
		
		QImage img((int)scene->sceneRect().width(),(int)scene->sceneRect().height(),QImage::Format_RGB32);
		QPainter painter(&img);
	
		// Background...
		painter.setBackground(QBrush(*bgColor));			// Set Color
		painter.setBackgroundMode(Qt::OpaqueMode);			// No Transparent Mode
		painter.fillRect(QRect(0,0,(int)scene->sceneRect().width(),(int)scene->sceneRect().height()), painter.background());	
		
		int posx=(viewport()->rect().width()-(int)scene->sceneRect().width())/2;
		
		render(&painter,QRect(),QRect(posx,0,(int)scene->sceneRect().width(),(int)scene->sceneRect().height()));
	
		img.save(fileName,"PNG");
	}
	
}



