File indexing completed on 2025-03-09 03:34:35

0001 /*
0002     File                 : LineWidget.cpp
0003     Project              : LabPlot
0004     Description          : line settings widget
0005     --------------------------------------------------------------------
0006     SPDX-FileCopyrightText: 2022-2024 Alexander Semke <alexander.semke@web.de>
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 
0010 #include "LineWidget.h"
0011 #include "kdefrontend/GuiTools.h"
0012 #include "kdefrontend/dockwidgets/BaseDock.h"
0013 
0014 #include <KConfigGroup>
0015 #include <QPainter>
0016 #include <QTimer>
0017 
0018 /*!
0019     \class LineWidget
0020     \brief Widget for editing the properties of a Line object, mostly used in an appropriate dock widget.
0021 
0022     \ingroup kdefrontend
0023  */
0024 LineWidget::LineWidget(QWidget* parent)
0025     : QWidget(parent) {
0026     ui.setupUi(this);
0027 
0028     ui.sbWidth->setMinimum(0);
0029 
0030     connect(ui.cbType, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &LineWidget::typeChanged);
0031     connect(ui.cbStyle, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &LineWidget::styleChanged);
0032     connect(ui.kcbColor, &KColorButton::changed, this, &LineWidget::colorChangedSlot);
0033     connect(ui.sbWidth, QOverload<double>::of(&NumberSpinBox::valueChanged), this, &LineWidget::widthChanged);
0034     connect(ui.sbOpacity, QOverload<int>::of(&QSpinBox::valueChanged), this, &LineWidget::opacityChanged);
0035 }
0036 
0037 void LineWidget::setLines(const QList<Line*>& lines) {
0038     CONDITIONAL_LOCK_RETURN;
0039     m_lines = lines;
0040     m_line = m_lines.first();
0041     m_prefix = m_line->prefix();
0042 
0043     if (m_line->histogramLineTypeAvailable()) {
0044         ui.lType->show();
0045         ui.cbType->show();
0046 
0047         if (ui.cbType->count() == 0) {
0048             ui.cbType->addItem(i18n("None"));
0049             ui.cbType->addItem(i18n("Bars"));
0050             ui.cbType->addItem(i18n("Envelope"));
0051             ui.cbType->addItem(i18n("Drop Lines"));
0052             ui.cbType->addItem(i18n("Half-Bars"));
0053         }
0054     } else if (m_prefix == QLatin1String("DropLine")) {
0055         ui.lType->show();
0056         ui.cbType->show();
0057 
0058         if (ui.cbType->count() == 0) {
0059             ui.cbType->addItem(i18n("No Drop Lines"));
0060             ui.cbType->addItem(i18n("Drop Lines, X"));
0061             ui.cbType->addItem(i18n("Drop Lines, Y"));
0062             ui.cbType->addItem(i18n("Drop Lines, XY"));
0063             ui.cbType->addItem(i18n("Drop Lines, X, Zero Baseline"));
0064             ui.cbType->addItem(i18n("Drop Lines, X, Min Baseline"));
0065             ui.cbType->addItem(i18n("Drop Lines, X, Max Baseline"));
0066         }
0067     } else {
0068         ui.lType->hide();
0069         ui.cbType->hide();
0070     }
0071 
0072     load();
0073 
0074     connect(m_line, &Line::histogramLineTypeChanged, this, &LineWidget::histogramLineTypeChanged);
0075     connect(m_line, &Line::dropLineTypeChanged, this, &LineWidget::dropLineTypeChanged);
0076     connect(m_line, &Line::styleChanged, this, &LineWidget::lineStyleChanged);
0077     connect(m_line, &Line::colorChanged, this, &LineWidget::lineColorChanged);
0078     connect(m_line, &Line::widthChanged, this, &LineWidget::lineWidthChanged);
0079     connect(m_line, &Line::opacityChanged, this, &LineWidget::lineOpacityChanged);
0080 }
0081 
0082 void LineWidget::showEvent(QShowEvent* event) {
0083     QWidget::showEvent(event);
0084     adjustLayout();
0085 }
0086 
0087 /*!
0088  * this functions adjusts the width of the first column in the layout of LineWidget
0089  * to the width of the first column in the layout of the parent widget
0090  * which LineWidget is being embedded into.
0091  */
0092 void LineWidget::adjustLayout() {
0093     auto* parentGridLayout = dynamic_cast<QGridLayout*>(parentWidget()->layout());
0094     if (!parentGridLayout)
0095         return;
0096 
0097     auto* parentWidget = parentGridLayout->itemAtPosition(0, 0)->widget();
0098     if (!parentWidget)
0099         return;
0100 
0101     auto* gridLayout = static_cast<QGridLayout*>(layout());
0102     auto* widget = gridLayout->itemAtPosition(2, 0)->widget(); // use the third line, the first two are optional and not always visible
0103 
0104     if (parentWidget->width() >= widget->width()) {
0105         gridLayout->activate();
0106         widget->setMinimumWidth(parentWidget->width());
0107         updateGeometry();
0108     } else {
0109         parentGridLayout->activate();
0110         parentWidget->setMinimumWidth(widget->width());
0111         this->parentWidget()->updateGeometry();
0112     }
0113 }
0114 
0115 void LineWidget::setEnabled(bool enabled) {
0116     ui.cbStyle->setEnabled(enabled);
0117     ui.kcbColor->setEnabled(enabled);
0118     ui.sbWidth->setEnabled(enabled);
0119     ui.sbOpacity->setEnabled(enabled);
0120 }
0121 
0122 void LineWidget::updateLocale() {
0123     const auto numberLocale = QLocale();
0124     ui.sbWidth->setLocale(numberLocale);
0125 }
0126 
0127 //*************************************************************
0128 //******** SLOTs for changes triggered in LineWidget **********
0129 //*************************************************************
0130 void LineWidget::typeChanged(int index) {
0131     bool enabled = true;
0132     if (m_line->histogramLineTypeAvailable()) {
0133         const auto type = Histogram::LineType(index);
0134         enabled = (type != Histogram::NoLine);
0135 
0136         if (!m_initializing) {
0137             for (auto* line : m_lines)
0138                 line->setHistogramLineType(type);
0139         }
0140     } else if (m_prefix == QLatin1String("DropLine")) {
0141         auto type = static_cast<XYCurve::DropLineType>(index);
0142         enabled = (type != XYCurve::DropLineType::NoDropLine);
0143 
0144         if (!m_initializing) {
0145             for (auto* line : m_lines)
0146                 line->setDropLineType(type);
0147         }
0148     }
0149 
0150     ui.cbStyle->setEnabled(enabled);
0151     ui.kcbColor->setEnabled(enabled);
0152     ui.sbWidth->setEnabled(enabled);
0153     ui.sbOpacity->setEnabled(enabled);
0154 
0155     // TODO
0156     // const bool fillingEnabled = (lineType == Histogram::LineType::Bars || lineType == Histogram::LineType::Envelope);
0157     // backgroundWidget->setEnabled(fillingEnabled);
0158 }
0159 
0160 void LineWidget::styleChanged(int index) {
0161     CONDITIONAL_LOCK_RETURN;
0162     auto style = static_cast<Qt::PenStyle>(index);
0163     for (auto* line : m_lines)
0164         line->setStyle(style);
0165 }
0166 
0167 void LineWidget::colorChangedSlot(const QColor& color) {
0168     CONDITIONAL_LOCK_RETURN;
0169     for (auto* line : m_lines)
0170         line->setColor(color);
0171 
0172     GuiTools::updatePenStyles(ui.cbStyle, color);
0173 }
0174 
0175 void LineWidget::widthChanged(double value) {
0176     CONDITIONAL_RETURN_NO_LOCK;
0177 
0178     const double width = Worksheet::convertToSceneUnits(value, Worksheet::Unit::Point);
0179     for (auto* line : m_lines)
0180         line->setWidth(width);
0181 }
0182 
0183 void LineWidget::opacityChanged(int value) {
0184     CONDITIONAL_LOCK_RETURN;
0185     double opacity = static_cast<double>(value) / 100.;
0186     for (auto* line : m_lines)
0187         line->setOpacity(opacity);
0188 }
0189 
0190 //*************************************************************
0191 //*********** SLOTs for changes triggered in Line *************
0192 //*************************************************************
0193 void LineWidget::histogramLineTypeChanged(Histogram::LineType type) {
0194     CONDITIONAL_LOCK_RETURN;
0195     ui.cbType->setCurrentIndex(static_cast<int>(type));
0196 }
0197 
0198 void LineWidget::dropLineTypeChanged(XYCurve::DropLineType type) {
0199     CONDITIONAL_LOCK_RETURN;
0200     ui.cbType->setCurrentIndex(static_cast<int>(type));
0201 }
0202 
0203 void LineWidget::lineStyleChanged(Qt::PenStyle style) {
0204     CONDITIONAL_LOCK_RETURN;
0205     ui.cbStyle->setCurrentIndex(static_cast<int>(style));
0206 }
0207 
0208 void LineWidget::lineColorChanged(const QColor& color) {
0209     Q_EMIT colorChanged(color);
0210 
0211     CONDITIONAL_LOCK_RETURN;
0212     ui.kcbColor->setColor(color);
0213 }
0214 
0215 void LineWidget::lineWidthChanged(double width) {
0216     CONDITIONAL_LOCK_RETURN;
0217     ui.sbWidth->setValue(Worksheet::convertFromSceneUnits(width, Worksheet::Unit::Point));
0218 }
0219 
0220 void LineWidget::lineOpacityChanged(double value) {
0221     CONDITIONAL_LOCK_RETURN;
0222     ui.sbOpacity->setValue(round(value * 100));
0223 }
0224 
0225 //**********************************************************
0226 //******************** SETTINGS ****************************
0227 //**********************************************************
0228 void LineWidget::load() {
0229     if (m_line->histogramLineTypeAvailable())
0230         ui.cbType->setCurrentIndex(static_cast<int>(m_line->histogramLineType()));
0231     else if (m_prefix == QLatin1String("DropLine"))
0232         ui.cbType->setCurrentIndex(static_cast<int>(m_line->dropLineType()));
0233 
0234     setColor(m_line->color());
0235     ui.sbWidth->setValue(Worksheet::convertFromSceneUnits(m_line->width(), Worksheet::Unit::Point));
0236     ui.sbOpacity->setValue(round(m_line->opacity() * 100));
0237     GuiTools::updatePenStyles(ui.cbStyle, ui.kcbColor->color());
0238     ui.cbStyle->setCurrentIndex(static_cast<int>(m_line->style()));
0239 }
0240 
0241 void LineWidget::loadConfig(const KConfigGroup& group) {
0242     if (m_line->histogramLineTypeAvailable())
0243         ui.cbType->setCurrentIndex(group.readEntry(m_prefix + QStringLiteral("Type"), static_cast<int>(m_line->histogramLineType())));
0244     else if (m_prefix == QLatin1String("DropLine"))
0245         ui.cbType->setCurrentIndex(group.readEntry("DropLineType", static_cast<int>(m_line->dropLineType())));
0246 
0247     ui.cbStyle->setCurrentIndex(group.readEntry(m_prefix + QStringLiteral("Style"), static_cast<int>(m_line->style())));
0248     setColor(group.readEntry(m_prefix + QStringLiteral("Color"), m_line->color()));
0249     ui.sbWidth->setValue(Worksheet::convertFromSceneUnits(group.readEntry(m_prefix + QStringLiteral("Width"), m_line->width()), Worksheet::Unit::Point));
0250     ui.sbOpacity->setValue(group.readEntry(m_prefix + QStringLiteral("Opacity"), m_line->opacity()) * 100);
0251     GuiTools::updatePenStyles(ui.cbStyle, ui.kcbColor->color());
0252 }
0253 
0254 void LineWidget::saveConfig(KConfigGroup& group) const {
0255     if (m_line->histogramLineTypeAvailable() || m_prefix == QLatin1String("DropLine"))
0256         group.writeEntry(m_prefix + QStringLiteral("Type"), ui.cbType->currentIndex());
0257 
0258     group.writeEntry(m_prefix + QStringLiteral("Style"), ui.cbStyle->currentIndex());
0259     group.writeEntry(m_prefix + QStringLiteral("Color"), ui.kcbColor->color());
0260     group.writeEntry(m_prefix + QStringLiteral("Width"), Worksheet::convertToSceneUnits(ui.sbWidth->value(), Worksheet::Unit::Point));
0261     group.writeEntry(m_prefix + QStringLiteral("Opacity"), ui.sbOpacity->value() / 100.0);
0262 }
0263 
0264 void LineWidget::setColor(const QColor& color) {
0265     ui.kcbColor->setColor(color);
0266 }