Subversion Repositories svn1-original

Rev

Rev 335 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*============================================================================
**
**  Project/Product : 
**  Filename        : qmteamdisplay.cpp
**  Author(s)       : DDP
**
**  Description     : Display and Update Team Information
**
**
**  Information     :
**   Compiler       : ANSI C++
**   Target         : 
**
***==========================================================================*/

#include "qmteamdisplay.h"
#include "ui_qmteamdisplay.h"
#include "spinboxdelegate.h"
#include "timedelegate.h"
#include "textdelegate.h"
#include "mainwindow.h"
#include "QmEditAddendum.h"

/*----------------------------------------------------------------------------
** FUNCTION           : qmTeamDisplay
**
** DESCRIPTION        : Construct a new widget
**
**
** INPUTS             :
**
** RETURNS            :
**
----------------------------------------------------------------------------*/


qmTeamDisplay::qmTeamDisplay(QWidget *parent, int initialTeam, bool useDone) :
    QWidget(parent),
    ui(new Ui::QmTeamDisplay)
{
    ui->setupUi(this);
    team = 0;
    dirty = true;
    populating = false;
    enableDone = useDone;

    /*
    **  Set delegates to assist in editing the members table
    **      Name
    **      Sex
    **      Age
    */
    ui->members->setItemDelegateForColumn(0, new textDelegate(MAX_PERSON_NAME));
    ui->members->setItemDelegateForColumn(2, new SpinBoxDelegate(0,120));

    ui->members->verticalHeader()->setVisible(true);
    QStringList labels;
    for ( int ii = 0 ; ii < config.num_legs; ii++)
    {
        labels << config.leg_name[ii];
    }
    ui->members->setVerticalHeaderLabels(labels);

    /*
    ** Insert widgets for the Team Times
    */
    for ( int ii = 1 ; ii <= config.num_legs; ii++)
    {
        lt[ii] = new QmLegTimes(ii, config.leg_name[ii-1]);
        ui->legTime_layout->addWidget(lt[ii]);
        connect (lt[ii], SIGNAL(dataChanged()), this, SLOT(recalculateTimes()) );
    }
    lt[0] = new QmLegTimes(0, "Overall Event");
    ui->legTime_layout->addWidget(lt[0]);

    /*
    ** Init initial displayed team
    */
    team = initialTeam ? initialTeam : config.min_team;

    /*
    **  Connect up various signals
    */
    connect(ui->pushButtonSave, SIGNAL(clicked()), this, SLOT(save()) );
    connect(ui->pushButtonRestore, SIGNAL(clicked()), this, SLOT(cancel()) );
    connect(ui->teamNumber, SIGNAL(valueChanged(int)), this, SLOT(populate(int)) );

    connect(ui->name, SIGNAL(textEdited(QString)), this, SLOT(changed()) );
    connect(ui->category , SIGNAL(currentIndexChanged(int)), this, SLOT(changed()));
    connect(ui->category , SIGNAL(currentIndexChanged(int)), this, SLOT(updateCategory()));
    connect(ui->members , SIGNAL(cellChanged(int,int)), this, SLOT(changed()));
    connect(ui->disqualified , SIGNAL(clicked(bool)), this, SLOT(changed()));
    connect(ui->nonEquestrian , SIGNAL(clicked(bool)), this, SLOT(recalculateTimes()));
    connect(ui->disabled , SIGNAL(clicked(bool)), this, SLOT(changed()));
    connect(ui->VetCheck , SIGNAL(clicked(bool)), this, SLOT(changed()));

    connect(ui->editNote, SIGNAL(clicked()), this, SLOT(editNote()));

    updateChanged(false);
}

/*----------------------------------------------------------------------------
** FUNCTION           : ~qmTeamDisplay
**
** DESCRIPTION        : Destructor
**
**
** INPUTS             :
**
** RETURNS            :
**
----------------------------------------------------------------------------*/

qmTeamDisplay::~qmTeamDisplay()
{
    delete ui;
}

/*----------------------------------------------------------------------------
** FUNCTION           : showEvent
**
** DESCRIPTION        : Slot that is wired into the main windows widget
**                      It will be called when the main window widget changes
**                      If this display is the current display, then load new data
**
** INPUTS             : index of the tab that now has focus
**
----------------------------------------------------------------------------*/

void qmTeamDisplay::showEvent ( QShowEvent * event )
{
    //qDebug("showEvent::showEvent");
    if ( ! event->spontaneous() )
    {
        if ( ! dirty)
        {
            populate(team);
        }
    }
}

/*----------------------------------------------------------------------------
** FUNCTION           : blockSignals
**
** DESCRIPTION        : Block signal from widgets that set Changed
**                      while populating the display
**
**
** INPUTS             : state - New blocking state
**
** RETURNS            : Nothing
**
----------------------------------------------------------------------------*/

void qmTeamDisplay::blockSignals(bool state)
{
//    ui->pushButtonSave->blockSignals(state);
//    ui->pushButtonRestore->blockSignals(state);
//    ui->teamNumber->blockSignals(state);

    ui->name->blockSignals(state);
    ui->category->blockSignals(state);
    ui->members->blockSignals(state);
    ui->disqualified->blockSignals(state);
    ui->nonEquestrian->blockSignals(state);
    ui->disabled->blockSignals(state);
    ui->VetCheck->blockSignals(state);

    for ( int ii = 0 ; ii <= config.num_legs; ii++)
    {
        lt[ii]->blockSignals(state);
    }
}

/*----------------------------------------------------------------------------
** FUNCTION           : populate
**
** DESCRIPTION        : Populate the widget with data
**
**
** INPUTS             : team_number         - Team number to use
**
** RETURNS            :
**
----------------------------------------------------------------------------*/

void qmTeamDisplay::populate(int team_number)
{
    /*
    **  Update the spinner that describes the current team number
    */
    populating = true;
    blockSignals(true);

    ui->teamNumber->setMaximum(config.max_team);
    ui->teamNumber->setMinimum(config.min_team);
    ui->teamNumber->setValue(team_number);
    team = team_number;

    /*
    **  Read in team data
    **  This will persist within this widget
    */
    g_record( team, &team_buf );

    /*
    ** Basic Data
    */
    ui->name->setText( team_buf.name );
    ui->category_abr->setText( config.team_class[team_buf.teamclass - 1].abr );

    /*
    ** ComboBox for Category selection
    **  Save category index as data inthe combobox
    **  Do not show the NE category - it should be selected
    */
    ui->category->clear();
    int selectedIndex = -1;
    for ( int ii = 0; ii < config.num_class ; ii++)
    {
        if (config.team_class[ii].abr[0] && (config.nonequestrian_class != ii + 1))
        {
            ui->category->addItem(config.team_class[ii].full_name, ii);
            if (ii == team_buf.teamclass - 1)
            {
                selectedIndex = ui->category->count() - 1;
                //qDebug("ComboIndex:%d",ii);
            }
        }
    }
    ui->category->setCurrentIndex(selectedIndex);

    ui->disqualified->setCheckState(team_buf.flags.disqualified ? Qt::Checked : Qt::Unchecked);
    ui->nonEquestrian->setCheckState(team_buf.flags.non_equestrian ? Qt::Checked : Qt::Unchecked);
    ui->disabled->setCheckState( !team_buf.flags.valid ? Qt::Checked : Qt::Unchecked);
    ui->VetCheck->setCheckState( team_buf.flags.vet_check ? Qt::Checked : Qt::Unchecked);

    /*
    ** Team Member data
    **       Name
    **      Sex
    **      Age
    */
    int age_sum = 0;
    for ( int ii = 0; ii < config.num_legs; ii ++)
    {
         QTableWidgetItem *item;
        ui->members->setItem(ii, 0, new QTableWidgetItem(team_buf.members[ii].name) );

        item = new QTableWidgetItem();
        item->setFlags(Qt::ItemIsTristate | item->flags());
        enum Qt::CheckState sex;
        switch ( team_buf.members[ii].sex )
        {
            case male:   sex = Qt::Unchecked;        break;
            case female: sex = Qt::Checked;          break;
            default:     sex = Qt::PartiallyChecked; break;
        }
        //qDebug("RSex:%d, %d, %d, %d", team, ii, sex, team_buf.members[ii].sex);
        item->setCheckState(sex );
        ui->members->setItem(ii, 1, item );

        item = new QTableWidgetItem();
        item->setData(Qt::EditRole,team_buf.members[ii].age);
        ui->members->setItem(ii, 2, item );

        /*
        **  Sum ages
        **  -1 indicates invalid age
        */
        if ( age_sum >= 0 )
        {
            ushort age = team_buf.members[ii].age;
            if ( age > 0 && age < 255 )
            {
                age_sum += age;
            }
            else
            {
                age_sum = -1;
            }
        }
    }
    ui->members->resizeColumnsToContents();

    /*
    **  Mainatain the display of total age
    */
    if ( age_sum <= 0 )
    {
        ui->totalAge->setText("--");
    }
    else
    {
        ui->totalAge->setText(QString::number(age_sum));
    }


    /*
    ** Leg Times
    */
    for ( int ii = 0 ; ii <= config.num_legs; ii++)
    {
        lt[ii]->setData(&team_buf.leg[ii]);
    }

    /*
    **  Team Note
    */
    populateNote();

    updateChanged(false);
    populating = false;
    blockSignals(false);
    
}

void qmTeamDisplay::updateCategory(void)
{
    int currentIndex = ui->category->currentIndex();
    if (currentIndex >= 0)
    {
        int itemData = ui->category->itemData(currentIndex).toInt();
        ui->category_abr->setText( config.team_class[itemData].abr );
    }
}

/*----------------------------------------------------------------------------
** FUNCTION           : recalculateTimes
**
** DESCRIPTION        : Recalculate and update all the times for the legs
**
**
** INPUTS             : None
**
** RETURNS            :
**
----------------------------------------------------------------------------*/

void qmTeamDisplay::recalculateTimes( void )
{
    for ( int ii = 0 ; ii <= config.num_legs; ii++)
    {
        lt[ii]->getData(&team_buf.leg[ii]);
    }
    suckData();
    set_times( &team_buf );
    test_times( &team_buf, 0 );
    for ( int ii = 0 ; ii <= config.num_legs; ii++)
    {
        lt[ii]->setData(&team_buf.leg[ii]);
    }

    // Flag data as changed
    changed();
}

/*----------------------------------------------------------------------------
** FUNCTION           : suckData
**
** DESCRIPTION        : Save the data back to memory
**
** INPUTS             :
**
** RETURNS            :
**
----------------------------------------------------------------------------*/

void qmTeamDisplay::suckData(void)
{
    /*
    ** Extract data from the widgets
    ** The time stuff is done on the fly as it changes
    */
    strncpy(team_buf.name , qPrintable(ui->name->text()), sizeof(team_buf.name));

    int currentIndex = ui->category->currentIndex();
    if (currentIndex >= 0)
    {
        int itemData = ui->category->itemData(currentIndex).toInt();
        team_buf.teamclass = itemData + 1;
    }

    team_buf.flags.disqualified =  ( ui->disqualified->checkState () == Qt::Checked);
    team_buf.flags.non_equestrian =  ( ui->nonEquestrian->checkState () == Qt::Checked);
    team_buf.flags.valid =  ( ui->disabled->checkState () != Qt::Checked);
    team_buf.flags.vet_check =  ( ui->VetCheck->checkState () == Qt::Checked);

    /*
    ** Extract Team Member Data
    */
    for ( int ii = 0; ii < config.num_legs; ii ++)
    {
        QTableWidgetItem *item;
        item = ui->members->item ( ii, 0 );
        strncpy(team_buf.members[ii].name , qPrintable(item->text()), sizeof(team_buf.members[ii].name));

        //TODO: Make Sex edit work
        item = ui->members->item ( ii, 1 );
        enum Qt::CheckState sex = item->checkState();
        switch (sex)
        {
            case Qt::Unchecked: team_buf.members[ii].sex = male;  break;
            case Qt::Checked: team_buf.members[ii].sex = female; break;
            default: team_buf.members[ii].sex = unknown; break;
        }
        //qDebug("WSex:%d, %d, %d, %d", team, ii, sex, team_buf.members[ii].sex);

        item = ui->members->item ( ii, 2 );
        team_buf.members[ii].age = item->data(Qt::EditRole).toInt();

    }
}

/*----------------------------------------------------------------------------
** FUNCTION           : save
**
** DESCRIPTION        : Save the data back to disk
**                      Also called if nothing to save - ie Done Mode
**
** INPUTS             :
**
** RETURNS            :
**
----------------------------------------------------------------------------*/

void qmTeamDisplay::save(void)
{
    if ( dirty )
    {
        /*
        ** Save the record back to disk
        */
        suckData();
        put_team_record( team, &team_buf );
        populate(team);
    }
    else
    {
        if ( enableDone )
            emit dialogDone(1);
    }
}

/*----------------------------------------------------------------------------
** FUNCTION           : cancel
**
** DESCRIPTION        : Kill of any edited data
**                      Redisplay the team data
**
** INPUTS             :
**
** RETURNS            :
**
----------------------------------------------------------------------------*/


void qmTeamDisplay::cancel(void)
{
    populate(team);
}

void qmTeamDisplay::changed(void)
{
//QObject * who = sender () ;
//qDebug ("Changed: %p", who);
    if (populating)
        return;
    updateChanged(true);

}

void qmTeamDisplay::updateChanged(bool newDirty)
{
    //qDebug("updateChanged: %d, %d -> %d", populating, dirty, newDirty );
    if (newDirty != dirty)
    {
        dirty = newDirty;
        if (dirty)
        {
            ui->Changed->setVisible(true);
            ui->teamNumber->setEnabled(false);
            ui->pushButtonSave->setEnabled(true);
            ui->pushButtonSave->setStyleSheet("background-color: rgb(255, 0, 0);");
            ui->pushButtonSave->setText("Save");

            //  Only valid when within a dialog
            //  Now have the dialog swallow <return>
            //ui->pushButtonSave->setDefault(true);
        }
        else
        {
            ui->Changed->setVisible(false);
            ui->teamNumber->setEnabled(true);
            //ui->pushButtonSave->setEnabled(false);
            ui->pushButtonSave->setStyleSheet("");

            if ( enableDone )
                ui->pushButtonSave->setText("Done");
        }
    }
}

/*----------------------------------------------------------------------------
** FUNCTION           : changeEvent
**
** DESCRIPTION        :
**
**
** INPUTS             :
**
** RETURNS            :
**
----------------------------------------------------------------------------*/

void qmTeamDisplay::changeEvent(QEvent *e)
{
//qDebug("qmTeamDisplay ChangeEvent: %d",e->type());
    QWidget::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        ui->retranslateUi(this);
        break;
    default:
        break;
    }
}

/*----------------------------------------------------------------------------
** FUNCTION           : populateNote
**
** DESCRIPTION        : Populate the Note area of the team display
**                      Must be called during populate as
**
**
** INPUTS             :
**
** RETURNS            :
**
----------------------------------------------------------------------------*/

void qmTeamDisplay::populateNote(void)
{
    noteFileName = "TeamNote_" + QString::number(team) + ".txt";
    //qDebug("NoteFile:%s",qPrintable(noteFileName));

    //  Clear combobox before we add text
    ui->noteText->clear();

    QFile noteFile(QString(filepath) + noteFileName);
    if ( noteFile.open( QIODevice::ReadOnly ) )
    {
        QTextStream stream( &noteFile );
        QString line;
        do {
             line = stream.readLine();
             if (line.isNull())
                 break;
             ui->noteText->addItem(line);
         } while (true);
        noteFile.close();
    }
    ui->noteText->setStyleSheet( ui->noteText->count() ? "background-color: #FFFFCB;" : "");

    /*
    ** Delete empy files to keep things clean
    */
    if (noteFile.size() == 0 )
    {
        noteFile.remove();
    }
}

/*----------------------------------------------------------------------------
** FUNCTION           : editNote
**
** DESCRIPTION        : Edit the Team Note in a  modal dialog box
**
** INPUTS             :
**
** RETURNS            :
**
----------------------------------------------------------------------------*/

void qmTeamDisplay::editNote(void)
{
    QmEditAddendum dialog(QmConfig::getAddendemFile(noteFileName, true), true);
     dialog.exec();
     populateNote();
}