The only way I can see from the documentation is to iterate over all the named colors that Qt knows about (provided by QColor::colorNames()
), converting each one to a QColor
and checking if the colors match (there is an operator==
for QColor
available).
If you want to do this repeatedly, it is advisable to use some sort of map instead of doing linear searches constantly. QColor
does not lend itself directly as map key (no operator<
and no hash function), but we can use its underlying RGBA value. If we write custom code for this we might as well get the performance aspect right by avoiding the (for our purposes) inefficient map/unordered_map implementations and using binary search over sorted vectors instead:
// Lookup class that is only accessible from getColorName free function.
class NamedQColorLookup
{
private:
NamedQColorLookup()
{
auto keyList = QColor::colorNames();
// Simple implementation for filling _keys and _values using std::map.
// Alternatively, sort two vectors at once, for example like
// https://stackoverflow.com/questions/17074324/how-can-i-sort-two-vectors-in-the-same-way-with-criteria-that-uses-only-one-of
// But that's less readable and (since it's only done once) has no meaningful performance impact.
std::map<std::uint64_t, QString> colorMap;
for (const auto& key : keyList)
colorMap.emplace(QColor(key).rgba64(), key);
// Convert to faster and smaller vector lookup.
_keys.reserve(colorMap.size());
_values.reserve(colorMap.size());
for (const auto& [key, value] : colorMap)
{
_keys.emplace_back(key);
_values.emplace_back(value);
}
}
QString getName(const QColor& color) const
{
auto rgba = color.rgba64();
// Binary search for the RGBA value.
auto [notLessThan, greaterThan] = std::equal_range(_keys.begin(), _keys.end(), rgba);
// If this is not a named color, return the RGB code instead.
if (notLessThan == greaterThan)
return color.name();
// We found a matching ARGB value, obtain its index.
auto index = std::distance(_keys.begin(), notLessThan);
return _values[index];
}
std::vector<std::uint64_t> _keys;
std::vector<QString> _values; // ...or some kind of string view if you want.
friend QString getColorName(const QColor& color);
};
// The interface for color -> name lookups.
QString getColorName(const QColor& color)
{
static NamedQColorLookup lookup;
return lookup.getName(color);
}
We could use a std::vector<std::pair<std::uint64_t, QString>>
instead of two separate vectors, but that would make the binary search slower (more cache misses).
Play with it here: https://godbolt.org/z/z1fgyc