File indexing completed on 2024-05-12 03:48:18

0001 /*
0002     File                 : Background.cpp
0003     Project              : LabPlot
0004     Description          : Background
0005     --------------------------------------------------------------------
0006     SPDX-FileCopyrightText: 2022 Alexander Semke <alexander.semke@web.de>
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 
0010 /*!
0011   \class Background
0012   \brief This class contains the background properties of worksheet elements like worksheet background,
0013   plot background, the area filling in XYCurve, Histogram, etc.
0014 
0015   \ingroup worksheet
0016 */
0017 
0018 #include "Background.h"
0019 #include "BackgroundPrivate.h"
0020 #include "backend/lib/XmlStreamReader.h"
0021 #include "backend/lib/commandtemplates.h"
0022 
0023 #include <KConfigGroup>
0024 #include <KLocalizedString>
0025 
0026 Background::Background(const QString& name)
0027     : AbstractAspect(name, AspectType::AbstractAspect)
0028     , d_ptr(new BackgroundPrivate(this)) {
0029 }
0030 
0031 Background::~Background() {
0032     delete d_ptr;
0033 }
0034 
0035 void Background::setPrefix(const QString& prefix) {
0036     Q_D(Background);
0037     d->prefix = prefix;
0038 }
0039 
0040 const QString& Background::prefix() const {
0041     Q_D(const Background);
0042     return d->prefix;
0043 }
0044 
0045 void Background::init(const KConfigGroup& group) {
0046     Q_D(Background);
0047 
0048     d->type = (Type)group.readEntry(d->prefix + QStringLiteral("Type"), static_cast<int>(Type::Color));
0049     d->colorStyle = (ColorStyle)group.readEntry(d->prefix + QStringLiteral("ColorStyle"), static_cast<int>(ColorStyle::SingleColor));
0050     d->imageStyle = (ImageStyle)group.readEntry(d->prefix + QStringLiteral("ImageStyle"), static_cast<int>(ImageStyle::Scaled));
0051     d->brushStyle = (Qt::BrushStyle)group.readEntry(d->prefix + QStringLiteral("BrushStyle"), static_cast<int>(Qt::SolidPattern));
0052     d->fileName = group.readEntry(d->prefix + QStringLiteral("FileName"), QString());
0053     d->firstColor = group.readEntry(d->prefix + QStringLiteral("FirstColor"), QColor(Qt::white));
0054     d->secondColor = group.readEntry(d->prefix + QStringLiteral("SecondColor"), QColor(Qt::black));
0055 
0056     double defaultOpacity = 1.0;
0057     auto type = parentAspect()->type();
0058     if (type == AspectType::Histogram || type == AspectType::BoxPlot)
0059         defaultOpacity = 0.5;
0060     d->opacity = group.readEntry(d->prefix + QStringLiteral("Opacity"), defaultOpacity);
0061 
0062     // optional parameters
0063     if (d->enabledAvailable)
0064         d->enabled = group.readEntry(d->prefix + QStringLiteral("Enabled"), true);
0065 
0066     if (d->positionAvailable)
0067         d->position = (Position)group.readEntry(d->prefix + QStringLiteral("Position"), static_cast<int>(Position::No));
0068 }
0069 
0070 // ##############################################################################
0071 // ##########################  getter methods  ##################################
0072 // ##############################################################################
0073 BASIC_SHARED_D_READER_IMPL(Background, bool, enabledAvailable, enabledAvailable)
0074 BASIC_SHARED_D_READER_IMPL(Background, bool, positionAvailable, positionAvailable)
0075 
0076 BASIC_SHARED_D_READER_IMPL(Background, bool, enabled, enabled)
0077 BASIC_SHARED_D_READER_IMPL(Background, Background::Position, position, position)
0078 BASIC_SHARED_D_READER_IMPL(Background, Background::Type, type, type)
0079 BASIC_SHARED_D_READER_IMPL(Background, Background::ColorStyle, colorStyle, colorStyle)
0080 BASIC_SHARED_D_READER_IMPL(Background, Background::ImageStyle, imageStyle, imageStyle)
0081 BASIC_SHARED_D_READER_IMPL(Background, Qt::BrushStyle, brushStyle, brushStyle)
0082 BASIC_SHARED_D_READER_IMPL(Background, QColor, firstColor, firstColor)
0083 BASIC_SHARED_D_READER_IMPL(Background, QColor, secondColor, secondColor)
0084 BASIC_SHARED_D_READER_IMPL(Background, QString, fileName, fileName)
0085 BASIC_SHARED_D_READER_IMPL(Background, double, opacity, opacity)
0086 
0087 // ##############################################################################
0088 // #################  setter methods and undo commands ##########################
0089 // ##############################################################################
0090 void Background::setEnabledAvailable(bool available) {
0091     Q_D(Background);
0092     d->enabledAvailable = available;
0093 }
0094 
0095 void Background::setPositionAvailable(bool available) {
0096     Q_D(Background);
0097     d->positionAvailable = available;
0098 }
0099 
0100 STD_SETTER_CMD_IMPL_F_S(Background, SetEnabled, bool, enabled, update)
0101 void Background::setEnabled(bool enabled) {
0102     Q_D(Background);
0103     if (enabled != d->enabled)
0104         exec(new BackgroundSetEnabledCmd(d, enabled, ki18n("%1: filling changed")));
0105 }
0106 
0107 STD_SETTER_CMD_IMPL_F_S(Background, SetPosition, Background::Position, position, updatePosition)
0108 void Background::setPosition(Position position) {
0109     Q_D(Background);
0110     if (position != d->position)
0111         exec(new BackgroundSetPositionCmd(d, position, ki18n("%1: filling position changed")));
0112 }
0113 
0114 STD_SETTER_CMD_IMPL_F_S(Background, SetType, Background::Type, type, update)
0115 void Background::setType(Background::Type type) {
0116     Q_D(Background);
0117     if (type != d->type)
0118         exec(new BackgroundSetTypeCmd(d, type, ki18n("%1: background type changed")));
0119 }
0120 
0121 STD_SETTER_CMD_IMPL_F_S(Background, SetColorStyle, Background::ColorStyle, colorStyle, update)
0122 void Background::setColorStyle(Background::ColorStyle style) {
0123     Q_D(Background);
0124     if (style != d->colorStyle)
0125         exec(new BackgroundSetColorStyleCmd(d, style, ki18n("%1: background color style changed")));
0126 }
0127 
0128 STD_SETTER_CMD_IMPL_F_S(Background, SetImageStyle, Background::ImageStyle, imageStyle, update)
0129 void Background::setImageStyle(Background::ImageStyle style) {
0130     Q_D(Background);
0131     if (style != d->imageStyle)
0132         exec(new BackgroundSetImageStyleCmd(d, style, ki18n("%1: background image style changed")));
0133 }
0134 
0135 STD_SETTER_CMD_IMPL_F_S(Background, SetBrushStyle, Qt::BrushStyle, brushStyle, update)
0136 void Background::setBrushStyle(Qt::BrushStyle style) {
0137     Q_D(Background);
0138     if (style != d->brushStyle)
0139         exec(new BackgroundSetBrushStyleCmd(d, style, ki18n("%1: background brush style changed")));
0140 }
0141 
0142 STD_SETTER_CMD_IMPL_F_S(Background, SetFirstColor, QColor, firstColor, update)
0143 void Background::setFirstColor(const QColor& color) {
0144     Q_D(Background);
0145     if (color != d->firstColor)
0146         exec(new BackgroundSetFirstColorCmd(d, color, ki18n("%1: set background first color")));
0147 }
0148 
0149 STD_SETTER_CMD_IMPL_F_S(Background, SetSecondColor, QColor, secondColor, update)
0150 void Background::setSecondColor(const QColor& color) {
0151     Q_D(Background);
0152     if (color != d->secondColor)
0153         exec(new BackgroundSetSecondColorCmd(d, color, ki18n("%1: set background second color")));
0154 }
0155 
0156 STD_SETTER_CMD_IMPL_F_S(Background, SetFileName, QString, fileName, update)
0157 void Background::setFileName(const QString& fileName) {
0158     Q_D(Background);
0159     if (fileName != d->fileName)
0160         exec(new BackgroundSetFileNameCmd(d, fileName, ki18n("%1: set background image")));
0161 }
0162 
0163 STD_SETTER_CMD_IMPL_F_S(Background, SetOpacity, double, opacity, update)
0164 void Background::setOpacity(double opacity) {
0165     Q_D(Background);
0166     if (opacity != d->opacity)
0167         exec(new BackgroundSetOpacityCmd(d, opacity, ki18n("%1: set background opacity")));
0168 }
0169 
0170 // ##############################################################################
0171 // ####################### Private implementation ###############################
0172 // ##############################################################################
0173 BackgroundPrivate::BackgroundPrivate(Background* owner)
0174     : q(owner) {
0175 }
0176 
0177 QString BackgroundPrivate::name() const {
0178     return q->parentAspect()->name();
0179 }
0180 
0181 void BackgroundPrivate::update() {
0182     Q_EMIT q->updateRequested();
0183 }
0184 
0185 void BackgroundPrivate::updatePosition() {
0186     Q_EMIT q->updatePositionRequested();
0187 }
0188 
0189 // ##############################################################################
0190 // ##################  Serialization/Deserialization  ###########################
0191 // ##############################################################################
0192 //! Save as XML
0193 void Background::save(QXmlStreamWriter* writer) const {
0194     Q_D(const Background);
0195 
0196     writer->writeStartElement(d->prefix.toLower());
0197     if (d->enabledAvailable)
0198         writer->writeAttribute(QStringLiteral("enabled"), QString::number(d->enabled));
0199 
0200     if (d->positionAvailable)
0201         writer->writeAttribute(QStringLiteral("position"), QString::number(static_cast<int>(d->position)));
0202 
0203     writer->writeAttribute(QStringLiteral("type"), QString::number(static_cast<int>(d->type)));
0204     writer->writeAttribute(QStringLiteral("colorStyle"), QString::number(static_cast<int>(d->colorStyle)));
0205     writer->writeAttribute(QStringLiteral("imageStyle"), QString::number(static_cast<int>(d->imageStyle)));
0206     writer->writeAttribute(QStringLiteral("brushStyle"), QString::number(d->brushStyle));
0207     writer->writeAttribute(QStringLiteral("firstColor_r"), QString::number(d->firstColor.red()));
0208     writer->writeAttribute(QStringLiteral("firstColor_g"), QString::number(d->firstColor.green()));
0209     writer->writeAttribute(QStringLiteral("firstColor_b"), QString::number(d->firstColor.blue()));
0210     writer->writeAttribute(QStringLiteral("secondColor_r"), QString::number(d->secondColor.red()));
0211     writer->writeAttribute(QStringLiteral("secondColor_g"), QString::number(d->secondColor.green()));
0212     writer->writeAttribute(QStringLiteral("secondColor_b"), QString::number(d->secondColor.blue()));
0213     writer->writeAttribute(QStringLiteral("fileName"), d->fileName);
0214     writer->writeAttribute(QStringLiteral("opacity"), QString::number(d->opacity));
0215     writer->writeEndElement();
0216 }
0217 
0218 //! Load from XML
0219 bool Background::load(XmlStreamReader* reader, bool preview) {
0220     if (preview)
0221         return true;
0222 
0223     Q_D(Background);
0224     QString str;
0225 
0226     auto attribs = reader->attributes();
0227 
0228     if (d->enabledAvailable)
0229         READ_INT_VALUE("enabled", enabled, bool);
0230 
0231     if (d->positionAvailable)
0232         READ_INT_VALUE("position", position, Position);
0233 
0234     READ_INT_VALUE("type", type, Background::Type);
0235     READ_INT_VALUE("colorStyle", colorStyle, Background::ColorStyle);
0236     READ_INT_VALUE("imageStyle", imageStyle, Background::ImageStyle);
0237     READ_INT_VALUE("brushStyle", brushStyle, Qt::BrushStyle);
0238 
0239     str = attribs.value(QStringLiteral("firstColor_r")).toString();
0240     if (str.isEmpty())
0241         reader->raiseMissingAttributeWarning(QStringLiteral("firstColor_r"));
0242     else
0243         d->firstColor.setRed(str.toInt());
0244 
0245     str = attribs.value(QStringLiteral("firstColor_g")).toString();
0246     if (str.isEmpty())
0247         reader->raiseMissingAttributeWarning(QStringLiteral("firstColor_g"));
0248     else
0249         d->firstColor.setGreen(str.toInt());
0250 
0251     str = attribs.value(QStringLiteral("firstColor_b")).toString();
0252     if (str.isEmpty())
0253         reader->raiseMissingAttributeWarning(QStringLiteral("firstColor_b"));
0254     else
0255         d->firstColor.setBlue(str.toInt());
0256 
0257     str = attribs.value(QStringLiteral("secondColor_r")).toString();
0258     if (str.isEmpty())
0259         reader->raiseMissingAttributeWarning(QStringLiteral("secondColor_r"));
0260     else
0261         d->secondColor.setRed(str.toInt());
0262 
0263     str = attribs.value(QStringLiteral("secondColor_g")).toString();
0264     if (str.isEmpty())
0265         reader->raiseMissingAttributeWarning(QStringLiteral("secondColor_g"));
0266     else
0267         d->secondColor.setGreen(str.toInt());
0268 
0269     str = attribs.value(QStringLiteral("secondColor_b")).toString();
0270     if (str.isEmpty())
0271         reader->raiseMissingAttributeWarning(QStringLiteral("secondColor_b"));
0272     else
0273         d->secondColor.setBlue(str.toInt());
0274 
0275     str = attribs.value(QStringLiteral("fileName")).toString();
0276     d->fileName = str;
0277 
0278     READ_DOUBLE_VALUE("opacity", opacity);
0279 
0280     return true;
0281 }
0282 
0283 // ##############################################################################
0284 // #########################  Theme management ##################################
0285 // ##############################################################################
0286 void Background::loadThemeConfig(const KConfigGroup& group) {
0287     Q_D(const Background);
0288     const QColor themeColor = group.readEntry(d->prefix + QStringLiteral("FirstColor"), QColor(Qt::white));
0289     loadThemeConfig(group, themeColor);
0290 }
0291 
0292 void Background::loadThemeConfig(const KConfigGroup& group, const QColor& themeColor) {
0293     Q_D(const Background);
0294 
0295     if (d->positionAvailable)
0296         setPosition((Position)group.readEntry(d->prefix + QStringLiteral("Position"), static_cast<int>(Position::No)));
0297 
0298     setType((Type)group.readEntry(d->prefix + QStringLiteral("Type"), static_cast<int>(Type::Color)));
0299     setColorStyle((ColorStyle)group.readEntry(d->prefix + QStringLiteral("ColorStyle"), static_cast<int>(ColorStyle::SingleColor)));
0300     setImageStyle((ImageStyle)group.readEntry(d->prefix + QStringLiteral("ImageStyle"), static_cast<int>(ImageStyle::Scaled)));
0301     setBrushStyle((Qt::BrushStyle)group.readEntry(d->prefix + QStringLiteral("BrushStyle"), static_cast<int>(Qt::SolidPattern)));
0302     setFirstColor(themeColor);
0303     setSecondColor(group.readEntry(d->prefix + QStringLiteral("SecondColor"), QColor(Qt::black)));
0304 
0305     double defaultOpacity = 1.0;
0306     auto type = parentAspect()->type();
0307     if (type == AspectType::Histogram || type == AspectType::BoxPlot || type == AspectType::BarPlot)
0308         defaultOpacity = 0.8;
0309     setOpacity(group.readEntry(d->prefix + QStringLiteral("Opacity"), defaultOpacity));
0310 }
0311 
0312 void Background::saveThemeConfig(KConfigGroup& group) const {
0313     Q_D(const Background);
0314 
0315     if (d->positionAvailable)
0316         group.writeEntry(d->prefix + QStringLiteral("Position"), static_cast<int>(d->position));
0317 
0318     group.writeEntry(d->prefix + QStringLiteral("Type"), static_cast<int>(d->type));
0319     group.writeEntry(d->prefix + QStringLiteral("ColorStyle"), static_cast<int>(d->colorStyle));
0320     group.writeEntry(d->prefix + QStringLiteral("BrushStyle"), static_cast<int>(d->brushStyle));
0321     group.writeEntry(d->prefix + QStringLiteral("ImageStyle"), static_cast<int>(d->imageStyle));
0322     group.writeEntry(d->prefix + QStringLiteral("FirstColor"), d->firstColor);
0323     group.writeEntry(d->prefix + QStringLiteral("SecondColor"), d->secondColor);
0324     group.writeEntry(d->prefix + QStringLiteral("Opacity"), d->opacity);
0325 }