Subversion Repositories svn1

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
95 david 1
#include "qmconfclass.h"
174 - 2
#include "qmconfig.h"
95 david 3
#include "ui_qmconfclass.h"
99 david 4
#include    "consts.h"
5
#include    "structs.h"
6
#include    "proto.h"
180 - 7
#include "mainwindow.h"
310 david 8
#include "qmTableWidgetItem.h"
95 david 9
 
286 david 10
#include <QDialogButtonBox>
99 david 11
#include "QTableWidgetItem"
107 david 12
#include "spinboxdelegate.h"
13
#include "timedelegate.h"
111 david 14
#include "textdelegate.h"
180 - 15
#include <QMenu>
99 david 16
 
227 - 17
#define COL_ABR 0
18
#define COL_CLASS 1
19
#define COL_TIME 2
20
#define COL_WINNERS 3
21
#define COL_NE 4
22
#define COL_NE_WINNERS 5
23
#define COL_ST_TOTAL 6
228 - 24
#define COL_ST_VALID 7
25
#define COL_ST_DISQ 8
26
#define COL_ST_NONEQ 9
27
#define COL_ST_VET 10
284 david 28
#define COL_ST_CEV 11
29
#define COL_ST_CNE 12
311 david 30
#define COL_INDEX 13
227 - 31
 
311 david 32
#define COL_COUNT 14
227 - 33
 
311 david 34
 
104 - 35
QmConfClass::QmConfClass(QWidget *parent) :
286 david 36
    QWidget(parent)
95 david 37
{
181 - 38
    populating = false;
286 david 39
    //resize ( 600,400);
99 david 40
 
286 david 41
    QVBoxLayout *verticalLayout = new QVBoxLayout(this);
42
    verticalLayout->setContentsMargins(0, 0, 0, 0);
43
 
44
    QGroupBox *groupBox = new QGroupBox("Class");
45
    verticalLayout->addWidget(groupBox);
46
    QVBoxLayout *verticalLayout2 = new QVBoxLayout(groupBox);
47
    tableWidget = new QTableWidget(groupBox);
48
    tableWidget->setAlternatingRowColors(true);
49
    tableWidget->setRowCount(config.num_class + 1);
50
    tableWidget->setColumnCount(COL_COUNT);
51
    tableWidget->setContextMenuPolicy(Qt::CustomContextMenu);
52
    tableWidget->horizontalHeader()->setVisible(true);
53
    tableWidget->horizontalHeader()->setDefaultSectionSize(70);
54
    tableWidget->horizontalHeader()->setHighlightSections(true);
290 david 55
    //tableWidget->horizontalHeader()->setStretchLastSection(true);
286 david 56
    tableWidget->verticalHeader()->setVisible(true);
57
    tableWidget->verticalHeader()->setDefaultSectionSize(20);
58
    //tableWidget->setSizePolicy(QSizePolicy::MinimumExpanding,QSizePolicy::MinimumExpanding );
59
    //tableWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
60
    verticalLayout2->addWidget(tableWidget);
61
 
62
    //QSpacerItem *verticalSpacer1;
63
    //verticalSpacer1 = new QSpacerItem(0, 10, QSizePolicy::Expanding, QSizePolicy::Expanding);
64
    //verticalLayout2->addItem(verticalSpacer1);
65
 
66
    QHBoxLayout *horizontalLayout;
67
    horizontalLayout = new QHBoxLayout();
68
    horizontalLayout->setContentsMargins(0, 0, 5, 5);
69
    verticalLayout->addLayout(horizontalLayout);
70
 
71
    QDialogButtonBox *buttonBox = new QDialogButtonBox();
72
    pushButtonRestore = buttonBox->addButton("Restore",QDialogButtonBox::ActionRole );
73
    pushButtonSave = buttonBox->addButton("Save",QDialogButtonBox::ActionRole );
74
    horizontalLayout->addWidget(buttonBox);
75
 
76
 
77
    connect(pushButtonSave, SIGNAL(clicked(bool)), this, SLOT(save()) );
78
    connect(pushButtonRestore, SIGNAL(clicked(bool)), this, SLOT(cancel()) );
79
 
109 david 80
    QStringList labels;
228 - 81
    labels << "Abr" << "Full Name" << "Start Time" << "Winners" << "NE" << "NE Winners";
109 david 82
 
311 david 83
    labels << "Total" << "Valid" <<"Disqual" << "NonEq" << "VetCheck" << "Comp Ev" << " Comp NE";
107 david 84
 
311 david 85
    labels << "Index";
86
 
87
    tableWidget->setHorizontalHeaderLabels(labels);
88
    tableWidget->resizeColumnsToContents();
89
 
286 david 90
    connect(tableWidget, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(ctxMenu(const QPoint &)));
91
    connect(tableWidget, SIGNAL(cellChanged(int,int)), this, SLOT(cellChanged(int,int)));
180 - 92
 
107 david 93
    /*
94
    **  Setup delegated for specialised editing
95
    */
286 david 96
    tableWidget->setItemDelegateForColumn(COL_ABR, new textDelegate(2));
97
    tableWidget->setItemDelegateForColumn(COL_CLASS, new textDelegate(LEN_CLASS_NAME));
98
    tableWidget->setItemDelegateForColumn(COL_TIME, new timeDelegate());
99
    tableWidget->setItemDelegateForColumn(COL_WINNERS, new SpinBoxDelegate(0,50));
100
    tableWidget->setItemDelegateForColumn(COL_NE_WINNERS, new SpinBoxDelegate(0,50));
107 david 101
 
99 david 102
    populate();
311 david 103
}
180 - 104
 
311 david 105
/*----------------------------------------------------------------------------
106
** FUNCTION           : populate
107
**
108
** DESCRIPTION        : Populate the display with information
109
**
110
----------------------------------------------------------------------------*/
180 - 111
 
104 - 112
void QmConfClass::populate(void)
99 david 113
{
311 david 114
    bool    reportDataLoaded = false;
115
    t_class_summary data;
116
 
181 - 117
    populating = true;
310 david 118
    tableWidget->clearContents();
119
    tableWidget->setSortingEnabled(false);
286 david 120
    tableWidget->setRowCount(config.num_class + 1);
311 david 121
 
122
    /*
123
    ** Load Report Data if we can
124
    */
125
    if( load_report_data() )
99 david 126
    {
311 david 127
        calc_class_summary( & data );
128
        reportDataLoaded = true;
129
    }
105 - 130
 
311 david 131
    /*
132
    **  Add all the information
133
    */
134
    int ii = 0;
135
    int entryIndex = 0;
136
    for ( ii = 0; ii < MAX_CLASS; ii++)
137
    {
138
        if ( config.team_class[ii].abr[0] )
111 david 139
        {
311 david 140
            // Keep the config item index entry
141
            //  Will need it when we write stiff out
142
            tableWidget->setItem(entryIndex, COL_INDEX, new qmTwiNumber(ii));
143
 
144
            tableWidget->setItem(entryIndex, COL_ABR, new QTableWidgetItem(config.team_class[ii].abr) );
145
            tableWidget->setItem(entryIndex, COL_CLASS, new QTableWidgetItem(config.team_class[ii].full_name ));
146
 
111 david 147
            QTableWidgetItem *item;
148
            item = new QTableWidgetItem();
149
            item->setData(Qt::EditRole,QTime().addSecs(config.team_class[ii].start) );
311 david 150
            tableWidget->setItem(entryIndex, COL_TIME, item);
107 david 151
 
310 david 152
            item = new qmTwiEditNumber(config.class_winners[ii]);
311 david 153
            tableWidget->setItem(entryIndex, COL_WINNERS, item);
181 - 154
 
155
            item = new QTableWidgetItem();
156
            item->setCheckState(config.nonequestrian_class == 1 + ii ? Qt::Checked : Qt::Unchecked);
311 david 157
            tableWidget->setItem(entryIndex, COL_NE, item);
181 - 158
 
310 david 159
            item = new qmTwiEditNumber(config.class_ne_winners[ii]);
311 david 160
            tableWidget->setItem(entryIndex, COL_NE_WINNERS, item);
161
 
162
            if (reportDataLoaded)
163
            {
164
                tableWidget->setItem(entryIndex,COL_ST_TOTAL, new qmTwiNumber(data.teamclass[ii+1].total) );
165
                tableWidget->setItem(entryIndex,COL_ST_VALID, new qmTwiNumber(data.teamclass[ii+1].valid) );
166
                tableWidget->setItem(entryIndex,COL_ST_DISQ,  new qmTwiNumber(data.teamclass[ii+1].disqualified));
167
                tableWidget->setItem(entryIndex,COL_ST_NONEQ, new qmTwiNumber(data.teamclass[ii+1].non_equestrian));
168
                tableWidget->setItem(entryIndex,COL_ST_VET,   new qmTwiNumber(data.teamclass[ii+1].vet_check));
169
                tableWidget->setItem(entryIndex,COL_ST_CEV,   new qmTwiNumber(data.teamclass[ii+1].valid_ev));
170
                tableWidget->setItem(entryIndex,COL_ST_CNE,   new qmTwiNumber(data.teamclass[ii+1].valid_ne));
171
            }
172
            entryIndex++;
111 david 173
        }
99 david 174
    }
311 david 175
 
176
    //  Insert Totals
177
    //      Flag that items on this this row is not to be sorted - or at least 
178
    //      sorted at the end
179
    //
180
    if (reportDataLoaded)
181
    {
182
        tableWidget->setItem(entryIndex,COL_ABR,      new qmTwiString("Totals", 1));
183
        tableWidget->setItem(entryIndex,COL_ST_TOTAL, new qmTwiNumber(data.total.total, 1));
184
        tableWidget->setItem(entryIndex,COL_ST_VALID, new qmTwiNumber(data.total.valid, 1));
185
        tableWidget->setItem(entryIndex,COL_ST_DISQ,  new qmTwiNumber(data.total.disqualified, 1));
186
        tableWidget->setItem(entryIndex,COL_ST_NONEQ, new qmTwiNumber(data.total.non_equestrian, 1));
187
        tableWidget->setItem(entryIndex,COL_ST_VET,   new qmTwiNumber(data.total.vet_check, 1));
188
        tableWidget->setItem(entryIndex,COL_ST_CEV,   new qmTwiNumber(data.total.valid_ev, 1));
189
        tableWidget->setItem(entryIndex,COL_ST_CNE,   new qmTwiNumber(data.total.valid_ne, 1));
190
    }
191
 
192
    tableWidget->resizeColumnsToContents();
193
    tableWidget->resizeRowsToContents();
194
    tableWidget->setSortingEnabled(true);
195
 
181 - 196
    updateChanged(false);
197
    populating = false;
99 david 198
}
199
 
104 - 200
void QmConfClass::save(void)
99 david 201
{
104 - 202
    /*
203
    **    Copy original data
204
    */
176 - 205
    QmConfig newcfg(config);
104 - 206
 
207
    /*
208
    **  Extract the data from the Widgets
209
    */
311 david 210
    for (int entryIndex = 0; entryIndex < tableWidget->rowCount(); entryIndex++)
104 - 211
    {
310 david 212
 
213
        // Check that this is a real Entry or the 'Totals' header
311 david 214
        //      Real rows have a COL_INDEX entr
310 david 215
        //
311 david 216
        QTableWidgetItem *item = tableWidget->item ( entryIndex, COL_INDEX );
217
        if (! item)
310 david 218
        {
219
            qDebug("Ignore row:%d", entryIndex);
220
            continue;
221
        }
311 david 222
        int ii = item->text().toInt();
223
        qDebug("Processing: %d", ii);
310 david 224
 
311 david 225
        if (ii >= MAX_CLASS || ii < 0)
226
        {
227
            qDebug("Ignore row:%d. Class out of rande", entryIndex);
228
            continue;
229
        }
230
 
231
        item = tableWidget->item ( entryIndex, COL_ABR );
111 david 232
        if ( item )
233
        {
234
            strncpy(newcfg.team_class[ii].abr, qPrintable(item->text()), sizeof(newcfg.team_class[ii].abr)-1);
235
        }
236
        else
237
        {
238
            *newcfg.team_class[ii].abr = 0;
239
        }
104 - 240
 
310 david 241
        item = tableWidget->item ( entryIndex, COL_CLASS );
111 david 242
        if ( item )
243
        {
244
            strncpy(newcfg.team_class[ii].full_name, qPrintable(item->text()), sizeof(newcfg.team_class[ii].full_name)-1);
245
        }
246
        else
247
        {
248
            *newcfg.team_class[ii].full_name = 0;
249
        }
108 david 250
 
310 david 251
        item = tableWidget->item( entryIndex, COL_TIME );
111 david 252
        if ( item )
253
        {
195 david 254
            QVariant data = item->data(Qt::EditRole);
255
            if (data.isValid())
256
            {
257
                newcfg.team_class[ii].start = QTime(0,0,0).secsTo(item->data(Qt::EditRole).toTime());
258
            }
259
            else
260
            {
261
                newcfg.team_class[ii].start = -1;
262
            }
111 david 263
        }
264
        else
265
        {
195 david 266
            newcfg.team_class[ii].start = -1;
111 david 267
        }
268
 
310 david 269
        item = tableWidget->item( entryIndex, COL_WINNERS );
111 david 270
        if ( item )
271
        {
272
            newcfg.class_winners[ii] = item->data(Qt::EditRole).toInt();
273
        }
274
        else
275
        {
276
            newcfg.class_winners[ii] = 0;
277
        }
227 - 278
 
310 david 279
        item = tableWidget->item( entryIndex, COL_NE );
181 - 280
        if ( item )
281
        {
282
            if ( item->checkState() == Qt::Checked)
283
            {
284
                newcfg.nonequestrian_class = ii;
285
                strncpy(newcfg.nonequestrian_class_abr, newcfg.team_class[ii].abr, sizeof(newcfg.team_class[ii].abr)-1);
286
            }
287
        }
227 - 288
 
310 david 289
        item = tableWidget->item( entryIndex, COL_NE_WINNERS );
227 - 290
        if ( item )
291
        {
292
            newcfg.class_ne_winners[ii] = item->data(Qt::EditRole).toInt();
293
        }
294
        else
295
        {
296
            newcfg.class_ne_winners[ii] = 0;
297
        }
104 - 298
    }
299
 
181 - 300
    // Validate the data
301
    try
104 - 302
    {
181 - 303
        MainWindow::showMessage( "Saving Config");
104 - 304
 
181 - 305
        /*
306
         **  Now do the Class definitions
307
         */
308
 
309
        for( int i = 0; i < MAX_CLASS; i++ )
104 - 310
        {
181 - 311
            compact( newcfg.team_class[i].abr );
312
            compact( newcfg.team_class[i].full_name );
104 - 313
        }
181 - 314
 
315
        for( int i = 0; i < MAX_CLASS; i++ )
104 - 316
        {
181 - 317
            if( ( newcfg.team_class[i].abr[0] == '\0' ) != ( newcfg.team_class[i].full_name[0] == '\0' ) )
318
            {
319
                throw( "Configuration error. Class without description" );
320
 
321
            }
322
            if( newcfg.team_class[i].abr[0] != '\0' && newcfg.team_class[i].start < 0L )
323
            {
324
                throw( "Configuration error. Bad start time on class" );
325
 
326
            }
104 - 327
        }
328
 
181 - 329
        newcfg.num_class = 0;
330
        for( int i = 0; i < MAX_CLASS; i++ )
331
            if( newcfg.team_class[i].full_name[0] )
332
                newcfg.num_class++;
104 - 333
 
181 - 334
        for( int i = newcfg.num_class; i < MAX_CLASS; i++ )
335
            if( newcfg.team_class[i].full_name[0] )
336
            {
337
                throw( "Configuration error: Missing Class name. Gaps not allowed" );
338
 
339
            }
340
 
341
        if( newcfg.num_class == 0 )
104 - 342
        {
181 - 343
            throw( "Error: No categories defined" );
344
 
104 - 345
        }
346
 
181 - 347
        newcfg.nonequestrian_class = newcfg.lookup_class( newcfg.nonequestrian_class_abr );
348
        if( newcfg.equestrian_leg && newcfg.nonequestrian_class == 0 )
349
            MainWindow::showMessage( "WARNING: Non-equestrian class not found" );
104 - 350
 
181 - 351
        /*
352
        **  Sanity test of the data
353
        */
354
        for( int i = 0; i < MAX_CLASS; i++ )
355
        {
356
            if( newcfg.team_class[i].abr[0] != '\0' && newcfg.class_winners[i] == 0 )
357
            {
104 - 358
 
181 - 359
                MainWindow::showMessage( QString("Warning: Class without winners:") + newcfg.team_class[i].abr );
360
            }
111 david 361
        }
362
 
227 - 363
        /*
364
        ** Cannot mix winners for NE class and NE Winners for each class
365
        */
366
        if (newcfg.nonequestrian_class)
367
        {
368
            newcfg.class_ne_winners_by_class = false;
369
            for( int i = 0; i < MAX_CLASS; i++ )
370
            {
228 - 371
                if ( newcfg.class_ne_winners[i])
372
                {
373
                    newcfg.class_ne_winners_by_class = true;
374
                    break;
375
                }
227 - 376
            }
377
            if (newcfg.class_winners[newcfg.nonequestrian_class - 1] && newcfg.class_ne_winners_by_class )
378
            {
379
                MainWindow::showMessage( QString("Should not mix NE winners by each class and by NE Class"));
380
                //throw( "Error: Cannot mix NE winners by each class and by NE Class" );
381
            }
382
        }
383
 
384
 
104 - 385
        config = newcfg;
176 - 386
        config.write_config();
181 - 387
        updateChanged(false);
388
 
104 - 389
    }
181 - 390
    catch (const char * str )
391
    {
392
        MainWindow::showMessage(str);
393
    }
104 - 394
 
99 david 395
}
396
 
104 - 397
void QmConfClass::cancel(void)
99 david 398
{
399
    populate();
400
}
401
 
104 - 402
QmConfClass::~QmConfClass()
95 david 403
{
286 david 404
 
95 david 405
}
406
 
180 - 407
void QmConfClass::ctxMenu(const QPoint & pos)
408
{
409
    qDebug("Context Menu");
410
    QMenu *menu = new QMenu;
286 david 411
    QTableWidgetItem *item = tableWidget->itemAt(pos);
180 - 412
    menu->addAction(tr("New Category"), this, SLOT(ctxMenuAddRow()));
413
    if (item)
414
    {
415
        menu->addAction(tr("Delete Category"), this, SLOT(ctxMenuDeleteRow()));
416
    }
286 david 417
   menu->exec(tableWidget->mapToGlobal(pos));
180 - 418
 
419
}
420
 
421
void QmConfClass::ctxMenuDeleteRow(void)
422
{
286 david 423
    //qDebug ("DELETE ROW: %d", tableWidget->currentRow () );
424
    tableWidget->removeRow(tableWidget->currentRow ());
189 - 425
    updateChanged(true);
180 - 426
}
427
 
428
void QmConfClass::ctxMenuAddRow(void)
429
{
286 david 430
    tableWidget->setRowCount( 1+ tableWidget->rowCount());
180 - 431
}
432
 
181 - 433
void QmConfClass::cellChanged(int row,int col)
434
{
435
    if ( populating )
436
        return;
437
    updateChanged(true);
438
    populating = true;
439
    //qDebug("Cell changed: %d, %d", row, col);
227 - 440
    if (col == COL_NE)
181 - 441
    {
286 david 442
        for (int ii = 0; ii < tableWidget->rowCount(); ii++)
181 - 443
        {
286 david 444
            QTableWidgetItem *item = tableWidget->item(ii, COL_NE);
181 - 445
            if (item)
446
            {
447
                item->setCheckState(ii == row ? Qt::Checked : Qt::Unchecked);
448
            }
449
        }
450
    }
451
    populating = false;
452
}
453
 
454
void QmConfClass::updateChanged(bool newDirty)
455
{
456
    if (newDirty != dirty)
457
    {
458
        dirty = newDirty;
459
        if (dirty)
460
        {
286 david 461
            pushButtonSave->setEnabled(true);
462
            pushButtonSave->setStyleSheet("background-color: rgb(255, 0, 0);");
181 - 463
        }
464
        else
465
        {
286 david 466
            pushButtonSave->setEnabled(false);
467
            pushButtonSave->setStyleSheet("");
181 - 468
        }
469
    }
470
}
471
 
104 - 472
void QmConfClass::changeEvent(QEvent *e)
95 david 473
{
474
    QWidget::changeEvent(e);
475
    switch (e->type()) {
286 david 476
 
95 david 477
    default:
478
        break;
479
    }
480
}