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 }