// $Id: moncalcontrol.cpp,v 1.37 2008/03/06 21:18:59 hvengel Exp $
//  Little cms Profiler
// Copyright (C) 2007 - 2008 Hal Engel
//
// THIS SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
// EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
// WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
//
// IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
// INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
// OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
// WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
// LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
// OF THIS SOFTWARE.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
// Version 1.11

#include "moncalcontrol.h"
#include "moncalreports.h"
#include "monitorcal.h"
#include "lprofmain.h"
#include <QDoubleSpinBox>
#include <QColormap>
#include "lcmsprf.h"
#include "main.h"

#include <q3textedit.h>
#include <qradiobutton.h>
#include <qpixmap.h>
#include <qlabel.h>
#include <qapplication.h>
#include <QMessageBox>
#include <qspinbox.h>
#include <qcombobox.h>
#include <qstring.h>
#include <qpushbutton.h>
#include <q3buttongroup.h>
#include <qtimer.h>
#include <qmutex.h>
#include <q3filedialog.h>
#include <qfileinfo.h>
#include <qthread.h>
//Added by qt3to4:
#include <QTranslator>

// ArgyllCMS instrument support stuff
extern "C"
{
#include "xspect.h"
#include "config.h"
#include "icoms.h"
#include "inst.h"
#include "icc.h"
#include "insttypes.h"
#include "ioerrorhandler.h"
#include "lcms.h"
}

#include <setjmp.h>
                 
#if !defined(__WIN32__) && (defined(_WIN32) || defined(WIN32))
#define __WIN32__
#endif


static controlData cd;
static PROFILERDATA sys;
instData listedInsts[instArraySize];
QTimer *timer;
static bool opKnown = false;
QMutex mutex;
bool instUpdate = TRUE;
inst *it;
operation reportOP;
bool measureing;
bool firstTime;

enum State
{
    needsCalibration,
    needsMeasurement,
    settingsChanged,
    ready
} currentState;

void controlData::get(controlData* out)
{
    out -> data = cd.data;
}

void controlData::put(controlData in)
{
    cd.data = in.data;
}

QString moncalcontrol_get_QTDIR()
{
    const char* qtdir= "QTDIR";
    return QString::fromLocal8Bit(getenv(qtdir));
}

void flashLEDsThread::run()
{
    if (setjmp(ioErrorJumpBuffer))
    {
        return;
    }
    it->set_opt_mode(it, inst_opt_set_led_state, 1);
    msleep(50);
    it->set_opt_mode(it, inst_opt_set_led_state, 2);
    msleep(50);
    it->set_opt_mode(it, inst_opt_set_led_state, 4);
    msleep(50);
    it->set_opt_mode(it, inst_opt_set_led_state, 8);
    msleep(50);
    it->set_opt_mode(it, inst_opt_set_led_state, 4);
    msleep(50);
    it->set_opt_mode(it, inst_opt_set_led_state, 2);
    msleep(50);
    it->set_opt_mode(it, inst_opt_set_led_state, 1);
    msleep(50);
    it->set_opt_mode(it, inst_opt_set_led_state, 0);
}

void MonitorCalControl::slotOK()
{
    monCal ok;
    ok.OK(TRUE);
}

void MonitorCalControl::slotCancel()
{
    monCal notok;
    notok.OK(FALSE);
}

void MonitorCalControl::takeAmbientReading()
{
    ipatch val;
    int rv;
    double instXYZ[3], XYZ[3];
    xsp2cie *sp2cie = NULL;
    
    if (initInstrumentAmbient())
    {
        QMessageBox mb( QTranslator::tr("Prepare to Read Ambient Lighting"),
                        QTranslator::tr("Prepare the measurement device for an ambient light reading.  Please put the ambient light head on device if it has one.  When ready push the OK button."),
                        QMessageBox::Critical,
                        QMessageBox::Ok | QMessageBox::Default,
                        QMessageBox::Cancel,  
                        Qt::NoButton);
    
        if (mb.exec() == QMessageBox::Ok)
        {
            if (setjmp(ioErrorJumpBuffer))
            {
            // There was a problem in any of the argyll calls below
            // It was trapped and we need to bypass the call
            // after issuing an error message fo the user.
                QString message;
                message = QString::fromLocal8Bit(getErrorMessage()); 
                QMessageBox mb( QTranslator::tr("Problem Initializing the device port."),
                                message + QTranslator::tr("This error indicates some type of problem with accessing the device.  A likely cause is not having access rights to the device.  Check your permissions to make sure you have USB access and access rights to this device."),
                                        QMessageBox::Critical,
                                        QMessageBox::Ok | QMessageBox::Default,
                                        Qt::NoButton,  Qt::NoButton);

                mb.exec();
                // clean up as needed.
                if (it != NULL) 
                    it->del(it);
                return;
            }
            flashLEDsThread flashLEDs;
            rv = it->read_sample(it, "SPOT", &val);
            if ((it->capabilities2(it) & inst2_has_leds) != 0)
                flashLEDs.start();
            if (!rv == inst_ok)
            {
                QMessageBox::critical(this, QTranslator::tr("Meter Error"), QTranslator::tr("There was a problem during the ambient light measurement."));
            }
            else // reading was OK
            {
                instXYZ[0] = -9999999.0;    // zero instXYZ - if there no valid
                instXYZ[1] = -9999999.0;    // measurement then this is what will
                instXYZ[2] = -9999999.0;    // be returned.  So XYZ.Z < -9999.0 is an error
                if (val.sp.spec_n <= 0)
                {
                    // qDebug("val.sp.spec_n <= 0");
                    if (val.XYZ_v == 0 && val.aXYZ_v == 0)
                    {
                        qDebug(tr("Instrument didn't return XYZ value").toLocal8Bit());
                    }

                    if (val.XYZ_v != 0)
                        for (int j = 0; j < 3; j++)
                            instXYZ[j] = val.XYZ[j];
                    else
                        for (int j = 0; j < 3; j++)
                            instXYZ[j] = val.aXYZ[j];
                }
                else
                {
                    // FIXME since we have spectral data we should 
                    // give users a graph of the spcrtral distribution
                    // This is much more useful than simply a color
                    // temperature reading.                    
                    sp2cie->convert(sp2cie, instXYZ, &val.sp);
                }
                double temp = 0.0;
                temp = icx_XYZ2ill_ct(XYZ, icxIT_Dtemp, 
                        icxOT_CIE_1931_2, NULL, instXYZ, NULL, 1); 
                QString tempStr = QTranslator::tr("The ambient color temperature is %1 degrees Kelvin\nWith a luminosity of %2 Cd/m^2 or approx. %2 lux").arg(temp, 5, 'f', 0).arg(instXYZ[1], 4, 'f', 1).arg(instXYZ[1]*16.6666666666667, 6, 'f', 1);
                QMessageBox::critical(this, QTranslator::tr("Ambient Lighting Reading"), tempStr);

            }
            if ((it->capabilities2(it) & inst2_has_leds) != 0)
                flashLEDs.wait();
        }
    }
    else
    {
        QMessageBox::critical(this, QTranslator::tr("Meter Error"), QTranslator::tr("Meter does not support ambient light readings."));
    }
    // clean up as needed.
    if (it != NULL) 
        it->del(it);
}

bool MonitorCalControl::initInstrumentAmbient()
{
    QString temp = QString::fromLocal8Bit("");
    int verb = 0;
    int mydebug=0;
    const bool OK = true;
    const bool notOK = false;
    inst_code ev;
    inst_code rv;
    baud_rate br = baud_19200;
    inst_opt_filter fe = inst_opt_filter_unknown;
    inst_capability  cap = inst_unknown;
    inst2_capability cap2 = inst2_unknown;
    char instName[64];
    
    strcpy(instName, cd.data.selectedInst.name.local8Bit());
    cd.data.selectedInst.Inst = inst_enum(instName);
    
    if (setjmp(ioErrorJumpBuffer))
    {
        // There was a problem in any calls to argyll below
        // It was trapped and we need to bypass the call
        // after issuing an error message fo the user.
        QString message;
        message = QString::fromLocal8Bit(getErrorMessage()); 
        QMessageBox mb( QTranslator::tr("Problem Initializing the device port."),
                        message + QTranslator::tr("This error indicates some type of problem with accessing the device.  A likely cause is not having access rights to the device.   Check your permissions to make sure you have USB access and access rights to this device."),
                                QMessageBox::Critical,
                                QMessageBox::Ok | QMessageBox::Default,
                                Qt::NoButton,  Qt::NoButton);

        mb.exec();
        return notOK;
    }

    if ((it = new_inst(cd.data.selectedInst.position + 1, 
            cd.data.selectedInst.Inst, mydebug, verb)) == NULL)
    {
        QMessageBox mb( QTranslator::tr("Failed to Initialize the Device"),
                        QTranslator::tr("Failed to initialize device.  Call to new_inst failed."),
                        QMessageBox::Critical,
                        QMessageBox::Ok | QMessageBox::Default,
                        Qt::NoButton,  Qt::NoButton);

        mb.exec();
        return notOK;
    }
    
    /* Establish communications */
    if ((rv = it->init_coms(it, cd.data.selectedInst.position + 1, br, fc_nc, 15.0)) != inst_ok)
    {        
        QMessageBox::critical(this, QTranslator::tr("Meter Error"), tr("Failed to initialize communications with instrument or wrong instrument or bad configuration!  (") + 
                QString::fromLocal8Bit(it->inst_interp_error(it, rv)) + QString::fromLocal8Bit(" ") +
                        QString::fromLocal8Bit(it->inst_interp_error(it, rv)) + QString::fromLocal8Bit(")"));
        return notOK;
    }
    else
    {
        /* set filter configuration before initializing/calibrating */
        if (fe != inst_opt_filter_unknown)
            if ((rv = it->set_opt_mode(it, inst_opt_set_filter, fe)) != inst_ok)
        {
            QMessageBox::critical(this, QTranslator::tr("Meter Error"), tr("Setting filter configuration not supported by instrument"));
            return notOK;
        }
        /* Initialise the instrument */
        if ((rv = it->init_inst(it)) != inst_ok)
        {
            
            QMessageBox mb( QTranslator::tr("Problem Initializing Instrument."),
                            QString::fromLocal8Bit(it->inst_interp_error(it, rv))
                                    + QString::fromLocal8Bit("(")  + QString::fromLocal8Bit(it->interp_error(it, rv)) + QString::fromLocal8Bit(")")
                                    + tr(" Instrument initialization failed!"),
                                            QMessageBox::Critical,
                                            QMessageBox::Ok | QMessageBox::Default,
                                            Qt::NoButton,  Qt::NoButton);

            mb.exec();
            return notOK;
        }
        else  /* it initialized OK so configure the instrument mode */
        {
            inst_mode mode = inst_mode_unknown;

            cap = it->capabilities(it);
            cap2 = it->capabilities2(it);

            if ((cap & inst_emis_ambient) == 0)
            {
                QMessageBox::critical(this, QTranslator::tr("Meter Error"), 
                                      tr("Need ambient light capability and instrument doesn't support it"));
                return notOK;
            }
            if ((rv = it->set_mode(it, inst_mode_emis_ambient)) != inst_ok)
            {
                QMessageBox::critical(this,QTranslator::tr("Meter Error"), 
                                      tr("Failed to set ambient measurement mode. ") + 
                                              QString::fromLocal8Bit(it->inst_interp_error(it, rv)) + QString::fromLocal8Bit(" ") + 
                                              QString::fromLocal8Bit(it->interp_error(it, rv)));
                return notOK;
            }
            rv = it->set_opt_mode(it, inst_opt_trig_prog);
            if (rv != inst_ok)
            {
                QMessageBox::critical(this, QTranslator::tr("Meter Error"), 
                                      tr("Setting trigger mode failed with error : ")
                                              + QString::fromLocal8Bit(it->inst_interp_error(it, rv)) + QString::fromLocal8Bit(" ")
                                              + QString::fromLocal8Bit(it->interp_error(it, rv)));
                return notOK;
            }            
        }
    }
    // qDebug ("done setting up instrument");
    return OK;
}

void MonitorCalControl::controlsToValues()
{
    // qDebug("controlsToValues()");
    if (LCDradioButton -> isOn())
        cd.data.disp = LCD;
    else
        cd.data.disp = CRT;

    if (k6500 -> isOn())
    {
        cd.data.wp = 6500.0;
    }
    else if (k5000 -> isOn())
    {
        cd.data.wp = 5000.0;
    }
    else if (native -> isOn())
    {
        cd.data.wp = 0.0;
    }
    else if ( tempUser -> isOn())
        cd.data.wp = spinBoxTempUser -> value();
    else
        qDebug("whitePoint is not being correctly set");

    if (nativeBrightness -> isOn())
        cd.data.displayBr=0.0;
    else
        cd.data.displayBr = (double) spinBoxBrightness -> value();

    if (sampleSmall -> isOn())
        cd.data.size = smallest;
    else if (sampleMedium -> isOn())
        cd.data.size = medium;
    else if (sampleLarge -> isOn())
        cd.data.size = large;
    else if (sampleHuge -> isOn())
        cd.data.size = huge;

    if (radioButtonGammaUser -> isOn())
        cd.data.gamma = userGamma -> value();
    else if (radioButtonGamma1_8 -> isOn())
        cd.data.gamma = 1.8;
    else cd.data.gamma = 2.2;

    if (radioGammasRGB -> isOn())
        cd.data.gammaType = gtsRGB;
    else if (radioButtonLstar -> isOn())
        cd.data.gammaType = gtLstar;
    else
        cd.data.gammaType = gtGeneric;
    
    mutex.lock();
    cd.data.selectedInst = listedInsts[comboBoxInstruments -> currentItem()];
    mutex.unlock();    
    
    opKnown = false;
}

void MonitorCalControl::slotCalibrate()
{
    cd.data.op = opCalibrate;
    opKnown = true;
    slotGo();
    if (cd.data.OK)
       this -> setNextEnabled(this -> currentPage(), true);
}

void MonitorCalControl::slotMeasure()
{
    cd.data.op = opMeasure;;
    opKnown = true;
    slotGo();
    if (cd.data.OK)
        this -> setFinishEnabled(this -> currentPage(), true);
}

void MonitorCalControl::slotReport()
{
    reportOP = noOp;
    MonitorCalReports mCR(this);
    mCR.exec();
    if (reportOP != noOp)
    {
        if (listedInsts[comboBoxInstruments -> currentItem()].Inst != instUnknown)
        {
            if (reportOP == opAmbient)
            {
                instUpdate = FALSE;
                controlsToValues();
                takeAmbientReading();
                instUpdate = TRUE;
            }
            else
            {
                cd.data.op = reportOP;
                opKnown = true;
                slotGo();
            }
        }
        else
        {
            QMessageBox::critical(this, QTranslator::tr("Error with device."), 
                                    QTranslator::tr("The measurement device is not valid.  It either it does not exist or does not support this operation.  Please correct this condition and retry the operation")); 
        }
    }
}

void MonitorCalControl::slotControls()
{
    if (setBlackPoint -> isOn())
       cd.data.op = opSetBlackPoint;
    else if (setWhitePoint -> isOn())
       cd.data.op = opSetWhitePoint;
    else if (setBlackLevel -> isOn())
       cd.data.op = opSetBlackLevel;
    else if (setWhiteLevel -> isOn())
        cd.data.op = opSetWhiteLevel;
    else qDebug("Operation not yet setup - moncalcontrol");
    opKnown = true;
    slotGo();
}

void MonitorCalControl::slotUserTemp()
{
        spinBoxTempUser -> setEnabled(tempUser -> isOn());
}

void MonitorCalControl::slotUserGamma()
{
    if (radioButtonGenericGamma -> isOn())
    {
        buttonGroupGamma -> setEnabled(TRUE);
        userGamma -> setEnabled(radioButtonGammaUser -> isOn());
    }
    else
    {
        buttonGroupGamma -> setEnabled(FALSE);
        userGamma -> setEnabled(FALSE);
    }
}

void MonitorCalControl::slotUserLuminosity()
{
   // qDebug("slotUserLuninosity()");
   spinBoxBrightness -> setEnabled(specifiedBrightness -> isOn());
   setWhiteLevel -> setEnabled(specifiedBrightness -> isOn());
}

void MonitorCalControl::slotDisplayType()
{
    setBlackLevel  -> setEnabled(CRTradioButton -> isOn());
}

void MonitorCalControl::slotGo()
{
    qDebug("inst type = %i", listedInsts[comboBoxInstruments -> currentItem()].Inst);
    if (// listedInsts[comboBoxInstruments -> currentItem()].Inst != instUnknown && 
        listedInsts[comboBoxInstruments -> currentItem()].deviceFlag == OK)
    {
        instUpdate = FALSE;
        controlsToValues();
        MonitorCal monCal(this);
        monCal.show();
        monCal.setWindowState(Qt::WindowFullScreen);
        monCal.exec();
        instUpdate = TRUE;        
    }
    else
    {
        QMessageBox::critical(this, QTranslator::tr("Error with device."), 
                              QTranslator::tr("The measurement device is not valid.  It either it does not exist or does not support this operation or is missing it's firmware.  Please correct this condition and retry the operation")); 
    }
}

void MonitorCalControl::checkSpyd2Firmware()
{
    QFileInfo fileInfo;
    
    // If we get here there is a Sypder2 connected to the system
    // but we did not find the firmware needed to use the device.
    //
    // Issue an error meassage that the device is not in working order
    //
    // If the user has write access to the LProf unstall directory
    // ask the user if they want to install the firmware and
    // if yes present them with a workfow to do this.
    //
    // otherwise let the user know hwat needs to be done.
    //
    fileInfo.setFile(getAppExecDir());
    if (fileInfo.isWritable())
    {
        QMessageBox mb( tr("Spyder2 Firmware Missing"), 
                        tr("Please install the firmware for your Spyder 2.  See the Spyder 2 section of the help files for details.  Your Spyder 2 will not function until the firmware is installed.  Do you want to install the Spyder 2 firmware?  If you answer yes you will be presented with a file dialog.  Use this to select the Spyder 2 setup.exe file from the install CD  or the installed library files if you are on a Windows or MacIntosh system.  These files will be named CVSpyder.dll on Windows or Spyder.lib on a MacIntosh."),
                        QMessageBox::Warning,
                        QMessageBox::Yes | QMessageBox::Default,
                        QMessageBox::Cancel,  
                        Qt::NoButton);
    
        if  (mb.exec() == QMessageBox::Yes)
        {
            QString startDir;
            QString filter;
            QString command = getAppExecDir() + QString::fromLocal8Bit("/spyd2enlprof");
#if defined (Q_WS_MAC)
            startDir = QString::fromLocal8Bit("/Applications/Spyder2express 2.2/Spyder2express.app/Contents/MacOSClassic/");
#elif defined (Q_WS_WIN)
            startDir = QString::fromLocal8Bit("C:/Program Files/ColorVision/Spyder2express/");
#else
            startDir = QString::fromLocal8Bit("/");
#endif
            filter = QString::fromLocal8Bit("Spyder 2 Files (Spyder.lib; CVSpyder.dll; setup.exe)");
            Q3FileDialog fd(startDir, filter, this, tr("Locate Firmware").toLocal8Bit(), TRUE);
            fd.show();
            fd.exec();
            if (!fd.selectedFile().isEmpty())
                command = command + QString::fromLocal8Bit(" ") + fd.selectedFile(); 
            system(command.toLocal8Bit());
            qDebug(command.toLocal8Bit());
            if (!QFile::exists(getAppExecDir() + QString::fromLocal8Bit("/") + QString::fromLocal8Bit("spyd2PLD.bin")))
                QMessageBox::critical(this, QTranslator::tr("Error"), tr("Firmware file creation failed."));
        }
    }
    else
        QMessageBox::warning(this,  tr("Spyder2 Firmware Missing"), 
                             tr("Please install the firmware for your Spyder 2.  See the Spyder 2 section of the help files for details.  Your Spyder 2 will not function until the firmware is installed.  The current user does not have authority to write the firmware file to the correct location.  To install the firmware you will need write access to ") + getAppExecDir()); 
}

void MonitorCalControl::fillComboBoxInstrument()
{
    bool changed = false;
    int currPos;
    bool spyd2FirmwareOK, instListChanged; 

    // qDebug("MonitorCalControl::fillComboBoxInstrument() start");
    fillListedInsts(listedInsts, spyd2FirmwareOK, instListChanged, emission);
    
    // get current possition in combobox
    if (firstTime)
        currPos = 0;
    else if (comboBoxInstruments -> count() > 0)
        currPos = comboBoxInstruments -> currentItem();
    else 
        currPos = 0;
    
    if (listedInsts[0].listSize == 0)
    {
        comboBoxInstruments -> clear ();
    }
    else
    {
        if (!firstTime && comboBoxInstruments -> count() == listedInsts[0].listSize)
        {
            int i = 0;
            while (i < listedInsts[0].listSize && !changed)
            {
                comboBoxInstruments -> setCurrentItem(i);
                if (listedInsts[i].name != comboBoxInstruments -> currentText())
                    changed = true;
                i++;
            }
            // restore position in combobox
            comboBoxInstruments -> setCurrentItem(currPos);
        }
        else  // size is different so it must have changed
            changed = true;
        if (changed)  // update the combobox only if the list has changed
        {
            // qDebug("Changed update combo box");
            if (!firstTime)
                comboBoxInstruments -> clear ();
            for (int i=0; i < listedInsts[0].listSize; i++)
            {
                comboBoxInstruments -> insertItem(listedInsts[i].name);
            }
            if (!spyd2FirmwareOK)
               checkSpyd2Firmware();
        }
    }
    firstTime = FALSE;
    // qDebug("MonitorCalControl::fillComboBoxInstrument() end");
}

void MonitorCalControl::slotCheckDevices()
{
    // qDebug("MonitorCalControl::slotCheckDevices() start");
    if (instUpdate)
    {
        instUpdate = FALSE;
        mutex.lock();
        fillComboBoxInstrument();
        mutex.unlock();
        instUpdate = TRUE;
        int i = timer->start( 1000, TRUE );
    }
    else
        timer -> stop();
    // qDebug("MonitorCalControl::slotCheckDevices() end");
}

MonitorCalControl::MonitorCalControl(QWidget *parent )
    : Q3Wizard(parent, "", 0, Qt::WStyle_SysMenu | Qt::WStyle_MinMax | Qt::WStyle_Title)
{
    setupUi(this);
    
    QObject::connect(GoButton_Calibrate, SIGNAL(clicked()), this, SLOT(slotCalibrate()));
    QObject::connect(GoButton_Measure, SIGNAL(clicked()), this, SLOT(slotMeasure()));
    QObject::connect(GoButton_DisplayControls, SIGNAL(clicked()), this, SLOT(slotControls()));
    QObject::connect(nativeBrightness, SIGNAL(toggled(bool)), this, SLOT(slotUserLuminosity()));
    QObject::connect(specifiedBrightness, SIGNAL(toggled(bool)), this, SLOT(slotUserLuminosity()));
    QObject::connect(radioButtonGammaUser, SIGNAL(clicked()), this, SLOT(slotUserGamma()));
    QObject::connect(radioButtonGamma2_2, SIGNAL(clicked()), this, SLOT(slotUserGamma()));
    QObject::connect(radioButtonGamma1_8, SIGNAL(clicked()), this, SLOT(slotUserGamma()));
    QObject::connect(radioButtonGenericGamma, SIGNAL(clicked()), this, SLOT(slotUserGamma()));
    QObject::connect(radioGammasRGB, SIGNAL(clicked()), this, SLOT(slotUserGamma()));
    QObject::connect(radioButtonLstar, SIGNAL(clicked()), this, SLOT(slotUserGamma()));
    QObject::connect(LCDradioButton, SIGNAL(toggled(bool)), this, SLOT(slotDisplayType()));
    QObject::connect(CRTradioButton, SIGNAL(toggled(bool)), this, SLOT(exec()));
    QObject::connect(pushButtonReports1, SIGNAL(clicked()), this, SLOT(slotReport()));
    QObject::connect(pushButtonReports2, SIGNAL(clicked()), this, SLOT(slotReport()));
    QObject::connect(pushButtonReports3, SIGNAL(clicked()), this, SLOT(slotReport()));
    QObject::connect(pushButtonReports4, SIGNAL(clicked()), this, SLOT(slotReport()));
    QObject::connect(tempUser, SIGNAL(toggled(bool)), this, SLOT(slotUserTemp()));


    passSys a;
    
    a.get(&sys);
    strcpy(cd.data.measureFile, sys.hdr.MonMeasurementSheet);
    strcpy(cd.data.calibFile, sys.hdr.MonCalibrationSheet);

    // setup polling for changes to connect devices
    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), SLOT(slotCheckDevices()));

    int depth = QColormap::instance().depth();
    if (depth < 24)
    {
        // need to issue an error message
        QString Message = tr("Display color depth is %1.  ").arg(depth, 0) + tr("It should be at least 24 for proper color management of your display.");

        QMessageBox::critical( this, tr("Display Color Depth Error"), Message);
    }
    slotUserLuminosity();
    slotUserGamma();
    slotUserTemp();
    slotDisplayType();
    currentState = needsCalibration;
    firstTime = TRUE;
    slotCheckDevices();
    
    textLabelHeading -> setAutoFillBackground ( true ); 
    QPalette pal = textLabelHeading -> palette();
    pal.setColor(textLabelHeading ->  backgroundRole(), Qt::white);
    textLabelHeading -> setPalette(pal);
    
    textLabelHeading3 -> setAutoFillBackground ( true ); 
    pal = textLabelHeading3 -> palette();
    pal.setColor(textLabelHeading3 ->  backgroundRole(), Qt::white);
    textLabelHeading3 -> setPalette(pal);
    
    textLabelHeading4 -> setAutoFillBackground ( true ); 
    pal = textLabelHeading4 -> palette();
    pal.setColor(textLabelHeading4 ->  backgroundRole(), Qt::white);
    textLabelHeading4 -> setPalette(pal);
    
    textLabelHeading5 -> setAutoFillBackground ( true ); 
    pal = textLabelHeading5 -> palette();
    pal.setColor(textLabelHeading5 ->  backgroundRole(), Qt::white);
    textLabelHeading5 -> setPalette(pal);
}

MonitorCalControl::~MonitorCalControl()
{
    dialogSize ds;
    
    cd.put(cd);
    ds.put(monCalControl, this -> height(), this -> width());
}


void MonitorCalControl::slotHelpButton()
{
    QString path = get_global_help_path()+  QString::fromLocal8Bit("/moncalcontrol.html");
    getHelp()->openAssistant ();
    getHelp()->showPage(path);
}

void MonitorCalControl::slotSettingsChanged()
{
     currentState = settingsChanged;
}


void MonitorCalControl::help()
{
    slotHelpButton();
}

void MonitorCalControl::accept()
{
   slotOK();
   Q3Wizard::accept();
}

void MonitorCalControl::reject()
{
    slotCancel();
    Q3Wizard::reject();
}

void MonitorCalControl::back()
{
    if ((this -> indexOf(this->currentPage()) == 1))
         instUpdate = TRUE;
    Q3Wizard::back();
}

void MonitorCalControl::next()
{
    instUpdate = FALSE;
    switch (this -> indexOf(this->currentPage()))
    {
        case 0:
            Q3Wizard::next();
            break;
        case 1:
            Q3Wizard::next();
            this -> setNextEnabled(this -> currentPage(), false);
            break;
        case 2:
        default:
            Q3Wizard::next();
            break;
    }
}

