File indexing completed on 2024-05-12 15:27:55

0001     /***************************************************************************
0002     File                 : AxisDock.cpp
0003     Project              : LabPlot
0004     Description          : axes widget class
0005     --------------------------------------------------------------------
0006     Copyright            : (C) 2011-2020 Alexander Semke (alexander.semke@web.de)
0007     Copyright            : (C) 2012-2020 Stefan Gerlach (stefan.gerlach@uni-konstanz.de)
0008 
0009  ***************************************************************************/
0010 
0011 /***************************************************************************
0012  *                                                                         *
0013  *  This program is free software; you can redistribute it and/or modify   *
0014  *  it under the terms of the GNU General Public License as published by   *
0015  *  the Free Software Foundation; either version 2 of the License, or      *
0016  *  (at your option) any later version.                                    *
0017  *                                                                         *
0018  *  This program is distributed in the hope that it will be useful,        *
0019  *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
0020  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
0021  *  GNU General Public License for more details.                           *
0022  *                                                                         *
0023  *   You should have received a copy of the GNU General Public License     *
0024  *   along with this program; if not, write to the Free Software           *
0025  *   Foundation, Inc., 51 Franklin Street, Fifth Floor,                    *
0026  *   Boston, MA  02110-1301  USA                                           *
0027  *                                                                         *
0028  ***************************************************************************/
0029 
0030 #include "AxisDock.h"
0031 #include "backend/core/AspectTreeModel.h"
0032 #include "backend/core/column/Column.h"
0033 #include "backend/core/Project.h"
0034 #include "backend/worksheet/Worksheet.h"
0035 #include "backend/worksheet/plots/cartesian/CartesianPlot.h"
0036 #include "commonfrontend/widgets/TreeViewComboBox.h"
0037 #include "kdefrontend/GuiTools.h"
0038 #include "kdefrontend/TemplateHandler.h"
0039 #include "kdefrontend/widgets/LabelWidget.h"
0040 #include "commonfrontend/widgets/DateTimeSpinBox.h"
0041 
0042 #include <QTimer>
0043 #include <QDir>
0044 #include <QPainter>
0045 #include <KLocalizedString>
0046 #include <KMessageBox>
0047 
0048 extern "C" {
0049 #include <gsl/gsl_math.h>
0050 #include "backend/nsl/nsl_math.h"
0051 }
0052 
0053 /*!
0054  \class AxisDock
0055  \brief Provides a widget for editing the properties of the axes currently selected in the project explorer.
0056 
0057  \ingroup kdefrontend
0058 */
0059 
0060 AxisDock::AxisDock(QWidget* parent) : BaseDock(parent) {
0061     ui.setupUi(this);
0062     m_leName = ui.leName;
0063     m_leComment = ui.leComment;
0064 
0065     //"Title"-tab
0066     auto* hboxLayout = new QHBoxLayout(ui.tabTitle);
0067     labelWidget = new LabelWidget(ui.tabTitle);
0068     labelWidget->setFixedLabelMode(true);
0069     hboxLayout->addWidget(labelWidget);
0070     hboxLayout->setContentsMargins(2,2,2,2);
0071     hboxLayout->setSpacing(2);
0072 
0073     //"Ticks"-tab
0074     auto* layout = static_cast<QGridLayout*>(ui.tabTicks->layout());
0075     cbMajorTicksColumn = new TreeViewComboBox(ui.tabTicks);
0076     layout->addWidget(cbMajorTicksColumn, 7, 2);
0077     cbMinorTicksColumn = new TreeViewComboBox(ui.tabTicks);
0078     layout->addWidget(cbMinorTicksColumn, 21, 2);
0079     dtsbMajorTicksIncrement = new DateTimeSpinBox(ui.tabTicks);
0080     layout->addWidget(dtsbMajorTicksIncrement, 6, 2);
0081     dtsbMinorTicksIncrement = new DateTimeSpinBox(ui.tabTicks);
0082     layout->addWidget(dtsbMinorTicksIncrement, 20, 2);
0083 
0084     //adjust layouts in the tabs
0085     for (int i = 0; i < ui.tabWidget->count(); ++i) {
0086         layout = dynamic_cast<QGridLayout*>(ui.tabWidget->widget(i)->layout());
0087         if (!layout)
0088             continue;
0089 
0090         layout->setContentsMargins(2,2,2,2);
0091         layout->setHorizontalSpacing(2);
0092         layout->setVerticalSpacing(2);
0093     }
0094 
0095     //set the current locale
0096     SET_NUMBER_LOCALE
0097     ui.sbLineWidth->setLocale(numberLocale);
0098     ui.sbMajorTicksSpacingNumeric->setLocale(numberLocale);
0099     ui.sbMajorTicksWidth->setLocale(numberLocale);
0100     ui.sbMajorTicksLength->setLocale(numberLocale);
0101     ui.sbMinorTicksSpacingNumeric->setLocale(numberLocale);
0102     ui.sbMinorTicksWidth->setLocale(numberLocale);
0103     ui.sbMinorTicksLength->setLocale(numberLocale);
0104     ui.sbLabelsOffset->setLocale(numberLocale);
0105     ui.sbMajorGridWidth->setLocale(numberLocale);
0106     ui.sbMinorGridWidth->setLocale(numberLocale);
0107     labelWidget->updateLocale();
0108 
0109     //**********************************  Slots **********************************************
0110 
0111     //"General"-tab
0112     connect(ui.leName, &QLineEdit::textChanged, this, &AxisDock::nameChanged);
0113     connect(ui.leComment, &QLineEdit::textChanged, this, &AxisDock::commentChanged);
0114     connect(ui.chkVisible, &QCheckBox::clicked, this, &AxisDock::visibilityChanged);
0115 
0116     connect(ui.cbOrientation, QOverload<int>::of(&QComboBox::currentIndexChanged),
0117             this, &AxisDock::orientationChanged);
0118     connect(ui.cbPosition, QOverload<int>::of(&QComboBox::currentIndexChanged),
0119             this, QOverload<int>::of(&AxisDock::positionChanged));
0120     connect(ui.lePosition, &QLineEdit::textChanged,
0121             this, QOverload<>::of(&AxisDock::positionChanged));
0122     connect(ui.cbScale, QOverload<int>::of(&QComboBox::currentIndexChanged),
0123             this, &AxisDock::scaleChanged);
0124 
0125     connect(ui.chkAutoScale, &QCheckBox::stateChanged, this, &AxisDock::autoScaleChanged);
0126     connect(ui.leStart, &QLineEdit::textChanged, this, &AxisDock::startChanged);
0127     connect(ui.leEnd, &QLineEdit::textChanged, this, &AxisDock::endChanged);
0128     connect(ui.dateTimeEditStart, &QDateTimeEdit::dateTimeChanged, this, &AxisDock::startDateTimeChanged);
0129     connect(ui.dateTimeEditEnd, &QDateTimeEdit::dateTimeChanged, this, &AxisDock::endDateTimeChanged);
0130     connect(ui.leZeroOffset, &QLineEdit::textChanged, this, &AxisDock::zeroOffsetChanged);
0131     connect(ui.leScalingFactor, &QLineEdit::textChanged, this, &AxisDock::scalingFactorChanged);
0132 
0133     //"Line"-tab
0134     connect(ui.cbLineStyle, QOverload<int>::of(&QComboBox::currentIndexChanged),
0135             this, &AxisDock::lineStyleChanged);
0136     connect(ui.kcbLineColor, &KColorButton::changed, this, &AxisDock::lineColorChanged);
0137     connect(ui.sbLineWidth, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
0138             this, &AxisDock::lineWidthChanged);
0139     connect(ui.sbLineOpacity, QOverload<int>::of(&QSpinBox::valueChanged),
0140             this, &AxisDock::lineOpacityChanged);
0141     connect(ui.cbArrowPosition, QOverload<int>::of(&QComboBox::currentIndexChanged),
0142             this, &AxisDock::arrowPositionChanged);
0143     connect(ui.cbArrowType, QOverload<int>::of(&QComboBox::currentIndexChanged),
0144             this, &AxisDock::arrowTypeChanged);
0145     connect(ui.sbArrowSize, QOverload<int>::of(&QSpinBox::valueChanged),
0146             this, &AxisDock::arrowSizeChanged);
0147 
0148     //"Major ticks"-tab
0149     connect(ui.cbMajorTicksDirection, QOverload<int>::of(&QComboBox::currentIndexChanged),
0150             this, &AxisDock::majorTicksDirectionChanged);
0151     connect(ui.cbMajorTicksType, QOverload<int>::of(&QComboBox::currentIndexChanged),
0152             this, &AxisDock::majorTicksTypeChanged);
0153     connect(ui.sbMajorTicksNumber, QOverload<int>::of(&QSpinBox::valueChanged),
0154             this, &AxisDock::majorTicksNumberChanged);
0155     connect(ui.sbMajorTicksSpacingNumeric, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
0156             this, &AxisDock::majorTicksSpacingChanged);
0157     connect(dtsbMajorTicksIncrement, &DateTimeSpinBox::valueChanged,
0158             this, &AxisDock::majorTicksSpacingChanged);
0159     connect(cbMajorTicksColumn, &TreeViewComboBox::currentModelIndexChanged,
0160             this, &AxisDock::majorTicksColumnChanged);
0161     connect(ui.cbMajorTicksLineStyle, QOverload<int>::of(&QComboBox::currentIndexChanged),
0162             this, &AxisDock::majorTicksLineStyleChanged);
0163     connect(ui.kcbMajorTicksColor, &KColorButton::changed, this, &AxisDock::majorTicksColorChanged);
0164     connect(ui.sbMajorTicksWidth, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
0165             this, &AxisDock::majorTicksWidthChanged);
0166     connect(ui.sbMajorTicksLength, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
0167             this, &AxisDock::majorTicksLengthChanged);
0168     connect(ui.sbMajorTicksOpacity, QOverload<int>::of(&QSpinBox::valueChanged),
0169             this, &AxisDock::majorTicksOpacityChanged);
0170 
0171     //"Minor ticks"-tab
0172     connect(ui.cbMinorTicksDirection, QOverload<int>::of(&QComboBox::currentIndexChanged),
0173             this, &AxisDock::minorTicksDirectionChanged);
0174     connect(ui.cbMinorTicksType, QOverload<int>::of(&QComboBox::currentIndexChanged),
0175             this, &AxisDock::minorTicksTypeChanged);
0176     connect(ui.sbMinorTicksNumber, QOverload<int>::of(&QSpinBox::valueChanged),
0177             this, &AxisDock::minorTicksNumberChanged);
0178     connect(ui.sbMinorTicksSpacingNumeric, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
0179             this, &AxisDock::minorTicksSpacingChanged);
0180     connect(dtsbMinorTicksIncrement, &DateTimeSpinBox::valueChanged,
0181             this, &AxisDock::minorTicksSpacingChanged);
0182     connect(cbMinorTicksColumn, &TreeViewComboBox::currentModelIndexChanged,
0183             this, &AxisDock::minorTicksColumnChanged);
0184     connect(ui.cbMinorTicksLineStyle, QOverload<int>::of(&QComboBox::currentIndexChanged),
0185             this, &AxisDock::minorTicksLineStyleChanged);
0186     connect(ui.kcbMinorTicksColor, &KColorButton::changed, this, &AxisDock::minorTicksColorChanged);
0187     connect(ui.sbMinorTicksWidth, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
0188             this, &AxisDock::minorTicksWidthChanged);
0189     connect(ui.sbMinorTicksLength, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
0190             this, &AxisDock::minorTicksLengthChanged);
0191     connect(ui.sbMinorTicksOpacity, QOverload<int>::of(&QSpinBox::valueChanged),
0192             this, &AxisDock::minorTicksOpacityChanged);
0193 
0194     //"Extra ticks"-tab
0195 
0196     //"Tick labels"-tab
0197     connect(ui.cbLabelsFormat, QOverload<int>::of(&QComboBox::currentIndexChanged),
0198             this, &AxisDock::labelsFormatChanged);
0199     connect(ui.sbLabelsPrecision, QOverload<int>::of(&QSpinBox::valueChanged),
0200             this, &AxisDock::labelsPrecisionChanged);
0201     connect(ui.chkLabelsAutoPrecision, &QCheckBox::stateChanged, this, &AxisDock::labelsAutoPrecisionChanged);
0202     connect(ui.cbLabelsDateTimeFormat, QOverload<int>::of(&QComboBox::currentIndexChanged),
0203             this, &AxisDock::labelsDateTimeFormatChanged);
0204     connect(ui.cbLabelsPosition, QOverload<int>::of(&QComboBox::currentIndexChanged),
0205             this, &AxisDock::labelsPositionChanged);
0206     connect(ui.sbLabelsOffset, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
0207             this, &AxisDock::labelsOffsetChanged);
0208     connect(ui.sbLabelsRotation, QOverload<int>::of(&QSpinBox::valueChanged),
0209             this, &AxisDock::labelsRotationChanged);
0210     connect(ui.kfrLabelsFont, &KFontRequester::fontSelected, this, &AxisDock::labelsFontChanged);
0211     connect(ui.kcbLabelsFontColor, &KColorButton::changed, this, &AxisDock::labelsFontColorChanged);
0212     connect(ui.cbLabelsBackgroundType, QOverload<int>::of(&QComboBox::currentIndexChanged),
0213             this, &AxisDock::labelsBackgroundTypeChanged);
0214     connect(ui.kcbLabelsBackgroundColor, &KColorButton::changed, this, &AxisDock::labelsBackgroundColorChanged);
0215     connect(ui.leLabelsPrefix, &QLineEdit::textChanged, this, &AxisDock::labelsPrefixChanged);
0216     connect(ui.leLabelsSuffix, &QLineEdit::textChanged, this, &AxisDock::labelsSuffixChanged);
0217     connect(ui.sbLabelsOpacity, QOverload<int>::of(&QSpinBox::valueChanged),
0218             this, &AxisDock::labelsOpacityChanged);
0219 
0220     //"Grid"-tab
0221     connect(ui.cbMajorGridStyle, QOverload<int>::of(&QComboBox::currentIndexChanged),
0222             this, &AxisDock::majorGridStyleChanged);
0223     connect(ui.kcbMajorGridColor, &KColorButton::changed, this, &AxisDock::majorGridColorChanged);
0224     connect(ui.sbMajorGridWidth, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
0225             this, &AxisDock::majorGridWidthChanged);
0226     connect(ui.sbMajorGridOpacity, QOverload<int>::of(&QSpinBox::valueChanged),
0227             this, &AxisDock::majorGridOpacityChanged);
0228 
0229     connect(ui.cbMinorGridStyle, QOverload<int>::of(&QComboBox::currentIndexChanged),
0230             this, &AxisDock::minorGridStyleChanged);
0231     connect(ui.kcbMinorGridColor, &KColorButton::changed, this, &AxisDock::minorGridColorChanged);
0232     connect(ui.sbMinorGridWidth, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
0233             this, &AxisDock::minorGridWidthChanged);
0234     connect(ui.sbMinorGridOpacity, QOverload<int>::of(&QSpinBox::valueChanged),
0235             this, &AxisDock::minorGridOpacityChanged);
0236 
0237     //template handler
0238     auto* frame = new QFrame(this);
0239     auto* hlayout = new QHBoxLayout(frame);
0240     hlayout->setContentsMargins(0, 11, 0, 11);
0241 
0242     auto* templateHandler = new TemplateHandler(this, TemplateHandler::ClassName::Axis);
0243     hlayout->addWidget(templateHandler);
0244     connect(templateHandler, &TemplateHandler::loadConfigRequested, this, &AxisDock::loadConfigFromTemplate);
0245     connect(templateHandler, &TemplateHandler::saveConfigRequested, this, &AxisDock::saveConfigAsTemplate);
0246     connect(templateHandler, &TemplateHandler::info, this, &AxisDock::info);
0247 
0248     ui.verticalLayout->addWidget(frame);
0249 
0250     init();
0251 }
0252 
0253 AxisDock::~AxisDock() {
0254     if (m_aspectTreeModel)
0255         delete m_aspectTreeModel;
0256 }
0257 
0258 void AxisDock::init() {
0259     Lock lock(m_initializing);
0260 
0261     //Validators
0262     ui.lePosition->setValidator( new QDoubleValidator(ui.lePosition) );
0263     ui.leStart->setValidator( new QDoubleValidator(ui.leStart) );
0264     ui.leEnd->setValidator( new QDoubleValidator(ui.leEnd) );
0265     ui.leZeroOffset->setValidator( new QDoubleValidator(ui.leZeroOffset) );
0266     ui.leScalingFactor->setValidator( new QDoubleValidator(ui.leScalingFactor) );
0267 
0268     //TODO move this stuff to retranslateUI()
0269     ui.cbPosition->addItem(i18n("Top"));
0270     ui.cbPosition->addItem(i18n("Bottom"));
0271     ui.cbPosition->addItem(i18n("Centered"));
0272     ui.cbPosition->addItem(i18n("Custom"));
0273 
0274     ui.cbScale->addItem( i18n("Linear") );
0275     ui.cbScale->addItem( QLatin1String("log(x)") );
0276     ui.cbScale->addItem( QLatin1String("log2(x)") );
0277     ui.cbScale->addItem( QLatin1String("ln(x)") );
0278     ui.cbScale->addItem( QLatin1String("sqrt(x)") );
0279     ui.cbScale->addItem( QLatin1String("x^2") );
0280 
0281     ui.cbOrientation->addItem( i18n("Horizontal") );
0282     ui.cbOrientation->addItem( i18n("Vertical") );
0283 
0284     //Arrows
0285     ui.cbArrowType->addItem( i18n("No arrow") );
0286     ui.cbArrowType->addItem( i18n("Simple, Small") );
0287     ui.cbArrowType->addItem( i18n("Simple, Big") );
0288     ui.cbArrowType->addItem( i18n("Filled, Small") );
0289     ui.cbArrowType->addItem( i18n("Filled, Big") );
0290     ui.cbArrowType->addItem( i18n("Semi-filled, Small") );
0291     ui.cbArrowType->addItem( i18n("Semi-filled, Big") );
0292 
0293     QPainter pa;
0294     pa.setPen( QPen(Qt::SolidPattern, 0) );
0295     QPixmap pm(20, 20);
0296     ui.cbArrowType->setIconSize( QSize(20,20) );
0297 
0298     //no arrow
0299     pm.fill(Qt::transparent);
0300     pa.begin( &pm );
0301     pa.setRenderHint(QPainter::Antialiasing);
0302     pa.setBrush(Qt::SolidPattern);
0303     pa.drawLine(3, 10, 17, 10);
0304     pa.end();
0305     ui.cbArrowType->setItemIcon(0, pm);
0306 
0307     //simple, small
0308     double cos_phi = cos(M_PI/6.);
0309     pm.fill(Qt::transparent);
0310     pa.begin( &pm );
0311     pa.setRenderHint(QPainter::Antialiasing);
0312     pa.drawLine(3, 10, 17, 10);
0313     pa.drawLine(17,10, 10, 10-5*cos_phi);
0314     pa.drawLine(17,10, 10, 10+5*cos_phi);
0315     pa.end();
0316     ui.cbArrowType->setItemIcon(1, pm);
0317 
0318     //simple, big
0319     pm.fill(Qt::transparent);
0320     pa.begin( &pm );
0321     pa.setRenderHint(QPainter::Antialiasing);
0322     pa.drawLine(3, 10, 17, 10);
0323     pa.drawLine(17,10, 10, 10-10*cos_phi);
0324     pa.drawLine(17,10, 10, 10+10*cos_phi);
0325     pa.end();
0326     ui.cbArrowType->setItemIcon(2, pm);
0327 
0328     //filled, small
0329     pm.fill(Qt::transparent);
0330     pa.begin( &pm );
0331     pa.setRenderHint(QPainter::Antialiasing);
0332     pa.setBrush(Qt::SolidPattern);
0333     pa.drawLine(3, 10, 17, 10);
0334     //TODO: use QPolygon?
0335     QPointF points3[3] = { QPointF(17, 10), QPointF(10, 10-4*cos_phi), QPointF(10, 10+4*cos_phi) };
0336     pa.drawPolygon(points3, 3);
0337     pa.end();
0338     ui.cbArrowType->setItemIcon(3, pm);
0339 
0340     //filled, big
0341     pm.fill(Qt::transparent);
0342     pa.begin( &pm );
0343     pa.setRenderHint(QPainter::Antialiasing);
0344     pa.setBrush(Qt::SolidPattern);
0345     pa.drawLine(3, 10, 17, 10);
0346     QPointF points4[3] = { QPointF(17, 10), QPointF(10, 10-10*cos_phi), QPointF(10, 10+10*cos_phi) };
0347     pa.drawPolygon(points4, 3);
0348     pa.end();
0349     ui.cbArrowType->setItemIcon(4, pm);
0350 
0351     //semi-filled, small
0352     pm.fill(Qt::transparent);
0353     pa.begin( &pm );
0354     pa.setRenderHint(QPainter::Antialiasing);
0355     pa.setBrush(Qt::SolidPattern);
0356     pa.drawLine(3, 10, 17, 10);
0357     QPointF points5[4] = { QPointF(17, 10), QPointF(10, 10-4*cos_phi), QPointF(13, 10), QPointF(10, 10+4*cos_phi) };
0358     pa.drawPolygon(points5, 4);
0359     pa.end();
0360     ui.cbArrowType->setItemIcon(5, pm);
0361 
0362     //semi-filled, big
0363     pm.fill(Qt::transparent);
0364     pa.begin( &pm );
0365     pa.setRenderHint(QPainter::Antialiasing);
0366     pa.setBrush(Qt::SolidPattern);
0367     pa.drawLine(3, 10, 17, 10);
0368     QPointF points6[4] = { QPointF(17, 10), QPointF(10, 10-10*cos_phi), QPointF(13, 10), QPointF(10, 10+10*cos_phi) };
0369     pa.drawPolygon(points6, 4);
0370     pa.end();
0371     ui.cbArrowType->setItemIcon(6, pm);
0372 
0373     ui.cbArrowPosition->addItem( i18n("Left") );
0374     ui.cbArrowPosition->addItem( i18n("Right") );
0375     ui.cbArrowPosition->addItem( i18n("Both") );
0376 
0377     ui.cbMajorTicksDirection->addItem( i18n("None") );
0378     ui.cbMajorTicksDirection->addItem( i18n("In") );
0379     ui.cbMajorTicksDirection->addItem( i18n("Out") );
0380     ui.cbMajorTicksDirection->addItem( i18n("In and Out") );
0381 
0382     ui.cbMajorTicksType->addItem( i18n("Number") );
0383     ui.cbMajorTicksType->addItem( i18n("Spacing") );
0384     ui.cbMajorTicksType->addItem( i18n("Custom column") );
0385 
0386     ui.cbMinorTicksDirection->addItem( i18n("None") );
0387     ui.cbMinorTicksDirection->addItem( i18n("In") );
0388     ui.cbMinorTicksDirection->addItem( i18n("Out") );
0389     ui.cbMinorTicksDirection->addItem( i18n("In and Out") );
0390 
0391     ui.cbMinorTicksType->addItem( i18n("Number") );
0392     ui.cbMinorTicksType->addItem( i18n("Spacing") );
0393     ui.cbMinorTicksType->addItem( i18n("Custom column") );
0394 
0395     GuiTools::updatePenStyles(ui.cbLineStyle, QColor(Qt::black));
0396     GuiTools::updatePenStyles(ui.cbMajorTicksLineStyle, QColor(Qt::black));
0397     GuiTools::updatePenStyles(ui.cbMinorTicksLineStyle, QColor(Qt::black));
0398     GuiTools::updatePenStyles(ui.cbMajorGridStyle, QColor(Qt::black));
0399     GuiTools::updatePenStyles(ui.cbMinorGridStyle, QColor(Qt::black));
0400 
0401     //labels
0402     ui.cbLabelsPosition->addItem(i18n("No labels"));
0403     ui.cbLabelsPosition->addItem(i18n("Top"));
0404     ui.cbLabelsPosition->addItem(i18n("Bottom"));
0405 
0406     ui.cbLabelsFormat->addItem( i18n("Decimal notation") );
0407     ui.cbLabelsFormat->addItem( i18n("Scientific notation") );
0408     ui.cbLabelsFormat->addItem( i18n("Powers of 10") );
0409     ui.cbLabelsFormat->addItem( i18n("Powers of 2") );
0410     ui.cbLabelsFormat->addItem( i18n("Powers of e") );
0411     ui.cbLabelsFormat->addItem( i18n("Multiples of π") );
0412 
0413     ui.cbLabelsDateTimeFormat->addItems(AbstractColumn::dateTimeFormats());
0414 
0415     ui.cbLabelsBackgroundType->addItem(i18n("Transparent"));
0416     ui.cbLabelsBackgroundType->addItem(i18n("Color"));
0417 }
0418 
0419 void AxisDock::setModel() {
0420     QList<AspectType> list{AspectType::Folder, AspectType::Workbook, AspectType::Spreadsheet, AspectType::Column};
0421     cbMajorTicksColumn->setTopLevelClasses(list);
0422     cbMinorTicksColumn->setTopLevelClasses(list);
0423 
0424     list = {AspectType::Column};
0425     m_aspectTreeModel->setSelectableAspects(list);
0426 
0427     cbMajorTicksColumn->setModel(m_aspectTreeModel);
0428     cbMinorTicksColumn->setModel(m_aspectTreeModel);
0429 }
0430 
0431 /*!
0432   sets the axes. The properties of the axes in the list \c list can be edited in this widget.
0433 */
0434 void AxisDock::setAxes(QList<Axis*> list) {
0435     Lock lock(m_initializing);
0436     m_axesList = list;
0437     m_axis = list.first();
0438     m_aspect = list.first();
0439     Q_ASSERT(m_axis != nullptr);
0440     m_aspectTreeModel = new AspectTreeModel(m_axis->project());
0441     this->setModel();
0442 
0443     labelWidget->setAxes(list);
0444 
0445     //if there are more then one axis in the list, disable the tab "general"
0446     if (list.size() == 1) {
0447         ui.lName->setEnabled(true);
0448         ui.leName->setEnabled(true);
0449         ui.lComment->setEnabled(true);
0450         ui.leComment->setEnabled(true);
0451         ui.leName->setText(m_axis->name());
0452         ui.leComment->setText(m_axis->comment());
0453         this->setModelIndexFromColumn(cbMajorTicksColumn, m_axis->majorTicksColumn());
0454         this->setModelIndexFromColumn(cbMinorTicksColumn, m_axis->minorTicksColumn());
0455     } else {
0456         ui.lName->setEnabled(false);
0457         ui.leName->setEnabled(false);
0458         ui.lComment->setEnabled(false);
0459         ui.leComment->setEnabled(false);
0460         ui.leName->setText(QString());
0461         ui.leComment->setText(QString());
0462         cbMajorTicksColumn->setCurrentModelIndex(QModelIndex());
0463         cbMinorTicksColumn->setCurrentModelIndex(QModelIndex());
0464     }
0465     ui.leName->setStyleSheet("");
0466     ui.leName->setToolTip("");
0467 
0468     //show the properties of the first axis
0469     this->load();
0470 
0471     // general
0472     connect(m_axis, &Axis::aspectDescriptionChanged, this, &AxisDock::axisDescriptionChanged);
0473     connect(m_axis, &Axis::orientationChanged, this, QOverload<Axis::Orientation>::of(&AxisDock::axisOrientationChanged));
0474     connect(m_axis, QOverload<Axis::Position>::of(&Axis::positionChanged),
0475             this, QOverload<Axis::Position>::of(&AxisDock::axisPositionChanged));
0476     connect(m_axis, &Axis::scaleChanged, this, &AxisDock::axisScaleChanged);
0477     connect(m_axis, &Axis::autoScaleChanged, this, &AxisDock::axisAutoScaleChanged);
0478     connect(m_axis, &Axis::startChanged, this, &AxisDock::axisStartChanged);
0479     connect(m_axis, &Axis::endChanged, this, &AxisDock::axisEndChanged);
0480     connect(m_axis, &Axis::zeroOffsetChanged, this, &AxisDock::axisZeroOffsetChanged);
0481     connect(m_axis, &Axis::scalingFactorChanged, this, &AxisDock::axisScalingFactorChanged);
0482 
0483     // line
0484     connect(m_axis, &Axis::linePenChanged, this, &AxisDock::axisLinePenChanged);
0485     connect(m_axis, &Axis::lineOpacityChanged, this, &AxisDock::axisLineOpacityChanged);
0486     connect(m_axis, &Axis::arrowTypeChanged, this, &AxisDock::axisArrowTypeChanged);
0487     connect(m_axis, &Axis::arrowPositionChanged, this, &AxisDock::axisArrowPositionChanged);
0488     connect(m_axis, &Axis::arrowSizeChanged, this, &AxisDock::axisArrowSizeChanged);
0489 
0490     // ticks
0491     connect(m_axis, &Axis::majorTicksDirectionChanged, this, &AxisDock::axisMajorTicksDirectionChanged);
0492     connect(m_axis, &Axis::majorTicksTypeChanged, this, &AxisDock::axisMajorTicksTypeChanged);
0493     connect(m_axis, &Axis::majorTicksNumberChanged, this, &AxisDock::axisMajorTicksNumberChanged);
0494     connect(m_axis, &Axis::majorTicksSpacingChanged, this, &AxisDock::axisMajorTicksSpacingChanged);
0495     connect(m_axis, &Axis::majorTicksPenChanged, this, &AxisDock::axisMajorTicksPenChanged);
0496     connect(m_axis, &Axis::majorTicksLengthChanged, this, &AxisDock::axisMajorTicksLengthChanged);
0497     connect(m_axis, &Axis::majorTicksOpacityChanged, this, &AxisDock::axisMajorTicksOpacityChanged);
0498     connect(m_axis, &Axis::minorTicksDirectionChanged, this, &AxisDock::axisMinorTicksDirectionChanged);
0499     connect(m_axis, &Axis::minorTicksTypeChanged, this, &AxisDock::axisMinorTicksTypeChanged);
0500     connect(m_axis, &Axis::minorTicksNumberChanged, this, &AxisDock::axisMinorTicksNumberChanged);
0501     connect(m_axis, &Axis::minorTicksIncrementChanged, this, &AxisDock::axisMinorTicksSpacingChanged);
0502     connect(m_axis, &Axis::minorTicksPenChanged, this, &AxisDock::axisMinorTicksPenChanged);
0503     connect(m_axis, &Axis::minorTicksLengthChanged, this, &AxisDock::axisMinorTicksLengthChanged);
0504     connect(m_axis, &Axis::minorTicksOpacityChanged, this, &AxisDock::axisMinorTicksOpacityChanged);
0505 
0506     // labels
0507     connect(m_axis, &Axis::labelsFormatChanged, this, &AxisDock::axisLabelsFormatChanged);
0508     connect(m_axis, &Axis::labelsAutoPrecisionChanged, this, &AxisDock::axisLabelsAutoPrecisionChanged);
0509     connect(m_axis, &Axis::labelsPrecisionChanged, this, &AxisDock::axisLabelsPrecisionChanged);
0510     connect(m_axis, &Axis::labelsDateTimeFormatChanged, this, &AxisDock::axisLabelsDateTimeFormatChanged);
0511     connect(m_axis, &Axis::labelsPositionChanged, this, &AxisDock::axisLabelsPositionChanged);
0512     connect(m_axis, &Axis::labelsOffsetChanged, this, &AxisDock::axisLabelsOffsetChanged);
0513     connect(m_axis, &Axis::labelsRotationAngleChanged, this, &AxisDock::axisLabelsRotationAngleChanged);
0514     connect(m_axis, &Axis::labelsFontChanged, this, &AxisDock::axisLabelsFontChanged);
0515     connect(m_axis, &Axis::labelsColorChanged, this, &AxisDock::axisLabelsFontColorChanged);
0516     connect(m_axis, &Axis::labelsBackgroundTypeChanged, this, &AxisDock::axisLabelsBackgroundTypeChanged);
0517     connect(m_axis, &Axis::labelsBackgroundColorChanged, this, &AxisDock::axisLabelsBackgroundColorChanged);
0518     connect(m_axis, &Axis::labelsPrefixChanged, this, &AxisDock::axisLabelsPrefixChanged);
0519     connect(m_axis, &Axis::labelsSuffixChanged, this, &AxisDock::axisLabelsSuffixChanged);
0520     connect(m_axis, &Axis::labelsOpacityChanged, this, &AxisDock::axisLabelsOpacityChanged);
0521 
0522     // grids
0523     connect(m_axis, &Axis::majorGridPenChanged, this, &AxisDock::axisMajorGridPenChanged);
0524     connect(m_axis, &Axis::majorGridOpacityChanged, this, &AxisDock::axisMajorGridOpacityChanged);
0525     connect(m_axis, &Axis::minorGridPenChanged, this, &AxisDock::axisMinorGridPenChanged);
0526     connect(m_axis, &Axis::minorGridOpacityChanged, this, &AxisDock::axisMinorGridOpacityChanged);
0527 
0528     connect(m_axis, &Axis::visibilityChanged, this, &AxisDock::axisVisibilityChanged);
0529 }
0530 
0531 /*
0532  * updates the locale in the widgets. called when the application settins are changed.
0533  */
0534 void AxisDock::updateLocale() {
0535     SET_NUMBER_LOCALE
0536     ui.sbLineWidth->setLocale(numberLocale);
0537     ui.sbMajorTicksSpacingNumeric->setLocale(numberLocale);
0538     ui.sbMajorTicksWidth->setLocale(numberLocale);
0539     ui.sbMajorTicksLength->setLocale(numberLocale);
0540     ui.sbMinorTicksSpacingNumeric->setLocale(numberLocale);
0541     ui.sbMinorTicksWidth->setLocale(numberLocale);
0542     ui.sbMinorTicksLength->setLocale(numberLocale);
0543     ui.sbLabelsOffset->setLocale(numberLocale);
0544     ui.sbMajorGridWidth->setLocale(numberLocale);
0545     ui.sbMinorGridWidth->setLocale(numberLocale);
0546 
0547     //update the QLineEdits, avoid the change events
0548     Lock lock(m_initializing);
0549     ui.lePosition->setText(numberLocale.toString(m_axis->offset()));
0550     ui.leStart->setText(numberLocale.toString(m_axis->start()));
0551     ui.leEnd->setText(numberLocale.toString(m_axis->end()));
0552 
0553     //update the title label
0554     labelWidget->updateLocale();
0555 }
0556 
0557 void AxisDock::activateTitleTab() {
0558     ui.tabWidget->setCurrentWidget(ui.tabTitle);
0559 }
0560 
0561 void AxisDock::setModelIndexFromColumn(TreeViewComboBox* cb, const AbstractColumn* column) {
0562     if (column)
0563         cb->setCurrentModelIndex(m_aspectTreeModel->modelIndexOfAspect(column));
0564     else
0565         cb->setCurrentModelIndex(QModelIndex());
0566 }
0567 
0568 //*************************************************************
0569 //********** SLOTs for changes triggered in AxisDock **********
0570 //*************************************************************
0571 //"General"-tab
0572 void AxisDock::visibilityChanged(bool state) {
0573     if (m_initializing)
0574         return;
0575 
0576     for (auto* axis : m_axesList)
0577         axis->setVisible(state);
0578 }
0579 
0580 /*!
0581     called if the orientation (horizontal or vertical) of the current axis is changed.
0582 */
0583 void AxisDock::orientationChanged(int item) {
0584     auto orientation{Axis::Orientation(item)};
0585     if (orientation == Axis::Orientation::Horizontal) {
0586         ui.cbPosition->setItemText(0, i18n("Top") );
0587         ui.cbPosition->setItemText(1, i18n("Bottom") );
0588         ui.cbLabelsPosition->setItemText(1, i18n("Top") );
0589         ui.cbLabelsPosition->setItemText(2, i18n("Bottom") );
0590 
0591         ui.cbScale->setItemText(1, QLatin1String("log(x)") );
0592         ui.cbScale->setItemText(2, QLatin1String("log2(x)") );
0593         ui.cbScale->setItemText(3, QLatin1String("ln(x)") );
0594         ui.cbScale->setItemText(4, QLatin1String("sqrt(x)") );
0595         ui.cbScale->setItemText(5, QLatin1String("x^2") );
0596     } else { //vertical
0597         ui.cbPosition->setItemText(0, i18n("Left") );
0598         ui.cbPosition->setItemText(1, i18n("Right") );
0599         ui.cbLabelsPosition->setItemText(1, i18n("Right") );
0600         ui.cbLabelsPosition->setItemText(2, i18n("Left") );
0601 
0602         ui.cbScale->setItemText(1, QLatin1String("log(y)") );
0603         ui.cbScale->setItemText(2, QLatin1String("log2(y)") );
0604         ui.cbScale->setItemText(3, QLatin1String("ln(y)") );
0605         ui.cbScale->setItemText(4, QLatin1String("sqrt(y)") );
0606         ui.cbScale->setItemText(5, QLatin1String("y^2") );
0607     }
0608 
0609     if (m_initializing)
0610         return;
0611 
0612     //depending on the current orientation we need to update axis position and labels position
0613 
0614     //axis position, map from the current index in the combobox to the enum value in Axis::Position
0615     Axis::Position axisPosition;
0616     int posIndex = ui.cbPosition->currentIndex();
0617     if (orientation == Axis::Orientation::Horizontal) {
0618         if (posIndex > 1)
0619             posIndex += 2;
0620         axisPosition = Axis::Position(posIndex);
0621     } else
0622         axisPosition = Axis::Position(posIndex+2);
0623 
0624     //labels position
0625     posIndex = ui.cbLabelsPosition->currentIndex();
0626     auto labelsPosition = Axis::LabelsPosition(posIndex);
0627 
0628     for (auto* axis : m_axesList) {
0629         axis->beginMacro(i18n("%1: set axis orientation", axis->name()));
0630         axis->setOrientation(orientation);
0631         axis->setPosition(axisPosition);
0632         axis->setLabelsPosition(labelsPosition);
0633         axis->endMacro();
0634     }
0635 }
0636 
0637 /*!
0638     called if one of the predefined axis positions
0639     (top, bottom, left, right, center or custom) was changed.
0640 */
0641 void AxisDock::positionChanged(int index) {
0642     if (index == -1)
0643         return; //we occasionally get -1 here, nothing to do in this case
0644 
0645     if (index == 3)
0646         ui.lePosition->setVisible(true);
0647     else
0648         ui.lePosition->setVisible(false);
0649 
0650     if (m_initializing)
0651         return;
0652 
0653     //map from the current index in the combo box to the enum value in Axis::Position,
0654     //depends on the current orientation
0655     Axis::Position position;
0656     if ( ui.cbOrientation->currentIndex() == 0 ) {
0657         if (index>1)
0658             index += 2;
0659         position = Axis::Position(index);
0660     } else
0661         position = Axis::Position(index+2);
0662 
0663     for (auto* axis : m_axesList)
0664         axis->setPosition(position);
0665 }
0666 
0667 /*!
0668     called when the custom position of the axis in the corresponding LineEdit is changed.
0669 */
0670 void AxisDock::positionChanged() {
0671     if (m_initializing)
0672         return;
0673 
0674     bool ok;
0675     SET_NUMBER_LOCALE
0676     const double offset{numberLocale.toDouble(ui.lePosition->text(), &ok)};
0677     if (ok) {
0678         for (auto* axis : m_axesList)
0679             axis->setOffset(offset);
0680     }
0681 }
0682 
0683 void AxisDock::scaleChanged(int index) {
0684     if (m_initializing)
0685         return;
0686 
0687     auto scale = static_cast<Axis::Scale>(index);
0688     for (auto* axis : m_axesList)
0689         axis->setScale(scale);
0690 }
0691 
0692 void AxisDock::autoScaleChanged(int index) {
0693     bool autoScale = index == Qt::Checked;
0694     ui.leStart->setEnabled(!autoScale);
0695     ui.leEnd->setEnabled(!autoScale);
0696     ui.dateTimeEditStart->setEnabled(!autoScale);
0697     ui.dateTimeEditEnd->setEnabled(!autoScale);
0698 
0699     if (m_initializing)
0700         return;
0701 
0702     for (auto* axis : m_axesList)
0703         axis->setAutoScale(autoScale);
0704 }
0705 
0706 void AxisDock::startChanged() {
0707     if (m_initializing)
0708         return;
0709 
0710     bool ok;
0711     SET_NUMBER_LOCALE
0712     double value{numberLocale.toDouble(ui.leStart->text(), &ok)};
0713     if (!ok)
0714         return;
0715 
0716     //check first, whether the value for the lower limit is valid for the log- and square root scaling. If not, set the default values.
0717     auto scale = Axis::Scale(ui.cbScale->currentIndex());
0718     if (scale == Axis::Scale::Log10 || scale == Axis::Scale::Log2 || scale == Axis::Scale::Ln) {
0719         if (value <= 0) {
0720             KMessageBox::sorry(this,
0721                                i18n("The axes lower limit has a non-positive value. Default minimal value will be used."),
0722                                i18n("Wrong lower limit value") );
0723             value = 0.01;
0724             ui.leStart->setText(numberLocale.toString(value) );
0725         }
0726     } else if (scale == Axis::Scale::Sqrt) {
0727         if (value < 0) {
0728             KMessageBox::sorry(this,
0729                                i18n("The axes lower limit has a negative value. Default minimal value will be used."),
0730                                i18n("Wrong lower limit value") );
0731             value = 0;
0732             ui.leStart->setText(numberLocale.toString(value) );
0733         }
0734     }
0735 
0736     const Lock lock(m_initializing);
0737     for (auto* axis : m_axesList)
0738         axis->setStart(value);
0739 }
0740 
0741 void AxisDock::endChanged() {
0742     if (m_initializing)
0743         return;
0744 
0745     bool ok;
0746     SET_NUMBER_LOCALE
0747     const double value{numberLocale.toDouble(ui.leEnd->text(), &ok)};
0748     if (!ok)
0749         return;
0750 
0751     const Lock lock(m_initializing);
0752     for (auto* axis : m_axesList)
0753         axis->setEnd(value);
0754 }
0755 
0756 void AxisDock::startDateTimeChanged(const QDateTime& dateTime) {
0757     if (m_initializing)
0758         return;
0759 
0760     quint64 value = dateTime.toMSecsSinceEpoch();
0761     for (auto* axis : m_axesList)
0762         axis->setStart(value);
0763 }
0764 
0765 void AxisDock::endDateTimeChanged(const QDateTime& dateTime) {
0766     if (m_initializing)
0767         return;
0768 
0769     quint64 value = dateTime.toMSecsSinceEpoch();
0770     for (auto* axis : m_axesList)
0771         axis->setEnd(value);
0772 }
0773 
0774 void AxisDock::zeroOffsetChanged() {
0775     if (m_initializing)
0776         return;
0777 
0778     bool ok;
0779     SET_NUMBER_LOCALE
0780     const double offset{numberLocale.toDouble(ui.leZeroOffset->text(), &ok)};
0781     if (!ok)
0782         return;
0783 
0784     const Lock lock(m_initializing);
0785     for (auto* axis : m_axesList)
0786         axis->setZeroOffset(offset);
0787 }
0788 
0789 void AxisDock::scalingFactorChanged() {
0790     if (m_initializing)
0791         return;
0792 
0793     bool ok;
0794     SET_NUMBER_LOCALE
0795     const double scalingFactor{numberLocale.toDouble(ui.leScalingFactor->text(), &ok)};
0796     if (!ok)
0797         return;
0798 
0799     if (scalingFactor != 0.0) {
0800         const Lock lock(m_initializing);
0801         for (auto* axis : m_axesList)
0802             axis->setScalingFactor(scalingFactor);
0803     }
0804 }
0805 
0806 // "Line"-tab
0807 void AxisDock::lineStyleChanged(int index) {
0808     if (index == -1)
0809         return;
0810 
0811     auto penStyle = Qt::PenStyle(index);
0812 
0813     bool b = (penStyle != Qt::NoPen);
0814     ui.lLineColor->setEnabled(b);
0815     ui.kcbLineColor->setEnabled(b);
0816     ui.lLineWidth->setEnabled(b);
0817     ui.sbLineWidth->setEnabled(b);
0818     ui.lLineOpacity->setEnabled(b);
0819     ui.sbLineOpacity->setEnabled(b);
0820 
0821     if (m_initializing)
0822         return;
0823 
0824     QPen pen;
0825     for (auto* axis : m_axesList) {
0826         pen = axis->linePen();
0827         pen.setStyle(penStyle);
0828         axis->setLinePen(pen);
0829     }
0830 }
0831 
0832 void AxisDock::lineColorChanged(const QColor& color) {
0833     if (m_initializing)
0834         return;
0835 
0836     QPen pen;
0837     for (auto* axis : m_axesList) {
0838         pen = axis->linePen();
0839         pen.setColor(color);
0840         axis->setLinePen(pen);
0841     }
0842 
0843     m_initializing = true;
0844     GuiTools::updatePenStyles(ui.cbLineStyle, color);
0845     m_initializing = false;
0846 }
0847 
0848 void AxisDock::lineWidthChanged(double value) {
0849     if (m_initializing)
0850         return;
0851 
0852     QPen pen;
0853     for (auto* axis : m_axesList) {
0854         pen = axis->linePen();
0855         pen.setWidthF(Worksheet::convertToSceneUnits(value, Worksheet::Unit::Point));
0856         axis->setLinePen(pen);
0857     }
0858 }
0859 
0860 void AxisDock::lineOpacityChanged(int value) {
0861     if (m_initializing)
0862         return;
0863 
0864     qreal opacity = (double)value/100.;
0865     for (auto* axis : m_axesList)
0866         axis->setLineOpacity(opacity);
0867 }
0868 
0869 void AxisDock::arrowTypeChanged(int index) {
0870     auto type = (Axis::ArrowType)index;
0871     if (type == Axis::ArrowType::NoArrow) {
0872         ui.cbArrowPosition->setEnabled(false);
0873         ui.sbArrowSize->setEnabled(false);
0874     } else {
0875         ui.cbArrowPosition->setEnabled(true);
0876         ui.sbArrowSize->setEnabled(true);
0877     }
0878 
0879     if (m_initializing)
0880         return;
0881 
0882     for (auto* axis : m_axesList)
0883         axis->setArrowType(type);
0884 }
0885 
0886 void AxisDock::arrowPositionChanged(int index) {
0887     if (m_initializing)
0888         return;
0889 
0890     auto position = (Axis::ArrowPosition)index;
0891     for (auto* axis : m_axesList)
0892         axis->setArrowPosition(position);
0893 }
0894 
0895 void AxisDock::arrowSizeChanged(int value) {
0896     if (m_initializing)
0897         return;
0898 
0899     double v = Worksheet::convertToSceneUnits(value, Worksheet::Unit::Point);
0900     for (auto* axis : m_axesList)
0901         axis->setArrowSize(v);
0902 }
0903 
0904 //"Major ticks" tab
0905 void AxisDock::majorTicksDirectionChanged(int index) {
0906     Axis::TicksDirection direction = Axis::TicksDirection(index);
0907 
0908     bool b = (direction != Axis::noTicks);
0909     ui.lMajorTicksType->setEnabled(b);
0910     ui.cbMajorTicksType->setEnabled(b);
0911     ui.lMajorTicksType->setEnabled(b);
0912     ui.cbMajorTicksType->setEnabled(b);
0913     ui.lMajorTicksNumber->setEnabled(b);
0914     ui.sbMajorTicksNumber->setEnabled(b);
0915     ui.lMajorTicksSpacingNumeric->setEnabled(b);
0916     ui.sbMajorTicksSpacingNumeric->setEnabled(b);
0917     ui.lMajorTicksIncrementDateTime->setEnabled(b);
0918     dtsbMajorTicksIncrement->setEnabled(b);
0919     ui.lMajorTicksLineStyle->setEnabled(b);
0920     ui.cbMajorTicksLineStyle->setEnabled(b);
0921     dtsbMinorTicksIncrement->setEnabled(b);
0922     if (b) {
0923         if (ui.cbMajorTicksLineStyle->currentIndex() != -1) {
0924             auto penStyle = Qt::PenStyle(ui.cbMajorTicksLineStyle->currentIndex());
0925             b = (penStyle != Qt::NoPen);
0926         } else
0927             b = false;
0928     }
0929     ui.lMajorTicksColor->setEnabled(b);
0930     ui.kcbMajorTicksColor->setEnabled(b);
0931     ui.lMajorTicksWidth->setEnabled(b);
0932     ui.sbMajorTicksWidth->setEnabled(b);
0933     ui.lMajorTicksLength->setEnabled(b);
0934     ui.sbMajorTicksLength->setEnabled(b);
0935     ui.lMajorTicksOpacity->setEnabled(b);
0936     ui.sbMajorTicksOpacity->setEnabled(b);
0937 
0938     if (m_initializing)
0939         return;
0940 
0941     for (auto* axis : m_axesList)
0942         axis->setMajorTicksDirection(direction);
0943 }
0944 
0945 /*!
0946     called if the current style of the ticks (Number or Increment) is changed.
0947     Shows/hides the corresponding widgets.
0948 */
0949 void AxisDock::majorTicksTypeChanged(int index) {
0950     if (!m_axis) // If elements are added to the combobox 'cbMajorTicksType' (at init of this class), then this function is called, which is a problem if no axis are available
0951         return;
0952 
0953     auto type = Axis::TicksType(index);
0954     if (type == Axis::TicksType::TotalNumber) {
0955         ui.lMajorTicksNumber->show();
0956         ui.sbMajorTicksNumber->show();
0957         ui.lMajorTicksSpacingNumeric->hide();
0958         ui.sbMajorTicksSpacingNumeric->hide();
0959         ui.lMajorTicksIncrementDateTime->hide();
0960         dtsbMajorTicksIncrement->hide();
0961         ui.lMajorTicksColumn->hide();
0962         cbMajorTicksColumn->hide();
0963     } else if (type == Axis::TicksType::Spacing) {
0964         ui.lMajorTicksNumber->hide();
0965         ui.sbMajorTicksNumber->hide();
0966         ui.lMajorTicksSpacingNumeric->show();
0967 
0968         const auto* plot = static_cast<const CartesianPlot*>(m_axis->parentAspect());
0969         bool numeric = ( (m_axis->orientation() == Axis::Orientation::Horizontal && plot->xRangeFormat() == CartesianPlot::RangeFormat::Numeric)
0970                     || (m_axis->orientation() == Axis::Orientation::Vertical && plot->yRangeFormat() == CartesianPlot::RangeFormat::Numeric) );
0971         if (numeric) {
0972             ui.lMajorTicksIncrementDateTime->hide();
0973             dtsbMajorTicksIncrement->hide();
0974             ui.lMajorTicksSpacingNumeric->show();
0975             ui.sbMajorTicksSpacingNumeric->show();
0976         } else {
0977             ui.lMajorTicksIncrementDateTime->show();
0978             dtsbMajorTicksIncrement->show();
0979             ui.lMajorTicksSpacingNumeric->hide();
0980             ui.sbMajorTicksSpacingNumeric->hide();
0981         }
0982 
0983         ui.lMajorTicksColumn->hide();
0984         cbMajorTicksColumn->hide();
0985 
0986         // Check if spacing is not to small
0987         majorTicksSpacingChanged();
0988     } else {
0989         ui.lMajorTicksNumber->hide();
0990         ui.sbMajorTicksNumber->hide();
0991         ui.lMajorTicksSpacingNumeric->hide();
0992         ui.sbMajorTicksSpacingNumeric->hide();
0993         ui.lMajorTicksIncrementDateTime->hide();
0994         dtsbMajorTicksIncrement->hide();
0995         ui.lMajorTicksColumn->show();
0996         cbMajorTicksColumn->show();
0997     }
0998 
0999     if (m_initializing)
1000         return;
1001 
1002     for (auto* axis : m_axesList)
1003         axis->setMajorTicksType(type);
1004 }
1005 
1006 void AxisDock::majorTicksNumberChanged(int value) {
1007     if (m_initializing)
1008         return;
1009 
1010     for (auto* axis : m_axesList)
1011         axis->setMajorTicksNumber(value);
1012 }
1013 
1014 void AxisDock::majorTicksSpacingChanged() {
1015     if (m_initializing)
1016         return;
1017 
1018     const auto* plot = static_cast<const CartesianPlot*>(m_axis->parentAspect());
1019 
1020     bool numeric = ( (m_axis->orientation() == Axis::Orientation::Horizontal && plot->xRangeFormat() == CartesianPlot::RangeFormat::Numeric)
1021         || (m_axis->orientation() == Axis::Orientation::Vertical && plot->yRangeFormat() == CartesianPlot::RangeFormat::Numeric) );
1022 
1023     double spacing = numeric ? ui.sbMajorTicksSpacingNumeric->value() : dtsbMajorTicksIncrement->value();
1024     double range = fabs(m_axis->end() - m_axis->start());
1025     DEBUG("major spacing = " << spacing << ", range = " << range)
1026 
1027     // fix spacing if incorrect (not set or > 100 ticks)
1028     if (spacing == 0. || range / spacing > 100.) {
1029         if (spacing == 0)
1030             spacing = range / (ui.sbMajorTicksNumber->value() - 1);
1031 
1032         if (range / spacing > 100.)
1033             spacing = range / 100.;
1034 
1035         DEBUG("new spacing = " << spacing)
1036         // determine stepsize and number of decimals
1037         m_initializing = true;
1038         if (numeric) {
1039             int decimals = nsl_math_rounded_decimals(spacing) + 1;
1040             DEBUG("decimals = " << decimals << ", step = " << gsl_pow_int(10., -decimals))
1041             ui.sbMajorTicksSpacingNumeric->setDecimals(decimals);
1042             ui.sbMajorTicksSpacingNumeric->setSingleStep(gsl_pow_int(10., -decimals));
1043             ui.sbMajorTicksSpacingNumeric->setMaximum(range);
1044             ui.sbMajorTicksSpacingNumeric->setValue(spacing);
1045         } else  //TODO: check reversed axis
1046             dtsbMajorTicksIncrement->setValue(spacing);
1047         m_initializing = false;
1048     }
1049 
1050     for (auto* axis : m_axesList)
1051         axis->setMajorTicksSpacing(spacing);
1052 }
1053 
1054 void AxisDock::majorTicksLineStyleChanged(int index) {
1055     if (index == -1)
1056         return;
1057 
1058     auto penStyle = Qt::PenStyle(index);
1059 
1060     bool b = (penStyle != Qt::NoPen);
1061     ui.lMajorTicksColor->setEnabled(b);
1062     ui.kcbMajorTicksColor->setEnabled(b);
1063     ui.lMajorTicksWidth->setEnabled(b);
1064     ui.sbMajorTicksWidth->setEnabled(b);
1065     ui.lMajorTicksLength->setEnabled(b);
1066     ui.sbMajorTicksLength->setEnabled(b);
1067     ui.lMajorTicksOpacity->setEnabled(b);
1068     ui.sbMajorTicksOpacity->setEnabled(b);
1069 
1070     if (m_initializing)
1071         return;
1072 
1073     QPen pen;
1074     for (auto* axis : m_axesList) {
1075         pen = axis->majorTicksPen();
1076         pen.setStyle(penStyle);
1077         axis->setMajorTicksPen(pen);
1078     }
1079 }
1080 
1081 void AxisDock::majorTicksColumnChanged(const QModelIndex& index) {
1082     if (m_initializing)
1083         return;
1084 
1085     auto* aspect = static_cast<AbstractAspect*>(index.internalPointer());
1086     AbstractColumn* column = nullptr;
1087     if (aspect) {
1088         column = dynamic_cast<AbstractColumn*>(aspect);
1089         Q_ASSERT(column != nullptr);
1090     }
1091 
1092     for (auto* axis : m_axesList)
1093         axis->setMajorTicksColumn(column);
1094 }
1095 
1096 void AxisDock::majorTicksColorChanged(const QColor& color) {
1097     if (m_initializing)
1098         return;
1099 
1100     QPen pen;
1101     for (auto* axis : m_axesList) {
1102         pen = axis->majorTicksPen();
1103         pen.setColor(color);
1104         axis->setMajorTicksPen(pen);
1105     }
1106 
1107     m_initializing = true;
1108     GuiTools::updatePenStyles(ui.cbMajorTicksLineStyle, color);
1109     m_initializing = false;
1110 }
1111 
1112 void AxisDock::majorTicksWidthChanged(double value) {
1113     if (m_initializing)
1114         return;
1115 
1116     QPen pen;
1117     for (auto* axis : m_axesList) {
1118         pen = axis->majorTicksPen();
1119         pen.setWidthF( Worksheet::convertToSceneUnits(value, Worksheet::Unit::Point) );
1120         axis->setMajorTicksPen(pen);
1121     }
1122 }
1123 
1124 void AxisDock::majorTicksLengthChanged(double value) {
1125     if (m_initializing)
1126         return;
1127 
1128     for (auto* axis : m_axesList)
1129         axis->setMajorTicksLength( Worksheet::convertToSceneUnits(value, Worksheet::Unit::Point) );
1130 }
1131 
1132 void AxisDock::majorTicksOpacityChanged(int value) {
1133     if (m_initializing)
1134         return;
1135 
1136     qreal opacity = (double)value/100.;
1137     for (auto* axis : m_axesList)
1138         axis->setMajorTicksOpacity(opacity);
1139 }
1140 
1141 //"Minor ticks" tab
1142 void AxisDock::minorTicksDirectionChanged(int index) {
1143     Axis::TicksDirection direction = Axis::TicksDirection(index);
1144     bool b = (direction != Axis::noTicks);
1145     ui.lMinorTicksType->setEnabled(b);
1146     ui.cbMinorTicksType->setEnabled(b);
1147     ui.lMinorTicksType->setEnabled(b);
1148     ui.cbMinorTicksType->setEnabled(b);
1149     ui.lMinorTicksNumber->setEnabled(b);
1150     ui.sbMinorTicksNumber->setEnabled(b);
1151     ui.lMinorTicksSpacingNumeric->setEnabled(b);
1152     ui.sbMinorTicksSpacingNumeric->setEnabled(b);
1153     ui.lMinorTicksIncrementDateTime->setEnabled(b);
1154     dtsbMinorTicksIncrement->setEnabled(b);
1155     ui.lMinorTicksLineStyle->setEnabled(b);
1156     ui.cbMinorTicksLineStyle->setEnabled(b);
1157     if (b) {
1158         if (ui.cbMinorTicksLineStyle->currentIndex() != -1) {
1159             auto penStyle = Qt::PenStyle(ui.cbMinorTicksLineStyle->currentIndex());
1160             b = (penStyle != Qt::NoPen);
1161         } else
1162             b = false;
1163     }
1164     ui.lMinorTicksColor->setEnabled(b);
1165     ui.kcbMinorTicksColor->setEnabled(b);
1166     ui.lMinorTicksWidth->setEnabled(b);
1167     ui.sbMinorTicksWidth->setEnabled(b);
1168     ui.lMinorTicksLength->setEnabled(b);
1169     ui.sbMinorTicksLength->setEnabled(b);
1170     ui.lMinorTicksOpacity->setEnabled(b);
1171     ui.sbMinorTicksOpacity->setEnabled(b);
1172 
1173     if (m_initializing)
1174         return;
1175 
1176     for (auto* axis : m_axesList)
1177         axis->setMinorTicksDirection(direction);
1178 }
1179 
1180 void AxisDock::minorTicksTypeChanged(int index) {
1181     if (!m_axis) // If elements are added to the combobox 'cbMajorTicksType' (at init of this class), then this function is called, which is a problem if no axis are available
1182         return;
1183 
1184     auto type = Axis::TicksType(index);
1185     if (type == Axis::TicksType::TotalNumber) {
1186         ui.lMinorTicksNumber->show();
1187         ui.sbMinorTicksNumber->show();
1188         ui.lMinorTicksSpacingNumeric->hide();
1189         ui.sbMinorTicksSpacingNumeric->hide();
1190         ui.lMinorTicksColumn->hide();
1191         cbMinorTicksColumn->hide();
1192         ui.lMinorTicksIncrementDateTime->hide();
1193         dtsbMinorTicksIncrement->hide();
1194     } else if ( type == Axis::TicksType::Spacing) {
1195         ui.lMinorTicksNumber->hide();
1196         ui.sbMinorTicksNumber->hide();
1197 
1198         const auto* plot = static_cast<const CartesianPlot*>(m_axis->parentAspect());
1199         bool numeric = ( (m_axis->orientation() == Axis::Orientation::Horizontal && plot->xRangeFormat() == CartesianPlot::RangeFormat::Numeric)
1200                     || (m_axis->orientation() == Axis::Orientation::Vertical && plot->yRangeFormat() == CartesianPlot::RangeFormat::Numeric) );
1201         if (numeric) {
1202             ui.lMinorTicksSpacingNumeric->show();
1203             ui.sbMinorTicksSpacingNumeric->show();
1204             ui.lMinorTicksIncrementDateTime->hide();
1205             dtsbMinorTicksIncrement->hide();
1206         } else {
1207             ui.lMinorTicksSpacingNumeric->hide();
1208             ui.sbMinorTicksSpacingNumeric->hide();
1209             ui.lMinorTicksIncrementDateTime->show();
1210             dtsbMinorTicksIncrement->show();
1211         }
1212 
1213         ui.lMinorTicksColumn->hide();
1214         cbMinorTicksColumn->hide();
1215 
1216         // Check if spacing is not to small
1217         minorTicksSpacingChanged();
1218     } else {
1219         ui.lMinorTicksNumber->hide();
1220         ui.sbMinorTicksNumber->hide();
1221         ui.lMinorTicksSpacingNumeric->hide();
1222         ui.sbMinorTicksSpacingNumeric->hide();
1223         ui.lMinorTicksIncrementDateTime->hide();
1224         dtsbMinorTicksIncrement->hide();
1225         ui.lMinorTicksColumn->show();
1226         cbMinorTicksColumn->show();
1227     }
1228 
1229     if (m_initializing)
1230         return;
1231 
1232     for (auto* axis : m_axesList)
1233         axis->setMinorTicksType(type);
1234 }
1235 
1236 void AxisDock::minorTicksNumberChanged(int value) {
1237     if (m_initializing)
1238         return;
1239 
1240     for (auto* axis : m_axesList)
1241         axis->setMinorTicksNumber(value);
1242 }
1243 
1244 void AxisDock::minorTicksSpacingChanged() {
1245     if (m_initializing)
1246         return;
1247 
1248     const auto* plot = static_cast<const CartesianPlot*>(m_axis->parentAspect());
1249 
1250     bool numeric = ( (m_axis->orientation() == Axis::Orientation::Horizontal && plot->xRangeFormat() == CartesianPlot::RangeFormat::Numeric)
1251         || (m_axis->orientation() == Axis::Orientation::Vertical && plot->yRangeFormat() == CartesianPlot::RangeFormat::Numeric) );
1252 
1253     double spacing = numeric ? ui.sbMinorTicksSpacingNumeric->value() : dtsbMinorTicksIncrement->value();
1254     double range = fabs(m_axis->end() - m_axis->start());
1255     //DEBUG("minor spacing = " << spacing << ", range = " << range)
1256     int numberTicks = 0;
1257 
1258     int majorTicks = m_axis->majorTicksNumber();
1259     if (spacing > 0.)
1260         numberTicks = range / (majorTicks - 1) / spacing - 1; // recalc
1261     //DEBUG("   nticks = " << numberTicks)
1262 
1263     // set if unset or > 100.
1264     if (spacing == 0. || numberTicks > 100) {
1265         if (spacing == 0.)
1266             spacing = range / (majorTicks - 1) / (ui.sbMinorTicksNumber->value() + 1);
1267 
1268         numberTicks = range / (majorTicks - 1) / spacing - 1; // recalculate number of ticks
1269 
1270         if (numberTicks > 100) // maximum 100 minor ticks
1271             spacing = range / (majorTicks - 1) / (100 + 1);
1272 
1273         DEBUG("new spacing = " << spacing)
1274         DEBUG("new nticks = " << numberTicks)
1275         // determine stepsize and number of decimals
1276         m_initializing = true;
1277         if (numeric) {
1278             int decimals = nsl_math_rounded_decimals(spacing) + 1;
1279             DEBUG("decimals = " << decimals << ", step = " << gsl_pow_int(10., -decimals))
1280             ui.sbMinorTicksSpacingNumeric->setDecimals(decimals);
1281             ui.sbMinorTicksSpacingNumeric->setSingleStep(gsl_pow_int(10., -decimals));
1282             ui.sbMinorTicksSpacingNumeric->setMaximum(range);
1283             ui.sbMinorTicksSpacingNumeric->setValue(spacing);
1284         } else
1285             dtsbMinorTicksIncrement->setValue(spacing);
1286         m_initializing = false;
1287     }
1288 
1289     for (auto* axis : m_axesList)
1290         axis->setMinorTicksSpacing(spacing);
1291 }
1292 
1293 void AxisDock::minorTicksColumnChanged(const QModelIndex& index) {
1294     if (m_initializing)
1295         return;
1296 
1297     auto* aspect = static_cast<AbstractAspect*>(index.internalPointer());
1298     auto* column = dynamic_cast<AbstractColumn*>(aspect);
1299     Q_ASSERT(column != nullptr);
1300 
1301     for (auto* axis : m_axesList)
1302         axis->setMinorTicksColumn(column);
1303 }
1304 
1305 void AxisDock::minorTicksLineStyleChanged(int index) {
1306     if (index == -1)
1307         return;
1308 
1309     auto penStyle = Qt::PenStyle(index);
1310 
1311     bool b = (penStyle != Qt::NoPen);
1312     ui.lMinorTicksColor->setEnabled(b);
1313     ui.kcbMinorTicksColor->setEnabled(b);
1314     ui.lMinorTicksWidth->setEnabled(b);
1315     ui.sbMinorTicksWidth->setEnabled(b);
1316     ui.lMinorTicksLength->setEnabled(b);
1317     ui.sbMinorTicksLength->setEnabled(b);
1318     ui.lMinorTicksOpacity->setEnabled(b);
1319     ui.sbMinorTicksOpacity->setEnabled(b);
1320 
1321     if (m_initializing)
1322         return;
1323 
1324     QPen pen;
1325     for (auto* axis : m_axesList) {
1326         pen = axis->minorTicksPen();
1327         pen.setStyle(penStyle);
1328         axis->setMinorTicksPen(pen);
1329     }
1330 }
1331 
1332 void AxisDock::minorTicksColorChanged(const QColor& color) {
1333     if (m_initializing)
1334         return;
1335 
1336     QPen pen;
1337     for (auto* axis : m_axesList) {
1338         pen = axis->minorTicksPen();
1339         pen.setColor(color);
1340         axis->setMinorTicksPen(pen);
1341     }
1342 
1343     m_initializing = true;
1344     GuiTools::updatePenStyles(ui.cbMinorTicksLineStyle, color);
1345     m_initializing = false;
1346 }
1347 
1348 void AxisDock::minorTicksWidthChanged(double value) {
1349     if (m_initializing)
1350         return;
1351 
1352     QPen pen;
1353     for (auto* axis : m_axesList) {
1354         pen = axis->minorTicksPen();
1355         pen.setWidthF( Worksheet::convertToSceneUnits(value, Worksheet::Unit::Point) );
1356         axis->setMinorTicksPen(pen);
1357     }
1358 }
1359 
1360 void AxisDock::minorTicksLengthChanged(double value) {
1361     if (m_initializing)
1362         return;
1363 
1364     for (auto* axis : m_axesList)
1365         axis->setMinorTicksLength( Worksheet::convertToSceneUnits(value, Worksheet::Unit::Point) );
1366 }
1367 
1368 void AxisDock::minorTicksOpacityChanged(int value) {
1369     if (m_initializing)
1370         return;
1371 
1372     qreal opacity = (double)value/100.;
1373     for (auto* axis : m_axesList)
1374         axis->setMinorTicksOpacity(opacity);
1375 }
1376 
1377 //"Tick labels"-tab
1378 void AxisDock::labelsFormatChanged(int index) {
1379     if (m_initializing)
1380         return;
1381 
1382     for (auto* axis : m_axesList)
1383         axis->setLabelsFormat(Axis::LabelsFormat(index));
1384 }
1385 
1386 void AxisDock::labelsPrecisionChanged(int value) {
1387     if (m_initializing)
1388         return;
1389 
1390     for (auto* axis : m_axesList)
1391         axis->setLabelsPrecision(value);
1392 }
1393 
1394 
1395 void AxisDock::labelsAutoPrecisionChanged(int state) {
1396     bool checked = (state == Qt::Checked);
1397     ui.sbLabelsPrecision->setEnabled(!checked);
1398 
1399     if (m_initializing)
1400         return;
1401 
1402     for (auto* axis : m_axesList)
1403         axis->setLabelsAutoPrecision(checked);
1404 }
1405 
1406 void AxisDock::labelsDateTimeFormatChanged(int) {
1407     if (m_initializing)
1408         return;
1409 
1410     for (auto* axis : m_axesList)
1411         axis->setLabelsDateTimeFormat(ui.cbLabelsDateTimeFormat->currentText());
1412 }
1413 
1414 void AxisDock::labelsPositionChanged(int index) {
1415     auto position = Axis::LabelsPosition(index);
1416 
1417     bool b = (position != Axis::LabelsPosition::NoLabels);
1418     ui.lLabelsOffset->setEnabled(b);
1419     ui.sbLabelsOffset->setEnabled(b);
1420     ui.lLabelsRotation->setEnabled(b);
1421     ui.sbLabelsRotation->setEnabled(b);
1422     ui.lLabelsFont->setEnabled(b);
1423     ui.kfrLabelsFont->setEnabled(b);
1424     ui.lLabelsColor->setEnabled(b);
1425     ui.kcbLabelsFontColor->setEnabled(b);
1426     ui.lLabelsPrefix->setEnabled(b);
1427     ui.leLabelsPrefix->setEnabled(b);
1428     ui.lLabelsSuffix->setEnabled(b);
1429     ui.leLabelsSuffix->setEnabled(b);
1430     ui.lLabelsOpacity->setEnabled(b);
1431     ui.sbLabelsOpacity->setEnabled(b);
1432 
1433     if (m_initializing)
1434         return;
1435 
1436     for (auto* axis : m_axesList)
1437         axis->setLabelsPosition(position);
1438 }
1439 
1440 void AxisDock::labelsOffsetChanged(double value) {
1441     if (m_initializing)
1442         return;
1443 
1444     for (auto* axis : m_axesList)
1445         axis->setLabelsOffset( Worksheet::convertToSceneUnits(value, Worksheet::Unit::Point) );
1446 }
1447 
1448 void AxisDock::labelsRotationChanged(int value) {
1449     if (m_initializing)
1450         return;
1451 
1452     for (auto* axis : m_axesList)
1453         axis->setLabelsRotationAngle(value);
1454 }
1455 
1456 void AxisDock::labelsPrefixChanged() {
1457     if (m_initializing)
1458         return;
1459 
1460     QString prefix = ui.leLabelsPrefix->text();
1461     for (auto* axis : m_axesList)
1462         axis->setLabelsPrefix(prefix);
1463 }
1464 
1465 void AxisDock::labelsSuffixChanged() {
1466     if (m_initializing)
1467         return;
1468 
1469     QString suffix = ui.leLabelsSuffix->text();
1470     for (auto* axis : m_axesList)
1471         axis->setLabelsSuffix(suffix);
1472 }
1473 
1474 void AxisDock::labelsFontChanged(const QFont& font) {
1475     if (m_initializing)
1476         return;
1477 
1478     QFont labelsFont = font;
1479     labelsFont.setPixelSize( Worksheet::convertToSceneUnits(font.pointSizeF(), Worksheet::Unit::Point) );
1480     for (auto* axis : m_axesList)
1481         axis->setLabelsFont( labelsFont );
1482 }
1483 
1484 void AxisDock::labelsFontColorChanged(const QColor& color) {
1485     if (m_initializing)
1486         return;
1487 
1488     for (auto* axis : m_axesList)
1489         axis->setLabelsColor(color);
1490 }
1491 
1492 void AxisDock::labelsBackgroundTypeChanged(int index) {
1493     auto type = Axis::LabelsBackgroundType(index);
1494 
1495     bool transparent = (type == Axis::LabelsBackgroundType::Transparent);
1496     ui.lLabelsBackgroundColor->setVisible(!transparent);
1497     ui.kcbLabelsBackgroundColor->setVisible(!transparent);
1498 
1499     if (m_initializing)
1500         return;
1501 
1502     for (auto* axis : m_axesList)
1503         axis->setLabelsBackgroundType(type);
1504 }
1505 
1506 void AxisDock::labelsBackgroundColorChanged(const QColor& color) {
1507     if (m_initializing)
1508         return;
1509 
1510     for (auto* axis : m_axesList)
1511         axis->setLabelsBackgroundColor(color);
1512 }
1513 
1514 void AxisDock::labelsOpacityChanged(int value) {
1515     if (m_initializing)
1516         return;
1517 
1518     qreal opacity = (float)value/100.;
1519     for (auto* axis : m_axesList)
1520         axis->setLabelsOpacity(opacity);
1521 }
1522 
1523 // "Grid"-tab
1524 //major grid
1525 void AxisDock::majorGridStyleChanged(int index) {
1526     if (index == -1)
1527         return;
1528 
1529     auto penStyle = Qt::PenStyle(index);
1530 
1531     bool b = (penStyle != Qt::NoPen);
1532     ui.lMajorGridColor->setEnabled(b);
1533     ui.kcbMajorGridColor->setEnabled(b);
1534     ui.lMajorGridWidth->setEnabled(b);
1535     ui.sbMajorGridWidth->setEnabled(b);
1536     ui.lMajorGridOpacity->setEnabled(b);
1537     ui.sbMajorGridOpacity->setEnabled(b);
1538 
1539     if (m_initializing)
1540         return;
1541 
1542     QPen pen;
1543     for (auto* axis : m_axesList) {
1544         pen = axis->majorGridPen();
1545         pen.setStyle(penStyle);
1546         axis->setMajorGridPen(pen);
1547     }
1548 }
1549 
1550 void AxisDock::majorGridColorChanged(const QColor& color) {
1551     if (m_initializing)
1552         return;
1553 
1554     QPen pen;
1555     for (auto* axis : m_axesList) {
1556         pen = axis->majorGridPen();
1557         pen.setColor(color);
1558         axis->setMajorGridPen(pen);
1559     }
1560 
1561     m_initializing = true;
1562     GuiTools::updatePenStyles(ui.cbMajorGridStyle, color);
1563     m_initializing = false;
1564 }
1565 
1566 void AxisDock::majorGridWidthChanged(double  value) {
1567     if (m_initializing)
1568         return;
1569 
1570     QPen pen;
1571     for (auto* axis : m_axesList) {
1572         pen = axis->majorGridPen();
1573         pen.setWidthF(Worksheet::convertToSceneUnits(value, Worksheet::Unit::Point));
1574         axis->setMajorGridPen(pen);
1575     }
1576 }
1577 
1578 void AxisDock::majorGridOpacityChanged(int value) {
1579     if (m_initializing)
1580         return;
1581 
1582     qreal opacity = (double)value/100.;
1583     for (auto* axis : m_axesList)
1584         axis->setMajorGridOpacity(opacity);
1585 }
1586 
1587 //minor grid
1588 void AxisDock::minorGridStyleChanged(int index) {
1589     if (index == -1)
1590         return;
1591 
1592     auto penStyle = Qt::PenStyle(index);
1593 
1594     bool b = (penStyle != Qt::NoPen);
1595     ui.lMinorGridColor->setEnabled(b);
1596     ui.kcbMinorGridColor->setEnabled(b);
1597     ui.lMinorGridWidth->setEnabled(b);
1598     ui.sbMinorGridWidth->setEnabled(b);
1599     ui.lMinorGridOpacity->setEnabled(b);
1600     ui.sbMinorGridOpacity->setEnabled(b);
1601 
1602     if (m_initializing)
1603         return;
1604 
1605     QPen pen;
1606     for (auto* axis : m_axesList) {
1607         pen = axis->minorGridPen();
1608         pen.setStyle(penStyle);
1609         axis->setMinorGridPen(pen);
1610     }
1611 }
1612 
1613 void AxisDock::minorGridColorChanged(const QColor& color) {
1614     if (m_initializing)
1615         return;
1616 
1617     QPen pen;
1618     for (auto* axis : m_axesList) {
1619         pen = axis->minorGridPen();
1620         pen.setColor(color);
1621         axis->setMinorGridPen(pen);
1622     }
1623 
1624     m_initializing = true;
1625     GuiTools::updatePenStyles(ui.cbMinorGridStyle, color);
1626     m_initializing = false;
1627 }
1628 
1629 void AxisDock::minorGridWidthChanged(double  value) {
1630     if (m_initializing)
1631         return;
1632 
1633     QPen pen;
1634     for (auto* axis : m_axesList) {
1635         pen = axis->minorGridPen();
1636         pen.setWidthF(Worksheet::convertToSceneUnits(value, Worksheet::Unit::Point));
1637         axis->setMinorGridPen(pen);
1638     }
1639 }
1640 
1641 void AxisDock::minorGridOpacityChanged(int value) {
1642     if (m_initializing)
1643         return;
1644 
1645     qreal opacity = (double)value/100.;
1646     for (auto* axis : m_axesList)
1647         axis->setMinorGridOpacity(opacity);
1648 }
1649 
1650 //*************************************************************
1651 //************ SLOTs for changes triggered in Axis ************
1652 //*************************************************************
1653 void AxisDock::axisDescriptionChanged(const AbstractAspect* aspect) {
1654     if (m_axis != aspect)
1655         return;
1656 
1657     const Lock lock(m_initializing);
1658     if (aspect->name() != ui.leName->text())
1659         ui.leName->setText(aspect->name());
1660     else if (aspect->comment() != ui.leComment->text())
1661         ui.leComment->setText(aspect->comment());
1662 }
1663 
1664 void AxisDock::axisOrientationChanged(Axis::Orientation orientation) {
1665     m_initializing = true;
1666     ui.cbOrientation->setCurrentIndex(static_cast<int>(orientation));
1667     m_initializing = false;
1668 }
1669 
1670 void AxisDock::axisPositionChanged(Axis::Position position) {
1671     m_initializing = true;
1672 
1673     //map from the enum Qt::Orientation to the index in the combo box
1674     int index{static_cast<int>(position)};
1675     if (index > 1)
1676         ui.cbPosition->setCurrentIndex(index-2);
1677     else
1678         ui.cbPosition->setCurrentIndex(index);
1679 
1680     m_initializing = false;
1681 }
1682 
1683 void AxisDock::axisPositionChanged(double value) {
1684     m_initializing = true;
1685     SET_NUMBER_LOCALE
1686     ui.lePosition->setText(numberLocale.toString(value));
1687     m_initializing = false;
1688 }
1689 
1690 void AxisDock::axisScaleChanged(Axis::Scale scale) {
1691     m_initializing = true;
1692     ui.cbScale->setCurrentIndex(static_cast<int>(scale));
1693     m_initializing = false;
1694 }
1695 
1696 void AxisDock::axisAutoScaleChanged(bool on) {
1697     m_initializing = true;
1698     ui.chkAutoScale->setChecked(on);
1699     m_initializing = false;
1700 }
1701 
1702 void AxisDock::axisStartChanged(double value) {
1703     if (m_initializing) return;
1704     const Lock lock(m_initializing);
1705 
1706     SET_NUMBER_LOCALE
1707     ui.leStart->setText(numberLocale.toString(value));
1708     ui.dateTimeEditStart->setDateTime( QDateTime::fromMSecsSinceEpoch(value) );
1709 
1710     // determine stepsize and number of decimals
1711     double range = std::abs(m_axis->end() - m_axis->start());
1712     int decimals = nsl_math_rounded_decimals(range) + 1;
1713     DEBUG("range = " << range << ", decimals = " << decimals)
1714     ui.sbMajorTicksSpacingNumeric->setDecimals(decimals);
1715     ui.sbMajorTicksSpacingNumeric->setSingleStep(gsl_pow_int(10., -decimals));
1716     ui.sbMajorTicksSpacingNumeric->setMaximum(range);
1717 }
1718 
1719 void AxisDock::axisEndChanged(double value) {
1720     if (m_initializing) return;
1721     const Lock lock(m_initializing);
1722 
1723     SET_NUMBER_LOCALE
1724     ui.leEnd->setText(numberLocale.toString(value));
1725     ui.dateTimeEditEnd->setDateTime( QDateTime::fromMSecsSinceEpoch(value) );
1726 
1727     // determine stepsize and number of decimals
1728     double range = std::abs(m_axis->end() - m_axis->start());
1729     int decimals = nsl_math_rounded_decimals(range) + 1;
1730     DEBUG("range = " << range << ", decimals = " << decimals)
1731     ui.sbMajorTicksSpacingNumeric->setDecimals(decimals);
1732     ui.sbMajorTicksSpacingNumeric->setSingleStep(gsl_pow_int(10., -decimals));
1733     ui.sbMajorTicksSpacingNumeric->setMaximum(range);
1734 }
1735 
1736 void AxisDock::axisZeroOffsetChanged(qreal value) {
1737     if (m_initializing) return;
1738     const Lock lock(m_initializing);
1739     SET_NUMBER_LOCALE
1740     ui.leZeroOffset->setText(numberLocale.toString(value));
1741 }
1742 
1743 void AxisDock::axisScalingFactorChanged(qreal value) {
1744     if (m_initializing) return;
1745     const Lock lock(m_initializing);
1746     SET_NUMBER_LOCALE
1747     ui.leScalingFactor->setText(numberLocale.toString(value));
1748 }
1749 
1750 //line
1751 void AxisDock::axisLinePenChanged(const QPen& pen) {
1752     m_initializing = true;
1753     ui.cbLineStyle->setCurrentIndex( pen.style() );
1754     ui.kcbLineColor->setColor( pen.color() );
1755     GuiTools::updatePenStyles(ui.cbLineStyle, pen.color() );
1756     ui.sbLineWidth->setValue( Worksheet::convertFromSceneUnits(pen.widthF(), Worksheet::Unit::Point) );
1757     m_initializing = false;
1758 }
1759 
1760 void AxisDock::axisArrowTypeChanged(Axis::ArrowType type) {
1761     m_initializing = true;
1762     ui.cbArrowType->setCurrentIndex((int)type);
1763     m_initializing = false;
1764 }
1765 
1766 void AxisDock::axisLineOpacityChanged(qreal opacity) {
1767     m_initializing = true;
1768     ui.sbLineOpacity->setValue( round(opacity*100.0) );
1769     m_initializing = false;
1770 }
1771 
1772 void AxisDock::axisArrowPositionChanged(Axis::ArrowPosition position) {
1773     m_initializing = true;
1774     ui.cbArrowPosition->setCurrentIndex( (int)position );
1775     m_initializing = false;
1776 }
1777 
1778 void AxisDock::axisArrowSizeChanged(qreal size) {
1779     m_initializing = true;
1780     ui.sbArrowSize->setValue( (int)Worksheet::convertFromSceneUnits(size, Worksheet::Unit::Point) );
1781     m_initializing = false;
1782 }
1783 
1784 //major ticks
1785 void AxisDock::axisMajorTicksDirectionChanged(Axis::TicksDirection direction) {
1786     m_initializing = true;
1787     ui.cbMajorTicksDirection->setCurrentIndex(direction);
1788     m_initializing = false;
1789 }
1790 void AxisDock::axisMajorTicksTypeChanged(Axis::TicksType type) {
1791     m_initializing = true;
1792     ui.cbMajorTicksType->setCurrentIndex(static_cast<int>(type));
1793     m_initializing = false;
1794 }
1795 void AxisDock::axisMajorTicksNumberChanged(int number) {
1796     m_initializing = true;
1797     ui.sbMajorTicksNumber->setValue(number);
1798     m_initializing = false;
1799 }
1800 void AxisDock::axisMajorTicksSpacingChanged(qreal increment) {
1801     m_initializing = true;
1802     const auto* plot = dynamic_cast<const CartesianPlot*>(m_axis->parentAspect());
1803     if (plot) {
1804         bool numeric = ( (m_axis->orientation() == Axis::Orientation::Horizontal && plot->xRangeFormat() == CartesianPlot::RangeFormat::Numeric)
1805             || (m_axis->orientation() == Axis::Orientation::Vertical && plot->yRangeFormat() == CartesianPlot::RangeFormat::Numeric) );
1806 
1807         if (numeric)
1808             ui.sbMajorTicksSpacingNumeric->setValue(increment);
1809         else {
1810             dtsbMajorTicksIncrement->setValue(increment);
1811         }
1812     }
1813     m_initializing = false;
1814 }
1815 void AxisDock::axisMajorTicksPenChanged(const QPen& pen) {
1816     m_initializing = true;
1817     ui.cbMajorTicksLineStyle->setCurrentIndex(pen.style());
1818     ui.kcbMajorTicksColor->setColor(pen.color());
1819     ui.sbMajorTicksWidth->setValue( Worksheet::convertFromSceneUnits(pen.widthF(), Worksheet::Unit::Point) );
1820     m_initializing = false;
1821 }
1822 void AxisDock::axisMajorTicksLengthChanged(qreal length) {
1823     m_initializing = true;
1824     ui.sbMajorTicksLength->setValue( Worksheet::convertFromSceneUnits(length, Worksheet::Unit::Point) );
1825     m_initializing = false;
1826 }
1827 void AxisDock::axisMajorTicksOpacityChanged(qreal opacity) {
1828     m_initializing = true;
1829     ui.sbMajorTicksOpacity->setValue( round(opacity*100.0));
1830     m_initializing = false;
1831 }
1832 
1833 //minor ticks
1834 void AxisDock::axisMinorTicksDirectionChanged(Axis::TicksDirection direction) {
1835     m_initializing = true;
1836     ui.cbMinorTicksDirection->setCurrentIndex(direction);
1837     m_initializing = false;
1838 }
1839 void AxisDock::axisMinorTicksTypeChanged(Axis::TicksType type) {
1840     m_initializing = true;
1841     ui.cbMinorTicksType->setCurrentIndex(static_cast<int>(type));
1842     m_initializing = false;
1843 }
1844 void AxisDock::axisMinorTicksNumberChanged(int number) {
1845     m_initializing = true;
1846     ui.sbMinorTicksNumber->setValue(number);
1847     m_initializing = false;
1848 }
1849 void AxisDock::axisMinorTicksSpacingChanged(qreal increment) {
1850     m_initializing = true;
1851     const auto* plot = dynamic_cast<const CartesianPlot*>(m_axis->parentAspect());
1852     if (plot) {
1853         bool numeric = ( (m_axis->orientation() == Axis::Orientation::Horizontal && plot->xRangeFormat() == CartesianPlot::RangeFormat::Numeric)
1854             || (m_axis->orientation() == Axis::Orientation::Vertical && plot->yRangeFormat() == CartesianPlot::RangeFormat::Numeric) );
1855 
1856         if (numeric)
1857             ui.sbMinorTicksSpacingNumeric->setValue(increment);
1858         else {
1859             dtsbMinorTicksIncrement->setValue(increment);
1860         }
1861     }
1862     m_initializing = false;
1863 }
1864 void AxisDock::axisMinorTicksPenChanged(const QPen& pen) {
1865     m_initializing = true;
1866     ui.cbMinorTicksLineStyle->setCurrentIndex(pen.style());
1867     ui.kcbMinorTicksColor->setColor(pen.color());
1868     ui.sbMinorTicksWidth->setValue( Worksheet::convertFromSceneUnits(pen.widthF(), Worksheet::Unit::Point) );
1869     m_initializing = false;
1870 }
1871 void AxisDock::axisMinorTicksLengthChanged(qreal length) {
1872     m_initializing = true;
1873     ui.sbMinorTicksLength->setValue( Worksheet::convertFromSceneUnits(length, Worksheet::Unit::Point) );
1874     m_initializing = false;
1875 }
1876 void AxisDock::axisMinorTicksOpacityChanged(qreal opacity) {
1877     m_initializing = true;
1878     ui.sbMinorTicksOpacity->setValue(round(opacity*100.0));
1879     m_initializing = false;
1880 }
1881 
1882 //labels
1883 void AxisDock::axisLabelsFormatChanged(Axis::LabelsFormat format) {
1884     m_initializing = true;
1885     ui.cbLabelsFormat->setCurrentIndex(static_cast<int>(format));
1886     m_initializing = false;
1887 }
1888 void AxisDock::axisLabelsAutoPrecisionChanged(bool on) {
1889     m_initializing = true;
1890     ui.chkLabelsAutoPrecision->setChecked((int) on);
1891     m_initializing = false;
1892 }
1893 void AxisDock::axisLabelsPrecisionChanged(int precision) {
1894     m_initializing = true;
1895     ui.sbLabelsPrecision->setValue(precision);
1896     m_initializing = false;
1897 }
1898 void AxisDock::axisLabelsDateTimeFormatChanged(const QString& format) {
1899     m_initializing = true;
1900     ui.cbLabelsDateTimeFormat->setCurrentText(format);
1901     m_initializing = false;
1902 }
1903 void AxisDock::axisLabelsPositionChanged(Axis::LabelsPosition position) {
1904     m_initializing = true;
1905     ui.cbLabelsPosition->setCurrentIndex(static_cast<int>(position));
1906     m_initializing = false;
1907 }
1908 void AxisDock::axisLabelsOffsetChanged(double offset) {
1909     m_initializing = true;
1910     ui.sbLabelsOffset->setValue( Worksheet::convertFromSceneUnits(offset, Worksheet::Unit::Point) );
1911     m_initializing = false;
1912 }
1913 void AxisDock::axisLabelsRotationAngleChanged(qreal rotation) {
1914     m_initializing = true;
1915     ui.sbLabelsRotation->setValue(rotation);
1916     m_initializing = false;
1917 }
1918 void AxisDock::axisLabelsFontChanged(const QFont& font) {
1919     m_initializing = true;
1920     //we need to set the font size in points for KFontRequester
1921     QFont newFont(font);
1922     newFont.setPointSizeF( round(Worksheet::convertFromSceneUnits(font.pixelSize(), Worksheet::Unit::Point)) );
1923     ui.kfrLabelsFont->setFont(newFont);
1924     m_initializing = false;
1925 }
1926 void AxisDock::axisLabelsFontColorChanged(const QColor& color) {
1927     m_initializing = true;
1928     ui.kcbLabelsFontColor->setColor(color);
1929     m_initializing = false;
1930 }
1931 void AxisDock::axisLabelsBackgroundTypeChanged(Axis::LabelsBackgroundType type) {
1932     m_initializing = true;
1933     ui.cbLabelsBackgroundType->setCurrentIndex(static_cast<int>(type));
1934     m_initializing = false;
1935 }
1936 void AxisDock::axisLabelsBackgroundColorChanged(const QColor& color) {
1937     m_initializing = true;
1938     ui.kcbLabelsBackgroundColor->setColor(color);
1939     m_initializing = false;
1940 }
1941 void AxisDock::axisLabelsPrefixChanged(const QString& prefix) {
1942     m_initializing = true;
1943     ui.leLabelsPrefix->setText(prefix);
1944     m_initializing = false;
1945 }
1946 void AxisDock::axisLabelsSuffixChanged(const QString& suffix) {
1947     m_initializing = true;
1948     ui.leLabelsSuffix->setText(suffix);
1949     m_initializing = false;
1950 }
1951 void AxisDock::axisLabelsOpacityChanged(qreal opacity) {
1952     m_initializing = true;
1953     ui.sbLabelsOpacity->setValue( round(opacity*100.0) );
1954     m_initializing = false;
1955 }
1956 
1957 //grid
1958 void AxisDock::axisMajorGridPenChanged(const QPen& pen) {
1959     m_initializing = true;
1960     ui.cbMajorGridStyle->setCurrentIndex((int) pen.style());
1961     ui.kcbMajorGridColor->setColor(pen.color());
1962     GuiTools::updatePenStyles(ui.cbMajorGridStyle, pen.color());
1963     ui.sbMajorGridWidth->setValue(Worksheet::convertFromSceneUnits(pen.widthF(), Worksheet::Unit::Point));
1964     m_initializing = false;
1965 }
1966 void AxisDock::axisMajorGridOpacityChanged(qreal opacity) {
1967     m_initializing = true;
1968     ui.sbMajorGridOpacity->setValue( round(opacity*100.0) );
1969     m_initializing = false;
1970 }
1971 void AxisDock::axisMinorGridPenChanged(const QPen& pen) {
1972     m_initializing = true;
1973     ui.cbMinorGridStyle->setCurrentIndex((int) pen.style());
1974     ui.kcbMinorGridColor->setColor(pen.color());
1975     GuiTools::updatePenStyles(ui.cbMinorGridStyle, pen.color());
1976     ui.sbMinorGridWidth->setValue(Worksheet::convertFromSceneUnits(pen.widthF(), Worksheet::Unit::Point));
1977     m_initializing = false;
1978 }
1979 void AxisDock::axisMinorGridOpacityChanged(qreal opacity) {
1980     m_initializing = true;
1981     ui.sbMinorGridOpacity->setValue( round(opacity*100.0) );
1982     m_initializing = false;
1983 }
1984 
1985 void AxisDock::axisVisibilityChanged(bool on) {
1986     m_initializing = true;
1987     ui.chkVisible->setChecked(on);
1988     m_initializing = false;
1989 }
1990 
1991 //*************************************************************
1992 //************************* Settings **************************
1993 //*************************************************************
1994 void AxisDock::load() {
1995     //General
1996     ui.chkVisible->setChecked( m_axis->isVisible() );
1997     ui.cbOrientation->setCurrentIndex( (int) m_axis->orientation() );
1998 
1999     int index = (int)m_axis->position();
2000     if (index > 1)
2001         ui.cbPosition->setCurrentIndex(index-2);
2002     else
2003         ui.cbPosition->setCurrentIndex(index);
2004 
2005     SET_NUMBER_LOCALE
2006     ui.lePosition->setText( numberLocale.toString(m_axis->offset()) );
2007     ui.cbScale->setCurrentIndex( (int)m_axis->scale() );
2008     ui.chkAutoScale->setChecked( m_axis->autoScale() );
2009     ui.leStart->setText( numberLocale.toString(m_axis->start()) );
2010     ui.leEnd->setText( numberLocale.toString(m_axis->end()) );
2011 
2012     ui.sbMajorTicksSpacingNumeric->setDecimals(0);
2013     ui.sbMajorTicksSpacingNumeric->setSingleStep(m_axis->majorTicksSpacing());
2014 
2015     //depending on range format of the axis (numeric vs. datetime), show/hide the corresponding widgets
2016     const auto* plot = dynamic_cast<const CartesianPlot*>(m_axis->parentAspect());
2017     if (plot) {
2018         bool numeric = ( (m_axis->orientation() == Axis::Orientation::Horizontal && plot->xRangeFormat() == CartesianPlot::RangeFormat::Numeric)
2019             || (m_axis->orientation() == Axis::Orientation::Vertical && plot->yRangeFormat() == CartesianPlot::RangeFormat::Numeric) );
2020         //ranges
2021         ui.lStart->setVisible(numeric);
2022         ui.lEnd->setVisible(numeric);
2023         ui.leStart->setVisible(numeric);
2024         ui.leEnd->setVisible(numeric);
2025         ui.lStartDateTime->setVisible(!numeric);
2026         ui.dateTimeEditStart->setVisible(!numeric);
2027         ui.lEndDateTime->setVisible(!numeric);
2028         ui.dateTimeEditEnd->setVisible(!numeric);
2029 
2030         //tick labels format
2031         ui.lLabelsFormat->setVisible(numeric);
2032         ui.cbLabelsFormat->setVisible(numeric);
2033         ui.chkLabelsAutoPrecision->setVisible(numeric);
2034         ui.lLabelsPrecision->setVisible(numeric);
2035         ui.sbLabelsPrecision->setVisible(numeric);
2036         ui.cbLabelsDateTimeFormat->setVisible(numeric);
2037         ui.lLabelsDateTimeFormat->setVisible(!numeric);
2038         ui.cbLabelsDateTimeFormat->setVisible(!numeric);
2039 
2040         if (!numeric) {
2041             if (m_axis->orientation() == Axis::Orientation::Horizontal) {
2042                 ui.dateTimeEditStart->setDisplayFormat(plot->xRangeDateTimeFormat());
2043                 ui.dateTimeEditEnd->setDisplayFormat(plot->xRangeDateTimeFormat());
2044             } else {
2045                 ui.dateTimeEditStart->setDisplayFormat(plot->yRangeDateTimeFormat());
2046                 ui.dateTimeEditEnd->setDisplayFormat(plot->yRangeDateTimeFormat());
2047             }
2048             ui.dateTimeEditStart->setDateTime(QDateTime::fromMSecsSinceEpoch(m_axis->start()));
2049             ui.dateTimeEditEnd->setDateTime(QDateTime::fromMSecsSinceEpoch(m_axis->end()));
2050 
2051         }
2052     }
2053 
2054     ui.leZeroOffset->setText( numberLocale.toString(m_axis->zeroOffset()) );
2055     ui.leScalingFactor->setText( numberLocale.toString(m_axis->scalingFactor()) );
2056 
2057     //Line
2058     ui.cbLineStyle->setCurrentIndex( (int) m_axis->linePen().style() );
2059     ui.kcbLineColor->setColor( m_axis->linePen().color() );
2060     ui.sbLineWidth->setValue( Worksheet::convertFromSceneUnits(m_axis->linePen().widthF(), Worksheet::Unit::Point) );
2061     ui.sbLineOpacity->setValue( round(m_axis->lineOpacity()*100.0) );
2062     ui.cbArrowType->setCurrentIndex( (int)m_axis->arrowType() );
2063     ui.cbArrowPosition->setCurrentIndex( (int)m_axis->arrowPosition() );
2064     ui.sbArrowSize->setValue( (int)Worksheet::convertFromSceneUnits(m_axis->arrowSize(), Worksheet::Unit::Point) );
2065 
2066     //Major ticks
2067     ui.cbMajorTicksDirection->setCurrentIndex( (int) m_axis->majorTicksDirection() );
2068     ui.cbMajorTicksType->setCurrentIndex( (int) m_axis->majorTicksType() );
2069     ui.sbMajorTicksNumber->setValue( m_axis->majorTicksNumber() );
2070     ui.cbMajorTicksLineStyle->setCurrentIndex( (int) m_axis->majorTicksPen().style() );
2071     ui.kcbMajorTicksColor->setColor( m_axis->majorTicksPen().color() );
2072     ui.sbMajorTicksWidth->setValue( Worksheet::convertFromSceneUnits( m_axis->majorTicksPen().widthF(), Worksheet::Unit::Point) );
2073     ui.sbMajorTicksLength->setValue( Worksheet::convertFromSceneUnits( m_axis->majorTicksLength(), Worksheet::Unit::Point) );
2074     ui.sbMajorTicksOpacity->setValue( round(m_axis->majorTicksOpacity()*100.0) );
2075 
2076     //Minor ticks
2077     ui.cbMinorTicksDirection->setCurrentIndex( (int) m_axis->minorTicksDirection() );
2078     ui.cbMinorTicksType->setCurrentIndex( (int) m_axis->minorTicksType() );
2079     ui.sbMinorTicksNumber->setValue( m_axis->minorTicksNumber() );
2080     ui.cbMinorTicksLineStyle->setCurrentIndex( (int) m_axis->minorTicksPen().style() );
2081     ui.kcbMinorTicksColor->setColor( m_axis->minorTicksPen().color() );
2082     ui.sbMinorTicksWidth->setValue( Worksheet::convertFromSceneUnits(m_axis->minorTicksPen().widthF(), Worksheet::Unit::Point) );
2083     ui.sbMinorTicksLength->setValue( Worksheet::convertFromSceneUnits(m_axis->minorTicksLength(), Worksheet::Unit::Point) );
2084     ui.sbMinorTicksOpacity->setValue( round(m_axis->minorTicksOpacity()*100.0) );
2085 
2086     //Extra ticks
2087     //TODO
2088 
2089     // Tick label
2090     ui.cbLabelsPosition->setCurrentIndex( (int) m_axis->labelsPosition() );
2091     ui.sbLabelsOffset->setValue( Worksheet::convertFromSceneUnits(m_axis->labelsOffset(), Worksheet::Unit::Point) );
2092     ui.sbLabelsRotation->setValue( m_axis->labelsRotationAngle() );
2093     ui.cbLabelsFormat->setCurrentIndex( (int) m_axis->labelsFormat() );
2094     ui.chkLabelsAutoPrecision->setChecked( (int) m_axis->labelsAutoPrecision() );
2095     ui.sbLabelsPrecision->setValue( (int)m_axis->labelsPrecision() );
2096     ui.cbLabelsDateTimeFormat->setCurrentText(m_axis->labelsDateTimeFormat());
2097     //we need to set the font size in points for KFontRequester
2098     QFont font = m_axis->labelsFont();
2099     font.setPointSizeF( round(Worksheet::convertFromSceneUnits(font.pixelSize(), Worksheet::Unit::Point)) );
2100     ui.kfrLabelsFont->setFont( font );
2101     ui.kcbLabelsFontColor->setColor( m_axis->labelsColor() );
2102     ui.cbLabelsBackgroundType->setCurrentIndex( (int) m_axis->labelsBackgroundType() );
2103     ui.kcbLabelsBackgroundColor->setColor( m_axis->labelsBackgroundColor() );
2104     ui.leLabelsPrefix->setText( m_axis->labelsPrefix() );
2105     ui.leLabelsSuffix->setText( m_axis->labelsSuffix() );
2106     ui.sbLabelsOpacity->setValue( round(m_axis->labelsOpacity()*100.0) );
2107 
2108     //Grid
2109     ui.cbMajorGridStyle->setCurrentIndex( (int) m_axis->majorGridPen().style() );
2110     ui.kcbMajorGridColor->setColor( m_axis->majorGridPen().color() );
2111     ui.sbMajorGridWidth->setValue( Worksheet::convertFromSceneUnits(m_axis->majorGridPen().widthF(), Worksheet::Unit::Point) );
2112     ui.sbMajorGridOpacity->setValue( round(m_axis->majorGridOpacity()*100.0) );
2113 
2114     ui.cbMinorGridStyle->setCurrentIndex( (int) m_axis->minorGridPen().style() );
2115     ui.kcbMinorGridColor->setColor( m_axis->minorGridPen().color() );
2116     ui.sbMinorGridWidth->setValue( Worksheet::convertFromSceneUnits(m_axis->minorGridPen().widthF(), Worksheet::Unit::Point) );
2117     ui.sbMinorGridOpacity->setValue( round(m_axis->minorGridOpacity()*100.0) );
2118 
2119     GuiTools::updatePenStyles(ui.cbLineStyle, ui.kcbLineColor->color());
2120     this->majorTicksTypeChanged(ui.cbMajorTicksType->currentIndex());
2121     GuiTools::updatePenStyles(ui.cbMajorTicksLineStyle, ui.kcbMajorTicksColor->color());
2122     this->minorTicksTypeChanged(ui.cbMinorTicksType->currentIndex());
2123     GuiTools::updatePenStyles(ui.cbMinorTicksLineStyle, ui.kcbMinorTicksColor->color());
2124     GuiTools::updatePenStyles(ui.cbMajorGridStyle, ui.kcbMajorGridColor->color());
2125     GuiTools::updatePenStyles(ui.cbMinorGridStyle, ui.kcbMinorGridColor->color());
2126 }
2127 
2128 void AxisDock::loadConfigFromTemplate(KConfig& config) {
2129     //extract the name of the template from the file name
2130     QString name;
2131     int index = config.name().lastIndexOf(QLatin1String("/"));
2132     if (index != -1)
2133         name = config.name().right(config.name().size() - index - 1);
2134     else
2135         name = config.name();
2136 
2137     int size = m_axesList.size();
2138     if (size > 1)
2139         m_axis->beginMacro(i18n("%1 axes: template \"%2\" loaded", size, name));
2140     else
2141         m_axis->beginMacro(i18n("%1: template \"%2\" loaded", m_axis->name(), name));
2142 
2143     this->loadConfig(config);
2144 
2145     m_axis->endMacro();
2146 }
2147 
2148 void AxisDock::loadConfig(KConfig& config) {
2149     KConfigGroup group = config.group( "Axis" );
2150 
2151     bool numeric = false;
2152     const auto* plot = dynamic_cast<const CartesianPlot*>(m_axis->parentAspect());
2153     if (plot) {
2154         numeric = ( (m_axis->orientation() == Axis::Orientation::Horizontal && plot->xRangeFormat() == CartesianPlot::RangeFormat::Numeric)
2155             || (m_axis->orientation() == Axis::Orientation::Vertical && plot->yRangeFormat() == CartesianPlot::RangeFormat::Numeric) );
2156     }
2157 
2158     //General
2159     ui.cbOrientation->setCurrentIndex( group.readEntry("Orientation", (int) m_axis->orientation()) );
2160 
2161     int index = group.readEntry("Position", (int) m_axis->position());
2162     if (index > 1)
2163         ui.cbPosition->setCurrentIndex(index-2);
2164     else
2165         ui.cbPosition->setCurrentIndex(index);
2166 
2167     SET_NUMBER_LOCALE
2168     ui.lePosition->setText( numberLocale.toString(group.readEntry("PositionOffset", m_axis->offset())) );
2169     ui.cbScale->setCurrentIndex( group.readEntry("Scale", (int) m_axis->scale()) );
2170     ui.chkAutoScale->setChecked( group.readEntry("AutoScale", m_axis->autoScale()) );
2171     ui.leStart->setText( numberLocale.toString(group.readEntry("Start", m_axis->start())) );
2172     ui.leEnd->setText( numberLocale.toString(group.readEntry("End", m_axis->end())) );
2173     ui.leZeroOffset->setText( numberLocale.toString(group.readEntry("ZeroOffset", m_axis->zeroOffset())) );
2174     ui.leScalingFactor->setText( numberLocale.toString(group.readEntry("ScalingFactor", m_axis->scalingFactor())) );
2175 
2176     //Title
2177     KConfigGroup axisLabelGroup = config.group("AxisLabel");
2178     labelWidget->loadConfig(axisLabelGroup);
2179 
2180     //Line
2181     ui.cbLineStyle->setCurrentIndex( group.readEntry("LineStyle", (int) m_axis->linePen().style()) );
2182     ui.kcbLineColor->setColor( group.readEntry("LineColor", m_axis->linePen().color()) );
2183     ui.sbLineWidth->setValue( Worksheet::convertFromSceneUnits(group.readEntry("LineWidth", m_axis->linePen().widthF()), Worksheet::Unit::Point) );
2184     ui.sbLineOpacity->setValue( round(group.readEntry("LineOpacity", m_axis->lineOpacity())*100.0) );
2185     ui.cbArrowType->setCurrentIndex( group.readEntry("ArrowType", (int) m_axis->arrowType()) );
2186     ui.cbArrowPosition->setCurrentIndex( group.readEntry("ArrowPosition", (int) m_axis->arrowPosition()) );
2187     ui.sbArrowSize->setValue( Worksheet::convertFromSceneUnits(group.readEntry("ArrowSize", m_axis->arrowSize()), Worksheet::Unit::Point) );
2188 
2189     //Major ticks
2190     ui.cbMajorTicksDirection->setCurrentIndex( group.readEntry("MajorTicksDirection", (int) m_axis->majorTicksDirection()) );
2191     ui.cbMajorTicksType->setCurrentIndex( group.readEntry("MajorTicksType", (int) m_axis->majorTicksType()) );
2192     ui.sbMajorTicksNumber->setValue( group.readEntry("MajorTicksNumber", m_axis->majorTicksNumber()) );
2193     if (numeric)
2194         ui.sbMajorTicksSpacingNumeric->setValue(group.readEntry("MajorTicksIncrement", m_axis->majorTicksSpacing()));
2195     else
2196         dtsbMajorTicksIncrement->setValue(group.readEntry("MajorTicksIncrement", m_axis->majorTicksSpacing()));
2197     ui.cbMajorTicksLineStyle->setCurrentIndex( group.readEntry("MajorTicksLineStyle", (int) m_axis->majorTicksPen().style()) );
2198     ui.kcbMajorTicksColor->setColor( group.readEntry("MajorTicksColor", m_axis->majorTicksPen().color()) );
2199     ui.sbMajorTicksWidth->setValue( Worksheet::convertFromSceneUnits(group.readEntry("MajorTicksWidth", m_axis->majorTicksPen().widthF()), Worksheet::Unit::Point) );
2200     ui.sbMajorTicksLength->setValue( Worksheet::convertFromSceneUnits(group.readEntry("MajorTicksLength", m_axis->majorTicksLength()), Worksheet::Unit::Point) );
2201     ui.sbMajorTicksOpacity->setValue( round(group.readEntry("MajorTicksOpacity", m_axis->majorTicksOpacity())*100.0) );
2202 
2203     //Minor ticks
2204     ui.cbMinorTicksDirection->setCurrentIndex( group.readEntry("MinorTicksDirection", (int) m_axis->minorTicksDirection()) );
2205     ui.cbMinorTicksType->setCurrentIndex( group.readEntry("MinorTicksType", (int) m_axis->minorTicksType()) );
2206     ui.sbMinorTicksNumber->setValue( group.readEntry("MinorTicksNumber", m_axis->minorTicksNumber()) );
2207     if (numeric)
2208         ui.sbMinorTicksSpacingNumeric->setValue(group.readEntry("MinorTicksIncrement", m_axis->minorTicksSpacing()));
2209     else
2210         dtsbMinorTicksIncrement->setValue(group.readEntry("MinorTicksIncrement", m_axis->minorTicksSpacing()));
2211     ui.cbMinorTicksLineStyle->setCurrentIndex( group.readEntry("MinorTicksLineStyle", (int) m_axis->minorTicksPen().style()) );
2212     ui.kcbMinorTicksColor->setColor( group.readEntry("MinorTicksColor", m_axis->minorTicksPen().color()) );
2213     ui.sbMinorTicksWidth->setValue( Worksheet::convertFromSceneUnits(group.readEntry("MinorTicksWidth", m_axis->minorTicksPen().widthF()), Worksheet::Unit::Point) );
2214     ui.sbMinorTicksLength->setValue( Worksheet::convertFromSceneUnits(group.readEntry("MinorTicksLength", m_axis->minorTicksLength()), Worksheet::Unit::Point) );
2215     ui.sbMinorTicksOpacity->setValue( round(group.readEntry("MinorTicksOpacity", m_axis->minorTicksOpacity())*100.0) );
2216 
2217     //Extra ticks
2218     //TODO
2219 
2220     // Tick label
2221     ui.cbLabelsFormat->setCurrentIndex( group.readEntry("LabelsFormat", (int) m_axis->labelsFormat()) );
2222     ui.chkLabelsAutoPrecision->setChecked( group.readEntry("LabelsAutoPrecision", (int) m_axis->labelsAutoPrecision()) );
2223     ui.sbLabelsPrecision->setValue( group.readEntry("LabelsPrecision", (int)m_axis->labelsPrecision()) );
2224     ui.cbLabelsDateTimeFormat->setCurrentText( group.readEntry("LabelsDateTimeFormat", "yyyy-MM-dd hh:mm:ss") );
2225     ui.cbLabelsPosition->setCurrentIndex( group.readEntry("LabelsPosition", (int) m_axis->labelsPosition()) );
2226     ui.sbLabelsOffset->setValue( Worksheet::convertFromSceneUnits(group.readEntry("LabelsOffset", m_axis->labelsOffset()), Worksheet::Unit::Point) );
2227     ui.sbLabelsRotation->setValue( group.readEntry("LabelsRotation", m_axis->labelsRotationAngle()) );
2228     //we need to set the font size in points for KFontRequester
2229     QFont font = m_axis->labelsFont();
2230     font.setPointSizeF( round(Worksheet::convertFromSceneUnits(font.pixelSize(), Worksheet::Unit::Point)) );
2231     ui.kfrLabelsFont->setFont( group.readEntry("LabelsFont", font) );
2232     ui.kcbLabelsFontColor->setColor( group.readEntry("LabelsFontColor", m_axis->labelsColor()) );
2233     ui.cbLabelsBackgroundType->setCurrentIndex( group.readEntry("LabelsBackgroundType", (int) m_axis->labelsBackgroundType()) );
2234     ui.kcbLabelsBackgroundColor->setColor( group.readEntry("LabelsBackgroundColor", m_axis->labelsBackgroundColor()) );
2235     ui.leLabelsPrefix->setText( group.readEntry("LabelsPrefix", m_axis->labelsPrefix()) );
2236     ui.leLabelsSuffix->setText( group.readEntry("LabelsSuffix", m_axis->labelsSuffix()) );
2237     ui.sbLabelsOpacity->setValue( round(group.readEntry("LabelsOpacity", m_axis->labelsOpacity())*100.0) );
2238 
2239     //Grid
2240     ui.cbMajorGridStyle->setCurrentIndex( group.readEntry("MajorGridStyle", (int) m_axis->majorGridPen().style()) );
2241     ui.kcbMajorGridColor->setColor( group.readEntry("MajorGridColor", m_axis->majorGridPen().color()) );
2242     ui.sbMajorGridWidth->setValue( Worksheet::convertFromSceneUnits(group.readEntry("MajorGridWidth", m_axis->majorGridPen().widthF()), Worksheet::Unit::Point) );
2243     ui.sbMajorGridOpacity->setValue( round(group.readEntry("MajorGridOpacity", m_axis->majorGridOpacity())*100.0) );
2244 
2245     ui.cbMinorGridStyle->setCurrentIndex( group.readEntry("MinorGridStyle", (int) m_axis->minorGridPen().style()) );
2246     ui.kcbMinorGridColor->setColor( group.readEntry("MinorGridColor", m_axis->minorGridPen().color()) );
2247     ui.sbMinorGridWidth->setValue( Worksheet::convertFromSceneUnits(group.readEntry("MinorGridWidth", m_axis->minorGridPen().widthF()), Worksheet::Unit::Point) );
2248     ui.sbMinorGridOpacity->setValue( round(group.readEntry("MinorGridOpacity", m_axis->minorGridOpacity())*100.0) );
2249 
2250     m_initializing = true;
2251     GuiTools::updatePenStyles(ui.cbLineStyle, ui.kcbLineColor->color());
2252     this->majorTicksTypeChanged(ui.cbMajorTicksType->currentIndex());
2253     GuiTools::updatePenStyles(ui.cbMajorTicksLineStyle, ui.kcbMajorTicksColor->color());
2254     this->minorTicksTypeChanged(ui.cbMinorTicksType->currentIndex());
2255     GuiTools::updatePenStyles(ui.cbMinorTicksLineStyle, ui.kcbMinorTicksColor->color());
2256     GuiTools::updatePenStyles(ui.cbMajorGridStyle, ui.kcbMajorGridColor->color());
2257     GuiTools::updatePenStyles(ui.cbMinorGridStyle, ui.kcbMinorGridColor->color());
2258     m_initializing = false;
2259 }
2260 
2261 void AxisDock::saveConfigAsTemplate(KConfig& config) {
2262     KConfigGroup group = config.group( "Axis" );
2263 
2264     bool numeric = false;
2265     const auto* plot = dynamic_cast<const CartesianPlot*>(m_axis->parentAspect());
2266     if (plot) {
2267         numeric = ( (m_axis->orientation() == Axis::Orientation::Horizontal && plot->xRangeFormat() == CartesianPlot::RangeFormat::Numeric)
2268             || (m_axis->orientation() == Axis::Orientation::Vertical && plot->yRangeFormat() == CartesianPlot::RangeFormat::Numeric) );
2269     }
2270 
2271     //General
2272     group.writeEntry("Orientation", ui.cbOrientation->currentIndex());
2273 
2274     if (ui.cbPosition->currentIndex() == 2) {
2275         group.writeEntry("Position", static_cast<int>(Axis::Position::Centered));
2276     } else if (ui.cbPosition->currentIndex() == 3) {
2277         group.writeEntry("Position", static_cast<int>(Axis::Position::Custom));
2278     } else {
2279         if (ui.cbOrientation->currentIndex() == static_cast<int>(Axis::Orientation::Horizontal))
2280             group.writeEntry("Position", ui.cbPosition->currentIndex());
2281         else
2282             group.writeEntry("Position", ui.cbPosition->currentIndex() + 2);
2283     }
2284 
2285     SET_NUMBER_LOCALE
2286     group.writeEntry("PositionOffset", numberLocale.toDouble(ui.lePosition->text()));
2287     group.writeEntry("Scale", ui.cbScale->currentIndex());
2288     group.writeEntry("Start", numberLocale.toDouble(ui.leStart->text()));
2289     group.writeEntry("End", numberLocale.toDouble(ui.leEnd->text()));
2290     group.writeEntry("ZeroOffset", numberLocale.toDouble(ui.leZeroOffset->text()));
2291     group.writeEntry("ScalingFactor", numberLocale.toDouble(ui.leScalingFactor->text()));
2292 
2293     //Title
2294     KConfigGroup axisLabelGroup = config.group("AxisLabel");
2295     labelWidget->saveConfig(axisLabelGroup);
2296 
2297     //Line
2298     group.writeEntry("LineStyle", ui.cbLineStyle->currentIndex());
2299     group.writeEntry("LineColor", ui.kcbLineColor->color());
2300     group.writeEntry("LineWidth", Worksheet::convertToSceneUnits(ui.sbLineWidth->value(), Worksheet::Unit::Point));
2301     group.writeEntry("LineOpacity", ui.sbLineOpacity->value()/100.);
2302 
2303     //Major ticks
2304     group.writeEntry("MajorTicksDirection", ui.cbMajorTicksDirection->currentIndex());
2305     group.writeEntry("MajorTicksType", ui.cbMajorTicksType->currentIndex());
2306     group.writeEntry("MajorTicksNumber", ui.sbMajorTicksNumber->value());
2307     if (numeric)
2308         group.writeEntry("MajorTicksIncrement", QString::number(ui.sbMajorTicksSpacingNumeric->value()));
2309     else
2310         group.writeEntry("MajorTicksIncrement", QString::number(dtsbMajorTicksIncrement->value()));
2311     group.writeEntry("MajorTicksLineStyle", ui.cbMajorTicksLineStyle->currentIndex());
2312     group.writeEntry("MajorTicksColor", ui.kcbMajorTicksColor->color());
2313     group.writeEntry("MajorTicksWidth", Worksheet::convertToSceneUnits(ui.sbMajorTicksWidth->value(), Worksheet::Unit::Point));
2314     group.writeEntry("MajorTicksLength", Worksheet::convertToSceneUnits(ui.sbMajorTicksLength->value(), Worksheet::Unit::Point));
2315     group.writeEntry("MajorTicksOpacity", ui.sbMajorTicksOpacity->value()/100.);
2316 
2317     //Minor ticks
2318     group.writeEntry("MinorTicksDirection", ui.cbMinorTicksDirection->currentIndex());
2319     group.writeEntry("MinorTicksType", ui.cbMinorTicksType->currentIndex());
2320     group.writeEntry("MinorTicksNumber", ui.sbMinorTicksNumber->value());
2321     if (numeric)
2322         group.writeEntry("MinorTicksIncrement", QString::number(ui.sbMinorTicksSpacingNumeric->value()));
2323     else
2324         group.writeEntry("MinorTicksIncrement", QString::number(dtsbMinorTicksIncrement->value()));
2325     group.writeEntry("MinorTicksLineStyle", ui.cbMinorTicksLineStyle->currentIndex());
2326     group.writeEntry("MinorTicksColor", ui.kcbMinorTicksColor->color());
2327     group.writeEntry("MinorTicksWidth", Worksheet::convertFromSceneUnits(ui.sbMinorTicksWidth->value(), Worksheet::Unit::Point));
2328     group.writeEntry("MinorTicksLength", Worksheet::convertFromSceneUnits(ui.sbMinorTicksLength->value(), Worksheet::Unit::Point));
2329     group.writeEntry("MinorTicksOpacity", ui.sbMinorTicksOpacity->value()/100.);
2330 
2331     //Extra ticks
2332     // TODO
2333 
2334     // Tick label
2335     group.writeEntry("LabelsFormat", ui.cbLabelsFormat->currentIndex());
2336     group.writeEntry("LabelsAutoPrecision", ui.chkLabelsAutoPrecision->isChecked());
2337     group.writeEntry("LabelsPrecision", ui.sbLabelsPrecision->value());
2338     group.writeEntry("LabelsPosition", ui.cbLabelsPosition->currentIndex());
2339     group.writeEntry("LabelsOffset", Worksheet::convertToSceneUnits(ui.sbLabelsOffset->value(), Worksheet::Unit::Point));
2340     group.writeEntry("LabelsRotation", ui.sbLabelsRotation->value());
2341     group.writeEntry("LabelsFont", ui.kfrLabelsFont->font());
2342     group.writeEntry("LabelsFontColor", ui.kcbLabelsFontColor->color());
2343     group.writeEntry("LabelsBackgroundType", ui.cbLabelsBackgroundType->currentIndex());
2344     group.writeEntry("LabelsBackgroundColor", ui.kcbLabelsBackgroundColor->color());
2345     group.writeEntry("LabelsPrefix", ui.leLabelsPrefix->text());
2346     group.writeEntry("LabelsSuffix", ui.leLabelsSuffix->text());
2347     group.writeEntry("LabelsOpacity", ui.sbLabelsOpacity->value()/100.);
2348 
2349     //Grid
2350     group.writeEntry("MajorGridStyle", ui.cbMajorGridStyle->currentIndex());
2351     group.writeEntry("MajorGridColor", ui.kcbMajorGridColor->color());
2352     group.writeEntry("MajorGridWidth", Worksheet::convertToSceneUnits(ui.sbMajorGridWidth->value(), Worksheet::Unit::Point));
2353     group.writeEntry("MajorGridOpacity", ui.sbMajorGridOpacity->value()/100.);
2354 
2355     group.writeEntry("MinorGridStyle", ui.cbMinorGridStyle->currentIndex());
2356     group.writeEntry("MinorGridColor", ui.kcbMinorGridColor->color());
2357     group.writeEntry("MinorGridWidth", Worksheet::convertToSceneUnits(ui.sbMinorGridWidth->value(), Worksheet::Unit::Point));
2358     group.writeEntry("MinorGridOpacity", ui.sbMinorGridOpacity->value()/100.);
2359     config.sync();
2360 }