/*
* Title:	PhaseTableWin.cpp 
* Author:	M.Thomas BEAM Ltd
* Date:		2007-02-13
*
* Contents:	State Table Setup
*
* Mod Rec:
*
*/


#include <PhaseTableWin.h>
#include <qlayout.h>
#include <qpushbutton.h>
#include <qvgroupbox.h>
#include <qmessagebox.h>
#include <qlabel.h>
#include <qfiledialog.h>
#include <qcheckbox.h>
#include <BFile.h>
#include <BQComboBox.h>

#include <qgroupbox.h>
#include <qvbox.h>
#include <qlistbox.h>
#include <qvalidator.h>
#include <qtable.h>
#include <Globals.h>
#include <math.h>
#include <TmsD.h>
#include <TmsC.h>
#include <TmsS.h>
#include <TmsLib.h>


const unsigned int MAX_CYCLE_STATES = 16;

using namespace Tms;

DetailViewGui::DetailViewGui(){
	QGridLayout*	l;
	
	l = new QGridLayout(this, 1, 1, 11, 6);

	ostateGui = new TmsStateGui(this);
	ostateGui->init();
	ostateGui->setMinimumSize(900,700);
	l->addWidget(ostateGui, 0, 0);
}

void DetailViewGui::init(Tms::CycleParamEdit& cycleParam, int reset){
	ostateGui->view(cycleParam, reset);
}


PhaseTableWin::PhaseTableWin(QWidget* parent,Control& c) : ocontrol(c)  {
	QGridLayout*	grid;
	BString		s;
	int		row = 0;
	int		col = 0;
	QVGroupBox*	baseParams;
	QVGroupBox*	positions;
	QVGroupBox * 	loadParams;
	QWidget*	w;
	QGridLayout* 	v;
	int		n;

	odetailViewGui = 0;

	oparams.cycleType = "";
	oparams.info = "";
	oparams.pllInitialFrequency = 0;
	oparams.pllInitialFrequencyDelay = 0;
	oparams.pllFrefGain = 0;
	oparams.pllGain = 0;
	oparams.channel = 0;

	for (unsigned int n = 0; n < MAX_CYCLE_STATES;n++) {
		CycleParamState s;
 		oparams.getDefaultState(s);
		ocycleStates.append(s);
	}
	

	QValidator* 		validatorInt = new QIntValidator(-(int)pow(2,31), (int)pow(2,31), this );
	QValidator* 		validatorDouble = new QDoubleValidator(this );
	QRegExpValidator* 	validatorHex = new QRegExpValidator(this);

	QRegExp		rx;
	rx.setPattern("0x[0-9,a-f][0-9,a-f][0-9,a-f][0-9,a-f][0-9,a-f][0-9,a-f][0-9,a-f][0-9,a-f]");
	validatorHex->setRegExp(rx);


	grid = new QGridLayout(this,5,3);
        grid->setMargin(10);
        grid->setSpacing(10);

	s = "<p><b>Cycle Parameters<b></p>";
	s += "<p>Select Cycle parameters file to be loaded</p>";

	// Load Cycle Parameters

	createGridGroupBox(loadParams,"Load Cycle Parameters",w,v);
	ocycleTypes 	= new QListBox(w,"cycleList");
	oloadFromTms 	= new QPushButton("Load from TMS",w);
	ofilename 	= new QLineEdit(w,"S");
	oselectFile 	= new QPushButton("Select",w);
	oloadFromFile 	= new QPushButton("Load from File",w);
	
	row = 0; col = 0;
	v->addWidget(new QLabel("Load from TMS",w),row,col);
	v->addMultiCellWidget(ocycleTypes,row,row + 8,col + 1,col +1);
	v->addWidget(oloadFromTms,row,col + 3);

	row = 9;col = 0;
	v->addWidget(new QLabel("Load from File",w),row,0);
	v->addWidget(ofilename,row,col + 1);
	v->addWidget(oselectFile,row,col +2);
	v->addWidget(oloadFromFile,row,col +3);


	// Base Paramters

	// Should have classed a GridGroupBox !
	
	createGridGroupBox(baseParams,"Base Parameters",w,v);
	ocycleType 			= new QLineEdit(w,"");
	oname 				= new QLineEdit(w,"");
	ochannel 			= new QSpinBox(w,""); ochannel->setMinValue(0); ochannel->setMaxValue(999);
	oring	 			= new QSpinBox(w,""); oring->setMinValue(0); oring->setMaxValue(4);
	oinfo 				= new QLineEdit(w,"");
	opllCycleStartFrequency 	= new QLineEdit(w,"");opllCycleStartFrequency->setValidator(validatorInt);
	opllInitialFrequency 		= new QLineEdit(w,"");opllInitialFrequency->setValidator(validatorInt);
	opllInitialFrequencyDelay	= new QLineEdit(w,"");opllInitialFrequencyDelay->setValidator(validatorInt);
	opllFrefGain			= new QLineEdit(w,"");opllFrefGain->setValidator(validatorInt);
	opllGain			= new QLineEdit(w,"");opllGain->setValidator(validatorInt);
	opllDdsMinimum			= new QLineEdit(w,"");opllDdsMinimum->setValidator(validatorInt);
	opllDdsMaximum			= new QLineEdit(w,"");opllDdsMaximum->setValidator(validatorInt);
	ostateDelay			= new QLineEdit(w,"");ostateDelay->setValidator(validatorInt);

	row = 0;col = 0;
	addEditorToGrid(v,w,"Cycle Type",			ocycleType,row,col);
	addEditorToGrid(v,w,"Name",				oname,row,col + 2); row++;
	addEditorToGrid(v,w,"Ring",				oring,row,col);
	addEditorToGrid(v,w,"Channel",				ochannel,row,col + 2); row++;
	addEditorToGrid(v,w,"Info",				oinfo,row,col, 3); row++;
	addEditorToGrid(v,w,"Pll CycleStart Frequency",		opllCycleStartFrequency,row,col); row++;
	addEditorToGrid(v,w,"Pll Init Frequency",		opllInitialFrequency,row,col);
	addEditorToGrid(v,w,"Pll Init Frequency Delay(ms)",	opllInitialFrequencyDelay,row,col + 2); row++;
	addEditorToGrid(v,w,"Pll Fref Gain",			opllFrefGain,row,col);
	addEditorToGrid(v,w,"Pll Gain (shift right)",		opllGain,row,col + 2); row++;
	addEditorToGrid(v,w,"Pll Dds Max",		opllDdsMinimum,row,col);
	addEditorToGrid(v,w,"Pll Dds Min",		opllDdsMaximum,row,col + 2); row++;
	addEditorToGrid(v,w,"State Delay (Fref)",	ostateDelay,row,col);

	// Positions

	createGridGroupBox(positions,"Positions",w,v);
	ophaseDelays 	= new QTable(40,1,w,"");
	ooffset 	= new QSpinBox(w,"");
	oaddOffsets 	= new QPushButton("Add Offset to all channels",w);
	oloadDefaults 	= new QPushButton("Load Defaults",w,"");


	ophaseDelays->horizontalHeader()->setLabel( 0, "Phase Offset" );
	ophaseDelays->setColumnStretchable (0,true);
	ooffset->setMaxValue(512);
	ooffset->setMinValue(-512);
	ooffset->setWrapping(true);

	row = 0; col = 0;
	addEditorToGrid(v,w,"Positions",ophaseDelays,row,col); row++;
	addEditorToGrid(v,w,"Offset",	ooffset,row,col); row++;
	
	v->addWidget(oloadDefaults,row,0);v->addWidget(oaddOffsets,row,1);
	
	
	// State Setup

	createGridGroupBox(ostateSetups,"State Setup",w,v);
	
	oenableModifications	= new QCheckBox("Enable Modifications",w,"");
	ostateNum	= new QSpinBox(w, "");
	ostateNum->setMinValue(0);
	ostateNum->setMaxValue(15);
	ostateNum->setWrapping(0);
	ophaseNames	= new QComboBox(w, "");
	oaddNextState	= new QPushButton("Append state",w,"");
	odelLastState	= new QPushButton("Delete Last State",w,"");

	olo1Harmonic 	= new QLineEdit(w,"");olo1Harmonic->setValidator(validatorInt);
	olo1Phase 	= new QLineEdit(w,"");olo1Phase->setValidator(validatorDouble);
	of1Ref	 	= new QCheckBox("F1RefSigma",w,"");
	of1Lo	 	= new QCheckBox("F1LoMsb",w,"");
	olo2Harmonic 	= new QLineEdit(w,"");olo2Harmonic->setValidator(validatorInt);
	olo2Phase 	= new QLineEdit(w,"");olo2Phase->setValidator(validatorDouble);
	of2Ref	 	= new QCheckBox("F2RefSigma",w,"");
	of2Lo	 	= new QCheckBox("F2LoMsb",w,"");

	obit6 		= new QCheckBox("StateBit6",w,"");
	obit7 		= new QCheckBox("StateBit7",w,"");
	opllF2 		= new QCheckBox("Pll Use F2",w,"");
	oacquireData 	= new QCheckBox("Acquire Data",w,"");

	obunchMask = new QLineEdit(w,"");obunchMask->setValidator(validatorHex);
	omean1Mask = new QLineEdit(w,"");omean1Mask->setValidator(validatorHex);
	omean2Mask = new QLineEdit(w,"");omean2Mask->setValidator(validatorHex);
	
	ogateWidth 	= new QLineEdit(w,"");ogateWidth->setValidator(validatorDouble);
	ogatePhase 	= new QLineEdit(w,"");ogatePhase->setValidator(validatorDouble);
	oblrWidth 	= new QLineEdit(w,"");oblrWidth->setValidator(validatorDouble);
	oblrPhase 	= new QLineEdit(w,"");oblrPhase->setValidator(validatorDouble);

	oenableModifications->setMaximumWidth(200);
	oaddNextState->setMaximumWidth(200);
	odelLastState->setMaximumWidth(200);
	obunchMask->setMaximumWidth(200);
	omean1Mask->setMaximumWidth(200);
	omean2Mask->setMaximumWidth(200);
	olo1Harmonic->setMaximumWidth(200);
	olo1Phase->setMaximumWidth(200);
	olo2Harmonic->setMaximumWidth(200);
	olo2Phase->setMaximumWidth(200);
	oacquireData->setMaximumWidth(200);
	ogateWidth->setMaximumWidth(200);
	ogatePhase->setMaximumWidth(200);
	oblrWidth->setMaximumWidth(200);
	oblrPhase->setMaximumWidth(200);

	row = 0;col = 0;
	v->addWidget(oenableModifications,row,0);
	v->addWidget(ostateNum,row,col+1);
	addEditorToGrid(v,w,"Period", ophaseNames, row, col+2);  
	v->addWidget(oaddNextState,row,col+4);
	v->addWidget(odelLastState,row,col+5); row++;

	addEditorToGrid(v,w,"Lo1 Harmonic",	olo1Harmonic,row,col); 
	addEditorToGrid(v,w,"Lo1 Phase",	olo1Phase,row,col + 2);
	v->addWidget(of1Ref,row,col+4);
	v->addWidget(of1Lo,row,col+5); row++;
	addEditorToGrid(v,w,"Lo2 Harmonic",	olo2Harmonic,row,col); 
	addEditorToGrid(v,w,"Lo2 Phase",	olo2Phase,row,col + 2);
	v->addWidget(of2Ref,row,col+4);
	v->addWidget(of2Lo,row,col+5); row++;
	v->addWidget(obit6,row,col+1);
	v->addWidget(obit7,row,col+3);
	v->addWidget(opllF2,row,col+4);
	v->addWidget(oacquireData,row,col+5); row++;

	addEditorToGrid(v,w,"Bunch Mask",	obunchMask,row,col); 
	addEditorToGrid(v,w,"Mean1Mask",	omean1Mask,row,col + 2);
	addEditorToGrid(v,w,"Mean2Mask",	omean2Mask,row,col + 4); row++;
	addEditorToGrid(v,w,"Gate Width",	ogateWidth,row,col);
	addEditorToGrid(v,w,"Gate Phase",	ogatePhase,row,col + 2); row++;
	addEditorToGrid(v,w,"Blr Width",	oblrWidth,row,col); 
	addEditorToGrid(v,w,"Blr Phase",	oblrPhase,row,col + 2); row++;

	QHBox* 	nextStatesLabels = new QHBox(w);
	new QLabel("", nextStatesLabels);
	new QLabel("Delay", nextStatesLabels);
	new QLabel("HChange", nextStatesLabels);
	new QLabel("Injection", nextStatesLabels);
	new QLabel("CalStart", nextStatesLabels);
	new QLabel("CalStop", nextStatesLabels);
	new QLabel("CycleStop", nextStatesLabels);
	v->addMultiCellWidget(nextStatesLabels,row,row,0,5);
	row++;

	QHBox* 	nextStates = new QHBox(w);
	new QLabel("NextStates", nextStates);
	for(n = 0; n < 6; n++){
		onextStates[n] = new QSpinBox(nextStates, "");
		onextStates[n]->setMinValue(0);
		onextStates[n]->setMaxValue(15);
		connect(onextStates[n], SIGNAL(valueChanged(int)), this, SLOT(setCyclePhaseParams()));
	}
	v->addMultiCellWidget(nextStates,row,row,0,5);

	// Control Buttons

	QHBox * 	controls	= new QHBox(this,"controls");
	oupload 	= new QPushButton("Upload",controls);
	osaveFile 	= new QPushButton("Save to file",controls);
	odelete 	= new QPushButton("Delete from server",controls);
	oupdate 	= new QPushButton("Update State", controls);
	oviewDetails 	= new QPushButton("View State Details", controls);

	controls->setSpacing(20);
	oupload->setMaximumWidth(200);
	osaveFile->setMaximumWidth(200);
	odelete->setMaximumWidth(200);
	oviewDetails->setMaximumWidth(200);
	oupdate->setMaximumWidth(200);

	row = 0;
	grid->addMultiCellWidget(loadParams,row,row,0,2);						row++;
	grid->addWidget(baseParams,row,0);		grid->addWidget(positions,row,1);		row++;
	grid->addMultiCellWidget(ostateSetups,row,row,0,2);						row++;
	grid->addWidget(controls,row,0);								row++;

	ophaseNames->insertItem("All");
	ophaseNames->insertItem("Calibration");
	ophaseNames->insertItem("Event0");
	ophaseNames->insertItem("Event1");
	ophaseNames->insertItem("Event2");
	ophaseNames->insertItem("Event3");
	ophaseNames->insertItem("Event4");
	ophaseNames->insertItem("Event5");
	ophaseNames->insertItem("Event6");
	ophaseNames->insertItem("Event7");
	ophaseNames->insertItem("Event8");
	ophaseNames->insertItem("Event9");

	connect(oloadFromFile,SIGNAL(clicked()),this,SLOT(loadFromFile()));
	connect(oloadFromTms,SIGNAL(clicked()),this,SLOT(loadFromTms()));
	connect(oselectFile,SIGNAL(clicked()),this,SLOT(selectFile()));
	connect(oaddOffsets,SIGNAL(clicked()),this,SLOT(addOffsets()));
	connect(oloadDefaults,SIGNAL(clicked()),this,SLOT(loadDefaults()));
	connect(osaveFile,SIGNAL(clicked()),this,SLOT(saveFile()));
	connect(odelete,SIGNAL(clicked()),this,SLOT(deleteTms()));
	connect(oupdate,SIGNAL(clicked()),this,SLOT(updateDetails()));
	connect(oviewDetails,SIGNAL(clicked()),this,SLOT(viewDetails()));
	connect(oupload,SIGNAL(clicked()),this,SLOT(saveTms()));


	connect(ostateNum,SIGNAL(valueChanged(int)),this,SLOT(cycleStateChanged()));
	connect(ophaseNames,SIGNAL(activated(int)),this,SLOT(setCyclePhaseParams()));

	connect(obunchMask,SIGNAL(textChanged(const QString &)),this,SLOT(setCyclePhaseParams()));
	connect(omean1Mask,SIGNAL(textChanged(const QString &)),this,SLOT(setCyclePhaseParams()));
	connect(omean2Mask,SIGNAL(textChanged(const QString &)),this,SLOT(setCyclePhaseParams()));
	connect(olo1Harmonic,SIGNAL(textChanged(const QString &)),this,SLOT(setCyclePhaseParams()));
	connect(olo1Phase,SIGNAL(textChanged(const QString &)),this,SLOT(setCyclePhaseParams()));
	connect(olo2Harmonic,SIGNAL(textChanged(const QString &)),this,SLOT(setCyclePhaseParams()));
	connect(olo2Phase,SIGNAL(textChanged(const QString &)),this,SLOT(setCyclePhaseParams()));
	connect(ogateWidth,SIGNAL(textChanged(const QString &)),this,SLOT(setCyclePhaseParams()));
	connect(ogatePhase,SIGNAL(textChanged(const QString &)),this,SLOT(setCyclePhaseParams()));
	connect(oblrWidth,SIGNAL(textChanged(const QString &)),this,SLOT(setCyclePhaseParams()));
	connect(oblrPhase,SIGNAL(textChanged(const QString &)),this,SLOT(setCyclePhaseParams()));

	connect(of1Ref,SIGNAL(toggled(bool)),this,SLOT(setCyclePhaseParams()));
	connect(of1Lo,SIGNAL(toggled(bool)),this,SLOT(setCyclePhaseParams()));
	connect(of2Ref,SIGNAL(toggled(bool)),this,SLOT(setCyclePhaseParams()));
	connect(of2Lo,SIGNAL(toggled(bool)),this,SLOT(setCyclePhaseParams()));
	connect(obit6,SIGNAL(toggled(bool)),this,SLOT(setCyclePhaseParams()));
	connect(obit7,SIGNAL(toggled(bool)),this,SLOT(setCyclePhaseParams()));
	connect(opllF2,SIGNAL(toggled(bool)),this,SLOT(setCyclePhaseParams()));
	connect(oacquireData,SIGNAL(toggled(bool)),this,SLOT(setCyclePhaseParams()));

	connect(oenableModifications,SIGNAL(toggled(bool)),this,SLOT(enableStateEdit()));
	connect(oaddNextState,SIGNAL(clicked()),this,SLOT(addNextState()));
	connect(odelLastState,SIGNAL(clicked()),this,SLOT(delLastState()));
	connect(&ocontrol,SIGNAL(newConnection()),this,SLOT(update()));
}
	
PhaseTableWin::~PhaseTableWin() {}


void	PhaseTableWin::show() {
	QWidget::show();
	update();
}


void 	PhaseTableWin::update() {
	if (! isVisible())
		return;
	updateCycleTypes();			// Cycle Types list is retrieved from server
	updateCycleInfo();
	updateCycleParamState();
}

void	PhaseTableWin::updateCycleParamState() {
	ocycleStates.clear();
	oparams.getStates(ocycleStates);

	ostateNum->setValue(0);
	refreshParamState(ocycleStates[0]);
}


/* updateCycleType() - Get the list on known cycle types from server and populate selection list.
*
*/

BError PhaseTableWin::updateCycleTypes() {
	BError			err;
	BIter			i;
	BList<CycleParamItem> 	l;
	
	if (err = ocontrol.getControlList(l)) {
		return err;
	}
	
	ocycleTypes->clear();
	for (l.start(i);! l.isEnd(i);l.next(i)) {
		ocycleTypes->insertItem((l[i].cycleType + " " +  l[i].ring + " " + l[i].channel).retStr());
	}
	return err;
}


/* updateCycleInfo() - 	Given cycle params (oparams) update the Gui to
*			should the cycle information.
*/

void PhaseTableWin::updateCycleInfo() {

	ocycleType->setText(oparams.cycleType.retStr());
	oname->setText(oparams.name.retStr());
	oring->setValue(oparams.ring);
	ochannel->setValue(oparams.channel);
	oinfo->setText(oparams.info.retStr());
	oinfo->setCursorPosition(0);
	
	opllCycleStartFrequency->setText(uIntToStr(oparams.pllCycleStartFrequency));
	opllInitialFrequency->setText(uIntToStr(oparams.pllInitialFrequency));
	opllInitialFrequencyDelay->setText(uIntToStr(oparams.pllInitialFrequencyDelay));
	opllFrefGain->setText(uIntToStr(oparams.pllFrefGain));
	opllGain->setText(uIntToStr(oparams.pllGain));
	opllDdsMinimum->setText(uIntToStr(oparams.pllDdsMinimum));
	opllDdsMaximum->setText(uIntToStr(oparams.pllDdsMaximum));
	ostateDelay->setText(uIntToStr(oparams.stateDelay));

	ophaseDelays->setNumRows(oparams.frefPhaseDelay.size());

	 for(unsigned int i = 0; i < oparams.frefPhaseDelay.size(); i++ ) {
		BString	s;
		s.printf("%d",oparams.frefPhaseDelay[i]);
		ophaseDelays->setText(i,0,s.retStr());
	}
}


void	PhaseTableWin::setParams() {
	bool		ok;
	BIter		i;
	
	oparams.cycleType 			= ocycleType->text().ascii();
	oparams.name 				= oname->text().ascii();
	oparams.ring 				= oring->value();
	oparams.channel 			= ochannel->value();
	oparams.info 				= oinfo->text().ascii();
	oparams.pllCycleStartFrequency 		= opllCycleStartFrequency->text().toUInt(&ok);
	oparams.pllInitialFrequency 		= opllInitialFrequency->text().toUInt(&ok);
	oparams.pllInitialFrequencyDelay 	= opllInitialFrequencyDelay->text().toUInt(&ok);
	oparams.pllFrefGain 			= opllFrefGain->text().toUInt(&ok);
	oparams.pllGain 			= opllGain->text().toUInt(&ok);
	oparams.pllDdsMinimum			= opllDdsMinimum->text().toUInt(&ok);
	oparams.pllDdsMaximum			= opllDdsMaximum->text().toUInt(&ok);
	oparams.stateDelay			= ostateDelay->text().toUInt(&ok);

	for(unsigned int i = 0; i < oparams.frefPhaseDelay.size(); i++ ) {
		oparams.frefPhaseDelay[i] = ophaseDelays->text(i,0).toInt(&ok);
	}
	setCyclePhaseParams();
	
	if (oenableModifications->isChecked()){
		// Validate
		for(ocycleStates.start(i); !ocycleStates.isEnd(i); ocycleStates.next(i)){
			if((ocycleStates[i].lo1Harmonic < 1) || (ocycleStates[i].lo1Harmonic > 31)){
				warningDialog("Parameter Error", BError(1, "Lo1Harmonic out of range"));
				return;
			}
			if((ocycleStates[i].lo2Harmonic < 1) || (ocycleStates[i].lo2Harmonic > 31)){
				warningDialog("Parameter Error", BError(1, "Lo2Harmonic out of range"));
				return;
			}
		}

		oparams.setStates(ocycleStates);
	}
}

void	PhaseTableWin::setCyclePhaseParams() {
	bool	ok;
	int 	n;
	int	i;

	n = ostateNum->value();
	if(ocycleStates.number() > n){
		ocycleStates[n].num		= n;
		ocycleStates[n].period		= ophaseNames->currentItem();

		ocycleStates[n].lo1Harmonic 	= olo1Harmonic->text().toUInt(&ok);
		ocycleStates[n].lo1Phase 	= olo1Phase->text().toDouble(&ok);
		ocycleStates[n].lo2Harmonic 	= olo2Harmonic->text().toUInt(&ok);
		ocycleStates[n].lo2Phase 	= olo2Phase->text().toDouble(&ok);

		ocycleStates[n].state.delay = onextStates[0]->value();
		ocycleStates[n].state.hchange = onextStates[1]->value();
		ocycleStates[n].state.injection = onextStates[2]->value();
		ocycleStates[n].state.calStart = onextStates[3]->value();
		ocycleStates[n].state.calStop = onextStates[4]->value();
		ocycleStates[n].state.cycleStop = onextStates[5]->value();
		
		ocycleStates[n].state.pllReference1 	= of1Ref->isChecked();
		ocycleStates[n].state.pllLO1FromAddress = of1Lo->isChecked();
		ocycleStates[n].state.pllReference2 	= of2Ref->isChecked();
		ocycleStates[n].state.pllLO2FromAddress = of2Lo->isChecked();
		ocycleStates[n].state.pllFeedbackSelect = opllF2->isChecked();
		ocycleStates[n].state.aquireData 	= oacquireData->isChecked();
		ocycleStates[n].state.bit6 		= obit6->isChecked();
		ocycleStates[n].state.bit7 		= obit7->isChecked();

		ocycleStates[n].bunchMask 	= obunchMask->text().toUInt(&ok,16);
		ocycleStates[n].mean1Mask 	= omean1Mask->text().toUInt(&ok,16);
		ocycleStates[n].mean2Mask 	= omean2Mask->text().toUInt(&ok,16);
		ocycleStates[n].gateWidth 	= ogateWidth->text().toDouble(&ok);
		ocycleStates[n].gatePhase 	= ogatePhase->text().toDouble(&ok);
		ocycleStates[n].blrWidth 	= oblrWidth->text().toDouble(&ok);
		ocycleStates[n].blrPhase 	= oblrPhase->text().toDouble(&ok);
	}
}


void	PhaseTableWin::cycleStateChanged(int num){
	ostateNum->setValue(num);
}

void	PhaseTableWin::cycleStateChanged() {
	int n = ostateNum->value();
	
	if(n >= ocycleStates.number())
		n = ocycleStates.number() - 1;
		
	refreshParamState(ocycleStates[n]);
	if(odetailViewGui)
		odetailViewGui->ostateGui->setState(n);
}

void	PhaseTableWin::refreshParamState(CycleParamState s) {
	int	n;
	bool	allowEdit = oenableModifications->isChecked();

	ostateNum->setValue(s.num);
	ophaseNames->setCurrentItem(s.period);

	olo1Harmonic->setText(uIntToStr(s.lo1Harmonic));
	olo1Phase->setText(doubleToStr(s.lo1Phase));;
	olo2Harmonic->setText(uIntToStr(s.lo2Harmonic));
	olo2Phase->setText(doubleToStr(s.lo2Phase));;

	of1Ref->setChecked(s.state.pllReference1);
	of1Lo->setChecked(s.state.pllLO1FromAddress);
	of2Ref->setChecked(s.state.pllReference2);
	of2Lo->setChecked(s.state.pllLO2FromAddress);
	opllF2->setChecked(s.state.pllFeedbackSelect);
	oacquireData->setChecked(s.state.aquireData);
	obit6->setChecked(s.state.bit6);
	obit7->setChecked(s.state.bit7);

	obunchMask->setText(uIntToHexStr(s.bunchMask));
	omean1Mask->setText(uIntToHexStr(s.mean1Mask));
	omean2Mask->setText(uIntToHexStr(s.mean2Mask));
	ogateWidth->setText(doubleToStr(s.gateWidth));
	ogatePhase->setText(doubleToStr(s.gatePhase));
	oblrWidth->setText(doubleToStr(s.blrWidth));
	oblrPhase->setText(doubleToStr(s.blrPhase));

	for(n = 0; n < 6; n++){
		onextStates[n]->setValue((s.state.value >> (28 - (4 * n))) & 0xF);
		onextStates[n]->setEnabled(allowEdit);
	}
	
	oaddNextState->setEnabled(allowEdit);
	odelLastState->setEnabled(allowEdit);
	obunchMask->setEnabled(allowEdit);
	omean1Mask->setEnabled(allowEdit);
	omean2Mask->setEnabled(allowEdit);
	olo1Harmonic->setEnabled(allowEdit);
	olo1Phase->setEnabled(allowEdit);
	olo2Harmonic->setEnabled(allowEdit);
	olo2Phase->setEnabled(allowEdit);
	of1Ref->setEnabled(allowEdit);
	of1Lo->setEnabled(allowEdit);
	of2Ref->setEnabled(allowEdit);
	of2Lo->setEnabled(allowEdit);
	opllF2->setEnabled(allowEdit);
	oacquireData->setEnabled(allowEdit);
	obit6->setEnabled(allowEdit);
	obit7->setEnabled(allowEdit);
	ogateWidth->setEnabled(allowEdit);
	ogatePhase->setEnabled(allowEdit);
	oblrWidth->setEnabled(allowEdit);
	oblrPhase->setEnabled(allowEdit);
}



void PhaseTableWin::enableStateEdit() {
	BString msg;
	if (oenableModifications->isChecked()) {
		msg = "<p>Enabling the state setup will overwrite all state/phase table information</p>";
		msg += "<p>Are you sure you wish to continue ?</p>";
		if (! confirmDialog("BEWARE",msg)) {
			oenableModifications->disconnect();
			oenableModifications->setChecked(false);
			connect(oenableModifications,SIGNAL(toggled(bool)),this,SLOT(enableStateEdit()));
			return;
		}	
	}
	update();
}

void	PhaseTableWin::addNextState() {
	CycleParamState 	s;

	if (ocycleStates.number() >= MAX_CYCLE_STATES) {
		warningDialog("Adding Additional State",BError(1,"Maximum number of state exceeded"));
		return;
	}

	oparams.getDefaultState(s);
	s.num = ocycleStates.number();
	ocycleStates.append(s);
	ostateNum->setValue(s.num);
	refreshParamState(s);
}

void	PhaseTableWin::delLastState() {
	
	if (ocycleStates.number() < 3) {
		warningDialog("Deleteing State",BError(1,"A minimum of two states are required"));
		return;
	}	

	ocycleStates.deleteLast();
	refreshParamState(ocycleStates.rear());
}

void PhaseTableWin::loadDefaults() {
	CycleParamEdit::getdefaultPickupPositions(oparams.frefPhaseDelay);
	update();
}


void PhaseTableWin::saveFile() {
	BError			err;
	BFile			f;
	BString			fname;


	setParams();

	if(oparams.cycleType == ""){
		warningDialog("Error", BError(1, "Cycle Type not set"));
		return;
	}
	
	fname = ofilename->text().ascii();
        QString s = QFileDialog::getSaveFileName("/usr/tms/stateTables","Tms Cycle Parameters File (*.spt)",this,"save file dialog","Specify filename");
	fname = s.ascii();
	if (fname.len() == 0)
		return;

	if (QFile::exists(fname.retStr())){
		BString msg = "The specified file already exists are you ";
		msg += BString("positive you wish to over write the file");
		if (! confirmDialog("Confirm Action",msg)) {
			return;
		}	
	}
	if(err = oparams.writeToFile(fname)) {
		warningDialog("Cycle Parameters - Save",err);
		return;
	}
	ofilename->setText(fname.retStr());
	gstatusbar->message("Cycle Parameters Saved",2000);
}

void PhaseTableWin::loadFromFile() {
	BError		err;
	BFile		f;
	BString		fname;

	disconnect(oenableModifications,SIGNAL(toggled(bool)),this,SLOT(enableStateEdit()));
	oenableModifications->setChecked(false);
	connect(oenableModifications,SIGNAL(toggled(bool)),this,SLOT(enableStateEdit()));
	
	fname = ofilename->text().ascii();
	if (err = f.open(fname,"r")) {
		warningDialog("Cycle Parameters - Reading",err);
		return;
	}
	if(err = oparams.readFromFile(fname)) {
		warningDialog("Cycle Parameters - Read Parsing",err);
		return;
	}	
	update();
	gstatusbar->message("Cycle Parameters Read",2000);
}


void PhaseTableWin::saveTms() {
	BError	err;
	
	setParams();

	if(oparams.cycleType == ""){
		warningDialog("Error", BError(1, "Cycle Type not set"));
		return;
	}
	
	if (err = ocontrol.setControlInfo(oparams)) {
		warningDialog("Upload of Cycle Params",err);
		return;
	}
	update();
	gstatusbar->message("Cycle Parameters Uploaded",2000);
}

void PhaseTableWin::deleteTms(){
	BError	err;

	setParams();
	
	if(oparams.cycleType == ""){
		warningDialog("Error", BError(1, "Cycle Type not set"));
		return;
	}
	
	// Check with user
	if(confirmDialog("BEWARE", BString("Are you sure you wish to delete Cycle Type: ") + oparams.cycleType + " from the TMS system ?")){
		if (err = ocontrol.delControlInfo(oparams.cycleType, 0, 0)){
			warningDialog("Delete of Cycle Params",err);
			return;
		}
		oparams.clear();
		update();
		gstatusbar->message("Cycle Parameters Deleted", 2000);
	}
}

void PhaseTableWin::updateDetails(){
	setParams();
	if(odetailViewGui)
		odetailViewGui->init(oparams, 0);
}

void PhaseTableWin::viewDetails() {
	if(!odetailViewGui){
		odetailViewGui = new DetailViewGui();
		connect(odetailViewGui->ostateGui, SIGNAL(stateChanged(int)), this, SLOT(cycleStateChanged(int)));
	}

	odetailViewGui->show();
	setParams();
	odetailViewGui->init(oparams, 1);
}

void PhaseTableWin::loadFromTms() {
	BError err;
	BString	str = ocycleTypes->currentText().ascii();
	BString	type;
	BUInt	ring;
	BUInt	channel;
	

	type = str.pullWord();
	ring = str.pullWord().retInt();
	channel = str.pullWord().retInt();
	
	disconnect(oenableModifications,SIGNAL(toggled(bool)),this,SLOT(enableStateEdit()));
	oenableModifications->setChecked(false);
	connect(oenableModifications,SIGNAL(toggled(bool)),this,SLOT(enableStateEdit()));


	if (err = ocontrol.getControlInfo(type, ring, channel, oparams)) {
		BString msg;
		msg.printf("Attempting to access cycle type (%s) ",type.retStr());
		msg += err.getString();
		err.set(err.getErrorNo(),msg);			
		warningDialog("Load from Tms",msg);
		return;
	}
	update();
}

void PhaseTableWin::selectFile() {
       QString s = QFileDialog::getOpenFileName(
                    "/usr/tms/stateTables",
                    "Tms Cycle Parameters File (*.spt)",
                    this,
                    "open file dialog",
                    "Choose a file" );
	ofilename->setText(s);
}

void	PhaseTableWin::warningDialog(BString title, BError err){
	BString		m;
	QMessageBox	b;
	
	m = BString("<h5>") + title + "</h5><p>" + err.getString() + "</p>";
	b.setMinimumWidth(300);
	b.setCaption("tmsControlGui - Warning");
	b.setIcon(QMessageBox::Warning);
	b.setText(m.retStr());
	b.exec();
}

int	PhaseTableWin::confirmDialog(BString title,BString msg){
	BString		s;
	
	s = BString("<h5>") + title + "</h5><p>" + msg + "</p>";

	QMessageBox mb( "tmsControlGui - Question",
   	     s.retStr(),
        	QMessageBox::Information,
        	QMessageBox::Yes | QMessageBox::Default,
        	QMessageBox::Cancel | QMessageBox::Escape,
		QMessageBox::NoButton );
	switch( mb.exec() ) {
		case QMessageBox::Yes:
        		return 1;
	        	break;
  		case QMessageBox::No:
        		return 0;
		        break;
		    case QMessageBox::Cancel:
		        return 0;
		        break;
	}
	return 0;
}

void PhaseTableWin::addOffsets() {
	 int val = ooffset->value();

	 for(unsigned int i = 0; i < oparams.frefPhaseDelay.size(); i++ ) {
		int	a;
		a = oparams.frefPhaseDelay[i] + val;
		a &= 0x1ff;
		oparams.frefPhaseDelay[i] = a;
	}
	update();
}
void	PhaseTableWin::addEditorToGrid(QGridLayout* g,QWidget* w,BString label,QWidget* editor,int row,int col, int colEnd) {
		g->addWidget(new QLabel(label.retStr(),w,""),row,col);
		if(colEnd)
			g->addMultiCellWidget(editor, row, row, col + 1, colEnd);		
		else
			g->addWidget(editor,row,col + 1);		
}

void	PhaseTableWin::createGridGroupBox(QVGroupBox*& g,BString title,QWidget*& w,QGridLayout*& l) {
	g = new QVGroupBox(title.retStr(),this,title.retStr());
	w 	= new QWidget(g,"");
	l 	= new QGridLayout(w);
	
	l->setSpacing(6);
}


QString PhaseTableWin::uIntToStr(UInt32 val) {
	QString	s;
	s.sprintf("%u",val);
	return s;
}

QString PhaseTableWin::doubleToStr(double val) {
	QString	s;
	s.sprintf("%f",val);
	return s;
}

QString PhaseTableWin::uIntToHexStr(UInt32 val) {
	QString	s;
	s.sprintf("0x%x",val);
	return s;
}
