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