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 }