File indexing completed on 2024-05-12 16:33:25
0001 /* This file is part of the KDE project 0002 0003 Copyright 2007-2008 Johannes Simon <johannes.simon@gmail.com> 0004 Copyright 2009 Inge Wallin <inge@lysator.liu.se> 0005 0006 This library is free software; you can redistribute it and/or 0007 modify it under the terms of the GNU Library General Public 0008 License as published by the Free Software Foundation; either 0009 version 2 of the License, or (at your option) any later version. 0010 0011 This library is distributed in the hope that it will be useful, 0012 but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 Library General Public License for more details. 0015 0016 You should have received a copy of the GNU Library General Public License 0017 along with this library; see the file COPYING.LIB. If not, write to 0018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0019 Boston, MA 02110-1301, USA. 0020 */ 0021 0022 // Own 0023 #include "AxesConfigWidget.h" 0024 #include "ui_AxesConfigWidget.h" 0025 0026 // Qt 0027 #include <QAction> 0028 0029 // KF5 0030 #include <klocalizedstring.h> 0031 #include <kmessagebox.h> 0032 #include <kfontchooser.h> 0033 0034 // Calligra 0035 #include <interfaces/KoChartModel.h> 0036 #include <KoIcon.h> 0037 0038 // KChart 0039 #include <KChartChart> 0040 #include <KChartPosition> 0041 #include <KChartCartesianAxis> 0042 #include <KChartGridAttributes> 0043 #include <KChartPieAttributes> 0044 #include <KChartAbstractCartesianDiagram> 0045 #include <KChartDataValueAttributes> 0046 #include <KChartTextAttributes> 0047 #include <KChartMarkerAttributes> 0048 #include <KChartMeasure> 0049 0050 // KoChart 0051 #include "ChartProxyModel.h" 0052 #include "PlotArea.h" 0053 #include "Axis.h" 0054 #include "NewAxisDialog.h" 0055 #include "AxisScalingDialog.h" 0056 #include "FontEditorDialog.h" 0057 #include "FormatErrorBarDialog.h" 0058 #include "CellRegionDialog.h" 0059 #include "TableEditorDialog.h" 0060 #include "commands/ChartTypeCommand.h" 0061 #include "CellRegionStringValidator.h" 0062 #include "ChartTableModel.h" 0063 #include "TableSource.h" 0064 #include "ChartDebug.h" 0065 0066 using namespace KoChart; 0067 0068 0069 class AxesConfigWidget::Private 0070 { 0071 public: 0072 Private(AxesConfigWidget *parent); 0073 ~Private(); 0074 0075 Ui::AxesConfigWidget ui; 0076 0077 QList<Axis*> dataSetAxes; 0078 QList<Axis*> axes; 0079 QList<DataSet*> dataSets; 0080 0081 // Dialogs 0082 NewAxisDialog newAxisDialog; 0083 AxisScalingDialog axisScalingDialog; 0084 FontEditorDialog axisFontEditorDialog; 0085 0086 }; 0087 0088 0089 AxesConfigWidget::Private::Private(AxesConfigWidget *parent) 0090 : newAxisDialog(parent) 0091 { 0092 ui.setupUi(parent); 0093 ui.axisPosition->insertItem(0, i18n("Start"), "start"); 0094 ui.axisPosition->insertItem(1, i18n("End"), "end"); 0095 0096 ui.axislabelPosition->insertItem(0, i18n("Near-axis"), "near-axis"); 0097 ui.axislabelPosition->insertItem(1, i18n("Other-side"), "near-axis-other-side"); 0098 ui.axislabelPosition->insertItem(2, i18n("End"), "outside-end"); 0099 ui.axislabelPosition->insertItem(3, i18n("Start"), "outside-start"); 0100 0101 0102 connect(ui.axisShowTitle, SIGNAL(toggled(bool)), parent, SLOT(ui_axisShowTitleChanged(bool))); 0103 connect(ui.axisShow, SIGNAL(toggled(bool)), parent, SLOT(ui_axisShowChanged(bool))); 0104 connect(ui.axisPosition, SIGNAL(currentIndexChanged(int)), parent, SLOT(ui_axisPositionChanged(int))); 0105 connect(ui.axislabelPosition, SIGNAL(currentIndexChanged(int)), parent, SLOT(ui_axisLabelsPositionChanged(int))); 0106 connect(ui.axisShowLabels, SIGNAL(toggled(bool)), parent, SLOT(ui_axisShowLabelsChanged(bool))); 0107 connect(ui.axisShowMajorGridLines, SIGNAL(toggled(bool)), parent, SLOT(ui_axisShowMajorGridLinesChanged(bool))); 0108 connect(ui.axisShowMinorGridLines, SIGNAL(toggled(bool)), parent, SLOT(ui_axisShowMinorGridLinesChanged(bool))); 0109 connect(ui.axes, SIGNAL(currentIndexChanged(int)),parent, SLOT(ui_axisSelectionChanged(int))); 0110 0111 connect(ui.gapBetweenBars, SIGNAL(editingFinished()), parent, SLOT(slotGapBetweenBars())); 0112 connect(ui.gapBetweenSets, SIGNAL(editingFinished()), parent, SLOT(slotGapBetweenSets())); 0113 } 0114 0115 AxesConfigWidget::Private::~Private() 0116 { 0117 } 0118 0119 // ================================================================ 0120 // class AxesConfigWidget 0121 0122 // TODO: 0123 // 1) Allow user to change axis' "visible" property 0124 0125 AxesConfigWidget::AxesConfigWidget(QWidget *parent) 0126 : ConfigSubWidgetBase(parent) 0127 , d(new Private(this)) 0128 { 0129 setObjectName("AxesConfigWidget"); 0130 0131 setupDialogs(); 0132 createActions(); 0133 } 0134 0135 AxesConfigWidget::AxesConfigWidget(QList<ChartType> types, QWidget *parent) 0136 : ConfigSubWidgetBase(types, parent) 0137 , d(new Private(this)) 0138 { 0139 setObjectName("AxesConfigWidget"); 0140 0141 setupDialogs(); 0142 createActions(); 0143 } 0144 0145 AxesConfigWidget::~AxesConfigWidget() 0146 { 0147 delete d; 0148 } 0149 0150 Axis *AxesConfigWidget::axis(int index) const 0151 { 0152 Axis *a = 0; 0153 switch (index) { 0154 case 0: a = chart->plotArea()->xAxis(); break; 0155 case 1: a = chart->plotArea()->yAxis(); break; 0156 case 2: a = chart->plotArea()->secondaryXAxis(); break; 0157 case 3: a = chart->plotArea()->secondaryYAxis(); break; 0158 default: 0159 Q_ASSERT(false); 0160 break; 0161 } 0162 return a; 0163 } 0164 0165 void AxesConfigWidget::deleteSubDialogs(ChartType type) 0166 { 0167 Q_UNUSED(type) 0168 } 0169 0170 void AxesConfigWidget::open(ChartShape* shape) 0171 { 0172 debugChartUiAxes<<shape; 0173 d->axes.clear(); 0174 ConfigSubWidgetBase::open(shape); 0175 } 0176 0177 void AxesConfigWidget::updateData(ChartType type, ChartSubtype subtype) 0178 { 0179 Q_UNUSED(subtype); 0180 0181 debugChartUiAxes<<chart<<d->ui.axes->currentIndex(); 0182 if (!chart || !chartTypes.contains(type)) { 0183 return; 0184 } 0185 show(); 0186 blockSignals(true); 0187 d->ui.axisShow->setChecked(false); 0188 d->ui.axisShowMajorGridLines->setChecked(false); 0189 d->ui.axisShowMinorGridLines->setChecked(false); 0190 d->ui.axisShowTitle->setChecked(false); 0191 0192 switch (d->ui.axes->currentIndex()) { 0193 case 0: 0194 case 1: 0195 // always ok 0196 break; 0197 case 2: 0198 // ensure we do not point to a removed axis 0199 if (!chart->plotArea()->secondaryXAxis()) { 0200 d->ui.axes->setCurrentIndex(0); 0201 } 0202 break; 0203 case 3: 0204 // ensure we do not point to a removed axis 0205 if (!chart->plotArea()->secondaryYAxis()) { 0206 d->ui.axes->setCurrentIndex(0); 0207 } 0208 break; 0209 default: 0210 d->ui.axes->setCurrentIndex(0); 0211 break; 0212 } 0213 blockSignals(false); 0214 ui_axisSelectionChanged(d->ui.axes->currentIndex()); 0215 } 0216 0217 0218 void AxesConfigWidget::setupDialogs() 0219 { 0220 // Axis scaling 0221 connect(d->ui.axisScalingButton, SIGNAL(clicked()), 0222 this, SLOT(ui_axisScalingButtonClicked())); 0223 connect(d->axisScalingDialog.logarithmicScaling, SIGNAL(toggled(bool)), 0224 this, SLOT(ui_axisUseLogarithmicScalingChanged(bool))); 0225 connect(d->axisScalingDialog.stepWidth, SIGNAL(valueChanged(double)), 0226 this, SLOT(ui_axisStepWidthChanged(double))); 0227 connect (d->axisScalingDialog.automaticStepWidth, SIGNAL(toggled(bool)), 0228 this, SLOT(ui_axisUseAutomaticStepWidthChanged(bool))); 0229 connect(d->axisScalingDialog.subStepWidth, SIGNAL(valueChanged(double)), 0230 this, SLOT(ui_axisSubStepWidthChanged(double))); 0231 connect (d->axisScalingDialog.automaticSubStepWidth, SIGNAL(toggled(bool)), 0232 this, SLOT(ui_axisUseAutomaticSubStepWidthChanged(bool))); 0233 0234 // Edit Fonts 0235 connect(d->ui.axisEditFontButton, SIGNAL(clicked()), 0236 this, SLOT(ui_axisEditFontButtonClicked())); 0237 connect(&d->axisFontEditorDialog, SIGNAL(accepted()), 0238 this, SLOT(ui_axisLabelsFontChanged())); 0239 0240 } 0241 0242 void AxesConfigWidget::createActions() 0243 { 0244 } 0245 0246 void AxesConfigWidget::ui_axisSelectionChanged(int index) 0247 { 0248 Q_ASSERT(chart); 0249 // Check for valid index 0250 if (index < 0 || index > 3) { 0251 warnChartUiAxes<<"Invalid axis index"<<index; 0252 return; 0253 } 0254 Axis *axis = 0; 0255 switch (index) { 0256 case 0: 0257 axis = chart->plotArea()->xAxis(); 0258 break; 0259 case 1: 0260 axis = chart->plotArea()->yAxis(); 0261 break; 0262 case 2: 0263 axis = chart->plotArea()->secondaryXAxis(); 0264 if (!axis) { 0265 debugChartUiAxes<<"create secondary x axis"; 0266 emit axisAdded(XAxisDimension, i18n("Axistitle")); 0267 return; 0268 } 0269 break; 0270 case 3: 0271 axis = chart->plotArea()->secondaryYAxis(); 0272 if (!axis) { 0273 debugChartUiAxes<<"create secondary y axis"; 0274 emit axisAdded(YAxisDimension, i18n("Axistitle")); 0275 return; 0276 } 0277 break; 0278 default: 0279 Q_ASSERT(false); 0280 break; 0281 } 0282 blockSignals(true); 0283 d->ui.axisShow->setChecked(axis->isVisible()); 0284 d->ui.axisShowTitle->setChecked(axis->title()->isVisible()); 0285 debugChartUiAxes<<axis<<axis->odfAxisPosition()<<axis->odfAxisLabelsPosition(); 0286 for (int i = 0; i < d->ui.axisPosition->count(); ++i) { 0287 if (d->ui.axisPosition->itemData(i).toString() == axis->odfAxisPosition()) { 0288 d->ui.axisPosition->setCurrentIndex(i); 0289 break; 0290 } 0291 } 0292 for (int i = 0; i < d->ui.axislabelPosition->count(); ++i) { 0293 if (d->ui.axislabelPosition->itemData(i).toString() == axis->odfAxisLabelsPosition()) { 0294 d->ui.axislabelPosition->setCurrentIndex(i); 0295 break; 0296 } 0297 } 0298 d->ui.axisShowLabels->setChecked(axis->showLabels()); 0299 d->ui.axisShowMajorGridLines->setChecked(axis->showMajorGrid()); 0300 d->ui.axisShowMinorGridLines->setChecked(axis->showMinorGrid()); 0301 0302 blockSignals(&d->axisScalingDialog, true); 0303 if (axis->dimension() == YAxisDimension) { 0304 d->axisScalingDialog.logarithmicScaling->setEnabled(true); 0305 } else { 0306 d->axisScalingDialog.logarithmicScaling->setEnabled(false); 0307 } 0308 0309 d->axisScalingDialog.stepWidth->setValue(axis->majorInterval()); 0310 0311 d->axisScalingDialog.subStepWidth->setValue(axis->minorInterval()); 0312 0313 d->axisScalingDialog.automaticStepWidth->setChecked(axis->useAutomaticMajorInterval()); 0314 d->axisScalingDialog.stepWidth->setEnabled(!axis->useAutomaticMajorInterval()); 0315 0316 d->axisScalingDialog.automaticSubStepWidth->setChecked(axis->useAutomaticMinorInterval()); 0317 d->axisScalingDialog.subStepWidth->setEnabled(!axis->useAutomaticMinorInterval()); 0318 blockSignals(&d->axisScalingDialog, false); 0319 0320 d->ui.gapBetweenBars->setValue(axis->gapBetweenBars()); 0321 d->ui.gapBetweenSets->setValue(axis->gapBetweenSets()); 0322 d->ui.barProperties->setVisible(chart->chartType() == BarChartType && axis->dimension() == YAxisDimension); 0323 blockSignals(false); 0324 } 0325 0326 0327 void AxesConfigWidget::ui_axisShowTitleChanged(bool b) 0328 { 0329 Axis *a = axis(d->ui.axes->currentIndex()); 0330 if (a) { 0331 emit axisShowTitleChanged(a, b); 0332 } 0333 } 0334 0335 void AxesConfigWidget::ui_axisShowChanged(bool b) 0336 { 0337 Axis *a = axis(d->ui.axes->currentIndex()); 0338 if (a) { 0339 debugChartUiAxes<<a<<b; 0340 emit axisShowChanged(a, b); 0341 } 0342 } 0343 0344 void AxesConfigWidget::ui_axisPositionChanged(int index) 0345 { 0346 Axis *a = axis(d->ui.axes->currentIndex()); 0347 if (a) { 0348 debugChartUiAxes<<a<<index; 0349 emit axisPositionChanged(a, d->ui.axisPosition->currentData().toString()); 0350 } 0351 } 0352 0353 void AxesConfigWidget::ui_axisLabelsPositionChanged(int index) 0354 { 0355 Axis *a = axis(d->ui.axes->currentIndex()); 0356 if (a) { 0357 debugChartUiAxes<<a<<index; 0358 emit axisLabelsPositionChanged(a, d->ui.axislabelPosition->currentData().toString()); 0359 } 0360 } 0361 0362 void AxesConfigWidget::ui_axisShowLabelsChanged(bool value) 0363 { 0364 Axis *a = axis(d->ui.axes->currentIndex()); 0365 if (a) { 0366 debugChartUiAxes<<a<<value; 0367 emit axisShowLabelsChanged(a, value); 0368 } 0369 } 0370 0371 void AxesConfigWidget::ui_axisShowMajorGridLinesChanged(bool b) 0372 { 0373 Axis *a = axis(d->ui.axes->currentIndex()); 0374 if (a) { 0375 debugChartUiAxes<<a<<b; 0376 emit axisShowMajorGridLinesChanged(a, b); 0377 } 0378 } 0379 0380 void AxesConfigWidget::ui_axisShowMinorGridLinesChanged(bool b) 0381 { 0382 Axis *a = axis(d->ui.axes->currentIndex()); 0383 if (a) { 0384 debugChartUiAxes<<a<<b; 0385 emit axisShowMinorGridLinesChanged(a, b); 0386 } 0387 } 0388 0389 void AxesConfigWidget::ui_axisLabelsFontChanged() 0390 { 0391 QFont font = d->axisFontEditorDialog.fontChooser->font(); 0392 Axis *a = axis(d->ui.axes->currentIndex()); 0393 if (a) { 0394 debugChartUiAxes<<a<<font; 0395 emit axisLabelsFontChanged(a, font); 0396 } 0397 } 0398 0399 void AxesConfigWidget::ui_axisUseLogarithmicScalingChanged(bool b) 0400 { 0401 Axis *a = axis(d->ui.axes->currentIndex()); 0402 if (a) { 0403 debugChartUiAxes<<a<<b; 0404 emit axisUseLogarithmicScalingChanged(a, b); 0405 } 0406 } 0407 0408 void AxesConfigWidget::ui_axisStepWidthChanged(double width) 0409 { 0410 Axis *a = axis(d->ui.axes->currentIndex()); 0411 if (a) { 0412 debugChartUiAxes<<a<<width; 0413 emit axisStepWidthChanged(a, width); 0414 } 0415 } 0416 0417 void AxesConfigWidget::ui_axisSubStepWidthChanged(double width) 0418 { 0419 Axis *a = axis(d->ui.axes->currentIndex()); 0420 if (a) { 0421 debugChartUiAxes<<a<<width; 0422 emit axisSubStepWidthChanged(a, width); 0423 } 0424 } 0425 0426 void AxesConfigWidget::ui_axisUseAutomaticStepWidthChanged(bool b) 0427 { 0428 Axis *a = axis(d->ui.axes->currentIndex()); 0429 if (a) { 0430 debugChartUiAxes<<a<<b; 0431 emit axisUseAutomaticStepWidthChanged(a, b); 0432 } 0433 } 0434 0435 void AxesConfigWidget::ui_axisUseAutomaticSubStepWidthChanged(bool b) 0436 { 0437 Axis *a = axis(d->ui.axes->currentIndex()); 0438 if (a) { 0439 debugChartUiAxes<<a<<b; 0440 emit axisUseAutomaticSubStepWidthChanged(a, b); 0441 } 0442 } 0443 0444 void AxesConfigWidget::ui_axisScalingButtonClicked() 0445 { 0446 d->axisScalingDialog.show(); 0447 } 0448 0449 void AxesConfigWidget::ui_axisEditFontButtonClicked() 0450 { 0451 Axis *a = axis(d->ui.axes->currentIndex()); 0452 if (a) { 0453 QFont font = a->font(); 0454 d->axisFontEditorDialog.fontChooser->setFont(font); 0455 d->axisFontEditorDialog.show(); 0456 } 0457 } 0458 0459 void AxesConfigWidget::slotGapBetweenBars() 0460 { 0461 Axis *a = axis(d->ui.axes->currentIndex()); 0462 if (a && a->dimension() == YAxisDimension) { 0463 debugChartUiAxes<<a<<d->ui.gapBetweenBars->value(); 0464 emit gapBetweenBarsChanged(a, d->ui.gapBetweenBars->value()); 0465 } 0466 } 0467 0468 void AxesConfigWidget::slotGapBetweenSets() 0469 { 0470 Axis *a = axis(d->ui.axes->currentIndex()); 0471 if (a && a->dimension() == YAxisDimension) { 0472 debugChartUiAxes<<a<<d->ui.gapBetweenSets->value(); 0473 emit gapBetweenSetsChanged(a, d->ui.gapBetweenSets->value()); 0474 } 0475 }