Commit e24eb979 authored by Marco Bubke's avatar Marco Bubke

TextEditor: Relative colors

We introduce relative colors to make it possible to change for
example the color of a declaration slightly.

Change-Id: I8c1991a8907207d3616be954504c68ea18c6deb1
Reviewed-by: David Schulz's avatarDavid Schulz <david.schulz@qt.io>
parent cbcc5566
......@@ -58,6 +58,26 @@ void Format::setBackground(const QColor &background)
m_background = background;
}
void Format::setRelativeForegroundSaturation(double relativeForegroundSaturation)
{
m_relativeForegroundSaturation = relativeForegroundSaturation;
}
void Format::setRelativeForegroundLightness(double relativeForegroundLightness)
{
m_relativeForegroundLightness = relativeForegroundLightness;
}
void Format::setRelativeBackgroundSaturation(double relativeBackgroundSaturation)
{
m_relativeBackgroundSaturation = relativeBackgroundSaturation;
}
void Format::setRelativeBackgroundLightness(double relativeBackgroundLightness)
{
m_relativeBackgroundLightness = relativeBackgroundLightness;
}
void Format::setBold(bool bold)
{
m_bold = bold;
......@@ -138,7 +158,13 @@ bool Format::equals(const Format &other) const
&& m_underlineColor == other.m_underlineColor
&& m_underlineStyle == other.m_underlineStyle
&& m_bold == other.m_bold
&& m_italic == other.m_italic;
&& m_italic == other.m_italic
&& qFuzzyCompare(m_relativeForegroundSaturation, other.m_relativeForegroundSaturation)
&& qFuzzyCompare(m_relativeForegroundLightness, other.m_relativeForegroundLightness)
&& qFuzzyCompare(m_relativeBackgroundSaturation, other.m_relativeBackgroundSaturation)
&& qFuzzyCompare(m_relativeBackgroundLightness, other.m_relativeBackgroundLightness)
;
}
QString Format::toString() const
......@@ -148,7 +174,11 @@ QString Format::toString() const
m_bold ? QLatin1String(trueString) : QLatin1String(falseString),
m_italic ? QLatin1String(trueString) : QLatin1String(falseString),
m_underlineColor.name(),
underlineStyleToString(m_underlineStyle)});
underlineStyleToString(m_underlineStyle),
QString::number(m_relativeForegroundSaturation),
QString::number(m_relativeForegroundLightness),
QString::number(m_relativeBackgroundSaturation),
QString::number(m_relativeBackgroundLightness)});
return text.join(QLatin1Char(';'));
}
......@@ -158,15 +188,23 @@ bool Format::fromString(const QString &str)
*this = Format();
const QStringList lst = str.split(QLatin1Char(';'));
if (lst.count() != 4 && lst.count() != 6)
if (lst.size() != 4 && lst.size() != 6 && lst.size() != 10)
return false;
m_foreground = stringToColor(lst.at(0));
m_background = stringToColor(lst.at(1));
m_bold = lst.at(2) == QLatin1String(trueString);
m_italic = lst.at(3) == QLatin1String(trueString);
m_underlineColor = stringToColor(lst.at(4));
m_underlineStyle = stringToUnderlineStyle(lst.at(5));
if (lst.size() > 4) {
m_underlineColor = stringToColor(lst.at(4));
m_underlineStyle = stringToUnderlineStyle(lst.at(5));
}
if (lst.size() > 6) {
m_relativeForegroundSaturation = lst.at(6).toDouble();
m_relativeForegroundLightness = lst.at(7).toDouble();
m_relativeBackgroundSaturation = lst.at(8).toDouble();
m_relativeBackgroundLightness = lst.at(9).toDouble();
}
return true;
}
......@@ -230,6 +268,14 @@ bool ColorScheme::save(const QString &fileName, QWidget *parent) const
w.writeAttribute(QStringLiteral("underlineColor"), format.underlineColor().name().toLower());
if (format.underlineStyle() != QTextCharFormat::NoUnderline)
w.writeAttribute(QLatin1String("underlineStyle"), underlineStyleToString(format.underlineStyle()));
if (!qFuzzyIsNull(format.relativeForegroundSaturation()))
w.writeAttribute(QLatin1String("relativeForegroundSaturation"), QString::number(format.relativeForegroundSaturation()));
if (!qFuzzyIsNull(format.relativeForegroundLightness()))
w.writeAttribute(QLatin1String("relativeForegroundLightness"), QString::number(format.relativeForegroundLightness()));
if (!qFuzzyIsNull(format.relativeBackgroundSaturation()))
w.writeAttribute(QLatin1String("relativeBackgroundSaturation"), QString::number(format.relativeBackgroundSaturation()));
if (!qFuzzyIsNull(format.relativeBackgroundLightness()))
w.writeAttribute(QLatin1String("relativeBackgroundLightness"), QString::number(format.relativeBackgroundLightness()));
w.writeEndElement();
}
......@@ -339,6 +385,10 @@ void ColorSchemeReader::readStyle()
bool italic = attr.value(QLatin1String("italic")) == QLatin1String(trueString);
QString underlineColor = attr.value(QLatin1String("underlineColor")).toString();
QString underlineStyle = attr.value(QLatin1String("underlineStyle")).toString();
double relativeForegroundSaturation = attr.value(QLatin1String("relativeForegroundSaturation")).toDouble();
double relativeForegroundLightness = attr.value(QLatin1String("relativeForegroundLightness")).toDouble();
double relativeBackgroundSaturation = attr.value(QLatin1String("relativeBackgroundSaturation")).toDouble();
double relativeBackgroundLightness = attr.value(QLatin1String("relativeBackgroundLightness")).toDouble();
Format format;
......@@ -362,6 +412,11 @@ void ColorSchemeReader::readStyle()
format.setUnderlineStyle(stringToUnderlineStyle(underlineStyle));
format.setRelativeForegroundSaturation(relativeForegroundSaturation);
format.setRelativeForegroundLightness(relativeForegroundLightness);
format.setRelativeBackgroundSaturation(relativeBackgroundSaturation);
format.setRelativeBackgroundLightness(relativeBackgroundLightness);
m_scheme->setFormatFor(Constants::styleFromName(name), format);
skipCurrentElement();
......
......@@ -52,6 +52,18 @@ public:
QColor background() const { return m_background; }
void setBackground(const QColor &background);
double relativeForegroundSaturation() const { return m_relativeForegroundSaturation; }
void setRelativeForegroundSaturation(double relativeForegroundSaturation);
double relativeForegroundLightness() const { return m_relativeForegroundLightness; }
void setRelativeForegroundLightness(double relativeForegroundLightness);
double relativeBackgroundSaturation() const { return m_relativeBackgroundSaturation; }
void setRelativeBackgroundSaturation(double relativeBackgroundSaturation);
double relativeBackgroundLightness() const { return m_relativeBackgroundLightness; }
void setRelativeBackgroundLightness(double relativeBackgroundLightness);
bool bold() const { return m_bold; }
void setBold(bool bold);
......@@ -73,6 +85,10 @@ private:
QColor m_foreground = Qt::black;
QColor m_background = Qt::white;
QColor m_underlineColor;
double m_relativeForegroundSaturation = 0.0;
double m_relativeForegroundLightness = 0.0;
double m_relativeBackgroundSaturation = 0.0;
double m_relativeBackgroundLightness = 0.0;
QTextCharFormat::UnderlineStyle m_underlineStyle = QTextCharFormat::NoUnderline;
bool m_bold = false;
bool m_italic = false;
......
......@@ -166,6 +166,14 @@ ColorSchemeEdit::ColorSchemeEdit(QWidget *parent) :
this, &ColorSchemeEdit::eraseBackColor);
connect(m_ui->eraseForegroundToolButton, &QAbstractButton::clicked,
this, &ColorSchemeEdit::eraseForeColor);
connect(m_ui->foregroundSaturationSpinBox, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
this, &ColorSchemeEdit::changeRelativeForeColor);
connect(m_ui->foregroundLightnessSpinBox, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
this, &ColorSchemeEdit::changeRelativeForeColor);
connect(m_ui->backgroundSaturationSpinBox, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
this, &ColorSchemeEdit::changeRelativeBackColor);
connect(m_ui->backgroundLightnessSpinBox, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
this, &ColorSchemeEdit::changeRelativeBackColor);
connect(m_ui->boldCheckBox, &QAbstractButton::toggled,
this, &ColorSchemeEdit::checkCheckBoxes);
connect(m_ui->italicCheckBox, &QAbstractButton::toggled,
......@@ -211,6 +219,16 @@ void ColorSchemeEdit::setReadOnly(bool readOnly)
m_ui->backgroundToolButton->setEnabled(enabled);
m_ui->eraseBackgroundToolButton->setEnabled(enabled);
m_ui->eraseForegroundToolButton->setEnabled(enabled);
m_ui->relativeForegroundLabel->setEnabled(enabled);
m_ui->foregroundSaturationLabel->setEnabled(enabled);
m_ui->foregroundLightnessLabel->setEnabled(enabled);
m_ui->foregroundSaturationSpinBox->setEnabled(enabled);
m_ui->foregroundLightnessSpinBox->setEnabled(enabled);
m_ui->relativeBackgroundLabel->setEnabled(enabled);
m_ui->backgroundSaturationLabel->setEnabled(enabled);
m_ui->backgroundLightnessLabel->setEnabled(enabled);
m_ui->backgroundSaturationSpinBox->setEnabled(enabled);
m_ui->backgroundLightnessSpinBox->setEnabled(enabled);
m_ui->boldCheckBox->setEnabled(enabled);
m_ui->italicCheckBox->setEnabled(enabled);
m_ui->underlineColorToolButton->setEnabled(enabled);
......@@ -244,6 +262,8 @@ void ColorSchemeEdit::updateControls()
{
updateForegroundControls();
updateBackgroundControls();
updateRelativeForegroundControls();
updateRelativeBackgroundControls();
updateFontControls();
updateUnderlineControls();
}
......@@ -282,6 +302,46 @@ void ColorSchemeEdit::updateBackgroundControls()
&& format.background().isValid());
}
void ColorSchemeEdit::updateRelativeForegroundControls()
{
const auto &formatDescription = m_descriptions[m_curItem];
const Format &format = m_scheme.formatFor(formatDescription.id());
QSignalBlocker saturationSignalBlocker(m_ui->foregroundSaturationSpinBox);
QSignalBlocker lightnessSignalBlocker(m_ui->foregroundLightnessSpinBox);
bool isVisible = formatDescription.showControl(FormatDescription::ShowRelativeForegroundControl);
m_ui->relativeForegroundLabel->setVisible(isVisible);
m_ui->foregroundSaturationLabel->setVisible(isVisible);
m_ui->foregroundLightnessLabel->setVisible(isVisible);
m_ui->foregroundSaturationSpinBox->setVisible(isVisible);
m_ui->foregroundLightnessSpinBox->setVisible(isVisible);
m_ui->foregroundSaturationSpinBox->setValue(format.relativeForegroundSaturation());
m_ui->foregroundLightnessSpinBox->setValue(format.relativeForegroundLightness());
}
void ColorSchemeEdit::updateRelativeBackgroundControls()
{
const auto &formatDescription = m_descriptions[m_curItem];
const Format &format = m_scheme.formatFor(formatDescription.id());
QSignalBlocker saturationSignalBlocker(m_ui->backgroundSaturationSpinBox);
QSignalBlocker lightnessSignalBlocker(m_ui->backgroundLightnessSpinBox);
bool isVisible = formatDescription.showControl(FormatDescription::ShowRelativeBackgroundControl);
m_ui->relativeBackgroundLabel->setVisible(isVisible);
m_ui->backgroundSaturationLabel->setVisible(isVisible);
m_ui->backgroundLightnessLabel->setVisible(isVisible);
m_ui->backgroundSaturationSpinBox->setVisible(isVisible);
m_ui->backgroundLightnessSpinBox->setVisible(isVisible);
m_ui->backgroundSaturationSpinBox->setValue(format.relativeBackgroundSaturation());
m_ui->backgroundLightnessSpinBox->setValue(format.relativeBackgroundLightness());
}
void ColorSchemeEdit::updateFontControls()
{
const auto formatDescription = m_descriptions[m_curItem];
......@@ -391,6 +451,70 @@ void ColorSchemeEdit::eraseForeColor()
}
}
void ColorSchemeEdit::changeRelativeForeColor()
{
if (m_curItem == -1)
return;
double saturation = m_ui->foregroundSaturationSpinBox->value();
double lightness = m_ui->foregroundLightnessSpinBox->value();
for (const QModelIndex &index : m_ui->itemList->selectionModel()->selectedRows()) {
const TextStyle category = m_descriptions[index.row()].id();
m_scheme.formatFor(category).setRelativeForegroundSaturation(saturation);
m_scheme.formatFor(category).setRelativeForegroundLightness(lightness);
m_formatsModel->emitDataChanged(index);
}
}
void ColorSchemeEdit::changeRelativeBackColor()
{
if (m_curItem == -1)
return;
double saturation = m_ui->backgroundSaturationSpinBox->value();
double lightness = m_ui->backgroundLightnessSpinBox->value();
for (const QModelIndex &index : m_ui->itemList->selectionModel()->selectedRows()) {
const TextStyle category = m_descriptions[index.row()].id();
m_scheme.formatFor(category).setRelativeBackgroundSaturation(saturation);
m_scheme.formatFor(category).setRelativeBackgroundLightness(lightness);
m_formatsModel->emitDataChanged(index);
}
}
void ColorSchemeEdit::eraseRelativeForeColor()
{
if (m_curItem == -1)
return;
m_ui->foregroundSaturationSpinBox->setValue(0.0);
m_ui->foregroundLightnessSpinBox->setValue(0.0);
foreach (const QModelIndex &index, m_ui->itemList->selectionModel()->selectedRows()) {
const TextStyle category = m_descriptions[index.row()].id();
m_scheme.formatFor(category).setRelativeForegroundSaturation(0.0);
m_scheme.formatFor(category).setRelativeForegroundLightness(0.0);
m_formatsModel->emitDataChanged(index);
}
}
void ColorSchemeEdit::eraseRelativeBackColor()
{
if (m_curItem == -1)
return;
m_ui->backgroundSaturationSpinBox->setValue(0.0);
m_ui->backgroundLightnessSpinBox->setValue(0.0);
foreach (const QModelIndex &index, m_ui->itemList->selectionModel()->selectedRows()) {
const TextStyle category = m_descriptions[index.row()].id();
m_scheme.formatFor(category).setRelativeBackgroundSaturation(0.0);
m_scheme.formatFor(category).setRelativeBackgroundLightness(0.0);
m_formatsModel->emitDataChanged(index);
}
}
void ColorSchemeEdit::checkCheckBoxes()
{
if (m_curItem == -1)
......
......@@ -63,8 +63,12 @@ private:
void currentItemChanged(const QModelIndex &index);
void changeForeColor();
void changeBackColor();
void eraseBackColor();
void eraseForeColor();
void eraseBackColor();
void changeRelativeForeColor();
void changeRelativeBackColor();
void eraseRelativeForeColor();
void eraseRelativeBackColor();
void checkCheckBoxes();
void changeUnderlineColor();
void eraseUnderlineColor();
......@@ -73,6 +77,8 @@ private:
void updateControls();
void updateForegroundControls();
void updateBackgroundControls();
void updateRelativeForegroundControls();
void updateRelativeBackgroundControls();
void updateFontControls();
void updateUnderlineControls();
void setItemListBackground(const QColor &color);
......
......@@ -7,27 +7,45 @@
<x>0</x>
<y>0</y>
<width>435</width>
<height>210</height>
<height>261</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" rowspan="6">
<widget class="QListView" name="itemList">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<item row="9" column="2">
<widget class="QLabel" name="backgroundSaturationLabel">
<property name="text">
<string>Saturation</string>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</widget>
</item>
<item row="7" column="3">
<widget class="QDoubleSpinBox" name="foregroundLightnessSpinBox">
<property name="minimum">
<double>-1.000000000000000</double>
</property>
<property name="uniformItemSizes">
<bool>true</bool>
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="singleStep">
<double>0.050000000000000</double>
</property>
</widget>
</item>
<item row="0" column="1">
<item row="7" column="2">
<widget class="QLabel" name="foregroundLightnessLabel">
<property name="text">
<string>Lightness</string>
</property>
</widget>
</item>
<item row="6" column="2">
<widget class="QLabel" name="foregroundSaturationLabel">
<property name="text">
<string>Saturation</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="foregroundLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
......@@ -43,7 +61,14 @@
</property>
</widget>
</item>
<item row="0" column="2">
<item row="11" column="3">
<widget class="QCheckBox" name="italicCheckBox">
<property name="text">
<string>Italic</string>
</property>
</widget>
</item>
<item row="0" column="3">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QToolButton" name="foregroundToolButton">
......@@ -73,8 +98,38 @@
</item>
</layout>
</item>
<item row="1" column="1">
<widget class="QLabel" name="backgroundLabel">
<item row="14" column="3">
<spacer>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>83</height>
</size>
</property>
</spacer>
</item>
<item row="5" column="2" colspan="2">
<widget class="QLabel" name="relativeForegroundLabel">
<property name="text">
<string>Relative Foreground</string>
</property>
</widget>
</item>
<item row="11" column="2">
<widget class="QCheckBox" name="boldCheckBox">
<property name="text">
<string>Bold</string>
</property>
</widget>
</item>
<item row="13" column="2" colspan="2">
<widget class="QComboBox" name="underlineComboBox"/>
</item>
<item row="12" column="2">
<widget class="QLabel" name="underlineLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
......@@ -82,17 +137,33 @@
</sizepolicy>
</property>
<property name="text">
<string>Background:</string>
<string>Underline:</string>
</property>
<property name="buddy">
<cstring>backgroundToolButton</cstring>
</property>
</widget>
</item>
<item row="1" column="2">
<layout class="QHBoxLayout" name="horizontalLayout">
<item row="0" column="0" rowspan="15">
<widget class="QListView" name="itemList">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
<property name="uniformItemSizes">
<bool>true</bool>
</property>
</widget>
</item>
<item row="12" column="3">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QToolButton" name="backgroundToolButton">
<widget class="QToolButton" name="underlineColorToolButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
......@@ -105,7 +176,7 @@
</widget>
</item>
<item>
<widget class="QToolButton" name="eraseBackgroundToolButton">
<widget class="QToolButton" name="eraseUnderlineColorToolButton">
<property name="toolTip">
<string>Erase background.</string>
</property>
......@@ -119,22 +190,21 @@
</item>
</layout>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="boldCheckBox">
<property name="text">
<string>Bold</string>
<item row="6" column="3">
<widget class="QDoubleSpinBox" name="foregroundSaturationSpinBox">
<property name="minimum">
<double>-1.000000000000000</double>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QCheckBox" name="italicCheckBox">
<property name="text">
<string>Italic</string>
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="singleStep">
<double>0.050000000000000</double>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="underlineLabel">
<item row="4" column="2">
<widget class="QLabel" name="backgroundLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
......@@ -142,17 +212,17 @@
</sizepolicy>
</property>
<property name="text">
<string>Underline:</string>
<string>Background:</string>
</property>
<property name="buddy">
<cstring>backgroundToolButton</cstring>
</property>
</widget>
</item>
<item row="3" column="2">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item row="4" column="3">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QToolButton" name="underlineColorToolButton">
<widget class="QToolButton" name="backgroundToolButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
......@@ -165,7 +235,7 @@
</widget>
</item>
<item>
<widget class="QToolButton" name="eraseUnderlineColorToolButton">
<widget class="QToolButton" name="eraseBackgroundToolButton">
<property name="toolTip">
<string>Erase background.</string>
</property>
......@@ -179,21 +249,45 @@
</item>
</layout>
</item>
<item row="4" column="1" colspan="2">
<widget class="QComboBox" name="underlineComboBox"/>
<item row="10" column="2">
<widget class="QLabel" name="backgroundLightnessLabel">
<property name="text">
<string>Lightness</string>
</property>
</widget>
</item>
<item row="5" column="2">
<spacer>
<property name="orientation">
<enum>Qt::Vertical</enum>
<item row="8" column="2" colspan="2">
<widget class="QLabel" name="relativeBackgroundLabel">
<property name="text">
<string>Relative Backgound</string>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>83</height>
</size>
</widget>
</item>
<item row="9" column="3">
<widget class="QDoubleSpinBox" name="backgroundSaturationSpinBox">
<property name="minimum">
<double>-1.000000000000000</double>
</property>
</spacer>
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="singleStep">
<double>0.050000000000000</double>
</property>
</widget>
</item>
<item row="10" column="3">
<widget class="QDoubleSpinBox" name="backgroundLightnessSpinBox">
<property name="minimum">
<double>-1.000000000000000</double>
</property>
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="singleStep">
<double>0.050000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
......
......@@ -39,6 +39,8 @@
#include <QSettings>
#include <QTextCharFormat>
#include <cmath>
static const char fontFamilyKey[] = "FontFamily";
static const char fontSizeKey[] = "FontSize";
static const char fontZoomKey[] = "FontZoom";
......@@ -193,26 +195,59 @@ bool operator==(const TextStyles &first, const TextStyles &second)
&& first.mixinStyles == second.mixinStyles;
}
namespace {