~valavanisalex/ubuntu/lucid/scidavis/scidavis-fix-565206

« back to all changes in this revision

Viewing changes to scidavis/src/future/table/TableView.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Ruben Molina
  • Date: 2009-09-06 11:34:04 UTC
  • Revision ID: james.westby@ubuntu.com-20090906113404-4awaey82l3686w4q
Tags: upstream-0.2.3
ImportĀ upstreamĀ versionĀ 0.2.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
    File                 : TableView.cpp
 
3
    Project              : SciDAVis
 
4
    Description          : View class for Table
 
5
    --------------------------------------------------------------------
 
6
    Copyright            : (C) 2007 Tilman Benkert (thzs*gmx.net)
 
7
                           (replace * with @ in the email addresses) 
 
8
 
 
9
 ***************************************************************************/
 
10
 
 
11
/***************************************************************************
 
12
 *                                                                         *
 
13
 *  This program is free software; you can redistribute it and/or modify   *
 
14
 *  it under the terms of the GNU General Public License as published by   *
 
15
 *  the Free Software Foundation; either version 2 of the License, or      *
 
16
 *  (at your option) any later version.                                    *
 
17
 *                                                                         *
 
18
 *  This program is distributed in the hope that it will be useful,        *
 
19
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
 
20
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
 
21
 *  GNU General Public License for more details.                           *
 
22
 *                                                                         *
 
23
 *   You should have received a copy of the GNU General Public License     *
 
24
 *   along with this program; if not, write to the Free Software           *
 
25
 *   Foundation, Inc., 51 Franklin Street, Fifth Floor,                    *
 
26
 *   Boston, MA  02110-1301  USA                                           *
 
27
 *                                                                         *
 
28
 ***************************************************************************/
 
29
 
 
30
#include "table/future_Table.h"
 
31
#include "table/TableView.h"
 
32
#include "table/TableModel.h"
 
33
#include "table/TableItemDelegate.h"
 
34
#include "table/tablecommands.h"
 
35
#include "table/TableDoubleHeaderView.h"
 
36
 
 
37
#include "core/column/Column.h"
 
38
#include "core/AbstractFilter.h"
 
39
#include "core/datatypes/SimpleCopyThroughFilter.h"
 
40
#include "core/datatypes/Double2StringFilter.h"
 
41
#include "core/datatypes/String2DoubleFilter.h"
 
42
#include "core/datatypes/DateTime2StringFilter.h"
 
43
#include "core/datatypes/String2DateTimeFilter.h"
 
44
 
 
45
#include <QKeyEvent>
 
46
#include <QtDebug>
 
47
#include <QHeaderView>
 
48
#include <QRect>
 
49
#include <QPoint>
 
50
#include <QSize>
 
51
#include <QFontMetrics>
 
52
#include <QFont>
 
53
#include <QItemSelectionModel>
 
54
#include <QItemSelection>
 
55
#include <QShortcut>
 
56
#include <QModelIndex>
 
57
#include <QGridLayout>
 
58
#include <QScrollArea>
 
59
#include <QMenu>
 
60
 
 
61
#ifndef LEGACY_CODE_0_2_x
 
62
TableView::TableView(future::Table *table)
 
63
 : d_table(table) 
 
64
#else
 
65
TableView::TableView(const QString& label, QWidget* parent, const char* name, Qt::WFlags f)
 
66
 : MyWidget(label, parent, name, f)
 
67
#endif
 
68
{
 
69
#ifndef LEGACY_CODE_0_2_x
 
70
        d_model = new TableModel(table);
 
71
        init();
 
72
#else
 
73
        d_model = NULL;
 
74
#endif
 
75
}
 
76
 
 
77
TableView::~TableView() 
 
78
{
 
79
        delete d_model;
 
80
}
 
81
 
 
82
void TableView::setTable(future::Table * table)
 
83
{
 
84
        d_table = table;
 
85
        d_model = new TableModel(table);
 
86
        init();
 
87
}
 
88
 
 
89
void TableView::init()
 
90
{
 
91
        d_main_layout = new QHBoxLayout(this);
 
92
        d_main_layout->setSpacing(0);
 
93
        d_main_layout->setContentsMargins(0, 0, 0, 0);
 
94
        
 
95
        d_view_widget = new TableViewWidget(this);
 
96
        d_view_widget->setModel(d_model);
 
97
        connect(d_view_widget, SIGNAL(advanceCell()), this, SLOT(advanceCell()));
 
98
        d_main_layout->addWidget(d_view_widget);
 
99
        
 
100
        d_horizontal_header = new TableDoubleHeaderView();
 
101
    d_horizontal_header->setClickable(true);
 
102
    d_horizontal_header->setHighlightSections(true);
 
103
        d_view_widget->setHorizontalHeader(d_horizontal_header);
 
104
 
 
105
        d_hide_button = new QToolButton();
 
106
        d_hide_button->setArrowType(Qt::RightArrow);
 
107
        d_hide_button->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding));
 
108
        d_hide_button->setCheckable(false);
 
109
        d_main_layout->addWidget(d_hide_button);
 
110
        connect(d_hide_button, SIGNAL(pressed()), this, SLOT(toggleControlTabBar()));
 
111
        d_control_tabs = new QWidget();
 
112
    ui.setupUi(d_control_tabs);
 
113
        d_main_layout->addWidget(d_control_tabs);
 
114
 
 
115
        d_delegate = new TableItemDelegate(d_view_widget);
 
116
        d_view_widget->setItemDelegate(d_delegate);
 
117
        
 
118
        d_view_widget->setSizePolicy(QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding));
 
119
        d_main_layout->setStretchFactor(d_view_widget, 1);
 
120
 
 
121
        setSizePolicy(QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding));
 
122
 
 
123
        d_view_widget->setFocusPolicy(Qt::StrongFocus);
 
124
        setFocusPolicy(Qt::StrongFocus);
 
125
        setFocus();
 
126
#if QT_VERSION >= 0x040300
 
127
        d_view_widget->setCornerButtonEnabled(true);
 
128
#endif
 
129
 
 
130
        d_view_widget->setSelectionMode(QAbstractItemView::ExtendedSelection);
 
131
 
 
132
        QHeaderView * v_header = d_view_widget->verticalHeader();
 
133
        // Remark: ResizeToContents works in Qt 4.2.3 but is broken in 4.3.0
 
134
        // Should be fixed in 4.3.1 though, see:
 
135
        // http://trolltech.com/developer/task-tracker/index_html?method=entry&id=165567
 
136
        v_header->setResizeMode(QHeaderView::ResizeToContents);
 
137
        v_header->setMovable(false);
 
138
        d_horizontal_header->setResizeMode(QHeaderView::Interactive);
 
139
        d_horizontal_header->setMovable(true);
 
140
        connect(d_horizontal_header, SIGNAL(sectionMoved(int,int,int)), this, SLOT(handleHorizontalSectionMoved(int,int,int)));
 
141
        connect(d_horizontal_header, SIGNAL(sectionDoubleClicked(int)), this, SLOT(handleHorizontalHeaderDoubleClicked(int)));
 
142
        
 
143
        d_horizontal_header->setDefaultSectionSize(future::Table::defaultColumnWidth());
 
144
 
 
145
        v_header->installEventFilter(this);
 
146
        d_horizontal_header->installEventFilter(this);
 
147
        d_view_widget->installEventFilter(this);
 
148
 
 
149
        connect(d_model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)), d_view_widget, 
 
150
                SLOT(updateHeaderGeometry(Qt::Orientation,int,int)) ); 
 
151
        connect(d_model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)), this, 
 
152
                SLOT(handleHeaderDataChanged(Qt::Orientation,int,int)) ); 
 
153
        connect(d_table, SIGNAL(aspectDescriptionChanged(const AbstractAspect*)),
 
154
                        this, SLOT(handleAspectDescriptionChanged(const AbstractAspect*)));
 
155
        connect(d_table, SIGNAL(aspectAdded(const AbstractAspect*)),
 
156
                        this, SLOT(handleAspectAdded(const AbstractAspect*)));
 
157
        connect(d_table, SIGNAL(aspectAboutToBeRemoved(const AbstractAspect*,int)),
 
158
                        this, SLOT(handleAspectAboutToBeRemoved(const AbstractAspect*,int)));
 
159
 
 
160
        rereadSectionSizes();
 
161
        
 
162
        // keyboard shortcuts
 
163
        QShortcut * sel_all = new QShortcut(QKeySequence(tr("Ctrl+A", "Table: select all")), d_view_widget);
 
164
        connect(sel_all, SIGNAL(activated()), d_view_widget, SLOT(selectAll()));
 
165
 
 
166
        connect(ui.type_box, SIGNAL(currentIndexChanged(int)), this, SLOT(updateFormatBox()));
 
167
        connect(ui.format_box, SIGNAL(currentIndexChanged(int)), this, SLOT(updateTypeInfo()));
 
168
        connect(ui.digits_box, SIGNAL(valueChanged(int)), this, SLOT(updateTypeInfo()));
 
169
        connect(ui.previous_column_button, SIGNAL(clicked()), this, SLOT(goToPreviousColumn()));
 
170
        connect(ui.next_column_button, SIGNAL(clicked()), this, SLOT(goToNextColumn()));
 
171
        retranslateStrings();
 
172
 
 
173
        QItemSelectionModel * sel_model = d_view_widget->selectionModel();
 
174
 
 
175
        connect(sel_model, SIGNAL(currentColumnChanged(const QModelIndex&, const QModelIndex&)), 
 
176
                this, SLOT(currentColumnChanged(const QModelIndex&, const QModelIndex&)));
 
177
        connect(sel_model, SIGNAL(selectionChanged(const QItemSelection&,const QItemSelection&)),
 
178
                this, SLOT(selectionChanged(const QItemSelection&,const QItemSelection&)));
 
179
        connect(ui.button_set_description, SIGNAL(pressed()), 
 
180
                this, SLOT(applyDescription()));
 
181
        connect(ui.button_set_type, SIGNAL(pressed()),
 
182
                this, SLOT(applyType()));
 
183
}
 
184
 
 
185
void TableView::rereadSectionSizes()
 
186
{
 
187
        disconnect(d_horizontal_header, SIGNAL(sectionResized(int, int, int)), this, SLOT(handleHorizontalSectionResized(int, int, int)));
 
188
 
 
189
        int cols = d_table->columnCount();
 
190
        for (int i=0; i<cols; i++)
 
191
                d_horizontal_header->resizeSection(i, d_table->columnWidth(i));
 
192
                
 
193
        connect(d_horizontal_header, SIGNAL(sectionResized(int, int, int)), this, SLOT(handleHorizontalSectionResized(int, int, int)));
 
194
}
 
195
 
 
196
void TableView::setColumnWidth(int col, int width) 
 
197
 
198
        d_horizontal_header->resizeSection(col, width);
 
199
}
 
200
 
 
201
int TableView::columnWidth(int col) const 
 
202
 
203
        return d_horizontal_header->sectionSize(col);
 
204
}
 
205
 
 
206
void TableView::handleHorizontalSectionResized(int logicalIndex, int oldSize, int newSize)
 
207
{
 
208
        static bool inside = false;
 
209
        d_table->setColumnWidth(logicalIndex, newSize);
 
210
        if (inside) return;
 
211
        inside = true;
 
212
 
 
213
        int cols = d_table->columnCount();
 
214
        for (int i=0; i<cols; i++)
 
215
                if(isColumnSelected(i, true)) 
 
216
                        d_horizontal_header->resizeSection(i, newSize);
 
217
 
 
218
        inside = false;
 
219
}
 
220
 
 
221
void TableView::changeEvent(QEvent * event)
 
222
{
 
223
        if (event->type() == QEvent::LanguageChange) 
 
224
                retranslateStrings();
 
225
        MyWidget::changeEvent(event);   
 
226
}
 
227
 
 
228
void TableView::retranslateStrings()
 
229
{
 
230
        d_hide_button->setToolTip(tr("Show/hide control tabs"));
 
231
    ui.retranslateUi(d_control_tabs);
 
232
 
 
233
        ui.type_box->clear();
 
234
        ui.type_box->addItem(tr("Numeric"), QVariant(int(SciDAVis::Numeric)));
 
235
        ui.type_box->addItem(tr("Text"), QVariant(int(SciDAVis::Text)));
 
236
        ui.type_box->addItem(tr("Month names"), QVariant(int(SciDAVis::Month)));
 
237
        ui.type_box->addItem(tr("Day names"), QVariant(int(SciDAVis::Day)));
 
238
        ui.type_box->addItem(tr("Date and time"), QVariant(int(SciDAVis::DateTime)));
 
239
 
 
240
        ui.type_box->setCurrentIndex(0);
 
241
 
 
242
        // TODO: implement formula stuff
 
243
        //ui.formula_info->document()->setPlainText("not implemented yet");
 
244
}
 
245
        
 
246
void TableView::advanceCell()
 
247
{
 
248
        QModelIndex idx = d_view_widget->currentIndex();
 
249
    if(idx.row()+1 >= d_table->rowCount())
 
250
        {
 
251
                int new_size = d_table->rowCount()+1;
 
252
                d_table->setRowCount(new_size);
 
253
        }
 
254
        d_view_widget->setCurrentIndex(idx.sibling(idx.row()+1, idx.column()));
 
255
}
 
256
 
 
257
void TableView::goToCell(int row, int col)
 
258
{
 
259
        QModelIndex index = d_model->index(row, col);
 
260
        d_view_widget->scrollTo(index);
 
261
        d_view_widget->setCurrentIndex(index);
 
262
}
 
263
 
 
264
void TableView::selectAll()
 
265
{
 
266
        d_view_widget->selectAll();
 
267
}
 
268
 
 
269
void TableView::deselectAll()
 
270
{
 
271
        d_view_widget->clearSelection();
 
272
}
 
273
 
 
274
void TableView::toggleControlTabBar() 
 
275
 
276
        d_control_tabs->setVisible(!d_control_tabs->isVisible());
 
277
        if(d_control_tabs->isVisible())
 
278
                d_hide_button->setArrowType(Qt::RightArrow);
 
279
        else
 
280
                d_hide_button->setArrowType(Qt::LeftArrow);
 
281
}
 
282
 
 
283
void TableView::handleHorizontalSectionMoved(int index, int from, int to)
 
284
{
 
285
        static bool inside = false;
 
286
        if(inside) return;
 
287
 
 
288
        Q_ASSERT(index == from);
 
289
 
 
290
        inside = true;
 
291
        d_view_widget->horizontalHeader()->moveSection(to, from);
 
292
        inside = false;
 
293
        d_table->moveColumn(from, to);
 
294
}
 
295
 
 
296
void TableView::handleHorizontalHeaderDoubleClicked(int index)
 
297
{
 
298
        Q_UNUSED(index);
 
299
        showControlDescriptionTab();
 
300
}
 
301
 
 
302
bool TableView::areCommentsShown() const
 
303
{
 
304
        return d_horizontal_header->areCommentsShown();
 
305
}
 
306
 
 
307
void TableView::toggleComments()
 
308
{
 
309
        showComments(!areCommentsShown());
 
310
}
 
311
 
 
312
void TableView::showComments(bool on)
 
313
{
 
314
        d_horizontal_header->showComments(on);
 
315
        update();
 
316
}
 
317
 
 
318
void TableView::currentColumnChanged(const QModelIndex & current, const QModelIndex & previous)
 
319
{
 
320
        Q_UNUSED(previous);
 
321
        int col = current.column();     
 
322
        if(col < 0 || col >= d_table->columnCount()) return;
 
323
        setColumnForControlTabs(col);
 
324
}
 
325
 
 
326
void TableView::setColumnForControlTabs(int col)
 
327
{
 
328
        if(col < 0 || col >= d_table->columnCount()) return;
 
329
        Column *col_ptr = d_table->column(col);
 
330
 
 
331
        QString str = tr("Current column:\nName: %1\nPosition: %2")\
 
332
                .arg(col_ptr->name()).arg(col+1);
 
333
                
 
334
        ui.name_edit->setText(col_ptr->name());
 
335
        ui.comment_box->document()->setPlainText(col_ptr->comment());
 
336
        ui.type_box->setCurrentIndex(ui.type_box->findData((int)col_ptr->columnMode()));
 
337
        switch(col_ptr->columnMode()) {
 
338
                case SciDAVis::Numeric:
 
339
                        {
 
340
                                Double2StringFilter * filter = static_cast<Double2StringFilter*>(col_ptr->outputFilter());
 
341
                                ui.format_box->setCurrentIndex(ui.format_box->findData(filter->numericFormat()));
 
342
                                ui.digits_box->setValue(filter->numDigits());
 
343
                                break;
 
344
                        }
 
345
                case SciDAVis::Month:
 
346
                case SciDAVis::Day:
 
347
                case SciDAVis::DateTime:
 
348
                        {
 
349
                                DateTime2StringFilter * filter = static_cast<DateTime2StringFilter*>(col_ptr->outputFilter());
 
350
                                ui.format_box->setCurrentIndex(ui.format_box->findData(filter->format()));
 
351
                                break;
 
352
                        }
 
353
                default:
 
354
                        break;
 
355
        }
 
356
        ui.formula_box->setText(col_ptr->formula(0));
 
357
}
 
358
 
 
359
void TableView::handleAspectDescriptionChanged(const AbstractAspect * aspect)
 
360
{
 
361
        const Column * col = qobject_cast<const Column*>(aspect);
 
362
        if (!col || col->parentAspect() != static_cast<AbstractAspect*>(d_table))
 
363
                return;
 
364
        ui.add_reference_combobox->setItemText(d_table->columnIndex(col), "col(\"" + col->name() + "\")");
 
365
}
 
366
 
 
367
void TableView::handleAspectAdded(const AbstractAspect *aspect) {
 
368
        const Column * col = qobject_cast<const Column*>(aspect);
 
369
        if (!col || col->parentAspect() != static_cast<AbstractAspect*>(d_table))
 
370
                return;
 
371
        ui.add_reference_combobox->insertItem(d_table->indexOfChild(aspect), "col(\"" + col->name() + "\")");
 
372
}
 
373
 
 
374
void TableView::handleAspectAboutToBeRemoved(const AbstractAspect *parent, int index) {
 
375
        if (parent != d_table)
 
376
                return;
 
377
        ui.add_reference_combobox->removeItem(index);
 
378
}
 
379
 
 
380
void TableView::selectionChanged(const QItemSelection & selected, const QItemSelection & deselected)
 
381
{
 
382
        Q_UNUSED(selected);
 
383
        Q_UNUSED(deselected);
 
384
}
 
385
 
 
386
void TableView::updateFormatBox()
 
387
{
 
388
        int type_index = ui.type_box->currentIndex();
 
389
        if(type_index < 0) return; // should never happen
 
390
        ui.format_box->clear();
 
391
        ui.digits_box->setEnabled(false);
 
392
        switch(ui.type_box->itemData(type_index).toInt())
 
393
        {
 
394
                case SciDAVis::Numeric:
 
395
                        ui.digits_box->setEnabled(true);
 
396
                        ui.format_box->addItem(tr("Decimal"), QVariant('f'));
 
397
                        ui.format_box->addItem(tr("Scientific (e)"), QVariant('e'));
 
398
                        ui.format_box->addItem(tr("Scientific (E)"), QVariant('E'));
 
399
                        ui.format_box->addItem(tr("Automatic (e)"), QVariant('g'));
 
400
                        ui.format_box->addItem(tr("Automatic (E)"), QVariant('G'));
 
401
                        break;
 
402
                case SciDAVis::Text:
 
403
                        ui.format_box->addItem(tr("Text"), QVariant());
 
404
                        break;
 
405
                case SciDAVis::Month:
 
406
                        ui.format_box->addItem(tr("Number without leading zero"), QVariant("M"));
 
407
                        ui.format_box->addItem(tr("Number with leading zero"), QVariant("MM"));
 
408
                        ui.format_box->addItem(tr("Abbreviated month name"), QVariant("MMM"));
 
409
                        ui.format_box->addItem(tr("Full month name"), QVariant("MMMM"));
 
410
                        break;
 
411
                case SciDAVis::Day:
 
412
                        ui.format_box->addItem(tr("Number without leading zero"), QVariant("d"));
 
413
                        ui.format_box->addItem(tr("Number with leading zero"), QVariant("dd"));
 
414
                        ui.format_box->addItem(tr("Abbreviated day name"), QVariant("ddd"));
 
415
                        ui.format_box->addItem(tr("Full day name"), QVariant("dddd"));
 
416
                        break;
 
417
                case SciDAVis::DateTime:
 
418
                        {
 
419
                                // TODO: allow adding of the combo box entries here
 
420
                                const char * date_strings[] = {
 
421
                                        "yyyy-MM-dd",   
 
422
                                        "yyyy/MM/dd", 
 
423
                                        "dd/MM/yyyy", 
 
424
                                        "dd/MM/yy", 
 
425
                                        "dd.MM.yyyy",   
 
426
                                        "dd.MM.yy",
 
427
                                        "MM/yyyy",
 
428
                                        "dd.MM.", 
 
429
                                        "yyyyMMdd",
 
430
                                        0
 
431
                                };
 
432
 
 
433
                                const char * time_strings[] = {
 
434
                                        "hh",
 
435
                                        "hh ap",
 
436
                                        "hh:mm",
 
437
                                        "hh:mm ap",
 
438
                                        "hh:mm:ss",
 
439
                                        "hh:mm:ss.zzz",
 
440
                                        "hh:mm:ss:zzz",
 
441
                                        "mm:ss.zzz",
 
442
                                        "hhmmss",
 
443
                                        0
 
444
                                };
 
445
                                int j,i;
 
446
                                for(i=0; date_strings[i] != 0; i++)
 
447
                                        ui.format_box->addItem(QString(date_strings[i]), QVariant(date_strings[i]));
 
448
                                for(j=0; time_strings[j] != 0; j++)
 
449
                                        ui.format_box->addItem(QString(time_strings[j]), QVariant(time_strings[j]));
 
450
                                for(i=0; date_strings[i] != 0; i++)
 
451
                                        for(j=0; time_strings[j] != 0; j++)
 
452
                                                ui.format_box->addItem(QString("%1 %2").arg(date_strings[i]).arg(time_strings[j]), 
 
453
                                                        QVariant(QString(date_strings[i]) + " " + QString(time_strings[j])));
 
454
                                break;
 
455
                        }
 
456
                default:
 
457
                        ui.format_box->addItem(QString()); // just for savety to have at least one item in any case
 
458
        }
 
459
        ui.format_box->setCurrentIndex(0);
 
460
}
 
461
 
 
462
void TableView::updateTypeInfo()
 
463
{
 
464
        int format_index = ui.format_box->currentIndex();
 
465
        int type_index = ui.type_box->currentIndex();
 
466
 
 
467
        QString str = tr("Selected column type:\n");
 
468
        if(format_index >= 0 && type_index >= 0)
 
469
        {
 
470
                int type = ui.type_box->itemData(type_index).toInt();
 
471
                switch(type)
 
472
                {
 
473
                        case SciDAVis::Numeric:
 
474
                                str += tr("Double precision\nfloating point values\n");
 
475
                                ui.digits_box->setEnabled(true);
 
476
                                break;
 
477
                        case SciDAVis::Text:
 
478
                                str += tr("Text\n");
 
479
                                break;
 
480
                        case SciDAVis::Month:
 
481
                                str += tr("Month names\n");
 
482
                                break;
 
483
                        case SciDAVis::Day:
 
484
                                str += tr("Days of the week\n");
 
485
                                break;
 
486
                        case SciDAVis::DateTime:
 
487
                                str += tr("Dates and/or times\n");
 
488
                                break;
 
489
                }
 
490
                str += tr("Example: ");
 
491
                switch(type)
 
492
                {
 
493
                        case SciDAVis::Numeric:
 
494
                                str += QString::number(123.1234567890123456, ui.format_box->itemData(format_index).toChar().toLatin1(), ui.digits_box->value());
 
495
                                break;
 
496
                        case SciDAVis::Text:
 
497
                                str += tr("Hello world!\n");
 
498
                                break;
 
499
                        case SciDAVis::Month:
 
500
                                str += QLocale().toString(QDate(1900,1,1), ui.format_box->itemData(format_index).toString());
 
501
                                break;
 
502
                        case SciDAVis::Day:
 
503
                                str += QLocale().toString(QDate(1900,1,1), ui.format_box->itemData(format_index).toString());
 
504
                                break;
 
505
                        case SciDAVis::DateTime:
 
506
                                str += QDateTime(QDate(1900,1,1), QTime(23,59,59,999)).toString(ui.format_box->itemData(format_index).toString());
 
507
                                break;
 
508
                }
 
509
        }
 
510
        ui.type_info->setText(str);
 
511
}
 
512
 
 
513
void TableView::showControlDescriptionTab()
 
514
{
 
515
        d_control_tabs->setVisible(true);
 
516
        d_hide_button->setArrowType(Qt::RightArrow);
 
517
        ui.tab_widget->setCurrentIndex(0);
 
518
        ui.tab_widget->setFocus();
 
519
}
 
520
 
 
521
void TableView::showControlTypeTab()
 
522
{
 
523
        d_control_tabs->setVisible(true);
 
524
        d_hide_button->setArrowType(Qt::RightArrow);
 
525
        ui.tab_widget->setCurrentIndex(1);
 
526
        ui.tab_widget->setFocus();
 
527
}
 
528
 
 
529
void TableView::showControlFormulaTab()
 
530
{
 
531
        d_control_tabs->setVisible(true);
 
532
        d_hide_button->setArrowType(Qt::RightArrow);
 
533
        ui.tab_widget->setCurrentIndex(2);
 
534
        ui.tab_widget->setFocus();
 
535
}
 
536
 
 
537
void TableView::applyDescription()
 
538
{
 
539
        QItemSelectionModel * sel_model = d_view_widget->selectionModel();
 
540
        int index = sel_model->currentIndex().column();
 
541
        if(index >= 0)
 
542
        {
 
543
                // changing the name triggers an update of the UI, which also resets the content of the
 
544
                // comment box => need to cache it so name and comment can be changed simultaneously
 
545
                QString comment = ui.comment_box->document()->toPlainText();
 
546
                d_table->column(index)->setName(ui.name_edit->text());
 
547
                d_table->column(index)->setComment(comment);
 
548
        }
 
549
}
 
550
 
 
551
void TableView::applyType()
 
552
{
 
553
        int format_index = ui.format_box->currentIndex();
 
554
        int type_index = ui.type_box->currentIndex();
 
555
        if(format_index < 0 && type_index < 0) return;
 
556
 
 
557
        SciDAVis::ColumnMode mode = (SciDAVis::ColumnMode)ui.type_box->itemData(type_index).toInt();
 
558
        QList<Column*> list = selectedColumns();
 
559
        switch(mode)
 
560
        {
 
561
                case SciDAVis::Numeric:
 
562
                        foreach(Column* col, list)
 
563
                        {
 
564
                                col->setColumnMode(mode);
 
565
                                Double2StringFilter * filter = static_cast<Double2StringFilter*>(col->outputFilter());
 
566
                                int digits = ui.digits_box->value(); // setNumericFormat causes digits_box to be modified...
 
567
                                filter->setNumericFormat(ui.format_box->itemData(format_index).toChar().toLatin1());
 
568
                                filter->setNumDigits(digits);
 
569
                                // TODO: make sure this is done by a signal from the filter to the column on to the table
 
570
        //                      d_model->emitColumnChanged(col); 
 
571
                                }
 
572
                        break;
 
573
                case SciDAVis::Text:
 
574
                        foreach(Column* col, list)
 
575
                                col->setColumnMode(mode);
 
576
                        break;
 
577
                case SciDAVis::Month:
 
578
                case SciDAVis::Day:
 
579
                case SciDAVis::DateTime:
 
580
                        foreach(Column* col, list)
 
581
                        {
 
582
                                col->setColumnMode(mode);
 
583
                                DateTime2StringFilter * filter = static_cast<DateTime2StringFilter*>(col->outputFilter());
 
584
                                filter->setFormat(ui.format_box->itemData(format_index).toString());
 
585
                                // TODO: make sure this is done by a signal from the filter to the column on to the table
 
586
        //                      d_model->emitColumnChanged(col); 
 
587
                        }
 
588
                        break;
 
589
        }
 
590
}
 
591
                
 
592
void TableView::handleHeaderDataChanged(Qt::Orientation orientation, int first, int last)
 
593
{
 
594
        if(orientation != Qt::Horizontal) return;
 
595
 
 
596
        QItemSelectionModel * sel_model = d_view_widget->selectionModel();
 
597
 
 
598
        int col = sel_model->currentIndex().column();
 
599
        if(col < first || col > last) return;
 
600
        setColumnForControlTabs(col);
 
601
}
 
602
 
 
603
int TableView::selectedColumnCount(bool full)
 
604
{
 
605
        int count = 0;
 
606
        int cols = d_table->columnCount();
 
607
        for (int i=0; i<cols; i++)
 
608
                if(isColumnSelected(i, full)) count++;
 
609
        return count;
 
610
}
 
611
 
 
612
int TableView::selectedColumnCount(SciDAVis::PlotDesignation pd)
 
613
{
 
614
        int count = 0;
 
615
        int cols = d_table->columnCount();
 
616
        for(int i=0; i<cols; i++)
 
617
                if( isColumnSelected(i, false) && (d_table->column(i)->plotDesignation() == pd) ) count++;
 
618
 
 
619
        return count;
 
620
}
 
621
 
 
622
bool TableView::isColumnSelected(int col, bool full)
 
623
{
 
624
        if(full)
 
625
                return d_view_widget->selectionModel()->isColumnSelected(col, QModelIndex());
 
626
        else
 
627
                return d_view_widget->selectionModel()->columnIntersectsSelection(col, QModelIndex());
 
628
}
 
629
 
 
630
QList<Column*> TableView::selectedColumns(bool full)
 
631
{
 
632
        QList<Column*> list;
 
633
        int cols = d_table->columnCount();
 
634
        for (int i=0; i<cols; i++)
 
635
                if(isColumnSelected(i, full)) list << d_table->column(i);
 
636
 
 
637
        return list;
 
638
}
 
639
 
 
640
int TableView::selectedRowCount(bool full)
 
641
{
 
642
        int count = 0;
 
643
        int rows = d_table->rowCount();
 
644
        for (int i=0; i<rows; i++)
 
645
                if(isRowSelected(i, full)) count++;
 
646
        return count;
 
647
}
 
648
 
 
649
bool TableView::isRowSelected(int row, bool full)
 
650
{
 
651
        if(full)
 
652
                return d_view_widget->selectionModel()->isRowSelected(row, QModelIndex());
 
653
        else
 
654
                return d_view_widget->selectionModel()->rowIntersectsSelection(row, QModelIndex());
 
655
}
 
656
 
 
657
int TableView::firstSelectedColumn(bool full)
 
658
{
 
659
        int cols = d_table->columnCount();
 
660
        for (int i=0; i<cols; i++)
 
661
        {
 
662
                if(isColumnSelected(i, full))
 
663
                        return i;
 
664
        }
 
665
        return -1;
 
666
}
 
667
 
 
668
int TableView::lastSelectedColumn(bool full)
 
669
{
 
670
        int cols = d_table->columnCount();
 
671
        for(int i=cols-1; i>=0; i--)
 
672
                if(isColumnSelected(i, full)) return i;
 
673
 
 
674
        return -2;
 
675
}
 
676
 
 
677
int TableView::firstSelectedRow(bool full)
 
678
{
 
679
        int rows = d_table->rowCount();
 
680
        for (int i=0; i<rows; i++)
 
681
        {
 
682
                if(isRowSelected(i, full))
 
683
                        return i;
 
684
        }
 
685
        return -1;
 
686
}
 
687
 
 
688
int TableView::lastSelectedRow(bool full)
 
689
{
 
690
        int rows = d_table->rowCount();
 
691
        for(int i=rows-1; i>=0; i--)
 
692
                if(isRowSelected(i, full)) return i;
 
693
 
 
694
        return -2;
 
695
}
 
696
 
 
697
IntervalAttribute<bool> TableView::selectedRows(bool full) {
 
698
        IntervalAttribute<bool> result;
 
699
        int rows = d_table->rowCount();
 
700
        for (int i=0; i<rows; i++)
 
701
                if (isRowSelected(i, full))
 
702
                        result.setValue(i, true);
 
703
        return result;
 
704
}
 
705
 
 
706
bool TableView::isCellSelected(int row, int col)
 
707
{
 
708
        if(row < 0 || col < 0 || row >= d_table->rowCount() || col >= d_table->columnCount()) return false;
 
709
 
 
710
        return d_view_widget->selectionModel()->isSelected(d_model->index(row, col));
 
711
}
 
712
 
 
713
void TableView::setCellSelected(int row, int col, bool select)
 
714
{
 
715
         d_view_widget->selectionModel()->select(d_model->index(row, col), 
 
716
                         select ? QItemSelectionModel::Select : QItemSelectionModel::Deselect);
 
717
}
 
718
 
 
719
void TableView::setCellsSelected(int first_row, int first_col, int last_row, int last_col, bool select)
 
720
{
 
721
        QModelIndex top_left = d_model->index(first_row, first_col);
 
722
        QModelIndex bottom_right = d_model->index(last_row, last_col);
 
723
        d_view_widget->selectionModel()->select(QItemSelection(top_left, bottom_right), 
 
724
                        select ? QItemSelectionModel::SelectCurrent : QItemSelectionModel::Deselect);
 
725
}
 
726
 
 
727
void TableView::getCurrentCell(int * row, int * col)
 
728
{
 
729
        QModelIndex index = d_view_widget->selectionModel()->currentIndex();
 
730
        if(index.isValid()) 
 
731
        {
 
732
                *row = index.row();
 
733
                *col = index.column();
 
734
        }
 
735
        else
 
736
        {
 
737
                *row = -1;
 
738
                *col = -1;
 
739
        }
 
740
}
 
741
 
 
742
bool TableView::eventFilter(QObject * watched, QEvent * event)
 
743
{
 
744
        QHeaderView * v_header = d_view_widget->verticalHeader();
 
745
 
 
746
        if (event->type() == QEvent::ContextMenu) 
 
747
        {
 
748
                QContextMenuEvent *cm_event = static_cast<QContextMenuEvent *>(event);
 
749
                QPoint global_pos = cm_event->globalPos();
 
750
                if(watched == v_header) 
 
751
                        d_table->showTableViewRowContextMenu(global_pos);
 
752
                else if(watched == d_horizontal_header) {       
 
753
                        int col = d_horizontal_header->logicalIndexAt(cm_event->pos());
 
754
                        if (!isColumnSelected(col, true)) {
 
755
                                QItemSelectionModel * sel_model = d_view_widget->selectionModel();
 
756
                                sel_model->clearSelection();
 
757
                                sel_model->select(QItemSelection(d_model->index(0, col, QModelIndex()),
 
758
                                                        d_model->index(d_model->rowCount()-1, col, QModelIndex())),
 
759
                                                QItemSelectionModel::Select);
 
760
                        }
 
761
                        d_table->showTableViewColumnContextMenu(global_pos);
 
762
                } else if(watched == d_view_widget)
 
763
                        d_table->showTableViewContextMenu(global_pos);
 
764
                else
 
765
                        return MyWidget::eventFilter(watched, event);
 
766
 
 
767
                return true;
 
768
        } 
 
769
        else 
 
770
                return MyWidget::eventFilter(watched, event);
 
771
}
 
772
 
 
773
bool TableView::formulaModeActive() const 
 
774
 
775
        return d_model->formulaModeActive(); 
 
776
}
 
777
 
 
778
void TableView::activateFormulaMode(bool on) 
 
779
 
780
        d_model->activateFormulaMode(on); 
 
781
}
 
782
 
 
783
void TableView::goToNextColumn()
 
784
{
 
785
        if (d_table->columnCount() == 0) return;
 
786
 
 
787
        QModelIndex idx = d_view_widget->currentIndex();
 
788
        int col = idx.column()+1;
 
789
    if (col >= d_table->columnCount())
 
790
                col = 0;
 
791
        d_view_widget->setCurrentIndex(idx.sibling(idx.row(), col));
 
792
}
 
793
 
 
794
void TableView::goToPreviousColumn()
 
795
{
 
796
        if (d_table->columnCount() == 0) return;
 
797
 
 
798
        QModelIndex idx = d_view_widget->currentIndex();
 
799
        int col = idx.column()-1;
 
800
    if (col < 0)
 
801
                col = d_table->columnCount()-1;
 
802
        d_view_widget->setCurrentIndex(idx.sibling(idx.row(), col));
 
803
}
 
804
 
 
805
 
 
806
/* ================== TableViewWidget ================ */
 
807
 
 
808
void TableViewWidget::selectAll()
 
809
{
 
810
        // the original QTableView::selectAll() toggles all cells which is strange behavior IMHO - thzs
 
811
        QItemSelectionModel * sel_model = selectionModel();
 
812
        QItemSelection sel(model()->index(0, 0, QModelIndex()), model()->index(model()->rowCount()-1, 
 
813
                model()->columnCount()-1, QModelIndex()));
 
814
        sel_model->select(sel, QItemSelectionModel::Select);
 
815
}
 
816
 
 
817
void TableViewWidget::updateHeaderGeometry(Qt::Orientation o, int first, int last)
 
818
{
 
819
        Q_UNUSED(first)
 
820
        Q_UNUSED(last)
 
821
        if(o != Qt::Horizontal) return;
 
822
        horizontalHeader()->setStretchLastSection(true);  // ugly hack (flaw in Qt? Does anyone know a better way?)
 
823
        horizontalHeader()->updateGeometry();
 
824
        horizontalHeader()->setStretchLastSection(false); // ugly hack part 2
 
825
}
 
826
 
 
827
void TableViewWidget::keyPressEvent(QKeyEvent * event)
 
828
{
 
829
    if(event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter)
 
830
                emit advanceCell();
 
831
        QTableView::keyPressEvent(event);
 
832
}
 
833