File indexing completed on 2024-05-12 15:28:20

0001 /***************************************************************************
0002     File                 : LabelWidget.cc
0003     Project              : LabPlot
0004     --------------------------------------------------------------------
0005     Copyright            : (C) 2008-2020 Alexander Semke (alexander.semke@web.de)
0006     Copyright            : (C) 2012-2017 Stefan Gerlach (stefan.gerlach@uni-konstanz.de)
0007     Description          : label settings widget
0008 
0009  ***************************************************************************/
0010 
0011 /***************************************************************************
0012  *                                                                         *
0013  *  This program is free software; you can redistribute it and/or modify   *
0014  *  it under the terms of the GNU General Public License as published by   *
0015  *  the Free Software Foundation; either version 2 of the License, or      *
0016  *  (at your option) any later version.                                    *
0017  *                                                                         *
0018  *  This program is distributed in the hope that it will be useful,        *
0019  *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
0020  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
0021  *  GNU General Public License for more details.                           *
0022  *                                                                         *
0023  *   You should have received a copy of the GNU General Public License     *
0024  *   along with this program; if not, write to the Free Software           *
0025  *   Foundation, Inc., 51 Franklin Street, Fifth Floor,                    *
0026  *   Boston, MA  02110-1301  USA                                           *
0027  *                                                                         *
0028  ***************************************************************************/
0029 #include "LabelWidget.h"
0030 #include "backend/worksheet/Worksheet.h"
0031 #include "backend/worksheet/plots/cartesian/Axis.h"
0032 #include "backend/worksheet/plots/cartesian/CartesianPlot.h"
0033 #include "backend/worksheet/plots/cartesian/CartesianPlotLegend.h"
0034 #include "kdefrontend/GuiTools.h"
0035 #include "kdefrontend/dockwidgets/BaseDock.h"
0036 #include "tools/TeXRenderer.h"
0037 
0038 #include <QFile>
0039 #include <QMenu>
0040 #include <QSettings>
0041 #include <QSplitter>
0042 #include <QTextDocumentFragment>
0043 #include <QWidgetAction>
0044 
0045 #include <KCharSelect>
0046 #include <KLocalizedString>
0047 #ifdef HAVE_KF5_SYNTAX_HIGHLIGHTING
0048 #include <KF5/KSyntaxHighlighting/SyntaxHighlighter>
0049 #include <KF5/KSyntaxHighlighting/Definition>
0050 #include <KF5/KSyntaxHighlighting/Theme>
0051 #endif
0052 
0053 #include <cmath>
0054 
0055 /*!
0056     \class LabelWidget
0057     \brief Widget for editing the properties of a TextLabel object, mostly used in an appropriate dock widget.
0058 
0059     In order the properties of the label to be shown, \c loadConfig() has to be called with the corresponding KConfigGroup
0060     (settings for a label in *Plot, Axis etc. or for an independent label on the worksheet).
0061 
0062     \ingroup kdefrontend
0063  */
0064 LabelWidget::LabelWidget(QWidget* parent) : QWidget(parent), m_dateTimeMenu(new QMenu(this)) {
0065     ui.setupUi(this);
0066 
0067     const KConfigGroup group = KSharedConfig::openConfig()->group(QLatin1String("Settings_General"));
0068     m_units = (BaseDock::Units)group.readEntry("Units", (int)BaseDock::Units::Metric);
0069     if (m_units == BaseDock::Units::Imperial)
0070         m_worksheetUnit = Worksheet::Unit::Inch;
0071 
0072     m_dateTimeMenu->setSeparatorsCollapsible(false); //we don't want the first separator to be removed
0073 
0074     ui.kcbFontColor->setColor(Qt::black); // default color
0075 
0076     //Icons
0077     ui.tbFontBold->setIcon( QIcon::fromTheme(QLatin1String("format-text-bold")) );
0078     ui.tbFontItalic->setIcon( QIcon::fromTheme(QLatin1String("format-text-italic")) );
0079     ui.tbFontUnderline->setIcon( QIcon::fromTheme(QLatin1String("format-text-underline")) );
0080     ui.tbFontStrikeOut->setIcon( QIcon::fromTheme(QLatin1String("format-text-strikethrough")) );
0081     ui.tbFontSuperScript->setIcon( QIcon::fromTheme(QLatin1String("format-text-superscript")) );
0082     ui.tbFontSubScript->setIcon( QIcon::fromTheme(QLatin1String("format-text-subscript")) );
0083     ui.tbSymbols->setIcon( QIcon::fromTheme(QLatin1String("labplot-format-text-symbol")) );
0084     ui.tbDateTime->setIcon( QIcon::fromTheme(QLatin1String("chronometer")) );
0085     ui.tbTexUsed->setIcon( QIcon::fromTheme(QLatin1String("labplot-TeX-logo")) );
0086 
0087     ui.tbFontBold->setToolTip(i18n("Bold"));
0088     ui.tbFontItalic->setToolTip(i18n("Italic"));
0089     ui.tbFontUnderline->setToolTip(i18n("Underline"));
0090     ui.tbFontStrikeOut->setToolTip(i18n("Strike Out"));
0091     ui.tbFontSuperScript->setToolTip(i18n("Super Script"));
0092     ui.tbFontSubScript->setToolTip(i18n("Sub-Script"));
0093     ui.tbSymbols->setToolTip(i18n("Insert Symbol"));
0094     ui.tbDateTime->setToolTip(i18n("Insert Date/Time"));
0095     ui.tbTexUsed->setToolTip(i18n("Switch to TeX mode"));
0096 
0097     //Positioning and alignment
0098     ui.cbPositionX->addItem(i18n("Left"));
0099     ui.cbPositionX->addItem(i18n("Center"));
0100     ui.cbPositionX->addItem(i18n("Right"));
0101     ui.cbPositionX->addItem(i18n("Custom"));
0102 
0103     ui.cbPositionY->addItem(i18n("Top"));
0104     ui.cbPositionY->addItem(i18n("Center"));
0105     ui.cbPositionY->addItem(i18n("Bottom"));
0106     ui.cbPositionY->addItem(i18n("Custom"));
0107 
0108     QString suffix;
0109     if (m_units == BaseDock::Units::Metric)
0110         suffix = QLatin1String(" cm");
0111     else
0112         suffix = QLatin1String(" in");
0113 
0114     ui.sbPositionX->setSuffix(suffix);
0115     ui.sbPositionY->setSuffix(suffix);
0116 
0117     ui.cbHorizontalAlignment->addItem(i18n("Left"));
0118     ui.cbHorizontalAlignment->addItem(i18n("Center"));
0119     ui.cbHorizontalAlignment->addItem(i18n("Right"));
0120 
0121     ui.cbVerticalAlignment->addItem(i18n("Top"));
0122     ui.cbVerticalAlignment->addItem(i18n("Center"));
0123     ui.cbVerticalAlignment->addItem(i18n("Bottom"));
0124 
0125     ui.cbBorderShape->addItem(i18n("No Border"));
0126     ui.cbBorderShape->addItem(i18n("Rectangle"));
0127     ui.cbBorderShape->addItem(i18n("Ellipse"));
0128     ui.cbBorderShape->addItem(i18n("Round sided rectangle"));
0129     ui.cbBorderShape->addItem(i18n("Round corner rectangle"));
0130     ui.cbBorderShape->addItem(i18n("Inwards round corner rectangle"));
0131     ui.cbBorderShape->addItem(i18n("Dented border rectangle"));
0132     ui.cbBorderShape->addItem(i18n("Cuboid"));
0133     ui.cbBorderShape->addItem(i18n("Up Pointing rectangle"));
0134     ui.cbBorderShape->addItem(i18n("Down Pointing rectangle"));
0135     ui.cbBorderShape->addItem(i18n("Left Pointing rectangle"));
0136     ui.cbBorderShape->addItem(i18n("Right Pointing rectangle"));
0137 
0138     ui.cbBorderStyle->addItem(i18n("No line"));
0139     ui.cbBorderStyle->addItem(i18n("Solid line"));
0140     ui.cbBorderStyle->addItem(i18n("Dash line"));
0141     ui.cbBorderStyle->addItem(i18n("Dot line"));
0142     ui.cbBorderStyle->addItem(i18n("Dash dot line"));
0143     ui.cbBorderStyle->addItem(i18n("Dash dot dot line"));
0144 
0145     ui.kcbBackgroundColor->setAlphaChannelEnabled(true);
0146     ui.kcbBackgroundColor->setColor(QColor(0,0,0, 0)); // transparent
0147     ui.kcbFontColor->setAlphaChannelEnabled(true);
0148     ui.kcbFontColor->setColor(QColor(255,255,255, 255)); // black
0149     ui.kcbBorderColor->setAlphaChannelEnabled(true);
0150     ui.kcbBorderColor->setColor(QColor(255,255,255, 255)); // black
0151 
0152     //check whether the used latex compiler is available.
0153     //Following logic is implemented (s.a. LabelWidget::teXUsedChanged()):
0154     //1. in case latex was used to generate the text label in the stored project
0155     //and no latex is available on the target system, latex button is toggled and
0156     //the user still can switch to the non-latex mode.
0157     //2. in case the label was in the non-latex mode and no latex is available,
0158     //deactivate the latex button so the user cannot switch to this mode.
0159     m_teXEnabled = TeXRenderer::enabled();
0160 
0161 #ifdef HAVE_KF5_SYNTAX_HIGHLIGHTING
0162     m_highlighter = new KSyntaxHighlighting::SyntaxHighlighter(ui.teLabel->document());
0163     m_highlighter->setDefinition(m_repository.definitionForName(QLatin1String("LaTeX")));
0164     m_highlighter->setTheme(  (palette().color(QPalette::Base).lightness() < 128)
0165                                 ? m_repository.defaultTheme(KSyntaxHighlighting::Repository::DarkTheme)
0166                                 : m_repository.defaultTheme(KSyntaxHighlighting::Repository::LightTheme) );
0167 #endif
0168 
0169     //SLOTS
0170     // text properties
0171     connect(ui.tbTexUsed, &QToolButton::clicked, this, &LabelWidget::teXUsedChanged );
0172     connect(ui.teLabel, &ResizableTextEdit::textChanged, this, &LabelWidget::textChanged);
0173     connect(ui.teLabel, &ResizableTextEdit::currentCharFormatChanged, this, &LabelWidget::charFormatChanged);
0174     connect(ui.kcbFontColor, &KColorButton::changed, this, &LabelWidget::fontColorChanged);
0175     connect(ui.kcbBackgroundColor, &KColorButton::changed, this, &LabelWidget::backgroundColorChanged);
0176     connect(ui.tbFontBold, &QToolButton::clicked, this, &LabelWidget::fontBoldChanged);
0177     connect(ui.tbFontItalic, &QToolButton::clicked, this, &LabelWidget::fontItalicChanged);
0178     connect(ui.tbFontUnderline, &QToolButton::clicked, this, &LabelWidget::fontUnderlineChanged);
0179     connect(ui.tbFontStrikeOut, &QToolButton::clicked, this, &LabelWidget::fontStrikeOutChanged);
0180     connect(ui.tbFontSuperScript, &QToolButton::clicked, this, &LabelWidget::fontSuperScriptChanged);
0181     connect(ui.tbFontSubScript, &QToolButton::clicked, this, &LabelWidget::fontSubScriptChanged);
0182     connect(ui.tbSymbols, &QToolButton::clicked, this, &LabelWidget::charMenu);
0183     connect(ui.tbDateTime, &QToolButton::clicked, this, &LabelWidget::dateTimeMenu);
0184     connect(m_dateTimeMenu, &QMenu::triggered, this, &LabelWidget::insertDateTime );
0185     connect(ui.kfontRequester, &KFontRequester::fontSelected, this, &LabelWidget::fontChanged);
0186     connect(ui.kfontRequesterTeX, &KFontRequester::fontSelected, this, &LabelWidget::teXFontChanged);
0187     connect(ui.sbFontSize, QOverload<int>::of(&QSpinBox::valueChanged), this, &LabelWidget::fontSizeChanged);
0188 
0189     // geometry
0190     connect( ui.cbPositionX, QOverload<int>::of(&KComboBox::currentIndexChanged), this, &LabelWidget::positionXChanged);
0191     connect( ui.cbPositionY, QOverload<int>::of(&KComboBox::currentIndexChanged), this, &LabelWidget::positionYChanged);
0192     connect( ui.sbPositionX, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &LabelWidget::customPositionXChanged);
0193     connect( ui.sbPositionY, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &LabelWidget::customPositionYChanged);
0194     connect( ui.cbHorizontalAlignment, QOverload<int>::of(&KComboBox::currentIndexChanged), this, &LabelWidget::horizontalAlignmentChanged);
0195     connect( ui.cbVerticalAlignment, QOverload<int>::of(&KComboBox::currentIndexChanged), this, &LabelWidget::verticalAlignmentChanged);
0196     connect( ui.sbRotation, QOverload<int>::of(&QSpinBox::valueChanged), this, &LabelWidget::rotationChanged);
0197     connect( ui.sbOffsetX, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &LabelWidget::offsetXChanged);
0198     connect( ui.sbOffsetY, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &LabelWidget::offsetYChanged);
0199 
0200     connect( ui.chbVisible, &QCheckBox::clicked, this, &LabelWidget::visibilityChanged);
0201 
0202     //Border
0203     connect(ui.cbBorderShape, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &LabelWidget::borderShapeChanged);
0204     connect(ui.cbBorderStyle, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &LabelWidget::borderStyleChanged);
0205     connect(ui.kcbBorderColor, &KColorButton::changed, this, &LabelWidget::borderColorChanged);
0206     connect(ui.sbBorderWidth, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &LabelWidget::borderWidthChanged);
0207     connect(ui.sbBorderOpacity, QOverload<int>::of(&QSpinBox::valueChanged), this, &LabelWidget::borderOpacityChanged);
0208 
0209     //TODO: https://bugreports.qt.io/browse/QTBUG-25420
0210     ui.tbFontUnderline->hide();
0211     ui.tbFontStrikeOut->hide();
0212 }
0213 
0214 void LabelWidget::setLabels(QList<TextLabel*> labels) {
0215     m_labelsList = labels;
0216     m_label = labels.first();
0217 
0218     ui.lOffsetX->hide();
0219     ui.lOffsetY->hide();
0220 
0221     ui.sbOffsetX->hide();
0222     ui.sbOffsetY->hide();
0223 
0224     this->load();
0225     initConnections();
0226     updateBackground();
0227     updateLocale();
0228 }
0229 
0230 void LabelWidget::setAxes(QList<Axis*> axes) {
0231     m_labelsList.clear();
0232     for (auto* axis : axes) {
0233         m_labelsList.append(axis->title());
0234         connect(axis, &Axis::titleOffsetXChanged, this, &LabelWidget::labelOffsetxChanged);
0235         connect(axis, &Axis::titleOffsetYChanged, this, &LabelWidget::labelOffsetyChanged );
0236         connect(axis->title(), &TextLabel::rotationAngleChanged, this, &LabelWidget::labelRotationAngleChanged );
0237     }
0238 
0239     m_axesList = axes;
0240     m_label = m_labelsList.first();
0241 
0242     this->load();
0243     initConnections();
0244     updateBackground();
0245     updateLocale();
0246 }
0247 
0248 /*!
0249  * this function keeps the background color of the TextEdit in LabelWidget in sync with
0250  * the background color of the parent aspect. This is to avoid the situations where the
0251  * text wouldn't be readable anymore if the foreground color is close or equal to the
0252  * background color of TextEdit - e.g., a label with white foreground color on a dark worksheet
0253  * and with white background color in TextEdit (desktop default color).
0254  *
0255  * Called if the background color of the parent aspect has changed.
0256  */
0257 void LabelWidget::updateBackground() const {
0258     if (ui.tbTexUsed->isChecked())
0259         return;
0260 
0261     QColor color;
0262     AspectType type = m_label->parentAspect()->type();
0263     if (type == AspectType::Worksheet)
0264         color = static_cast<const Worksheet*>(m_label->parentAspect())->backgroundFirstColor();
0265     else if (type == AspectType::CartesianPlot)
0266         color = static_cast<CartesianPlot*>(m_label->parentAspect())->plotArea()->backgroundFirstColor();
0267     else if (type == AspectType::CartesianPlotLegend)
0268         color = static_cast<const CartesianPlotLegend*>(m_label->parentAspect())->backgroundFirstColor();
0269     if (type == AspectType::Axis)
0270         color = static_cast<CartesianPlot*>(m_label->parentAspect()->parentAspect())->plotArea()->backgroundFirstColor();
0271 
0272     QPalette p = ui.teLabel->palette();
0273     p.setColor(QPalette::Base, color);
0274     ui.teLabel->setPalette(p);
0275 }
0276 
0277 void LabelWidget::initConnections() const {
0278     connect(m_label, &TextLabel::textWrapperChanged, this, &LabelWidget::labelTextWrapperChanged);
0279     connect(m_label, &TextLabel::teXImageUpdated, this, &LabelWidget::labelTeXImageUpdated);
0280     connect(m_label, &TextLabel::teXFontChanged, this, &LabelWidget::labelTeXFontChanged);
0281     connect(m_label, &TextLabel::fontColorChanged, this, &LabelWidget::labelFontColorChanged);
0282     connect(m_label, &TextLabel::backgroundColorChanged, this, &LabelWidget::labelBackgroundColorChanged);
0283     connect(m_label, &TextLabel::positionChanged, this, &LabelWidget::labelPositionChanged);
0284     connect(m_label, &TextLabel::horizontalAlignmentChanged, this, &LabelWidget::labelHorizontalAlignmentChanged);
0285     connect(m_label, &TextLabel::verticalAlignmentChanged, this, &LabelWidget::labelVerticalAlignmentChanged);
0286     connect(m_label, &TextLabel::rotationAngleChanged, this, &LabelWidget::labelRotationAngleChanged);
0287     connect(m_label, &TextLabel::borderShapeChanged, this, &LabelWidget::labelBorderShapeChanged);
0288     connect(m_label, &TextLabel::borderPenChanged, this, &LabelWidget::labelBorderPenChanged);
0289     connect(m_label, &TextLabel::borderOpacityChanged, this, &LabelWidget::labelBorderOpacityChanged);
0290     connect(m_label, &TextLabel::visibleChanged, this, &LabelWidget::labelVisibleChanged);
0291 
0292     AspectType type = m_label->parentAspect()->type();
0293     if (type == AspectType::Worksheet) {
0294         auto* worksheet = static_cast<const Worksheet*>(m_label->parentAspect());
0295         connect(worksheet, &Worksheet::backgroundFirstColorChanged, this, &LabelWidget::updateBackground);
0296     }else if (type == AspectType::CartesianPlot) {
0297         auto* plotArea = static_cast<CartesianPlot*>(m_label->parentAspect())->plotArea();
0298         connect(plotArea, &PlotArea::backgroundFirstColorChanged, this, &LabelWidget::updateBackground);
0299     } else if (type == AspectType::CartesianPlotLegend) {
0300         auto* legend = static_cast<const CartesianPlotLegend*>(m_label->parentAspect());
0301         connect(legend, &CartesianPlotLegend::backgroundFirstColorChanged, this, &LabelWidget::updateBackground);
0302     } else if (type == AspectType::Axis) {
0303         auto* plotArea = static_cast<CartesianPlot*>(m_label->parentAspect()->parentAspect())->plotArea();
0304         connect(plotArea, &PlotArea::backgroundFirstColorChanged, this, &LabelWidget::updateBackground);
0305     }
0306 }
0307 
0308 /*!
0309  * enables/disables the "fixed label"-mode, used when displaying
0310  * the properties of axis' title label.
0311  * In this mode, in the "geometry"-part only the offset (offset to the axis)
0312  * and the rotation of the label are available.
0313  */
0314 void LabelWidget::setFixedLabelMode(const bool b) {
0315     ui.lPositionX->setVisible(!b);
0316     ui.cbPositionX->setVisible(!b);
0317     ui.sbPositionX->setVisible(!b);
0318     ui.lPositionY->setVisible(!b);
0319     ui.cbPositionY->setVisible(!b);
0320     ui.sbPositionY->setVisible(!b);
0321     ui.lHorizontalAlignment->setVisible(!b);
0322     ui.cbHorizontalAlignment->setVisible(!b);
0323     ui.lVerticalAlignment->setVisible(!b);
0324     ui.cbVerticalAlignment->setVisible(!b);
0325     ui.lOffsetX->setVisible(b);
0326     ui.lOffsetY->setVisible(b);
0327     ui.sbOffsetX->setVisible(b);
0328     ui.sbOffsetY->setVisible(b);
0329 }
0330 
0331 /*!
0332  * enables/disables all geometry relevant widgets.
0333  * Used when displaying legend's title label.
0334  */
0335 void LabelWidget::setGeometryAvailable(const bool b) {
0336     ui.lGeometry->setVisible(b);
0337     ui.lPositionX->setVisible(b);
0338     ui.cbPositionX->setVisible(b);
0339     ui.sbPositionX->setVisible(b);
0340     ui.lPositionY->setVisible(b);
0341     ui.cbPositionY->setVisible(b);
0342     ui.sbPositionY->setVisible(b);
0343     ui.lHorizontalAlignment->setVisible(b);
0344     ui.cbHorizontalAlignment->setVisible(b);
0345     ui.lVerticalAlignment->setVisible(b);
0346     ui.cbVerticalAlignment->setVisible(b);
0347     ui.lOffsetX->setVisible(b);
0348     ui.lOffsetY->setVisible(b);
0349     ui.sbOffsetX->setVisible(b);
0350     ui.sbOffsetY->setVisible(b);
0351     ui.lRotation->setVisible(b);
0352     ui.sbRotation->setVisible(b);
0353 }
0354 
0355 /*!
0356  * enables/disables all border relevant widgets.
0357  * Used when displaying legend's title label.
0358  */
0359 void LabelWidget::setBorderAvailable(bool b) {
0360     ui.lBorder->setVisible(b);
0361     ui.lBorderShape->setVisible(b);
0362     ui.cbBorderShape->setVisible(b);
0363     ui.lBorderStyle->setVisible(b);
0364     ui.cbBorderStyle->setVisible(b);
0365     ui.lBorderColor->setVisible(b);
0366     ui.kcbBorderColor->setVisible(b);
0367     ui.lBorderWidth->setVisible(b);
0368     ui.sbBorderWidth->setVisible(b);
0369     ui.lBorderOpacity->setVisible(b);
0370     ui.sbBorderOpacity->setVisible(b);
0371 }
0372 
0373 void LabelWidget::updateUnits() {
0374     const KConfigGroup group = KSharedConfig::openConfig()->group(QLatin1String("Settings_General"));
0375     BaseDock::Units units = (BaseDock::Units)group.readEntry("Units", (int)BaseDock::Units::Metric);
0376     if (units == m_units)
0377         return;
0378 
0379     m_units = units;
0380     Lock lock(m_initializing);
0381     QString suffix;
0382     if (m_units == BaseDock::Units::Metric) {
0383         //convert from imperial to metric
0384         m_worksheetUnit = Worksheet::Unit::Centimeter;
0385         suffix = QLatin1String(" cm");
0386         ui.sbPositionX->setValue(ui.sbPositionX->value()*2.54);
0387         ui.sbPositionY->setValue(ui.sbPositionX->value()*2.54);
0388     } else {
0389         //convert from metric to imperial
0390         m_worksheetUnit = Worksheet::Unit::Inch;
0391         suffix = QLatin1String(" in");
0392         ui.sbPositionX->setValue(ui.sbPositionX->value()/2.54);
0393         ui.sbPositionY->setValue(ui.sbPositionY->value()/2.54);
0394     }
0395 
0396     ui.sbPositionX->setSuffix(suffix);
0397     ui.sbPositionY->setSuffix(suffix);
0398 }
0399 
0400 void LabelWidget::updateLocale() {
0401     SET_NUMBER_LOCALE
0402     ui.sbPositionX->setLocale(numberLocale);
0403     ui.sbPositionY->setLocale(numberLocale);
0404     ui.sbOffsetX->setLocale(numberLocale);
0405     ui.sbOffsetY->setLocale(numberLocale);
0406     ui.sbBorderWidth->setLocale(numberLocale);
0407 }
0408 
0409 //**********************************************************
0410 //****** SLOTs for changes triggered in LabelWidget ********
0411 //**********************************************************
0412 
0413 // text formatting slots
0414 
0415 void LabelWidget::textChanged() {
0416     if (m_initializing)
0417         return;
0418 
0419     const Lock lock(m_initializing);
0420 
0421     if (ui.tbTexUsed->isChecked()) {
0422         QString text = ui.teLabel->toPlainText();
0423         TextLabel::TextWrapper wrapper(text, true);
0424 
0425         for (auto* label : m_labelsList)
0426             label->setText(wrapper);
0427     } else {
0428         //save an empty string instead of a html-string with empty body,
0429         //if no text available in QTextEdit
0430         QString text;
0431         if (!ui.teLabel->toPlainText().isEmpty()) {
0432             //if the current label text is empty, set the color first
0433             if (m_label->text().text.isEmpty()) {
0434                 ui.teLabel->selectAll();
0435                 ui.teLabel->setTextColor(m_label->fontColor());
0436             }
0437 
0438             text = ui.teLabel->toHtml();
0439         }
0440 
0441         TextLabel::TextWrapper wrapper(text, false, true);
0442         for (auto* label : m_labelsList)
0443             label->setText(wrapper);
0444     }
0445 
0446     //background color gets lost on every text change...
0447     updateBackground();
0448 }
0449 
0450 /*!
0451  * \brief LabelWidget::charFormatChanged
0452  * \param format
0453  * Used to update the colors, font,... in the color font widgets to show the style of the selected text
0454  */
0455 void LabelWidget::charFormatChanged(const QTextCharFormat& format) {
0456     if (m_initializing)
0457         return;
0458 
0459     if (ui.tbTexUsed->isChecked())
0460         return;
0461 
0462     const Lock lock(m_initializing);
0463 
0464     // update button state
0465     ui.tbFontBold->setChecked(ui.teLabel->fontWeight() == QFont::Bold);
0466     ui.tbFontItalic->setChecked(ui.teLabel->fontItalic());
0467     ui.tbFontUnderline->setChecked(ui.teLabel->fontUnderline());
0468     ui.tbFontStrikeOut->setChecked(format.fontStrikeOut());
0469     ui.tbFontSuperScript->setChecked(format.verticalAlignment() == QTextCharFormat::AlignSuperScript);
0470     ui.tbFontSubScript->setChecked(format.verticalAlignment() == QTextCharFormat::AlignSubScript);
0471 
0472     //font and colors
0473     if (format.foreground().color().isValid())
0474         ui.kcbFontColor->setColor(format.foreground().color());
0475     else
0476         ui.kcbFontColor->setColor(m_label->fontColor());
0477 
0478     if (format.background().color().isValid())
0479         ui.kcbBackgroundColor->setColor(format.background().color());
0480     else
0481         ui.kcbBackgroundColor->setColor(m_label->backgroundColor());
0482 
0483     ui.kfontRequester->setFont(format.font());
0484 }
0485 
0486 void LabelWidget::teXUsedChanged(bool checked) {
0487     //hide text editing elements if TeX-option is used
0488     ui.tbFontBold->setVisible(!checked);
0489     ui.tbFontItalic->setVisible(!checked);
0490 
0491     //TODO: https://bugreports.qt.io/browse/QTBUG-25420
0492 //  ui.tbFontUnderline->setVisible(!checked);
0493 //  ui.tbFontStrikeOut->setVisible(!checked);
0494 
0495     ui.tbFontSubScript->setVisible(!checked);
0496     ui.tbFontSuperScript->setVisible(!checked);
0497     ui.tbSymbols->setVisible(!checked);
0498 
0499     ui.lFont->setVisible(!checked);
0500     ui.kfontRequester->setVisible(!checked);
0501 
0502     //TODO:
0503     //for normal text we need to hide the background color because of QTBUG-25420
0504     ui.kcbBackgroundColor->setVisible(checked);
0505     ui.lBackgroundColor->setVisible(checked);
0506 
0507     if (checked) {
0508         ui.tbTexUsed->setToolTip(i18n("Switch to TeX mode"));
0509 
0510         //reset all applied formattings when switching from html to tex mode
0511         QTextCursor cursor = ui.teLabel->textCursor();
0512         int position = cursor.position();
0513         ui.teLabel->selectAll();
0514         QTextCharFormat format;
0515         ui.teLabel->setCurrentCharFormat(format);
0516         cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, position);
0517         ui.teLabel->setTextCursor(cursor);
0518 
0519 #ifdef HAVE_KF5_SYNTAX_HIGHLIGHTING
0520         m_highlighter->setDocument(ui.teLabel->document());
0521 #endif
0522         KConfigGroup conf(KSharedConfig::openConfig(), QLatin1String("Settings_Worksheet"));
0523         QString engine = conf.readEntry(QLatin1String("LaTeXEngine"), "");
0524         if (engine == QLatin1String("xelatex") || engine == QLatin1String("lualatex")) {
0525             ui.lFontTeX->setVisible(true);
0526             ui.kfontRequesterTeX->setVisible(true);
0527             ui.lFontSize->setVisible(false);
0528             ui.sbFontSize->setVisible(false);
0529         } else {
0530             ui.lFontTeX->setVisible(false);
0531             ui.kfontRequesterTeX->setVisible(false);
0532             ui.lFontSize->setVisible(true);
0533             ui.sbFontSize->setVisible(true);
0534         }
0535 
0536         //update TeX colors
0537         ui.kcbFontColor->setColor(m_label->fontColor());
0538         ui.kcbBackgroundColor->setColor(m_label->backgroundColor());
0539     } else {
0540         ui.tbTexUsed->setToolTip(i18n("Switch to text mode"));
0541 
0542 #ifdef HAVE_KF5_SYNTAX_HIGHLIGHTING
0543         m_highlighter->setDocument(nullptr);
0544 #endif
0545         ui.lFontTeX->setVisible(false);
0546         ui.kfontRequesterTeX->setVisible(false);
0547         ui.lFontSize->setVisible(false);
0548         ui.sbFontSize->setVisible(false);
0549 
0550         //when switching to the text mode, set the background color to white just for the case the latex code provided by the user
0551         //in the TeX-mode is not valid and the background was set to red (s.a. LabelWidget::labelTeXImageUpdated())
0552         ui.teLabel->setStyleSheet(QString());
0553     }
0554 
0555     //no latex is available and the user switched to the text mode,
0556     //deactivate the button since it shouldn't be possible anymore to switch to the TeX-mode
0557     if (!m_teXEnabled && !checked) {
0558         ui.tbTexUsed->setEnabled(false);
0559         ui.tbTexUsed->setToolTip(i18n("LaTeX typesetting not possible. Please check the settings."));
0560     } else
0561         ui.tbTexUsed->setEnabled(true);
0562 
0563     if (m_initializing)
0564         return;
0565 
0566     QString text = checked ? ui.teLabel->toPlainText() : ui.teLabel->toHtml();
0567     TextLabel::TextWrapper wrapper(text, checked);
0568     for (auto* label : m_labelsList)
0569         label->setText(wrapper);
0570 }
0571 
0572 void LabelWidget::fontColorChanged(const QColor& color) {
0573     if (m_initializing)
0574         return;
0575 
0576     QTextCursor c = ui.teLabel->textCursor();
0577     if (c.selectedText().isEmpty())
0578         ui.teLabel->selectAll();
0579     ui.teLabel->setTextColor(color);
0580 }
0581 
0582 void LabelWidget::backgroundColorChanged(const QColor& color) {
0583     if (m_initializing)
0584         return;
0585 
0586     if (!m_teXEnabled && m_label->text().teXUsed) {
0587         QTextCursor c = ui.teLabel->textCursor();
0588         if (c.selectedText().isEmpty())
0589             ui.teLabel->selectAll();
0590 
0591         ui.teLabel->setTextBackgroundColor(color);
0592     } else {
0593         // Latex text does not support html code. For this the backgroundColor variable is used
0594         // Only single color background is supported
0595         for (auto* label : m_labelsList)
0596             label->setBackgroundColor(color);
0597     }
0598 }
0599 
0600 void LabelWidget::fontSizeChanged(int value) {
0601     if (m_initializing)
0602         return;
0603 
0604     QFont font = m_label->teXFont();
0605     font.setPointSize(value);
0606     for (auto* label : m_labelsList)
0607         label->setTeXFont(font);
0608 }
0609 
0610 void LabelWidget::fontBoldChanged(bool checked) {
0611     if (m_initializing)
0612         return;
0613 
0614     QTextCursor c = ui.teLabel->textCursor();
0615     if (c.selectedText().isEmpty())
0616         ui.teLabel->selectAll();
0617 
0618     if (checked)
0619         ui.teLabel->setFontWeight(QFont::Bold);
0620     else
0621         ui.teLabel->setFontWeight(QFont::Normal);
0622 }
0623 
0624 void LabelWidget::fontItalicChanged(bool checked) {
0625     if (m_initializing)
0626         return;
0627 
0628     QTextCursor c = ui.teLabel->textCursor();
0629     if (c.selectedText().isEmpty())
0630         ui.teLabel->selectAll();
0631 
0632     ui.teLabel->setFontItalic(checked);
0633 }
0634 
0635 void LabelWidget::fontUnderlineChanged(bool checked) {
0636     if (m_initializing)
0637         return;
0638 
0639     QTextCursor c = ui.teLabel->textCursor();
0640     if (c.selectedText().isEmpty())
0641         ui.teLabel->selectAll();
0642 
0643     ui.teLabel->setFontUnderline(checked);
0644 }
0645 
0646 void LabelWidget::fontStrikeOutChanged(bool checked) {
0647     if (m_initializing)
0648         return;
0649 
0650     QTextCursor c = ui.teLabel->textCursor();
0651     if (c.selectedText().isEmpty())
0652         ui.teLabel->selectAll();
0653 
0654     QTextCharFormat format = ui.teLabel->currentCharFormat();
0655     format.setFontStrikeOut(checked);
0656     ui.teLabel->setCurrentCharFormat(format);
0657 }
0658 
0659 void LabelWidget::fontSuperScriptChanged(bool checked) {
0660     if (m_initializing)
0661         return;
0662 
0663     QTextCursor c = ui.teLabel->textCursor();
0664     if (c.selectedText().isEmpty())
0665         ui.teLabel->selectAll();
0666 
0667     QTextCharFormat format = ui.teLabel->currentCharFormat();
0668     if (checked)
0669         format.setVerticalAlignment(QTextCharFormat::AlignSuperScript);
0670     else
0671         format.setVerticalAlignment(QTextCharFormat::AlignNormal);
0672 
0673     ui.teLabel->setCurrentCharFormat(format);
0674 }
0675 
0676 void LabelWidget::fontSubScriptChanged(bool checked) {
0677     if (m_initializing)
0678         return;
0679 
0680     QTextCursor c = ui.teLabel->textCursor();
0681     if (c.selectedText().isEmpty())
0682         ui.teLabel->selectAll();
0683 
0684     QTextCharFormat format = ui.teLabel->currentCharFormat();
0685     if (checked)
0686         format.setVerticalAlignment(QTextCharFormat::AlignSubScript);
0687     else
0688         format.setVerticalAlignment(QTextCharFormat::AlignNormal);
0689 
0690     ui.teLabel->setCurrentCharFormat(format);
0691 }
0692 
0693 void LabelWidget::fontChanged(const QFont& font) {
0694     if (m_initializing)
0695         return;
0696 
0697     const auto c = ui.teLabel->textCursor();
0698     if (c.selectedText().isEmpty())
0699         ui.teLabel->selectAll();
0700 
0701     // use mergeCurrentCharFormat(QTextCharFormat) instead of setFontFamily(font.family()), etc.
0702     // because this avoids textChanged() after every command
0703     QTextCharFormat format;
0704     format.setFontFamily(font.family());
0705 #if (QT_VERSION >= QT_VERSION_CHECK(5, 13, 0))
0706     format.setFontFamilies({font.family()});    // see QTBUG-80475
0707 #endif
0708     format.setFontPointSize(font.pointSize());
0709     format.setFontItalic(font.italic());
0710     format.setFontWeight(font.weight());
0711     if (font.underline())
0712         format.setUnderlineStyle(QTextCharFormat::UnderlineStyle::SingleUnderline);
0713     if (font.strikeOut())
0714         format.setFontStrikeOut(font.strikeOut());
0715 
0716     //QDEBUG(Q_FUNC_INFO << ", BEFORE:" << ui.teLabel->toHtml())
0717     ui.teLabel->mergeCurrentCharFormat(format);
0718     //QDEBUG(Q_FUNC_INFO << ", AFTER :" << ui.teLabel->toHtml())
0719 }
0720 
0721 void LabelWidget::teXFontChanged(const QFont& font) {
0722     if (m_initializing)
0723         return;
0724 
0725     for (auto* label : m_labelsList)
0726         label->setTeXFont(font);
0727 }
0728 
0729 void LabelWidget::charMenu() {
0730     QMenu menu;
0731     KCharSelect selection(this, nullptr, KCharSelect::SearchLine | KCharSelect::CharacterTable | KCharSelect::BlockCombos | KCharSelect::HistoryButtons);
0732     QFont font = ui.teLabel->currentFont();
0733     // use the system default size, otherwise the symbols might be hard to read
0734     // if the current label font size is too small
0735     font.setPointSize(QFont().pointSize());
0736     selection.setCurrentFont(font);
0737     connect(&selection, &KCharSelect::charSelected, this, &LabelWidget::insertChar);
0738     connect(&selection, &KCharSelect::charSelected, &menu, &LabelWidget::close);
0739 
0740     auto* widgetAction = new QWidgetAction(this);
0741     widgetAction->setDefaultWidget(&selection);
0742     menu.addAction(widgetAction);
0743 
0744     QPoint pos(-menu.sizeHint().width()+ui.tbSymbols->width(),-menu.sizeHint().height());
0745     menu.exec(ui.tbSymbols->mapToGlobal(pos));
0746 }
0747 
0748 void LabelWidget::insertChar(QChar c) {
0749     ui.teLabel->insertPlainText(QString(c));
0750 }
0751 
0752 void LabelWidget::dateTimeMenu() {
0753     m_dateTimeMenu->clear();
0754 
0755     const QString configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation);
0756     const QString configFile = configPath + QLatin1String("/klanguageoverridesrc");
0757     if (!QFile::exists(configFile)) {
0758         QDate date = QDate::currentDate();
0759         m_dateTimeMenu->addSeparator()->setText(i18n("Date"));
0760         m_dateTimeMenu->addAction( date.toString(Qt::TextDate) );
0761         m_dateTimeMenu->addAction( date.toString(Qt::ISODate) );
0762         m_dateTimeMenu->addAction( date.toString(Qt::SystemLocaleShortDate) );
0763         m_dateTimeMenu->addAction( date.toString(Qt::SystemLocaleLongDate) );
0764         m_dateTimeMenu->addAction( date.toString(Qt::RFC2822Date) );
0765 
0766         QDateTime time = QDateTime::currentDateTime();
0767         m_dateTimeMenu->addSeparator()->setText(i18n("Date and Time"));
0768         m_dateTimeMenu->addAction( time.toString(Qt::TextDate) );
0769         m_dateTimeMenu->addAction( time.toString(Qt::ISODate) );
0770         m_dateTimeMenu->addAction( time.toString(Qt::SystemLocaleShortDate) );
0771         m_dateTimeMenu->addAction( time.toString(Qt::SystemLocaleLongDate) );
0772         m_dateTimeMenu->addAction( time.toString(Qt::RFC2822Date) );
0773     } else {
0774         //application language was changed:
0775         //determine the currently used language and use QLocale::toString()
0776         //to get the strings translated into the currently used language
0777         //TODO: why not use QLocale() ?
0778         QSettings settings (configFile, QSettings::IniFormat);
0779         settings.beginGroup(QLatin1String("Language"));
0780         QByteArray languageCode;
0781         languageCode = settings.value(qAppName(), languageCode).toByteArray();
0782         QLocale locale(QString::fromLatin1(languageCode.data()));
0783 
0784         QDate date = QDate::currentDate();
0785         m_dateTimeMenu->addSeparator()->setText(i18n("Date"));
0786         m_dateTimeMenu->addAction( locale.toString(date, QLatin1String("ddd MMM d yyyy")) ); //Qt::TextDate
0787         m_dateTimeMenu->addAction( locale.toString(date, QLatin1String("yyyy-MM-dd")) ); //Qt::ISODate
0788         m_dateTimeMenu->addAction( locale.system().toString(date, QLocale::ShortFormat) ); //Qt::SystemLocaleShortDate
0789         //no LongFormat here since it would contain strings in system's language which (potentially) is not the current application language
0790         m_dateTimeMenu->addAction( locale.toString(date, QLatin1String("dd MMM yyyy")) ); //Qt::RFC2822Date
0791 
0792         QDateTime time = QDateTime::currentDateTime();
0793         m_dateTimeMenu->addSeparator()->setText(i18n("Date and Time"));
0794         m_dateTimeMenu->addAction( locale.toString(time, QLatin1String("ddd MMM d hh:mm:ss yyyy")) ); //Qt::TextDate
0795         m_dateTimeMenu->addAction( locale.toString(time, QLatin1String("yyyy-MM-ddTHH:mm:ss")) ); //Qt::ISODate
0796         m_dateTimeMenu->addAction( locale.system().toString(time, QLocale::ShortFormat) ); //Qt::SystemLocaleShortDate
0797         //no LongFormat here since it would contain strings in system's language which (potentially) is not the current application language
0798 
0799         //TODO: RFC2822 requires time zone but Qt QLocale::toString() seems to ignore TZD (time zone designator) completely,
0800         //which works correctly with QDateTime::toString()
0801         m_dateTimeMenu->addAction( locale.toString(time, QLatin1String("dd MMM yyyy hh:mm:ss")) ); //Qt::RFC2822Date
0802     }
0803 
0804     m_dateTimeMenu->exec( mapToGlobal(ui.tbDateTime->rect().bottomLeft()));
0805 }
0806 
0807 void LabelWidget::insertDateTime(QAction* action) {
0808     ui.teLabel->insertPlainText( action->text().remove('&') );
0809 }
0810 
0811 // geometry slots
0812 
0813 /*!
0814     called when label's current horizontal position relative to its parent (left, center, right, custom ) is changed.
0815 */
0816 void LabelWidget::positionXChanged(int index) {
0817     //Enable/disable the spinbox for the x- oordinates if the "custom position"-item is selected/deselected
0818     if (index == ui.cbPositionX->count()-1 )
0819         ui.sbPositionX->setEnabled(true);
0820     else
0821         ui.sbPositionX->setEnabled(false);
0822 
0823     if (m_initializing)
0824         return;
0825 
0826     auto horPos = TextLabel::HorizontalPosition(index);
0827     for (auto* label : m_labelsList) {
0828         auto position = label->position();
0829         position.horizontalPosition = horPos;
0830         label->setPosition(position);
0831     }
0832 }
0833 
0834 /*!
0835     called when label's current horizontal position relative to its parent (top, center, bottom, custom ) is changed.
0836 */
0837 void LabelWidget::positionYChanged(int index) {
0838     //Enable/disable the spinbox for the y-coordinates if the "custom position"-item is selected/deselected
0839     if (index == ui.cbPositionY->count()-1 )
0840         ui.sbPositionY->setEnabled(true);
0841     else
0842         ui.sbPositionY->setEnabled(false);
0843 
0844     if (m_initializing)
0845         return;
0846 
0847     auto verPos = TextLabel::VerticalPosition(index);
0848     for (auto* label : m_labelsList) {
0849         auto position = label->position();
0850         position.verticalPosition = verPos;
0851         label->setPosition(position);
0852     }
0853 }
0854 
0855 void LabelWidget::customPositionXChanged(double value) {
0856     if (m_initializing)
0857         return;
0858 
0859     double x = Worksheet::convertToSceneUnits(value, m_worksheetUnit);
0860     for (auto* label : m_labelsList) {
0861         auto position = label->position();
0862         position.point.setX(x);
0863         label->setPosition(position);
0864     }
0865 }
0866 
0867 void LabelWidget::customPositionYChanged(double value) {
0868     if (m_initializing)
0869         return;
0870 
0871     double y = Worksheet::convertToSceneUnits(value, m_worksheetUnit);
0872     for (auto* label : m_labelsList) {
0873         auto position = label->position();
0874         position.point.setY(y);
0875         label->setPosition(position);
0876     }
0877 }
0878 
0879 void LabelWidget::horizontalAlignmentChanged(int index) {
0880     if (m_initializing)
0881         return;
0882 
0883     for (auto* label : m_labelsList)
0884         label->setHorizontalAlignment(TextLabel::HorizontalAlignment(index));
0885 }
0886 
0887 void LabelWidget::verticalAlignmentChanged(int index) {
0888     if (m_initializing)
0889         return;
0890 
0891     for (auto* label : m_labelsList)
0892         label->setVerticalAlignment(TextLabel::VerticalAlignment(index));
0893 }
0894 
0895 void LabelWidget::rotationChanged(int value) {
0896     if (m_initializing)
0897         return;
0898 
0899     for (auto* label : m_labelsList)
0900         label->setRotationAngle(value);
0901 }
0902 
0903 void LabelWidget::offsetXChanged(double value) {
0904     if (m_initializing)
0905         return;
0906 
0907     for (auto* axis : m_axesList)
0908         axis->setTitleOffsetX( Worksheet::convertToSceneUnits(value, Worksheet::Unit::Point) );
0909 }
0910 
0911 void LabelWidget::offsetYChanged(double value) {
0912     if (m_initializing)
0913         return;
0914 
0915     for (auto* axis : m_axesList)
0916         axis->setTitleOffsetY( Worksheet::convertToSceneUnits(value, Worksheet::Unit::Point) );
0917 }
0918 
0919 void LabelWidget::visibilityChanged(bool state) {
0920     if (m_initializing)
0921         return;
0922 
0923     for (auto* label : m_labelsList)
0924         label->setVisible(state);
0925 }
0926 
0927 //border
0928 void LabelWidget::borderShapeChanged(int index) {
0929     auto shape = (TextLabel::BorderShape)index;
0930     bool b = (shape != TextLabel::BorderShape::NoBorder);
0931     ui.lBorderStyle->setVisible(b);
0932     ui.cbBorderStyle->setVisible(b);
0933     ui.lBorderWidth->setVisible(b);
0934     ui.sbBorderWidth->setVisible(b);
0935     ui.lBorderColor->setVisible(b);
0936     ui.kcbBorderColor->setVisible(b);
0937     ui.lBorderOpacity->setVisible(b);
0938     ui.sbBorderOpacity->setVisible(b);
0939 
0940     if (m_initializing)
0941         return;
0942 
0943     for (auto* label : m_labelsList)
0944         label->setBorderShape(shape);
0945 }
0946 
0947 void LabelWidget::borderStyleChanged(int index) {
0948     if (m_initializing)
0949         return;
0950 
0951     auto penStyle = Qt::PenStyle(index);
0952     QPen pen;
0953     for (auto* label : m_labelsList) {
0954         pen = label->borderPen();
0955         pen.setStyle(penStyle);
0956         label->setBorderPen(pen);
0957     }
0958 }
0959 
0960 void LabelWidget::borderColorChanged(const QColor& color) {
0961     if (m_initializing)
0962         return;
0963 
0964     QPen pen;
0965     for (auto* label : m_labelsList) {
0966         pen = label->borderPen();
0967         pen.setColor(color);
0968         label->setBorderPen(pen);
0969     }
0970 
0971     m_initializing = true;
0972     GuiTools::updatePenStyles(ui.cbBorderStyle, color);
0973     m_initializing = false;
0974 }
0975 
0976 void LabelWidget::borderWidthChanged(double value) {
0977     if (m_initializing)
0978         return;
0979 
0980     QPen pen;
0981     for (auto* label : m_labelsList) {
0982         pen = label->borderPen();
0983         pen.setWidthF( Worksheet::convertToSceneUnits(value, Worksheet::Unit::Point) );
0984         label->setBorderPen(pen);
0985     }
0986 }
0987 
0988 void LabelWidget::borderOpacityChanged(int value) {
0989     if (m_initializing)
0990         return;
0991 
0992     qreal opacity = (float)value/100.;
0993     for (auto* label : m_labelsList)
0994         label->setBorderOpacity(opacity);
0995 }
0996 
0997 //*********************************************************
0998 //****** SLOTs for changes triggered in TextLabel *********
0999 //*********************************************************
1000 void LabelWidget::labelTextWrapperChanged(const TextLabel::TextWrapper& text) {
1001     if (m_initializing)return;
1002     const Lock lock(m_initializing);
1003 
1004     //save and restore the current cursor position after changing the text
1005     QTextCursor cursor = ui.teLabel->textCursor();
1006     int position = cursor.position();
1007     if (text.teXUsed)
1008         ui.teLabel->setText(text.text);
1009     else
1010         ui.teLabel->setHtml(text.text);
1011     cursor.movePosition(QTextCursor::Start);
1012     cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, position);
1013     ui.teLabel->setTextCursor(cursor);
1014 
1015     ui.tbTexUsed->setChecked(text.teXUsed);
1016     this->teXUsedChanged(text.teXUsed);
1017 }
1018 
1019 /*!
1020  * \brief Highlights the text field red if wrong latex syntax was used (null image was produced)
1021  * or something else went wrong during rendering (\sa ExpressionTextEdit::validateExpression())
1022  */
1023 void LabelWidget::labelTeXImageUpdated(bool valid) {
1024     if (!valid) {
1025         if (ui.teLabel->styleSheet().isEmpty())
1026             ui.teLabel->setStyleSheet(QLatin1String("QTextEdit{background: red;}"));
1027     } else
1028         ui.teLabel->setStyleSheet(QString());
1029 }
1030 
1031 void LabelWidget::labelTeXFontChanged(const QFont& font) {
1032     m_initializing = true;
1033     ui.kfontRequesterTeX->setFont(font);
1034     ui.sbFontSize->setValue(font.pointSize());
1035     m_initializing = false;
1036 }
1037 
1038 void LabelWidget::labelFontColorChanged(const QColor color) {
1039     // this function is only called when the theme is changed. Otherwise the color
1040     // is directly in the html text.
1041     // when the theme changes, the hole text should change color regardless of the color it has
1042     m_initializing = true;
1043     ui.kcbFontColor->setColor(color);
1044     ui.teLabel->selectAll();
1045     ui.teLabel->setTextColor(color);
1046     m_initializing = false;
1047 }
1048 
1049 void LabelWidget::labelPositionChanged(const TextLabel::PositionWrapper& position) {
1050     m_initializing = true;
1051     ui.sbPositionX->setValue( Worksheet::convertFromSceneUnits(position.point.x(), m_worksheetUnit) );
1052     ui.sbPositionY->setValue( Worksheet::convertFromSceneUnits(position.point.y(), m_worksheetUnit) );
1053     ui.cbPositionX->setCurrentIndex( static_cast<int>(position.horizontalPosition) );
1054     ui.cbPositionY->setCurrentIndex( static_cast<int>(position.verticalPosition) );
1055     m_initializing = false;
1056 }
1057 
1058 void LabelWidget::labelBackgroundColorChanged(const QColor color) {
1059     m_initializing = true;
1060     ui.kcbBackgroundColor->setColor(color);
1061     m_initializing = false;
1062 }
1063 
1064 void LabelWidget::labelHorizontalAlignmentChanged(TextLabel::HorizontalAlignment index) {
1065     m_initializing = true;
1066     ui.cbHorizontalAlignment->setCurrentIndex(static_cast<int>(index));
1067     m_initializing = false;
1068 }
1069 
1070 void LabelWidget::labelVerticalAlignmentChanged(TextLabel::VerticalAlignment index) {
1071     m_initializing = true;
1072     ui.cbVerticalAlignment->setCurrentIndex(static_cast<int>(index));
1073     m_initializing = false;
1074 }
1075 
1076 void LabelWidget::labelOffsetxChanged(qreal offset) {
1077     m_initializing = true;
1078     ui.sbOffsetX->setValue(Worksheet::convertFromSceneUnits(offset, Worksheet::Unit::Point));
1079     m_initializing = false;
1080 }
1081 
1082 void LabelWidget::labelOffsetyChanged(qreal offset) {
1083     m_initializing = true;
1084     ui.sbOffsetY->setValue(Worksheet::convertFromSceneUnits(offset, Worksheet::Unit::Point));
1085     m_initializing = false;
1086 }
1087 
1088 void LabelWidget::labelRotationAngleChanged(qreal angle) {
1089     m_initializing = true;
1090     ui.sbRotation->setValue(angle);
1091     m_initializing = false;
1092 }
1093 
1094 void LabelWidget::labelVisibleChanged(bool on) {
1095     m_initializing = true;
1096     ui.chbVisible->setChecked(on);
1097     m_initializing = false;
1098 }
1099 
1100 //border
1101 void LabelWidget::labelBorderShapeChanged(TextLabel::BorderShape shape) {
1102     m_initializing = true;
1103     ui.cbBorderShape->setCurrentIndex(static_cast<int>(shape));
1104     m_initializing = false;
1105 }
1106 
1107 void LabelWidget::labelBorderPenChanged(const QPen& pen) {
1108     m_initializing = true;
1109     if (ui.cbBorderStyle->currentIndex() != pen.style())
1110         ui.cbBorderStyle->setCurrentIndex(pen.style());
1111     if (ui.kcbBorderColor->color() != pen.color())
1112         ui.kcbBorderColor->setColor(pen.color());
1113     if (ui.sbBorderWidth->value() != pen.widthF())
1114         ui.sbBorderWidth->setValue(Worksheet::convertFromSceneUnits(pen.widthF(), Worksheet::Unit::Point));
1115     m_initializing = false;
1116 }
1117 
1118 void LabelWidget::labelBorderOpacityChanged(float value) {
1119     m_initializing = true;
1120     float v = (float)value*100.;
1121     ui.sbBorderOpacity->setValue(v);
1122     m_initializing = false;
1123 }
1124 
1125 //**********************************************************
1126 //******************** SETTINGS ****************************
1127 //**********************************************************
1128 void LabelWidget::load() {
1129     if (!m_label)
1130         return;
1131 
1132     m_initializing = true;
1133 
1134     ui.chbVisible->setChecked(m_label->isVisible());
1135 
1136     //Text/TeX
1137     ui.tbTexUsed->setChecked( (bool) m_label->text().teXUsed );
1138     if (m_label->text().teXUsed)
1139         ui.teLabel->setText(m_label->text().text);
1140     else {
1141         ui.teLabel->setHtml(m_label->text().text);
1142         ui.teLabel->selectAll(); // must be done to retrieve font
1143         ui.kfontRequester->setFont(ui.teLabel->currentFont());
1144     }
1145 
1146     // if the text is empty yet, user LabelWidget::fontColor(),
1147     //extract the color from the html formatted text otherwise
1148      if (!m_label->text().text.isEmpty()) {
1149         QTextCharFormat format = ui.teLabel->currentCharFormat();
1150         ui.kcbFontColor->setColor(format.foreground().color());
1151         //ui.kcbBackgroundColor->setColor(format.background().color());
1152      } else
1153         ui.kcbFontColor->setColor(m_label->fontColor());
1154 
1155     //used for latex text only
1156     ui.kcbBackgroundColor->setColor(m_label->backgroundColor());
1157 
1158     this->teXUsedChanged(m_label->text().teXUsed);
1159     ui.kfontRequesterTeX->setFont(m_label->teXFont());
1160     ui.sbFontSize->setValue( m_label->teXFont().pointSize() );
1161 
1162     //move the cursor to the end and set the focus to the text editor
1163     QTextCursor cursor = ui.teLabel->textCursor();
1164     cursor.movePosition(QTextCursor::End);
1165     ui.teLabel->setTextCursor(cursor);
1166     ui.teLabel->setFocus();
1167 
1168     // Geometry
1169     ui.cbPositionX->setCurrentIndex( (int)m_label->position().horizontalPosition );
1170     positionXChanged(ui.cbPositionX->currentIndex());
1171     ui.sbPositionX->setValue( Worksheet::convertFromSceneUnits(m_label->position().point.x(), m_worksheetUnit) );
1172     ui.cbPositionY->setCurrentIndex( (int)m_label->position().verticalPosition );
1173     positionYChanged(ui.cbPositionY->currentIndex());
1174     ui.sbPositionY->setValue( Worksheet::convertFromSceneUnits(m_label->position().point.y(), m_worksheetUnit) );
1175 
1176     if (!m_axesList.isEmpty()) {
1177         ui.sbOffsetX->setValue( Worksheet::convertFromSceneUnits(m_axesList.first()->titleOffsetX(), Worksheet::Unit::Point) );
1178         ui.sbOffsetY->setValue( Worksheet::convertFromSceneUnits(m_axesList.first()->titleOffsetY(), Worksheet::Unit::Point) );
1179     }
1180     ui.cbHorizontalAlignment->setCurrentIndex( (int) m_label->horizontalAlignment() );
1181     ui.cbVerticalAlignment->setCurrentIndex( (int) m_label->verticalAlignment() );
1182     ui.sbRotation->setValue( m_label->rotationAngle() );
1183 
1184     //Border
1185     ui.cbBorderShape->setCurrentIndex(static_cast<int>(m_label->borderShape()));
1186     borderShapeChanged(ui.cbBorderShape->currentIndex());
1187     ui.kcbBorderColor->setColor( m_label->borderPen().color() );
1188     ui.cbBorderStyle->setCurrentIndex( (int) m_label->borderPen().style() );
1189     ui.sbBorderWidth->setValue( Worksheet::convertFromSceneUnits(m_label->borderPen().widthF(), Worksheet::Unit::Point) );
1190     ui.sbBorderOpacity->setValue( round(m_label->borderOpacity()*100) );
1191     GuiTools::updatePenStyles(ui.cbBorderStyle, ui.kcbBorderColor->color());
1192 
1193     m_initializing = false;
1194 }
1195 
1196 void LabelWidget::loadConfig(KConfigGroup& group) {
1197     if (!m_label)
1198         return;
1199 
1200     m_initializing = true;
1201 
1202     //TeX
1203     ui.tbTexUsed->setChecked(group.readEntry("TeXUsed", (bool) m_label->text().teXUsed));
1204     this->teXUsedChanged(m_label->text().teXUsed);
1205     ui.sbFontSize->setValue( group.readEntry("TeXFontSize", m_label->teXFont().pointSize()) );
1206     ui.kfontRequesterTeX->setFont(group.readEntry("TeXFont", m_label->teXFont()));
1207 
1208     // Geometry
1209     ui.cbPositionX->setCurrentIndex( group.readEntry("PositionX", (int) m_label->position().horizontalPosition ) );
1210     ui.sbPositionX->setValue( Worksheet::convertFromSceneUnits(group.readEntry("PositionXValue", m_label->position().point.x()), m_worksheetUnit) );
1211     ui.cbPositionY->setCurrentIndex( group.readEntry("PositionY", (int) m_label->position().verticalPosition ) );
1212     ui.sbPositionY->setValue( Worksheet::convertFromSceneUnits(group.readEntry("PositionYValue", m_label->position().point.y()), m_worksheetUnit) );
1213 
1214     if (!m_axesList.isEmpty()) {
1215         ui.sbOffsetX->setValue( Worksheet::convertFromSceneUnits(group.readEntry("OffsetX", m_axesList.first()->titleOffsetX()), Worksheet::Unit::Point) );
1216         ui.sbOffsetY->setValue( Worksheet::convertFromSceneUnits(group.readEntry("OffsetY", m_axesList.first()->titleOffsetY()), Worksheet::Unit::Point) );
1217     }
1218     ui.cbHorizontalAlignment->setCurrentIndex( group.readEntry("HorizontalAlignment", (int) m_label->horizontalAlignment()) );
1219     ui.cbVerticalAlignment->setCurrentIndex( group.readEntry("VerticalAlignment", (int) m_label->verticalAlignment()) );
1220     ui.sbRotation->setValue( group.readEntry("Rotation", m_label->rotationAngle()) );
1221 
1222     //Border
1223     ui.cbBorderShape->setCurrentIndex(group.readEntry("BorderShape").toInt());
1224     ui.kcbBorderColor->setColor( group.readEntry("BorderColor", m_label->borderPen().color()) );
1225     ui.cbBorderStyle->setCurrentIndex( group.readEntry("BorderStyle", (int)m_label->borderPen().style()) );
1226     ui.sbBorderWidth->setValue( Worksheet::convertFromSceneUnits(group.readEntry("BorderWidth", m_label->borderPen().widthF()), Worksheet::Unit::Point) );
1227     ui.sbBorderOpacity->setValue( group.readEntry("BorderOpacity", m_label->borderOpacity())*100 );
1228     m_initializing = false;
1229 }
1230 
1231 void LabelWidget::saveConfig(KConfigGroup& group) {
1232     //TeX
1233     group.writeEntry("TeXUsed", ui.tbTexUsed->isChecked());
1234     group.writeEntry("TeXFontColor", ui.kcbFontColor->color());
1235     group.writeEntry("TeXBackgroundColor", ui.kcbBackgroundColor->color());
1236     group.writeEntry("TeXFont", ui.kfontRequesterTeX->font());
1237 
1238     // Geometry
1239     group.writeEntry("PositionX", ui.cbPositionX->currentIndex());
1240     group.writeEntry("PositionXValue", Worksheet::convertToSceneUnits(ui.sbPositionX->value(),m_worksheetUnit) );
1241     group.writeEntry("PositionY", ui.cbPositionY->currentIndex());
1242     group.writeEntry("PositionYValue",  Worksheet::convertToSceneUnits(ui.sbPositionY->value(),m_worksheetUnit) );
1243 
1244     if (!m_axesList.isEmpty()) {
1245         group.writeEntry("OffsetX",  Worksheet::convertToSceneUnits(ui.sbOffsetX->value(), Worksheet::Unit::Point) );
1246         group.writeEntry("OffsetY",  Worksheet::convertToSceneUnits(ui.sbOffsetY->value(), Worksheet::Unit::Point) );
1247     }
1248     group.writeEntry("HorizontalAlignment", ui.cbHorizontalAlignment->currentIndex());
1249     group.writeEntry("VerticalAlignment", ui.cbVerticalAlignment->currentIndex());
1250     group.writeEntry("Rotation", ui.sbRotation->value());
1251 
1252     //Border
1253     group.writeEntry("BorderShape", ui.cbBorderShape->currentIndex());
1254     group.writeEntry("BorderStyle", ui.cbBorderStyle->currentIndex());
1255     group.writeEntry("BorderColor", ui.kcbBorderColor->color());
1256     group.writeEntry("BorderWidth", Worksheet::convertToSceneUnits(ui.sbBorderWidth->value(), Worksheet::Unit::Point));
1257     group.writeEntry("BorderOpacity", ui.sbBorderOpacity->value()/100.0);
1258 }