1
/* This file is part of the KDE project
3
Copyright 2007-2008 Johannes Simon <johannes.simon@gmail.com>
4
Copyright 2009 Inge Wallin <inge@lysator.liu.se>
6
This library is free software; you can redistribute it and/or
7
modify it under the terms of the GNU Library General Public
8
License as published by the Free Software Foundation; either
9
version 2 of the License, or (at your option) any later version.
11
This library is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
Library General Public License for more details.
16
You should have received a copy of the GNU Library General Public License
17
along with this library; see the file COPYING.LIB. If not, write to
18
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19
Boston, MA 02110-1301, USA.
23
#include "ChartConfigWidget.h"
26
#include <QButtonGroup>
28
#include <QGridLayout>
29
#include <QHBoxLayout>
30
#include <QVBoxLayout>
31
#include <QToolButton>
36
#include <KIconLoader>
38
#include <KMessageBox>
39
#include <KColorButton>
42
#include <interfaces/KoChartModel.h>
45
#include <KDChartChart>
46
#include <KDChartPosition>
47
#include <KDChartCartesianAxis>
48
#include <KDChartGridAttributes>
49
#include <KDChartAbstractCartesianDiagram>
50
#include <KDChartLegend>
51
#include <KDChartDataValueAttributes>
54
#include "ChartProxyModel.h"
59
#include "ui_ChartTableEditor.h"
60
#include "ui_ChartConfigWidget.h"
61
#include "NewAxisDialog.h"
62
#include "AxisScalingDialog.h"
63
#include "CellRegionDialog.h"
64
#include "TableEditorDialog.h"
65
#include "commands/ChartTypeCommand.h"
66
#include "CellRegionStringValidator.h"
67
#include "ChartTableModel.h"
68
#include "TableSource.h"
70
using namespace KChart;
73
class ChartConfigWidget::Private
76
Private( QWidget *parent );
79
// The owner of this struct.
82
// Basic properties of the chart.
87
// Layouts and widgets.
88
QVBoxLayout *leftLayout;
89
QVBoxLayout *rightLayout;
90
Ui::ChartConfigWidget ui;
91
bool isExternalDataSource;
94
QMenu *dataSetBarChartMenu;
95
QMenu *dataSetLineChartMenu;
96
QMenu *dataSetAreaChartMenu;
98
// chart type selection actions
99
QAction *normalBarChartAction;
100
QAction *stackedBarChartAction;
101
QAction *percentBarChartAction;
103
QAction *normalLineChartAction;
104
QAction *stackedLineChartAction;
105
QAction *percentLineChartAction;
107
QAction *normalAreaChartAction;
108
QAction *stackedAreaChartAction;
109
QAction *percentAreaChartAction;
111
QAction *circleChartAction;
112
QAction *ringChartAction;
113
QAction *radarChartAction;
115
QAction *scatterChartAction;
116
QAction *bubbleChartAction;
118
QAction *stockChartAction;
119
QAction *surfaceChartAction;
120
QAction *ganttChartAction;
122
// chart type selection actions for datasets
123
QAction *dataSetNormalBarChartAction;
124
QAction *dataSetStackedBarChartAction;
125
QAction *dataSetPercentBarChartAction;
127
QAction *dataSetNormalLineChartAction;
128
QAction *dataSetStackedLineChartAction;
129
QAction *dataSetPercentLineChartAction;
131
QAction *dataSetNormalAreaChartAction;
132
QAction *dataSetStackedAreaChartAction;
133
QAction *dataSetPercentAreaChartAction;
135
QAction *dataSetCircleChartAction;
136
QAction *dataSetRingChartAction;
137
QAction *dataSetRadarChartAction;
138
QAction *dataSetScatterChartAction;
139
QAction *dataSetBubbleChartAction;
140
QAction *dataSetStockChartAction;
141
QAction *dataSetSurfaceChartAction;
142
QAction *dataSetGanttChartAction;
144
// Table Editor (a.k.a. the data editor)
145
TableEditorDialog *tableEditorDialog;
146
// Source containing all tables the chart uses (name/model pairs)
147
TableSource *tableSource;
150
QButtonGroup *positionButtonGroup;
151
int lastHorizontalAlignment;
152
int lastVerticalAlignment;
153
KDChart::Position fixedPosition;
154
KDChart::Position lastFixedPosition;
157
int selectedDataSet_CellRegionDialog;
160
QList<Axis*> dataSetAxes;
162
QList<DataSet*> dataSets;
165
NewAxisDialog newAxisDialog;
166
AxisScalingDialog axisScalingDialog;
167
CellRegionDialog cellRegionDialog;
169
CellRegionStringValidator *cellRegionStringValidator;
173
ChartConfigWidget::Private::Private( QWidget *parent )
174
: tableEditorDialog( 0 )
175
, newAxisDialog( parent )
176
, axisScalingDialog( parent )
177
, cellRegionDialog( parent )
180
lastHorizontalAlignment = 1; // Qt::AlignCenter
181
lastVerticalAlignment = 1; // Qt::AlignCenter
182
fixedPosition = KDChart::Position::East;
183
lastFixedPosition = KDChart::Position::East;
188
type = KChart::LastChartType;
189
subtype = KChart::NoChartSubtype;
192
isExternalDataSource = false;
193
cellRegionStringValidator = 0;
195
dataSetBarChartMenu = 0;
196
dataSetLineChartMenu = 0;
197
dataSetAreaChartMenu = 0;
198
dataSetNormalBarChartAction = 0;
199
dataSetStackedBarChartAction = 0;
200
dataSetPercentBarChartAction = 0;
201
dataSetNormalLineChartAction = 0;
202
dataSetStackedLineChartAction = 0;
203
dataSetPercentLineChartAction = 0;
204
dataSetNormalAreaChartAction = 0;
205
dataSetStackedAreaChartAction = 0;
206
dataSetPercentAreaChartAction = 0;
207
dataSetCircleChartAction = 0;
208
dataSetRingChartAction = 0;
209
dataSetScatterChartAction = 0;
210
dataSetRadarChartAction = 0;
211
dataSetStockChartAction = 0;
212
dataSetBubbleChartAction = 0;
213
dataSetSurfaceChartAction = 0;
214
dataSetGanttChartAction = 0;
217
ChartConfigWidget::Private::~Private()
222
// ================================================================
223
// class ChartConfigWidget
226
// 1) Allow user to change axis' "visible" property
229
* Returns, if existent, the name of the icon representing
230
* a given chart type, following the KDE4 icon naming convention.
232
static QString chartTypeIcon( ChartType type, ChartSubtype subtype )
237
case NormalChartSubtype:
238
return "office-chart-bar";
239
case StackedChartSubtype:
240
return "office-chart-bar-stacked";
241
case PercentChartSubtype:
242
return "office-chart-bar-percentage";
244
Q_ASSERT( "Invalid bar chart subtype!" );
248
case NormalChartSubtype:
249
return "office-chart-line";
250
case StackedChartSubtype:
251
return "office-chart-line-stacked";
252
case PercentChartSubtype:
253
return "office-chart-line-percentage";
255
Q_ASSERT( "Invalid line chart subtype!" );
259
case NormalChartSubtype:
260
return "office-chart-area";
261
case StackedChartSubtype:
262
return "office-chart-area-stacked";
263
case PercentChartSubtype:
264
return "office-chart-area-percentage";
266
Q_ASSERT( "Invalid area chart subtype!" );
268
case CircleChartType:
269
return "office-chart-pie";
271
return "office-chart-ring";
273
return "office-chart-polar";
281
ChartConfigWidget::ChartConfigWidget()
282
: d( new Private( this ) )
284
setObjectName("Chart Type");
285
d->ui.setupUi( this );
287
// Chart type button with its associated menu
288
QMenu *chartTypeMenu = new QMenu( this );
289
chartTypeMenu->setIcon( KIcon( "office-chart-bar" ) );
292
QMenu *barChartMenu = chartTypeMenu->addMenu( KIcon( "office-chart-bar" ), i18n( "Bar Chart" ) );
293
d->normalBarChartAction = barChartMenu->addAction( KIcon( "office-chart-bar" ), i18n("Normal") );
294
d->stackedBarChartAction = barChartMenu->addAction( KIcon( "office-chart-bar-stacked" ), i18n("Stacked") );
295
d->percentBarChartAction = barChartMenu->addAction( KIcon( "office-chart-bar-percentage" ), i18n("Percent") );
298
QMenu *lineChartMenu = chartTypeMenu->addMenu( KIcon( "office-chart-line" ), i18n( "Line Chart" ) );
299
d->normalLineChartAction = lineChartMenu->addAction( KIcon( "office-chart-line" ), i18n("Normal") );
300
d->stackedLineChartAction = lineChartMenu->addAction( KIcon( "office-chart-line-stacked" ), i18n("Stacked") );
301
d->percentLineChartAction = lineChartMenu->addAction( KIcon( "office-chart-line-percentage" ), i18n("Percent") );
304
QMenu *areaChartMenu = chartTypeMenu->addMenu( KIcon( "office-chart-area" ), i18n( "Area Chart" ) );
305
d->normalAreaChartAction = areaChartMenu->addAction( KIcon( "office-chart-area" ), i18n("Normal") );
306
d->stackedAreaChartAction = areaChartMenu->addAction( KIcon( "office-chart-area-stacked" ), i18n("Stacked") );
307
d->percentAreaChartAction = areaChartMenu->addAction( KIcon( "office-chart-area-percentage" ), i18n("Percent") );
309
chartTypeMenu->addSeparator();
311
// Circular charts: pie and ring
312
d->circleChartAction = chartTypeMenu->addAction( KIcon( "office-chart-pie" ), i18n("Pie Chart") );
313
d->ringChartAction = chartTypeMenu->addAction( KIcon( "office-chart-ring" ), i18n("Ring Chart") );
315
chartTypeMenu->addSeparator();
317
// Polar charts: radar
318
d->radarChartAction = chartTypeMenu->addAction( KIcon( "office-chart-polar" ), i18n("Polar Chart") );
320
chartTypeMenu->addSeparator();
322
// X/Y charts: scatter and bubble
323
d->scatterChartAction = chartTypeMenu->addAction( KIcon( "office-chart-scatter" ), i18n("Scatter Chart") );
324
d->bubbleChartAction = chartTypeMenu->addAction( i18n("Bubble Chart") );
326
chartTypeMenu->addSeparator();
328
d->stockChartAction = chartTypeMenu->addAction( i18n("Stock Chart") );
329
d->surfaceChartAction = chartTypeMenu->addAction( i18n("Surface Chart") );
330
d->surfaceChartAction->setEnabled( false );
331
d->ganttChartAction = chartTypeMenu->addAction( i18n("Gantt Chart") );
332
d->ganttChartAction->setEnabled( false );
334
d->ui.chartTypeMenu->setMenu( chartTypeMenu );
335
d->ui.chartTypeMenu->setIconSize( QSize( 32, 32 ) );
337
connect( chartTypeMenu, SIGNAL( triggered( QAction* ) ),
338
this, SLOT( chartTypeSelected( QAction* ) ) );
340
// Data set chart type button
341
QMenu *dataSetChartTypeMenu = new QMenu( this );
343
// Default chart type is a bar chart
344
dataSetChartTypeMenu->setIcon( KIcon( "chart-bar" ) );
347
d->dataSetBarChartMenu = dataSetChartTypeMenu->addMenu( KIcon( "office-chart-bar" ), "Bar Chart" );
348
d->dataSetNormalBarChartAction = d->dataSetBarChartMenu->addAction( KIcon( "office-chart-bar" ), i18n("Normal") );
349
d->dataSetStackedBarChartAction = d->dataSetBarChartMenu->addAction( KIcon( "office-chart-bar-stacked" ), i18n("Stacked") );
350
d->dataSetPercentBarChartAction = d->dataSetBarChartMenu->addAction( KIcon( "office-chart-bar-percentage" ), i18n("Percent") );
352
d->dataSetLineChartMenu = dataSetChartTypeMenu->addMenu( KIcon( "office-chart-line" ), "Line Chart" );
353
d->dataSetNormalLineChartAction = d->dataSetLineChartMenu->addAction( KIcon( "office-chart-line" ), i18n("Normal") );
354
d->dataSetStackedLineChartAction = d->dataSetLineChartMenu->addAction( KIcon( "office-chart-line-stacked" ), i18n("Stacked") );
355
d->dataSetPercentLineChartAction = d->dataSetLineChartMenu->addAction( KIcon( "office-chart-line-percentage" ), i18n("Percent") );
357
d->dataSetAreaChartMenu = dataSetChartTypeMenu->addMenu( KIcon( "office-chart-area" ), "Area Chart" );
358
d->dataSetNormalAreaChartAction = d->dataSetAreaChartMenu->addAction( KIcon( "office-chart-area" ), i18n("Normal") );
359
d->dataSetStackedAreaChartAction = d->dataSetAreaChartMenu->addAction( KIcon( "office-chart-area-stacked" ), i18n("Stacked") );
360
d->dataSetPercentAreaChartAction = d->dataSetAreaChartMenu->addAction( KIcon( "office-chart-area-percentage" ), i18n("Percent") );
362
d->dataSetCircleChartAction = dataSetChartTypeMenu->addAction( KIcon( "office-chart-pie" ), i18n("Pie Chart") );
363
d->dataSetRingChartAction = dataSetChartTypeMenu->addAction( KIcon( "office-chart-ring" ), i18n("Ring Chart") );
364
d->dataSetRadarChartAction = dataSetChartTypeMenu->addAction( KIcon( "office-chart-polar" ), i18n("Polar Chart") );
365
d->dataSetStockChartAction = dataSetChartTypeMenu->addAction( i18n("Stock Chart") );
366
d->dataSetBubbleChartAction = dataSetChartTypeMenu->addAction( i18n("Bubble Chart") );
368
d->dataSetScatterChartAction = dataSetChartTypeMenu->addAction( KIcon( "office-chart-scatter" ), i18n("Scatter Chart") );
370
d->ui.dataSetChartTypeMenu->setMenu( dataSetChartTypeMenu );
372
connect( dataSetChartTypeMenu, SIGNAL( triggered( QAction* ) ),
373
this, SLOT( dataSetChartTypeSelected( QAction* ) ) );
375
connect( d->ui.dataSetHasChartType, SIGNAL( toggled( bool ) ),
376
this, SLOT( ui_dataSetHasChartTypeChanged( bool ) ) );
379
connect( d->ui.showTitle, SIGNAL( toggled( bool ) ),
380
this, SIGNAL( showTitleChanged( bool ) ) );
381
connect( d->ui.showSubTitle, SIGNAL( toggled( bool ) ),
382
this, SIGNAL( showSubTitleChanged( bool ) ) );
383
connect( d->ui.showFooter, SIGNAL( toggled( bool ) ),
384
this, SIGNAL( showFooterChanged( bool ) ) );
386
connect( d->ui.threeDLook, SIGNAL( toggled( bool ) ),
387
this, SLOT( setThreeDMode( bool ) ) );
388
connect( d->ui.showLegend, SIGNAL( toggled( bool ) ),
389
this, SIGNAL( showLegendChanged( bool ) ) );
392
connect( d->ui.datasetBrush, SIGNAL( changed( const QColor& ) ),
393
this, SLOT( datasetBrushSelected( const QColor& ) ) );
394
connect( d->ui.datasetPen, SIGNAL( changed( const QColor& ) ),
395
this, SLOT( datasetPenSelected( const QColor& ) ) );
396
connect( d->ui.datasetShowValues, SIGNAL( toggled( bool ) ),
397
this, SLOT( ui_datasetShowValuesChanged( bool ) ) );
398
connect( d->ui.gapBetweenBars, SIGNAL( valueChanged( int ) ),
399
this, SIGNAL( gapBetweenBarsChanged( int ) ) );
400
connect( d->ui.gapBetweenSets, SIGNAL( valueChanged( int ) ),
401
this, SIGNAL( gapBetweenSetsChanged( int ) ) );
402
connect( d->ui.pieExplodeFactor, SIGNAL( valueChanged( int ) ),
403
this, SLOT( ui_dataSetPieExplodeFactorChanged( int ) ) );
406
connect( d->ui.legendTitle, SIGNAL( textChanged( const QString& ) ),
407
this, SIGNAL( legendTitleChanged( const QString& ) ) );
408
connect( d->ui.legendShowFrame, SIGNAL( toggled( bool ) ),
409
this, SIGNAL( legendShowFrameChanged( bool ) ) );
410
connect( d->ui.legendOrientationIsVertical, SIGNAL( toggled( bool ) ),
411
this, SLOT( setLegendOrientationIsVertical( bool ) ) );
413
// Second part of "Plot Area" tab.
414
// FIXME: Is there any particular reason it's separated from the Labels?
415
d->ui.addAxis->setIcon( KIcon( "list-add" ) );
416
d->ui.removeAxis->setIcon( KIcon( "list-remove" ) );
418
connect( d->ui.axisTitle, SIGNAL( textChanged( const QString& ) ),
419
this, SLOT( ui_axisTitleChanged( const QString& ) ) );
420
connect( d->ui.axisShowTitle, SIGNAL( toggled( bool ) ),
421
this, SLOT( ui_axisShowTitleChanged( bool ) ) );
422
connect( d->ui.axisShowGridLines, SIGNAL( toggled( bool ) ),
423
this, SLOT( ui_axisShowGridLinesChanged( bool ) ) );
424
connect ( d->ui.axes, SIGNAL( currentIndexChanged( int ) ),
425
this, SLOT( ui_axisSelectionChanged( int ) ) );
427
connect( d->ui.dataSets, SIGNAL( currentIndexChanged( int ) ),
428
this, SLOT( ui_dataSetSelectionChanged( int ) ) );
429
connect( d->ui.dataSetAxes, SIGNAL( currentIndexChanged( int ) ),
430
this, SLOT( ui_dataSetAxisSelectionChanged( int ) ) );
435
// Activate spin box "acceleration" for "Data Sets"->"Foo Properties"
436
// where Foo is one of the chart types with special property settings.
437
d->ui.gapBetweenBars->setAccelerated( true );
438
d->ui.gapBetweenSets->setAccelerated( true );
439
d->ui.pieExplodeFactor->setAccelerated( true );
442
ChartConfigWidget::~ChartConfigWidget()
447
void ChartConfigWidget::deleteSubDialogs()
449
if ( d->tableEditorDialog ) {
450
delete d->tableEditorDialog;
451
d->tableEditorDialog = 0;
455
void ChartConfigWidget::open( KoShape* shape )
461
// There are 3 shapes that we can select: the full chart shape,
462
// the plotarea and the legend.
464
// Find the selected shape and adapt the tool option window to
465
// which of the subshapes of the chart widget that was actually
466
// selected. Then select the tab depending on which one it was.
468
// First see if it was the chart shape itself.
469
d->shape = dynamic_cast<ChartShape*>( shape );
471
// If not, try to see if it was the plot area.
472
PlotArea *plotArea = dynamic_cast<PlotArea*>( shape );
474
d->shape = plotArea->parent();
475
d->ui.tabWidget->setCurrentIndex( 0 );
478
// And finally try if it was the legend.
479
Legend *legend = dynamic_cast<Legend*>( shape );
485
d->shape = dynamic_cast<ChartShape*>( shape->parent() );
486
Q_ASSERT( d->shape );
487
d->ui.tabWidget->setCurrentIndex( 2 );
491
d->tableSource = d->shape->tableSource();
493
// NOTE: There's no single source table anymore, a KSpread workbook allows multiple to be used with a chart.
494
// KoChart::ChartModel *spreadSheetModel = qobject_cast<KoChart::ChartModel*>( d->shape->internalModel() );
495
// NOTE: This is obsolete, ChartShape::usesInternalModelOnly() is now used instead.
496
// ChartTableModel *tableModel = qobject_cast<ChartTableModel*>( d->shape->model() );
497
// d->isExternalDataSource = ( spreadSheetModel != 0 && tableModel == 0 );
499
// Update the axis titles
500
//d->ui.xAxisTitle->setText( ((KDChart::AbstractCartesianDiagram*)d->shape->chart()->coordinatePlane()->diagram())->axes()[0]->titleText() );
501
//d->ui.yAxisTitle->setText( ((KDChart::AbstractCartesianDiagram*)d->shape->chart()->coordinatePlane()->diagram())->axes()[1]->titleText() );
503
// Update the legend title
504
//d->ui.legendTitle->setText( d->shape->legend()->title() );
506
// Fill the data table
507
if ( !d->shape->usesInternalModelOnly() ) {
508
// FIXME: CellRegion itself together with a TableSource should now be used
509
// to validate the correctness of a table range address.
511
d->cellRegionStringValidator = new CellRegionStringValidator( spreadSheetModel );
512
d->cellRegionDialog.labelDataRegion->setValidator( d->cellRegionStringValidator );
513
d->cellRegionDialog.xDataRegion->setValidator( d->cellRegionStringValidator );
514
d->cellRegionDialog.yDataRegion->setValidator( d->cellRegionStringValidator );
515
d->cellRegionDialog.categoryDataRegion->setValidator( d->cellRegionStringValidator );
518
// If the data source is external, the editData button opens a
519
// dialog to edit the data ranges instead of the data itself.
520
d->ui.editData->setText( i18n( "Data Ranges..." ) );
521
connect( d->ui.editData, SIGNAL( clicked( bool ) ),
522
this, SLOT( slotShowCellRegionDialog() ) );
523
connect( d->cellRegionDialog.xDataRegion, SIGNAL( editingFinished() ),
524
this, SLOT( ui_dataSetXDataRegionChanged() ) );
525
connect( d->cellRegionDialog.yDataRegion, SIGNAL( editingFinished() ),
526
this, SLOT( ui_dataSetYDataRegionChanged() ) );
527
connect( d->cellRegionDialog.labelDataRegion, SIGNAL( editingFinished() ),
528
this, SLOT( ui_dataSetLabelDataRegionChanged() ) );
529
//connect( d->cellRegionDialog.customDataRegion, SIGNAL( textEdited( const QString&) ),
530
// this, SLOT( ui_dataSetCustomDataRegionChanged( const QString& ) ) );
531
connect( d->cellRegionDialog.categoryDataRegion, SIGNAL( editingFinished() ),
532
this, SLOT( ui_dataSetCategoryDataRegionChanged() ) );
533
connect( d->cellRegionDialog.dataSets, SIGNAL( currentIndexChanged( int ) ),
534
this, SLOT( ui_dataSetSelectionChanged_CellRegionDialog( int ) ) );
537
// This part is run when the data source is not external,
538
// i.e. the data is handled by the chart shape itself.
539
connect( d->ui.editData, SIGNAL( clicked( bool ) ),
540
this, SLOT( slotShowTableEditor() ) );
546
void ChartConfigWidget::save()
548
ChartTypeCommand command( d->shape );
549
command.setChartType( d->type, d->subtype );
553
KAction* ChartConfigWidget::createAction()
558
void ChartConfigWidget::chartTypeSelected( QAction *action )
560
ChartType type = LastChartType;
561
ChartSubtype subtype = NoChartSubtype;
564
if ( action == d->normalBarChartAction ) {
566
subtype = NormalChartSubtype;
567
} else if ( action == d->stackedBarChartAction ) {
569
subtype = StackedChartSubtype;
570
} else if ( action == d->percentBarChartAction ) {
572
subtype = PercentChartSubtype;
576
else if ( action == d->normalLineChartAction ) {
577
type = LineChartType;
578
subtype = NormalChartSubtype;
579
} else if ( action == d->stackedLineChartAction ) {
580
type = LineChartType;
581
subtype = StackedChartSubtype;
582
} else if ( action == d->percentLineChartAction ) {
583
type = LineChartType;
584
subtype = PercentChartSubtype;
588
else if ( action == d->normalAreaChartAction ) {
589
type = AreaChartType;
590
subtype = NormalChartSubtype;
591
} else if ( action == d->stackedAreaChartAction ) {
592
type = AreaChartType;
593
subtype = StackedChartSubtype;
594
} else if ( action == d->percentAreaChartAction ) {
595
type = AreaChartType;
596
subtype = PercentChartSubtype;
599
// also known as polar chart.
600
else if ( action == d->radarChartAction ) {
601
type = RadarChartType;
602
subtype = NoChartSubtype;
605
// Also known as pie chart
606
else if ( action == d->circleChartAction ) {
607
type = CircleChartType;
608
subtype = NoChartSubtype;
610
else if ( action == d->ringChartAction ) {
611
type = RingChartType;
612
subtype = NoChartSubtype;
615
else if ( action == d->scatterChartAction ) {
616
type = ScatterChartType;
617
subtype = NoChartSubtype;
620
else if ( action == d->stockChartAction ) {
621
type = StockChartType;
622
subtype = NoChartSubtype;
625
else if ( action == d->bubbleChartAction ) {
626
type = BubbleChartType;
627
subtype = NoChartSubtype;
630
else if ( action == d->surfaceChartAction ) {
631
type = SurfaceChartType;
632
subtype = NoChartSubtype;
635
else if ( action == d->ganttChartAction ) {
636
type = GanttChartType;
637
subtype = NoChartSubtype;
641
// o Make sure polar and cartesian plots can't conflict and
642
// don't allow the user to mix these two types
643
// o Hide axis configuration options for polar plots
644
if ( isPolar( type ) ) {
645
setPolarChartTypesEnabled( true );
646
setCartesianChartTypesEnabled( false );
648
// Pie charts and ring charts have no axes but radar charts do.
649
// Disable choosing of attached axis if there is none.
650
bool hasAxes = !(type == CircleChartType || type == RingChartType );
651
d->ui.axisConfiguration->setEnabled( hasAxes );
652
d->ui.dataSetAxes->setEnabled( hasAxes );
653
d->ui.dataSetHasChartType->setEnabled( hasAxes );
654
d->ui.dataSetChartTypeMenu->setEnabled( hasAxes );
656
setPolarChartTypesEnabled( false );
657
setCartesianChartTypesEnabled( true );
659
// All the cartesian chart types have axes.
660
d->ui.axisConfiguration->setEnabled( true );
661
d->ui.dataSetAxes->setEnabled( true );
662
d->ui.dataSetHasChartType->setEnabled( true );
663
d->ui.dataSetChartTypeMenu->setEnabled( true );
666
emit chartTypeChanged( type );
667
emit chartSubTypeChanged( subtype );
673
* Enabled/Disabled menu actions to set a polar chart type
675
void ChartConfigWidget::setPolarChartTypesEnabled( bool enabled )
677
d->dataSetCircleChartAction->setEnabled( enabled );
678
d->dataSetRingChartAction->setEnabled( enabled );
679
d->dataSetRadarChartAction->setEnabled( enabled );
683
* Enabled/Disabled menu actions to set a cartesian chart type
685
void ChartConfigWidget::setCartesianChartTypesEnabled( bool enabled )
687
d->dataSetBarChartMenu->setEnabled( enabled );
688
d->dataSetLineChartMenu->setEnabled( enabled );
689
d->dataSetAreaChartMenu->setEnabled( enabled );
690
d->dataSetScatterChartAction->setEnabled( enabled );
691
d->dataSetStockChartAction->setEnabled( enabled );
692
d->dataSetBubbleChartAction->setEnabled( enabled );
693
// FIXME: Enable for:
700
void ChartConfigWidget::ui_dataSetPieExplodeFactorChanged( int percent )
702
if ( d->selectedDataSet < 0 )
705
DataSet *dataSet = d->dataSets[ d->selectedDataSet ];
710
emit pieExplodeFactorChanged( dataSet, percent );
713
void ChartConfigWidget::ui_dataSetHasChartTypeChanged( bool b )
715
if ( d->selectedDataSet < 0 )
719
DataSet *dataSet = d->dataSets[ d->selectedDataSet ];
724
emit dataSetChartTypeChanged( dataSet, LastChartType );
725
emit dataSetChartSubTypeChanged( dataSet, NoChartSubtype );
726
d->ui.dataSetChartTypeMenu->setIcon( QIcon() );
730
void ChartConfigWidget::dataSetChartTypeSelected( QAction *action )
732
if ( d->selectedDataSet < 0 )
735
ChartType type = LastChartType;
736
ChartSubtype subtype = NoChartSubtype;
738
if ( action == d->dataSetNormalBarChartAction ) {
740
subtype = NormalChartSubtype;
741
} else if ( action == d->dataSetStackedBarChartAction ) {
743
subtype = StackedChartSubtype;
744
} else if ( action == d->dataSetPercentBarChartAction ) {
746
subtype = PercentChartSubtype;
749
else if ( action == d->dataSetNormalLineChartAction ) {
750
type = LineChartType;
751
subtype = NormalChartSubtype;
752
} else if ( action == d->dataSetStackedLineChartAction ) {
753
type = LineChartType;
754
subtype = StackedChartSubtype;
755
} else if ( action == d->dataSetPercentLineChartAction ) {
756
type = LineChartType;
757
subtype = PercentChartSubtype;
760
else if ( action == d->dataSetNormalAreaChartAction ) {
761
type = AreaChartType;
762
subtype = NormalChartSubtype;
763
} else if ( action == d->dataSetStackedAreaChartAction ) {
764
type = AreaChartType;
765
subtype = StackedChartSubtype;
766
} else if ( action == d->dataSetPercentAreaChartAction ) {
767
type = AreaChartType;
768
subtype = PercentChartSubtype;
771
else if ( action == d->dataSetRadarChartAction )
772
type = RadarChartType;
773
else if ( action == d->dataSetCircleChartAction )
774
type = CircleChartType;
775
else if ( action == d->dataSetRingChartAction )
776
type = RingChartType;
777
else if ( action == d->dataSetScatterChartAction )
778
type = ScatterChartType;
779
else if ( action == d->dataSetStockChartAction )
780
type = StockChartType;
781
else if ( action == d->dataSetBubbleChartAction )
782
type = BubbleChartType;
784
// FIXME: Not supported by KChart yet:
788
DataSet *dataSet = d->dataSets[ d->selectedDataSet ];
793
QString iconName = chartTypeIcon( type, subtype );
794
if ( !iconName.isEmpty() )
795
d->ui.dataSetChartTypeMenu->setIcon( KIcon( iconName ) );
797
emit dataSetChartTypeChanged( dataSet, type );
798
emit dataSetChartSubTypeChanged( dataSet, subtype );
803
void ChartConfigWidget::chartSubTypeSelected( int type )
805
d->subtype = (ChartSubtype) type;
806
emit chartSubTypeChanged( d->subtype );
809
void ChartConfigWidget::datasetBrushSelected( const QColor& color )
811
if ( d->selectedDataSet < 0 )
814
emit datasetBrushChanged( d->dataSets[ d->selectedDataSet ], color );
817
void ChartConfigWidget::datasetPenSelected( const QColor& color )
819
if ( d->selectedDataSet < 0 )
822
emit datasetPenChanged( d->dataSets[ d->selectedDataSet ], color );
825
void ChartConfigWidget::setThreeDMode( bool threeD )
827
d->threeDMode = threeD;
828
emit threeDModeToggled( threeD );
834
* Only some chart types support a 3D mode in KD Chart.
836
static bool supportsThreeD( ChartType type )
842
case CircleChartType:
843
case BubbleChartType:
851
static QString nonEmptyAxisTitle( Axis *axis, int index )
853
QString title = axis->titleText();
854
if ( title.isEmpty() )
855
// TODO (post-2.3): Use "X Axis" or "Y Axis" as default labels instead
856
title = i18n( "Axis %1", index + 1 );
860
void ChartConfigWidget::update()
865
// We only want to update this widget according to the current
866
// state of the shape
867
// Note that this does not recursively block signals but only those
868
// of ChartConfigWidget.
869
blockSignals( true );
871
// Update cartesian diagram-specific properties
872
// Always update, as e.g. name of axis could have changed
873
// if ( d->axes != d->shape->plotArea()->axes() ) {
874
// Remove old items from the combo box
876
d->ui.dataSetAxes->clear();
877
// Sync the internal list
878
d->axes = d->shape->plotArea()->axes();
879
d->dataSetAxes.clear();
881
if ( !d->axes.isEmpty() ) {
882
foreach ( Axis *axis, d->axes ) {
883
QString title = nonEmptyAxisTitle( axis, d->axes.indexOf( axis ) );
884
// This automatically calls ui_axisSelectionChanged()
885
// after first insertion
886
d->ui.axes->addItem( title );
887
if ( axis->dimension() == YAxisDimension ) {
888
d->dataSetAxes.append( axis );
889
d->ui.dataSetAxes->blockSignals( true );
890
d->ui.dataSetAxes->addItem( title );
891
d->ui.dataSetAxes->blockSignals( false );
895
d->ui.axisShowGridLines->blockSignals( true );
896
d->ui.axisShowGridLines->setChecked( false );
897
d->ui.axisShowGridLines->setEnabled( false );
898
d->ui.axisShowGridLines->blockSignals( false );
900
d->ui.axisShowTitle->blockSignals( true );
901
d->ui.axisShowTitle->setChecked( false );
902
d->ui.axisShowTitle->setEnabled( false );
903
d->ui.axisShowTitle->blockSignals( false );
905
d->ui.axisTitle->blockSignals( true );
906
d->ui.axisTitle->setText( "" );
907
d->ui.axisTitle->setEnabled( false );
908
d->ui.axisTitle->blockSignals( false );
912
// Update "Labels" section in "Plot Area" tab
913
d->ui.showTitle->setChecked( d->shape->title()->isVisible() );
914
d->ui.showSubTitle->setChecked( d->shape->subTitle()->isVisible() );
915
d->ui.showFooter->setChecked( d->shape->footer()->isVisible() );
917
// Update "Bar Properties" in "Data Sets" tab
918
d->ui.gapBetweenBars->setValue( d->shape->plotArea()->gapBetweenBars() );
919
d->ui.gapBetweenSets->setValue( d->shape->plotArea()->gapBetweenSets() );
921
if ( d->type != d->shape->chartType()
922
|| d->subtype != d->shape->chartSubType() )
924
// Update the chart type specific settings in the "Data Sets" tab
925
bool needSeparator = false;
926
if ( d->shape->chartType() == BarChartType ) {
927
d->ui.barProperties->show();
928
d->ui.pieProperties->hide();
929
needSeparator = true;
930
} else if ( d->shape->chartType() == CircleChartType ) {
931
d->ui.barProperties->hide();
932
d->ui.pieProperties->show();
933
needSeparator = true;
934
} else if ( d->shape->chartType() == RingChartType ) {
935
d->ui.barProperties->hide();
936
d->ui.pieProperties->show();
937
needSeparator = true;
939
d->ui.barProperties->hide();
940
d->ui.pieProperties->hide();
942
d->ui.propertiesSeparator->setVisible( needSeparator );
944
// Set the chart type icon in the chart type button.
945
QString iconName = chartTypeIcon( d->shape->chartType(), d->shape->chartSubType() );
946
if ( !iconName.isEmpty() )
947
d->ui.chartTypeMenu->setIcon( KIcon( iconName ) );
949
// Make sure we only allow legal chart type combinations
950
if ( isPolar( d->shape->chartType() ) ) {
951
setPolarChartTypesEnabled( true );
952
setCartesianChartTypesEnabled( false );
954
setPolarChartTypesEnabled( false );
955
setCartesianChartTypesEnabled( true );
958
// ...and finally save the new chart type and subtype.
959
d->type = d->shape->chartType();
960
d->subtype = d->shape->chartSubType();
963
// If the datasets have changed, set up the new ones.
964
if ( d->shape->plotArea()->dataSets() != d->dataSets ) {
965
d->dataSets = d->shape->plotArea()->dataSets();
966
d->ui.dataSets->clear();
967
d->cellRegionDialog.dataSets->clear();
968
foreach ( DataSet *dataSet, d->dataSets ) {
969
QString title = dataSet->labelData().toString();
970
if ( title.isEmpty() )
971
title = i18n( "Data Set %1", d->ui.dataSets->count() + 1 );
972
d->ui.dataSets->addItem( title );
973
d->cellRegionDialog.dataSets->addItem( title );
976
// Select the first data set
977
ui_dataSetSelectionChanged( 0 );
978
ui_dataSetSelectionChanged_CellRegionDialog( 0 );
981
// If the "3D" checkbox is checked, then adapt the chart to that.
982
bool enableThreeDOption = supportsThreeD( d->type );
983
d->threeDMode = enableThreeDOption && d->shape->isThreeD();
984
d->shape->setThreeD( d->threeDMode );
985
d->ui.threeDLook->setChecked( d->threeDMode );
986
d->ui.threeDLook->setEnabled( enableThreeDOption );
988
if ( d->shape->legend() ) {
989
d->ui.legendTitle->blockSignals( true );
990
d->ui.legendTitle->setText( d->shape->legend()->title() );
991
d->ui.legendTitle->blockSignals( false );
994
// "Fill" property of data set doesn't make sense for 2D line
995
// charts, there's nothing to fill.
996
bool enableFill = d->type != LineChartType || d->threeDMode;
997
d->ui.datasetBrush->setEnabled( enableFill );
999
blockSignals( false );
1003
void ChartConfigWidget::slotShowTableEditor()
1005
if ( !d->tableEditorDialog ) {
1006
d->tableEditorDialog = new TableEditorDialog;
1007
d->tableEditorDialog->setProxyModel( d->shape->proxyModel() );
1008
d->tableEditorDialog->setModel( d->shape->internalModel() );
1011
d->tableEditorDialog->show();
1015
void ChartConfigWidget::slotShowCellRegionDialog()
1017
// Update regions of selected dataset
1018
int selectedDataSet = d->cellRegionDialog.dataSets->currentIndex();
1019
ui_dataSetSelectionChanged_CellRegionDialog( selectedDataSet );
1021
d->cellRegionDialog.show();
1025
void ChartConfigWidget::setLegendOrientation( int boxEntryIndex )
1027
Q_UNUSED(boxEntryIndex);
1028
//emit legendOrientationChanged( ( Qt::Orientation ) ( d->ui.orientation->itemData( boxEntryIndex ).toInt() ) );
1031
void ChartConfigWidget::setLegendShowTitle( bool show )
1034
d->ui.legendTitle->setEnabled( true );
1035
emit legendTitleChanged( d->ui.legendTitle->text() );
1037
d->ui.legendTitle->setEnabled( false );
1038
emit legendTitleChanged( "" );
1042
void ChartConfigWidget::setLegendAlignment( int boxEntryIndex )
1044
Q_UNUSED(boxEntryIndex);
1045
if ( d->fixedPosition == KDChart::Position::North
1046
|| d->fixedPosition == KDChart::Position::South ) {
1047
//d->lastHorizontalAlignment = d->ui.alignment->currentIndex();
1048
} else if ( d->fixedPosition == KDChart::Position::East
1049
|| d->fixedPosition == KDChart::Position::West ) {
1050
//d->lastVerticalAlignment = d->ui.alignment->currentIndex();
1052
//emit legendAlignmentChanged( ( Qt::Alignment ) ( d->ui.alignment->itemData( boxEntryIndex ).toInt() ) );
1055
void ChartConfigWidget::setLegendFixedPosition( int buttonGroupIndex )
1057
Q_UNUSED(buttonGroupIndex);
1058
d->lastFixedPosition = d->fixedPosition;
1059
//d->fixedPosition = buttonIndexToFixedPosition[ buttonGroupIndex ];
1060
//emit legendFixedPositionChanged( buttonIndexToFixedPosition[ buttonGroupIndex ] );
1063
void ChartConfigWidget::updateFixedPosition( Position position )
1067
if ( position == KDChart::Position::North
1068
|| position == KDChart::Position::South ) {
1069
d->ui.alignment->setEnabled( true );
1070
d->ui.alignment->setItemText( 0, i18n( "Left" ) );
1071
d->ui.alignment->setItemData( 0, Qt::AlignLeft );
1072
d->ui.alignment->setItemData( 1, Qt::AlignCenter );
1073
d->ui.alignment->setItemText( 2, i18n( "Right" ) );
1074
d->ui.alignment->setItemData( 2, Qt::AlignRight );
1075
// Set the alignment to the one last used for horizontal legend alignment
1076
if ( d->lastFixedPosition != KDChart::Position::North
1077
&& d->lastFixedPosition != KDChart::Position::South ) {
1078
// Make sure that the combobox gets updated. Since we changed the values of the entries,
1079
// same index doesn't mean same value, though it will think so. Solution: Select no entry first
1080
d->ui.alignment->blockSignals( true );
1081
d->ui.alignment->setCurrentIndex( -1 );
1082
d->ui.alignment->blockSignals( false );
1084
d->ui.alignment->setCurrentIndex( d->lastHorizontalAlignment );
1086
} else if ( position == KDChart::Position::East
1087
|| position == KDChart::Position::West ) {
1088
d->ui.alignment->setEnabled( true );
1089
d->ui.alignment->setItemText( 0, i18n( "Top" ) );
1090
d->ui.alignment->setItemData( 0, Qt::AlignTop );
1091
d->ui.alignment->setItemData( 1, Qt::AlignCenter );
1092
d->ui.alignment->setItemText( 2, i18n( "Bottom" ) );
1093
d->ui.alignment->setItemData( 2, Qt::AlignBottom );
1094
// Set the alignment to the one last used for vertical legend alignment
1095
if ( d->lastFixedPosition != KDChart::Position::East
1096
&& d->lastFixedPosition != KDChart::Position::West ) {
1097
// Make sure that the combobox gets updated. Since we changed the values of the entries,
1098
// same index doesn't mean same value, though it will think so. Solution: Select no entry first
1099
d->ui.alignment->blockSignals( true );
1100
d->ui.alignment->setCurrentIndex( -1 );
1101
d->ui.alignment->blockSignals( false );
1103
d->ui.alignment->setCurrentIndex( d->lastVerticalAlignment );
1106
d->ui.alignment->setEnabled( false );
1109
for( int i = 0; i < NUM_FIXED_POSITIONS; i++ ) {
1110
if( position == buttonIndexToFixedPosition[i] ) {
1111
if ( d->positionButtonGroup->checkedId() != i )
1112
d->positionButtonGroup->button( i )->setChecked( true );
1120
void ChartConfigWidget::setupDialogs()
1122
// Adding/removing axes
1123
connect( d->ui.addAxis, SIGNAL( clicked() ),
1124
this, SLOT( ui_addAxisClicked() ) );
1125
connect( d->ui.removeAxis, SIGNAL( clicked() ),
1126
this, SLOT( ui_removeAxisClicked() ) );
1127
connect( &d->newAxisDialog, SIGNAL( accepted() ),
1128
this, SLOT( ui_axisAdded() ) );
1131
connect( d->ui.axisScalingButton, SIGNAL( clicked() ),
1132
this, SLOT( ui_axisScalingButtonClicked() ) );
1133
connect( d->axisScalingDialog.logarithmicScaling, SIGNAL( toggled( bool ) ),
1134
this, SLOT( ui_axisUseLogarithmicScalingChanged( bool ) ) );
1135
connect( d->axisScalingDialog.stepWidth, SIGNAL( valueChanged( double ) ),
1136
this, SLOT( ui_axisStepWidthChanged( double ) ) );
1137
connect ( d->axisScalingDialog.automaticStepWidth, SIGNAL( toggled( bool ) ),
1138
this, SLOT( ui_axisUseAutomaticStepWidthChanged( bool ) ) );
1139
connect( d->axisScalingDialog.subStepWidth, SIGNAL( valueChanged( double ) ),
1140
this, SLOT( ui_axisSubStepWidthChanged( double ) ) );
1141
connect ( d->axisScalingDialog.automaticSubStepWidth, SIGNAL( toggled( bool ) ),
1142
this, SLOT( ui_axisUseAutomaticSubStepWidthChanged( bool ) ) );
1145
void ChartConfigWidget::createActions()
1149
void ChartConfigWidget::setLegendOrientationIsVertical( bool b )
1152
emit legendOrientationChanged( Qt::Vertical );
1154
emit legendOrientationChanged( Qt::Horizontal );
1157
void ChartConfigWidget::ui_axisSelectionChanged( int index )
1159
// Check for valid index
1160
if ( index < 0 || index >= d->axes.size() )
1163
Axis *axis = d->axes[ index ];
1165
// Count how many axes there are of the same dimension
1166
int numAxesOfSameDimension = 0;
1167
foreach ( Axis *a, d->axes )
1168
if ( axis->dimension() == a->dimension() )
1169
numAxesOfSameDimension++;
1171
// Don't let the user remove the last axis of a particular dimension
1172
d->ui.removeAxis->setEnabled( numAxesOfSameDimension > 1 );
1174
d->ui.axisTitle->blockSignals( true );
1175
d->ui.axisTitle->setText( axis->titleText() );
1176
d->ui.axisTitle->blockSignals( false );
1177
d->ui.axisShowTitle->blockSignals( true );
1178
d->ui.axisShowTitle->setChecked( axis->title()->isVisible() );
1179
d->ui.axisShowTitle->blockSignals( false );
1180
d->ui.axisShowGridLines->blockSignals( true );
1181
d->ui.axisShowGridLines->setChecked( axis->showMajorGrid() || axis->showMinorGrid() );
1182
d->ui.axisShowGridLines->blockSignals( false );
1184
d->axisScalingDialog.logarithmicScaling->blockSignals( true );
1185
if ( axis->dimension() == YAxisDimension )
1186
d->axisScalingDialog.logarithmicScaling->setEnabled( true );
1188
d->axisScalingDialog.logarithmicScaling->setEnabled( false );
1189
d->axisScalingDialog.logarithmicScaling->blockSignals( false );
1191
d->axisScalingDialog.stepWidth->blockSignals( true );
1192
d->axisScalingDialog.stepWidth->setValue( axis->majorInterval() );
1193
d->axisScalingDialog.stepWidth->blockSignals( false );
1195
d->axisScalingDialog.subStepWidth->blockSignals( true );
1196
d->axisScalingDialog.subStepWidth->setValue( axis->minorInterval() );
1197
d->axisScalingDialog.subStepWidth->blockSignals( false );
1199
d->axisScalingDialog.automaticStepWidth->blockSignals( true );
1200
d->axisScalingDialog.automaticStepWidth->setChecked( axis->useAutomaticMajorInterval() );
1201
d->axisScalingDialog.stepWidth->setEnabled( !axis->useAutomaticMajorInterval() );
1202
d->axisScalingDialog.automaticStepWidth->blockSignals( false );
1204
d->axisScalingDialog.automaticSubStepWidth->blockSignals( true );
1205
d->axisScalingDialog.automaticSubStepWidth->setChecked( axis->useAutomaticMinorInterval() );
1206
d->axisScalingDialog.subStepWidth->setEnabled( !axis->useAutomaticMinorInterval() );
1207
d->axisScalingDialog.automaticSubStepWidth->blockSignals( false );
1211
void ChartConfigWidget::ui_dataSetXDataRegionChanged()
1213
// Check for valid index
1214
if ( d->selectedDataSet_CellRegionDialog < 0 )
1217
const QString regionString = d->cellRegionDialog.xDataRegion->text();
1218
const CellRegion region( d->tableSource, regionString );
1220
DataSet *dataSet = d->dataSets[ d->selectedDataSet_CellRegionDialog ];
1222
emit dataSetXDataRegionChanged( dataSet, region );
1225
void ChartConfigWidget::ui_dataSetYDataRegionChanged()
1227
// Check for valid index
1228
if ( d->selectedDataSet_CellRegionDialog < 0 )
1231
const QString regionString = d->cellRegionDialog.yDataRegion->text();
1232
const CellRegion region( d->tableSource, regionString );
1234
DataSet *dataSet = d->dataSets[ d->selectedDataSet_CellRegionDialog ];
1236
emit dataSetYDataRegionChanged( dataSet, region );
1239
void ChartConfigWidget::ui_dataSetCustomDataRegionChanged()
1241
// Only makes sense when bubble charts are implemented
1242
// TODO: ui_dataSetCustomDataRegionChanged
1246
// Check for valid index
1247
if ( d->selectedDataSet_CellRegionDialog < 0 )
1250
const QString region = d->cellRegionDialog.customDataRegion->text();
1252
DataSet *dataSet = d->dataSets[ d->selectedDataSet_CellRegionDialog ];
1254
emit dataSetCustomDataRegionChanged( dataSet, region );
1258
void ChartConfigWidget::ui_dataSetCategoryDataRegionChanged()
1260
// Check for valid index
1261
if ( d->selectedDataSet_CellRegionDialog < 0 )
1264
const QString regionString = d->cellRegionDialog.categoryDataRegion->text();
1265
const CellRegion region( d->tableSource, regionString );
1267
DataSet *dataSet = d->dataSets[ d->selectedDataSet_CellRegionDialog ];
1269
emit dataSetCategoryDataRegionChanged( dataSet, region );
1272
void ChartConfigWidget::ui_dataSetLabelDataRegionChanged()
1274
// Check for valid index
1275
if ( d->selectedDataSet_CellRegionDialog < 0 )
1278
const QString regionString = d->cellRegionDialog.labelDataRegion->text();
1279
const CellRegion region( d->tableSource, regionString );
1281
DataSet *dataSet = d->dataSets[ d->selectedDataSet_CellRegionDialog ];
1283
emit dataSetLabelDataRegionChanged( dataSet, region );
1286
void ChartConfigWidget::ui_dataSetSelectionChanged_CellRegionDialog( int index )
1288
// Check for valid index
1289
if ( index < 0 || index >= d->dataSets.size() )
1292
DataSet *dataSet = d->dataSets[ index ];
1293
const int dimensions = dataSet->dimension();
1295
d->cellRegionDialog.labelDataRegion->setText( dataSet->labelDataRegion().toString() );
1296
if ( dimensions > 1 )
1298
d->cellRegionDialog.xDataRegion->setEnabled( true );
1299
d->cellRegionDialog.xDataRegion->setText( dataSet->xDataRegion().toString() );
1302
d->cellRegionDialog.xDataRegion->setEnabled( false );
1303
d->cellRegionDialog.yDataRegion->setText( dataSet->yDataRegion().toString() );
1304
d->cellRegionDialog.categoryDataRegion->setText( dataSet->categoryDataRegion().toString() );
1306
d->selectedDataSet_CellRegionDialog = index;
1309
void ChartConfigWidget::ui_dataSetSelectionChanged( int index )
1311
// Check for valid index
1312
if ( index < 0 || index >= d->dataSets.size() )
1315
DataSet *dataSet = d->dataSets[ index ];
1316
//d->ui.datasetColor->setText( axis->titleText() );
1317
d->ui.dataSetAxes->blockSignals( true );
1318
d->ui.dataSetAxes->setCurrentIndex( d->dataSetAxes.indexOf( dataSet->attachedAxis() ) );
1319
d->ui.dataSetAxes->blockSignals( false );
1321
d->ui.datasetBrush->blockSignals( true );
1322
d->ui.datasetBrush->setColor( dataSet->brush().color() );
1323
d->ui.datasetBrush->blockSignals( false );
1325
d->ui.datasetPen->blockSignals( true );
1326
d->ui.datasetPen->setColor( dataSet->pen().color() );
1327
d->ui.datasetPen->blockSignals( false );
1329
d->ui.datasetShowValues->blockSignals( true );
1330
d->ui.datasetShowValues->setChecked( dataSet->valueLabelType() == DataSet::RealValueLabel );
1331
d->ui.datasetShowValues->blockSignals( false );
1333
d->ui.dataSetShowLabels->blockSignals( true );
1334
d->ui.dataSetShowLabels->setChecked( dataSet->showLabels() );
1335
d->ui.dataSetShowLabels->blockSignals( false );
1337
if ( dataSet->chartType() != LastChartType ) {
1338
d->ui.dataSetHasChartType->blockSignals( true );
1339
d->ui.dataSetHasChartType->setChecked( true );
1340
d->ui.dataSetHasChartType->blockSignals( false );
1341
d->ui.dataSetChartTypeMenu->setEnabled( true );
1344
d->ui.dataSetHasChartType->blockSignals( true );
1345
d->ui.dataSetHasChartType->setChecked( false );
1346
d->ui.dataSetHasChartType->blockSignals( false );
1347
d->ui.dataSetChartTypeMenu->setEnabled( false );
1350
Q_ASSERT( d->ui.dataSetChartTypeMenu->menu() );
1352
if ( dataSet->chartType() == LastChartType ) {
1353
d->ui.dataSetChartTypeMenu->setIcon( QIcon() );
1356
switch ( dataSet->chartType() ) {
1358
switch ( dataSet->chartSubType() ) {
1359
case StackedChartSubtype:
1360
d->ui.dataSetChartTypeMenu->setIcon( KIcon( "chart_bar_stacked" ) );
1362
case PercentChartSubtype:
1363
d->ui.dataSetChartTypeMenu->setIcon( KIcon( "chart_bar_layer" ) );
1366
d->ui.dataSetChartTypeMenu->setIcon( KIcon( "chart_bar_beside" ) );
1370
switch ( dataSet->chartSubType() ) {
1371
case StackedChartSubtype:
1372
d->ui.dataSetChartTypeMenu->setIcon( KIcon( "chart_line_stacked" ) );
1374
case PercentChartSubtype:
1375
d->ui.dataSetChartTypeMenu->setIcon( KIcon( "chart_line_percent" ) );
1378
d->ui.dataSetChartTypeMenu->setIcon( KIcon( "chart_line_normal" ) );
1382
switch ( dataSet->chartSubType() ) {
1383
case StackedChartSubtype:
1384
d->ui.dataSetChartTypeMenu->setIcon( KIcon( "chart_area_stacked" ) );
1386
case PercentChartSubtype:
1387
d->ui.dataSetChartTypeMenu->setIcon( KIcon( "chart_area_percent" ) );
1390
d->ui.dataSetChartTypeMenu->setIcon( KIcon( "chart_area_normal" ) );
1393
case CircleChartType:
1394
d->ui.dataSetChartTypeMenu->menu()->setIcon( KIcon( "chart_circle_normal" ) );
1397
d->ui.dataSetChartTypeMenu->menu()->setIcon( KIcon( "chart_ring_normal" ) );
1399
case ScatterChartType:
1400
d->ui.dataSetChartTypeMenu->menu()->setIcon( KIcon( "chart_scatter_normal" ) );
1402
case RadarChartType:
1403
d->ui.dataSetChartTypeMenu->menu()->setIcon( KIcon( "chart_radar_normal" ) );
1405
case StockChartType:
1406
d->ui.dataSetChartTypeMenu->menu()->setIcon( KIcon( "chart_stock_normal" ) );
1408
case BubbleChartType:
1409
d->ui.dataSetChartTypeMenu->menu()->setIcon( KIcon( "chart_bubble_normal" ) );
1411
case SurfaceChartType:
1412
d->ui.dataSetChartTypeMenu->menu()->setIcon( KIcon( "chart_surface_normal" ) );
1414
case GanttChartType:
1415
d->ui.dataSetChartTypeMenu->menu()->setIcon( KIcon( "chart_gantt_normal" ) );
1418
// Fixes a warning that LastChartType isn't handled.
1424
d->selectedDataSet = index;
1427
void ChartConfigWidget::ui_dataSetAxisSelectionChanged( int index )
1429
if ( d->ui.dataSets->currentIndex() < 0 || d->ui.dataSets->currentIndex() >= d->dataSets.count() )
1431
DataSet *dataSet = d->dataSets[ d->ui.dataSets->currentIndex() ];
1433
if ( index < 0 || index >= d->dataSetAxes.count() )
1435
Axis *axis = d->dataSetAxes[ index ];
1437
emit dataSetAxisChanged( dataSet, axis );
1440
void ChartConfigWidget::ui_axisTitleChanged( const QString& title )
1442
if( d->ui.axes->currentIndex() < 0 || d->ui.axes->currentIndex() >= d->axes.size() )
1445
const int index = d->ui.axes->currentIndex();
1446
Axis *axis = d->axes[index];
1448
emit axisTitleChanged( axis, title );
1450
QString nonEmptyTitle = nonEmptyAxisTitle( axis, index );
1452
// TODO: This can surely be done better
1453
int dataSetAxisIndex = d->dataSetAxes.indexOf( axis );
1454
d->ui.dataSetAxes->setItemText( dataSetAxisIndex, nonEmptyTitle );
1455
d->ui.axes->setItemText( index, nonEmptyTitle );
1458
void ChartConfigWidget::ui_axisShowTitleChanged( bool b )
1460
if( d->ui.axes->currentIndex() < 0 || d->ui.axes->currentIndex() >= d->axes.size() )
1463
// To hide the axis title, we pass an empty string
1464
emit axisShowTitleChanged( d->axes[ d->ui.axes->currentIndex() ], b );
1467
void ChartConfigWidget::ui_axisShowGridLinesChanged( bool b )
1469
if( d->ui.axes->currentIndex() < 0 || d->ui.axes->currentIndex() >= d->axes.size() )
1472
emit axisShowGridLinesChanged( d->axes[ d->ui.axes->currentIndex() ], b );
1475
void ChartConfigWidget::ui_axisAdded()
1477
AxisDimension dimension;
1478
if ( d->newAxisDialog.dimensionIsX->isChecked() )
1479
dimension = XAxisDimension;
1481
dimension = YAxisDimension;
1483
emit axisAdded( dimension, d->newAxisDialog.title->text() );
1486
if( d->ui.axes->count() > 0 )
1487
d->ui.axes->setCurrentIndex( d->ui.axes->count() - 1 );
1490
void ChartConfigWidget::ui_addAxisClicked()
1492
d->newAxisDialog.show();
1495
void ChartConfigWidget::ui_removeAxisClicked()
1497
int index = d->ui.axes->currentIndex();
1498
// Check for valid index
1499
if ( index < 0 || index >= d->axes.size() )
1502
if ( KMessageBox::questionYesNo( this,
1503
i18n("Are you sure you want to remove this axis? All settings specific to this axis will be lost."),
1504
i18n("Axis Removal Confirmation") ) != KMessageBox::Yes )
1507
emit axisRemoved( d->axes[ index ] );
1510
// Select the axis after the current selection, if possible
1511
if ( d->ui.axes->count() > 0 ) {
1512
index = qMin( index, d->ui.axes->count() - 1 );
1513
d->ui.axes->setCurrentIndex( index );
1517
void ChartConfigWidget::ui_axisUseLogarithmicScalingChanged( bool b )
1519
int index = d->ui.axes->currentIndex();
1520
// Check for valid index
1521
if ( index < 0 || index >= d->axes.size() )
1524
emit axisUseLogarithmicScalingChanged( d->axes[ index ], b );
1527
void ChartConfigWidget::ui_axisStepWidthChanged( double width )
1529
int index = d->ui.axes->currentIndex();
1530
// Check for valid index
1531
if ( index < 0 || index >= d->axes.size() )
1534
emit axisStepWidthChanged( d->axes[ index ], width );
1537
void ChartConfigWidget::ui_axisSubStepWidthChanged( double width )
1539
int index = d->ui.axes->currentIndex();
1540
// Check for valid index
1541
if ( index < 0 || index >= d->axes.size() )
1544
emit axisSubStepWidthChanged( d->axes[ index ], width );
1547
void ChartConfigWidget::ui_axisUseAutomaticStepWidthChanged( bool b )
1549
int index = d->ui.axes->currentIndex();
1550
// Check for valid index
1551
if ( index < 0 || index >= d->axes.size() )
1554
emit axisUseAutomaticStepWidthChanged( d->axes[ index ], b );
1557
void ChartConfigWidget::ui_axisUseAutomaticSubStepWidthChanged( bool b )
1559
int index = d->ui.axes->currentIndex();
1560
// Check for valid index
1561
if ( index < 0 || index >= d->axes.size() )
1564
emit axisUseAutomaticSubStepWidthChanged( d->axes[ index ], b );
1567
void ChartConfigWidget::ui_axisScalingButtonClicked()
1569
d->axisScalingDialog.show();
1572
void ChartConfigWidget::ui_datasetShowValuesChanged( bool b )
1574
if ( d->selectedDataSet < 0 || d->selectedDataSet >= d->dataSets.count() )
1577
emit datasetShowValuesChanged( d->dataSets[ d->selectedDataSet ], b );
1580
void ChartConfigWidget::ui_datasetShowLabelsChanged( bool b )
1582
if ( d->selectedDataSet < 0 || d->selectedDataSet >= d->dataSets.count() )
1585
emit datasetShowValuesChanged( d->dataSets[ d->selectedDataSet ], b );
1589
#include "ChartConfigWidget.moc"