You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
901 lines
25 KiB
901 lines
25 KiB
#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 <klocale.h>
|
|
#include <kdebug.h>
|
|
#include <kmessagebox.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 KIcon("name").pixmap(32).
|
|
m_insertRowButton->setPixmap( BarIcon( TQString("insert_table_row"),
|
|
KIcon::SizeMedium,
|
|
KIcon::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"),
|
|
KIcon::SizeMedium,
|
|
KIcon::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"),
|
|
KIcon::SizeMedium,
|
|
KIcon::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"),
|
|
KIcon::SizeMedium,
|
|
KIcon::DefaultState,
|
|
KChartFactory::global() ) );
|
|
//m_removeColButton = new TQPushButton( i18n("Remove Column") , page);
|
|
connect( m_removeColButton, TQT_SIGNAL( clicked() ),
|
|
this, TQT_SLOT( removeCurrentColumn() ) );
|
|
|
|
// Start the tqlayout. 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").tqarg(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
|