summaryrefslogtreecommitdiffstats
path: root/kchart/kchartDataEditor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kchart/kchartDataEditor.cpp')
-rw-r--r--kchart/kchartDataEditor.cpp900
1 files changed, 900 insertions, 0 deletions
diff --git a/kchart/kchartDataEditor.cpp b/kchart/kchartDataEditor.cpp
new file mode 100644
index 000000000..8f08dd78b
--- /dev/null
+++ b/kchart/kchartDataEditor.cpp
@@ -0,0 +1,900 @@
+#include <tqcheckbox.h>
+#include <tqlabel.h>
+#include <tqspinbox.h>
+#include <tqlayout.h>
+#include <tqlineedit.h>
+#include <tqregexp.h>
+#include <tqwhatsthis.h>
+#include <tqtooltip.h>
+#include <tqvalidator.h>
+#include <tqpushbutton.h>
+
+#include <kinputdialog.h>
+#include <tdelocale.h>
+#include <kdebug.h>
+#include <tdemessagebox.h>
+#include <kiconloader.h>
+
+#include "kdchart/KDChartAxisParams.h"
+#include "kchart_params.h"
+#include "kchart_factory.h"
+
+#include "kchartDataEditor.h"
+#include "kchartDataEditor.moc"
+
+namespace KChart
+{
+
+
+// ================================================================
+// Class kchartDataSpinBox
+
+
+// We don't provide very much generality, since this spinbox is used
+// here and here only.
+//
+kchartDataSpinBox::kchartDataSpinBox(TQWidget *parent)
+ : TQSpinBox(parent)
+{
+ m_ignore = false;
+}
+
+
+kchartDataSpinBox::~kchartDataSpinBox()
+{
+}
+
+
+void kchartDataSpinBox::stepUp()
+{
+ m_ignore = true;
+ uint const new_value = value() + 1;
+
+ TQSpinBox::stepUp();
+ setValue(new_value);
+
+ emit valueChangedSpecial( value() );
+ m_ignore = false;
+}
+
+
+void kchartDataSpinBox::stepDown()
+{
+ m_ignore = true;
+
+ uint const new_value = value() - 1;
+ TQSpinBox::stepDown();
+ setValue(new_value);
+
+ emit valueChangedSpecial( value() );
+ m_ignore = false;
+}
+
+
+bool kchartDataSpinBox::eventFilter( TQObject *obj, TQEvent *ev )
+{
+ if ( TQT_BASE_OBJECT(obj) == TQT_BASE_OBJECT(editor()) ) {
+ if ( ev->type() == TQEvent::FocusOut ) {
+ //kdDebug() << "Focus out" << endl;
+ setValue(editor()->text().toInt());
+
+ // Don't emit valueChangedSpecial(int) twice when
+ // stepUp/stepDown has been called
+ if (!m_ignore)
+ emit valueChangedSpecial( value() );
+ }
+ }
+
+ // Pass the event on to the parent class.
+ return TQSpinBox::eventFilter( obj, ev );
+}
+
+
+// ================================================================
+// Class kchartDataTable
+
+
+// Used for the keyboard navigation
+//
+kchartDataTable::kchartDataTable(TQWidget *parent)
+ : TQTable(parent)
+{
+}
+
+
+kchartDataTable::~kchartDataTable()
+{
+}
+
+
+bool kchartDataTable::eventFilter( TQObject *obj, TQEvent *ev )
+{
+ if (ev->type() == TQEvent::KeyPress && strcmp(obj->name(),
+ "qt_tableeditor")==0 ) {
+ TQKeyEvent *e = (TQKeyEvent *)ev;
+
+ switch ( e->key() ) {
+ case TQt::Key_Up:
+ {
+ if ( currentRow() > 0 ) {
+ setCurrentCell( currentRow()-1, currentColumn() );
+ editCell(currentRow(), currentColumn() );
+ return true;
+ }
+ break;
+ }
+ case TQt::Key_Down:
+ {
+ if ( currentRow() < numRows()-1 ) {
+ setCurrentCell( currentRow()+1, currentColumn() );
+ editCell(currentRow(), currentColumn() );
+ return true;
+ }
+ break;
+ }
+ case TQt::Key_Right:
+ {
+ if ( currentColumn() < numCols()-1 ) {
+ setCurrentCell( currentRow(), currentColumn()+1 );
+ editCell(currentRow(), currentColumn() );
+ return true;
+ }
+ break;
+ }
+ case TQt::Key_Left:
+ {
+ if ( currentColumn() > 0 ) {
+ setCurrentCell( currentRow(), currentColumn()-1 );
+ editCell(currentRow(), currentColumn() );
+ return true;
+ }
+ break;
+ }
+ }
+ }
+
+ return TQTable::eventFilter( obj, ev );
+}
+
+
+// ================================================================
+// Class kchartDataEditor
+
+
+#define COLUMNWIDTH 80
+
+kchartDataEditor::kchartDataEditor(TQWidget* parent) :
+ KDialogBase(parent, "dataeditor", true, i18n("KChart Data Editor"),
+ KDialogBase::Ok | KDialogBase::Cancel | KDialogBase::Apply,
+ KDialogBase::Ok, true)
+{
+ TQWidget *page = new TQWidget( this );
+ setMainWidget(page);
+
+ // Create the main table.
+ m_table = new kchartDataTable(page);
+ m_table->setSelectionMode(TQTable::NoSelection);
+ m_table->setFocus();
+ m_table->setRowMovingEnabled(true);
+ m_table->setColumnMovingEnabled(true);
+
+ connect( m_table, TQT_SIGNAL( currentChanged(int, int) ),
+ this, TQT_SLOT( currentChanged(int, int) ) );
+
+ // Create the Rows setting
+ m_rowsLA = new TQLabel( i18n("# Rows:" ), page );
+ m_rowsLA->resize( m_rowsLA->sizeHint() );
+ m_rowsSB = new kchartDataSpinBox( page );
+ m_rowsSB->resize( m_rowsSB->sizeHint() );
+ m_rowsSB->setMinValue(1);
+
+ // Create the columns setting
+ m_colsLA = new TQLabel( i18n("# Columns:" ), page );
+ m_colsLA->resize( m_colsLA->sizeHint() );
+ m_colsSB = new kchartDataSpinBox( page );
+ m_colsSB->resize( m_colsSB->sizeHint() );
+ m_colsSB->setMinValue(1);
+
+#if 0
+ // The row/column as label checkboxes.
+ m_firstRowAsLabel = new TQCheckBox( i18n( "First row as label" ), page);
+ m_firstColAsLabel = new TQCheckBox( i18n( "First column as label" ), page);
+#endif
+
+ // Buttons for Inserting / Removing rows & columns
+ // The icon images are taken from the standard
+ m_insertRowButton = new TQPushButton( page);
+ // In 2.0; this is supposed to be just TDEIcon("name").pixmap(32).
+ m_insertRowButton->setPixmap( BarIcon( TQString("insert_table_row"),
+ TDEIcon::SizeMedium,
+ TDEIcon::DefaultState,
+ KChartFactory::global() ) );
+ //m_insertRowButton = new TQPushButton( i18n("Insert Row") , page);
+ connect( m_insertRowButton, TQT_SIGNAL( clicked() ),
+ this, TQT_SLOT( insertRow() ) );
+
+ m_removeRowButton = new TQPushButton( page );
+ m_removeRowButton->setPixmap( BarIcon( TQString("delete_table_row"),
+ TDEIcon::SizeMedium,
+ TDEIcon::DefaultState,
+ KChartFactory::global() ) );
+ //m_removeRowButton = new TQPushButton( i18n("Remove Row") , page);
+ connect( m_removeRowButton, TQT_SIGNAL( clicked() ),
+ this, TQT_SLOT( removeCurrentRow() ) );
+
+ m_insertColButton = new TQPushButton( page );
+ m_insertColButton->setPixmap( BarIcon( TQString("insert_table_col"),
+ TDEIcon::SizeMedium,
+ TDEIcon::DefaultState,
+ KChartFactory::global() ) );
+ //m_insertColButton = new TQPushButton( i18n("Insert Column") , page);
+ connect( m_insertColButton, TQT_SIGNAL( clicked() ),
+ this, TQT_SLOT( insertColumn() ) );
+
+ m_removeColButton = new TQPushButton( page );
+ m_removeColButton->setPixmap( BarIcon( TQString("delete_table_col"),
+ TDEIcon::SizeMedium,
+ TDEIcon::DefaultState,
+ KChartFactory::global() ) );
+ //m_removeColButton = new TQPushButton( i18n("Remove Column") , page);
+ connect( m_removeColButton, TQT_SIGNAL( clicked() ),
+ this, TQT_SLOT( removeCurrentColumn() ) );
+
+ // Start the layout. The buttons are at the top.
+ TQVBoxLayout *topLayout = new TQVBoxLayout( page );
+
+ TQHBoxLayout* insertRemoveLayout = new TQHBoxLayout( );
+
+ insertRemoveLayout->setSpacing(5);
+ insertRemoveLayout->addWidget(m_insertRowButton);
+ insertRemoveLayout->addWidget(m_removeRowButton);
+ insertRemoveLayout->addWidget(m_insertColButton);
+ insertRemoveLayout->addWidget(m_removeColButton);
+ insertRemoveLayout->addStretch(1);
+
+ topLayout->addLayout(insertRemoveLayout);
+ topLayout->addSpacing(10);
+
+ // The table is below the buttons.
+ topLayout->addWidget(m_table);
+
+ // Then, a horizontal layer with the rows and columns settings
+ TQHBoxLayout *hbl1 = new TQHBoxLayout( );
+ hbl1->addWidget(m_rowsLA);
+ hbl1->addWidget(m_rowsSB);
+ hbl1->addSpacing(20);
+ hbl1->addWidget(m_colsLA);
+ hbl1->addWidget(m_colsSB);
+ hbl1->addStretch(1);
+ hbl1->setMargin(10);
+ topLayout->addLayout(hbl1);
+
+#if 0
+ // Last, the checkboxes with "First row/column as label"
+ TQHBoxLayout *hbl2 = new TQHBoxLayout( );
+ hbl2->addWidget(m_firstRowAsLabel);
+ hbl2->addWidget(m_firstColAsLabel);
+ hbl2->addStretch(1);
+ hbl2->setMargin(10);
+ topLayout->addLayout(hbl2);
+#endif
+
+ topLayout->setStretchFactor(m_table, 1);
+ topLayout->setStretchFactor(insertRemoveLayout,1);
+
+ // Connect signals from the spin boxes.
+ connect(m_rowsSB, TQT_SIGNAL(valueChangedSpecial(int)),
+ this, TQT_SLOT(setRows(int)));
+ connect(m_colsSB, TQT_SIGNAL(valueChangedSpecial(int)),
+ this, TQT_SLOT(setCols(int)));
+
+
+#if 0
+ // -- Changed data editor to use top row and leftmost column for
+ // series names and labels so this is no longer necessary.
+
+ connect(m_table->horizontalHeader(), TQT_SIGNAL(clicked(int)),
+ this, TQT_SLOT(column_clicked(int)) );
+ connect(m_table->verticalHeader(), TQT_SIGNAL(clicked(int)),
+ this, TQT_SLOT(row_clicked(int)) );
+#endif
+
+ connect(m_table, TQT_SIGNAL(valueChanged(int, int)),
+ this, TQT_SLOT(tableChanged(int, int)) );
+
+ // At first, assume that any shrinking of the table is a mistake.
+ // A confirmation dialog will make sure that the user knows what
+ // (s)he is doing.
+ m_userWantsToShrink = false;
+
+ // The data is not modified at the start.
+ m_modified = false;
+
+ // If the cursor starts at cell (0, 0), that is the header row and
+ // col, and the user isn't allowed to remove those.
+ m_removeRowButton->setEnabled( false );
+ m_removeColButton->setEnabled( false );
+
+ // Add tooltips and WhatsThis help.
+ addDocs();
+}
+
+
+// Add Tooltips and WhatsThis help to various parts of the Data Editor.
+//
+void kchartDataEditor::addDocs()
+{
+ // The rows settings.
+ TQString rowwhatsthis = i18n("<p><b>Sets the number of rows in the data table."
+ "</b><br><br>Each row represents one data set.</p>");
+ TQToolTip::add(m_rowsSB, i18n("Number of active data rows"));
+ TQWhatsThis::add(m_rowsLA, rowwhatsthis);
+ TQWhatsThis::add(m_rowsSB, rowwhatsthis);
+
+ // The columns settings.
+ TQString colwhatsthis = i18n("<p><b>Sets the number of columns in the data table."
+ "</b><br><br>The number of columns defines the number of data values in each data set (row).</p>");
+ TQToolTip::add(m_colsSB, i18n("Number of active data columns"));
+ TQWhatsThis::add(m_colsLA, colwhatsthis);
+ TQWhatsThis::add(m_colsSB, colwhatsthis);
+
+ // The table.
+ TQToolTip::add(m_table, i18n("Chart data table."));
+
+ //GUI
+ //The TQWhatsThis information below is incorrect since the way that the contents of the table
+ //are displayed in the chart depends upon the data format selected (which can be
+ //either "Data in columns" (default) or "Data in rows)
+ //The names of the data sets / axes labels are no longer set by clicking on the table
+ //headers - since that was slow to work with and did not allow for keyboard input.
+ //Instead the names are taken from the topmost row and leftmost column.
+ //
+ //eg: Month | Sales
+ // Jan | 105
+ // Feb | 117
+ // March | 120
+ //
+ //The captions of the header are automatically set to the names of the cells in the topmost row
+ //and leftmost column. This means that if you have more data than will fit in the visible area,
+ //you can still see the column names or row names when the table has been scrolled.
+ //KSpread could use some functionality like this as well.
+
+
+#if 0
+ TQWhatsThis::add(m_table, i18n("<p>This table contains the data"
+ " for the chart.<br><br> Each row is one data set of values."
+ " The name of such a data set can be changed in the column header (on the left)"
+ " of the table. In a line diagram each row is one line. In a ring diagram each row"
+ " is one slice. <br><br> Each column represents one value of each data set."
+ " Just like rows you can also change the name of each value in the"
+ " column headers (at the top) of the table. In a bar diagram the number"
+ " of columns defines the number of value sets. In a ring diagram each"
+ " column is one ring.</p>"));
+#endif
+
+ TQToolTip::add( m_insertRowButton, i18n("Insert row") );
+ TQToolTip::add( m_removeRowButton, i18n("Delete row") );
+ TQToolTip::add( m_insertColButton, i18n("Insert column") );
+ TQToolTip::add( m_removeColButton, i18n("Delete column") );
+}
+
+
+// Set the data in the data editor.
+//
+// The data is taken from the KDChart data. This method is never
+// called when the chart is a part of a spreadsheet.
+//
+void kchartDataEditor::setData( KChartParams *params, KDChartTableData *dat )
+{
+ unsigned int rowsCount;
+ unsigned int colsCount;
+
+ // Get the correct number of rows and columns.
+ if ( dat->usedRows() == 0 && dat->usedCols() == 0) { // Data from KSpread
+ rowsCount = dat->rows();
+ colsCount = dat->cols();
+ }
+ else {
+ rowsCount = dat->usedRows();
+ colsCount = dat->usedCols();
+ }
+
+ // Empty table
+ if ( rowsCount==0 && colsCount==0 ) {
+ m_table->setNumRows(1);
+ m_table->setNumCols(1);
+ resize(600, 300);
+ return;
+ }
+
+ rowsCount += headerRows();
+ colsCount += headerCols();
+
+ // Initiate widgets with the correct rows and columns.
+ m_rowsSB->setValue(rowsCount);
+ m_colsSB->setValue(colsCount);
+#if 0
+ m_firstRowAsLabel->setChecked( params->firstRowAsLabel() );
+ m_firstColAsLabel->setChecked( params->firstColAsLabel() );
+#endif
+
+ // Fill the data from the chart into the editor.
+ m_table->setNumRows(rowsCount);
+ m_table->setNumCols(colsCount);
+ for (unsigned int row = headerRows(); row < rowsCount; row++) {
+ for (unsigned int col = headerCols(); col < colsCount; col++) {
+ TQVariant t = dat->cellVal(row-headerRows(), col-headerCols());
+
+ // Fill it in from the part.
+ if (t.isValid()) {
+ if ( t.type() == TQVariant::Double ) {
+ m_table->setText(row, col,
+ TQString("%1").arg(t.toDouble()));
+ }
+ else if ( t.type() == TQVariant::String )
+ kdDebug(35001) << "I cannot handle strings in the table yet"
+ << endl;
+ else {
+ // nothing on purpose
+ }
+ }
+ }
+ }
+
+ // Set column widths. The default is a little too wide.
+ for (unsigned int col = 0; col < colsCount + 1; col++)
+ m_table->setColumnWidth(col, COLUMNWIDTH);
+
+ // and resize the widget to a good size.
+ resize(600, 300);
+}
+
+
+// Get the data from the data editor and put it back into the chart.
+//
+void kchartDataEditor::getData( KChartParams *params, KDChartTableData *dat )
+{
+ //Number of rows used as headers
+ int labelRows = headerRows();
+ //Number of columns used as headers
+ int labelCols = headerCols();
+
+ int numRows = m_table->numRows()-labelRows;
+ int numCols = m_table->numCols()-labelCols;
+
+ // Make sure that the data table for the chart is not smaller than
+ // the data in the editor.
+ if ( static_cast<int>( dat->rows() ) < numRows
+ || static_cast<int>( dat->cols() ) < numCols )
+ dat->expand( numRows, numCols );
+
+ dat->setUsedRows( numRows );
+ dat->setUsedCols( numCols );
+
+ // Empty table
+#if 0
+ if ( numRows==1 && numCols==1 && m_table->horizontalHeader()->label(0).isEmpty()
+ && m_table->verticalHeader()->label(0).isEmpty()
+ && m_table->text(0, 0).isEmpty() ) {
+ dat->expand(0,0);
+ return;
+ }
+#endif
+
+ // Get all the data.
+ for (int row = labelRows ; row < (numRows+labelRows); row++) {
+ for (int col = labelCols ; col < (numCols+labelCols); col++) {
+
+ // Get the text and convert to double.
+ TQString tmp = m_table->text(row, col);
+ bool bOk;
+ double val = tmp.toDouble( &bOk );
+ if (!bOk)
+ val = 0.0;
+ // and do the actual setting.
+ //t = KoChart::Value( val );
+ dat->setCell(row-labelRows,col-labelCols, val);
+ }
+ }
+
+#if 0
+ params->setFirstRowAsLabel( m_firstRowAsLabel->isChecked() );
+ params->setFirstColAsLabel( m_firstColAsLabel->isChecked() );
+#endif
+}
+
+
+// Set the row labels in the data editor.
+//
+void kchartDataEditor::setRowLabels(const TQStringList &rowLabels)
+{
+#if 0
+ TQHeader *rowHeader = m_table->verticalHeader();
+ int row;
+ int numRows = m_rowsSB->value();
+
+ rowHeader->setLabel(0, "");
+ if ( numRows==1 && m_colsSB->value()==1 && m_table->text(0, 0).isEmpty() )
+ return;
+ for (row = 0; row < numRows; row++) {
+ rowHeader->setLabel(row, rowLabels[row]);
+ }
+#endif
+
+ for (unsigned int i=0; i < rowLabels.count(); i++) {
+ m_table->setText(i + headerRows(), 0, rowLabels[i]);
+ }
+
+ updateRowHeaders();
+}
+
+
+int kchartDataEditor::headerRows()
+{
+ return 1;
+}
+
+int kchartDataEditor::headerCols()
+{
+ return 1;
+}
+
+
+// Get the row labels from the data editor.
+//
+void kchartDataEditor::getRowLabels(TQStringList &rowLabels)
+{
+#if 0
+ TQHeader *rowHeader = m_table->verticalHeader();
+ int numRows = m_rowsSB->value();
+ int row;
+
+ rowLabels.clear();
+ for (row = 0; row < numRows; row++) {
+ rowLabels << rowHeader->label(row);
+ }
+#endif
+ rowLabels.clear();
+
+ for (int i=headerRows();i < m_table->numRows();i++)
+ {
+ rowLabels << m_table->text(i,0);
+ }
+}
+
+
+// Set the column labels in the data editor.
+//
+void kchartDataEditor::setColLabels(const TQStringList &colLabels)
+{
+#if 0
+ TQHeader *colHeader = m_table->horizontalHeader();
+ int col;
+
+ int numCols = m_colsSB->value();
+
+ colHeader->setLabel(0, "");
+ if ( m_rowsSB->value()==1 && numCols==1 && m_table->text(0, 0).isEmpty() )
+ return;
+ for (col = 0; col < numCols; col++) {
+ colHeader->setLabel(col, colLabels[col]);
+ }
+#endif
+
+ for (unsigned int i = 0; i < colLabels.count(); i++)
+ {
+ m_table->setText(0,i+headerCols(),colLabels[i]);
+ }
+
+ updateColHeaders();
+}
+
+
+// Get the column labels from the data editor.
+//
+void kchartDataEditor::getColLabels(TQStringList &colLabels)
+{
+#if 0
+ TQHeader *colHeader = m_table->horizontalHeader();
+ int numCols = m_colsSB->value();
+ int col;
+
+ colLabels.clear();
+ for (col = 0; col < numCols; col++) {
+ colLabels << colHeader->label(col);
+ }
+#endif
+
+ colLabels.clear();
+
+ for (int i = headerCols(); i < m_table->numCols(); i++) {
+ colLabels << m_table->text(0, i);
+ }
+}
+
+
+// ================================================================
+// Slots
+
+
+// Slots for the buttons that insert/remove rows/columns.
+//
+
+void kchartDataEditor::removeCurrentRow()
+{
+ int row = m_table->currentRow();
+
+ // Can't remove the header row.
+ if ( row == 0 )
+ return;
+
+ // Need at least one data row.
+ if ( m_table->numRows() == 2 )
+ return;
+
+ m_table->removeRow(row);
+ m_rowsSB->setValue(m_table->numRows());
+
+ m_modified = true;
+}
+
+void kchartDataEditor::removeCurrentColumn()
+{
+ int col = m_table->currentColumn();
+
+ // Can't remove the header column.
+ if ( col == 0 )
+ return;
+
+ // Need at least one data column.
+ if ( m_table->numCols() == 2 )
+ return;
+
+ m_table->removeColumn(col);
+ m_colsSB->setValue(m_table->numCols());
+
+ m_modified = true;
+}
+
+void kchartDataEditor::insertColumn()
+{
+ m_table->insertColumns(m_table->currentColumn() + 1, 1);
+ m_colsSB->setValue(m_table->numCols());
+ updateColHeaders();
+
+ m_modified = true;
+}
+
+void kchartDataEditor::insertRow()
+{
+ m_table->insertRows(m_table->currentRow() + 1, 1);
+ m_rowsSB->setValue(m_table->numRows());
+ updateRowHeaders();
+
+ m_modified = true;
+}
+
+
+// Ask user to make sure that (s)he really wants to remove a row or
+// column.
+//
+static int askUserForConfirmation(TQWidget *parent)
+{
+ return KMessageBox::warningContinueCancel(parent,
+ i18n("You are about to shrink the data table and remove some values. "
+ "This will lead to loss of existing data in the table "
+ "and/or the headers.\n\n"
+ "This message will not be shown again if you click Continue"));
+}
+
+
+// This slot is called when the spinbox for rows is changed.
+//
+void kchartDataEditor::setRows(int rows)
+{
+ kdDebug(35001) << "setRows called: rows = " << rows << endl;;
+
+ // Sanity check. This should never happen since the spinbox has a
+ // minvalue of 1, but just to be sure...
+ if (rows < 1) {
+ m_rowsSB->setValue(1);
+ return;
+ }
+
+ int old_rows = m_table->numRows();
+ if (rows > old_rows) {
+ m_table->setNumRows(rows);
+
+ // Default value for the new rows: empty string
+ for (int i = old_rows; i < rows; i++)
+ m_table->verticalHeader()->setLabel(i, "");
+
+ m_modified = true;
+ }
+ else if (rows < m_table->numRows()) {
+ bool ask_user = false;
+
+ // Check if the last row is empty.
+ for (int col=0; col<m_table->numCols(); col++) {
+ if (!m_table->text(rows, col).isEmpty()) {
+ ask_user = true;
+ break;
+ }
+ }
+
+ // If it is not, ask if the user really wants to shrink the table.
+ if ( ask_user && !m_userWantsToShrink
+ && askUserForConfirmation(this) == KMessageBox::Cancel) {
+
+ // The user aborts. Reset the number of rows and return.
+ m_rowsSB->setValue(m_table->numRows());
+ return;
+ }
+
+ // Record the fact that the user knows what (s)he is doing.
+ if (ask_user)
+ m_userWantsToShrink = true;
+
+ // Do the actual shrinking.
+ m_table->setNumRows(rows);
+
+ m_modified = true;
+ }
+}
+
+
+// This slot is called when the spinbox for columns is changed.
+//
+void kchartDataEditor::setCols(int cols)
+{
+ kdDebug(35001) << "setCols called: cols = " << cols << endl;;
+
+ // Sanity check. This should never happen since the spinbox has a
+ // minvalue of 1, but just to be sure...
+ if (cols < 1) {
+ m_colsSB->setValue(1);
+ return;
+ }
+
+ int old_cols = m_table->numCols();
+ if (cols > old_cols) {
+ m_table->setNumCols(cols);
+
+ // Default value for the new columns: empty string.
+ for (int i = old_cols; i < cols; i++) {
+ m_table->horizontalHeader()->setLabel(i, "");
+ m_table->setColumnWidth(i, COLUMNWIDTH);
+ }
+
+ m_modified = true;
+ }
+ else if (cols < m_table->numCols()) {
+ bool ask_user = false;
+
+ // Check if the last column is empty.
+ for (int row=0; row<m_table->numRows(); row++) {
+ if (!m_table->text(row, cols).isEmpty()) {
+ ask_user = true;
+ break;
+ }
+ }
+
+ // If it is not, ask if the user really wants to shrink the table.
+ if (ask_user && !m_userWantsToShrink
+ && askUserForConfirmation(this) == KMessageBox::Cancel) {
+
+ // The user aborts. Reset the number of rows and return.
+ m_colsSB->setValue(m_table->numCols());
+ return;
+ }
+
+ // Record the fact that the user knows what (s)he is doing.
+ if (ask_user)
+ m_userWantsToShrink = true;
+
+ // Do the actual shrinking.
+ m_table->setNumCols(cols);
+
+ m_modified = true;
+ }
+}
+
+
+// Get the new name for a column header.
+//
+#if 0 // Disabled since the first row / column now contains the labels.
+void kchartDataEditor::column_clicked(int column)
+{
+ bool ok;
+ TQString name = KInputDialog::getText(i18n("Column Name"),
+ i18n("Type a new column name:"),
+ m_table->horizontalHeader()->label(column),
+ &ok, this, 0, new TQRegExpValidator(TQRegExp(".*"), this) );
+
+ // Rename the column.
+ if ( ok ) {
+ m_table->horizontalHeader()->setLabel(column, name);
+ m_modified = true;
+ }
+}
+
+
+// Get the new name for a row header.
+//
+void kchartDataEditor::row_clicked(int row)
+{
+ bool ok;
+ TQString name = KInputDialog::getText(i18n("Row Name"),
+ i18n("Type a new row name:"),
+ m_table->verticalHeader()->label(row),
+ &ok, this, 0, new TQRegExpValidator(TQRegExp(".*"), this) );
+
+ // Rename the row.
+ if ( ok ) {
+ m_table->verticalHeader()->setLabel(row, name);
+ m_modified = true;
+ }
+}
+#endif
+
+
+void kchartDataEditor::tableChanged(int row, int col)
+{
+ if (row <= headerRows())
+ updateColHeaders();
+ if (col <= headerCols())
+ updateRowHeaders();
+
+ m_modified = true;
+}
+
+
+void kchartDataEditor::currentChanged(int row, int col)
+{
+ m_removeRowButton->setEnabled( row != 0 && m_table->numRows() > 2 );
+ m_removeColButton->setEnabled( col != 0 && m_table->numCols() > 2 );
+}
+
+
+void kchartDataEditor::updateRowHeaders()
+{
+ for (int i=0;i<m_table->numRows();i++)
+ {
+ TQHeader* header=m_table->verticalHeader();
+
+ TQString tableCellText=m_table->text(i,0);
+
+ if (tableCellText == TQString())
+ tableCellText=TQString("");
+
+ header->setLabel(header->mapToSection(i),tableCellText);
+ }
+}
+
+void kchartDataEditor::updateColHeaders()
+{
+ for (int i=0;i<m_table->numCols();i++)
+ {
+ TQHeader* header=m_table->horizontalHeader();
+
+ TQString tableCellText=m_table->text(0,i);
+
+ if (tableCellText == TQString())
+ tableCellText=TQString("");
+
+ header->setLabel(header->mapToSection(i),tableCellText);
+ }
+}
+
+
+// This is a reimplementation of a slot defined in KDialogBase. The
+// reason for the reimplementation is that we need to emit the signal
+// with a pointer to this so that we can get the data.
+//
+void kchartDataEditor::slotApply()
+{
+ emit applyClicked(this);
+}
+
+
+} //KChart namespace