1use cxx::{type_id, ExternType};
7use std::fmt;
8use std::mem::MaybeUninit;
9
10use crate::{QString, QStringList};
11
12#[cxx::bridge]
13mod ffi {
14 #[repr(i32)]
16 #[namespace = "rust::cxxqtlib1"]
17 enum QColorNameFormat {
18 HexRgb,
20 HexArgb,
22 }
23
24 #[repr(i32)]
26 #[namespace = "rust::cxxqtlib1"]
27 enum QColorSpec {
28 Invalid,
29 Rgb,
30 Hsv,
31 Cmyk,
32 Hsl,
33 ExtendedRgb,
34 }
35
36 unsafe extern "C++" {
37 include!("cxx-qt-lib/qcolor.h");
38 type QColor = super::QColor;
39 include!("cxx-qt-lib/qstring.h");
40 type QString = crate::QString;
41 include!("cxx-qt-lib/qstringlist.h");
42 type QStringList = crate::QStringList;
43
44 fn alpha(self: &QColor) -> i32;
46 fn black(self: &QColor) -> i32;
48 fn blue(self: &QColor) -> i32;
50 #[rust_name = "convert_to"]
52 fn convertTo(self: &QColor, color_spec: QColorSpec) -> QColor;
53 fn cyan(self: &QColor) -> i32;
55 fn darker(self: &QColor, factor: i32) -> QColor;
61 fn green(self: &QColor) -> i32;
63 #[rust_name = "hsl_hue"]
65 fn hslHue(self: &QColor) -> i32;
66 #[rust_name = "hsl_saturation"]
68 fn hslSaturation(self: &QColor) -> i32;
69 #[rust_name = "hsv_hue"]
71 fn hsvHue(self: &QColor) -> i32;
72 #[rust_name = "hsv_saturation"]
74 fn hsvSaturation(self: &QColor) -> i32;
75 fn hue(self: &QColor) -> i32;
79 #[rust_name = "is_valid"]
81 fn isValid(self: &QColor) -> bool;
82 fn lighter(self: &QColor, factor: i32) -> QColor;
88 fn lightness(self: &QColor) -> i32;
90 fn magenta(self: &QColor) -> i32;
92 fn name(self: &QColor, format: QColorNameFormat) -> QString;
94 fn red(self: &QColor) -> i32;
96 fn saturation(self: &QColor) -> i32;
100 #[rust_name = "set_alpha"]
102 fn setAlpha(self: &mut QColor, alpha: i32);
103 #[rust_name = "set_blue"]
105 fn setBlue(self: &mut QColor, blue: i32);
106 #[rust_name = "set_cmyk"]
110 fn setCmyk(self: &mut QColor, c: i32, m: i32, y: i32, k: i32, a: i32);
111 #[rust_name = "set_green"]
113 fn setGreen(self: &mut QColor, green: i32);
114 #[rust_name = "set_hsl"]
118 fn setHsl(self: &mut QColor, h: i32, s: i32, l: i32, a: i32);
119 #[rust_name = "set_hsv"]
123 fn setHsv(self: &mut QColor, h: i32, s: i32, v: i32, a: i32);
124 #[rust_name = "set_red"]
126 fn setRed(self: &mut QColor, red: i32);
127 #[rust_name = "set_rgb"]
131 fn setRgb(self: &mut QColor, r: i32, g: i32, b: i32, a: i32);
132 fn spec(self: &QColor) -> QColorSpec;
134 #[rust_name = "to_cmyk"]
136 fn toCmyk(self: &QColor) -> QColor;
137 #[rust_name = "to_extended_rgb"]
139 fn toExtendedRgb(self: &QColor) -> QColor;
140 #[rust_name = "to_hsl"]
142 fn toHsl(self: &QColor) -> QColor;
143 #[rust_name = "to_hsv"]
145 fn toHsv(self: &QColor) -> QColor;
146 #[rust_name = "to_rgb"]
148 fn toRgb(self: &QColor) -> QColor;
149 fn value(self: &QColor) -> i32;
151 fn yellow(self: &QColor) -> i32;
153 }
154
155 #[namespace = "rust::cxxqtlib1"]
156 unsafe extern "C++" {
157 type QColorNameFormat;
158 type QColorSpec;
159
160 #[doc(hidden)]
161 #[rust_name = "qcolor_color_names"]
162 fn qcolorColorNames() -> QStringList;
163 #[doc(hidden)]
164 #[rust_name = "qcolor_init_from_cmyk"]
165 fn qcolorInitFromCmyk(c: i32, m: i32, y: i32, k: i32, a: i32) -> QColor;
166 #[doc(hidden)]
167 #[rust_name = "qcolor_init_from_cmyk_f"]
168 fn qcolorInitFromCmykF(c: f32, m: f32, y: f32, k: f32, a: f32) -> QColor;
169 #[doc(hidden)]
170 #[rust_name = "qcolor_init_from_hsl"]
171 fn qcolorInitFromHsl(h: i32, s: i32, l: i32, a: i32) -> QColor;
172 #[doc(hidden)]
173 #[rust_name = "qcolor_init_from_hsl_f"]
174 fn qcolorInitFromHslF(h: f32, s: f32, l: f32, a: f32) -> QColor;
175 #[doc(hidden)]
176 #[rust_name = "qcolor_init_from_hsv"]
177 fn qcolorInitFromHsv(h: i32, s: i32, v: i32, a: i32) -> QColor;
178 #[doc(hidden)]
179 #[rust_name = "qcolor_init_from_hsv_f"]
180 fn qcolorInitFromHsvF(h: f32, s: f32, v: f32, a: f32) -> QColor;
181 #[doc(hidden)]
182 #[rust_name = "qcolor_init_from_rgb"]
183 fn qcolorInitFromRgb(red: i32, green: i32, blue: i32, alpha: i32) -> QColor;
184 #[doc(hidden)]
185 #[rust_name = "qcolor_init_from_rgb_f"]
186 fn qcolorInitFromRgbF(red: f32, green: f32, blue: f32, alpha: f32) -> QColor;
187
188 #[doc(hidden)]
189 #[rust_name = "qcolor_alpha_f"]
190 fn qcolorAlphaF(color: &QColor) -> f32;
191 #[doc(hidden)]
192 #[rust_name = "qcolor_black_f"]
193 fn qcolorBlackF(color: &QColor) -> f32;
194 #[doc(hidden)]
195 #[rust_name = "qcolor_blue_f"]
196 fn qcolorBlueF(color: &QColor) -> f32;
197 #[doc(hidden)]
198 #[rust_name = "qcolor_cyan_f"]
199 fn qcolorCyanF(color: &QColor) -> f32;
200 #[doc(hidden)]
201 #[rust_name = "qcolor_green_f"]
202 fn qcolorGreenF(color: &QColor) -> f32;
203 #[doc(hidden)]
204 #[rust_name = "qcolor_hsl_hue_f"]
205 fn qcolorHslHueF(color: &QColor) -> f32;
206 #[doc(hidden)]
207 #[rust_name = "qcolor_hsl_saturation_f"]
208 fn qcolorHslSaturationF(color: &QColor) -> f32;
209 #[doc(hidden)]
210 #[rust_name = "qcolor_hsv_hue_f"]
211 fn qcolorHsvHueF(color: &QColor) -> f32;
212 #[doc(hidden)]
213 #[rust_name = "qcolor_hsv_saturation_f"]
214 fn qcolorHsvSaturationF(color: &QColor) -> f32;
215 #[doc(hidden)]
216 #[rust_name = "qcolor_hue_f"]
217 fn qcolorHueF(color: &QColor) -> f32;
218 #[doc(hidden)]
219 #[rust_name = "qcolor_lightness_f"]
220 fn qcolorLightnessF(color: &QColor) -> f32;
221 #[doc(hidden)]
222 #[rust_name = "qcolor_magenta_f"]
223 fn qcolorMagentaF(color: &QColor) -> f32;
224 #[doc(hidden)]
225 #[rust_name = "qcolor_red_f"]
226 fn qcolorRedF(color: &QColor) -> f32;
227 #[doc(hidden)]
228 #[rust_name = "qcolor_saturation_f"]
229 fn qcolorSaturationF(color: &QColor) -> f32;
230 #[doc(hidden)]
231 #[rust_name = "qcolor_set_alpha_f"]
232 fn qcolorSetAlphaF(color: &mut QColor, alpha: f32);
233 #[doc(hidden)]
234 #[rust_name = "qcolor_set_blue_f"]
235 fn qcolorSetBlueF(color: &mut QColor, blue: f32);
236 #[doc(hidden)]
237 #[rust_name = "qcolor_set_cmyk_f"]
238 fn qcolorSetCmykF(color: &mut QColor, c: f32, m: f32, y: f32, k: f32, a: f32);
239 #[doc(hidden)]
240 #[rust_name = "qcolor_set_green_f"]
241 fn qcolorSetGreenF(color: &mut QColor, green: f32);
242 #[doc(hidden)]
243 #[rust_name = "qcolor_set_hsl_f"]
244 fn qcolorSetHslF(color: &mut QColor, h: f32, s: f32, l: f32, a: f32);
245 #[doc(hidden)]
246 #[rust_name = "qcolor_set_hsv_f"]
247 fn qcolorSetHsvF(color: &mut QColor, h: f32, s: f32, v: f32, a: f32);
248 #[doc(hidden)]
249 #[rust_name = "qcolor_set_red_f"]
250 fn qcolorSetRedF(color: &mut QColor, red: f32);
251 #[doc(hidden)]
252 #[rust_name = "qcolor_set_rgb_f"]
253 fn qcolorSetRgbF(color: &mut QColor, r: f32, g: f32, b: f32, a: f32);
254 #[doc(hidden)]
255 #[rust_name = "qcolor_value_f"]
256 fn qcolorValueF(color: &QColor) -> f32;
257 #[doc(hidden)]
258 #[rust_name = "qcolor_yellow_f"]
259 fn qcolorYellowF(color: &QColor) -> f32;
260 }
261
262 #[namespace = "rust::cxxqtlib1"]
263 unsafe extern "C++" {
264 include!("cxx-qt-lib/common.h");
265
266 #[doc(hidden)]
267 #[rust_name = "qcolor_init_default"]
268 fn construct() -> QColor;
269 #[doc(hidden)]
270 #[rust_name = "qcolor_init_from_qstring"]
271 fn construct(name: &QString) -> QColor;
272 #[doc(hidden)]
273 #[rust_name = "qcolor_eq"]
274 fn operatorEq(a: &QColor, b: &QColor) -> bool;
275 }
276}
277
278pub use ffi::{QColorNameFormat, QColorSpec};
279
280#[derive(Clone)]
284#[repr(C)]
285pub struct QColor {
286 _cspec: MaybeUninit<i32>,
287 _ct: MaybeUninit<[u16; 5]>,
288}
289
290impl QColor {
291 pub fn alpha_f(&self) -> f32 {
293 ffi::qcolor_alpha_f(self)
294 }
295
296 pub fn black_f(&self) -> f32 {
298 ffi::qcolor_black_f(self)
299 }
300
301 pub fn blue_f(&self) -> f32 {
303 ffi::qcolor_blue_f(self)
304 }
305
306 pub fn color_names() -> QStringList {
308 ffi::qcolor_color_names()
309 }
310
311 pub fn cyan_f(&self) -> f32 {
313 ffi::qcolor_cyan_f(self)
314 }
315
316 pub fn from_cmyk(c: i32, m: i32, y: i32, k: i32) -> Self {
318 ffi::qcolor_init_from_cmyk(c, m, y, k, 255)
319 }
320
321 pub fn from_cmyka(c: i32, m: i32, y: i32, k: i32, a: i32) -> Self {
323 ffi::qcolor_init_from_cmyk(c, m, y, k, a)
324 }
325
326 pub fn from_cmyk_f(c: f32, m: f32, y: f32, k: f32) -> Self {
328 ffi::qcolor_init_from_cmyk_f(c, m, y, k, 1.0)
329 }
330
331 pub fn from_cmyka_f(c: f32, m: f32, y: f32, k: f32, a: f32) -> Self {
333 ffi::qcolor_init_from_cmyk_f(c, m, y, k, a)
334 }
335
336 pub fn from_hsl(h: i32, s: i32, l: i32) -> Self {
338 ffi::qcolor_init_from_hsl(h, s, l, 255)
339 }
340
341 pub fn from_hsla(h: i32, s: i32, l: i32, a: i32) -> Self {
343 ffi::qcolor_init_from_hsl(h, s, l, a)
344 }
345
346 pub fn from_hsl_f(h: f32, s: f32, l: f32) -> Self {
348 ffi::qcolor_init_from_hsl_f(h, s, l, 1.0)
349 }
350
351 pub fn from_hsla_f(h: f32, s: f32, l: f32, a: f32) -> Self {
353 ffi::qcolor_init_from_hsl_f(h, s, l, a)
354 }
355
356 pub fn from_hsv(h: i32, s: i32, v: i32) -> Self {
358 ffi::qcolor_init_from_hsv(h, s, v, 255)
359 }
360
361 pub fn from_hsva(h: i32, s: i32, v: i32, a: i32) -> Self {
363 ffi::qcolor_init_from_hsv(h, s, v, a)
364 }
365
366 pub fn from_hsv_f(h: f32, s: f32, v: f32) -> Self {
368 ffi::qcolor_init_from_hsv_f(h, s, v, 1.0)
369 }
370
371 pub fn from_hsva_f(h: f32, s: f32, v: f32, a: f32) -> Self {
373 ffi::qcolor_init_from_hsv_f(h, s, v, a)
374 }
375
376 pub fn from_rgb(red: i32, green: i32, blue: i32) -> Self {
380 ffi::qcolor_init_from_rgb(red, green, blue, 255)
381 }
382
383 pub fn from_rgba(red: i32, green: i32, blue: i32, alpha: i32) -> Self {
387 ffi::qcolor_init_from_rgb(red, green, blue, alpha)
388 }
389
390 pub fn from_rgb_f(red: f32, green: f32, blue: f32) -> Self {
392 ffi::qcolor_init_from_rgb_f(red, green, blue, 1.0)
393 }
394
395 pub fn from_rgba_f(red: f32, green: f32, blue: f32, alpha: f32) -> Self {
397 ffi::qcolor_init_from_rgb_f(red, green, blue, alpha)
398 }
399
400 pub fn green_f(&self) -> f32 {
402 ffi::qcolor_green_f(self)
403 }
404
405 pub fn hsl_hue_f(&self) -> f32 {
407 ffi::qcolor_hsl_hue_f(self)
408 }
409
410 pub fn hsl_saturation_f(&self) -> f32 {
412 ffi::qcolor_hsl_saturation_f(self)
413 }
414
415 pub fn hsv_hue_f(&self) -> f32 {
417 ffi::qcolor_hsv_hue_f(self)
418 }
419
420 pub fn hsv_saturation_f(&self) -> f32 {
422 ffi::qcolor_hsv_saturation_f(self)
423 }
424
425 pub fn hue_f(self: &QColor) -> f32 {
429 ffi::qcolor_hue_f(self)
430 }
431
432 pub fn lightness_f(&self) -> f32 {
434 ffi::qcolor_lightness_f(self)
435 }
436
437 pub fn magenta_f(&self) -> f32 {
439 ffi::qcolor_magenta_f(self)
440 }
441
442 pub fn red_f(&self) -> f32 {
444 ffi::qcolor_red_f(self)
445 }
446
447 pub fn saturation_f(&self) -> f32 {
451 ffi::qcolor_saturation_f(self)
452 }
453
454 pub fn set_alpha_f(&mut self, alpha: f32) {
456 ffi::qcolor_set_alpha_f(self, alpha);
457 }
458
459 pub fn set_blue_f(&mut self, blue: f32) {
463 ffi::qcolor_set_blue_f(self, blue);
464 }
465
466 pub fn set_cmyk_f(&mut self, c: f32, m: f32, y: f32, k: f32, a: f32) {
470 ffi::qcolor_set_cmyk_f(self, c, m, y, k, a);
471 }
472
473 pub fn set_green_f(&mut self, green: f32) {
477 ffi::qcolor_set_green_f(self, green);
478 }
479
480 pub fn set_hsl_f(&mut self, h: f32, s: f32, l: f32, a: f32) {
484 ffi::qcolor_set_hsl_f(self, h, s, l, a);
485 }
486
487 pub fn set_hsv_f(&mut self, h: f32, s: f32, v: f32, a: f32) {
491 ffi::qcolor_set_hsv_f(self, h, s, v, a);
492 }
493
494 pub fn set_red_f(&mut self, red: f32) {
498 ffi::qcolor_set_red_f(self, red);
499 }
500
501 pub fn set_rgb_f(&mut self, r: f32, g: f32, b: f32, a: f32) {
505 ffi::qcolor_set_rgb_f(self, r, g, b, a);
506 }
507
508 pub fn value_f(self: &QColor) -> f32 {
510 ffi::qcolor_value_f(self)
511 }
512
513 pub fn yellow_f(self: &QColor) -> f32 {
515 ffi::qcolor_yellow_f(self)
516 }
517}
518
519impl Default for QColor {
520 fn default() -> Self {
524 ffi::qcolor_init_default()
525 }
526}
527
528impl TryFrom<&str> for QColor {
529 type Error = &'static str;
530
531 fn try_from(value: &str) -> Result<Self, Self::Error> {
532 Self::try_from(&QString::from(value))
533 }
534}
535
536impl TryFrom<&String> for QColor {
537 type Error = &'static str;
538
539 fn try_from(value: &String) -> Result<Self, Self::Error> {
540 Self::try_from(value.as_str())
541 }
542}
543
544impl TryFrom<&QString> for QColor {
545 type Error = &'static str;
546
547 fn try_from(value: &QString) -> Result<Self, Self::Error> {
548 let color = ffi::qcolor_init_from_qstring(value);
549 if color.is_valid() {
550 Ok(color)
551 } else {
552 Err("Invalid color")
553 }
554 }
555}
556
557impl std::cmp::PartialEq for QColor {
558 fn eq(&self, other: &Self) -> bool {
559 ffi::qcolor_eq(self, other)
560 }
561}
562
563impl std::cmp::Eq for QColor {}
564
565impl fmt::Display for QColor {
566 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
567 if f.width().is_some() || f.precision().is_some() {
568 #[allow(clippy::recursive_format_impl)]
569 return f.pad(&self.to_string());
570 }
571 let r = self.red();
573 let g = self.green();
574 let b = self.blue();
575 let a = self.alpha();
576 write!(f, "RGBA({r}, {g}, {b}, {a})")
577 }
578}
579
580impl fmt::Debug for QColor {
581 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
584 let r = self.red();
586 let g = self.green();
587 let b = self.blue();
588 let a = self.alpha();
589 let fg = if (r + b + g) < 384 { 255 } else { 0 };
591 write!(f, "\x1b[48;2;{r};{g};{b}m\x1b[38;2;{fg};{fg};{fg}mRGBA({r}, {g}, {b}, {a})\x1b[39m\x1b[49m")
593 }
594}
595
596#[cfg(feature = "rgb")]
597impl From<&rgb::RGB8> for QColor {
598 fn from(value: &rgb::RGB8) -> Self {
599 Self::from_rgb(value.r as i32, value.g as i32, value.b as i32)
600 }
601}
602
603#[cfg(feature = "rgb")]
604impl From<&rgb::RGBA8> for QColor {
605 fn from(value: &rgb::RGBA8) -> Self {
606 Self::from_rgba(
607 value.r as i32,
608 value.g as i32,
609 value.b as i32,
610 value.a as i32,
611 )
612 }
613}
614
615#[cfg(feature = "rgb")]
616impl From<&QColor> for rgb::RGB8 {
617 fn from(value: &QColor) -> Self {
618 Self {
619 r: value.red() as u8,
620 g: value.green() as u8,
621 b: value.blue() as u8,
622 }
623 }
624}
625
626#[cfg(feature = "rgb")]
627impl From<&QColor> for rgb::RGBA8 {
628 fn from(value: &QColor) -> Self {
629 Self {
630 r: value.red() as u8,
631 g: value.green() as u8,
632 b: value.blue() as u8,
633 a: value.alpha() as u8,
634 }
635 }
636}
637
638unsafe impl ExternType for QColor {
642 type Id = type_id!("QColor");
643 type Kind = cxx::kind::Trivial;
644}
645
646#[cfg(test)]
647mod tests {
648 #[cfg(feature = "rgb")]
649 use super::*;
650
651 #[cfg(feature = "rgb")]
652 #[test]
653 fn test_rgb() {
654 let color = rgb::RGB8 {
655 r: 0,
656 g: 100,
657 b: 255,
658 };
659 let qcolor = QColor::from(&color);
660 assert_eq!(qcolor.red(), 0);
661 assert_eq!(qcolor.green(), 100);
662 assert_eq!(qcolor.blue(), 255);
663 assert_eq!(qcolor.alpha(), 255);
664
665 let rgb_color = rgb::RGB8::from(&qcolor);
666 assert_eq!(color, rgb_color);
667 }
668
669 #[cfg(feature = "rgb")]
670 #[test]
671 fn test_rgba() {
672 let color = rgb::RGBA8 {
673 r: 0,
674 g: 100,
675 b: 255,
676 a: 100,
677 };
678 let qcolor = QColor::from(&color);
679 assert_eq!(qcolor.red(), 0);
680 assert_eq!(qcolor.green(), 100);
681 assert_eq!(qcolor.blue(), 255);
682 assert_eq!(qcolor.alpha(), 100);
683
684 let rgba_color = rgb::RGBA8::from(&qcolor);
685 assert_eq!(color, rgba_color);
686 }
687
688 #[test]
689 fn test_display_fmt() {
690 let qcolor = QColor::from_rgba(50, 100, 150, 200);
691 assert_eq!(format!("{qcolor:-<30}"), "RGBA(50, 100, 150, 200)-------");
692 }
693}