Commit 331e9d88 authored by Marco Bubke's avatar Marco Bubke Committed by David Schulz

TextEdit: Add underline support to text settings

Underlines colors was hard coded to the foreground color of some settings.
With this patch you can set the underline color and the underline style
to your taste.

Change-Id: Ibc64c2d2c89bf1827a2cadaf6aee9d50d08cd1ee
Reviewed-by: default avatarDavid Schulz <david.schulz@theqtcompany.com>
parent 0d20d561
......@@ -32,6 +32,12 @@
<style name="Text" foreground="#000000" background="#ffffff"/>
<style name="Type"/>
<style name="VirtualMethod" italic="true"/>
<style name="Occurrences.Unused" underlineColor="#8F8F8F" underlineStyle="SingleUnderline"/>
<style name="Warning" underlineColor="#505050" underlineStyle="SingleUnderline"/>
<style name="WarningContext" underlineColor="#505050" underlineStyle="DotLine"/>
<style name="Error" underlineColor="#000000" underlineStyle="WaveUnderline"/>
<style name="ErrorContext" underlineColor="#000000" underlineStyle="DotLine"/>
<!--
Relying on default colors for:
......@@ -43,7 +49,6 @@
Selection
Occurrences
Occurrences.Rename
Occurrences.Unused
VisualWhitespace
-->
......
......@@ -36,27 +36,20 @@
#include <QFile>
#include <QCoreApplication>
#include <QMetaEnum>
#include <QXmlStreamWriter>
using namespace TextEditor;
static const char trueString[] = "true";
static const char falseString[] = "false";
// Format
Format::Format() :
m_foreground(Qt::black),
m_background(Qt::white),
m_bold(false),
m_italic(false)
{
}
Format::Format(const QColor &foreground, const QColor &background) :
m_foreground(foreground),
m_background(background),
m_bold(false),
m_italic(false)
m_background(background)
{
}
......@@ -80,6 +73,26 @@ void Format::setItalic(bool italic)
m_italic = italic;
}
void Format::setUnderlineColor(const QColor &underlineColor)
{
m_underlineColor = underlineColor;
}
QColor Format::underlineColor() const
{
return m_underlineColor;
}
void Format::setUnderlineStyle(QTextCharFormat::UnderlineStyle underlineStyle)
{
m_underlineStyle = underlineStyle;
}
QTextCharFormat::UnderlineStyle Format::underlineStyle() const
{
return m_underlineStyle;
}
static QColor stringToColor(const QString &string)
{
if (string == QLatin1String("invalid"))
......@@ -87,10 +100,62 @@ static QColor stringToColor(const QString &string)
return QColor(string);
}
bool Format::equals(const Format &f) const
static QTextCharFormat::UnderlineStyle stringToUnderlineStyle(const QString &string)
{
if (string.isEmpty() || string == QStringLiteral("NoUnderline"))
return QTextCharFormat::NoUnderline;
else if (string == QStringLiteral("SingleUnderline"))
return QTextCharFormat::SingleUnderline;
else if (string == QStringLiteral("DashUnderline"))
return QTextCharFormat::DashUnderline;
else if (string == QStringLiteral("DotLine"))
return QTextCharFormat::DotLine;
else if (string == QStringLiteral("DashDotLine"))
return QTextCharFormat::DashDotLine;
else if (string == QStringLiteral("DashDotDotLine"))
return QTextCharFormat::DashDotDotLine;
else if (string == QStringLiteral("WaveUnderline"))
return QTextCharFormat::WaveUnderline;
return QTextCharFormat::NoUnderline;
}
static QString underlineStyleToString(QTextCharFormat::UnderlineStyle underlineStyle)
{
switch (underlineStyle) {
case QTextCharFormat::NoUnderline: return QStringLiteral("NoUnderline");
case QTextCharFormat::SingleUnderline: return QStringLiteral("SingleUnderline");
case QTextCharFormat::DashUnderline: return QStringLiteral("DashUnderline");
case QTextCharFormat::DotLine: return QStringLiteral("DotLine");
case QTextCharFormat::DashDotLine: return QStringLiteral("DashDotLine");
case QTextCharFormat::DashDotDotLine: return QStringLiteral("DashDotDotLine");
case QTextCharFormat::WaveUnderline: return QStringLiteral("WaveUnderline");
case QTextCharFormat::SpellCheckUnderline: return QString();
}
return QString();
}
bool Format::equals(const Format &other) const
{
return m_foreground == other.m_foreground
&& m_background == other.m_background
&& m_underlineColor == other.m_underlineColor
&& m_underlineStyle == other.m_underlineStyle
&& m_bold == other.m_bold
&& m_italic == other.m_italic;
}
QString Format::toString() const
{
return m_foreground == f.m_foreground && m_background == f.m_background &&
m_bold == f.m_bold && m_italic == f.m_italic;
QStringList text({m_foreground.name(),
m_background.name(),
m_bold ? QLatin1String(trueString) : QLatin1String(falseString),
m_italic ? QLatin1String(trueString) : QLatin1String(falseString),
m_underlineColor.name(),
underlineStyleToString(m_underlineStyle)});
return text.join(QLatin1Char(';'));
}
bool Format::fromString(const QString &str)
......@@ -98,23 +163,22 @@ bool Format::fromString(const QString &str)
*this = Format();
const QStringList lst = str.split(QLatin1Char(';'));
if (lst.count() != 4)
if (lst.count() != 4 && lst.count() != 6)
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));
return true;
}
// ColorScheme
ColorScheme::ColorScheme()
{
}
bool ColorScheme::contains(TextStyle category) const
{
return m_formats.contains(category);
......@@ -167,6 +231,10 @@ bool ColorScheme::save(const QString &fileName, QWidget *parent) const
w.writeAttribute(QLatin1String("bold"), QLatin1String(trueString));
if (format.italic())
w.writeAttribute(QLatin1String("italic"), QLatin1String(trueString));
if (format.underlineColor().isValid())
w.writeAttribute(QStringLiteral("underlineColor"), format.underlineColor().name().toLower());
if (format.underlineStyle() != QTextCharFormat::NoUnderline)
w.writeAttribute(QLatin1String("underlineStyle"), underlineStyleToString(format.underlineStyle()));
w.writeEndElement();
}
......@@ -274,6 +342,8 @@ void ColorSchemeReader::readStyle()
QString background = attr.value(QLatin1String("background")).toString();
bool bold = attr.value(QLatin1String("bold")) == QLatin1String(trueString);
bool italic = attr.value(QLatin1String("italic")) == QLatin1String(trueString);
QString underlineColor = attr.value(QLatin1String("underlineColor")).toString();
QString underlineStyle = attr.value(QLatin1String("underlineStyle")).toString();
Format format;
......@@ -290,6 +360,13 @@ void ColorSchemeReader::readStyle()
format.setBold(bold);
format.setItalic(italic);
if (QColor::isValidColor(underlineColor))
format.setUnderlineColor(QColor(underlineColor));
else
format.setUnderlineColor(QColor());
format.setUnderlineStyle(stringToUnderlineStyle(underlineStyle));
m_scheme->setFormatFor(Constants::styleFromName(name), format);
skipCurrentElement();
......
......@@ -37,6 +37,7 @@
#include <QMap>
#include <QString>
#include <QColor>
#include <QTextCharFormat>
QT_BEGIN_NAMESPACE
class QWidget;
......@@ -48,7 +49,7 @@ namespace TextEditor {
class TEXTEDITOR_EXPORT Format
{
public:
Format();
Format() = default;
Format(const QColor &foreground, const QColor &background);
QColor foreground() const { return m_foreground; }
......@@ -63,16 +64,24 @@ public:
bool italic() const { return m_italic; }
void setItalic(bool italic);
void setUnderlineColor(const QColor &underlineColor);
QColor underlineColor() const;
void setUnderlineStyle(QTextCharFormat::UnderlineStyle underlineStyle);
QTextCharFormat::UnderlineStyle underlineStyle() const;
bool equals(const Format &f) const;
QString toString() const;
bool fromString(const QString &str);
private:
QColor m_foreground;
QColor m_background;
bool m_bold;
bool m_italic;
QColor m_foreground = Qt::black;
QColor m_background = Qt::white;
QColor m_underlineColor;
QTextCharFormat::UnderlineStyle m_underlineStyle = QTextCharFormat::NoUnderline;
bool m_bold = false;
bool m_italic = false;
};
inline bool operator==(const Format &f1, const Format &f2) { return f1.equals(f2); }
......@@ -85,8 +94,6 @@ inline bool operator!=(const Format &f1, const Format &f2) { return !f1.equals(f
class ColorScheme
{
public:
ColorScheme();
void setDisplayName(const QString &name)
{ m_displayName = name; }
......
......@@ -112,8 +112,10 @@ public:
}
case Qt::FontRole: {
QFont font = m_baseFont;
font.setBold(m_scheme->formatFor(description.id()).bold());
font.setItalic(m_scheme->formatFor(description.id()).italic());
auto format = m_scheme->formatFor(description.id());
font.setBold(format.bold());
font.setItalic(format.italic());
font.setUnderline(format.underlineStyle() != QTextCharFormat::NoUnderline);
return font;
}
case Qt::ToolTipRole: {
......@@ -154,6 +156,8 @@ ColorSchemeEdit::ColorSchemeEdit(QWidget *parent) :
m_ui->setupUi(this);
m_ui->itemList->setModel(m_formatsModel);
populateUnderlineStyleComboBox();
connect(m_ui->itemList->selectionModel(), SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),
SLOT(currentItemChanged(QModelIndex)));
connect(m_ui->foregroundToolButton, SIGNAL(clicked()), SLOT(changeForeColor()));
......@@ -162,6 +166,18 @@ ColorSchemeEdit::ColorSchemeEdit(QWidget *parent) :
connect(m_ui->eraseForegroundToolButton, SIGNAL(clicked()), SLOT(eraseForeColor()));
connect(m_ui->boldCheckBox, SIGNAL(toggled(bool)), SLOT(checkCheckBoxes()));
connect(m_ui->italicCheckBox, SIGNAL(toggled(bool)), SLOT(checkCheckBoxes()));
connect(m_ui->underlineColorToolButton,
&QToolButton::clicked,
this,
&ColorSchemeEdit::changeUnderlineColor);
connect(m_ui->eraseUnderlineColorToolButton,
&QToolButton::clicked,
this,
&ColorSchemeEdit::eraseUnderlineColor);
connect(m_ui->underlineComboBox,
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
this,
&ColorSchemeEdit::changeUnderlineStyle);
}
ColorSchemeEdit::~ColorSchemeEdit()
......@@ -199,6 +215,9 @@ void ColorSchemeEdit::setReadOnly(bool readOnly)
m_ui->eraseForegroundToolButton->setEnabled(enabled);
m_ui->boldCheckBox->setEnabled(enabled);
m_ui->italicCheckBox->setEnabled(enabled);
m_ui->underlineColorToolButton->setEnabled(enabled);
m_ui->eraseUnderlineColorToolButton->setEnabled(enabled);
m_ui->underlineComboBox->setEnabled(enabled);
}
void ColorSchemeEdit::setColorScheme(const ColorScheme &colorScheme)
......@@ -236,12 +255,18 @@ void ColorSchemeEdit::updateControls()
&& m_curItem > 0
&& format.foreground().isValid());
const bool boldBlocked = m_ui->boldCheckBox->blockSignals(true);
QSignalBlocker boldSignalBlocker(m_ui->boldCheckBox);
m_ui->boldCheckBox->setChecked(format.bold());
m_ui->boldCheckBox->blockSignals(boldBlocked);
const bool italicBlocked = m_ui->italicCheckBox->blockSignals(true);
QSignalBlocker italicSignalBlocker(m_ui->italicCheckBox);
m_ui->italicCheckBox->setChecked(format.italic());
m_ui->italicCheckBox->blockSignals(italicBlocked);
m_ui->underlineColorToolButton->setStyleSheet(colorButtonStyleSheet(format.underlineColor()));
m_ui->eraseUnderlineColorToolButton->setEnabled(!m_readOnly
&& m_curItem > 0
&& format.underlineColor().isValid());
int index = m_ui->underlineComboBox->findData(QVariant::fromValue(int(format.underlineStyle())));
QSignalBlocker comboBoxSignalBlocker(m_ui->underlineComboBox);
m_ui->underlineComboBox->setCurrentIndex(index);
}
void ColorSchemeEdit::changeForeColor()
......@@ -326,9 +351,74 @@ void ColorSchemeEdit::checkCheckBoxes()
}
}
void ColorSchemeEdit::changeUnderlineColor()
{
if (m_curItem == -1)
return;
QColor color = m_scheme.formatFor(m_descriptions[m_curItem].id()).underlineColor();
const QColor newColor = QColorDialog::getColor(color, m_ui->boldCheckBox->window());
if (!newColor.isValid())
return;
m_ui->underlineColorToolButton->setStyleSheet(colorButtonStyleSheet(newColor));
m_ui->eraseUnderlineColorToolButton->setEnabled(true);
foreach (const QModelIndex &index, m_ui->itemList->selectionModel()->selectedRows()) {
const TextStyle category = m_descriptions[index.row()].id();
m_scheme.formatFor(category).setUnderlineColor(newColor);
m_formatsModel->emitDataChanged(index);
}
}
void ColorSchemeEdit::eraseUnderlineColor()
{
if (m_curItem == -1)
return;
QColor newColor;
m_ui->underlineColorToolButton->setStyleSheet(colorButtonStyleSheet(newColor));
m_ui->eraseUnderlineColorToolButton->setEnabled(false);
foreach (const QModelIndex &index, m_ui->itemList->selectionModel()->selectedRows()) {
const TextStyle category = m_descriptions[index.row()].id();
m_scheme.formatFor(category).setUnderlineColor(newColor);
m_formatsModel->emitDataChanged(index);
}
}
void ColorSchemeEdit::changeUnderlineStyle(int comboBoxIndex)
{
if (m_curItem == -1)
return;
foreach (const QModelIndex &index, m_ui->itemList->selectionModel()->selectedRows()) {
const TextStyle category = m_descriptions[index.row()].id();
auto value = m_ui->underlineComboBox->itemData(comboBoxIndex);
auto enumeratorIndex = static_cast<QTextCharFormat::UnderlineStyle>(value.toInt());
m_scheme.formatFor(category).setUnderlineStyle(enumeratorIndex);
m_formatsModel->emitDataChanged(index);
}
}
void ColorSchemeEdit::setItemListBackground(const QColor &color)
{
QPalette pal;
pal.setColor(QPalette::Base, color);
m_ui->itemList->setPalette(pal);
}
void ColorSchemeEdit::populateUnderlineStyleComboBox()
{
m_ui->underlineComboBox->addItem(tr("No Underline"),
QVariant::fromValue(int(QTextCharFormat::NoUnderline)));
m_ui->underlineComboBox->addItem(tr("Single Underline"),
QVariant::fromValue(int(QTextCharFormat::SingleUnderline)));
m_ui->underlineComboBox->addItem(tr("Wave Underline"),
QVariant::fromValue(int(QTextCharFormat::WaveUnderline)));
m_ui->underlineComboBox->addItem(tr("Dot Underline"),
QVariant::fromValue(int(QTextCharFormat::DotLine)));
m_ui->underlineComboBox->addItem(tr("Dash Underline"),
QVariant::fromValue(int(QTextCharFormat::DashUnderline)));
m_ui->underlineComboBox->addItem(tr("Dash-Dot Underline"),
QVariant::fromValue(int(QTextCharFormat::DashDotLine)));
m_ui->underlineComboBox->addItem(tr("Dash-Dot-Dot Underline"),
QVariant::fromValue(int(QTextCharFormat::DashDotDotLine)));
}
......@@ -72,11 +72,16 @@ private slots:
void eraseBackColor();
void eraseForeColor();
void checkCheckBoxes();
void changeUnderlineColor();
void eraseUnderlineColor();
void changeUnderlineStyle(int index);
private:
void updateControls();
void setItemListBackground(const QColor &color);
void populateUnderlineStyleComboBox();
private:
FormatDescriptions m_descriptions;
ColorScheme m_scheme;
int m_curItem;
......
......@@ -11,7 +11,7 @@
</rect>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" rowspan="4">
<item row="0" column="0" rowspan="6">
<widget class="QListView" name="itemList">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
......@@ -133,7 +133,56 @@
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="underlineLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Underline:</string>
</property>
<property name="buddy">
<cstring>backgroundToolButton</cstring>
</property>
</widget>
</item>
<item row="3" column="2">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QToolButton" name="underlineColorToolButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="eraseUnderlineColorToolButton">
<property name="toolTip">
<string>Erase background.</string>
</property>
<property name="text">
<string>x</string>
</property>
<property name="arrowType">
<enum>Qt::LeftArrow</enum>
</property>
</widget>
</item>
</layout>
</item>
<item row="4" column="1" colspan="2">
<widget class="QComboBox" name="underlineComboBox"/>
</item>
<item row="5" column="2">
<spacer>
<property name="orientation">
<enum>Qt::Vertical</enum>
......
......@@ -130,6 +130,8 @@ bool FontSettings::fromSettings(const QString &category,
format.setBackground(desc.background());
format.setBold(desc.format().bold());
format.setItalic(desc.format().italic());
format.setUnderlineColor(desc.format().underlineColor());
format.setUnderlineStyle(desc.format().underlineStyle());
} else {
format.fromString(fmt);
}
......@@ -152,19 +154,6 @@ bool FontSettings::equals(const FontSettings &f) const
&& m_scheme == f.m_scheme;
}
static bool isDiagnostic(TextStyle textStyle)
{
switch (textStyle) {
case C_ERROR:
case C_ERROR_CONTEXT:
case C_WARNING:
case C_WARNING_CONTEXT: return true;
default: return false;
}
Q_UNREACHABLE();
}
/**
* Returns the QTextCharFormat of the given format category.
*/
......@@ -183,34 +172,24 @@ QTextCharFormat FontSettings::toTextCharFormat(TextStyle category) const
}
if (category == C_OCCURRENCES_UNUSED) {
tf.setUnderlineStyle(QTextCharFormat::SingleUnderline);
tf.setUnderlineColor(f.foreground());
tf.setToolTip(QCoreApplication::translate("FontSettings_C_OCCURRENCES_UNUSED",
"Unused variable"));
}
if (isDiagnostic(category)) {
if (category == C_ERROR || category == C_WARNING)
tf.setUnderlineStyle(QTextCharFormat::SingleUnderline);
else
tf.setUnderlineStyle(QTextCharFormat::DotLine);
tf.setUnderlineColor(f.foreground());
}
if (f.foreground().isValid()
&& category != C_OCCURRENCES
&& category != C_OCCURRENCES_RENAME
&& category != C_OCCURRENCES_UNUSED
&& category != C_SEARCH_RESULT
&& category != C_PARENTHESES_MISMATCH
&& !isDiagnostic(category))
&& category != C_PARENTHESES_MISMATCH)
tf.setForeground(f.foreground());
if (f.background().isValid() && (category == C_TEXT || f.background() != m_scheme.formatFor(C_TEXT).background()))
tf.setBackground(f.background());
tf.setFontWeight(f.bold() ? QFont::Bold : QFont::Normal);
tf.setFontItalic(f.italic());
tf.setUnderlineColor(f.underlineColor());
tf.setUnderlineStyle(f.underlineStyle());
m_formatCache.insert(category, tf);
return tf;
}
......@@ -345,6 +324,8 @@ bool FontSettings::loadColorScheme(const QString &fileName,
format.setBackground(desc.background());
format.setBold(desc.format().bold());
format.setItalic(desc.format().italic());
format.setUnderlineColor(desc.format().underlineColor());
format.setUnderlineStyle(desc.format().underlineStyle());
m_scheme.setFormatFor(id, format);
}
}
......
......@@ -192,6 +192,8 @@ FontSettingsPagePrivate::FontSettingsPagePrivate(const FormatDescriptions &fd,
format.setBackground(f.background());
format.setBold(f.format().bold());
format.setItalic(f.format().italic());
format.setUnderlineColor(f.format().underlineColor());
format.setUnderlineStyle(f.format().underlineStyle());
}
} else if (m_value.colorSchemeFileName().isEmpty()) {
// No color scheme was loaded, but one might be imported from the ini file
......@@ -202,6 +204,8 @@ FontSettingsPagePrivate::FontSettingsPagePrivate(const FormatDescriptions &fd,
format.setBackground(f.background());
format.setBold(f.format().bold());
format.setItalic(f.format().italic());
format.setUnderlineColor(f.format().underlineColor());
format.setUnderlineStyle(f.format().underlineStyle());
}
if (m_value.colorScheme() != defaultScheme) {
// Save it as a color scheme file
......@@ -239,6 +243,21 @@ FormatDescription::FormatDescription(TextStyle id, const QString &displayName, c
{
}
FormatDescription::FormatDescription(TextStyle id,
const QString &displayName,
const QString &tooltipText,
const QColor &underlineColor,
const QTextCharFormat::UnderlineStyle underlineStyle)
: m_id(id),
m_displayName(displayName),
m_tooltipText(tooltipText)
{
m_format.setForeground(QColor());
m_format.setBackground(QColor());
m_format.setUnderlineColor(underlineColor);
m_format.setUnderlineStyle(underlineStyle);
}
QColor FormatDescription::foreground() const
{
if (m_id == C_LINE_NUMBER) {
......@@ -253,8 +272,6 @@ QColor FormatDescription::foreground() const
return QApplication::palette().foreground().color();
else
return m_format.foreground();
} else if (m_id == C_OCCURRENCES_UNUSED) {
return Qt::darkYellow;
} else if (m_id == C_PARENTHESES) {
return QColor(Qt::red);
}
......@@ -314,7 +331,6 @@ QColor FormatDescription::background() const
return QColor(); // invalid color
}
// ------------ FontSettingsPage
FontSettingsPage::FontSettingsPage(const FormatDescriptions &fd,
Core::Id id,
......
......@@ -57,10 +57,19 @@ namespace Internal { class FontSettingsPagePrivate; }
class TEXTEDITOR_EXPORT FormatDescription
{
public:
FormatDescription(TextStyle id, const QString &displayName, const QString &tooltipText,
FormatDescription(TextStyle id,
const QString &displayName,
const QString &tooltipText,
const QColor &foreground = Qt::black);
FormatDescription(TextStyle id, const QString &displayName, const QString &tooltipText,
FormatDescription(TextStyle id,
const QString &displayName,
const QString &tooltipText,
const Format &format);
FormatDescription(TextStyle id,
const QString &displayName,
const QString &tooltipText,
const QColor &underlineColor,
const QTextCharFormat::UnderlineStyle underlineStyle);
TextStyle id() const { return m_id; }
......
......@@ -104,8 +104,8 @@ const char *nameForStyle(TextStyle style)
case C_WARNING: return "Warning";
case C_WARNING_CONTEXT: return "WarningContext";
case C_LAST_STYLE_SENTINEL: return "LastStyleSentinel";
case C_LAST_STYLE_SENTINEL: return "LastStyleSentinel";
}
return "Unknown Style";
}
......
......@@ -135,8 +135,11 @@ TextEditorSettings::TextEditorSettings(QObject *parent)
formatDescr.append(FormatDescription(C_OCCURRENCES, tr("Occurrences"),
tr("Occurrences of the symbol under the cursor.\n"
"(Only the background will be applied.)")));
formatDescr.append(FormatDescription(C_OCCURRENCES_UNUSED, tr("Unused Occurrence"),
tr("Occurrences of unused variables.")));
formatDescr.append(FormatDescription(C_OCCURRENCES_UNUSED,
tr("Unused Occurrence"),
tr("Occurrences of unused variables."),