/* SPDX-FileCopyrightText: 2016 Volker Krause SPDX-FileCopyrightText: 2020 Jonathan Poelen SPDX-License-Identifier: MIT */ #include "format.h" #include "definition.h" #include "format_p.h" #include "textstyledata_p.h" #include "themedata_p.h" #include "xml_p.h" #include #include #include using namespace KSyntaxHighlighting; static Theme::TextStyle stringToDefaultFormat(QStringView str) { if (!str.startsWith(QLatin1String("ds"))) { return Theme::Normal; } const auto metaEnum = QMetaEnum::fromType(); bool ok = false; const auto value = metaEnum.keyToValue(str.sliced(2).toLatin1().constData(), &ok); if (!ok || value < 0) { return Theme::Normal; } return static_cast(value); } FormatPrivate *FormatPrivate::detachAndGet(Format &format) { format.d.detach(); return format.d.data(); } TextStyleData FormatPrivate::styleOverride(const Theme &theme) const { return ThemeData::get(theme)->textStyleOverride(definitionName, name); } QColor FormatPrivate::color(const Theme &theme, StyleColor styleColor, ThemeColor themeColor) const { const auto overrideStyle = styleOverride(theme); if (overrideStyle.*styleColor) { return QColor::fromRgb(overrideStyle.*styleColor); } // use QColor::fromRgba for QRgb => QColor conversion to avoid unset colors == black! return QColor::fromRgba(style.*styleColor ? style.*styleColor : (theme.*themeColor)(defaultStyle)); } bool FormatPrivate::hasColor(const Theme &theme, StyleColor styleColor, ThemeColor themeColor) const { // use QColor::fromRgba for background QRgb => QColor conversion to avoid unset colors == black! return color(theme, styleColor, themeColor) != QColor::fromRgba((theme.*themeColor)(Theme::Normal)) && (style.*styleColor || (theme.*themeColor)(defaultStyle) || styleOverride(theme).*styleColor); } static QExplicitlySharedDataPointer &sharedDefaultPrivate() { static QExplicitlySharedDataPointer def(new FormatPrivate); return def; } Format::Format() : d(sharedDefaultPrivate()) { } Format::Format(const Format &other) : d(other.d) { } Format::~Format() { } Format &Format::operator=(const Format &other) { d = other.d; return *this; } bool Format::isValid() const { return !d->name.isEmpty(); } QString Format::name() const { return d->name; } int Format::id() const { return d->id; } Theme::TextStyle Format::textStyle() const { return d->defaultStyle; } bool Format::isDefaultTextStyle(const Theme &theme) const { // use QColor::fromRgba for background QRgb => QColor conversion to avoid unset colors == black! return (!hasTextColor(theme)) && (!hasBackgroundColor(theme)) && (selectedTextColor(theme).rgba() == theme.selectedTextColor(Theme::Normal)) && (selectedBackgroundColor(theme).rgba() == (theme.selectedBackgroundColor(Theme::Normal))) && (isBold(theme) == theme.isBold(Theme::Normal)) && (isItalic(theme) == theme.isItalic(Theme::Normal)) && (isUnderline(theme) == theme.isUnderline(Theme::Normal)) && (isStrikeThrough(theme) == theme.isStrikeThrough(Theme::Normal)); } bool Format::hasTextColor(const Theme &theme) const { return d->hasColor(theme, &TextStyleData::textColor, &Theme::textColor); } QColor Format::textColor(const Theme &theme) const { return d->color(theme, &TextStyleData::textColor, &Theme::textColor); } QColor Format::selectedTextColor(const Theme &theme) const { return d->color(theme, &TextStyleData::selectedTextColor, &Theme::selectedTextColor); } bool Format::hasBackgroundColor(const Theme &theme) const { return d->hasColor(theme, &TextStyleData::backgroundColor, &Theme::backgroundColor); } QColor Format::backgroundColor(const Theme &theme) const { return d->color(theme, &TextStyleData::backgroundColor, &Theme::backgroundColor); } QColor Format::selectedBackgroundColor(const Theme &theme) const { return d->color(theme, &TextStyleData::selectedBackgroundColor, &Theme::selectedBackgroundColor); } bool Format::isBold(const Theme &theme) const { const auto overrideStyle = d->styleOverride(theme); if (overrideStyle.hasBold) { return overrideStyle.bold; } return d->style.hasBold ? d->style.bold : theme.isBold(d->defaultStyle); } bool Format::isItalic(const Theme &theme) const { const auto overrideStyle = d->styleOverride(theme); if (overrideStyle.hasItalic) { return overrideStyle.italic; } return d->style.hasItalic ? d->style.italic : theme.isItalic(d->defaultStyle); } bool Format::isUnderline(const Theme &theme) const { const auto overrideStyle = d->styleOverride(theme); if (overrideStyle.hasUnderline) { return overrideStyle.underline; } return d->style.hasUnderline ? d->style.underline : theme.isUnderline(d->defaultStyle); } bool Format::isStrikeThrough(const Theme &theme) const { const auto overrideStyle = d->styleOverride(theme); if (overrideStyle.hasStrikeThrough) { return overrideStyle.strikeThrough; } return d->style.hasStrikeThrough ? d->style.strikeThrough : theme.isStrikeThrough(d->defaultStyle); } bool Format::spellCheck() const { return d->spellCheck; } bool Format::hasBoldOverride() const { return d->style.hasBold; } bool Format::hasItalicOverride() const { return d->style.hasItalic; } bool Format::hasUnderlineOverride() const { return d->style.hasUnderline; } bool Format::hasStrikeThroughOverride() const { return d->style.hasStrikeThrough; } bool Format::hasTextColorOverride() const { return d->style.textColor; } bool Format::hasBackgroundColorOverride() const { return d->style.backgroundColor; } bool Format::hasSelectedTextColorOverride() const { return d->style.selectedTextColor; } bool Format::hasSelectedBackgroundColorOverride() const { return d->style.selectedBackgroundColor; } void FormatPrivate::load(QXmlStreamReader &reader) { name = reader.attributes().value(QLatin1String("name")).toString(); defaultStyle = stringToDefaultFormat(reader.attributes().value(QLatin1String("defStyleNum"))); QStringView attribute = reader.attributes().value(QLatin1String("color")); if (!attribute.isEmpty()) { style.textColor = QColor(attribute).rgba(); } attribute = reader.attributes().value(QLatin1String("selColor")); if (!attribute.isEmpty()) { style.selectedTextColor = QColor(attribute).rgba(); } attribute = reader.attributes().value(QLatin1String("backgroundColor")); if (!attribute.isEmpty()) { style.backgroundColor = QColor(attribute).rgba(); } attribute = reader.attributes().value(QLatin1String("selBackgroundColor")); if (!attribute.isEmpty()) { style.selectedBackgroundColor = QColor(attribute).rgba(); } attribute = reader.attributes().value(QLatin1String("italic")); if (!attribute.isEmpty()) { style.hasItalic = true; style.italic = Xml::attrToBool(attribute); } attribute = reader.attributes().value(QLatin1String("bold")); if (!attribute.isEmpty()) { style.hasBold = true; style.bold = Xml::attrToBool(attribute); } attribute = reader.attributes().value(QLatin1String("underline")); if (!attribute.isEmpty()) { style.hasUnderline = true; style.underline = Xml::attrToBool(attribute); } attribute = reader.attributes().value(QLatin1String("strikeOut")); if (!attribute.isEmpty()) { style.hasStrikeThrough = true; style.strikeThrough = Xml::attrToBool(attribute); } attribute = reader.attributes().value(QLatin1String("spellChecking")); if (!attribute.isEmpty()) { spellCheck = Xml::attrToBool(attribute); } }