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