2

I am creating a QLineEditor to manually input a color in hex format. I want to set a validator to check if the input color is a pure HUE color.

All hue colors follow this pattern, being X any hex character [from 0-9 or A-F]:

#FF00XX
#00FFXX
#00XXFF
#XX00FF
#XXFF00
#FFXX00

I managed to check for a correct HEX color value: ^#([A-Fa-f0-9]{6})$, but I don't know how to extend the validator to accept only hue colors.

Any ideas?

CinCout
  • 9,486
  • 12
  • 49
  • 67
laurapons
  • 971
  • 13
  • 32

3 Answers3

1

The pattern you want is ^#(?:00(?:FFXX|XXFF)|FF(?:00XX|XX00)|XX(?:00FF|FF00))$.

If you want XX to be any hex char, replace with [a-fA-F0-9]{2}. Then, the regex will look like

^#(?:00(?:FF[a-fA-F0-9]{2}|[a-fA-F0-9]{2}FF)|FF(?:00[a-fA-F0-9]{2}|[a-fA-F0-9]{2}00)|[a-fA-F0-9]{2}(?:00FF|FF00))$

See the regex demo.

If you do not want XX to match 00 and FF, replace XX with (?![fF]{2}|00)[a-fA-F0-9]{2}. Then, the regex will look like

^#(?:00(?:FF(?![fF]{2}|00)[a-fA-F0-9]{2}|(?![fF]{2}|00)[a-fA-F0-9]{2}FF)|FF(?:00(?![fF]{2}|00)[a-fA-F0-9]{2}|(?![fF]{2}|00)[a-fA-F0-9]{2}00)|(?![fF]{2}|00)[a-fA-F0-9]{2}(?:00FF|FF00))$

See the regex demo.

The (?![fF]{2}|00)[a-fA-F0-9]{2} part matches any two hex chars that are not equal to FF or 00 (case insensitive).

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • Your solution matches the one produced by running `perl -MRegexp::Assemble -E 'say Regexp::Assemble->new->add(@ARGV)->as_string' #FF00XX #00FFXX #00XXFF #XX00FF #XXFF00 #FFXX00`. Is that the tool you used to derive your answer from? – tchrist Dec 16 '21 at 13:15
  • @tchrist No, this is something new to me, I just used a regex trie. – Wiktor Stribiżew Dec 16 '21 at 13:19
  • That makes good sense because a regex trie should produce an optimal branching structure for matching a set of fixed strings. I think you might enjoy seeing how the perl regex compiler generates `TRIE-EXACT` regex opcodes internally when fed your pattern by looking at the "debug output" from the regex compiler by typing this command: `perl -Mre=debug -ce '/^#(?:00(?:FFXX|XXFF)|FF(?:00XX|XX00)|XX(?:00FF|FF00))$/'` – tchrist Dec 16 '21 at 13:23
0

The simplest way is to just use the pipe operator to cover all the six cases:

00[A-Fa-f0-9]{2}FF|00FF[A-Fa-f0-9]{2}|FF00[A-Fa-f0-9]{2}|FF[A-Fa-f0-9]{2}00|[A-Fa-f0-9]{2}00FF|[A-Fa-f0-9]{2}FF00

Demo

Obviously the pattern [A-Fa-f0-9]{2} is repeated several times. To remove redundancy, you can save it in a separate variable and use string formatting to substitute it and form the pattern as shown above.

CinCout
  • 9,486
  • 12
  • 49
  • 67
0

If there are just 6 cases you can write this cases using boolean OR (|)

(?<=#00FF|#FF00)[A-Fa-f0-9]{2}|[A-Fa-f0-9]{2}(?=00FF|FF00)|(?<=#00)[A-Fa-f0-9]{2}(?=FF)|(?<=#FF)[A-Fa-f0-9]{2}(?=00)

Demo