kchart

kchartDataEditor.cpp
1#include <tqcheckbox.h>
2#include <tqlabel.h>
3#include <tqspinbox.h>
4#include <tqlayout.h>
5#include <tqlineedit.h>
6#include <tqregexp.h>
7#include <tqwhatsthis.h>
8#include <tqtooltip.h>
9#include <tqvalidator.h>
10#include <tqpushbutton.h>
11
12#include <kinputdialog.h>
13#include <tdelocale.h>
14#include <kdebug.h>
15#include <tdemessagebox.h>
16#include <kiconloader.h>
17
19#include "kchart_params.h"
20#include "kchart_factory.h"
21
22#include "kchartDataEditor.h"
23#include "kchartDataEditor.moc"
24
25namespace KChart
26{
27
28
29// ================================================================
30// Class kchartDataSpinBox
31
32
33// We don't provide very much generality, since this spinbox is used
34// here and here only.
35//
36kchartDataSpinBox::kchartDataSpinBox(TQWidget *parent)
37 : TQSpinBox(parent)
38{
39 m_ignore = false;
40}
41
42
43kchartDataSpinBox::~kchartDataSpinBox()
44{
45}
46
47
48void kchartDataSpinBox::stepUp()
49{
50 m_ignore = true;
51 uint const new_value = value() + 1;
52
53 TQSpinBox::stepUp();
54 setValue(new_value);
55
56 emit valueChangedSpecial( value() );
57 m_ignore = false;
58}
59
60
61void kchartDataSpinBox::stepDown()
62{
63 m_ignore = true;
64
65 uint const new_value = value() - 1;
66 TQSpinBox::stepDown();
67 setValue(new_value);
68
69 emit valueChangedSpecial( value() );
70 m_ignore = false;
71}
72
73
74bool kchartDataSpinBox::eventFilter( TQObject *obj, TQEvent *ev )
75{
76 if ( obj == editor() ) {
77 if ( ev->type() == TQEvent::FocusOut ) {
78 //kdDebug() << "Focus out" << endl;
79 setValue(editor()->text().toInt());
80
81 // Don't emit valueChangedSpecial(int) twice when
82 // stepUp/stepDown has been called
83 if (!m_ignore)
84 emit valueChangedSpecial( value() );
85 }
86 }
87
88 // Pass the event on to the parent class.
89 return TQSpinBox::eventFilter( obj, ev );
90}
91
92
93// ================================================================
94// Class kchartDataTable
95
96
97// Used for the keyboard navigation
98//
99kchartDataTable::kchartDataTable(TQWidget *parent)
100 : TQTable(parent)
101{
102}
103
104
105kchartDataTable::~kchartDataTable()
106{
107}
108
109
110bool kchartDataTable::eventFilter( TQObject *obj, TQEvent *ev )
111{
112 if (ev->type() == TQEvent::KeyPress && strcmp(obj->name(),
113 "qt_tableeditor")==0 ) {
114 TQKeyEvent *e = (TQKeyEvent *)ev;
115
116 switch ( e->key() ) {
117 case TQt::Key_Up:
118 {
119 if ( currentRow() > 0 ) {
120 setCurrentCell( currentRow()-1, currentColumn() );
121 editCell(currentRow(), currentColumn() );
122 return true;
123 }
124 break;
125 }
126 case TQt::Key_Down:
127 {
128 if ( currentRow() < numRows()-1 ) {
129 setCurrentCell( currentRow()+1, currentColumn() );
130 editCell(currentRow(), currentColumn() );
131 return true;
132 }
133 break;
134 }
135 case TQt::Key_Right:
136 {
137 if ( currentColumn() < numCols()-1 ) {
138 setCurrentCell( currentRow(), currentColumn()+1 );
139 editCell(currentRow(), currentColumn() );
140 return true;
141 }
142 break;
143 }
144 case TQt::Key_Left:
145 {
146 if ( currentColumn() > 0 ) {
147 setCurrentCell( currentRow(), currentColumn()-1 );
148 editCell(currentRow(), currentColumn() );
149 return true;
150 }
151 break;
152 }
153 }
154 }
155
156 return TQTable::eventFilter( obj, ev );
157}
158
159
160// ================================================================
161// Class kchartDataEditor
162
163
164#define COLUMNWIDTH 80
165
166kchartDataEditor::kchartDataEditor(TQWidget* parent) :
167 KDialogBase(parent, "dataeditor", true, i18n("KChart Data Editor"),
168 KDialogBase::Ok | KDialogBase::Cancel | KDialogBase::Apply,
169 KDialogBase::Ok, true)
170{
171 TQWidget *page = new TQWidget( this );
172 setMainWidget(page);
173
174 // Create the main table.
175 m_table = new kchartDataTable(page);
176 m_table->setSelectionMode(TQTable::NoSelection);
177 m_table->setFocus();
178 m_table->setRowMovingEnabled(true);
179 m_table->setColumnMovingEnabled(true);
180
181 connect( m_table, TQ_SIGNAL( currentChanged(int, int) ),
182 this, TQ_SLOT( currentChanged(int, int) ) );
183
184 // Create the Rows setting
185 m_rowsLA = new TQLabel( i18n("# Rows:" ), page );
186 m_rowsLA->resize( m_rowsLA->sizeHint() );
187 m_rowsSB = new kchartDataSpinBox( page );
188 m_rowsSB->resize( m_rowsSB->sizeHint() );
189 m_rowsSB->setMinValue(1);
190
191 // Create the columns setting
192 m_colsLA = new TQLabel( i18n("# Columns:" ), page );
193 m_colsLA->resize( m_colsLA->sizeHint() );
194 m_colsSB = new kchartDataSpinBox( page );
195 m_colsSB->resize( m_colsSB->sizeHint() );
196 m_colsSB->setMinValue(1);
197
198#if 0
199 // The row/column as label checkboxes.
200 m_firstRowAsLabel = new TQCheckBox( i18n( "First row as label" ), page);
201 m_firstColAsLabel = new TQCheckBox( i18n( "First column as label" ), page);
202#endif
203
204 // Buttons for Inserting / Removing rows & columns
205 // The icon images are taken from the standard
206 m_insertRowButton = new TQPushButton( page);
207 // In 2.0; this is supposed to be just TDEIcon("name").pixmap(32).
208 m_insertRowButton->setPixmap( BarIcon( TQString("insert_table_row"),
209 TDEIcon::SizeMedium,
210 TDEIcon::DefaultState,
211 KChartFactory::global() ) );
212 //m_insertRowButton = new TQPushButton( i18n("Insert Row") , page);
213 connect( m_insertRowButton, TQ_SIGNAL( clicked() ),
214 this, TQ_SLOT( insertRow() ) );
215
216 m_removeRowButton = new TQPushButton( page );
217 m_removeRowButton->setPixmap( BarIcon( TQString("delete_table_row"),
218 TDEIcon::SizeMedium,
219 TDEIcon::DefaultState,
220 KChartFactory::global() ) );
221 //m_removeRowButton = new TQPushButton( i18n("Remove Row") , page);
222 connect( m_removeRowButton, TQ_SIGNAL( clicked() ),
223 this, TQ_SLOT( removeCurrentRow() ) );
224
225 m_insertColButton = new TQPushButton( page );
226 m_insertColButton->setPixmap( BarIcon( TQString("insert_table_col"),
227 TDEIcon::SizeMedium,
228 TDEIcon::DefaultState,
229 KChartFactory::global() ) );
230 //m_insertColButton = new TQPushButton( i18n("Insert Column") , page);
231 connect( m_insertColButton, TQ_SIGNAL( clicked() ),
232 this, TQ_SLOT( insertColumn() ) );
233
234 m_removeColButton = new TQPushButton( page );
235 m_removeColButton->setPixmap( BarIcon( TQString("delete_table_col"),
236 TDEIcon::SizeMedium,
237 TDEIcon::DefaultState,
238 KChartFactory::global() ) );
239 //m_removeColButton = new TQPushButton( i18n("Remove Column") , page);
240 connect( m_removeColButton, TQ_SIGNAL( clicked() ),
241 this, TQ_SLOT( removeCurrentColumn() ) );
242
243 // Start the layout. The buttons are at the top.
244 TQVBoxLayout *topLayout = new TQVBoxLayout( page );
245
246 TQHBoxLayout* insertRemoveLayout = new TQHBoxLayout( );
247
248 insertRemoveLayout->setSpacing(5);
249 insertRemoveLayout->addWidget(m_insertRowButton);
250 insertRemoveLayout->addWidget(m_removeRowButton);
251 insertRemoveLayout->addWidget(m_insertColButton);
252 insertRemoveLayout->addWidget(m_removeColButton);
253 insertRemoveLayout->addStretch(1);
254
255 topLayout->addLayout(insertRemoveLayout);
256 topLayout->addSpacing(10);
257
258 // The table is below the buttons.
259 topLayout->addWidget(m_table);
260
261 // Then, a horizontal layer with the rows and columns settings
262 TQHBoxLayout *hbl1 = new TQHBoxLayout( );
263 hbl1->addWidget(m_rowsLA);
264 hbl1->addWidget(m_rowsSB);
265 hbl1->addSpacing(20);
266 hbl1->addWidget(m_colsLA);
267 hbl1->addWidget(m_colsSB);
268 hbl1->addStretch(1);
269 hbl1->setMargin(10);
270 topLayout->addLayout(hbl1);
271
272#if 0
273 // Last, the checkboxes with "First row/column as label"
274 TQHBoxLayout *hbl2 = new TQHBoxLayout( );
275 hbl2->addWidget(m_firstRowAsLabel);
276 hbl2->addWidget(m_firstColAsLabel);
277 hbl2->addStretch(1);
278 hbl2->setMargin(10);
279 topLayout->addLayout(hbl2);
280#endif
281
282 topLayout->setStretchFactor(m_table, 1);
283 topLayout->setStretchFactor(insertRemoveLayout,1);
284
285 // Connect signals from the spin boxes.
286 connect(m_rowsSB, TQ_SIGNAL(valueChangedSpecial(int)),
287 this, TQ_SLOT(setRows(int)));
288 connect(m_colsSB, TQ_SIGNAL(valueChangedSpecial(int)),
289 this, TQ_SLOT(setCols(int)));
290
291
292#if 0
293 // -- Changed data editor to use top row and leftmost column for
294 // series names and labels so this is no longer necessary.
295
296 connect(m_table->horizontalHeader(), TQ_SIGNAL(clicked(int)),
297 this, TQ_SLOT(column_clicked(int)) );
298 connect(m_table->verticalHeader(), TQ_SIGNAL(clicked(int)),
299 this, TQ_SLOT(row_clicked(int)) );
300#endif
301
302 connect(m_table, TQ_SIGNAL(valueChanged(int, int)),
303 this, TQ_SLOT(tableChanged(int, int)) );
304
305 // At first, assume that any shrinking of the table is a mistake.
306 // A confirmation dialog will make sure that the user knows what
307 // (s)he is doing.
308 m_userWantsToShrink = false;
309
310 // The data is not modified at the start.
311 m_modified = false;
312
313 // If the cursor starts at cell (0, 0), that is the header row and
314 // col, and the user isn't allowed to remove those.
315 m_removeRowButton->setEnabled( false );
316 m_removeColButton->setEnabled( false );
317
318 // Add tooltips and WhatsThis help.
319 addDocs();
320}
321
322
323// Add Tooltips and WhatsThis help to various parts of the Data Editor.
324//
325void kchartDataEditor::addDocs()
326{
327 // The rows settings.
328 TQString rowwhatsthis = i18n("<p><b>Sets the number of rows in the data table."
329 "</b><br><br>Each row represents one data set.</p>");
330 TQToolTip::add(m_rowsSB, i18n("Number of active data rows"));
331 TQWhatsThis::add(m_rowsLA, rowwhatsthis);
332 TQWhatsThis::add(m_rowsSB, rowwhatsthis);
333
334 // The columns settings.
335 TQString colwhatsthis = i18n("<p><b>Sets the number of columns in the data table."
336 "</b><br><br>The number of columns defines the number of data values in each data set (row).</p>");
337 TQToolTip::add(m_colsSB, i18n("Number of active data columns"));
338 TQWhatsThis::add(m_colsLA, colwhatsthis);
339 TQWhatsThis::add(m_colsSB, colwhatsthis);
340
341 // The table.
342 TQToolTip::add(m_table, i18n("Chart data table."));
343
344 //GUI
345 //The TQWhatsThis information below is incorrect since the way that the contents of the table
346 //are displayed in the chart depends upon the data format selected (which can be
347 //either "Data in columns" (default) or "Data in rows)
348 //The names of the data sets / axes labels are no longer set by clicking on the table
349 //headers - since that was slow to work with and did not allow for keyboard input.
350 //Instead the names are taken from the topmost row and leftmost column.
351 //
352 //eg: Month | Sales
353 // Jan | 105
354 // Feb | 117
355 // March | 120
356 //
357 //The captions of the header are automatically set to the names of the cells in the topmost row
358 //and leftmost column. This means that if you have more data than will fit in the visible area,
359 //you can still see the column names or row names when the table has been scrolled.
360 //KSpread could use some functionality like this as well.
361
362
363#if 0
364 TQWhatsThis::add(m_table, i18n("<p>This table contains the data"
365 " for the chart.<br><br> Each row is one data set of values."
366 " The name of such a data set can be changed in the column header (on the left)"
367 " of the table. In a line diagram each row is one line. In a ring diagram each row"
368 " is one slice. <br><br> Each column represents one value of each data set."
369 " Just like rows you can also change the name of each value in the"
370 " column headers (at the top) of the table. In a bar diagram the number"
371 " of columns defines the number of value sets. In a ring diagram each"
372 " column is one ring.</p>"));
373#endif
374
375 TQToolTip::add( m_insertRowButton, i18n("Insert row") );
376 TQToolTip::add( m_removeRowButton, i18n("Delete row") );
377 TQToolTip::add( m_insertColButton, i18n("Insert column") );
378 TQToolTip::add( m_removeColButton, i18n("Delete column") );
379}
380
381
382// Set the data in the data editor.
383//
384// The data is taken from the KDChart data. This method is never
385// called when the chart is a part of a spreadsheet.
386//
387void kchartDataEditor::setData( KChartParams *params, KDChartTableData *dat )
388{
389 unsigned int rowsCount;
390 unsigned int colsCount;
391
392 // Get the correct number of rows and columns.
393 if ( dat->usedRows() == 0 && dat->usedCols() == 0) { // Data from KSpread
394 rowsCount = dat->rows();
395 colsCount = dat->cols();
396 }
397 else {
398 rowsCount = dat->usedRows();
399 colsCount = dat->usedCols();
400 }
401
402 // Empty table
403 if ( rowsCount==0 && colsCount==0 ) {
404 m_table->setNumRows(1);
405 m_table->setNumCols(1);
406 resize(600, 300);
407 return;
408 }
409
410 rowsCount += headerRows();
411 colsCount += headerCols();
412
413 // Initiate widgets with the correct rows and columns.
414 m_rowsSB->setValue(rowsCount);
415 m_colsSB->setValue(colsCount);
416#if 0
417 m_firstRowAsLabel->setChecked( params->firstRowAsLabel() );
418 m_firstColAsLabel->setChecked( params->firstColAsLabel() );
419#endif
420
421 // Fill the data from the chart into the editor.
422 m_table->setNumRows(rowsCount);
423 m_table->setNumCols(colsCount);
424 for (unsigned int row = headerRows(); row < rowsCount; row++) {
425 for (unsigned int col = headerCols(); col < colsCount; col++) {
426 TQVariant t = dat->cellVal(row-headerRows(), col-headerCols());
427
428 // Fill it in from the part.
429 if (t.isValid()) {
430 if ( t.type() == TQVariant::Double ) {
431 m_table->setText(row, col,
432 TQString("%1").arg(t.toDouble()));
433 }
434 else if ( t.type() == TQVariant::String )
435 kdDebug(35001) << "I cannot handle strings in the table yet"
436 << endl;
437 else {
438 // nothing on purpose
439 }
440 }
441 }
442 }
443
444 // Set column widths. The default is a little too wide.
445 for (unsigned int col = 0; col < colsCount + 1; col++)
446 m_table->setColumnWidth(col, COLUMNWIDTH);
447
448 // and resize the widget to a good size.
449 resize(600, 300);
450}
451
452
453// Get the data from the data editor and put it back into the chart.
454//
455void kchartDataEditor::getData( KChartParams *params, KDChartTableData *dat )
456{
457 //Number of rows used as headers
458 int labelRows = headerRows();
459 //Number of columns used as headers
460 int labelCols = headerCols();
461
462 int numRows = m_table->numRows()-labelRows;
463 int numCols = m_table->numCols()-labelCols;
464
465 // Make sure that the data table for the chart is not smaller than
466 // the data in the editor.
467 if ( static_cast<int>( dat->rows() ) < numRows
468 || static_cast<int>( dat->cols() ) < numCols )
469 dat->expand( numRows, numCols );
470
471 dat->setUsedRows( numRows );
472 dat->setUsedCols( numCols );
473
474 // Empty table
475#if 0
476 if ( numRows==1 && numCols==1 && m_table->horizontalHeader()->label(0).isEmpty()
477 && m_table->verticalHeader()->label(0).isEmpty()
478 && m_table->text(0, 0).isEmpty() ) {
479 dat->expand(0,0);
480 return;
481 }
482#endif
483
484 // Get all the data.
485 for (int row = labelRows ; row < (numRows+labelRows); row++) {
486 for (int col = labelCols ; col < (numCols+labelCols); col++) {
487
488 // Get the text and convert to double.
489 TQString tmp = m_table->text(row, col);
490 bool bOk;
491 double val = tmp.toDouble( &bOk );
492 if (!bOk)
493 val = 0.0;
494 // and do the actual setting.
495 //t = KoChart::Value( val );
496 dat->setCell(row-labelRows,col-labelCols, val);
497 }
498 }
499
500#if 0
501 params->setFirstRowAsLabel( m_firstRowAsLabel->isChecked() );
502 params->setFirstColAsLabel( m_firstColAsLabel->isChecked() );
503#endif
504}
505
506
507// Set the row labels in the data editor.
508//
509void kchartDataEditor::setRowLabels(const TQStringList &rowLabels)
510{
511#if 0
512 TQHeader *rowHeader = m_table->verticalHeader();
513 int row;
514 int numRows = m_rowsSB->value();
515
516 rowHeader->setLabel(0, "");
517 if ( numRows==1 && m_colsSB->value()==1 && m_table->text(0, 0).isEmpty() )
518 return;
519 for (row = 0; row < numRows; row++) {
520 rowHeader->setLabel(row, rowLabels[row]);
521 }
522#endif
523
524 for (unsigned int i=0; i < rowLabels.count(); i++) {
525 m_table->setText(i + headerRows(), 0, rowLabels[i]);
526 }
527
528 updateRowHeaders();
529}
530
531
532int kchartDataEditor::headerRows()
533{
534 return 1;
535}
536
537int kchartDataEditor::headerCols()
538{
539 return 1;
540}
541
542
543// Get the row labels from the data editor.
544//
545void kchartDataEditor::getRowLabels(TQStringList &rowLabels)
546{
547#if 0
548 TQHeader *rowHeader = m_table->verticalHeader();
549 int numRows = m_rowsSB->value();
550 int row;
551
552 rowLabels.clear();
553 for (row = 0; row < numRows; row++) {
554 rowLabels << rowHeader->label(row);
555 }
556#endif
557 rowLabels.clear();
558
559 for (int i=headerRows();i < m_table->numRows();i++)
560 {
561 rowLabels << m_table->text(i,0);
562 }
563}
564
565
566// Set the column labels in the data editor.
567//
568void kchartDataEditor::setColLabels(const TQStringList &colLabels)
569{
570#if 0
571 TQHeader *colHeader = m_table->horizontalHeader();
572 int col;
573
574 int numCols = m_colsSB->value();
575
576 colHeader->setLabel(0, "");
577 if ( m_rowsSB->value()==1 && numCols==1 && m_table->text(0, 0).isEmpty() )
578 return;
579 for (col = 0; col < numCols; col++) {
580 colHeader->setLabel(col, colLabels[col]);
581 }
582#endif
583
584 for (unsigned int i = 0; i < colLabels.count(); i++)
585 {
586 m_table->setText(0,i+headerCols(),colLabels[i]);
587 }
588
589 updateColHeaders();
590}
591
592
593// Get the column labels from the data editor.
594//
595void kchartDataEditor::getColLabels(TQStringList &colLabels)
596{
597#if 0
598 TQHeader *colHeader = m_table->horizontalHeader();
599 int numCols = m_colsSB->value();
600 int col;
601
602 colLabels.clear();
603 for (col = 0; col < numCols; col++) {
604 colLabels << colHeader->label(col);
605 }
606#endif
607
608 colLabels.clear();
609
610 for (int i = headerCols(); i < m_table->numCols(); i++) {
611 colLabels << m_table->text(0, i);
612 }
613}
614
615
616// ================================================================
617// Slots
618
619
620// Slots for the buttons that insert/remove rows/columns.
621//
622
623void kchartDataEditor::removeCurrentRow()
624{
625 int row = m_table->currentRow();
626
627 // Can't remove the header row.
628 if ( row == 0 )
629 return;
630
631 // Need at least one data row.
632 if ( m_table->numRows() == 2 )
633 return;
634
635 m_table->removeRow(row);
636 m_rowsSB->setValue(m_table->numRows());
637
638 m_modified = true;
639}
640
641void kchartDataEditor::removeCurrentColumn()
642{
643 int col = m_table->currentColumn();
644
645 // Can't remove the header column.
646 if ( col == 0 )
647 return;
648
649 // Need at least one data column.
650 if ( m_table->numCols() == 2 )
651 return;
652
653 m_table->removeColumn(col);
654 m_colsSB->setValue(m_table->numCols());
655
656 m_modified = true;
657}
658
659void kchartDataEditor::insertColumn()
660{
661 m_table->insertColumns(m_table->currentColumn() + 1, 1);
662 m_colsSB->setValue(m_table->numCols());
663 updateColHeaders();
664
665 m_modified = true;
666}
667
668void kchartDataEditor::insertRow()
669{
670 m_table->insertRows(m_table->currentRow() + 1, 1);
671 m_rowsSB->setValue(m_table->numRows());
672 updateRowHeaders();
673
674 m_modified = true;
675}
676
677
678// Ask user to make sure that (s)he really wants to remove a row or
679// column.
680//
681static int askUserForConfirmation(TQWidget *parent)
682{
683 return KMessageBox::warningContinueCancel(parent,
684 i18n("You are about to shrink the data table and remove some values. "
685 "This will lead to loss of existing data in the table "
686 "and/or the headers.\n\n"
687 "This message will not be shown again if you click Continue"));
688}
689
690
691// This slot is called when the spinbox for rows is changed.
692//
693void kchartDataEditor::setRows(int rows)
694{
695 kdDebug(35001) << "setRows called: rows = " << rows << endl;;
696
697 // Sanity check. This should never happen since the spinbox has a
698 // minvalue of 1, but just to be sure...
699 if (rows < 1) {
700 m_rowsSB->setValue(1);
701 return;
702 }
703
704 int old_rows = m_table->numRows();
705 if (rows > old_rows) {
706 m_table->setNumRows(rows);
707
708 // Default value for the new rows: empty string
709 for (int i = old_rows; i < rows; i++)
710 m_table->verticalHeader()->setLabel(i, "");
711
712 m_modified = true;
713 }
714 else if (rows < m_table->numRows()) {
715 bool ask_user = false;
716
717 // Check if the last row is empty.
718 for (int col=0; col<m_table->numCols(); col++) {
719 if (!m_table->text(rows, col).isEmpty()) {
720 ask_user = true;
721 break;
722 }
723 }
724
725 // If it is not, ask if the user really wants to shrink the table.
726 if ( ask_user && !m_userWantsToShrink
727 && askUserForConfirmation(this) == KMessageBox::Cancel) {
728
729 // The user aborts. Reset the number of rows and return.
730 m_rowsSB->setValue(m_table->numRows());
731 return;
732 }
733
734 // Record the fact that the user knows what (s)he is doing.
735 if (ask_user)
736 m_userWantsToShrink = true;
737
738 // Do the actual shrinking.
739 m_table->setNumRows(rows);
740
741 m_modified = true;
742 }
743}
744
745
746// This slot is called when the spinbox for columns is changed.
747//
748void kchartDataEditor::setCols(int cols)
749{
750 kdDebug(35001) << "setCols called: cols = " << cols << endl;;
751
752 // Sanity check. This should never happen since the spinbox has a
753 // minvalue of 1, but just to be sure...
754 if (cols < 1) {
755 m_colsSB->setValue(1);
756 return;
757 }
758
759 int old_cols = m_table->numCols();
760 if (cols > old_cols) {
761 m_table->setNumCols(cols);
762
763 // Default value for the new columns: empty string.
764 for (int i = old_cols; i < cols; i++) {
765 m_table->horizontalHeader()->setLabel(i, "");
766 m_table->setColumnWidth(i, COLUMNWIDTH);
767 }
768
769 m_modified = true;
770 }
771 else if (cols < m_table->numCols()) {
772 bool ask_user = false;
773
774 // Check if the last column is empty.
775 for (int row=0; row<m_table->numRows(); row++) {
776 if (!m_table->text(row, cols).isEmpty()) {
777 ask_user = true;
778 break;
779 }
780 }
781
782 // If it is not, ask if the user really wants to shrink the table.
783 if (ask_user && !m_userWantsToShrink
784 && askUserForConfirmation(this) == KMessageBox::Cancel) {
785
786 // The user aborts. Reset the number of rows and return.
787 m_colsSB->setValue(m_table->numCols());
788 return;
789 }
790
791 // Record the fact that the user knows what (s)he is doing.
792 if (ask_user)
793 m_userWantsToShrink = true;
794
795 // Do the actual shrinking.
796 m_table->setNumCols(cols);
797
798 m_modified = true;
799 }
800}
801
802
803// Get the new name for a column header.
804//
805#if 0 // Disabled since the first row / column now contains the labels.
806void kchartDataEditor::column_clicked(int column)
807{
808 bool ok;
809 TQString name = KInputDialog::getText(i18n("Column Name"),
810 i18n("Type a new column name:"),
811 m_table->horizontalHeader()->label(column),
812 &ok, this, 0, new TQRegExpValidator(TQRegExp(".*"), this) );
813
814 // Rename the column.
815 if ( ok ) {
816 m_table->horizontalHeader()->setLabel(column, name);
817 m_modified = true;
818 }
819}
820
821
822// Get the new name for a row header.
823//
824void kchartDataEditor::row_clicked(int row)
825{
826 bool ok;
827 TQString name = KInputDialog::getText(i18n("Row Name"),
828 i18n("Type a new row name:"),
829 m_table->verticalHeader()->label(row),
830 &ok, this, 0, new TQRegExpValidator(TQRegExp(".*"), this) );
831
832 // Rename the row.
833 if ( ok ) {
834 m_table->verticalHeader()->setLabel(row, name);
835 m_modified = true;
836 }
837}
838#endif
839
840
841void kchartDataEditor::tableChanged(int row, int col)
842{
843 if (row <= headerRows())
844 updateColHeaders();
845 if (col <= headerCols())
846 updateRowHeaders();
847
848 m_modified = true;
849}
850
851
852void kchartDataEditor::currentChanged(int row, int col)
853{
854 m_removeRowButton->setEnabled( row != 0 && m_table->numRows() > 2 );
855 m_removeColButton->setEnabled( col != 0 && m_table->numCols() > 2 );
856}
857
858
859void kchartDataEditor::updateRowHeaders()
860{
861 for (int i=0;i<m_table->numRows();i++)
862 {
863 TQHeader* header=m_table->verticalHeader();
864
865 TQString tableCellText=m_table->text(i,0);
866
867 if (tableCellText == TQString())
868 tableCellText=TQString("");
869
870 header->setLabel(header->mapToSection(i),tableCellText);
871 }
872}
873
874void kchartDataEditor::updateColHeaders()
875{
876 for (int i=0;i<m_table->numCols();i++)
877 {
878 TQHeader* header=m_table->horizontalHeader();
879
880 TQString tableCellText=m_table->text(0,i);
881
882 if (tableCellText == TQString())
883 tableCellText=TQString("");
884
885 header->setLabel(header->mapToSection(i),tableCellText);
886 }
887}
888
889
890// This is a reimplementation of a slot defined in KDialogBase. The
891// reason for the reimplementation is that we need to emit the signal
892// with a pointer to this so that we can get the data.
893//
894void kchartDataEditor::slotApply()
895{
896 emit applyClicked(this);
897}
898
899
900} //KChart namespace
Provide access to the chart axis parameters.