kchart

kchartDataEditor.cc

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 //                    Class kchartDataSpinBox
00029 
00030 
00031 // We don't provide very much generality, since this spinbox is used
00032 // here and here only.
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             //kdDebug() << "Focus out" << endl;
00077             setValue(editor()->text().toInt());
00078 
00079             // Don't emit valueChangedSpecial(int) twice when
00080             // stepUp/stepDown has been called
00081             if (!m_ignore)
00082                 emit valueChangedSpecial( value() );
00083         }
00084     }
00085  
00086     // Pass the event on to the parent class.
00087     return QSpinBox::eventFilter( obj, ev );
00088 }
00089 
00090 
00091 // ================================================================
00092 //                    Class kchartDataTable
00093 
00094 
00095 // Used for the keyboard navigation
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 //                    Class kchartDataEditor
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     // Create the main table.
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     // Create the Rows setting
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     // Create the columns setting
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     // The row/column as label checkboxes. 
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     //Buttons for Inserting / Removing rows & columns 
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     // Start the layout.  The buttons are at the top.
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     // The table is below the buttons.
00232     topLayout->addWidget(m_table);
00233 
00234     // Then, a horizontal layer with the rows and columns settings
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     // Connect signals from the spin boxes.
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     // -- Changed data editor to use top row and leftmost column for
00267     //    series names and labels so this is no longer necessary.
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     // At first, assume that any shrinking of the table is a mistake.
00279     // A confirmation dialog will make sure that the user knows what
00280     // (s)he is doing.
00281     m_userWantsToShrink = false;
00282 
00283     // The data is not modified at the start.
00284     m_modified          = false;
00285 
00286     // Add tooltips and WhatsThis help.
00287     addDocs();
00288 }
00289 
00290 
00291 // Add Tooltips and WhatsThis help to various parts of the Data Editor.
00292 //
00293 void kchartDataEditor::addDocs()
00294 {
00295     // The rows settings.
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     // The columns settings.
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     // The table.
00310     QToolTip::add(m_table, i18n("Chart data table."));
00311     
00312     //GUI
00313     //The QWhatsThis information below is incorrect since the way that the contents of the table
00314     //are displayed in the chart depends upon the data format selected (which can be 
00315     //either "Data in columns" (default) or "Data in rows)
00316     //The names of the data sets / axes labels are no longer set by clicking on the table 
00317     //headers - since that was slow to work with and did not allow for keyboard input. 
00318     //Instead the names are taken from the topmost row and leftmost column.  
00319     //
00320     //eg:       Month | Sales 
00321     //          Jan   | 105
00322     //          Feb   | 117
00323     //          March | 120
00324     //
00325     //The captions of the header are automatically set to the names of the cells in the topmost row
00326     //and leftmost column.  This means that if you have more data than will fit in the visible area,
00327     //you can still see the column names or row names when the table has been scrolled.
00328     //KSpread could use some functionality like this as well.
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 // Set the data in the data editor.
00346 //
00347 // The data is taken from the KDChart data.  This method is never
00348 // called when the chart is a part of a spreadsheet.
00349 //
00350 void kchartDataEditor::setData( KChartParams *params, KDChartTableData *dat )
00351 {
00352     unsigned int  rowsCount;
00353     unsigned int  colsCount;
00354 
00355     // Get the correct number of rows and columns.
00356     if ( dat->usedRows() == 0 && dat->usedCols() == 0) { // Data from KSpread
00357         rowsCount = dat->rows();
00358         colsCount = dat->cols();
00359     }
00360     else {
00361         rowsCount = dat->usedRows();
00362         colsCount = dat->usedCols();
00363     }
00364 
00365     // Empty table
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     // Initiate widgets with the correct rows and columns.
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     // Fill the data from the chart into the editor.
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             // Fill it in from the part.
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                     // nothing on purpose
00403                 }
00404             }
00405         }
00406     }
00407 
00408     // Set column widths.  The default is a little too wide.
00409     for (unsigned int col = 0; col < colsCount + 1; col++) 
00410     m_table->setColumnWidth(col, COLUMNWIDTH);
00411 
00412     // and resize the widget to a good size.
00413     resize(600, 300);
00414 }
00415 
00416 
00417 // Get the data from the data editor and put it back into the chart.
00418 //
00419 void kchartDataEditor::getData( KChartParams *params, KDChartTableData *dat )
00420 {   
00421     //Number of rows used as headers
00422     int labelRows = headerRows();
00423     //Number of columns used as headers 
00424     int labelCols = headerCols();
00425     
00426     int  numRows = m_table->numRows()-labelRows;
00427     int  numCols = m_table->numCols()-labelCols;
00428     
00429     // Make sure that the data table for the chart is not smaller than
00430     // the data in the editor.
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     // Empty table
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     // Get all the data.
00449     for (int row = labelRows ; row < (numRows+labelRows); row++) {
00450         for (int col = labelCols ; col < (numCols+labelCols); col++) {
00451 
00452             // Get the text and convert to double.
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             // and do the actual setting.
00459             //t = KoChart::Value( val );
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 // Set the row labels in the data editor.
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 // Get the row labels from the data editor.
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 // Set the column labels in the data editor.
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 // Get the column labels from the data editor.
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 //                              Slots
00582 
00583 
00584 // Slots for the buttons that insert/remove rows/columns.
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 // Ask user to make sure that (s)he really wants to remove a row or
00633 // column.
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 // This slot is called when the spinbox for rows is changed.
00646 //
00647 void kchartDataEditor::setRows(int rows)
00648 {
00649     kdDebug(35001) << "setRows called: rows = " << rows << endl;;
00650 
00651     // Sanity check.  This should never happen since the spinbox has a
00652     // minvalue of 1, but just to be sure...
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     // Default value for the new rows: empty string
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     // Check if the last row is empty.
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     // If it is not, ask if the user really wants to shrink the table.
00680     if ( ask_user && !m_userWantsToShrink
00681         && askUserForConfirmation(this) == KMessageBox::Cancel) {
00682 
00683         // The user aborts.  Reset the number of rows and return.
00684         m_rowsSB->setValue(m_table->numRows());
00685         return;
00686     }
00687 
00688     // Record the fact that the user knows what (s)he is doing.
00689     if (ask_user)
00690         m_userWantsToShrink = true;
00691 
00692     // Do the actual shrinking.
00693     m_table->setNumRows(rows);
00694 
00695     m_modified = true;
00696     }
00697 }
00698 
00699 
00700 // This slot is called when the spinbox for columns is changed.
00701 //
00702 void kchartDataEditor::setCols(int cols)
00703 {
00704     kdDebug(35001) << "setCols called: cols = " << cols << endl;;
00705 
00706     // Sanity check.  This should never happen since the spinbox has a
00707     // minvalue of 1, but just to be sure...
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     // Default value for the new columns: empty string.
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     // Check if the last column is empty.
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     // If it is not, ask if the user really wants to shrink the table.
00737     if (ask_user && !m_userWantsToShrink
00738         && askUserForConfirmation(this) == KMessageBox::Cancel) {
00739 
00740         // The user aborts.  Reset the number of rows and return.
00741         m_colsSB->setValue(m_table->numCols());
00742         return;
00743     }
00744 
00745     // Record the fact that the user knows what (s)he is doing.
00746     if (ask_user)
00747         m_userWantsToShrink = true;
00748 
00749     // Do the actual shrinking.
00750     m_table->setNumCols(cols);
00751 
00752     m_modified = true;
00753     }
00754 }
00755 
00756 
00757 // Get the new name for a column header.
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     // Rename the column.
00769     if ( ok ) {
00770     m_table->horizontalHeader()->setLabel(column, name);
00771     m_modified = true;
00772     }
00773 }
00774 
00775 
00776 // Get the new name for a row header.
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     // Rename the row.
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 // This is a reimplementation of a slot defined in KDialogBase.  The
00837 // reason for the reimplementation is that we need to emit the signal
00838 // with a pointer to this so that we can get the data.
00839 //
00840 void kchartDataEditor::slotApply()
00841 {
00842     emit applyClicked(this);
00843 }
00844 
00845 
00846 }  //KChart namespace
KDE Home | KDE Accessibility Home | Description of Access Keys