00001 #include <qcheckbox.h>
00002 #include <qlabel.h>
00003 #include <qspinbox.h>
00004 #include <qlayout.h>
00005 #include <qlineedit.h>
00006 #include <qregexp.h>
00007 #include <qwhatsthis.h>
00008 #include <qtooltip.h>
00009 #include <qvalidator.h>
00010 #include <qpushbutton.h>
00011
00012 #include <kinputdialog.h>
00013 #include <klocale.h>
00014 #include <kdebug.h>
00015 #include <kmessagebox.h>
00016
00017 #include "kdchart/KDChartAxisParams.h"
00018 #include "kchart_params.h"
00019
00020 #include "kchartDataEditor.h"
00021 #include "kchartDataEditor.moc"
00022
00023 namespace KChart
00024 {
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 kchartDataSpinBox::kchartDataSpinBox(QWidget *parent)
00035 : QSpinBox(parent)
00036 {
00037 m_ignore = false;
00038 }
00039
00040
00041 kchartDataSpinBox::~kchartDataSpinBox()
00042 {
00043 }
00044
00045
00046 void kchartDataSpinBox::stepUp()
00047 {
00048 m_ignore = true;
00049 uint const new_value = value() + 1;
00050
00051 QSpinBox::stepUp();
00052 setValue(new_value);
00053
00054 emit valueChangedSpecial( value() );
00055 m_ignore = false;
00056 }
00057
00058
00059 void kchartDataSpinBox::stepDown()
00060 {
00061 m_ignore = true;
00062
00063 uint const new_value = value() - 1;
00064 QSpinBox::stepDown();
00065 setValue(new_value);
00066
00067 emit valueChangedSpecial( value() );
00068 m_ignore = false;
00069 }
00070
00071
00072 bool kchartDataSpinBox::eventFilter( QObject *obj, QEvent *ev )
00073 {
00074 if ( obj == editor() ) {
00075 if ( ev->type() == QEvent::FocusOut ) {
00076
00077 setValue(editor()->text().toInt());
00078
00079
00080
00081 if (!m_ignore)
00082 emit valueChangedSpecial( value() );
00083 }
00084 }
00085
00086
00087 return QSpinBox::eventFilter( obj, ev );
00088 }
00089
00090
00091
00092
00093
00094
00095
00096
00097 kchartDataTable::kchartDataTable(QWidget *parent)
00098 : QTable(parent)
00099 {
00100 }
00101
00102
00103 kchartDataTable::~kchartDataTable()
00104 {
00105 }
00106
00107
00108 bool kchartDataTable::eventFilter( QObject *obj, QEvent *ev )
00109 {
00110 if (ev->type() == QEvent::KeyPress && strcmp(obj->name(),
00111 "qt_tableeditor")==0 ) {
00112 QKeyEvent *e = (QKeyEvent *)ev;
00113
00114 switch ( e->key() ) {
00115 case Qt::Key_Up:
00116 {
00117 if ( currentRow() > 0 ) {
00118 setCurrentCell( currentRow()-1, currentColumn() );
00119 editCell(currentRow(), currentColumn() );
00120 return true;
00121 }
00122 break;
00123 }
00124 case Qt::Key_Down:
00125 {
00126 if ( currentRow() < numRows()-1 ) {
00127 setCurrentCell( currentRow()+1, currentColumn() );
00128 editCell(currentRow(), currentColumn() );
00129 return true;
00130 }
00131 break;
00132 }
00133 case Qt::Key_Right:
00134 {
00135 if ( currentColumn() < numCols()-1 ) {
00136 setCurrentCell( currentRow(), currentColumn()+1 );
00137 editCell(currentRow(), currentColumn() );
00138 return true;
00139 }
00140 break;
00141 }
00142 case Qt::Key_Left:
00143 {
00144 if ( currentColumn() > 0 ) {
00145 setCurrentCell( currentRow(), currentColumn()-1 );
00146 editCell(currentRow(), currentColumn() );
00147 return true;
00148 }
00149 break;
00150 }
00151 }
00152 }
00153
00154 return QTable::eventFilter( obj, ev );
00155 }
00156
00157
00158
00159
00160
00161
00162 #define COLUMNWIDTH 80
00163
00164 kchartDataEditor::kchartDataEditor(QWidget* parent) :
00165 KDialogBase(parent, "dataeditor", true, i18n("KChart Data Editor"),
00166 KDialogBase::Ok | KDialogBase::Cancel | KDialogBase::Apply,
00167 KDialogBase::Ok, true)
00168 {
00169 QWidget *page = new QWidget( this );
00170 setMainWidget(page);
00171
00172
00173 m_table = new kchartDataTable(page);
00174 m_table->setSelectionMode(QTable::NoSelection);
00175 m_table->setFocus();
00176 m_table->setRowMovingEnabled(true);
00177 m_table->setColumnMovingEnabled(true);
00178
00179
00180 m_rowsLA = new QLabel( i18n("# Rows:" ), page );
00181 m_rowsLA->resize( m_rowsLA->sizeHint() );
00182 m_rowsSB = new kchartDataSpinBox( page );
00183 m_rowsSB->resize( m_rowsSB->sizeHint() );
00184 m_rowsSB->setMinValue(1);
00185
00186
00187 m_colsLA = new QLabel( i18n("# Columns:" ), page );
00188 m_colsLA->resize( m_colsLA->sizeHint() );
00189 m_colsSB = new kchartDataSpinBox( page );
00190 m_colsSB->resize( m_colsSB->sizeHint() );
00191 m_colsSB->setMinValue(1);
00192
00193 #if 0
00194
00195 m_firstRowAsLabel = new QCheckBox( i18n( "First row as label" ), page);
00196 m_firstColAsLabel = new QCheckBox( i18n( "First column as label" ), page);
00197 #endif
00198
00199 QPushButton *insertRowButton = new QPushButton( i18n("Insert Row") , page);
00200 connect( insertRowButton, SIGNAL( clicked() ),
00201 this, SLOT( insertRow() ) );
00202
00203 QPushButton *insertColButton = new QPushButton( i18n("Insert Column") , page);
00204 connect( insertColButton, SIGNAL( clicked() ),
00205 this, SLOT( insertColumn() ) );
00206
00207 QPushButton* removeRowButton = new QPushButton( i18n("Remove Row") , page);
00208 connect( removeRowButton, SIGNAL( clicked() ),
00209 this, SLOT( removeCurrentRow() ) );
00210
00211 QPushButton* removeColButton = new QPushButton( i18n("Remove Column") , page);
00212 connect( removeColButton, SIGNAL( clicked() ),
00213 this, SLOT( removeCurrentColumn() ) );
00214
00215
00216
00217 QVBoxLayout *topLayout = new QVBoxLayout( page );
00218
00219 QHBoxLayout* insertRemoveLayout = new QHBoxLayout( );
00220
00221 insertRemoveLayout->setSpacing(5);
00222 insertRemoveLayout->addWidget(insertRowButton);
00223 insertRemoveLayout->addWidget(insertColButton);
00224 insertRemoveLayout->addWidget(removeRowButton);
00225 insertRemoveLayout->addWidget(removeColButton);
00226 insertRemoveLayout->addStretch(1);
00227
00228 topLayout->addLayout(insertRemoveLayout);
00229 topLayout->addSpacing(10);
00230
00231
00232 topLayout->addWidget(m_table);
00233
00234
00235 QHBoxLayout *hbl1 = new QHBoxLayout( );
00236 hbl1->addWidget(m_rowsLA);
00237 hbl1->addWidget(m_rowsSB);
00238 hbl1->addSpacing(20);
00239 hbl1->addWidget(m_colsLA);
00240 hbl1->addWidget(m_colsSB);
00241 hbl1->addStretch(1);
00242 hbl1->setMargin(10);
00243 topLayout->addLayout(hbl1);
00244
00245 #if 0
00246 QHBoxLayout *hbl2 = new QHBoxLayout( );
00247 hbl2->addWidget(m_firstRowAsLabel);
00248 hbl2->addWidget(m_firstColAsLabel);
00249 hbl2->addStretch(1);
00250 hbl2->setMargin(10);
00251 topLayout->addLayout(hbl2);
00252 #endif
00253
00254 topLayout->setStretchFactor(m_table, 1);
00255 topLayout->setStretchFactor(insertRemoveLayout,1);
00256
00257
00258 connect(m_rowsSB, SIGNAL(valueChangedSpecial(int)),
00259 this, SLOT(setRows(int)));
00260 connect(m_colsSB, SIGNAL(valueChangedSpecial(int)),
00261 this, SLOT(setCols(int)));
00262
00263
00264
00265 #if 0
00266
00267
00268
00269 connect(m_table->horizontalHeader(), SIGNAL(clicked(int)),
00270 this, SLOT(column_clicked(int)) );
00271 connect(m_table->verticalHeader(), SIGNAL(clicked(int)),
00272 this, SLOT(row_clicked(int)) );
00273 #endif
00274
00275 connect(m_table, SIGNAL(valueChanged(int, int)),
00276 this, SLOT(tableChanged(int, int)) );
00277
00278
00279
00280
00281 m_userWantsToShrink = false;
00282
00283
00284 m_modified = false;
00285
00286
00287 addDocs();
00288 }
00289
00290
00291
00292
00293 void kchartDataEditor::addDocs()
00294 {
00295
00296 QString rowwhatsthis = i18n("<p><b>Sets the number of rows in the data table."
00297 "</b><br><br>Each row represents one data set.</p>");
00298 QToolTip::add(m_rowsSB, i18n("Number of active data rows"));
00299 QWhatsThis::add(m_rowsLA, rowwhatsthis);
00300 QWhatsThis::add(m_rowsSB, rowwhatsthis);
00301
00302
00303 QString colwhatsthis = i18n("<p><b>Sets the number of columns in the data table."
00304 "</b><br><br>The number of columns defines the number of data values in each data set (row).</p>");
00305 QToolTip::add(m_colsSB, i18n("Number of active data columns"));
00306 QWhatsThis::add(m_colsLA, colwhatsthis);
00307 QWhatsThis::add(m_colsSB, colwhatsthis);
00308
00309
00310 QToolTip::add(m_table, i18n("Chart data table."));
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331 #if 0
00332 QWhatsThis::add(m_table, i18n("<p>This table contains the data"
00333 " for the chart.<br><br> Each row is one data set of values."
00334 " The name of such a data set can be changed in the column header (on the left)"
00335 " of the table. In a line diagram each row is one line. In a ring diagram each row"
00336 " is one slice. <br><br> Each column represents one value of each data set."
00337 " Just like rows you can also change the name of each value in the"
00338 " column headers (at the top) of the table. In a bar diagram the number"
00339 " of columns defines the number of value sets. In a ring diagram each"
00340 " column is one ring.</p>"));
00341 #endif
00342 }
00343
00344
00345
00346
00347
00348
00349
00350 void kchartDataEditor::setData( KChartParams *params, KDChartTableData *dat )
00351 {
00352 unsigned int rowsCount;
00353 unsigned int colsCount;
00354
00355
00356 if ( dat->usedRows() == 0 && dat->usedCols() == 0) {
00357 rowsCount = dat->rows();
00358 colsCount = dat->cols();
00359 }
00360 else {
00361 rowsCount = dat->usedRows();
00362 colsCount = dat->usedCols();
00363 }
00364
00365
00366 if ( rowsCount==0 && colsCount==0 ) {
00367 m_table->setNumRows(1);
00368 m_table->setNumCols(1);
00369 resize(600, 300);
00370 return;
00371 }
00372
00373 rowsCount += headerRows();
00374 colsCount += headerCols();
00375
00376
00377 m_rowsSB->setValue(rowsCount);
00378 m_colsSB->setValue(colsCount);
00379 #if 0
00380 m_firstRowAsLabel->setChecked( params->firstRowAsLabel() );
00381 m_firstColAsLabel->setChecked( params->firstColAsLabel() );
00382 #endif
00383 m_table->setNumRows(rowsCount);
00384 m_table->setNumCols(colsCount);
00385
00386
00387 for (unsigned int row = headerRows(); row < rowsCount; row++) {
00388 for (unsigned int col = headerCols(); col < colsCount; col++) {
00389 QVariant t = dat->cellVal(row-headerRows(), col-headerCols());
00390
00391
00392
00393 if (t.isValid()) {
00394 if ( t.type() == QVariant::Double ) {
00395 m_table->setText(row, col,
00396 QString("%1").arg(t.toDouble()));
00397 }
00398 else if ( t.type() == QVariant::String )
00399 kdDebug(35001) << "I cannot handle strings in the table yet"
00400 << endl;
00401 else {
00402
00403 }
00404 }
00405 }
00406 }
00407
00408
00409 for (unsigned int col = 0; col < colsCount + 1; col++)
00410 m_table->setColumnWidth(col, COLUMNWIDTH);
00411
00412
00413 resize(600, 300);
00414 }
00415
00416
00417
00418
00419 void kchartDataEditor::getData( KChartParams *params, KDChartTableData *dat )
00420 {
00421
00422 int labelRows = headerRows();
00423
00424 int labelCols = headerCols();
00425
00426 int numRows = m_table->numRows()-labelRows;
00427 int numCols = m_table->numCols()-labelCols;
00428
00429
00430
00431 if ( static_cast<int>( dat->rows() ) < numRows
00432 || static_cast<int>( dat->cols() ) < numCols )
00433 dat->expand( numRows, numCols );
00434
00435 dat->setUsedRows( numRows );
00436 dat->setUsedCols( numCols );
00437
00438
00439 #if 0
00440 if ( numRows==1 && numCols==1 && m_table->horizontalHeader()->label(0).isEmpty()
00441 && m_table->verticalHeader()->label(0).isEmpty()
00442 && m_table->text(0, 0).isEmpty() ) {
00443 dat->expand(0,0);
00444 return;
00445 }
00446 #endif
00447
00448
00449 for (int row = labelRows ; row < (numRows+labelRows); row++) {
00450 for (int col = labelCols ; col < (numCols+labelCols); col++) {
00451
00452
00453 QString tmp = m_table->text(row, col);
00454 bool bOk;
00455 double val = tmp.toDouble( &bOk );
00456 if (!bOk)
00457 val = 0.0;
00458
00459
00460 dat->setCell(row-labelRows,col-labelCols, val);
00461 }
00462 }
00463
00464 #if 0
00465 params->setFirstRowAsLabel( m_firstRowAsLabel->isChecked() );
00466 params->setFirstColAsLabel( m_firstColAsLabel->isChecked() );
00467 #endif
00468 }
00469
00470
00471
00472
00473 void kchartDataEditor::setRowLabels(const QStringList &rowLabels)
00474 {
00475 #if 0
00476 QHeader *rowHeader = m_table->verticalHeader();
00477 int row;
00478 int numRows = m_rowsSB->value();
00479
00480 rowHeader->setLabel(0, "");
00481 if ( numRows==1 && m_colsSB->value()==1 && m_table->text(0, 0).isEmpty() )
00482 return;
00483 for (row = 0; row < numRows; row++) {
00484 rowHeader->setLabel(row, rowLabels[row]);
00485 }
00486 #endif
00487
00488 for (unsigned int i=0; i < rowLabels.count(); i++) {
00489 m_table->setText(i + headerRows(), 0, rowLabels[i]);
00490 }
00491
00492 updateRowHeaders();
00493 }
00494
00495
00496 int kchartDataEditor::headerRows()
00497 {
00498 return 1;
00499 }
00500
00501 int kchartDataEditor::headerCols()
00502 {
00503 return 1;
00504 }
00505
00506
00507
00508
00509 void kchartDataEditor::getRowLabels(QStringList &rowLabels)
00510 {
00511 #if 0
00512 QHeader *rowHeader = m_table->verticalHeader();
00513 int numRows = m_rowsSB->value();
00514 int row;
00515
00516 rowLabels.clear();
00517 for (row = 0; row < numRows; row++) {
00518 rowLabels << rowHeader->label(row);
00519 }
00520 #endif
00521 rowLabels.clear();
00522
00523 for (int i=headerRows();i < m_table->numRows();i++)
00524 {
00525 rowLabels << m_table->text(i,0);
00526 }
00527 }
00528
00529
00530
00531
00532 void kchartDataEditor::setColLabels(const QStringList &colLabels)
00533 {
00534 #if 0
00535 QHeader *colHeader = m_table->horizontalHeader();
00536 int col;
00537
00538 int numCols = m_colsSB->value();
00539
00540 colHeader->setLabel(0, "");
00541 if ( m_rowsSB->value()==1 && numCols==1 && m_table->text(0, 0).isEmpty() )
00542 return;
00543 for (col = 0; col < numCols; col++) {
00544 colHeader->setLabel(col, colLabels[col]);
00545 }
00546 #endif
00547
00548 for (unsigned int i = 0; i < colLabels.count(); i++)
00549 {
00550 m_table->setText(0,i+headerCols(),colLabels[i]);
00551 }
00552
00553 updateColHeaders();
00554 }
00555
00556
00557
00558
00559 void kchartDataEditor::getColLabels(QStringList &colLabels)
00560 {
00561 #if 0
00562 QHeader *colHeader = m_table->horizontalHeader();
00563 int numCols = m_colsSB->value();
00564 int col;
00565
00566 colLabels.clear();
00567 for (col = 0; col < numCols; col++) {
00568 colLabels << colHeader->label(col);
00569 }
00570 #endif
00571
00572 colLabels.clear();
00573
00574 for (int i = headerCols(); i < m_table->numCols(); i++) {
00575 colLabels << m_table->text(0, i);
00576 }
00577 }
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587 void kchartDataEditor::removeCurrentRow()
00588 {
00589 int row = m_table->currentRow();
00590
00591 m_table->removeRow(row);
00592 m_rowsSB->setValue(m_table->numRows());
00593
00594 if (row == 0)
00595 updateColHeaders();
00596
00597 m_modified = true;
00598 }
00599
00600 void kchartDataEditor::removeCurrentColumn()
00601 {
00602 int col = m_table->currentColumn();
00603
00604 m_table->removeColumn(col);
00605 m_colsSB->setValue(m_table->numCols());
00606
00607 if (col == 0)
00608 updateRowHeaders();
00609
00610 m_modified = true;
00611 }
00612
00613 void kchartDataEditor::insertColumn()
00614 {
00615 m_table->insertColumns(m_table->currentColumn() + 1, 1);
00616 m_colsSB->setValue(m_table->numCols());
00617 updateColHeaders();
00618
00619 m_modified = true;
00620 }
00621
00622 void kchartDataEditor::insertRow()
00623 {
00624 m_table->insertRows(m_table->currentRow() + 1, 1);
00625 m_rowsSB->setValue(m_table->numRows());
00626 updateRowHeaders();
00627
00628 m_modified = true;
00629 }
00630
00631
00632
00633
00634
00635 static int askUserForConfirmation(QWidget *parent)
00636 {
00637 return KMessageBox::warningContinueCancel(parent,
00638 i18n("You are about to shrink the data table and remove some values. "
00639 "This will lead to loss of existing data in the table "
00640 "and/or the headers.\n\n"
00641 "This message will not be shown again if you click Continue"));
00642 }
00643
00644
00645
00646
00647 void kchartDataEditor::setRows(int rows)
00648 {
00649 kdDebug(35001) << "setRows called: rows = " << rows << endl;;
00650
00651
00652
00653 if (rows < 1) {
00654 m_rowsSB->setValue(1);
00655 return;
00656 }
00657
00658 int old_rows = m_table->numRows();
00659 if (rows > old_rows) {
00660 m_table->setNumRows(rows);
00661
00662
00663 for (int i = old_rows; i < rows; i++)
00664 m_table->verticalHeader()->setLabel(i, "");
00665
00666 m_modified = true;
00667 }
00668 else if (rows < m_table->numRows()) {
00669 bool ask_user = false;
00670
00671
00672 for (int col=0; col<m_table->numCols(); col++) {
00673 if (!m_table->text(rows, col).isEmpty()) {
00674 ask_user = true;
00675 break;
00676 }
00677 }
00678
00679
00680 if ( ask_user && !m_userWantsToShrink
00681 && askUserForConfirmation(this) == KMessageBox::Cancel) {
00682
00683
00684 m_rowsSB->setValue(m_table->numRows());
00685 return;
00686 }
00687
00688
00689 if (ask_user)
00690 m_userWantsToShrink = true;
00691
00692
00693 m_table->setNumRows(rows);
00694
00695 m_modified = true;
00696 }
00697 }
00698
00699
00700
00701
00702 void kchartDataEditor::setCols(int cols)
00703 {
00704 kdDebug(35001) << "setCols called: cols = " << cols << endl;;
00705
00706
00707
00708 if (cols < 1) {
00709 m_colsSB->setValue(1);
00710 return;
00711 }
00712
00713 int old_cols = m_table->numCols();
00714 if (cols > old_cols) {
00715 m_table->setNumCols(cols);
00716
00717
00718 for (int i = old_cols; i < cols; i++) {
00719 m_table->horizontalHeader()->setLabel(i, "");
00720 m_table->setColumnWidth(i, COLUMNWIDTH);
00721 }
00722
00723 m_modified = true;
00724 }
00725 else if (cols < m_table->numCols()) {
00726 bool ask_user = false;
00727
00728
00729 for (int row=0; row<m_table->numRows(); row++) {
00730 if (!m_table->text(row, cols).isEmpty()) {
00731 ask_user = true;
00732 break;
00733 }
00734 }
00735
00736
00737 if (ask_user && !m_userWantsToShrink
00738 && askUserForConfirmation(this) == KMessageBox::Cancel) {
00739
00740
00741 m_colsSB->setValue(m_table->numCols());
00742 return;
00743 }
00744
00745
00746 if (ask_user)
00747 m_userWantsToShrink = true;
00748
00749
00750 m_table->setNumCols(cols);
00751
00752 m_modified = true;
00753 }
00754 }
00755
00756
00757
00758
00759 #if 0 // Disabled since the first row / column now contains the labels.
00760 void kchartDataEditor::column_clicked(int column)
00761 {
00762 bool ok;
00763 QString name = KInputDialog::getText(i18n("Column Name"),
00764 i18n("Type a new column name:"),
00765 m_table->horizontalHeader()->label(column),
00766 &ok, this, 0, new QRegExpValidator(QRegExp(".*"), this) );
00767
00768
00769 if ( ok ) {
00770 m_table->horizontalHeader()->setLabel(column, name);
00771 m_modified = true;
00772 }
00773 }
00774
00775
00776
00777
00778 void kchartDataEditor::row_clicked(int row)
00779 {
00780 bool ok;
00781 QString name = KInputDialog::getText(i18n("Row Name"),
00782 i18n("Type a new row name:"),
00783 m_table->verticalHeader()->label(row),
00784 &ok, this, 0, new QRegExpValidator(QRegExp(".*"), this) );
00785
00786
00787 if ( ok ) {
00788 m_table->verticalHeader()->setLabel(row, name);
00789 m_modified = true;
00790 }
00791 }
00792 #endif
00793
00794
00795 void kchartDataEditor::tableChanged(int row, int col)
00796 {
00797 if (row <= headerRows())
00798 updateColHeaders();
00799 if (col <= headerCols())
00800 updateRowHeaders();
00801
00802 m_modified = true;
00803 }
00804
00805 void kchartDataEditor::updateRowHeaders()
00806 {
00807 for (int i=0;i<m_table->numRows();i++)
00808 {
00809 QHeader* header=m_table->verticalHeader();
00810
00811 QString tableCellText=m_table->text(i,0);
00812
00813 if (tableCellText == QString::null)
00814 tableCellText=QString("");
00815
00816 header->setLabel(header->mapToSection(i),tableCellText);
00817 }
00818 }
00819
00820 void kchartDataEditor::updateColHeaders()
00821 {
00822 for (int i=0;i<m_table->numCols();i++)
00823 {
00824 QHeader* header=m_table->horizontalHeader();
00825
00826 QString tableCellText=m_table->text(0,i);
00827
00828 if (tableCellText == QString::null)
00829 tableCellText=QString("");
00830
00831 header->setLabel(header->mapToSection(i),tableCellText);
00832 }
00833 }
00834
00835
00836
00837
00838
00839
00840 void kchartDataEditor::slotApply()
00841 {
00842 emit applyClicked(this);
00843 }
00844
00845
00846 }