diff --git a/libs/pigment/KoColorConversions.cpp b/libs/pigment/KoColorConversions.cpp index 0a00c3383b..085033af8c 100644 --- a/libs/pigment/KoColorConversions.cpp +++ b/libs/pigment/KoColorConversions.cpp @@ -1,909 +1,908 @@ /* * Copyright (c) 2005 Boudewijn Rempt * Copyright (c) 2014 Wolthera van Hövell * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "KoColorConversions.h" #include #include /** * A number of often-used conversions between color models */ void rgb_to_hsv(int R, int G, int B, int *H, int *S, int *V) { unsigned int max = R; unsigned int min = R; unsigned char maxValue = 0; // r = 0, g = 1, b = 2 // find maximum and minimum RGB values if (static_cast(G) > max) { max = G; maxValue = 1; } if (static_cast(B) > max) { max = B; maxValue = 2; } if (static_cast(G) < min) min = G; if (static_cast(B) < min) min = B; int delta = max - min; *V = max; // value *S = max ? (510 * delta + max) / (2 * max) : 0; // saturation // calc hue if (*S == 0) *H = -1; // undefined hue else { switch (maxValue) { case 0: // red if (G >= B) *H = (120 * (G - B) + delta) / (2 * delta); else *H = (120 * (G - B + delta) + delta) / (2 * delta) + 300; break; case 1: // green if (B > R) *H = 120 + (120 * (B - R) + delta) / (2 * delta); else *H = 60 + (120 * (B - R + delta) + delta) / (2 * delta); break; case 2: // blue if (R > G) *H = 240 + (120 * (R - G) + delta) / (2 * delta); else *H = 180 + (120 * (R - G + delta) + delta) / (2 * delta); break; } } } void hsv_to_rgb(int H, int S, int V, int *R, int *G, int *B) { *R = *G = *B = V; if (S != 0 && H != -1) { // chromatic if (H >= 360) { // angle > 360 H %= 360; } unsigned int f = H % 60; H /= 60; unsigned int p = static_cast(2 * V * (255 - S) + 255) / 510; if (H & 1) { unsigned int q = static_cast(2 * V * (15300 - S * f) + 15300) / 30600; switch (H) { case 1: *R = static_cast(q); *G = static_cast(V); *B = static_cast(p); break; case 3: *R = static_cast(p); *G = static_cast(q); *B = static_cast(V); break; case 5: *R = static_cast(V); *G = static_cast(p); *B = static_cast(q); break; } } else { unsigned int t = static_cast(2 * V * (15300 - (S * (60 - f))) + 15300) / 30600; switch (H) { case 0: *R = static_cast(V); *G = static_cast(t); *B = static_cast(p); break; case 2: *R = static_cast(p); *G = static_cast(V); *B = static_cast(t); break; case 4: *R = static_cast(t); *G = static_cast(p); *B = static_cast(V); break; } } } } #define EPSILON 1e-6 #define UNDEFINED_HUE -1 void RGBToHSV(float r, float g, float b, float *h, float *s, float *v) { float max = qMax(r, qMax(g, b)); float min = qMin(r, qMin(g, b)); *v = max; if (max > EPSILON) { *s = (max - min) / max; } else { *s = 0; } if (*s < EPSILON) { *h = UNDEFINED_HUE; } else { float delta = max - min; if (r == max) { *h = (g - b) / delta; } else if (g == max) { *h = 2 + (b - r) / delta; } else { *h = 4 + (r - g) / delta; } *h *= 60; if (*h < 0) { *h += 360; } } } void HSVToRGB(float h, float s, float v, float *r, float *g, float *b) { if (s < EPSILON || h == UNDEFINED_HUE) { // Achromatic case *r = v; *g = v; *b = v; } else { float f, p, q, t; int i; if (h > 360 - EPSILON) { h -= 360; } h /= 60; i = static_cast(floor(h)); f = h - i; p = v * (1 - s); q = v * (1 - (s * f)); t = v * (1 - (s * (1 - f))); switch (i) { case 0: *r = v; *g = t; *b = p; break; case 1: *r = q; *g = v; *b = p; break; case 2: *r = p; *g = v; *b = t; break; case 3: *r = p; *g = q; *b = v; break; case 4: *r = t; *g = p; *b = v; break; case 5: *r = v; *g = p; *b = q; break; } } } void rgb_to_hls(quint8 red, quint8 green, quint8 blue, float * hue, float * lightness, float * saturation) { float r = red / 255.0; float g = green / 255.0; float b = blue / 255.0; float h = 0; float l = 0; float s = 0; float max, min, delta; max = qMax(r, g); max = qMax(max, b); min = qMin(r, g); min = qMin(min, b); delta = max - min; l = (max + min) / 2; if (delta == 0) { // This is a gray, no chroma... h = 0; s = 0; } else { if (l < 0.5) s = delta / (max + min); else s = delta / (2 - max - min); float delta_r, delta_g, delta_b; delta_r = ((max - r) / 6) / delta; delta_g = ((max - g) / 6) / delta; delta_b = ((max - b) / 6) / delta; if (r == max) h = delta_b - delta_g; else if (g == max) h = (1.0 / 3) + delta_r - delta_b; else if (b == max) h = (2.0 / 3) + delta_g - delta_r; if (h < 0) h += 1; if (h > 1) h += 1; } *hue = h * 360; *saturation = s; *lightness = l; } float hue_value(float n1, float n2, float hue) { if (hue > 360) hue = hue - 360; else if (hue < 0) hue = hue + 360; if (hue < 60) return n1 + (((n2 - n1) * hue) / 60); else if (hue < 180) return n2; else if (hue < 240) return n1 + (((n2 - n1) *(240 - hue)) / 60); else return n1; } void hls_to_rgb(float h, float l, float s, quint8 * r, quint8 * g, quint8 * b) { float m1, m2; if (l <= 0.5) m2 = l * (1 + s); else m2 = l + s - l * s; m1 = 2 * l - m2; *r = (quint8)(hue_value(m1, m2, h + 120) * 255 + 0.5); *g = (quint8)(hue_value(m1, m2, h) * 255 + 0.5); *b = (quint8)(hue_value(m1, m2, h - 120) * 255 + 0.5); } void rgb_to_hls(quint8 r, quint8 g, quint8 b, int * h, int * l, int * s) { float hue, saturation, lightness; rgb_to_hls(r, g, b, &hue, &lightness, &saturation); *h = (int)(hue + 0.5); *l = (int)(lightness * 255 + 0.5); *s = (int)(saturation * 255 + 0.5); } void hls_to_rgb(int h, int l, int s, quint8 * r, quint8 * g, quint8 * b) { float hue = h; float lightness = l / 255.0; float saturation = s / 255.0; hls_to_rgb(hue, lightness, saturation, r, g, b); } /* A Fast HSL-to-RGB Transform by Ken Fishkin from "Graphics Gems", Academic Press, 1990 */ void RGBToHSL(float r, float g, float b, float *h, float *s, float *l) { float v; float m; float vm; float r2, g2, b2; v = qMax(r, g); v = qMax(v, b); m = qMin(r, g); m = qMin(m, b); if ((*l = (m + v) / 2.0) <= 0.0) { *h = UNDEFINED_HUE; *s = 0; return; } if ((*s = vm = v - m) > 0.0) { *s /= (*l <= 0.5) ? (v + m) : (2.0 - v - m) ; } else { *h = UNDEFINED_HUE; return; } r2 = (v - r) / vm; g2 = (v - g) / vm; b2 = (v - b) / vm; if (r == v) *h = (g == m ? 5.0 + b2 : 1.0 - g2); else if (g == v) *h = (b == m ? 1.0 + r2 : 3.0 - b2); else *h = (r == m ? 3.0 + g2 : 5.0 - r2); *h *= 60; - if (*h == 360.) { - *h = 0; - } + *h = fmod(*h, 360.0); } void HSLToRGB(float h, float sl, float l, float *r, float *g, float *b) { float v; v = (l <= 0.5) ? (l * (1.0 + sl)) : (l + sl - l * sl); if (v <= 0) { *r = *g = *b = 0.0; } else { float m; float sv; int sextant; float fract, vsf, mid1, mid2; m = l + l - v; sv = (v - m) / v; + h = fmod(h, 360.0); h /= 60.0; sextant = static_cast(h); fract = h - sextant; vsf = v * sv * fract; mid1 = m + vsf; mid2 = v - vsf; switch (sextant) { case 0: *r = v; *g = mid1; *b = m; break; case 1: *r = mid2; *g = v; *b = m; break; case 2: *r = m; *g = v; *b = mid1; break; case 3: *r = m; *g = mid2; *b = v; break; case 4: *r = mid1; *g = m; *b = v; break; case 5: *r = v; *g = m; *b = mid2; break; } } } //functions for converting from and back to HSI void HSIToRGB(const qreal h,const qreal s, const qreal i, qreal *red, qreal *green, qreal *blue) {//This function takes H, S and I values, which are converted to rgb. qreal onethird = 1.0/3.0; HSYToRGB(h, s, i, red, green, blue, onethird, onethird, onethird); } void RGBToHSI(qreal r,qreal g, qreal b, qreal *h, qreal *s, qreal *i) { qreal onethird = 1.0/3.0; RGBToHSY(r, g, b, h, s, i, onethird, onethird, onethird); } //functions for converting from and back to hsy' void HSYToRGB(const qreal h,const qreal s, const qreal y, qreal *red, qreal *green, qreal *blue, qreal R, qreal G, qreal B) {//This function takes H, S and Y values, which are converted to rgb. //Those are then used to create a qcolor. qreal hue = 0.0; qreal sat = 0.0; qreal luma = 0.0; if (h>1.0 || h<0.0){hue=fmod(h, 1.0);} else {hue=h;} if (s<0.0){sat=0.0;} else {sat=s;} //if (y>1.0){luma=1.0;} if (y<0.0){luma=0.0;} else {luma=y;} qreal segment = 0.166667;//1/6; qreal r=0.0; qreal g=0.0; qreal b=0.0; //weights for rgb to Y'(Luma), these are the same weights used in color space maths and the desaturate. //This is not luminance or luminosity, it just quacks like it. //qreal R=0.299; //qreal G=0.587; //qreal B=0.114; //The intermediary variables for the weighted HSL forumala, based on the HSL in KoColorConversions. qreal max_sat, m, fract, luma_a, chroma, x; if (hue >= 0.0 && hue < (segment) ) { //need to treat this as a weighted hsl thingy. //so first things first, at which luma is the maximum saturation for this hue? //between R and G+R (yellow) max_sat = R + ( G*(hue*6) ); if (luma<=max_sat){luma_a = (luma/max_sat)*0.5; chroma=sat*2*luma_a;} else {luma_a = ((luma-max_sat)/(1-max_sat)*0.5)+0.5; chroma=sat*(2-2*luma_a);} fract = hue*6.0; x = (1-fabs(fmod(fract,2)-1))*chroma; r = chroma; g=x; b=0; m = luma-( (R*r)+(B*b)+(G*g) ); r += m; g += m; b += m; } else if (hue >= (segment) && hue < (2.0*segment) ) { max_sat = (G+R) - (R*(hue-segment)*6); if (luma= (2.0*segment) && hue < (3.0*segment) ) { max_sat = G + (B*(hue-2.0*segment)*6); if (luma= (3.0*segment) && hue < (4.0*segment) ) { max_sat = (G+B) - (G*(hue-3.0*segment)*6); if (luma= (4.0*segment) && hue < (5*segment) ) { max_sat = B + (R*((hue-4.0*segment)*6)); if (luma= (5.0*segment) && hue <= 1.0) { max_sat = (B+R) - (B*(hue-5.0*segment)*6); if (luma1.0){r=1.0;} //if (g>1.0){g=1.0;} //if (b>1.0){b=1.0;} //don't limit upwards due to floating point. if (r<0.0){r=0.0;} if (g<0.0){g=0.0;} if (b<0.0){b=0.0;} *red=r; *green=g; *blue=b; } void RGBToHSY(const qreal r,const qreal g,const qreal b, qreal *h, qreal *s, qreal *y, qreal R, qreal G, qreal B) { //This is LUMA btw, not Luminance. //Using these RGB values, we calculate the H, S and I. qreal red; qreal green; qreal blue; if (r<0.0){red=0.0;} else {red=r;} if (g<0.0){green=0.0;} else {green=g;} if (b<0.0){blue=0.0;} else {blue=b;} qreal minval = qMin(r, qMin(g, b)); qreal maxval = qMax(r, qMax(g, b)); qreal hue = 0.0; qreal sat = 0.0; qreal luma = 0.0; //weights for rgb, these are the same weights used in color space maths and the desaturate. //qreal R=0.299; //qreal G=0.587; //qreal B=0.114; luma=(R*red+G*green+B*blue); qreal luma_a=luma;//defined later qreal chroma = maxval-minval; qreal max_sat=0.5; if(chroma==0) { hue = 0.0; sat = 0.0; } else { //the following finds the hue if(maxval==r) { //hue = fmod(((g-b)/chroma), 6.0); //above doesn't work so let's try this one: if (minval==b) { hue = (g-b)/chroma; } else { hue = (g-b)/chroma + 6.0; } } else if(maxval==g) { hue = (b-r)/chroma + 2.0; } else if(maxval==b) { hue = (r-g)/chroma + 4.0; } hue /=6.0;//this makes sure that hue is in the 0-1.0 range. //Most HSY formula will tell you that Sat=Chroma. However, this HSY' formula tries to be a //weighted HSL formula, where instead of 0.5, we search for a Max_Sat value, which is the Y' //at which the saturation is maximum. //This requires using the hue, and combining the weighting values accordingly. qreal segment = 0.166667; if (hue>1.0 || hue<0.0) { hue=fmod(hue, 1.0); } if (hue>=0.0 && hue=segment && hue<(2.0*segment)) { max_sat = (G+R) - R*((hue-segment)*6); } else if (hue>=(2.0*segment) && hue<(3.0*segment)) { max_sat = G + B*((hue-2.0*segment)*6); } else if (hue>=(3.0*segment) && hue<(4.0*segment)) { max_sat = (B+G) - G*((hue-3.0*segment)*6); } else if (hue>=(4.0*segment) && hue<(5.0*segment)) { max_sat = (B) + R*((hue-4.0*segment)*6); } else if (hue>=(5.0*segment) && hue<=1.0) { max_sat = (R+B) - B*((hue-5.0*segment)*6); } else { max_sat=0.5; } if(max_sat>1.0 || max_sat<0.0){ //This should not show up during normal use max_sat=(fmod(max_sat,1.0)); } //If it does, it'll try to correct, but it's not good! //This is weighting the luma for the saturation) if (luma <= max_sat) { luma_a = (luma/max_sat)*0.5; } else{ luma_a = ((luma-max_sat)/(1-max_sat)*0.5)+0.5; } if (chroma > 0.0) { sat = (luma <= max_sat) ? (chroma/ (2*luma_a) ) :(chroma/(2.0-(2*luma_a) ) ) ; } } //if (sat>1.0){sat=1.0;} //if (luma>1.0){luma=1.0;} if (sat<0.0){sat=0.0;} if (luma<0.0){luma=0.0;} *h=hue; *s=sat; *y=luma; } //Extra: Functions for converting from and back to HCI. Where the HSI function is forced cylindrical, HCI is a //double cone. This is for compatibility purposes, and of course, making future programmers who expect a double-cone // function less sad. These algorithms were taken from wikipedia. void HCIToRGB(const qreal h, const qreal c, const qreal i, qreal *red, qreal *green, qreal *blue) { //This function may not be correct, but it's based on the HCY function on the basis of seeing HCI as similar //to the weighted HCY, but assuming that the weights are the same(one-third). qreal hue=0.0; qreal chroma=0.0; qreal intensity=0.0; if(i<0.0){intensity = 0.0;} else{intensity = i;} if (h>1.0 || h<0.0){hue=fmod(h, 1.0);} else {hue=h;} if(c<0.0){chroma = 0.0;} else{chroma = c;} const qreal onethird = 1.0/3.0; qreal r=0.0; qreal g=0.0; qreal b=0.0; int fract = static_cast(hue*6.0); qreal x = (1-fabs(fmod(hue*6.0,2)-1) )*chroma; switch (fract) { case 0:r = chroma; g=x; b=0;break; case 1:r = x; g=chroma; b=0;break; case 2:r = 0; g=chroma; b=x;break; case 3:r = 0; g=x; b=chroma;break; case 4:r = x; g=0; b=chroma;break; case 5:r = chroma; g=0; b=x;break; } qreal m = intensity-( onethird*(r+g+b) ); r += m; g += m; b += m; *red=r; *green=g; *blue=b; } void RGBToHCI(const qreal r,const qreal g,const qreal b, qreal *h, qreal *c, qreal *i) { qreal minval = qMin(r, qMin(g, b)); qreal maxval = qMax(r, qMax(g, b)); qreal hue = 0.0; qreal sat = 0.0; qreal intensity = 0.0; intensity=(r+g+b)/3.0; qreal chroma = maxval-minval; if(chroma==0) { hue = 0.0; sat = 0.0; } else { //the following finds the hue if(maxval==r) { if (minval==b) { hue = (g-b)/chroma; } else { hue = (g-b)/chroma + 6.0; } } else if(maxval==g) { hue = (b-r)/chroma + 2.0; } else if(maxval==b) { hue = (r-g)/chroma + 4.0; } hue /=6.0;//this makes sure that hue is in the 0-1.0 range. sat= 1-(minval/intensity); } *h=hue; *c=sat; *i=intensity; } void HCYToRGB(const qreal h, const qreal c, const qreal y, qreal *red, qreal *green, qreal *blue, qreal R, qreal G, qreal B) { qreal hue=0.0; qreal chroma=c; qreal luma=y; if (h>1.0 || h<0.0){hue=(fmod((h*2.0), 2.0))/2.0;} else {hue=h;} //const qreal R=0.299; //const qreal G=0.587; //const qreal B=0.114; qreal r=0.0; qreal g=0.0; qreal b=0.0; int fract =static_cast(hue*6.0); qreal x = (1-fabs(fmod(hue*6.0,2)-1) )*chroma; switch (fract) { case 0:r = chroma; g=x; b=0;break; case 1:r = x; g=chroma; b=0;break; case 2:r = 0; g=chroma; b=x;break; case 3:r = 0; g=x; b=chroma;break; case 4:r = x; g=0; b=chroma;break; case 5:r = chroma; g=0; b=x;break; } qreal m = luma-( (R*r)+(B*b)+(G*g) ); r += m; g += m; b += m; *red=r; *green=g; *blue=b; } void RGBToHCY(const qreal r,const qreal g,const qreal b, qreal *h, qreal *c, qreal *y, qreal R, qreal G, qreal B) { qreal minval = qMin(r, qMin(g, b)); qreal maxval = qMax(r, qMax(g, b)); qreal hue = 0.0; qreal chroma = 0.0; qreal luma = 0.0; //weights for rgb, these are the same weights used in color space maths and the desaturate. //qreal R=0.299; //qreal G=0.587; //qreal B=0.114; luma=(R*r+G*g+B*b); chroma = maxval-minval; if(chroma==0) { hue = 0.0; } else { //the following finds the hue if(maxval==r) { //hue = fmod(((g-b)/chroma), 6.0); //above doesn't work so let's try this one: if (minval==b) { hue = (g-b)/chroma; } else { hue = (g-b)/chroma + 6.0; } } else if(maxval==g) { hue = (b-r)/chroma + 2.0; } else if(maxval==b) { hue = (r-g)/chroma + 4.0; } hue /=6.0;//this makes sure that hue is in the 0-1.0 range. } if (chroma<0.0){chroma=0.0;} if (luma<0.0){luma=0.0;} *h=qBound(0.0,hue,1.0); *c=chroma; *y=luma; } void RGBToYUV(const qreal r,const qreal g,const qreal b, qreal *y, qreal *u, qreal *v, qreal R, qreal G, qreal B) { qreal uvmax = 0.5; qreal luma = R*r+G*g+B*b; qreal chromaBlue = uvmax*( (b - luma) / (1.0-B) ); qreal chromaRed = uvmax*( (r - luma) / (1.0-R) ); *y = luma; //qBound(0.0,luma,1.0); *u = chromaBlue+uvmax;//qBound(0.0,chromaBlue+ uvmax,1.0); *v = chromaRed+uvmax;//qBound(0.0,chromaRed + uvmax,1.0); } void YUVToRGB(const qreal y, const qreal u, const qreal v, qreal *r, qreal *g, qreal *b, qreal R, qreal G, qreal B) { qreal uvmax = 0.5; qreal chromaBlue = u-uvmax;//qBound(0.0,u,1.0)- uvmax;//put into -0.5-+0.5 range// qreal chromaRed = v-uvmax;//qBound(0.0,v,1.0)- uvmax; qreal negB = 1.0-B; qreal negR = 1.0-R; qreal red = y+(chromaRed * (negR / uvmax) ); qreal green = y-(chromaBlue * ((B*negB) / (uvmax*G)) ) - (chromaRed* ((R*negR) / (uvmax*G))); qreal blue = y+(chromaBlue * (negB / uvmax) ); *r=red;//qBound(0.0,red ,1.0); *g=green;//qBound(0.0,green,1.0); *b=blue;//qBound(0.0,blue ,1.0); } void LabToLCH(const qreal l, const qreal a, const qreal b, qreal *L, qreal *C, qreal *H) { qreal atemp = (a - 0.5)*10.0;//the multiplication is only so that we get out of floating-point maths qreal btemp = (b - 0.5)*10.0; *L=qBound(0.0,l,1.0); *C=sqrt( pow(atemp,2.0) + pow(btemp,2.0) )*0.1; qreal hue = (atan2(btemp,atemp))* 180.0 / M_PI; if (hue<0.0) { hue+=360.0; } else { hue = fmod(hue, 360.0); } *H=hue/360.0; } void LCHToLab(const qreal L, const qreal C, const qreal H, qreal *l, qreal *a, qreal *b) { qreal chroma = qBound(0.0,C,1.0); qreal hue = (qBound(0.0,H,1.0)*360.0)* M_PI / 180.0; *l=qBound(0.0,L,1.0); *a=(chroma * cos(hue) ) + 0.5; *b=(chroma * sin(hue) ) + 0.5; } void XYZToxyY(const qreal X, const qreal Y, const qreal Z, qreal *x, qreal *y, qreal *yY) { qBound(0.0,X,1.0); qBound(0.0,Y,1.0); qBound(0.0,Z,1.0); *x=X/(X+Y+Z); *y=Y/(X+Y+Z); *yY=Y; } void xyYToXYZ(const qreal x, const qreal y, const qreal yY, qreal *X, qreal *Y, qreal *Z) { qBound(0.0,x,1.0); qBound(0.0,y,1.0); qBound(0.0,yY,1.0); *X=(x*yY)/y; *Z=((1.0-x-y)/yY)/y; *Y=yY; } void CMYToCMYK(qreal *c, qreal *m, qreal *y, qreal *k) { qreal cyan, magenta, yellow, key = 1.0; cyan = *c; magenta = *m; yellow = *y; if ( cyan < key ) {key = cyan;} if ( magenta < key ) {key = magenta;} if ( yellow < key ) {key = yellow;} if ( key == 1 ) { //Black cyan = 0; magenta = 0; yellow = 0; } else { cyan = ( cyan - key ) / ( 1.0 - key ); magenta = ( magenta - key ) / ( 1.0 - key ); yellow = ( yellow - key ) / ( 1.0 - key ); } *c=qBound(0.0,cyan ,1.0); *m=qBound(0.0,magenta,1.0); *y=qBound(0.0,yellow ,1.0); *k=qBound(0.0,key ,1.0); } /*code from easyrgb.com*/ void CMYKToCMY(qreal *c, qreal *m, qreal *y, qreal *k) { qreal key = *k; qreal cyan = *c; qreal magenta = *m; qreal yellow = *y; cyan = ( cyan * ( 1.0 - key ) + key ); magenta = ( magenta * ( 1.0 - key ) + key ); yellow = ( yellow * ( 1.0 - key ) + key ); *c=qBound(0.0,cyan ,1.0); *m=qBound(0.0,magenta,1.0); *y=qBound(0.0,yellow ,1.0); } diff --git a/libs/pigment/KoColorDisplayRendererInterface.cpp b/libs/pigment/KoColorDisplayRendererInterface.cpp index a0b42b10b7..fb6b0a9165 100644 --- a/libs/pigment/KoColorDisplayRendererInterface.cpp +++ b/libs/pigment/KoColorDisplayRendererInterface.cpp @@ -1,80 +1,85 @@ /* * Copyright (c) 2014 Dmitry Kazakov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "KoColorDisplayRendererInterface.h" #include #include #include Q_GLOBAL_STATIC(KoDumbColorDisplayRenderer, s_instance) KoColorDisplayRendererInterface::KoColorDisplayRendererInterface() { } KoColorDisplayRendererInterface::~KoColorDisplayRendererInterface() { } QColor KoDumbColorDisplayRenderer::toQColor(const KoColor &c) const { return c.toQColor(); } KoColor KoDumbColorDisplayRenderer::approximateFromRenderedQColor(const QColor &c) const { KoColor color; color.fromQColor(c); return color; } KoColor KoDumbColorDisplayRenderer::fromHsv(int h, int s, int v, int a) const { h = qBound(0, h, 359); s = qBound(0, s, 255); v = qBound(0, v, 255); a = qBound(0, a, 255); QColor qcolor(QColor::fromHsv(h, s, v, a)); return KoColor(qcolor, KoColorSpaceRegistry::instance()->rgb8()); } void KoDumbColorDisplayRenderer::getHsv(const KoColor &srcColor, int *h, int *s, int *v, int *a) const { QColor qcolor = toQColor(srcColor); qcolor.getHsv(h, s, v, a); } KoColorDisplayRendererInterface* KoDumbColorDisplayRenderer::instance() { return s_instance; } qreal KoDumbColorDisplayRenderer::minVisibleFloatValue(const KoChannelInfo *chaninfo) const { Q_ASSERT(chaninfo); return chaninfo->getUIMin(); } qreal KoDumbColorDisplayRenderer::maxVisibleFloatValue(const KoChannelInfo *chaninfo) const { Q_ASSERT(chaninfo); return chaninfo->getUIMax(); } + +const KoColorSpace* KoDumbColorDisplayRenderer::getPaintingColorSpace() const +{ + return KoColorSpaceRegistry::instance()->rgb8(); +} diff --git a/libs/pigment/KoColorDisplayRendererInterface.h b/libs/pigment/KoColorDisplayRendererInterface.h index e52e01fd80..2e974767cc 100644 --- a/libs/pigment/KoColorDisplayRendererInterface.h +++ b/libs/pigment/KoColorDisplayRendererInterface.h @@ -1,109 +1,117 @@ /* * Copyright (c) 2014 Dmitry Kazakov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef __KO_COLOR_DISPLAY_RENDERER_INTERFACE_H #define __KO_COLOR_DISPLAY_RENDERER_INTERFACE_H #include #include #include #include "KoColor.h" class KoChannelInfo; /** * A special interface class provided by pigment to let widgets render * a KoColor on screen using custom profiling provided by the user. * * If you want to provide your own rendering of the KoColor on screen, * reimplement this class and provide its instance to a supporting * widget. */ class KRITAPIGMENT_EXPORT KoColorDisplayRendererInterface : public QObject { Q_OBJECT public: KoColorDisplayRendererInterface(); virtual ~KoColorDisplayRendererInterface(); /** * Convert the color \p c to a custom QColor that will be * displayed by the widget on screen. Please note, that the * reverse conversion may simply not exist. */ virtual QColor toQColor(const KoColor &c) const = 0; /** * This tries to approximate a rendered QColor into the KoColor * of the painting color space. Please note, that in most of the * cases the exact reverse transformation does not exist, so the * resulting color will be only a rough approximation. Never try * to do a round trip like that: * * // r will never be equal to c! * r = approximateFromRenderedQColor(toQColor(c)); */ virtual KoColor approximateFromRenderedQColor(const QColor &c) const = 0; virtual KoColor fromHsv(int h, int s, int v, int a = 255) const = 0; virtual void getHsv(const KoColor &srcColor, int *h, int *s, int *v, int *a = 0) const = 0; /** * \return the minimum value of a floating point channel that can * be seen on screen */ virtual qreal minVisibleFloatValue(const KoChannelInfo *chaninfo) const = 0; /** * \return the maximum value of a floating point channel that can * be seen on screen. In normal situation it is 1.0. When * the user changes exposure the value varies. */ virtual qreal maxVisibleFloatValue(const KoChannelInfo *chaninfo) const = 0; + /** + * @brief getColorSpace + * @return the painting color space, this is useful for determining the transform. + */ + virtual const KoColorSpace* getPaintingColorSpace() const = 0; + Q_SIGNALS: void displayConfigurationChanged(); private: Q_DISABLE_COPY(KoColorDisplayRendererInterface) }; /** * The default conversion class that just calls KoColor::toQColor() * conversion implementation which efectively renders the color into * sRGB color space. */ class KRITAPIGMENT_EXPORT KoDumbColorDisplayRenderer : public KoColorDisplayRendererInterface { public: QColor toQColor(const KoColor &c) const; KoColor approximateFromRenderedQColor(const QColor &c) const; KoColor fromHsv(int h, int s, int v, int a = 255) const; void getHsv(const KoColor &srcColor, int *h, int *s, int *v, int *a = 0) const; virtual qreal minVisibleFloatValue(const KoChannelInfo *chaninfo) const; virtual qreal maxVisibleFloatValue(const KoChannelInfo *chaninfo) const; + virtual const KoColorSpace* getPaintingColorSpace() const; + static KoColorDisplayRendererInterface* instance(); }; #endif /* __KO_COLOR_DISPLAY_RENDERER_INTERFACE_H */ diff --git a/libs/pigment/KoColorSpaceTraits.h b/libs/pigment/KoColorSpaceTraits.h index 1122353ab1..73fec601f6 100644 --- a/libs/pigment/KoColorSpaceTraits.h +++ b/libs/pigment/KoColorSpaceTraits.h @@ -1,225 +1,228 @@ /* * Copyright (c) 2006-2007 Cyrille Berger * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef _KO_COLORSPACE_TRAITS_H_ #define _KO_COLORSPACE_TRAITS_H_ #include #include "KoColorSpaceConstants.h" #include "KoColorSpaceMaths.h" #include "DebugPigment.h" /** * This class is the base class to define the main characteristics of a colorspace * which inherits KoColorSpaceAbstract. * * - _channels_type_ is the type of the value use for each channel, for example quint8 for 8bits per channel * color spaces, or quint16 for 16bits integer per channel, float for 32bits per channel * floating point color spaces * - _channels_nb_ is the total number of channels in an image (for example RGB is 3 but RGBA is four) * - _alpha_pos_ is the position of the alpha channel among the channels, if there is no alpha channel, * then _alpha_pos_ is set to -1 * * For instance a colorspace of three color channels and alpha channel in 16bits, * will be defined as KoColorSpaceTrait\. The same without the alpha * channel is KoColorSpaceTrait\ * */ template struct KoColorSpaceTrait { /// the type of the value of the channels of this color space typedef _channels_type_ channels_type; /// the number of channels in this color space static const quint32 channels_nb = _channels_nb_; /// the position of the alpha channel in the channels of the pixel (or -1 if no alpha /// channel. static const qint32 alpha_pos = _alpha_pos_; /// the number of bit for each channel static const int depth = KoColorSpaceMathsTraits<_channels_type_>::bits; /** * @return the size in byte of one pixel */ static const quint32 pixelSize = channels_nb * sizeof(channels_type); /** * @return the value of the alpha channel for this pixel in the 0..255 range */ inline static quint8 opacityU8(const quint8 * U8_pixel) { if (alpha_pos < 0) return OPACITY_OPAQUE_U8; channels_type c = nativeArray(U8_pixel)[alpha_pos]; return KoColorSpaceMaths::scaleToA(c); } inline static qreal opacityF(const quint8 * U8_pixel) { if (alpha_pos < 0) return OPACITY_OPAQUE_F; channels_type c = nativeArray(U8_pixel)[alpha_pos]; return KoColorSpaceMaths::scaleToA(c); } /** * Set the alpha channel for this pixel from a value in the 0..255 range */ inline static void setOpacity(quint8 * pixels, quint8 alpha, qint32 nPixels) { if (alpha_pos < 0) return; qint32 psize = pixelSize; channels_type valpha = KoColorSpaceMaths::scaleToA(alpha); for (; nPixels > 0; --nPixels, pixels += psize) { nativeArray(pixels)[alpha_pos] = valpha; } } inline static void setOpacity(quint8 * pixels, qreal alpha, qint32 nPixels) { if (alpha_pos < 0) return; qint32 psize = pixelSize; channels_type valpha = KoColorSpaceMaths::scaleToA(alpha); for (; nPixels > 0; --nPixels, pixels += psize) { nativeArray(pixels)[alpha_pos] = valpha; } } /** * Convenient function for transforming a quint8* array in a pointer of the native channels type */ inline static const channels_type* nativeArray(const quint8 * a) { return reinterpret_cast(a); } /** * Convenient function for transforming a quint8* array in a pointer of the native channels type */ inline static channels_type* nativeArray(quint8 * a) { return reinterpret_cast< channels_type*>(a); } /** * Allocate nPixels pixels for this colorspace. */ inline static quint8* allocate(quint32 nPixels) { return new quint8[ nPixels * pixelSize ]; } inline static void singleChannelPixel(quint8 *dstPixel, const quint8 *srcPixel, quint32 channelIndex) { const channels_type* src = nativeArray(srcPixel); channels_type* dst = nativeArray(dstPixel); for (uint i = 0; i < channels_nb; i++) { if (i != channelIndex) { dst[i] = 0; } else { dst[i] = src[i]; } } } inline static QString channelValueText(const quint8 *pixel, quint32 channelIndex) { if (channelIndex > channels_nb) return QString("Error"); channels_type c = nativeArray(pixel)[channelIndex]; return QString().setNum(c); } inline static QString normalisedChannelValueText(const quint8 *pixel, quint32 channelIndex) { if (channelIndex > channels_nb) return QString("Error"); channels_type c = nativeArray(pixel)[channelIndex]; return QString().setNum(100. *((qreal)c) / KoColorSpaceMathsTraits< channels_type>::unitValue); } inline static void normalisedChannelsValue(const quint8 *pixel, QVector &channels) { Q_ASSERT((int)channels.count() == (int)channels_nb); channels_type c; for (uint i = 0; i < channels_nb; i++) { c = nativeArray(pixel)[i]; channels[i] = ((qreal)c) / KoColorSpaceMathsTraits::unitValue; } } inline static void fromNormalisedChannelsValue(quint8 *pixel, const QVector &values) { Q_ASSERT((int)values.count() == (int)channels_nb); channels_type c; for (uint i = 0; i < channels_nb; i++) { - c = (channels_type) - ((float)KoColorSpaceMathsTraits::unitValue * values[i]); + float b = qBound((float)KoColorSpaceMathsTraits::min, + (float)KoColorSpaceMathsTraits::unitValue * values[i], + (float)KoColorSpaceMathsTraits::max); + c = (channels_type)b; nativeArray(pixel)[i] = c; + } } inline static void multiplyAlpha(quint8 * pixels, quint8 alpha, qint32 nPixels) { if (alpha_pos < 0) return; channels_type valpha = KoColorSpaceMaths::scaleToA(alpha); for (; nPixels > 0; --nPixels, pixels += pixelSize) { channels_type* alphapixel = nativeArray(pixels) + alpha_pos; *alphapixel = KoColorSpaceMaths::multiply(*alphapixel, valpha); } } inline static void applyAlphaU8Mask(quint8 * pixels, const quint8 * alpha, qint32 nPixels) { if (alpha_pos < 0) return; for (; nPixels > 0; --nPixels, pixels += pixelSize, ++alpha) { channels_type valpha = KoColorSpaceMaths::scaleToA(*alpha); channels_type* alphapixel = nativeArray(pixels) + alpha_pos; *alphapixel = KoColorSpaceMaths::multiply(*alphapixel, valpha); } } inline static void applyInverseAlphaU8Mask(quint8 * pixels, const quint8 * alpha, qint32 nPixels) { if (alpha_pos < 0) return; for (; nPixels > 0; --nPixels, pixels += pixelSize, ++alpha) { channels_type valpha = KoColorSpaceMaths::scaleToA(OPACITY_OPAQUE_U8 - *alpha); channels_type* alphapixel = nativeArray(pixels) + alpha_pos; *alphapixel = KoColorSpaceMaths::multiply(*alphapixel, valpha); } } inline static void applyAlphaNormedFloatMask(quint8 * pixels, const float * alpha, qint32 nPixels) { if (alpha_pos < 0) return; for (; nPixels > 0; --nPixels, pixels += pixelSize, ++alpha) { channels_type valpha = channels_type(KoColorSpaceMathsTraits::unitValue * (*alpha)); channels_type* alphapixel = nativeArray(pixels) + alpha_pos; *alphapixel = KoColorSpaceMaths::multiply(*alphapixel, valpha); } } inline static void applyInverseAlphaNormedFloatMask(quint8 * pixels, const float * alpha, qint32 nPixels) { if (alpha_pos < 0) return; for (; nPixels > 0; --nPixels, pixels += pixelSize, ++alpha) { channels_type valpha = channels_type(KoColorSpaceMathsTraits::unitValue * (1.0f - *alpha)); channels_type* alphapixel = nativeArray(pixels) + alpha_pos; *alphapixel = KoColorSpaceMaths::multiply(*alphapixel, valpha); } } }; #include "KoRgbColorSpaceTraits.h" #include "KoBgrColorSpaceTraits.h" #include "KoGrayColorSpaceTraits.h" #include "KoLabColorSpaceTraits.h" #include "KoXyzColorSpaceTraits.h" #include "KoYcbcrColorSpaceTraits.h" #include "KoCmykColorSpaceTraits.h" #endif diff --git a/libs/pigment/resources/KoColorSet.cpp b/libs/pigment/resources/KoColorSet.cpp index d4747e3bc5..524e3481b5 100644 --- a/libs/pigment/resources/KoColorSet.cpp +++ b/libs/pigment/resources/KoColorSet.cpp @@ -1,526 +1,557 @@ /* This file is part of the KDE project Copyright (c) 2005 Boudewijn Rempt This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include // qFromLittleEndian #include #include #include #include #include #include #include #include #include #include #include #include "KoColor.h" #include "KoColorSpaceRegistry.h" #include "KoColorModelStandardIds.h" KoColorSet::PaletteType detectFormat(const QString &fileName, const QByteArray &ba) { QFileInfo fi(fileName); // .pal if (ba.startsWith("RIFF") && ba.indexOf("PAL data", 8)) { return KoColorSet::RIFF_PAL; } // .gpl else if (ba.startsWith("GIMP Palette")) { return KoColorSet::GPL; } // .pal else if (ba.startsWith("JASC-PAL")) { return KoColorSet::PSP_PAL; } else if (fi.suffix().toLower() == "aco") { return KoColorSet::ACO; } else if (fi.suffix().toLower() == "act") { return KoColorSet::ACT; } return KoColorSet::UNKNOWN; } KoColorSet::KoColorSet(const QString& filename) : KoResource(filename) { // Implemented in KoResource class m_columns = 0; // Set the default value that the GIMP uses... } KoColorSet::KoColorSet() : KoResource("") { m_columns = 0; // Set the default value that the GIMP uses... } /// Create an copied palette KoColorSet::KoColorSet(const KoColorSet& rhs) : QObject(0) , KoResource("") { setFilename(rhs.filename()); m_ownData = false; m_name = rhs.m_name; m_comment = rhs.m_comment; m_columns = rhs.m_columns; m_colors = rhs.m_colors; setValid(true); } KoColorSet::~KoColorSet() { } bool KoColorSet::load() { QFile file(filename()); if (file.size() == 0) return false; if (!file.open(QIODevice::ReadOnly)) { warnPigment << "Can't open file " << filename(); return false; } bool res = loadFromDevice(&file); file.close(); return res; } bool KoColorSet::loadFromDevice(QIODevice *dev) { if (!dev->isOpen()) dev->open(QIODevice::ReadOnly); m_data = dev->readAll(); Q_ASSERT(m_data.size() != 0); return init(); } bool KoColorSet::save() { QFile file(filename()); if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { return false; } saveToDevice(&file); file.close(); return true; } qint32 KoColorSet::nColors() { return m_colors.count(); } +qint32 KoColorSet::getIndexClosestColor(KoColor color, bool useGivenColorSpace) +{ + qint32 closestIndex = 0; + quint8 highestPercentage = 0; + quint8 testPercentage = 0; + KoColor compare = color; + for (qint32 i=0; idifference(compare.data(), entry.data())); + if (testPercentage>highestPercentage) + { + closestIndex = i; + highestPercentage = testPercentage; + } + } + return closestIndex; +} + +QString KoColorSet::closestColorName(KoColor color, bool useGivenColorSpace) +{ + int i = getIndexClosestColor(color, useGivenColorSpace); + QString name = m_colors.at(i).name; + return name; +} + bool KoColorSet::saveToDevice(QIODevice *dev) const { QTextStream stream(dev); stream << "GIMP Palette\nName: " << name() << "\nColumns: " << m_columns << "\n#\n"; for (int i = 0; i < m_colors.size(); i++) { const KoColorSetEntry& entry = m_colors.at(i); QColor c = entry.color.toQColor(); stream << c.red() << " " << c.green() << " " << c.blue() << "\t"; if (entry.name.isEmpty()) stream << "Untitled\n"; else stream << entry.name << "\n"; } KoResource::saveToDevice(dev); return true; } bool KoColorSet::init() { m_colors.clear(); // just in case this is a reload (eg by KoEditColorSetDialog), if (filename().isNull()) { warnPigment << "Cannot load palette" << name() << "there is no filename set"; return false; } if (m_data.isNull()) { QFile file(filename()); if (file.size() == 0) { warnPigment << "Cannot load palette" << name() << "there is no data available"; return false; } file.open(QIODevice::ReadOnly); m_data = file.readAll(); file.close(); } bool res = false; PaletteType paletteType = detectFormat(filename(), m_data); switch(paletteType) { case GPL: res = loadGpl(); break; case ACT: res = loadAct(); break; case RIFF_PAL: res = loadRiff(); break; case PSP_PAL: res = loadPsp(); break; case ACO: res = loadAco(); break; default: res = false; } setValid(res); if (m_columns == 0) { m_columns = 10; } QImage img(m_columns * 4, (m_colors.size() / m_columns) * 4, QImage::Format_ARGB32); QPainter gc(&img); gc.fillRect(img.rect(), Qt::darkGray); int counter = 0; for(int i = 0; i < m_columns; ++i) { for (int j = 0; j < (m_colors.size() / m_columns); ++j) { if (counter < m_colors.size()) { QColor c = m_colors.at(counter).color.toQColor(); gc.fillRect(i * 4, j * 4, 4, 4, c); counter++; } else { break; } } } setImage(img); // save some memory m_data.clear(); return res; } void KoColorSet::add(const KoColorSetEntry & c) { m_colors.push_back(c); } void KoColorSet::remove(const KoColorSetEntry & c) { for (auto it = m_colors.begin(); it != m_colors.end(); /*noop*/) { if ((*it) == c) { it = m_colors.erase(it); return; } ++it; } } void KoColorSet::removeAt(quint32 index) { m_colors.remove(index); } KoColorSetEntry KoColorSet::getColor(quint32 index) { return m_colors[index]; } void KoColorSet::setColumnCount(int columns) { m_columns = columns; } int KoColorSet::columnCount() { return m_columns; } QString KoColorSet::defaultFileExtension() const { return QString(".gpl"); } bool KoColorSet::loadGpl() { QString s = QString::fromUtf8(m_data.data(), m_data.count()); if (s.isEmpty() || s.isNull() || s.length() < 50) { warnPigment << "Illegal Gimp palette file: " << filename(); return false; } quint32 index = 0; QStringList lines = s.split('\n', QString::SkipEmptyParts); if (lines.size() < 3) { return false; } QString columns; qint32 r, g, b; KoColorSetEntry e; // Read name if (!lines[0].startsWith("GIMP") || !lines[1].startsWith("Name: ")) { warnPigment << "Illegal Gimp palette file: " << filename(); return false; } setName(i18n(lines[1].mid(strlen("Name: ")).trimmed().toLatin1())); index = 2; // Read columns if (lines[index].startsWith("Columns: ")) { columns = lines[index].mid(strlen("Columns: ")).trimmed(); m_columns = columns.toInt(); index = 3; } for (qint32 i = index; i < lines.size(); i++) { if (lines[i].startsWith('#')) { m_comment += lines[i].mid(1).trimmed() + ' '; } else if (!lines[i].isEmpty()) { QStringList a = lines[i].replace('\t', ' ').split(' ', QString::SkipEmptyParts); if (a.count() < 3) { break; } r = a[0].toInt(); a.pop_front(); g = a[0].toInt(); a.pop_front(); b = a[0].toInt(); a.pop_front(); r = qBound(0, r, 255); g = qBound(0, g, 255); b = qBound(0, b, 255); e.color = KoColor(KoColorSpaceRegistry::instance()->rgb8()); e.color.fromQColor(QColor(r, g, b)); QString name = a.join(" "); e.name = name.isEmpty() ? i18n("Untitled") : name; add(e); } } return true; } bool KoColorSet::loadAct() { QFileInfo info(filename()); setName(info.baseName()); KoColorSetEntry e; for (int i = 0; i < m_data.size(); i += 3) { quint8 r = m_data[i]; quint8 g = m_data[i+1]; quint8 b = m_data[i+2]; e.color = KoColor(KoColorSpaceRegistry::instance()->rgb8()); e.color.fromQColor(QColor(r, g, b)); add(e); } return true; } struct RiffHeader { quint32 riff; quint32 size; quint32 signature; quint32 data; quint32 datasize; quint16 version; quint16 colorcount; }; bool KoColorSet::loadRiff() { // http://worms2d.info/Palette_file QFileInfo info(filename()); setName(info.baseName()); KoColorSetEntry e; RiffHeader header; memcpy(&header, m_data.constData(), sizeof(RiffHeader)); header.colorcount = qFromBigEndian(header.colorcount); for (int i = sizeof(RiffHeader); (i < (int)(sizeof(RiffHeader) + header.colorcount) && i < m_data.size()); i += 4) { quint8 r = m_data[i]; quint8 g = m_data[i+1]; quint8 b = m_data[i+2]; e.color = KoColor(KoColorSpaceRegistry::instance()->rgb8()); e.color.fromQColor(QColor(r, g, b)); add(e); } return true; } bool KoColorSet::loadPsp() { QFileInfo info(filename()); setName(info.baseName()); KoColorSetEntry e; qint32 r, g, b; QString s = QString::fromUtf8(m_data.data(), m_data.count()); QStringList l = s.split('\n', QString::SkipEmptyParts); if (l.size() < 4) return false; if (l[0] != "JASC-PAL") return false; if (l[1] != "0100") return false; int entries = l[2].toInt(); for (int i = 0; i < entries; ++i) { QStringList a = l[i + 3].replace('\t', ' ').split(' ', QString::SkipEmptyParts); if (a.count() != 3) { continue; } r = a[0].toInt(); a.pop_front(); g = a[0].toInt(); a.pop_front(); b = a[0].toInt(); a.pop_front(); r = qBound(0, r, 255); g = qBound(0, g, 255); b = qBound(0, b, 255); e.color = KoColor(KoColorSpaceRegistry::instance()->rgb8()); e.color.fromQColor(QColor(r, g, b)); QString name = a.join(" "); e.name = name.isEmpty() ? i18n("Untitled") : name; add(e); } return true; } quint16 readShort(QIODevice *io) { quint16 val; quint64 read = io->read((char*)&val, 2); if (read != 2) return false; return qFromBigEndian(val); } bool KoColorSet::loadAco() { QFileInfo info(filename()); setName(info.baseName()); QBuffer buf(&m_data); buf.open(QBuffer::ReadOnly); quint16 version = readShort(&buf); quint16 numColors = readShort(&buf); KoColorSetEntry e; const quint16 quint16_MAX = 65535; for (int i = 0; i < numColors && !buf.atEnd(); ++i) { quint16 colorSpace = readShort(&buf); quint16 ch1 = readShort(&buf); quint16 ch2 = readShort(&buf); quint16 ch3 = readShort(&buf); quint16 ch4 = readShort(&buf); bool skip = false; if (colorSpace == 0) { // RGB e.color = KoColor(KoColorSpaceRegistry::instance()->rgb16()); reinterpret_cast(e.color.data())[0] = ch3; reinterpret_cast(e.color.data())[1] = ch2; reinterpret_cast(e.color.data())[2] = ch1; e.color.setOpacity(OPACITY_OPAQUE_U8); } else if (colorSpace == 1) { // HSB e.color = KoColor(KoColorSpaceRegistry::instance()->rgb16()); QColor c; c.setHsvF(ch1 / 65536.0, ch2 / 65536.0, ch3 / 65536.0); e.color.fromQColor(c); e.color.setOpacity(OPACITY_OPAQUE_U8); } else if (colorSpace == 2) { // CMYK e.color = KoColor(KoColorSpaceRegistry::instance()->colorSpace(CMYKAColorModelID.id(), Integer16BitsColorDepthID.id(), "")); reinterpret_cast(e.color.data())[0] = quint16_MAX - ch1; reinterpret_cast(e.color.data())[1] = quint16_MAX - ch2; reinterpret_cast(e.color.data())[2] = quint16_MAX - ch3; reinterpret_cast(e.color.data())[3] = quint16_MAX - ch4; e.color.setOpacity(OPACITY_OPAQUE_U8); } else if (colorSpace == 7) { // LAB e.color = KoColor(KoColorSpaceRegistry::instance()->lab16()); reinterpret_cast(e.color.data())[0] = ch3; reinterpret_cast(e.color.data())[1] = ch2; reinterpret_cast(e.color.data())[2] = ch1; e.color.setOpacity(OPACITY_OPAQUE_U8); } else if (colorSpace == 8) { // GRAY e.color = KoColor(KoColorSpaceRegistry::instance()->colorSpace(GrayAColorModelID.id(), Integer16BitsColorDepthID.id(), "")); reinterpret_cast(e.color.data())[0] = ch1 * (quint16_MAX / 10000); e.color.setOpacity(OPACITY_OPAQUE_U8); } else { warnPigment << "Unsupported colorspace in palette" << filename() << "(" << colorSpace << ")"; skip = true; } if (version == 2) { quint16 v2 = readShort(&buf); if (v2 != 2) { warnPigment << "Version 2 block is not version 2" << filename() << "(" << v2 << ")"; return false; } quint16 size = readShort(&buf); QByteArray ba = buf.read(size); if (ba.size() != size) { warnPigment << "Version 2 name block is the wrong size" << filename(); return false; } e.name = QString::fromUtf8(ba.constData(), ba.size()); } if (!skip) { add(e); } } return true; } diff --git a/libs/pigment/resources/KoColorSet.h b/libs/pigment/resources/KoColorSet.h index a87d10442e..af9f436452 100644 --- a/libs/pigment/resources/KoColorSet.h +++ b/libs/pigment/resources/KoColorSet.h @@ -1,108 +1,128 @@ /* This file is part of the KDE project Copyright (c) 2005 Boudewijn Rempt This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef KOCOLORSET #define KOCOLORSET #include #include #include #include #include "KoColor.h" struct KoColorSetEntry { KoColor color; QString name; bool operator==(const KoColorSetEntry& rhs) const { return color == rhs.color && name == rhs.name; } }; /** * Open Gimp, Photoshop or RIFF palette files. This is a straight port * from the Gimp. */ class KRITAPIGMENT_EXPORT KoColorSet : public QObject, public KoResource { Q_OBJECT public: enum PaletteType { UNKNOWN = 0, GPL, // GIMP RIFF_PAL, // RIFF ACT, // Photoshop binary PSP_PAL, // PaintShop Pro ACO // Photoshop Swatches }; /** * Load a color set from a file. This can be a Gimp * palette, a RIFF palette or a Photoshop palette. */ explicit KoColorSet(const QString &filename); /// Create an empty color set KoColorSet(); /// Explicit copy constructor (KoResource copy constructor is private) KoColorSet(const KoColorSet& rhs); virtual ~KoColorSet(); virtual bool load(); virtual bool loadFromDevice(QIODevice *dev); virtual bool save(); virtual bool saveToDevice(QIODevice* dev) const; virtual QString defaultFileExtension() const; void setColumnCount(int columns); int columnCount(); public: void add(const KoColorSetEntry &); void remove(const KoColorSetEntry &); void removeAt(quint32 index); KoColorSetEntry getColor(quint32 index); qint32 nColors(); + /** + * @brief getIndexClosestColor + * function that matches the color to all colors in the colorset, and returns the index + * of the closest match. + * @param color the color you wish to compare. + * @param useGivenColorSpace whether to use the color space of the color given + * when the two colors' colorspaces don't match. Else it'll use the entry's colorspace. + * @return returns the int of the closest match. + */ + qint32 getIndexClosestColor(KoColor color, bool useGivenColorSpace = true); + + /** + * @brief closestColorName + * convenience function to get the name of the closest match. + * @param color + * @param useGivenColorSpace + * @return + */ + QString closestColorName(KoColor color, bool useGivenColorSpace = true); + private: bool init(); bool loadGpl(); bool loadAct(); bool loadRiff(); bool loadPsp(); bool loadAco(); QByteArray m_data; bool m_ownData; QString m_name; QString m_comment; qint32 m_columns; QVector m_colors; }; #endif // KOCOLORSET diff --git a/libs/ui/CMakeLists.txt b/libs/ui/CMakeLists.txt index 0cb23da1bc..76df00d3cc 100644 --- a/libs/ui/CMakeLists.txt +++ b/libs/ui/CMakeLists.txt @@ -1,542 +1,549 @@ # Disable -Wswitch because of the extra definitions we here: # kis_input_manager.cpp: In member function ‘virtual bool KisInputManager::eventFilter(QObject*, QEvent*)’: # warning: case value ‘1001’ not in enumerated type ‘QEvent::Type’ [-Wswitch] # warning: case value ‘1002’ not in enumerated type ‘QEvent::Type’ [-Wswitch] if (CMAKE_COMPILER_IS_GNUCXX) add_definitions(${KDE4_ENABLE_EXCEPTIONS} -Wno-switch) endif () include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/qtlockedfile ${EXIV2_INCLUDE_DIR} ) include_directories(SYSTEM ${EIGEN3_INCLUDE_DIR} ${OCIO_INCLUDE_DIR} ${Boost_INCLUDE_DIRS} ) add_subdirectory( tests ) if (APPLE) find_library(FOUNDATION_LIBRARY Foundation) endif () set(kritaui_LIB_SRCS canvas/kis_canvas_widget_base.cpp canvas/kis_canvas2.cpp canvas/kis_canvas_updates_compressor.cpp canvas/kis_canvas_controller.cpp canvas/kis_paintop_transformation_connector.cpp canvas/kis_display_color_converter.cpp canvas/kis_display_filter.cpp canvas/kis_exposure_gamma_correction_interface.cpp canvas/kis_tool_proxy.cpp canvas/kis_canvas_decoration.cc canvas/kis_coordinates_converter.cpp canvas/kis_grid_manager.cpp canvas/kis_grid_decoration.cpp canvas/kis_grid_config.cpp canvas/kis_prescaled_projection.cpp canvas/kis_qpainter_canvas.cpp canvas/kis_projection_backend.cpp canvas/kis_update_info.cpp canvas/kis_image_patch.cpp canvas/kis_image_pyramid.cpp canvas/kis_infinity_manager.cpp canvas/kis_change_guides_command.cpp canvas/kis_guides_decoration.cpp canvas/kis_guides_manager.cpp canvas/kis_guides_config.cpp canvas/kis_snap_config.cpp canvas/kis_snap_line_strategy.cpp dialogs/kis_about_application.cpp dialogs/kis_dlg_adj_layer_props.cc dialogs/kis_dlg_adjustment_layer.cc dialogs/kis_dlg_filter.cpp dialogs/kis_dlg_generator_layer.cpp dialogs/kis_dlg_file_layer.cpp dialogs/kis_dlg_image_properties.cc dialogs/kis_dlg_layer_properties.cc dialogs/kis_dlg_preferences.cc dialogs/slider_and_spin_box_sync.cpp dialogs/kis_dlg_blacklist_cleanup.cpp dialogs/kis_dlg_layer_style.cpp dialogs/kis_dlg_png_import.cpp dialogs/kis_dlg_import_image_sequence.cpp dialogs/kis_delayed_save_dialog.cpp + dialogs/kis_dlg_internal_color_selector.cpp flake/kis_node_dummies_graph.cpp flake/kis_dummies_facade_base.cpp flake/kis_dummies_facade.cpp flake/kis_node_shapes_graph.cpp flake/kis_node_shape.cpp flake/kis_shape_controller.cpp flake/kis_shape_layer.cc flake/kis_shape_layer_canvas.cpp flake/kis_shape_selection.cpp flake/kis_shape_selection_canvas.cpp flake/kis_shape_selection_model.cpp flake/kis_take_all_shapes_command.cpp brushhud/kis_uniform_paintop_property_widget.cpp brushhud/kis_brush_hud.cpp brushhud/kis_round_hud_button.cpp brushhud/kis_dlg_brush_hud_config.cpp brushhud/kis_brush_hud_properties_list.cpp brushhud/kis_brush_hud_properties_config.cpp kis_aspect_ratio_locker.cpp kis_autogradient.cc kis_bookmarked_configurations_editor.cc kis_bookmarked_configurations_model.cc kis_bookmarked_filter_configurations_model.cc kis_canvas_resource_provider.cpp kis_derived_resources.cpp kis_categories_mapper.cpp kis_categorized_list_model.cpp kis_categorized_item_delegate.cpp kis_clipboard.cc kis_config.cc kis_config_notifier.cpp kis_control_frame.cpp kis_composite_ops_model.cc kis_paint_ops_model.cpp kis_cursor.cc kis_cursor_cache.cpp kis_custom_pattern.cc kis_file_layer.cpp kis_safe_document_loader.cpp kis_splash_screen.cpp kis_filter_manager.cc kis_filters_model.cc kis_histogram_view.cc kis_image_manager.cc kis_image_view_converter.cpp kis_import_catcher.cc kis_layer_manager.cc kis_mask_manager.cc kis_mimedata.cpp kis_node_commands_adapter.cpp kis_node_manager.cpp kis_node_juggler_compressed.cpp kis_node_selection_adapter.cpp kis_node_insertion_adapter.cpp kis_node_model.cpp kis_node_filter_proxy_model.cpp kis_model_index_converter_base.cpp kis_model_index_converter.cpp kis_model_index_converter_show_all.cpp kis_painting_assistant.cc kis_painting_assistants_decoration.cpp kis_painting_assistants_manager.cpp kis_paintop_box.cc kis_paintop_option.cpp kis_paintop_options_model.cpp kis_paintop_settings_widget.cpp kis_popup_palette.cpp kis_png_converter.cpp kis_preference_set_registry.cpp kis_resource_server_provider.cpp kis_selection_decoration.cc kis_selection_manager.cc kis_statusbar.cc kis_zoom_manager.cc kis_favorite_resource_manager.cpp kis_workspace_resource.cpp kis_action.cpp kis_action_manager.cpp kis_view_plugin.cpp kis_canvas_controls_manager.cpp kis_tooltip_manager.cpp kis_multinode_property.cpp kis_async_action_feedback.cpp kisexiv2/kis_exif_io.cpp kisexiv2/kis_exiv2.cpp kisexiv2/kis_iptc_io.cpp kisexiv2/kis_xmp_io.cpp kra/kis_kra_utils.cpp kra/kis_kra_load_visitor.cpp kra/kis_kra_loader.cpp kra/kis_kra_save_visitor.cpp kra/kis_kra_saver.cpp kra/kis_kra_savexml_visitor.cpp opengl/kis_opengl.cpp opengl/kis_opengl_canvas2.cpp opengl/kis_opengl_canvas_debugger.cpp opengl/kis_opengl_image_textures.cpp opengl/kis_texture_tile.cpp kis_fps_decoration.cpp ora/kis_open_raster_stack_load_visitor.cpp ora/kis_open_raster_stack_save_visitor.cpp ora/ora_load_context.cc ora/ora_save_context.cc recorder/kis_node_query_path_editor.cc recorder/kis_recorded_action_creator.cc recorder/kis_recorded_action_creator_factory.cc recorder/kis_recorded_action_creator_factory_registry.cc recorder/kis_recorded_action_editor_factory.cc recorder/kis_recorded_action_editor_factory_registry.cc recorder/kis_recorded_filter_action_editor.cc recorder/kis_recorded_filter_action_creator.cpp recorder/kis_recorded_paint_action_editor.cc tool/kis_selection_tool_helper.cpp tool/kis_selection_tool_config_widget_helper.cpp tool/kis_rectangle_constraint_widget.cpp tool/kis_shape_tool_helper.cpp tool/kis_tool.cc tool/kis_delegated_tool_policies.cpp tool/kis_tool_freehand.cc tool/kis_speed_smoother.cpp tool/kis_painting_information_builder.cpp tool/kis_stabilized_events_sampler.cpp tool/kis_tool_freehand_helper.cpp tool/kis_tool_multihand_helper.cpp tool/kis_figure_painting_tool_helper.cpp tool/kis_recording_adapter.cpp tool/kis_tool_paint.cc tool/kis_tool_shape.cc tool/kis_tool_ellipse_base.cpp tool/kis_tool_rectangle_base.cpp tool/kis_tool_polyline_base.cpp tool/kis_tool_utils.cpp tool/kis_resources_snapshot.cpp tool/kis_smoothing_options.cpp tool/strokes/freehand_stroke.cpp tool/strokes/kis_painter_based_stroke_strategy.cpp tool/strokes/kis_filter_stroke_strategy.cpp tool/strokes/kis_color_picker_stroke_strategy.cpp widgets/kis_cmb_composite.cc widgets/kis_cmb_contour.cpp widgets/kis_cmb_gradient.cpp widgets/kis_paintop_list_widget.cpp widgets/kis_cmb_idlist.cc widgets/kis_color_space_selector.cc widgets/kis_advanced_color_space_selector.cc widgets/kis_cie_tongue_widget.cpp widgets/kis_tone_curve_widget.cpp widgets/kis_curve_widget.cpp widgets/kis_custom_image_widget.cc widgets/kis_image_from_clipboard_widget.cpp widgets/kis_double_widget.cc widgets/kis_filter_selector_widget.cc widgets/kis_gradient_chooser.cc widgets/kis_gradient_slider_widget.cc widgets/kis_gradient_slider.cpp widgets/kis_iconwidget.cc widgets/kis_mask_widgets.cpp widgets/kis_meta_data_merge_strategy_chooser_widget.cc widgets/kis_multi_bool_filter_widget.cc widgets/kis_multi_double_filter_widget.cc widgets/kis_multi_integer_filter_widget.cc widgets/kis_multipliers_double_slider_spinbox.cpp widgets/kis_paintop_presets_popup.cpp widgets/kis_tool_options_popup.cpp widgets/kis_paintop_presets_chooser_popup.cpp widgets/kis_pattern_chooser.cc widgets/kis_popup_button.cc widgets/kis_preset_chooser.cpp widgets/kis_progress_widget.cpp widgets/kis_selection_options.cc widgets/kis_scratch_pad.cpp widgets/kis_scratch_pad_event_filter.cpp widgets/kis_preset_selector_strip.cpp widgets/kis_slider_spin_box.cpp widgets/kis_size_group.cpp widgets/kis_size_group_p.cpp widgets/kis_wdg_generator.cpp widgets/kis_workspace_chooser.cpp widgets/squeezedcombobox.cpp widgets/kis_categorized_list_view.cpp widgets/kis_widget_chooser.cpp widgets/kis_tool_button.cpp widgets/kis_floating_message.cpp widgets/kis_lod_availability_widget.cpp widgets/kis_color_label_selector_widget.cpp widgets/kis_color_filter_combo.cpp widgets/kis_elided_label.cpp - + widgets/kis_spinbox_color_selector.cpp + widgets/kis_screen_color_picker.cpp + widgets/kis_visual_color_selector.cpp + widgets/KoDualColorButton.cpp + widgets/kis_color_input.cpp + widgets/kis_color_button.cpp input/kis_input_manager.cpp input/kis_input_manager_p.cpp input/kis_extended_modifiers_mapper.cpp input/kis_abstract_input_action.cpp input/kis_tool_invocation_action.cpp input/kis_pan_action.cpp input/kis_alternate_invocation_action.cpp input/kis_rotate_canvas_action.cpp input/kis_zoom_action.cpp input/kis_change_frame_action.cpp input/kis_gamma_exposure_action.cpp input/kis_show_palette_action.cpp input/kis_change_primary_setting_action.cpp input/kis_abstract_shortcut.cpp input/kis_single_action_shortcut.cpp input/kis_stroke_shortcut.cpp input/kis_shortcut_matcher.cpp input/kis_select_layer_action.cpp operations/kis_operation.cpp operations/kis_operation_configuration.cpp operations/kis_operation_registry.cpp operations/kis_operation_ui_factory.cpp operations/kis_operation_ui_widget.cpp operations/kis_filter_selection_operation.cpp actions/kis_selection_action_factories.cpp input/kis_touch_shortcut.cpp kis_document_undo_store.cpp kis_transaction_based_command.cpp kis_gui_context_command.cpp kis_gui_context_command_p.cpp input/kis_tablet_debugger.cpp input/kis_input_profile_manager.cpp input/kis_input_profile.cpp input/kis_shortcut_configuration.cpp input/config/kis_input_configuration_page.cpp input/config/kis_edit_profiles_dialog.cpp input/config/kis_input_profile_model.cpp input/config/kis_input_configuration_page_item.cpp input/config/kis_action_shortcuts_model.cpp input/config/kis_input_type_delegate.cpp input/config/kis_input_mode_delegate.cpp input/config/kis_input_button.cpp input/config/kis_input_editor_delegate.cpp input/config/kis_mouse_input_editor.cpp input/config/kis_wheel_input_editor.cpp input/config/kis_key_input_editor.cpp processing/fill_processing_visitor.cpp kis_asl_layer_style_serializer.cpp kis_psd_layer_style_resource.cpp canvas/kis_mirror_axis.cpp kis_abstract_perspective_grid.cpp KisApplication.cpp KisAutoSaveRecoveryDialog.cpp KisDetailsPane.cpp KisDocument.cpp KisNodeDelegate.cpp kis_node_view_visibility_delegate.cpp KisNodeToolTip.cpp KisNodeView.cpp kis_node_view_color_scheme.cpp KisFilterChain.cpp KisFilterChainLink.cpp KisFilterChainLinkList.cpp KisImportExportFilter.cpp KisFilterEdge.cpp KisFilterEntry.cpp KisFilterGraph.cpp KisImportExportManager.cpp KisFilterVertex.cpp KisMainWindow.cpp KisOpenPane.cpp KisPart.cpp KisPrintJob.cpp KisTemplate.cpp KisTemplateCreateDia.cpp KisTemplateGroup.cpp KisTemplates.cpp KisTemplatesPane.cpp KisTemplateTree.cpp KisUndoStackAction.cpp KisView.cpp thememanager.cpp kis_mainwindow_observer.cpp KisViewManager.cpp kis_mirror_manager.cpp qtlockedfile/qtlockedfile.cpp qtsingleapplication/qtlocalpeer.cpp qtsingleapplication/qtsingleapplication.cpp KisResourceBundle.cpp KisResourceBundleManifest.cpp kis_md5_generator.cpp KisApplicationArguments.cpp KisNetworkAccessManager.cpp KisMultiFeedRSSModel.cpp KisRemoteFileFetcher.cpp KisPaletteModel.cpp KisColorsetChooser.cpp KisSaveGroupVisitor.cpp ) if(WIN32) if (NOT Qt5Gui_PRIVATE_INCLUDE_DIRS) message(FATAL_ERROR "Qt5Gui Private header are missing!") endif() set(kritaui_LIB_SRCS ${kritaui_LIB_SRCS} input/kis_tablet_event.cpp input/wintab/kis_tablet_support_win.cpp input/wintab/kis_screen_size_choice_dialog.cpp qtlockedfile/qtlockedfile_win.cpp ) include_directories(${Qt5Gui_PRIVATE_INCLUDE_DIRS}) endif() set(kritaui_LIB_SRCS ${kritaui_LIB_SRCS} kis_animation_frame_cache.cpp kis_animation_cache_populator.cpp canvas/kis_animation_player.cpp kis_animation_exporter.cpp kis_animation_importer.cpp ) if(UNIX) set(kritaui_LIB_SRCS ${kritaui_LIB_SRCS} input/kis_tablet_event.cpp input/wintab/kis_tablet_support.cpp qtlockedfile/qtlockedfile_unix.cpp ) if(NOT APPLE) set(kritaui_LIB_SRCS ${kritaui_LIB_SRCS} input/wintab/kis_tablet_support_x11.cpp input/wintab/qxcbconnection_xi2.cpp input/wintab/qxcbconnection.cpp input/wintab/kis_xi2_event_filter.cpp ) endif() endif() if(WIN32) #ki18n_wrap_ui( # input/wintab/kis_screen_size_choice_dialog.ui #) endif() ki18n_wrap_ui(kritaui_LIB_SRCS forms/wdgdlgpngimport.ui forms/wdgfullscreensettings.ui forms/wdgautogradient.ui forms/wdggeneralsettings.ui forms/wdgperformancesettings.ui forms/wdggenerators.ui forms/wdgbookmarkedconfigurationseditor.ui forms/wdgapplyprofile.ui forms/wdgcustompattern.ui forms/wdglayerproperties.ui forms/wdgcolorsettings.ui forms/wdgtabletsettings.ui forms/wdgcolorspaceselector.ui forms/wdgcolorspaceselectoradvanced.ui forms/wdgdisplaysettings.ui forms/kis_previewwidgetbase.ui forms/kis_matrix_widget.ui forms/wdgselectionoptions.ui forms/wdggeometryoptions.ui forms/wdgnewimage.ui forms/wdgimageproperties.ui forms/wdgmaskfromselection.ui forms/wdgmasksource.ui forms/wdgfilterdialog.ui forms/wdgmetadatamergestrategychooser.ui forms/wdgpaintoppresets.ui forms/wdgpaintopsettings.ui forms/wdgdlggeneratorlayer.ui forms/wdgdlgfilelayer.ui forms/wdgfilterselector.ui forms/wdgfilternodecreation.ui forms/wdgpaintactioneditor.ui forms/wdgmultipliersdoublesliderspinbox.ui forms/wdgnodequerypatheditor.ui forms/wdgpresetselectorstrip.ui forms/wdgdlgblacklistcleanup.ui forms/wdgrectangleconstraints.ui forms/wdgimportimagesequence.ui forms/KisDetailsPaneBase.ui forms/KisOpenPaneBase.ui brushhud/kis_dlg_brush_hud_config.ui + forms/wdgdlginternalcolorselector.ui dialogs/kis_delayed_save_dialog.ui input/config/kis_input_configuration_page.ui input/config/kis_edit_profiles_dialog.ui input/config/kis_input_configuration_page_item.ui input/config/kis_mouse_input_editor.ui input/config/kis_wheel_input_editor.ui input/config/kis_key_input_editor.ui layerstyles/wdgBevelAndEmboss.ui layerstyles/wdgblendingoptions.ui layerstyles/WdgColorOverlay.ui layerstyles/wdgContour.ui layerstyles/wdgdropshadow.ui layerstyles/WdgGradientOverlay.ui layerstyles/wdgInnerGlow.ui layerstyles/wdglayerstyles.ui layerstyles/WdgPatternOverlay.ui layerstyles/WdgSatin.ui layerstyles/WdgStroke.ui layerstyles/wdgstylesselector.ui layerstyles/wdgTexture.ui wdgsplash.ui input/wintab/kis_screen_size_choice_dialog.ui ) QT5_WRAP_CPP(kritaui_HEADERS_MOC KisNodePropertyAction_p.h) add_library(kritaui SHARED ${kritaui_HEADERS_MOC} ${kritaui_LIB_SRCS} ) generate_export_header(kritaui BASE_NAME kritaui) target_link_libraries(kritaui KF5::CoreAddons KF5::Completion KF5::I18n KF5::ItemViews Qt5::Network kritacolor kritaimage kritalibbrush kritawidgets kritawidgetutils ${PNG_LIBRARIES} ${EXIV2_LIBRARIES} ) if (HAVE_KIO) target_link_libraries(kritaui KF5::KIOCore) endif() if (NOT WIN32 AND NOT APPLE) target_link_libraries(kritaui ${X11_X11_LIB} ${X11_Xinput_LIB} ${XCB_LIBRARIES}) endif() if(APPLE) target_link_libraries(kritaui ${FOUNDATION_LIBRARY}) endif () target_link_libraries(kritaui ${OPENEXR_LIBRARIES}) # Add VSync disable workaround if(NOT WIN32 AND NOT APPLE) target_link_libraries(kritaui ${CMAKE_DL_LIBS} Qt5::X11Extras) endif() if(X11_FOUND) target_link_libraries(kritaui Qt5::X11Extras ${X11_LIBRARIES}) endif() target_link_libraries(kritaui LINK_INTERFACE_LIBRARIES kritaimage kritalibbrush kritapigment kritawidgets KF5::Completion KF5::I18n ${GL_INTERFACE_LIBRARIES}) target_include_directories(kritaui PUBLIC $ $ $ $ $ $ $ ) set_target_properties(kritaui PROPERTIES VERSION ${GENERIC_KRITA_LIB_VERSION} SOVERSION ${GENERIC_KRITA_LIB_SOVERSION} ) install(TARGETS kritaui ${INSTALL_TARGETS_DEFAULT_ARGS}) if (APPLE) install(FILES osx.stylesheet DESTINATION ${DATA_INSTALL_DIR}/krita) endif () diff --git a/libs/ui/KisColorsetChooser.cpp b/libs/ui/KisColorsetChooser.cpp index 2f730f96c9..621ffa709c 100644 --- a/libs/ui/KisColorsetChooser.cpp +++ b/libs/ui/KisColorsetChooser.cpp @@ -1,159 +1,160 @@ /* This file is part of the KDE project * Copyright (C) 2013 Sven Langkamp * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "KisColorsetChooser.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_resource_server_provider.h" #include "KisViewManager.h" #include #include #include #include #include #include "kis_int_parse_spin_box.h" class ColorSetDelegate : public QAbstractItemDelegate { public: ColorSetDelegate(QObject * parent = 0) : QAbstractItemDelegate(parent) {} virtual ~ColorSetDelegate() {} /// reimplemented virtual void paint(QPainter *, const QStyleOptionViewItem &, const QModelIndex &) const; /// reimplemented QSize sizeHint(const QStyleOptionViewItem & option, const QModelIndex &) const { return option.decorationSize; } }; void ColorSetDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const { painter->save(); if (! index.isValid()) return; KoResource* resource = static_cast(index.internalPointer()); KoColorSet* colorSet = static_cast(resource); if (option.state & QStyle::State_Selected) { painter->fillRect(option.rect, option.palette.highlight()); painter->setPen(option.palette.highlightedText().color()); } else { painter->setBrush(option.palette.text().color()); } painter->drawText(option.rect.x() + 5, option.rect.y() + painter->fontMetrics().ascent() + 5, colorSet->name()); int size = 7; for (int i = 0; i < colorSet->nColors() && i*size < option.rect.width(); i++) { QRect rect(option.rect.x() + i*size, option.rect.y() + option.rect.height() - size, size, size); painter->fillRect(rect, colorSet->getColor(i).color.toQColor()); } painter->restore(); } KisColorsetChooser::KisColorsetChooser(QWidget* parent): QWidget(parent) { KoResourceServer * rserver = KoResourceServerProvider::instance()->paletteServer(false); QSharedPointer adapter(new KoResourceServerAdapter(rserver)); m_itemChooser = new KoResourceItemChooser(adapter, this); m_itemChooser->setItemDelegate(new ColorSetDelegate(this)); + m_itemChooser->showTaggingBar(true); m_itemChooser->setFixedSize(250, 250); m_itemChooser->setRowHeight(30); m_itemChooser->setColumnCount(1); connect(m_itemChooser, SIGNAL(resourceSelected(KoResource*)), this, SLOT(resourceSelected(KoResource*))); QPushButton* saveButton = new QPushButton(i18n("Save")); connect(saveButton, SIGNAL(clicked(bool)), this, SLOT(slotSave())); m_nameEdit = new QLineEdit(this); m_nameEdit->setPlaceholderText(i18n("Insert name")); m_nameEdit->setClearButtonEnabled(true); m_columnEdit = new KisIntParseSpinBox(this); m_columnEdit->setRange(1, 30); m_columnEdit->setValue(10); QGridLayout* layout = new QGridLayout(this); layout->addWidget(m_itemChooser, 0, 0, 1, 3); layout->addWidget(new QLabel(i18n("Name:"), this), 1, 0, 1, 1); layout->addWidget(m_nameEdit, 1, 1, 1, 2); layout->addWidget(new QLabel(i18n("Columns:"), this), 2, 0, 1, 1); layout->addWidget(m_columnEdit, 2, 1, 1, 1); layout->addWidget(saveButton, 2, 2, 1, 1); layout->setColumnStretch(1, 1); } KisColorsetChooser::~KisColorsetChooser() { } void KisColorsetChooser::resourceSelected(KoResource* resource) { emit paletteSelected(static_cast(resource)); } void KisColorsetChooser::slotSave() { KoResourceServer * rserver = KoResourceServerProvider::instance()->paletteServer(); KoColorSet* colorset = new KoColorSet(); colorset->setValid(true); QString saveLocation = rserver->saveLocation(); QString name = m_nameEdit->text(); int columns = m_columnEdit->value(); bool newName = false; if(name.isEmpty()) { newName = true; name = i18n("Palette"); } QFileInfo fileInfo(saveLocation + name + colorset->defaultFileExtension()); int i = 1; while (fileInfo.exists()) { fileInfo.setFile(saveLocation + name + QString("%1").arg(i) + colorset->defaultFileExtension()); i++; } colorset->setFilename(fileInfo.filePath()); if(newName) { name = i18n("Palette %1", i); } colorset->setName(name); colorset->setColumnCount(columns); rserver->addResource(colorset); } diff --git a/libs/ui/KisViewManager.cpp b/libs/ui/KisViewManager.cpp index 4cfc936128..b737b7a453 100644 --- a/libs/ui/KisViewManager.cpp +++ b/libs/ui/KisViewManager.cpp @@ -1,1253 +1,1254 @@ /* * This file is part of KimageShop^WKrayon^WKrita * * Copyright (c) 1999 Matthias Elter * 1999 Michael Koch * 1999 Carsten Pfeiffer * 2002 Patrick Julien * 2003-2011 Boudewijn Rempt * 2004 Clarence Dang * 2011 José Luis Vergara * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include "KisViewManager.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "input/kis_input_manager.h" #include "canvas/kis_canvas2.h" #include "canvas/kis_canvas_controller.h" #include "canvas/kis_grid_manager.h" #include "dialogs/kis_dlg_blacklist_cleanup.h" #include "input/kis_input_profile_manager.h" #include "kis_action_manager.h" #include "kis_action.h" #include "kis_canvas_controls_manager.h" #include "kis_canvas_resource_provider.h" #include "kis_composite_progress_proxy.h" #include "kis_config.h" #include "kis_config_notifier.h" #include "kis_control_frame.h" #include "kis_coordinates_converter.h" #include "KisDocument.h" #include "kis_favorite_resource_manager.h" #include "kis_filter_manager.h" #include "kis_group_layer.h" #include #include "kis_image_manager.h" #include #include "kis_mainwindow_observer.h" #include "kis_mask_manager.h" #include "kis_mimedata.h" #include "kis_mirror_manager.h" #include "kis_node_commands_adapter.h" #include "kis_node.h" #include "kis_node_manager.h" #include "kis_painting_assistants_manager.h" #include #include "kis_paintop_box.h" #include #include "KisPart.h" #include "KisPrintJob.h" #include "kis_progress_widget.h" #include "kis_resource_server_provider.h" #include "kis_selection.h" #include "kis_selection_manager.h" #include "kis_shape_controller.h" #include "kis_shape_layer.h" #include #include "kis_statusbar.h" #include #include #include "kis_tooltip_manager.h" #include #include "KisView.h" #include "kis_zoom_manager.h" #include "kra/kis_kra_loader.h" #include "widgets/kis_floating_message.h" #include "kis_signal_auto_connection.h" #include "kis_icon_utils.h" #include "kis_guides_manager.h" #include "kis_derived_resources.h" class BlockingUserInputEventFilter : public QObject { bool eventFilter(QObject *watched, QEvent *event) { Q_UNUSED(watched); if(dynamic_cast(event) || dynamic_cast(event) || dynamic_cast(event)) { return true; } else { return false; } } }; class KisViewManager::KisViewManagerPrivate { public: KisViewManagerPrivate(KisViewManager *_q, QWidget *_q_parent) : filterManager(_q) , createTemplate(0) , saveIncremental(0) , saveIncrementalBackup(0) , openResourcesDirectory(0) , rotateCanvasRight(0) , rotateCanvasLeft(0) , resetCanvasRotation(0) , wrapAroundAction(0) , levelOfDetailAction(0) , showRulersAction(0) , rulersTrackMouseAction(0) , zoomTo100pct(0) , zoomIn(0) , zoomOut(0) , selectionManager(_q) , statusBar(_q) , controlFrame(_q, _q_parent) , nodeManager(_q) , imageManager(_q) , gridManager(_q) , canvasControlsManager(_q) , paintingAssistantsManager(_q) , actionManager(_q) , mainWindow(0) , showFloatingMessage(true) , currentImageView(0) , canvasResourceProvider(_q) , canvasResourceManager() , guiUpdateCompressor(30, KisSignalCompressor::POSTPONE, _q) , mirrorManager(_q) , inputManager(_q) , actionAuthor(0) { canvasResourceManager.addDerivedResourceConverter(toQShared(new KisCompositeOpResourceConverter)); canvasResourceManager.addDerivedResourceConverter(toQShared(new KisEffectiveCompositeOpResourceConverter)); canvasResourceManager.addDerivedResourceConverter(toQShared(new KisOpacityResourceConverter)); canvasResourceManager.addDerivedResourceConverter(toQShared(new KisFlowResourceConverter)); canvasResourceManager.addDerivedResourceConverter(toQShared(new KisSizeResourceConverter)); canvasResourceManager.addDerivedResourceConverter(toQShared(new KisLodAvailabilityResourceConverter)); canvasResourceManager.addDerivedResourceConverter(toQShared(new KisEraserModeResourceConverter)); canvasResourceManager.addResourceUpdateMediator(toQShared(new KisPresetUpdateMediator)); } public: KisFilterManager filterManager; KisAction *createTemplate; KisAction *createCopy; KisAction *saveIncremental; KisAction *saveIncrementalBackup; KisAction *openResourcesDirectory; KisAction *rotateCanvasRight; KisAction *rotateCanvasLeft; KisAction *resetCanvasRotation; KisAction *wrapAroundAction; KisAction *levelOfDetailAction; KisAction *showRulersAction; KisAction *rulersTrackMouseAction; KisAction *zoomTo100pct; KisAction *zoomIn; KisAction *zoomOut; KisAction *softProof; KisAction *gamutCheck; KisSelectionManager selectionManager; KisGuidesManager guidesManager; KisStatusBar statusBar; KisControlFrame controlFrame; KisNodeManager nodeManager; KisImageManager imageManager; KisGridManager gridManager; KisCanvasControlsManager canvasControlsManager; KisPaintingAssistantsManager paintingAssistantsManager; BlockingUserInputEventFilter blockingEventFilter; KisActionManager actionManager; QMainWindow* mainWindow; QPointer savedFloatingMessage; bool showFloatingMessage; QPointer currentImageView; KisCanvasResourceProvider canvasResourceProvider; KoCanvasResourceManager canvasResourceManager; KisSignalCompressor guiUpdateCompressor; KActionCollection *actionCollection; KisMirrorManager mirrorManager; KisInputManager inputManager; KisSignalAutoConnectionsStore viewConnections; KSelectAction *actionAuthor; // Select action for author profile. QByteArray canvasState; }; KisViewManager::KisViewManager(QWidget *parent, KActionCollection *_actionCollection) : d(new KisViewManagerPrivate(this, parent)) { d->actionCollection = _actionCollection; d->mainWindow = dynamic_cast(parent); d->canvasResourceProvider.setResourceManager(&d->canvasResourceManager); connect(&d->guiUpdateCompressor, SIGNAL(timeout()), this, SLOT(guiUpdateTimeout())); createActions(); setupManagers(); // These initialization functions must wait until KisViewManager ctor is complete. d->statusBar.setup(); d->controlFrame.setup(parent); //Check to draw scrollbars after "Canvas only mode" toggle is created. this->showHideScrollbars(); QScopedPointer dummy(new KoDummyCanvasController(actionCollection())); KoToolManager::instance()->registerToolActions(actionCollection(), dummy.data()); QTimer::singleShot(0, this, SLOT(initializeStatusBarVisibility())); connect(KoToolManager::instance(), SIGNAL(inputDeviceChanged(KoInputDevice)), d->controlFrame.paintopBox(), SLOT(slotInputDeviceChanged(KoInputDevice))); connect(KoToolManager::instance(), SIGNAL(changedTool(KoCanvasController*,int)), d->controlFrame.paintopBox(), SLOT(slotToolChanged(KoCanvasController*,int))); connect(&d->nodeManager, SIGNAL(sigNodeActivated(KisNodeSP)), resourceProvider(), SLOT(slotNodeActivated(KisNodeSP))); connect(resourceProvider()->resourceManager(), SIGNAL(canvasResourceChanged(int,QVariant)), d->controlFrame.paintopBox(), SLOT(slotCanvasResourceChanged(int,QVariant))); connect(KisPart::instance(), SIGNAL(sigViewAdded(KisView*)), SLOT(slotViewAdded(KisView*))); connect(KisPart::instance(), SIGNAL(sigViewRemoved(KisView*)), SLOT(slotViewRemoved(KisView*))); connect(KisConfigNotifier::instance(), SIGNAL(configChanged()), SLOT(slotUpdateAuthorProfileActions())); KisInputProfileManager::instance()->loadProfiles(); KisConfig cfg; d->showFloatingMessage = cfg.showCanvasMessages(); } KisViewManager::~KisViewManager() { KisConfig cfg; if (resourceProvider() && resourceProvider()->currentPreset()) { cfg.writeEntry("LastPreset", resourceProvider()->currentPreset()->name()); } cfg.writeEntry("baseLength", KoResourceItemChooserSync::instance()->baseLength()); delete d; } KActionCollection *KisViewManager::actionCollection() const { return d->actionCollection; } void KisViewManager::slotViewAdded(KisView *view) { d->inputManager.addTrackedCanvas(view->canvasBase()); if (viewCount() == 0) { d->statusBar.showAllStatusBarItems(); } } void KisViewManager::slotViewRemoved(KisView *view) { d->inputManager.removeTrackedCanvas(view->canvasBase()); if (viewCount() == 0) { d->statusBar.hideAllStatusBarItems(); } } void KisViewManager::setCurrentView(KisView *view) { bool first = true; if (d->currentImageView) { d->currentImageView->notifyCurrentStateChanged(false); d->currentImageView->canvasBase()->setCursor(QCursor(Qt::ArrowCursor)); first = false; KisDocument* doc = d->currentImageView->document(); if (doc) { doc->disconnect(this); } d->currentImageView->canvasController()->proxyObject->disconnect(&d->statusBar); d->viewConnections.clear(); } // Restore the last used brush preset if (first) { KisConfig cfg; KisPaintOpPresetResourceServer * rserver = KisResourceServerProvider::instance()->paintOpPresetServer(); QString lastPreset = cfg.readEntry("LastPreset", QString("Basic_tip_default")); KisPaintOpPresetSP preset = rserver->resourceByName(lastPreset); if (!preset) { preset = rserver->resourceByName("Basic_tip_default"); } if (!preset) { preset = rserver->resources().first(); } if (preset) { paintOpBox()->restoreResource(preset.data()); } } d->softProof->setChecked(view->softProofing()); d->gamutCheck->setChecked(view->gamutCheck()); QPointerimageView = qobject_cast(view); if (imageView) { // Wait for the async image to have loaded KisDocument* doc = view->document(); // connect(canvasController()->proxyObject, SIGNAL(documentMousePositionChanged(QPointF)), d->statusBar, SLOT(documentMousePositionChanged(QPointF))); d->currentImageView = imageView; KisCanvasController *canvasController = dynamic_cast(d->currentImageView->canvasController()); d->viewConnections.addUniqueConnection(&d->nodeManager, SIGNAL(sigNodeActivated(KisNodeSP)), doc->image(), SLOT(requestStrokeEndActiveNode())); d->viewConnections.addUniqueConnection(d->rotateCanvasRight, SIGNAL(triggered()), canvasController, SLOT(rotateCanvasRight15())); d->viewConnections.addUniqueConnection(d->rotateCanvasLeft, SIGNAL(triggered()),canvasController, SLOT(rotateCanvasLeft15())); d->viewConnections.addUniqueConnection(d->resetCanvasRotation, SIGNAL(triggered()),canvasController, SLOT(resetCanvasRotation())); d->viewConnections.addUniqueConnection(d->wrapAroundAction, SIGNAL(toggled(bool)), canvasController, SLOT(slotToggleWrapAroundMode(bool))); d->wrapAroundAction->setChecked(canvasController->wrapAroundMode()); d->viewConnections.addUniqueConnection(d->levelOfDetailAction, SIGNAL(toggled(bool)), canvasController, SLOT(slotToggleLevelOfDetailMode(bool))); d->levelOfDetailAction->setChecked(canvasController->levelOfDetailMode()); d->viewConnections.addUniqueConnection(d->currentImageView->image(), SIGNAL(sigColorSpaceChanged(const KoColorSpace*)), d->controlFrame.paintopBox(), SLOT(slotColorSpaceChanged(const KoColorSpace*))); d->viewConnections.addUniqueConnection(d->showRulersAction, SIGNAL(toggled(bool)), imageView->zoomManager(), SLOT(setShowRulers(bool))); d->viewConnections.addUniqueConnection(d->rulersTrackMouseAction, SIGNAL(toggled(bool)), imageView->zoomManager(), SLOT(setRulersTrackMouse(bool))); d->viewConnections.addUniqueConnection(d->zoomTo100pct, SIGNAL(triggered()), imageView->zoomManager(), SLOT(zoomTo100())); d->viewConnections.addUniqueConnection(d->zoomIn, SIGNAL(triggered()), imageView->zoomController()->zoomAction(), SLOT(zoomIn())); d->viewConnections.addUniqueConnection(d->zoomOut, SIGNAL(triggered()), imageView->zoomController()->zoomAction(), SLOT(zoomOut())); d->viewConnections.addUniqueConnection(d->softProof, SIGNAL(toggled(bool)), view, SLOT(slotSoftProofing(bool)) ); d->viewConnections.addUniqueConnection(d->gamutCheck, SIGNAL(toggled(bool)), view, SLOT(slotGamutCheck(bool)) ); imageView->zoomManager()->setShowRulers(d->showRulersAction->isChecked()); imageView->zoomManager()->setRulersTrackMouse(d->rulersTrackMouseAction->isChecked()); showHideScrollbars(); } d->filterManager.setView(imageView); d->selectionManager.setView(imageView); d->guidesManager.setView(imageView); d->nodeManager.setView(imageView); d->imageManager.setView(imageView); d->canvasControlsManager.setView(imageView); d->actionManager.setView(imageView); d->gridManager.setView(imageView); d->statusBar.setView(imageView); d->paintingAssistantsManager.setView(imageView); d->mirrorManager.setView(imageView); if (d->currentImageView) { d->currentImageView->notifyCurrentStateChanged(true); d->currentImageView->canvasController()->activate(); d->currentImageView->canvasController()->setFocus(); } d->actionManager.updateGUI(); d->viewConnections.addUniqueConnection( image(), SIGNAL(sigSizeChanged(const QPointF&, const QPointF&)), resourceProvider(), SLOT(slotImageSizeChanged())); d->viewConnections.addUniqueConnection( image(), SIGNAL(sigResolutionChanged(double,double)), resourceProvider(), SLOT(slotOnScreenResolutionChanged())); d->viewConnections.addUniqueConnection( image(), SIGNAL(sigNodeChanged(KisNodeSP)), this, SLOT(updateGUI())); d->viewConnections.addUniqueConnection( view->zoomManager()->zoomController(), SIGNAL(zoomChanged(KoZoomMode::Mode,qreal)), resourceProvider(), SLOT(slotOnScreenResolutionChanged())); resourceProvider()->slotImageSizeChanged(); resourceProvider()->slotOnScreenResolutionChanged(); + Q_EMIT viewChanged(); } KoZoomController *KisViewManager::zoomController() const { if (d->currentImageView) { return d->currentImageView->zoomController(); } return 0; } KisImageWSP KisViewManager::image() const { if (document()) { return document()->image(); } return 0; } KisCanvasResourceProvider * KisViewManager::resourceProvider() { return &d->canvasResourceProvider; } KisCanvas2 * KisViewManager::canvasBase() const { if (d && d->currentImageView) { return d->currentImageView->canvasBase(); } return 0; } QWidget* KisViewManager::canvas() const { if (d && d->currentImageView && d->currentImageView->canvasBase()->canvasWidget()) { return d->currentImageView->canvasBase()->canvasWidget(); } return 0; } KisStatusBar * KisViewManager::statusBar() const { return &d->statusBar; } void KisViewManager::addStatusBarItem(QWidget *widget, int stretch, bool permanent) { d->statusBar.addStatusBarItem(widget, stretch, permanent); } void KisViewManager::removeStatusBarItem(QWidget *widget) { d->statusBar.removeStatusBarItem(widget); } KisPaintopBox* KisViewManager::paintOpBox() const { return d->controlFrame.paintopBox(); } KoProgressUpdater* KisViewManager::createProgressUpdater(KoProgressUpdater::Mode mode) { return new KisProgressUpdater(d->statusBar.progress(), document()->progressProxy(), mode); } KisSelectionManager * KisViewManager::selectionManager() { return &d->selectionManager; } KisNodeSP KisViewManager::activeNode() { return d->nodeManager.activeNode(); } KisLayerSP KisViewManager::activeLayer() { return d->nodeManager.activeLayer(); } KisPaintDeviceSP KisViewManager::activeDevice() { return d->nodeManager.activePaintDevice(); } KisZoomManager * KisViewManager::zoomManager() { if (d->currentImageView) { return d->currentImageView->zoomManager(); } return 0; } KisFilterManager * KisViewManager::filterManager() { return &d->filterManager; } KisImageManager * KisViewManager::imageManager() { return &d->imageManager; } KisInputManager* KisViewManager::inputManager() const { return &d->inputManager; } KisSelectionSP KisViewManager::selection() { if (d->currentImageView) { return d->currentImageView->selection(); } return 0; } bool KisViewManager::selectionEditable() { KisLayerSP layer = activeLayer(); if (layer) { KoProperties properties; QList masks = layer->childNodes(QStringList("KisSelectionMask"), properties); if (masks.size() == 1) { return masks[0]->isEditable(); } } // global selection is always editable return true; } KisUndoAdapter * KisViewManager::undoAdapter() { if (!document()) return 0; KisImageWSP image = document()->image(); Q_ASSERT(image); return image->undoAdapter(); } void KisViewManager::createActions() { KisConfig cfg; d->saveIncremental = actionManager()->createAction("save_incremental_version"); connect(d->saveIncremental, SIGNAL(triggered()), this, SLOT(slotSaveIncremental())); d->saveIncrementalBackup = actionManager()->createAction("save_incremental_backup"); connect(d->saveIncrementalBackup, SIGNAL(triggered()), this, SLOT(slotSaveIncrementalBackup())); connect(mainWindow(), SIGNAL(documentSaved()), this, SLOT(slotDocumentSaved())); d->saveIncremental->setEnabled(false); d->saveIncrementalBackup->setEnabled(false); KisAction *tabletDebugger = actionManager()->createAction("tablet_debugger"); connect(tabletDebugger, SIGNAL(triggered()), this, SLOT(toggleTabletLogger())); d->createTemplate = actionManager()->createAction("create_template"); connect(d->createTemplate, SIGNAL(triggered()), this, SLOT(slotCreateTemplate())); d->createCopy = actionManager()->createAction("create_copy"); connect(d->createCopy, SIGNAL(triggered()), this, SLOT(slotCreateCopy())); d->openResourcesDirectory = actionManager()->createAction("open_resources_directory"); connect(d->openResourcesDirectory, SIGNAL(triggered()), SLOT(openResourcesDirectory())); d->rotateCanvasRight = actionManager()->createAction("rotate_canvas_right"); d->rotateCanvasLeft = actionManager()->createAction("rotate_canvas_left"); d->resetCanvasRotation = actionManager()->createAction("reset_canvas_rotation"); d->wrapAroundAction = actionManager()->createAction("wrap_around_mode"); d->levelOfDetailAction = actionManager()->createAction("level_of_detail_mode"); d->softProof = actionManager()->createAction("softProof"); d->gamutCheck = actionManager()->createAction("gamutCheck"); KisAction *tAction = actionManager()->createAction("showStatusBar"); tAction->setChecked(cfg.showStatusBar()); connect(tAction, SIGNAL(toggled(bool)), this, SLOT(showStatusBar(bool))); tAction = actionManager()->createAction("view_show_canvas_only"); tAction->setChecked(false); connect(tAction, SIGNAL(toggled(bool)), this, SLOT(switchCanvasOnly(bool))); //Workaround, by default has the same shortcut as mirrorCanvas KisAction *a = dynamic_cast(actionCollection()->action("format_italic")); if (a) { a->setDefaultShortcut(QKeySequence()); } a = actionManager()->createAction("edit_blacklist_cleanup"); connect(a, SIGNAL(triggered()), this, SLOT(slotBlacklistCleanup())); d->showRulersAction = actionManager()->createAction("view_ruler"); d->showRulersAction->setChecked(cfg.showRulers()); connect(d->showRulersAction, SIGNAL(toggled(bool)), SLOT(slotSaveShowRulersState(bool))); d->rulersTrackMouseAction = actionManager()->createAction("rulers_track_mouse"); d->rulersTrackMouseAction->setChecked(cfg.rulersTrackMouse()); connect(d->rulersTrackMouseAction, SIGNAL(toggled(bool)), SLOT(slotSaveRulersTrackMouseState(bool))); d->zoomTo100pct = actionManager()->createAction("zoom_to_100pct"); d->zoomIn = actionManager()->createStandardAction(KStandardAction::ZoomIn, 0, ""); d->zoomOut = actionManager()->createStandardAction(KStandardAction::ZoomOut, 0, ""); d->actionAuthor = new KSelectAction(KisIconUtils::loadIcon("im-user"), i18n("Active Author Profile"), this); connect(d->actionAuthor, SIGNAL(triggered(const QString &)), this, SLOT(changeAuthorProfile(const QString &))); actionCollection()->addAction("settings_active_author", d->actionAuthor); slotUpdateAuthorProfileActions(); } void KisViewManager::setupManagers() { // Create the managers for filters, selections, layers etc. // XXX: When the currentlayer changes, call updateGUI on all // managers d->filterManager.setup(actionCollection(), actionManager()); d->selectionManager.setup(actionManager()); d->guidesManager.setup(actionManager()); d->nodeManager.setup(actionCollection(), actionManager()); d->imageManager.setup(actionManager()); d->gridManager.setup(actionManager()); d->paintingAssistantsManager.setup(actionManager()); d->canvasControlsManager.setup(actionManager()); d->mirrorManager.setup(actionCollection()); } void KisViewManager::updateGUI() { d->guiUpdateCompressor.start(); } void KisViewManager::slotBlacklistCleanup() { KisDlgBlacklistCleanup dialog; dialog.exec(); } KisNodeManager * KisViewManager::nodeManager() const { return &d->nodeManager; } KisActionManager* KisViewManager::actionManager() const { return &d->actionManager; } KisGridManager * KisViewManager::gridManager() const { return &d->gridManager; } KisGuidesManager * KisViewManager::guidesManager() const { return &d->guidesManager; } KisPaintingAssistantsManager* KisViewManager::paintingAssistantsManager() const { return &d->paintingAssistantsManager; } KisDocument *KisViewManager::document() const { if (d->currentImageView && d->currentImageView->document()) { return d->currentImageView->document(); } return 0; } int KisViewManager::viewCount() const { KisMainWindow *mw = qobject_cast(d->mainWindow); if (mw) { return mw->viewCount(); } return 0; } void KisViewManager::slotCreateTemplate() { if (!document()) return; KisTemplateCreateDia::createTemplate( QStringLiteral("templates/"), ".kra", document(), mainWindow()); } void KisViewManager::slotCreateCopy() { if (!document()) return; KisDocument *doc = KisPart::instance()->createDocument(); QString name = document()->documentInfo()->aboutInfo("name"); if (name.isEmpty()) { name = document()->url().toLocalFile(); } name = i18n("%1 (Copy)", name); doc->documentInfo()->setAboutInfo("title", name); KisImageWSP image = document()->image(); KisImageSP newImage = new KisImage(doc->createUndoStore(), image->width(), image->height(), image->colorSpace(), name); newImage->setRootLayer(dynamic_cast(image->rootLayer()->clone().data())); doc->setCurrentImage(newImage); KisPart::instance()->addDocument(doc); KisMainWindow *mw = qobject_cast(d->mainWindow); mw->addViewAndNotifyLoadingCompleted(doc); } QMainWindow* KisViewManager::qtMainWindow() const { if (d->mainWindow) return d->mainWindow; //Fallback for when we have not yet set the main window. QMainWindow* w = qobject_cast(qApp->activeWindow()); if(w) return w; return mainWindow(); } void KisViewManager::setQtMainWindow(QMainWindow* newMainWindow) { d->mainWindow = newMainWindow; } void KisViewManager::slotDocumentSaved() { d->saveIncremental->setEnabled(true); d->saveIncrementalBackup->setEnabled(true); } void KisViewManager::slotSaveIncremental() { if (!document()) return; bool foundVersion; bool fileAlreadyExists; bool isBackup; QString version = "000"; QString newVersion; QString letter; QString fileName = document()->localFilePath(); // Find current version filenames // v v Regexp to find incremental versions in the filename, taking our backup scheme into account as well // Considering our incremental version and backup scheme, format is filename_001~001.ext QRegExp regex("_\\d{1,4}[.]|_\\d{1,4}[a-z][.]|_\\d{1,4}[~]|_\\d{1,4}[a-z][~]"); regex.indexIn(fileName); // Perform the search QStringList matches = regex.capturedTexts(); foundVersion = matches.at(0).isEmpty() ? false : true; // Ensure compatibility with Save Incremental Backup // If this regex is not kept separate, the entire algorithm needs modification; // It's simpler to just add this. QRegExp regexAux("_\\d{1,4}[~]|_\\d{1,4}[a-z][~]"); regexAux.indexIn(fileName); // Perform the search QStringList matchesAux = regexAux.capturedTexts(); isBackup = matchesAux.at(0).isEmpty() ? false : true; // If the filename has a version, prepare it for incrementation if (foundVersion) { version = matches.at(matches.count() - 1); // Look at the last index, we don't care about other matches if (version.contains(QRegExp("[a-z]"))) { version.chop(1); // Trim "." letter = version.right(1); // Save letter version.chop(1); // Trim letter } else { version.chop(1); // Trim "." } version.remove(0, 1); // Trim "_" } else { // ...else, simply add a version to it so the next loop works QRegExp regex2("[.][a-z]{2,4}$"); // Heuristic to find file extension regex2.indexIn(fileName); QStringList matches2 = regex2.capturedTexts(); QString extensionPlusVersion = matches2.at(0); extensionPlusVersion.prepend(version); extensionPlusVersion.prepend("_"); fileName.replace(regex2, extensionPlusVersion); } // Prepare the base for new version filename int intVersion = version.toInt(0); ++intVersion; QString baseNewVersion = QString::number(intVersion); while (baseNewVersion.length() < version.length()) { baseNewVersion.prepend("0"); } // Check if the file exists under the new name and search until options are exhausted (test appending a to z) do { newVersion = baseNewVersion; newVersion.prepend("_"); if (!letter.isNull()) newVersion.append(letter); if (isBackup) { newVersion.append("~"); } else { newVersion.append("."); } fileName.replace(regex, newVersion); fileAlreadyExists = QFile(fileName).exists(); if (fileAlreadyExists) { if (!letter.isNull()) { char letterCh = letter.at(0).toLatin1(); ++letterCh; letter = QString(QChar(letterCh)); } else { letter = 'a'; } } } while (fileAlreadyExists && letter != "{"); // x, y, z, {... if (letter == "{") { QMessageBox::critical(mainWindow(), i18nc("@title:window", "Couldn't save incremental version"), i18n("Alternative names exhausted, try manually saving with a higher number")); return; } document()->setFileBatchMode(true); document()->saveAs(QUrl::fromUserInput(fileName)); document()->setFileBatchMode(false); if (mainWindow()) { mainWindow()->updateCaption(); } } void KisViewManager::slotSaveIncrementalBackup() { if (!document()) return; bool workingOnBackup; bool fileAlreadyExists; QString version = "000"; QString newVersion; QString letter; QString fileName = document()->localFilePath(); // First, discover if working on a backup file, or a normal file QRegExp regex("~\\d{1,4}[.]|~\\d{1,4}[a-z][.]"); regex.indexIn(fileName); // Perform the search QStringList matches = regex.capturedTexts(); workingOnBackup = matches.at(0).isEmpty() ? false : true; if (workingOnBackup) { // Try to save incremental version (of backup), use letter for alt versions version = matches.at(matches.count() - 1); // Look at the last index, we don't care about other matches if (version.contains(QRegExp("[a-z]"))) { version.chop(1); // Trim "." letter = version.right(1); // Save letter version.chop(1); // Trim letter } else { version.chop(1); // Trim "." } version.remove(0, 1); // Trim "~" // Prepare the base for new version filename int intVersion = version.toInt(0); ++intVersion; QString baseNewVersion = QString::number(intVersion); QString backupFileName = document()->localFilePath(); while (baseNewVersion.length() < version.length()) { baseNewVersion.prepend("0"); } // Check if the file exists under the new name and search until options are exhausted (test appending a to z) do { newVersion = baseNewVersion; newVersion.prepend("~"); if (!letter.isNull()) newVersion.append(letter); newVersion.append("."); backupFileName.replace(regex, newVersion); fileAlreadyExists = QFile(backupFileName).exists(); if (fileAlreadyExists) { if (!letter.isNull()) { char letterCh = letter.at(0).toLatin1(); ++letterCh; letter = QString(QChar(letterCh)); } else { letter = 'a'; } } } while (fileAlreadyExists && letter != "{"); // x, y, z, {... if (letter == "{") { QMessageBox::critical(mainWindow(), i18nc("@title:window", "Couldn't save incremental backup"), i18n("Alternative names exhausted, try manually saving with a higher number")); return; } QFile::copy(fileName, backupFileName); document()->saveAs(QUrl::fromUserInput(fileName)); if (mainWindow()) mainWindow()->updateCaption(); } else { // if NOT working on a backup... // Navigate directory searching for latest backup version, ignore letters const quint8 HARDCODED_DIGIT_COUNT = 3; QString baseNewVersion = "000"; QString backupFileName = document()->localFilePath(); QRegExp regex2("[.][a-z]{2,4}$"); // Heuristic to find file extension regex2.indexIn(backupFileName); QStringList matches2 = regex2.capturedTexts(); QString extensionPlusVersion = matches2.at(0); extensionPlusVersion.prepend(baseNewVersion); extensionPlusVersion.prepend("~"); backupFileName.replace(regex2, extensionPlusVersion); // Save version with 1 number higher than the highest version found ignoring letters do { newVersion = baseNewVersion; newVersion.prepend("~"); newVersion.append("."); backupFileName.replace(regex, newVersion); fileAlreadyExists = QFile(backupFileName).exists(); if (fileAlreadyExists) { // Prepare the base for new version filename, increment by 1 int intVersion = baseNewVersion.toInt(0); ++intVersion; baseNewVersion = QString::number(intVersion); while (baseNewVersion.length() < HARDCODED_DIGIT_COUNT) { baseNewVersion.prepend("0"); } } } while (fileAlreadyExists); // Save both as backup and on current file for interapplication workflow document()->setFileBatchMode(true); QFile::copy(fileName, backupFileName); document()->saveAs(QUrl::fromUserInput(fileName)); document()->setFileBatchMode(false); if (mainWindow()) mainWindow()->updateCaption(); } } void KisViewManager::disableControls() { // prevents possible crashes, if somebody changes the paintop during dragging by using the mousewheel // this is for Bug 250944 // the solution blocks all wheel, mouse and key event, while dragging with the freehand tool // see KisToolFreehand::initPaint() and endPaint() d->controlFrame.paintopBox()->installEventFilter(&d->blockingEventFilter); Q_FOREACH (QObject* child, d->controlFrame.paintopBox()->children()) { child->installEventFilter(&d->blockingEventFilter); } } void KisViewManager::enableControls() { d->controlFrame.paintopBox()->removeEventFilter(&d->blockingEventFilter); Q_FOREACH (QObject* child, d->controlFrame.paintopBox()->children()) { child->removeEventFilter(&d->blockingEventFilter); } } void KisViewManager::showStatusBar(bool toggled) { KisMainWindow *mw = mainWindow(); if(mw && mw->statusBar()) { mw->statusBar()->setVisible(toggled); KisConfig cfg; cfg.setShowStatusBar(toggled); } } void KisViewManager::switchCanvasOnly(bool toggled) { KisConfig cfg; KisMainWindow* main = mainWindow(); if(!main) { dbgUI << "Unable to switch to canvas-only mode, main window not found"; return; } if (toggled) { d->canvasState = qtMainWindow()->saveState(); } if (cfg.hideStatusbarFullscreen()) { if (main->statusBar()) { if (!toggled) { if (main->statusBar()->dynamicPropertyNames().contains("wasvisible")) { if (main->statusBar()->property("wasvisible").toBool()) { main->statusBar()->setVisible(true); } } } else { main->statusBar()->setProperty("wasvisible", main->statusBar()->isVisible()); main->statusBar()->setVisible(false); } } } if (cfg.hideDockersFullscreen()) { KisAction* action = qobject_cast(main->actionCollection()->action("view_toggledockers")); action->setCheckable(true); if (action && action->isChecked() == toggled) { action->setChecked(!toggled); } } if (cfg.hideTitlebarFullscreen() && !cfg.fullscreenMode()) { if(toggled) { main->setWindowState( main->windowState() | Qt::WindowFullScreen); } else { main->setWindowState( main->windowState() & ~Qt::WindowFullScreen); } } if (cfg.hideMenuFullscreen()) { if (!toggled) { if (main->menuBar()->dynamicPropertyNames().contains("wasvisible")) { if (main->menuBar()->property("wasvisible").toBool()) { main->menuBar()->setVisible(true); } } } else { main->menuBar()->setProperty("wasvisible", main->menuBar()->isVisible()); main->menuBar()->setVisible(false); } } if (cfg.hideToolbarFullscreen()) { QList toolBars = main->findChildren(); Q_FOREACH (QToolBar* toolbar, toolBars) { if (!toggled) { if (toolbar->dynamicPropertyNames().contains("wasvisible")) { if (toolbar->property("wasvisible").toBool()) { toolbar->setVisible(true); } } } else { toolbar->setProperty("wasvisible", toolbar->isVisible()); toolbar->setVisible(false); } } } showHideScrollbars(); if (toggled) { // show a fading heads-up display about the shortcut to go back showFloatingMessage(i18n("Going into Canvas-Only mode.\nPress %1 to go back.", actionCollection()->action("view_show_canvas_only")->shortcut().toString()), QIcon()); } else { main->restoreState(d->canvasState); } } void KisViewManager::toggleTabletLogger() { d->inputManager.toggleTabletLogger(); } void KisViewManager::openResourcesDirectory() { QString dir = KoResourcePaths::locateLocal("data", ""); QDesktopServices::openUrl(QUrl::fromLocalFile(dir)); } void KisViewManager::updateIcons() { if (mainWindow()) { QList dockers = mainWindow()->dockWidgets(); Q_FOREACH (QDockWidget* dock, dockers) { dbgKrita << "name " << dock->objectName(); KoDockWidgetTitleBar* titlebar = dynamic_cast(dock->titleBarWidget()); if (titlebar) { titlebar->updateIcons(); } QObjectList objects; objects.append(dock); while (!objects.isEmpty()) { QObject* object = objects.takeFirst(); objects.append(object->children()); KisIconUtils::updateIconCommon(object); } } } } void KisViewManager::initializeStatusBarVisibility() { KisConfig cfg; d->mainWindow->statusBar()->setVisible(cfg.showStatusBar()); } void KisViewManager::guiUpdateTimeout() { d->nodeManager.updateGUI(); d->selectionManager.updateGUI(); d->filterManager.updateGUI(); if (zoomManager()) { zoomManager()->updateGUI(); } d->gridManager.updateGUI(); d->actionManager.updateGUI(); } void KisViewManager::showFloatingMessage(const QString &message, const QIcon& icon, int timeout, KisFloatingMessage::Priority priority, int alignment) { if (!d->currentImageView) return; d->currentImageView->showFloatingMessageImpl(message, icon, timeout, priority, alignment); emit floatingMessageRequested(message, icon.name()); } KisMainWindow *KisViewManager::mainWindow() const { return qobject_cast(d->mainWindow); } void KisViewManager::showHideScrollbars() { if (!d->currentImageView) return; if (!d->currentImageView->canvasController()) return; KisConfig cfg; bool toggled = actionCollection()->action("view_show_canvas_only")->isChecked(); if ( (toggled && cfg.hideScrollbarsFullscreen()) || (!toggled && cfg.hideScrollbars()) ) { d->currentImageView->canvasController()->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); d->currentImageView->canvasController()->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); } else { d->currentImageView->canvasController()->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); d->currentImageView->canvasController()->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); } } void KisViewManager::slotSaveShowRulersState(bool value) { KisConfig cfg; cfg.setShowRulers(value); } void KisViewManager::slotSaveRulersTrackMouseState(bool value) { KisConfig cfg; cfg.setRulersTrackMouse(value); } void KisViewManager::setShowFloatingMessage(bool show) { d->showFloatingMessage = show; } void KisViewManager::changeAuthorProfile(const QString &profileName) { KConfigGroup appAuthorGroup(KoGlobal::calligraConfig(), "Author"); if (profileName.isEmpty()) { appAuthorGroup.writeEntry("active-profile", ""); } else if (profileName == i18nc("choice for author profile", "Anonymous")) { appAuthorGroup.writeEntry("active-profile", "anonymous"); } else { appAuthorGroup.writeEntry("active-profile", profileName); } appAuthorGroup.sync(); Q_FOREACH (KisDocument *doc, KisPart::instance()->documents()) { doc->documentInfo()->updateParameters(); } } void KisViewManager::slotUpdateAuthorProfileActions() { Q_ASSERT(d->actionAuthor); if (!d->actionAuthor) { return; } d->actionAuthor->clear(); d->actionAuthor->addAction(i18n("Default Author Profile")); d->actionAuthor->addAction(i18nc("choice for author profile", "Anonymous")); KConfigGroup authorGroup(KoGlobal::calligraConfig(), "Author"); QStringList profiles = authorGroup.readEntry("profile-names", QStringList()); Q_FOREACH (const QString &profile , profiles) { d->actionAuthor->addAction(profile); } KConfigGroup appAuthorGroup(KoGlobal::calligraConfig(), "Author"); QString profileName = appAuthorGroup.readEntry("active-profile", ""); if (profileName == "anonymous") { d->actionAuthor->setCurrentItem(1); } else if (profiles.contains(profileName)) { d->actionAuthor->setCurrentAction(profileName); } else { d->actionAuthor->setCurrentItem(0); } } diff --git a/libs/ui/KisViewManager.h b/libs/ui/KisViewManager.h index add5dc8df9..8657548d06 100644 --- a/libs/ui/KisViewManager.h +++ b/libs/ui/KisViewManager.h @@ -1,246 +1,251 @@ /* * Copyright (c) 2006 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_GUI_CLIENT_H #define KIS_GUI_CLIENT_H #include #include #include #include #include #include #include #include #include "kis_floating_message.h" class QPoint; class KisView; class KisCanvas2; class KisCanvasResourceProvider; class KisDocument; class KisFilterManager; class KisGridManager; class KisGuidesManager; class KisImageManager; class KisNodeManager; class KisPaintingAssistantsManager; class KisPaintopBox; class KisSelectionManager; class KisStatusBar; class KisUndoAdapter; class KisZoomManager; class KisPaintopBox; class KisActionManager; class KisInputManager; /** * Krita view class * * Following the broad model-view-controller idea this class shows you one view on the document. * There can be multiple views of the same document each in with independent settings for viewMode and zoom etc. */ class KRITAUI_EXPORT KisViewManager : public QObject { Q_OBJECT public: /** * Construct a new view on the krita document. * @param document the document we show. * @param parent a parent widget we show ourselves in. */ KisViewManager(QWidget *parent, KActionCollection *actionCollection); virtual ~KisViewManager(); /** * Retrieves the entire action collection. */ virtual KActionCollection* actionCollection() const; public: // Krita specific interfaces void setCurrentView(KisView *view); /// Return the image this view is displaying KisImageWSP image() const; KoZoomController *zoomController() const; /// The resource provider contains all per-view settings, such as /// current color, current paint op etc. KisCanvasResourceProvider * resourceProvider(); /// Return the canvasbase class KisCanvas2 * canvasBase() const; /// Return the actual widget that is displaying the current image QWidget* canvas() const; /// Return the wrapper class around the statusbar KisStatusBar * statusBar() const; /** * This adds a widget to the statusbar for this view. * If you use this method instead of using statusBar() directly, * KisView will take care of removing the items when the view GUI is deactivated * and readding them when it is reactivated. * The parameters are the same as QStatusBar::addWidget(). */ void addStatusBarItem(QWidget * widget, int stretch = 0, bool permanent = false); /** * Remove a widget from the statusbar for this view. */ void removeStatusBarItem(QWidget * widget); KisPaintopBox* paintOpBox() const; /// create a new progress updater KoProgressUpdater *createProgressUpdater(KoProgressUpdater::Mode mode = KoProgressUpdater::Threaded); /// The selection manager handles everything action related to /// selections. KisSelectionManager *selectionManager(); /// The node manager handles everything about nodes KisNodeManager *nodeManager() const; KisActionManager *actionManager() const; /** * Convenience method to get at the active node, which may be * a layer or a mask or a selection */ KisNodeSP activeNode(); /// Convenience method to get at the active layer KisLayerSP activeLayer(); /// Convenience method to get at the active paint device KisPaintDeviceSP activeDevice(); /// The filtermanager handles everything action-related to filters KisFilterManager *filterManager(); /// The image manager handles everything action-related to the /// current image KisImageManager *imageManager(); /// Filters events and sends them to canvas actions KisInputManager *inputManager() const; /// Convenience method to get at the active selection (the /// selection of the current layer, or, if that does not exist, /// the global selection. KisSelectionSP selection(); /// Checks if the current global or local selection is editable bool selectionEditable(); /// The undo adapter is used to add commands to the undo stack KisUndoAdapter *undoAdapter(); KisDocument *document() const; int viewCount() const; public: KisGridManager * gridManager() const; KisGuidesManager * guidesManager() const; KisPaintingAssistantsManager* paintingAssistantsManager() const; /// disable and enable toolbar controls. used for disabling them during painting. void enableControls(); void disableControls(); /// shows a floating message in the top right corner of the canvas void showFloatingMessage(const QString &message, const QIcon& icon, int timeout = 4500, KisFloatingMessage::Priority priority = KisFloatingMessage::Medium, int alignment = Qt::AlignCenter | Qt::TextWordWrap); /// @return the KoMaindow this view is in, or 0 KisMainWindow *mainWindow() const; /// The QMainWindow associated with this view. This is most likely going to be shell(), but /// when running as Gemini or Sketch, this will be set to the applications' own QMainWindow. /// This can be checked by qobject_casting to KisMainWindow to check the difference. QMainWindow* qtMainWindow() const; /// The mainWindow function will return the shell() value, unless this function is called /// with a non-null value. To make it return shell() again, simply pass null to this function. void setQtMainWindow(QMainWindow* newMainWindow); public Q_SLOTS: void switchCanvasOnly(bool toggled); void setShowFloatingMessage(bool show); void showHideScrollbars(); /// Visit all managers to update gui elements, e.g. enable / disable actions. /// This is heavy-duty call, so it uses a compressor. void updateGUI(); /// Update the style of all the icons void updateIcons(); void slotViewAdded(KisView *view); void slotViewRemoved(KisView *view); Q_SIGNALS: void floatingMessageRequested(const QString &message, const QString &iconName); + /** + * @brief viewChanged + * sent out when the view has changed. + */ + void viewChanged(); private Q_SLOTS: void slotBlacklistCleanup(); void slotCreateTemplate(); void slotCreateCopy(); void slotDocumentSaved(); void slotSaveIncremental(); void slotSaveIncrementalBackup(); void showStatusBar(bool toggled); void toggleTabletLogger(); void openResourcesDirectory(); void initializeStatusBarVisibility(); void guiUpdateTimeout(); void changeAuthorProfile(const QString &profileName); void slotUpdateAuthorProfileActions(); void slotSaveShowRulersState(bool value); void slotSaveRulersTrackMouseState(bool value); private: void createActions(); void setupManagers(); /// The zoommanager handles everything action-related to zooming KisZoomManager * zoomManager(); private: class KisViewManagerPrivate; KisViewManagerPrivate * const d; }; #endif diff --git a/libs/ui/canvas/kis_display_color_converter.cpp b/libs/ui/canvas/kis_display_color_converter.cpp index 5fd4b32693..a9188d3a66 100644 --- a/libs/ui/canvas/kis_display_color_converter.cpp +++ b/libs/ui/canvas/kis_display_color_converter.cpp @@ -1,632 +1,636 @@ /* * Copyright (c) 2014 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_display_color_converter.h" #include #include #include #include #include #include #include #include #include #include "kis_config_notifier.h" #include "kis_canvas_resource_provider.h" #include "kis_canvas2.h" #include "KisViewManager.h" #include "kis_image.h" #include "kis_node.h" #include "kundo2command.h" #include "kis_config.h" #include "kis_paint_device.h" #include "kis_iterator_ng.h" Q_GLOBAL_STATIC(KisDisplayColorConverter, s_instance) struct KisDisplayColorConverter::Private { Private(KisDisplayColorConverter *_q, KoCanvasResourceManager *_resourceManager) : q(_q), resourceManager(_resourceManager), nodeColorSpace(0), paintingColorSpace(0), monitorColorSpace(0), monitorProfile(0), renderingIntent(KoColorConversionTransformation::internalRenderingIntent()), conversionFlags(KoColorConversionTransformation::internalConversionFlags()), displayFilter(0), intermediateColorSpace(0), displayRenderer(new DisplayRenderer(_q, _resourceManager)) { } KisDisplayColorConverter *const q; KoCanvasResourceManager *resourceManager; const KoColorSpace *nodeColorSpace; const KoColorSpace *paintingColorSpace; const KoColorSpace *monitorColorSpace; const KoColorProfile *monitorProfile; KoColorConversionTransformation::Intent renderingIntent; KoColorConversionTransformation::ConversionFlags conversionFlags; KisDisplayFilter *displayFilter; const KoColorSpace *intermediateColorSpace; KoColor intermediateFgColor; KisNodeSP connectedNode; inline KoColor approximateFromQColor(const QColor &qcolor); inline QColor approximateToQColor(const KoColor &color); void slotCanvasResourceChanged(int key, const QVariant &v); void slotUpdateCurrentNodeColorSpace(); void selectPaintingColorSpace(); void updateIntermediateFgColor(const KoColor &color); void setCurrentNode(KisNodeSP node); bool useOcio() const; bool finalIsRgba(const KoColorSpace *cs) const; template QColor floatArrayToQColor(const float *p); template QImage convertToQImageDirect(KisPaintDeviceSP device); class DisplayRenderer : public KoColorDisplayRendererInterface { public: DisplayRenderer(KisDisplayColorConverter *parent, KoCanvasResourceManager *resourceManager) : m_parent(parent), m_resourceManager(resourceManager) { parent->connect(parent, SIGNAL(displayConfigurationChanged()), this, SIGNAL(displayConfigurationChanged())); } QColor toQColor(const KoColor &c) const { return m_parent->toQColor(c); } KoColor approximateFromRenderedQColor(const QColor &c) const { return m_parent->approximateFromRenderedQColor(c); } KoColor fromHsv(int h, int s, int v, int a) const { return m_parent->fromHsv(h, s, v, a); } void getHsv(const KoColor &srcColor, int *h, int *s, int *v, int *a) const { m_parent->getHsv(srcColor, h, s, v, a); } virtual qreal minVisibleFloatValue(const KoChannelInfo *chaninfo) const { return chaninfo->getUIMin(); } virtual qreal maxVisibleFloatValue(const KoChannelInfo *chaninfo) const { qreal maxValue = chaninfo->getUIMax(); if (m_resourceManager) { qreal exposure = m_resourceManager->resource(KisCanvasResourceProvider::HdrExposure).value(); // not sure if *= is what we want maxValue *= std::pow(2.0, -exposure); } return maxValue; } + virtual const KoColorSpace* getPaintingColorSpace() const { + return m_parent->paintingColorSpace(); + } + private: KisDisplayColorConverter *m_parent; QPointer m_resourceManager; }; QScopedPointer displayRenderer; }; KisDisplayColorConverter::KisDisplayColorConverter(KoCanvasResourceManager *resourceManager, QObject *parent) : QObject(parent), m_d(new Private(this, resourceManager)) { connect(m_d->resourceManager, SIGNAL(canvasResourceChanged(int, const QVariant&)), SLOT(slotCanvasResourceChanged(int, const QVariant&))); connect(KisConfigNotifier::instance(), SIGNAL(configChanged()), SLOT(selectPaintingColorSpace())); m_d->setCurrentNode(0); setMonitorProfile(0); setDisplayFilter(0); } KisDisplayColorConverter::KisDisplayColorConverter() : m_d(new Private(this, 0)) { setDisplayFilter(0); delete m_d->displayFilter; m_d->paintingColorSpace = KoColorSpaceRegistry::instance()->rgb8(); m_d->setCurrentNode(0); setMonitorProfile(0); } KisDisplayColorConverter::~KisDisplayColorConverter() { } KisDisplayColorConverter* KisDisplayColorConverter::dumbConverterInstance() { return s_instance; } KoColorDisplayRendererInterface* KisDisplayColorConverter::displayRendererInterface() const { return m_d->displayRenderer.data(); } bool KisDisplayColorConverter::Private::useOcio() const { return displayFilter && paintingColorSpace->colorModelId() == RGBAColorModelID; } void KisDisplayColorConverter::Private::updateIntermediateFgColor(const KoColor &srcColor) { KIS_ASSERT_RECOVER_RETURN(displayFilter); KoColor color = srcColor; color.convertTo(intermediateColorSpace); displayFilter->approximateForwardTransformation(color.data(), 1); intermediateFgColor = color; } void KisDisplayColorConverter::Private::slotCanvasResourceChanged(int key, const QVariant &v) { if (key == KisCanvasResourceProvider::CurrentKritaNode) { KisNodeSP currentNode = v.value(); setCurrentNode(currentNode); } else if (useOcio() && key == KoCanvasResourceManager::ForegroundColor) { updateIntermediateFgColor(v.value()); } } void KisDisplayColorConverter::Private::slotUpdateCurrentNodeColorSpace() { setCurrentNode(connectedNode); } inline KisPaintDeviceSP findValidDevice(KisNodeSP node) { return node->paintDevice() ? node->paintDevice() : node->original(); } void KisDisplayColorConverter::Private::setCurrentNode(KisNodeSP node) { if (connectedNode) { KisPaintDeviceSP device = findValidDevice(connectedNode); if (device) { q->disconnect(device, 0); } } if (node) { KisPaintDeviceSP device = findValidDevice(node); nodeColorSpace = device ? device->compositionSourceColorSpace() : node->colorSpace(); KIS_ASSERT_RECOVER_NOOP(nodeColorSpace); if (device) { q->connect(device, SIGNAL(profileChanged(const KoColorProfile*)), SLOT(slotUpdateCurrentNodeColorSpace()), Qt::UniqueConnection); q->connect(device, SIGNAL(colorSpaceChanged(const KoColorSpace*)), SLOT(slotUpdateCurrentNodeColorSpace()), Qt::UniqueConnection); } } else { nodeColorSpace = KoColorSpaceRegistry::instance()->rgb8(); } connectedNode = node; selectPaintingColorSpace(); } void KisDisplayColorConverter::Private::selectPaintingColorSpace() { KisConfig cfg; paintingColorSpace = cfg.customColorSelectorColorSpace(); if (!paintingColorSpace || displayFilter) { paintingColorSpace = nodeColorSpace; } emit q->displayConfigurationChanged(); } const KoColorSpace* KisDisplayColorConverter::paintingColorSpace() const { KIS_ASSERT_RECOVER(m_d->paintingColorSpace) { return KoColorSpaceRegistry::instance()->rgb8(); } return m_d->paintingColorSpace; } void KisDisplayColorConverter::setMonitorProfile(const KoColorProfile *monitorProfile) { m_d->monitorColorSpace = KoColorSpaceRegistry::instance()->rgb8(monitorProfile); m_d->monitorProfile = monitorProfile; m_d->renderingIntent = renderingIntent(); m_d->conversionFlags = conversionFlags(); emit displayConfigurationChanged(); } void KisDisplayColorConverter::setDisplayFilter(KisDisplayFilter *displayFilter) { if (m_d->displayFilter && displayFilter && displayFilter->lockCurrentColorVisualRepresentation()) { KoColor color(m_d->intermediateFgColor); displayFilter->approximateInverseTransformation(color.data(), 1); color.convertTo(m_d->paintingColorSpace); m_d->resourceManager->setForegroundColor(color); } m_d->displayFilter = displayFilter; m_d->intermediateColorSpace = 0; if (m_d->displayFilter) { // choosing default profile, which is scRGB const KoColorProfile *intermediateProfile = 0; m_d->intermediateColorSpace = KoColorSpaceRegistry::instance()-> colorSpace(RGBAColorModelID.id(), Float32BitsColorDepthID.id(), intermediateProfile); KIS_ASSERT_RECOVER(m_d->intermediateColorSpace) { m_d->intermediateColorSpace = m_d->monitorColorSpace; } m_d->updateIntermediateFgColor( m_d->resourceManager->foregroundColor()); } { // sanity check KisConfig cfg; //KIS_ASSERT_RECOVER_NOOP(cfg.useOcio() == (bool) m_d->displayFilter); } m_d->selectPaintingColorSpace(); } KoColorConversionTransformation::Intent KisDisplayColorConverter::renderingIntent() { KisConfig cfg; return (KoColorConversionTransformation::Intent)cfg.monitorRenderIntent(); } KoColorConversionTransformation::ConversionFlags KisDisplayColorConverter::conversionFlags() { KoColorConversionTransformation::ConversionFlags conversionFlags = KoColorConversionTransformation::HighQuality; KisConfig cfg; if (cfg.useBlackPointCompensation()) conversionFlags |= KoColorConversionTransformation::BlackpointCompensation; if (!cfg.allowLCMSOptimization()) conversionFlags |= KoColorConversionTransformation::NoOptimization; return conversionFlags; } KisDisplayFilter *KisDisplayColorConverter::displayFilter() const { return m_d->displayFilter; } const KoColorProfile* KisDisplayColorConverter::monitorProfile() const { return m_d->monitorProfile; } bool KisDisplayColorConverter::Private::finalIsRgba(const KoColorSpace *cs) const { /** * In Krita RGB color spaces differ: 8/16bit are BGRA, 16f/32f-bit RGBA */ KoID colorDepthId = cs->colorDepthId(); return colorDepthId == Float16BitsColorDepthID || colorDepthId == Float32BitsColorDepthID; } template QColor KisDisplayColorConverter::Private::floatArrayToQColor(const float *p) { if (flipToBgra) { return QColor(KoColorSpaceMaths::scaleToA(p[0]), KoColorSpaceMaths::scaleToA(p[1]), KoColorSpaceMaths::scaleToA(p[2]), KoColorSpaceMaths::scaleToA(p[3])); } else { return QColor(KoColorSpaceMaths::scaleToA(p[2]), KoColorSpaceMaths::scaleToA(p[1]), KoColorSpaceMaths::scaleToA(p[0]), KoColorSpaceMaths::scaleToA(p[3])); } } QColor KisDisplayColorConverter::toQColor(const KoColor &srcColor) const { KoColor c(srcColor); c.convertTo(m_d->paintingColorSpace); if (!m_d->useOcio()) { // we expect the display profile is rgb8, which is BGRA here KIS_ASSERT_RECOVER(m_d->monitorColorSpace->pixelSize() == 4) { return Qt::red; }; c.convertTo(m_d->monitorColorSpace, m_d->renderingIntent, m_d->conversionFlags); const quint8 *p = c.data(); return QColor(p[2], p[1], p[0], p[3]); } else { const KoColorSpace *srcCS = c.colorSpace(); if (m_d->displayFilter->useInternalColorManagement()) { srcCS = KoColorSpaceRegistry::instance()->colorSpace( RGBAColorModelID.id(), Float32BitsColorDepthID.id(), m_d->monitorProfile); c.convertTo(srcCS, m_d->renderingIntent, m_d->conversionFlags); } int numChannels = srcCS->channelCount(); QVector normalizedChannels(numChannels); srcCS->normalisedChannelsValue(c.data(), normalizedChannels); m_d->displayFilter->filter((quint8*)normalizedChannels.data(), 1); const float *p = (const float *)normalizedChannels.constData(); return m_d->finalIsRgba(srcCS) ? m_d->floatArrayToQColor(p) : m_d->floatArrayToQColor(p); } } KoColor KisDisplayColorConverter::approximateFromRenderedQColor(const QColor &c) const { return m_d->approximateFromQColor(c); } template QImage KisDisplayColorConverter::Private::convertToQImageDirect(KisPaintDeviceSP device) { QRect bounds = device->exactBounds(); if (bounds.isEmpty()) return QImage(); QImage image(bounds.size(), QImage::Format_ARGB32); KisSequentialConstIterator it(device, bounds); quint8 *dstPtr = image.bits(); const KoColorSpace *cs = device->colorSpace(); int numChannels = cs->channelCount(); QVector normalizedChannels(numChannels); do { cs->normalisedChannelsValue(it.rawDataConst(), normalizedChannels); displayFilter->filter((quint8*)normalizedChannels.data(), 1); const float *p = normalizedChannels.constData(); if (flipToBgra) { dstPtr[0] = KoColorSpaceMaths::scaleToA(p[2]); dstPtr[1] = KoColorSpaceMaths::scaleToA(p[1]); dstPtr[2] = KoColorSpaceMaths::scaleToA(p[0]); dstPtr[3] = KoColorSpaceMaths::scaleToA(p[3]); } else { dstPtr[0] = KoColorSpaceMaths::scaleToA(p[0]); dstPtr[1] = KoColorSpaceMaths::scaleToA(p[1]); dstPtr[2] = KoColorSpaceMaths::scaleToA(p[2]); dstPtr[3] = KoColorSpaceMaths::scaleToA(p[3]); } dstPtr += 4; } while (it.nextPixel()); return image; } QImage KisDisplayColorConverter::toQImage(KisPaintDeviceSP srcDevice) const { KisPaintDeviceSP device = srcDevice; if (!(*device->colorSpace() == *m_d->paintingColorSpace)) { device = new KisPaintDevice(*srcDevice); KUndo2Command *cmd = device->convertTo(m_d->paintingColorSpace); delete cmd; } if (!m_d->useOcio()) { return device->convertToQImage(m_d->monitorProfile, m_d->renderingIntent, m_d->conversionFlags); } else { if (m_d->displayFilter->useInternalColorManagement()) { if (device == srcDevice) { device = new KisPaintDevice(*srcDevice); } const KoColorSpace *srcCS = KoColorSpaceRegistry::instance()->colorSpace( RGBAColorModelID.id(), Float32BitsColorDepthID.id(), m_d->monitorProfile); KUndo2Command *cmd = device->convertTo(srcCS, m_d->renderingIntent, m_d->conversionFlags); delete cmd; } return m_d->finalIsRgba(device->colorSpace()) ? m_d->convertToQImageDirect(device) : m_d->convertToQImageDirect(device); } return QImage(); } KoColor KisDisplayColorConverter::Private::approximateFromQColor(const QColor &qcolor) { if (!useOcio()) { return KoColor(qcolor, paintingColorSpace); } else { KoColor color(qcolor, intermediateColorSpace); displayFilter->approximateInverseTransformation(color.data(), 1); color.convertTo(paintingColorSpace); return color; } qFatal("Must not be reachable"); return KoColor(); } QColor KisDisplayColorConverter::Private::approximateToQColor(const KoColor &srcColor) { KoColor color(srcColor); if (useOcio()) { color.convertTo(intermediateColorSpace); displayFilter->approximateForwardTransformation(color.data(), 1); } return color.toQColor(); } KoColor KisDisplayColorConverter::fromHsv(int h, int s, int v, int a) const { // generate HSV from sRGB! QColor qcolor(QColor::fromHsv(h, s, v, a)); return m_d->approximateFromQColor(qcolor); } void KisDisplayColorConverter::getHsv(const KoColor &srcColor, int *h, int *s, int *v, int *a) const { // we are going through sRGB here! QColor color = m_d->approximateToQColor(srcColor); color.getHsv(h, s, v, a); } KoColor KisDisplayColorConverter::fromHsvF(qreal h, qreal s, qreal v, qreal a) { // generate HSV from sRGB! QColor qcolor(QColor::fromHsvF(h, s, v, a)); return m_d->approximateFromQColor(qcolor); } void KisDisplayColorConverter::getHsvF(const KoColor &srcColor, qreal *h, qreal *s, qreal *v, qreal *a) { // we are going through sRGB here! QColor color = m_d->approximateToQColor(srcColor); color.getHsvF(h, s, v, a); } KoColor KisDisplayColorConverter::fromHslF(qreal h, qreal s, qreal l, qreal a) { // generate HSL from sRGB! QColor qcolor(QColor::fromHslF(h, s, l, a)); if (!qcolor.isValid()) { warnKrita << "Could not construct valid color from h" << h << "s" << s << "l" << l << "a" << a; qcolor = Qt::black; } return m_d->approximateFromQColor(qcolor); } void KisDisplayColorConverter::getHslF(const KoColor &srcColor, qreal *h, qreal *s, qreal *l, qreal *a) { // we are going through sRGB here! QColor color = m_d->approximateToQColor(srcColor); color.getHslF(h, s, l, a); } KoColor KisDisplayColorConverter::fromHsiF(qreal h, qreal s, qreal i) { // generate HSI from sRGB! qreal r=0.0; qreal g=0.0; qreal b=0.0; qreal a=1.0; HSIToRGB(h, s, i, &r, &g, &b); QColor qcolor; qcolor.setRgbF(qBound(0.0,r,1.0), qBound(0.0,g,1.0), qBound(0.0,b,1.0), a); return m_d->approximateFromQColor(qcolor); } void KisDisplayColorConverter::getHsiF(const KoColor &srcColor, qreal *h, qreal *s, qreal *i) { // we are going through sRGB here! QColor color = m_d->approximateToQColor(srcColor); qreal r=color.redF(); qreal g=color.greenF(); qreal b=color.blueF(); RGBToHSI(r, g, b, h, s, i); } KoColor KisDisplayColorConverter::fromHsyF(qreal h, qreal s, qreal y, qreal R, qreal G, qreal B, qreal gamma) { // generate HSL from sRGB! QVector channelValues(3); y = pow(y, gamma); HSYToRGB(h, s, y, &channelValues[0], &channelValues[1], &channelValues[2], R, G, B); KoColorSpaceRegistry::instance()->rgb8()->profile()->delinearizeFloatValueFast(channelValues); QColor qcolor; qcolor.setRgbF(qBound(0.0,channelValues[0],1.0), qBound(0.0,channelValues[1],1.0), qBound(0.0,channelValues[2],1.0), 1.0); return m_d->approximateFromQColor(qcolor); } void KisDisplayColorConverter::getHsyF(const KoColor &srcColor, qreal *h, qreal *s, qreal *y, qreal R, qreal G, qreal B, qreal gamma) { // we are going through sRGB here! QColor color = m_d->approximateToQColor(srcColor); QVector channelValues(3); channelValues[0]=color.redF(); channelValues[1]=color.greenF(); channelValues[2]=color.blueF(); //TODO: if we're going to have KoColor here, remember to check whether the TRC of the profile exists... KoColorSpaceRegistry::instance()->rgb8()->profile()->linearizeFloatValueFast(channelValues); RGBToHSY(channelValues[0], channelValues[1], channelValues[2], h, s, y, R, G, B); *y = pow(*y, 1/gamma); } #include "moc_kis_display_color_converter.cpp" diff --git a/libs/ui/dialogs/kis_dlg_image_properties.cc b/libs/ui/dialogs/kis_dlg_image_properties.cc index 244cb971be..ab3b110bbf 100644 --- a/libs/ui/dialogs/kis_dlg_image_properties.cc +++ b/libs/ui/dialogs/kis_dlg_image_properties.cc @@ -1,176 +1,177 @@ /* * Copyright (c) 2004 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_dlg_image_properties.h" #include #include #include #include #include #include #include #include #include #include #include #include "KoColorProfile.h" #include "KoColorSpaceRegistry.h" #include "KoColor.h" #include "KoColorConversionTransformation.h" #include "KoColorPopupAction.h" #include "kis_icon_utils.h" #include "KoID.h" #include "kis_image.h" #include "kis_annotation.h" #include "kis_config.h" #include "kis_signal_compressor.h" #include "widgets/kis_cmb_idlist.h" #include "widgets/squeezedcombobox.h" #include "kis_layer_utils.h" KisDlgImageProperties::KisDlgImageProperties(KisImageWSP image, QWidget *parent, const char *name) : KoDialog(parent) { setButtons(Ok | Cancel); setDefaultButton(Ok); setObjectName(name); setCaption(i18n("Image Properties")); m_page = new WdgImageProperties(this); m_image = image; setMainWidget(m_page); resize(m_page->sizeHint()); KisConfig cfg; m_page->lblWidthValue->setText(QString::number(image->width())); m_page->lblHeightValue->setText(QString::number(image->height())); m_page->lblResolutionValue->setText(QLocale().toString(image->xRes()*72, 2)); // XXX: separate values for x & y? - //Set the canvas projection color: - m_defaultColorAction = new KoColorPopupAction(this); - m_defaultColorAction->setCurrentColor(m_image->defaultProjectionColor()); - m_defaultColorAction->setToolTip(i18n("Change the background color of the image")); - m_page->bnBackgroundColor->setDefaultAction(m_defaultColorAction); + //Set the canvas projection color: backgroundColor + KoColor background = m_image->defaultProjectionColor(); + background.setOpacity(1.0); + m_page->bnBackgroundColor->setColor(background); + m_page->sldBackgroundColor->setRange(0.0,1.0,2); + m_page->sldBackgroundColor->setSingleStep(0.05); + m_page->sldBackgroundColor->setValue(m_image->defaultProjectionColor().opacityF()); KisSignalCompressor *compressor = new KisSignalCompressor(500 /* ms */, KisSignalCompressor::POSTPONE, this); - connect(m_defaultColorAction, SIGNAL(colorChanged(const KoColor&)), compressor, SLOT(start())); + connect(m_page->bnBackgroundColor, SIGNAL(changed(KoColor)), compressor, SLOT(start())); + connect(m_page->sldBackgroundColor, SIGNAL(valueChanged(qreal)), compressor, SLOT(start())); connect(compressor, SIGNAL(timeout()), this, SLOT(setCurrentColor())); - connect(m_defaultColorAction, SIGNAL(colorChanged(const KoColor&)), this, SLOT(setCurrentColor())); - //Set the color space m_page->colorSpaceSelector->setCurrentColorSpace(image->colorSpace()); //set the proofing space m_proofingConfig = m_image->proofingConfiguration(); m_page->proofSpaceSelector->setCurrentColorSpace(KoColorSpaceRegistry::instance()->colorSpace(m_proofingConfig->proofingModel, m_proofingConfig->proofingDepth,m_proofingConfig->proofingProfile)); m_page->cmbIntent->setCurrentIndex((int)m_proofingConfig->intent); m_page->ckbBlackPointComp->setChecked(m_proofingConfig->conversionFlags.testFlag(KoColorConversionTransformation::BlackpointCompensation)); - m_gamutWarning = new KoColorPopupAction(this); - m_gamutWarning->setCurrentColor(m_proofingConfig->warningColor); - m_gamutWarning->setToolTip(i18n("Set color used for warning")); - m_page->gamutAlarm->setDefaultAction(m_gamutWarning); + m_page->gamutAlarm->setColor(m_proofingConfig->warningColor); + m_page->gamutAlarm->setToolTip(i18n("Set color used for warning")); m_page->sldAdaptationState->setMaximum(20); m_page->sldAdaptationState->setMinimum(0); m_page->sldAdaptationState->setValue((int)m_proofingConfig->adaptationState*20); KisSignalCompressor *softProofConfigCompressor = new KisSignalCompressor(500, KisSignalCompressor::POSTPONE,this); - connect(m_gamutWarning, SIGNAL(colorChanged(KoColor)), softProofConfigCompressor, SLOT(start())); + connect(m_page->gamutAlarm, SIGNAL(changed(KoColor)), softProofConfigCompressor, SLOT(start())); connect(m_page->proofSpaceSelector, SIGNAL(colorSpaceChanged(const KoColorSpace*)), softProofConfigCompressor, SLOT(start())); connect(m_page->cmbIntent, SIGNAL(currentIndexChanged(int)), softProofConfigCompressor, SLOT(start())); connect(m_page->ckbBlackPointComp, SIGNAL(stateChanged(int)), softProofConfigCompressor, SLOT(start())); connect(m_page->sldAdaptationState, SIGNAL(valueChanged(int)), softProofConfigCompressor, SLOT(start())); connect(softProofConfigCompressor, SIGNAL(timeout()), this, SLOT(setProofingConfig())); //annotations vKisAnnotationSP_it beginIt = image->beginAnnotations(); vKisAnnotationSP_it endIt = image->endAnnotations(); vKisAnnotationSP_it it = beginIt; while (it != endIt) { if (!(*it) || (*it)->type().isEmpty()) { dbgFile << "Warning: empty annotation"; it++; continue; } m_page->cmbAnnotations->addItem((*it) -> type()); it++; } connect(m_page->cmbAnnotations, SIGNAL(activated(QString)), SLOT(setAnnotation(QString))); setAnnotation(m_page->cmbAnnotations->currentText()); } KisDlgImageProperties::~KisDlgImageProperties() { delete m_page; } const KoColorSpace * KisDlgImageProperties::colorSpace() { return m_page->colorSpaceSelector->currentColorSpace(); } void KisDlgImageProperties::setCurrentColor() { - KisLayerUtils::changeImageDefaultProjectionColor(m_image, m_defaultColorAction->currentKoColor()); + KoColor background = m_page->bnBackgroundColor->color(); + background.setOpacity(m_page->sldBackgroundColor->value()); + KisLayerUtils::changeImageDefaultProjectionColor(m_image, background); } void KisDlgImageProperties::setProofingConfig() { m_proofingConfig->conversionFlags = KoColorConversionTransformation::HighQuality; if (m_page->ckbBlackPointComp) m_proofingConfig->conversionFlags |= KoColorConversionTransformation::BlackpointCompensation; m_proofingConfig->intent = (KoColorConversionTransformation::Intent)m_page->cmbIntent->currentIndex(); m_proofingConfig->proofingProfile = m_page->proofSpaceSelector->currentColorSpace()->profile()->name(); m_proofingConfig->proofingModel = m_page->proofSpaceSelector->currentColorSpace()->colorModelId().id(); m_proofingConfig->proofingDepth = "U8";//default to this - m_proofingConfig->warningColor = m_gamutWarning->currentKoColor(); + m_proofingConfig->warningColor = m_page->gamutAlarm->color(); m_proofingConfig->adaptationState = (double)m_page->sldAdaptationState->value()/20.0; qDebug()<<"set proofing config in properties: "<proofingProfile; m_image->setProofingConfiguration(m_proofingConfig); } void KisDlgImageProperties::setAnnotation(const QString &type) { KisAnnotationSP annotation = m_image->annotation(type); if (annotation) { m_page->lblDescription->clear(); m_page->txtAnnotation->clear(); m_page->lblDescription->setText(annotation->description()); m_page->txtAnnotation->appendPlainText(annotation->displayText()); } else { m_page->lblDescription->clear(); m_page->txtAnnotation->clear(); } } diff --git a/libs/ui/dialogs/kis_dlg_image_properties.h b/libs/ui/dialogs/kis_dlg_image_properties.h index 22b0dbbef5..4c35e89328 100644 --- a/libs/ui/dialogs/kis_dlg_image_properties.h +++ b/libs/ui/dialogs/kis_dlg_image_properties.h @@ -1,69 +1,65 @@ /* * Copyright (c) 2004 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_DLG_IMAGE_PROPERTIES_H_ #define KIS_DLG_IMAGE_PROPERTIES_H_ #include #include "KisProofingConfiguration.h" #include #include "ui_wdgimageproperties.h" class KoColorSpace; -class KoColorPopupAction; - class WdgImageProperties : public QWidget, public Ui::WdgImageProperties { Q_OBJECT public: WdgImageProperties(QWidget *parent) : QWidget(parent) { setupUi(this); } }; class KisDlgImageProperties : public KoDialog { Q_OBJECT public: KisDlgImageProperties(KisImageWSP image, QWidget *parent = 0, const char *name = 0); virtual ~KisDlgImageProperties(); const KoColorSpace * colorSpace(); private Q_SLOTS: void setAnnotation(const QString& type); void setCurrentColor(); void setProofingConfig(); private: WdgImageProperties * m_page; KisImageWSP m_image; - KoColorPopupAction *m_defaultColorAction; - KoColorPopupAction *m_gamutWarning; KisProofingConfigurationSP m_proofingConfig; }; #endif // KIS_DLG_IMAGE_PROPERTIES_H_ diff --git a/libs/ui/dialogs/kis_dlg_internal_color_selector.cpp b/libs/ui/dialogs/kis_dlg_internal_color_selector.cpp new file mode 100644 index 0000000000..8af2254e6f --- /dev/null +++ b/libs/ui/dialogs/kis_dlg_internal_color_selector.cpp @@ -0,0 +1,271 @@ +/* + * Copyright (C) Wolthera van Hovell tot Westerflier , (C) 2016 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include +#include + +#include "KoColorSpaceRegistry.h" +#include +#include +#include + +#include "kis_signal_compressor.h" +#include "KisViewManager.h" +#include "KoColorDisplayRendererInterface.h" + +#include "kis_spinbox_color_selector.h" + +#include "kis_dlg_internal_color_selector.h" +#include "ui_wdgdlginternalcolorselector.h" +#include "kis_config.h" +#include "kis_config_notifier.h" +#include "kis_color_input.h" + +struct KisDlgInternalColorSelector::Private +{ + bool allowUpdates = true; + KoColor currentColor; + KoColor previousColor; + KoColor sRGB = KoColor(KoColorSpaceRegistry::instance()->rgb8()); + const KoColorSpace *currentColorSpace; + bool lockUsedCS = false; + bool chooseAlpha = false; + KisSignalCompressor *compressColorChanges; + const KoColorDisplayRendererInterface *displayRenderer; + KisHexColorInput *hexColorInput; +}; + +KisDlgInternalColorSelector::KisDlgInternalColorSelector(QWidget *parent, KoColor color, Config config, const QString &caption, const KoColorDisplayRendererInterface *displayRenderer) + : QDialog(parent) + ,m_d(new Private) +{ + setModal(config.modal); + this->setFocusPolicy(Qt::ClickFocus); + m_ui = new Ui_WdgDlgInternalColorSelector(); + m_ui->setupUi(this); + + setWindowTitle(caption); + + m_d->currentColor = color; + m_d->currentColorSpace = m_d->currentColor.colorSpace(); + m_d->displayRenderer = displayRenderer; + + m_ui->spinboxselector->slotSetColor(color); + connect(m_ui->spinboxselector, SIGNAL(sigNewColor(KoColor)), this, SLOT(slotColorUpdated(KoColor))); + + m_ui->visualSelector->slotSetColor(color); + m_ui->visualSelector->setDisplayRenderer(displayRenderer); + m_ui->visualSelector->setConfig(false, config.modal); + if (config.visualColorSelector) { + connect(m_ui->visualSelector, SIGNAL(sigNewColor(KoColor)), this, SLOT(slotColorUpdated(KoColor))); + connect(KisConfigNotifier::instance(), SIGNAL(configChanged()), m_ui->visualSelector, SLOT(ConfigurationChanged())); + } else { + m_ui->visualSelector->hide(); + } + if (config.screenColorPicker) { + connect(m_ui->screenColorPicker, SIGNAL(sigNewColorPicked(KoColor)),this, SLOT(slotColorUpdated(KoColor))); + } else { + m_ui->screenColorPicker->hide(); + } + //TODO: Add disable signal as well. Might be not necessary...? + KisConfig cfg; + QString paletteName = cfg.readEntry("internal_selector_active_color_set", QString()); + KoResourceServer* rServer = KoResourceServerProvider::instance()->paletteServer(false); + KoColorSet *savedPal = rServer->resourceByName(paletteName); + if (savedPal) { + m_ui->paletteBox->setColorSet(savedPal); + } else { + savedPal = rServer->resources().first(); + if (savedPal) { + m_ui->paletteBox->setColorSet(savedPal); + } + } + if (config.paletteBox) { + connect(m_ui->paletteBox, SIGNAL(colorChanged(KoColor,bool)), this, SLOT(slotColorUpdated(KoColor))); + m_ui->paletteBox->setDisplayRenderer(displayRenderer); + } else { + m_ui->paletteBox->hide(); + } + + if (config.prevNextButtons) { + m_ui->currentColor->setColor(m_d->currentColor); + m_ui->currentColor->setDisplayRenderer(displayRenderer); + m_ui->previousColor->setColor(m_d->currentColor); + m_ui->previousColor->setDisplayRenderer(displayRenderer); + connect(this, SIGNAL(accepted()), this, SLOT(setPreviousColor())); + connect(m_ui->previousColor, SIGNAL(triggered(KoColorPatch*)), SLOT(slotSetColorFromPatch(KoColorPatch*))); + } else { + m_ui->currentColor->hide(); + m_ui->previousColor->hide(); + } + + if (config.hexInput) { + m_d->sRGB.fromKoColor(m_d->currentColor); + m_d->hexColorInput = new KisHexColorInput(this, &m_d->sRGB); + m_d->hexColorInput->update(); + connect(m_d->hexColorInput, SIGNAL(updated()), SLOT(slotSetColorFromHex())); + m_ui->rightPane->addWidget(m_d->hexColorInput); + m_d->hexColorInput->setToolTip(i18n("This is a hexcode input, for webcolors. It can only get colors in the sRGB space.")); + } + + connect(this, SIGNAL(signalForegroundColorChosen(KoColor)), this, SLOT(slotLockSelector())); + m_d->compressColorChanges = new KisSignalCompressor(100 /* ms */, KisSignalCompressor::POSTPONE, this); + connect(m_d->compressColorChanges, SIGNAL(timeout()), this, SLOT(endUpdateWithNewColor())); + + connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept())); + connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject())); +} + +KisDlgInternalColorSelector::~KisDlgInternalColorSelector() +{ + delete m_ui; + //TODO: Does the scoped pointer also need to be deleted??? +} + +void KisDlgInternalColorSelector::slotColorUpdated(KoColor newColor) +{ + //if the update did not come from this selector... + if (m_d->allowUpdates || QObject::sender() == this->parent()) { + if (m_d->lockUsedCS){ + newColor.convertTo(m_d->currentColorSpace); + m_d->currentColor = newColor; + } else { + m_d->currentColor = newColor; + } + updateAllElements(QObject::sender()); + } +} + +void KisDlgInternalColorSelector::colorSpaceChanged(const KoColorSpace *cs) +{ + if (cs == m_d->currentColorSpace) { + return; + } + + m_d->currentColorSpace = KoColorSpaceRegistry::instance()->colorSpace(cs->colorModelId().id(), cs->colorDepthId().id(), cs->profile()); + m_ui->spinboxselector->slotSetColorSpace(m_d->currentColorSpace); + m_ui->visualSelector->slotsetColorSpace(m_d->currentColorSpace); + +} + +void KisDlgInternalColorSelector::lockUsedColorSpace(const KoColorSpace *cs) +{ + colorSpaceChanged(cs); + m_d->lockUsedCS = true; +} + +void KisDlgInternalColorSelector::setDisplayRenderer(const KoColorDisplayRendererInterface *displayRenderer) +{ + if (displayRenderer) { + m_d->displayRenderer = displayRenderer; + m_ui->visualSelector->setDisplayRenderer(displayRenderer); + m_ui->currentColor->setDisplayRenderer(displayRenderer); + m_ui->previousColor->setDisplayRenderer(displayRenderer); + m_ui->paletteBox->setDisplayRenderer(displayRenderer); + } else { + m_d->displayRenderer = KoDumbColorDisplayRenderer::instance(); + } +} + +KoColor KisDlgInternalColorSelector::getModalColorDialog(const KoColor color, QWidget* parent, QString caption) +{ + Config config = Config(); + KisDlgInternalColorSelector dialog(parent, color, config, caption); + dialog.exec(); + return dialog.getCurrentColor(); +} + +KoColor KisDlgInternalColorSelector::getCurrentColor() +{ + return m_d->currentColor; +} + +void KisDlgInternalColorSelector::chooseAlpha(bool chooseAlpha) +{ + m_d->chooseAlpha = chooseAlpha; +} + +void KisDlgInternalColorSelector::slotConfigurationChanged() +{ + //m_d->canvas->displayColorConverter()-> + //slotColorSpaceChanged(m_d->canvas->image()->colorSpace()); +} + +void KisDlgInternalColorSelector::slotLockSelector() +{ + m_d->allowUpdates = false; +} + +void KisDlgInternalColorSelector::setPreviousColor() +{ + m_d->previousColor = m_d->currentColor; + KisConfig cfg; + if (m_ui->paletteBox->colorSet()) { + cfg.writeEntry("internal_selector_active_color_set", m_ui->paletteBox->colorSet()->name()); + } +} + +void KisDlgInternalColorSelector::updateAllElements(QObject *source) +{ + //update everything!!! + if (source != m_ui->spinboxselector) { + m_ui->spinboxselector->slotSetColor(m_d->currentColor); + } + if (source != m_ui->visualSelector) { + m_ui->visualSelector->slotSetColor(m_d->currentColor); + } + + if (source != m_d->hexColorInput) { + m_d->sRGB.fromKoColor(m_d->currentColor); + m_d->hexColorInput->update(); + } + + m_ui->previousColor->setColor(m_d->previousColor); + + m_ui->currentColor->setColor(m_d->currentColor); + + if (source != this->parent()) { + emit(signalForegroundColorChosen(m_d->currentColor)); + m_d->compressColorChanges->start(); + } +} + + +void KisDlgInternalColorSelector::endUpdateWithNewColor() +{ + m_d->allowUpdates = true; +} + +void KisDlgInternalColorSelector::focusInEvent(QFocusEvent *) +{ + //setPreviousColor(); +} + +void KisDlgInternalColorSelector::slotSetColorFromPatch(KoColorPatch* patch) +{ + slotColorUpdated(patch->color()); +} + +void KisDlgInternalColorSelector::slotSetColorFromHex() +{ + slotColorUpdated(m_d->sRGB); +} + diff --git a/libs/ui/dialogs/kis_dlg_internal_color_selector.h b/libs/ui/dialogs/kis_dlg_internal_color_selector.h new file mode 100644 index 0000000000..07fc5f4e40 --- /dev/null +++ b/libs/ui/dialogs/kis_dlg_internal_color_selector.h @@ -0,0 +1,171 @@ +/* + * Copyright (C) Wolthera van Hovell tot Westerflier , (C) 2016 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KISINTERNALCOLORSELECTOR_H +#define KISINTERNALCOLORSELECTOR_H + +#include "kritaui_export.h" +#include "KoColor.h" +#include "KoColorSpace.h" +#include "KoColorDisplayRendererInterface.h" + +#include + +#include "ui_wdgdlginternalcolorselector.h" + +/** + * @brief The KisInternalColorSelector class + * + * A non-modal color selector dialog that is not a plugin and can thus be used for filters. + */ +class KRITAUI_EXPORT KisDlgInternalColorSelector : public QDialog +{ + Q_OBJECT +public: + struct Config + { + Config() : + modal(true), + visualColorSelector(true), + paletteBox(true), + screenColorPicker(true), + prevNextButtons(true), + hexInput(true), + useAlpha(false){} + bool modal; + bool visualColorSelector; + bool paletteBox; + bool screenColorPicker; + bool prevNextButtons; + bool hexInput; + bool useAlpha; + }; + + KisDlgInternalColorSelector(QWidget* parent, KoColor color, Config config, const QString &caption, const KoColorDisplayRendererInterface *displayRenderer = KoDumbColorDisplayRenderer::instance()); + ~KisDlgInternalColorSelector(); + + /** + * @brief slotColorSpaceChanged + * Color space has changed, use this dialog to change the colorspace. + */ + void colorSpaceChanged(const KoColorSpace *cs); + + /** + * @brief lockUsedColorSpace + * Lock the used colorspace of this selector. + * @param cs + */ + void lockUsedColorSpace(const KoColorSpace *cs); + + /** + * @brief setDisplayRenderer + * Set the display renderer. This is necessary for HDR color manage support. + * @param displayRenderer + */ + void setDisplayRenderer(const KoColorDisplayRendererInterface *displayRenderer); + + /** + * @brief getModalColorDialog + * Excecute this dialog modally. The function returns + * the KoColor you want. + * @param color - The current color. Make sure this is in the color space you want your + * end color to be in. + * @param chooseAlpha - Whether or not the alpha-choosing functionality should be used. + */ + static KoColor getModalColorDialog(const KoColor color, QWidget* parent = Q_NULLPTR, QString caption = QString()); + + /** + * @brief getCurrentColor + * @return gives currently active color; + */ + KoColor getCurrentColor(); + + void chooseAlpha(bool chooseAlpha); + +Q_SIGNALS: + /** + * @brief signalForegroundColorChosen + * The most important signal. This will sent out when a color has been picked from the selector. + * There will be a small delay to make sure that the selector causes too many updates. + * + * Do not connect this to slotColorUpdated. + * @param color The new color chosen + */ + + void signalForegroundColorChosen(KoColor color); +public Q_SLOTS: + /** + * @brief slotColorUpdated + * Very important slot. Is connected to krita's resources to make sure it has + * the currently active color. It's very important that this function is able to understand + * when the signal came from itself. + * @param newColor This is the new color. + */ + void slotColorUpdated(KoColor newColor); +private Q_SLOTS: + + /** + * @brief slotLockSelector + * This slot will prevent the color from being updated. + */ + void slotLockSelector(); + + /** + * @brief slotConfigurationChanged + * Wrapper slot for changes to the colorspace. + */ + void slotConfigurationChanged(); + + void endUpdateWithNewColor(); + + /** + * @brief setPreviousColor + * triggered when the dialog is either accepted or hidden. + */ + void setPreviousColor(); + + /** + * @brief slotSetColorFromPatch + * update current color from kocolorpatch. + * @param patch + */ + void slotSetColorFromPatch(KoColorPatch* patch); + + /** + * @brief slotSetColorFromHex + * Update from the hex color input. + */ + void slotSetColorFromHex(); + + +private: + Ui_WdgDlgInternalColorSelector *m_ui; //the UI + struct Private; //The private struct + const QScopedPointer m_d; //the private pointer + + /** + * @brief updateAllElements + * Updates each widget with the new element, and if it's responsible for the update sents + * a signal out that there's a new color. + */ + void updateAllElements(QObject *source); + + virtual void focusInEvent(QFocusEvent *); +}; + +#endif // KISINTERNALCOLORSELECTOR_H diff --git a/libs/ui/dialogs/kis_dlg_layer_style.cpp b/libs/ui/dialogs/kis_dlg_layer_style.cpp index 9de074c419..c7bd978f77 100644 --- a/libs/ui/dialogs/kis_dlg_layer_style.cpp +++ b/libs/ui/dialogs/kis_dlg_layer_style.cpp @@ -1,1432 +1,1445 @@ /* * Copyright (c) 2014 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_dlg_layer_style.h" #include #include #include #include #include #include #include #include #include #include #include #include +#include #include #include "kis_config.h" #include "kis_cmb_contour.h" #include "kis_cmb_gradient.h" #include "kis_resource_server_provider.h" #include "kis_psd_layer_style_resource.h" #include "kis_psd_layer_style.h" #include "kis_signals_blocker.h" #include "kis_signal_compressor.h" #include "kis_canvas_resource_provider.h" #include KoAbstractGradient* fetchGradientLazy(KoAbstractGradient *gradient, KisCanvasResourceProvider *resourceProvider) { if (!gradient) { gradient = resourceProvider->currentGradient(); } return gradient; } KisDlgLayerStyle::KisDlgLayerStyle(KisPSDLayerStyleSP layerStyle, KisCanvasResourceProvider *resourceProvider, QWidget *parent) : KoDialog(parent) , m_layerStyle(layerStyle) , m_initialLayerStyle(layerStyle->clone()) , m_isSwitchingPredefinedStyle(false) , m_sanityLayerStyleDirty(false) { setCaption(i18n("Layer Styles")); setButtons(Ok | Cancel); setDefaultButton(Ok); m_configChangedCompressor = new KisSignalCompressor(1000, KisSignalCompressor::POSTPONE, this); connect(m_configChangedCompressor, SIGNAL(timeout()), SIGNAL(configChanged())); QWidget *page = new QWidget(this); wdgLayerStyles.setupUi(page); setMainWidget(page); connect(wdgLayerStyles.lstStyleSelector, SIGNAL(itemChanged(QListWidgetItem*)), SLOT(notifyGuiConfigChanged())); m_stylesSelector = new StylesSelector(this); connect(m_stylesSelector, SIGNAL(styleSelected(KisPSDLayerStyleSP)), SLOT(notifyPredefinedStyleSelected(KisPSDLayerStyleSP))); wdgLayerStyles.stylesStack->addWidget(m_stylesSelector); m_blendingOptions = new BlendingOptions(this); wdgLayerStyles.stylesStack->addWidget(m_blendingOptions); m_dropShadow = new DropShadow(DropShadow::DropShadowMode, this); wdgLayerStyles.stylesStack->addWidget(m_dropShadow); connect(m_dropShadow, SIGNAL(configChanged()), SLOT(notifyGuiConfigChanged())); m_innerShadow = new DropShadow(DropShadow::InnerShadowMode, this); wdgLayerStyles.stylesStack->addWidget(m_innerShadow); connect(m_innerShadow, SIGNAL(configChanged()), SLOT(notifyGuiConfigChanged())); m_outerGlow = new InnerGlow(InnerGlow::OuterGlowMode, resourceProvider, this); wdgLayerStyles.stylesStack->addWidget(m_outerGlow); connect(m_outerGlow, SIGNAL(configChanged()), SLOT(notifyGuiConfigChanged())); m_innerGlow = new InnerGlow(InnerGlow::InnerGlowMode, resourceProvider, this); wdgLayerStyles.stylesStack->addWidget(m_innerGlow); connect(m_innerGlow, SIGNAL(configChanged()), SLOT(notifyGuiConfigChanged())); m_contour = new Contour(this); m_texture = new Texture(this); m_bevelAndEmboss = new BevelAndEmboss(m_contour, m_texture, this); wdgLayerStyles.stylesStack->addWidget(m_bevelAndEmboss); wdgLayerStyles.stylesStack->addWidget(m_contour); wdgLayerStyles.stylesStack->addWidget(m_texture); connect(m_bevelAndEmboss, SIGNAL(configChanged()), SLOT(notifyGuiConfigChanged())); m_satin = new Satin(this); wdgLayerStyles.stylesStack->addWidget(m_satin); connect(m_satin, SIGNAL(configChanged()), SLOT(notifyGuiConfigChanged())); m_colorOverlay = new ColorOverlay(this); wdgLayerStyles.stylesStack->addWidget(m_colorOverlay); connect(m_colorOverlay, SIGNAL(configChanged()), SLOT(notifyGuiConfigChanged())); m_gradientOverlay = new GradientOverlay(resourceProvider, this); wdgLayerStyles.stylesStack->addWidget(m_gradientOverlay); connect(m_gradientOverlay, SIGNAL(configChanged()), SLOT(notifyGuiConfigChanged())); m_patternOverlay = new PatternOverlay(this); wdgLayerStyles.stylesStack->addWidget(m_patternOverlay); connect(m_patternOverlay, SIGNAL(configChanged()), SLOT(notifyGuiConfigChanged())); m_stroke = new Stroke(resourceProvider, this); wdgLayerStyles.stylesStack->addWidget(m_stroke); connect(m_stroke, SIGNAL(configChanged()), SLOT(notifyGuiConfigChanged())); KisConfig cfg; wdgLayerStyles.stylesStack->setCurrentIndex(cfg.readEntry("KisDlgLayerStyle::current", 1)); wdgLayerStyles.lstStyleSelector->setCurrentRow(cfg.readEntry("KisDlgLayerStyle::current", 1)); connect(wdgLayerStyles.lstStyleSelector, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)), this, SLOT(changePage(QListWidgetItem*,QListWidgetItem*))); notifyPredefinedStyleSelected(layerStyle); connect(m_dropShadow, SIGNAL(globalAngleChanged(int)), SLOT(syncGlobalAngle(int))); connect(m_innerShadow, SIGNAL(globalAngleChanged(int)), SLOT(syncGlobalAngle(int))); connect(m_bevelAndEmboss, SIGNAL(globalAngleChanged(int)), SLOT(syncGlobalAngle(int))); connect(wdgLayerStyles.btnNewStyle, SIGNAL(clicked()), SLOT(slotNewStyle())); connect(wdgLayerStyles.btnLoadStyle, SIGNAL(clicked()), SLOT(slotLoadStyle())); connect(wdgLayerStyles.btnSaveStyle, SIGNAL(clicked()), SLOT(slotSaveStyle())); connect(wdgLayerStyles.chkMasterFxSwitch, SIGNAL(toggled(bool)), SLOT(slotMasterFxSwitchChanged(bool))); connect(this, SIGNAL(accepted()), SLOT(slotNotifyOnAccept())); connect(this, SIGNAL(rejected()), SLOT(slotNotifyOnReject())); } KisDlgLayerStyle::~KisDlgLayerStyle() { } void KisDlgLayerStyle::slotMasterFxSwitchChanged(bool value) { wdgLayerStyles.lstStyleSelector->setEnabled(value); wdgLayerStyles.stylesStack->setEnabled(value); wdgLayerStyles.btnNewStyle->setEnabled(value); wdgLayerStyles.btnLoadStyle->setEnabled(value); wdgLayerStyles.btnSaveStyle->setEnabled(value); notifyGuiConfigChanged(); } void KisDlgLayerStyle::notifyGuiConfigChanged() { if (m_isSwitchingPredefinedStyle) return; m_configChangedCompressor->start(); m_layerStyle->setUuid(QUuid::createUuid()); m_sanityLayerStyleDirty = true; m_stylesSelector->notifyExternalStyleChanged(m_layerStyle->name(), m_layerStyle->uuid()); } void KisDlgLayerStyle::notifyPredefinedStyleSelected(KisPSDLayerStyleSP style) { m_isSwitchingPredefinedStyle = true; setStyle(style); m_isSwitchingPredefinedStyle = false; m_configChangedCompressor->start(); } void KisDlgLayerStyle::slotNotifyOnAccept() { if (m_configChangedCompressor->isActive()) { m_configChangedCompressor->stop(); emit configChanged(); } } void KisDlgLayerStyle::slotNotifyOnReject() { notifyPredefinedStyleSelected(m_initialLayerStyle); m_configChangedCompressor->stop(); emit configChanged(); } bool checkCustomNameAvailable(const QString &name) { const QString customName = "CustomStyles.asl"; KoResourceServer *server = KisResourceServerProvider::instance()->layerStyleCollectionServer(); KoResource *resource = server->resourceByName(customName); if (!resource) return true; KisPSDLayerStyleCollectionResource *collection = dynamic_cast(resource); Q_FOREACH (KisPSDLayerStyleSP style, collection->layerStyles()) { if (style->name() == name) { return false; } } return true; } QString selectAvailableStyleName(const QString &name) { QString finalName = name; if (checkCustomNameAvailable(finalName)) { return finalName; } int i = 0; do { finalName = QString("%1%2").arg(name).arg(i++); } while (!checkCustomNameAvailable(finalName)); return finalName; } void KisDlgLayerStyle::slotNewStyle() { QString styleName = QInputDialog::getText(this, i18nc("@title:window", "Enter new style name"), i18nc("@label:textbox", "Name:"), QLineEdit::Normal, i18nc("Default name for a new style", "New Style")); KisPSDLayerStyleSP style = this->style(); style->setName(selectAvailableStyleName(styleName)); m_stylesSelector->addNewStyle(style->clone()); } void KisDlgLayerStyle::slotLoadStyle() { QString filename; // default value? KoFileDialog dialog(this, KoFileDialog::OpenFile, "layerstyle"); dialog.setCaption(i18n("Select ASL file")); dialog.setMimeTypeFilters(QStringList() << "application/x-photoshop-style-library", "application/x-photoshop-style-library"); filename = dialog.filename(); m_stylesSelector->loadCollection(filename); wdgLayerStyles.lstStyleSelector->setCurrentRow(0); } void KisDlgLayerStyle::slotSaveStyle() { QString filename; // default value? KoFileDialog dialog(this, KoFileDialog::SaveFile, "layerstyle"); dialog.setCaption(i18n("Select ASL file")); dialog.setMimeTypeFilters(QStringList() << "application/x-photoshop-style-library", "application/x-photoshop-style-library"); filename = dialog.filename(); QScopedPointer collection( new KisPSDLayerStyleCollectionResource(filename)); KisPSDLayerStyleSP newStyle = style()->clone(); newStyle->setName(QFileInfo(filename).baseName()); KisPSDLayerStyleCollectionResource::StylesVector vector = collection->layerStyles(); vector << newStyle; collection->setLayerStyles(vector); collection->save(); } void KisDlgLayerStyle::changePage(QListWidgetItem *current, QListWidgetItem *previous) { if (!current) { current = previous; } wdgLayerStyles.stylesStack->setCurrentIndex(wdgLayerStyles.lstStyleSelector->row(current)); } void KisDlgLayerStyle::setStyle(KisPSDLayerStyleSP style) { *m_layerStyle = *style; m_sanityLayerStyleDirty = false; m_stylesSelector->notifyExternalStyleChanged(m_layerStyle->name(), m_layerStyle->uuid()); QListWidgetItem *item; item = wdgLayerStyles.lstStyleSelector->item(2); item->setCheckState(m_layerStyle->dropShadow()->effectEnabled() ? Qt::Checked : Qt::Unchecked); item = wdgLayerStyles.lstStyleSelector->item(3); item->setCheckState(m_layerStyle->innerShadow()->effectEnabled() ? Qt::Checked : Qt::Unchecked); item = wdgLayerStyles.lstStyleSelector->item(4); item->setCheckState(m_layerStyle->outerGlow()->effectEnabled() ? Qt::Checked : Qt::Unchecked); item = wdgLayerStyles.lstStyleSelector->item(5); item->setCheckState(m_layerStyle->innerGlow()->effectEnabled() ? Qt::Checked : Qt::Unchecked); item = wdgLayerStyles.lstStyleSelector->item(6); item->setCheckState(m_layerStyle->bevelAndEmboss()->effectEnabled() ? Qt::Checked : Qt::Unchecked); item = wdgLayerStyles.lstStyleSelector->item(7); item->setCheckState(m_layerStyle->bevelAndEmboss()->contourEnabled() ? Qt::Checked : Qt::Unchecked); item = wdgLayerStyles.lstStyleSelector->item(8); item->setCheckState(m_layerStyle->bevelAndEmboss()->textureEnabled() ? Qt::Checked : Qt::Unchecked); item = wdgLayerStyles.lstStyleSelector->item(9); item->setCheckState(m_layerStyle->satin()->effectEnabled() ? Qt::Checked : Qt::Unchecked); item = wdgLayerStyles.lstStyleSelector->item(10); item->setCheckState(m_layerStyle->colorOverlay()->effectEnabled() ? Qt::Checked : Qt::Unchecked); item = wdgLayerStyles.lstStyleSelector->item(11); item->setCheckState(m_layerStyle->gradientOverlay()->effectEnabled() ? Qt::Checked : Qt::Unchecked); item = wdgLayerStyles.lstStyleSelector->item(12); item->setCheckState(m_layerStyle->patternOverlay()->effectEnabled() ? Qt::Checked : Qt::Unchecked); item = wdgLayerStyles.lstStyleSelector->item(13); item->setCheckState(m_layerStyle->stroke()->effectEnabled() ? Qt::Checked : Qt::Unchecked); m_dropShadow->setShadow(m_layerStyle->dropShadow()); m_innerShadow->setShadow(m_layerStyle->innerShadow()); m_outerGlow->setConfig(m_layerStyle->outerGlow()); m_innerGlow->setConfig(m_layerStyle->innerGlow()); m_bevelAndEmboss->setBevelAndEmboss(m_layerStyle->bevelAndEmboss()); m_satin->setSatin(m_layerStyle->satin()); m_colorOverlay->setColorOverlay(m_layerStyle->colorOverlay()); m_gradientOverlay->setGradientOverlay(m_layerStyle->gradientOverlay()); m_patternOverlay->setPatternOverlay(m_layerStyle->patternOverlay()); m_stroke->setStroke(m_layerStyle->stroke()); wdgLayerStyles.chkMasterFxSwitch->setChecked(m_layerStyle->isEnabled()); slotMasterFxSwitchChanged(m_layerStyle->isEnabled()); } KisPSDLayerStyleSP KisDlgLayerStyle::style() const { m_layerStyle->setEnabled(wdgLayerStyles.chkMasterFxSwitch->isChecked()); m_layerStyle->dropShadow()->setEffectEnabled(wdgLayerStyles.lstStyleSelector->item(2)->checkState() == Qt::Checked); m_layerStyle->innerShadow()->setEffectEnabled(wdgLayerStyles.lstStyleSelector->item(3)->checkState() == Qt::Checked); m_layerStyle->outerGlow()->setEffectEnabled(wdgLayerStyles.lstStyleSelector->item(4)->checkState() == Qt::Checked); m_layerStyle->innerGlow()->setEffectEnabled(wdgLayerStyles.lstStyleSelector->item(5)->checkState() == Qt::Checked); m_layerStyle->bevelAndEmboss()->setEffectEnabled(wdgLayerStyles.lstStyleSelector->item(6)->checkState() == Qt::Checked); m_layerStyle->bevelAndEmboss()->setContourEnabled(wdgLayerStyles.lstStyleSelector->item(7)->checkState() == Qt::Checked); m_layerStyle->bevelAndEmboss()->setTextureEnabled(wdgLayerStyles.lstStyleSelector->item(8)->checkState() == Qt::Checked); m_layerStyle->satin()->setEffectEnabled(wdgLayerStyles.lstStyleSelector->item(9)->checkState() == Qt::Checked); m_layerStyle->colorOverlay()->setEffectEnabled(wdgLayerStyles.lstStyleSelector->item(10)->checkState() == Qt::Checked); m_layerStyle->gradientOverlay()->setEffectEnabled(wdgLayerStyles.lstStyleSelector->item(11)->checkState() == Qt::Checked); m_layerStyle->patternOverlay()->setEffectEnabled(wdgLayerStyles.lstStyleSelector->item(12)->checkState() == Qt::Checked); m_layerStyle->stroke()->setEffectEnabled(wdgLayerStyles.lstStyleSelector->item(13)->checkState() == Qt::Checked); m_dropShadow->fetchShadow(m_layerStyle->dropShadow()); m_innerShadow->fetchShadow(m_layerStyle->innerShadow()); m_outerGlow->fetchConfig(m_layerStyle->outerGlow()); m_innerGlow->fetchConfig(m_layerStyle->innerGlow()); m_bevelAndEmboss->fetchBevelAndEmboss(m_layerStyle->bevelAndEmboss()); m_satin->fetchSatin(m_layerStyle->satin()); m_colorOverlay->fetchColorOverlay(m_layerStyle->colorOverlay()); m_gradientOverlay->fetchGradientOverlay(m_layerStyle->gradientOverlay()); m_patternOverlay->fetchPatternOverlay(m_layerStyle->patternOverlay()); m_stroke->fetchStroke(m_layerStyle->stroke()); m_sanityLayerStyleDirty = false; m_stylesSelector->notifyExternalStyleChanged(m_layerStyle->name(), m_layerStyle->uuid()); return m_layerStyle; } void KisDlgLayerStyle::syncGlobalAngle(int angle) { KisPSDLayerStyleSP style = this->style(); if (style->dropShadow()->useGlobalLight()) { style->dropShadow()->setAngle(angle); } if (style->innerShadow()->useGlobalLight()) { style->innerShadow()->setAngle(angle); } if (style->bevelAndEmboss()->useGlobalLight()) { style->bevelAndEmboss()->setAngle(angle); } setStyle(style); } /********************************************************************/ /***** Styles Selector **********************************************/ /********************************************************************/ class StyleItem : public QListWidgetItem { public: StyleItem(KisPSDLayerStyleSP style) : QListWidgetItem(style->name()) , m_style(style) { } public: KisPSDLayerStyleSP m_style; }; StylesSelector::StylesSelector(QWidget *parent) : QWidget(parent) { ui.setupUi(this); connect(ui.cmbStyleCollections, SIGNAL(activated(QString)), this, SLOT(loadStyles(QString))); connect(ui.listStyles, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)), this, SLOT(selectStyle(QListWidgetItem*,QListWidgetItem*))); refillCollections(); if (ui.cmbStyleCollections->count()) { ui.cmbStyleCollections->setCurrentIndex(0); loadStyles(ui.cmbStyleCollections->currentText()); } } void StylesSelector::refillCollections() { QString previousCollection = ui.cmbStyleCollections->currentText(); ui.cmbStyleCollections->clear(); Q_FOREACH (KoResource *res, KisResourceServerProvider::instance()->layerStyleCollectionServer()->resources()) { ui.cmbStyleCollections->addItem(res->name()); } if (!previousCollection.isEmpty()) { KisSignalsBlocker blocker(this); int index = ui.cmbStyleCollections->findText(previousCollection); ui.cmbStyleCollections->setCurrentIndex(index); } } void StylesSelector::notifyExternalStyleChanged(const QString &name, const QUuid &uuid) { int currentIndex = -1; for (int i = 0; i < ui.listStyles->count(); i++ ) { StyleItem *item = dynamic_cast(ui.listStyles->item(i)); QString itemName = item->m_style->name(); if (itemName == name) { bool isDirty = item->m_style->uuid() != uuid; if (isDirty) { itemName += "*"; } currentIndex = i; } item->setText(itemName); } ui.listStyles->setCurrentRow(currentIndex); } void StylesSelector::loadStyles(const QString &name) { ui.listStyles->clear(); KoResource *res = KisResourceServerProvider::instance()->layerStyleCollectionServer()->resourceByName(name); KisPSDLayerStyleCollectionResource *collection = dynamic_cast(res); if (collection) { Q_FOREACH (KisPSDLayerStyleSP style, collection->layerStyles()) { // XXX: also use the preview image, when we have one ui.listStyles->addItem(new StyleItem(style)); } } } void StylesSelector::selectStyle(QListWidgetItem *current, QListWidgetItem* /*previous*/) { StyleItem *item = dynamic_cast(current); if (item) { emit styleSelected(item->m_style); } } void StylesSelector::loadCollection(const QString &fileName) { if (!QFileInfo(fileName).exists()) { warnKrita << "Loaded style collection doesn't exist!"; return; } KisPSDLayerStyleCollectionResource *collection = new KisPSDLayerStyleCollectionResource(fileName); collection->load(); KoResourceServer *server = KisResourceServerProvider::instance()->layerStyleCollectionServer(); collection->setFilename(server->saveLocation() + QDir::separator() + collection->name()); server->addResource(collection); refillCollections(); int index = ui.cmbStyleCollections->findText(collection->name()); ui.cmbStyleCollections->setCurrentIndex(index); loadStyles(collection->name()); } void StylesSelector::addNewStyle(KisPSDLayerStyleSP style) { KoResourceServer *server = KisResourceServerProvider::instance()->layerStyleCollectionServer(); // NOTE: not translatable, since it is a key! const QString customName = "CustomStyles.asl"; const QString saveLocation = server->saveLocation(); const QString fullFilename = saveLocation + customName; KoResource *resource = server->resourceByName(customName); KisPSDLayerStyleCollectionResource *collection = 0; if (!resource) { collection = new KisPSDLayerStyleCollectionResource(""); collection->setName(customName); collection->setFilename(fullFilename); KisPSDLayerStyleCollectionResource::StylesVector vector; vector << style; collection->setLayerStyles(vector); server->addResource(collection); } else { collection = dynamic_cast(resource); KisPSDLayerStyleCollectionResource::StylesVector vector; vector = collection->layerStyles(); vector << style; collection->setLayerStyles(vector); collection->save(); } refillCollections(); // select in gui int index = ui.cmbStyleCollections->findText(customName); KIS_ASSERT_RECOVER_RETURN(index >= 0); ui.cmbStyleCollections->setCurrentIndex(index); loadStyles(customName); notifyExternalStyleChanged(style->name(), style->uuid()); } /********************************************************************/ /***** Bevel and Emboss *********************************************/ /********************************************************************/ BevelAndEmboss::BevelAndEmboss(Contour *contour, Texture *texture, QWidget *parent) : QWidget(parent) , m_contour(contour) , m_texture(texture) { ui.setupUi(this); // Structure ui.intDepth->setRange(0, 100); ui.intDepth->setSuffix(i18n(" %")); ui.intSize->setRange(0, 250); ui.intSize->setSuffix(i18n(" px")); ui.intSoften->setRange(0, 18); ui.intSoften->setSuffix(i18n(" px")); connect(ui.cmbStyle, SIGNAL(currentIndexChanged(int)), SIGNAL(configChanged())); connect(ui.cmbTechnique, SIGNAL(currentIndexChanged(int)), SIGNAL(configChanged())); connect(ui.intDepth, SIGNAL(valueChanged(int)), SIGNAL(configChanged())); connect(ui.cmbDirection, SIGNAL(currentIndexChanged(int)), SIGNAL(configChanged())); connect(ui.intSize, SIGNAL(valueChanged(int)), SIGNAL(configChanged())); connect(ui.intSoften, SIGNAL(valueChanged(int)), SIGNAL(configChanged())); // Shading ui.intOpacity->setRange(0, 100); ui.intOpacity->setSuffix(i18n(" %")); ui.intOpacity2->setRange(0, 100); ui.intOpacity2->setSuffix(i18n(" %")); connect(ui.dialAngle, SIGNAL(valueChanged(int)), SLOT(slotDialAngleChanged(int))); connect(ui.intAngle, SIGNAL(valueChanged(int)), SLOT(slotIntAngleChanged(int))); connect(ui.chkUseGlobalLight, SIGNAL(toggled(bool)), SLOT(slotGlobalLightToggled())); connect(ui.dialAngle, SIGNAL(valueChanged(int)), SIGNAL(configChanged())); connect(ui.intAngle, SIGNAL(valueChanged(int)), SIGNAL(configChanged())); connect(ui.chkUseGlobalLight, SIGNAL(toggled(bool)), SIGNAL(configChanged())); connect(ui.intAltitude, SIGNAL(valueChanged(int)), SIGNAL(configChanged())); connect(ui.cmbContour, SIGNAL(currentIndexChanged(int)), SIGNAL(configChanged())); connect(ui.chkAntiAliased, SIGNAL(toggled(bool)), SIGNAL(configChanged())); connect(ui.cmbHighlightMode, SIGNAL(currentIndexChanged(int)), SIGNAL(configChanged())); - connect(ui.bnHighlightColor, SIGNAL(changed(QColor)), SIGNAL(configChanged())); + connect(ui.bnHighlightColor, SIGNAL(changed(KoColor)), SIGNAL(configChanged())); connect(ui.intOpacity, SIGNAL(valueChanged(int)), SIGNAL(configChanged())); connect(ui.cmbShadowMode, SIGNAL(currentIndexChanged(int)), SIGNAL(configChanged())); - connect(ui.bnShadowColor, SIGNAL(changed(QColor)), SIGNAL(configChanged())); + connect(ui.bnShadowColor, SIGNAL(changed(KoColor)), SIGNAL(configChanged())); connect(ui.intOpacity2, SIGNAL(valueChanged(int)), SIGNAL(configChanged()));; // Contour m_contour->ui.intRange->setRange(1, 100); m_contour->ui.intRange->setSuffix(i18n(" %")); connect(m_contour->ui.cmbContour, SIGNAL(currentIndexChanged(int)), SIGNAL(configChanged())); connect(m_contour->ui.chkAntiAliased, SIGNAL(toggled(bool)), SIGNAL(configChanged())); connect(m_contour->ui.intRange, SIGNAL(valueChanged(int)), SIGNAL(configChanged())); // Texture m_texture->ui.intScale->setRange(0, 100); m_texture->ui.intScale->setSuffix(i18n(" %")); m_texture->ui.intDepth->setRange(-1000, 1000); m_texture->ui.intDepth->setSuffix(i18n(" %")); connect(m_texture->ui.patternChooser, SIGNAL(resourceSelected(KoResource*)), SIGNAL(configChanged())); connect(m_texture->ui.intScale, SIGNAL(valueChanged(int)), SIGNAL(configChanged())); connect(m_texture->ui.intDepth, SIGNAL(valueChanged(int)), SIGNAL(configChanged())); connect(m_texture->ui.chkInvert, SIGNAL(toggled(bool)), SIGNAL(configChanged())); connect(m_texture->ui.chkLinkWithLayer, SIGNAL(toggled(bool)), SIGNAL(configChanged())); } void BevelAndEmboss::setBevelAndEmboss(const psd_layer_effects_bevel_emboss *bevelAndEmboss) { ui.cmbStyle->setCurrentIndex((int)bevelAndEmboss->style()); ui.cmbTechnique->setCurrentIndex((int)bevelAndEmboss->technique()); ui.intDepth->setValue(bevelAndEmboss->depth()); ui.cmbDirection->setCurrentIndex((int)bevelAndEmboss->direction()); ui.intSize->setValue(bevelAndEmboss->size()); ui.intSoften->setValue(bevelAndEmboss->soften()); ui.dialAngle->setValue(bevelAndEmboss->angle()); ui.intAngle->setValue(bevelAndEmboss->angle()); ui.chkUseGlobalLight->setChecked(bevelAndEmboss->useGlobalLight()); ui.intAltitude->setValue(bevelAndEmboss->altitude()); // FIXME: curve editing // ui.cmbContour; ui.chkAntiAliased->setChecked(bevelAndEmboss->glossAntiAliased()); ui.cmbHighlightMode->selectCompositeOp(KoID(bevelAndEmboss->highlightBlendMode())); - ui.bnHighlightColor->setColor(bevelAndEmboss->highlightColor()); + KoColor highlightshadow(KoColorSpaceRegistry::instance()->rgb8()); + highlightshadow.fromQColor(bevelAndEmboss->highlightColor()); + ui.bnHighlightColor->setColor(highlightshadow); ui.intOpacity->setValue(bevelAndEmboss->highlightOpacity()); ui.cmbShadowMode->selectCompositeOp(KoID(bevelAndEmboss->shadowBlendMode())); - ui.bnShadowColor->setColor(bevelAndEmboss->shadowColor()); + highlightshadow.fromQColor(bevelAndEmboss->shadowColor()); + ui.bnShadowColor->setColor(highlightshadow); ui.intOpacity2->setValue(bevelAndEmboss->shadowOpacity()); // FIXME: curve editing // m_contour->ui.cmbContour; m_contour->ui.chkAntiAliased->setChecked(bevelAndEmboss->antiAliased()); m_contour->ui.intRange->setValue(bevelAndEmboss->contourRange()); m_texture->ui.patternChooser->setCurrentPattern(bevelAndEmboss->texturePattern()); m_texture->ui.intScale->setValue(bevelAndEmboss->textureScale()); m_texture->ui.intDepth->setValue(bevelAndEmboss->textureDepth()); m_texture->ui.chkInvert->setChecked(bevelAndEmboss->textureInvert()); m_texture->ui.chkLinkWithLayer->setChecked(bevelAndEmboss->textureAlignWithLayer()); } void BevelAndEmboss::fetchBevelAndEmboss(psd_layer_effects_bevel_emboss *bevelAndEmboss) const { bevelAndEmboss->setStyle((psd_bevel_style)ui.cmbStyle->currentIndex()); bevelAndEmboss->setTechnique((psd_technique_type)ui.cmbTechnique->currentIndex()); bevelAndEmboss->setDepth(ui.intDepth->value()); bevelAndEmboss->setDirection((psd_direction)ui.cmbDirection->currentIndex()); bevelAndEmboss->setSize(ui.intSize->value()); bevelAndEmboss->setSoften(ui.intSoften->value()); bevelAndEmboss->setAngle(ui.dialAngle->value()); bevelAndEmboss->setUseGlobalLight(ui.chkUseGlobalLight->isChecked()); bevelAndEmboss->setAltitude(ui.intAltitude->value()); bevelAndEmboss->setGlossAntiAliased(ui.chkAntiAliased->isChecked()); bevelAndEmboss->setHighlightBlendMode(ui.cmbHighlightMode->selectedCompositeOp().id()); - bevelAndEmboss->setHighlightColor(ui.bnHighlightColor->color()); + bevelAndEmboss->setHighlightColor(ui.bnHighlightColor->color().toQColor()); bevelAndEmboss->setHighlightOpacity(ui.intOpacity->value()); bevelAndEmboss->setShadowBlendMode(ui.cmbShadowMode->selectedCompositeOp().id()); - bevelAndEmboss->setShadowColor(ui.bnShadowColor->color()); + bevelAndEmboss->setShadowColor(ui.bnShadowColor->color().toQColor()); bevelAndEmboss->setShadowOpacity(ui.intOpacity2->value()); // FIXME: curve editing bevelAndEmboss->setAntiAliased(m_contour->ui.chkAntiAliased->isChecked()); bevelAndEmboss->setContourRange(m_contour->ui.intRange->value()); bevelAndEmboss->setTexturePattern(static_cast(m_texture->ui.patternChooser->currentResource())); bevelAndEmboss->setTextureScale(m_texture->ui.intScale->value()); bevelAndEmboss->setTextureDepth(m_texture->ui.intDepth->value()); bevelAndEmboss->setTextureInvert(m_texture->ui.chkInvert->isChecked()); bevelAndEmboss->setTextureAlignWithLayer(m_texture->ui.chkLinkWithLayer->isChecked()); } void BevelAndEmboss::slotDialAngleChanged(int value) { KisSignalsBlocker b(ui.intAngle); ui.intAngle->setValue(value); if (ui.chkUseGlobalLight->isChecked()) { emit globalAngleChanged(value); } } void BevelAndEmboss::slotIntAngleChanged(int value) { KisSignalsBlocker b(ui.dialAngle); ui.dialAngle->setValue(value); if (ui.chkUseGlobalLight->isChecked()) { emit globalAngleChanged(value); } } void BevelAndEmboss::slotGlobalLightToggled() { if (ui.chkUseGlobalLight->isChecked()) { emit globalAngleChanged(ui.intAngle->value()); } } /********************************************************************/ /***** Texture *********************************************/ /********************************************************************/ Texture::Texture(QWidget *parent) : QWidget(parent) { ui.setupUi(this); } /********************************************************************/ /***** Contour *********************************************/ /********************************************************************/ Contour::Contour(QWidget *parent) : QWidget(parent) { ui.setupUi(this); } /********************************************************************/ /***** Blending Options *********************************************/ /********************************************************************/ BlendingOptions::BlendingOptions(QWidget *parent) : QWidget(parent) { ui.setupUi(this); // FIXME: Blend options are not implemented yet ui.grpBlendingOptions->setTitle(QString("%1 (%2)").arg(ui.grpBlendingOptions->title()).arg(i18n("Not Implemented Yet"))); ui.grpBlendingOptions->setEnabled(false); } /********************************************************************/ /***** Color Overlay *********************************************/ /********************************************************************/ ColorOverlay::ColorOverlay(QWidget *parent) : QWidget(parent) { ui.setupUi(this); ui.intOpacity->setRange(0, 100); ui.intOpacity->setSuffix(i18n(" %")); connect(ui.cmbCompositeOp, SIGNAL(currentIndexChanged(int)), SIGNAL(configChanged())); connect(ui.intOpacity, SIGNAL(valueChanged(int)), SIGNAL(configChanged())); - connect(ui.bnColor, SIGNAL(changed(QColor)), SIGNAL(configChanged())); + connect(ui.bnColor, SIGNAL(changed(KoColor)), SIGNAL(configChanged())); } void ColorOverlay::setColorOverlay(const psd_layer_effects_color_overlay *colorOverlay) { ui.cmbCompositeOp->selectCompositeOp(KoID(colorOverlay->blendMode())); ui.intOpacity->setValue(colorOverlay->opacity()); - ui.bnColor->setColor(colorOverlay->color()); + KoColor color(KoColorSpaceRegistry::instance()->rgb8()); + color.fromQColor(colorOverlay->color()); + ui.bnColor->setColor(color); } void ColorOverlay::fetchColorOverlay(psd_layer_effects_color_overlay *colorOverlay) const { colorOverlay->setBlendMode(ui.cmbCompositeOp->selectedCompositeOp().id()); colorOverlay->setOpacity(ui.intOpacity->value()); - colorOverlay->setColor(ui.bnColor->color()); + colorOverlay->setColor(ui.bnColor->color().toQColor()); } /********************************************************************/ /***** Drop Shadow **************************************************/ /********************************************************************/ DropShadow::DropShadow(Mode mode, QWidget *parent) : QWidget(parent), m_mode(mode) { ui.setupUi(this); ui.intOpacity->setRange(0, 100); ui.intOpacity->setSuffix(i18n(" %")); ui.intDistance->setRange(0, 500); ui.intDistance->setSuffix(i18n(" px")); ui.intDistance->setExponentRatio(3.0); ui.intSpread->setRange(0, 100); ui.intSpread->setSuffix(i18n(" %")); ui.intSize->setRange(0, 250); ui.intSize->setSuffix(i18n(" px")); ui.intNoise->setRange(0, 100); ui.intNoise->setSuffix(i18n(" %")); connect(ui.dialAngle, SIGNAL(valueChanged(int)), SLOT(slotDialAngleChanged(int))); connect(ui.intAngle, SIGNAL(valueChanged(int)), SLOT(slotIntAngleChanged(int))); connect(ui.chkUseGlobalLight, SIGNAL(toggled(bool)), SLOT(slotGlobalLightToggled())); // connect everything to configChanged() signal connect(ui.cmbCompositeOp, SIGNAL(currentIndexChanged(int)), SIGNAL(configChanged())); connect(ui.intOpacity, SIGNAL(valueChanged(int)), SIGNAL(configChanged())); - connect(ui.bnColor, SIGNAL(changed(QColor)), SIGNAL(configChanged())); + connect(ui.bnColor, SIGNAL(changed(KoColor)), SIGNAL(configChanged())); connect(ui.dialAngle, SIGNAL(valueChanged(int)), SIGNAL(configChanged())); connect(ui.intAngle, SIGNAL(valueChanged(int)), SIGNAL(configChanged())); connect(ui.chkUseGlobalLight, SIGNAL(toggled(bool)), SIGNAL(configChanged())); connect(ui.intDistance, SIGNAL(valueChanged(int)), SIGNAL(configChanged())); connect(ui.intSpread, SIGNAL(valueChanged(int)), SIGNAL(configChanged())); connect(ui.intSize, SIGNAL(valueChanged(int)), SIGNAL(configChanged())); connect(ui.cmbContour, SIGNAL(currentIndexChanged(int)), SIGNAL(configChanged())); connect(ui.chkAntiAliased, SIGNAL(toggled(bool)), SIGNAL(configChanged())); connect(ui.intNoise, SIGNAL(valueChanged(int)), SIGNAL(configChanged())); connect(ui.chkLayerKnocksOutDropShadow, SIGNAL(toggled(bool)), SIGNAL(configChanged())); if (m_mode == InnerShadowMode) { ui.chkLayerKnocksOutDropShadow->setVisible(false); ui.grpMain->setTitle(i18n("Inner Shadow")); ui.lblSpread->setText(i18n("Choke:")); } } void DropShadow::slotDialAngleChanged(int value) { KisSignalsBlocker b(ui.intAngle); ui.intAngle->setValue(value); if (ui.chkUseGlobalLight->isChecked()) { emit globalAngleChanged(value); } } void DropShadow::slotIntAngleChanged(int value) { KisSignalsBlocker b(ui.dialAngle); ui.dialAngle->setValue(value); if (ui.chkUseGlobalLight->isChecked()) { emit globalAngleChanged(value); } } void DropShadow::slotGlobalLightToggled() { if (ui.chkUseGlobalLight->isChecked()) { emit globalAngleChanged(ui.intAngle->value()); } } void DropShadow::setShadow(const psd_layer_effects_shadow_common *shadow) { ui.cmbCompositeOp->selectCompositeOp(KoID(shadow->blendMode())); ui.intOpacity->setValue(shadow->opacity()); - ui.bnColor->setColor(shadow->color()); + KoColor color(KoColorSpaceRegistry::instance()->rgb8()); + color.fromQColor(shadow->color()); + ui.bnColor->setColor(color); ui.dialAngle->setValue(shadow->angle()); ui.intAngle->setValue(shadow->angle()); ui.chkUseGlobalLight->setChecked(shadow->useGlobalLight()); ui.intDistance->setValue(shadow->distance()); ui.intSpread->setValue(shadow->spread()); ui.intSize->setValue(shadow->size()); // FIXME: curve editing // ui.cmbContour; ui.chkAntiAliased->setChecked(shadow->antiAliased()); ui.intNoise->setValue(shadow->noise()); if (m_mode == DropShadowMode) { const psd_layer_effects_drop_shadow *realDropShadow = dynamic_cast(shadow); KIS_ASSERT_RECOVER_NOOP(realDropShadow); ui.chkLayerKnocksOutDropShadow->setChecked(shadow->knocksOut()); } } void DropShadow::fetchShadow(psd_layer_effects_shadow_common *shadow) const { shadow->setBlendMode(ui.cmbCompositeOp->selectedCompositeOp().id()); shadow->setOpacity(ui.intOpacity->value()); - shadow->setColor(ui.bnColor->color()); + shadow->setColor(ui.bnColor->color().toQColor()); shadow->setAngle(ui.dialAngle->value()); shadow->setUseGlobalLight(ui.chkUseGlobalLight->isChecked()); shadow->setDistance(ui.intDistance->value()); shadow->setSpread(ui.intSpread->value()); shadow->setSize(ui.intSize->value()); // FIXME: curve editing // ui.cmbContour; shadow->setAntiAliased(ui.chkAntiAliased->isChecked()); shadow->setNoise(ui.intNoise->value()); if (m_mode == DropShadowMode) { psd_layer_effects_drop_shadow *realDropShadow = dynamic_cast(shadow); KIS_ASSERT_RECOVER_NOOP(realDropShadow); realDropShadow->setKnocksOut(ui.chkLayerKnocksOutDropShadow->isChecked()); } } class GradientPointerConverter { public: static KoAbstractGradientSP resourceToStyle(KoAbstractGradient *gradient) { return gradient ? KoAbstractGradientSP(gradient->clone()) : KoAbstractGradientSP(); } static KoAbstractGradient* styleToResource(KoAbstractGradientSP gradient) { if (!gradient) return 0; KoResourceServer *server = KoResourceServerProvider::instance()->gradientServer(); KoAbstractGradient *resource = server->resourceByMD5(gradient->md5()); if (!resource) { KoAbstractGradient *clone = gradient->clone(); clone->setName(findAvailableName(gradient->name())); server->addResource(clone, false); resource = clone; } return resource; } private: static QString findAvailableName(const QString &name) { KoResourceServer *server = KoResourceServerProvider::instance()->gradientServer(); QString newName = name; int i = 0; while (server->resourceByName(newName)) { newName = QString("%1%2").arg(name).arg(i++); } return newName; } }; /********************************************************************/ /***** Gradient Overlay *********************************************/ /********************************************************************/ GradientOverlay::GradientOverlay(KisCanvasResourceProvider *resourceProvider, QWidget *parent) : QWidget(parent), m_resourceProvider(resourceProvider) { ui.setupUi(this); ui.intOpacity->setRange(0, 100); ui.intOpacity->setSuffix(i18n(" %")); ui.intScale->setRange(0, 100); ui.intScale->setSuffix(i18n(" %")); connect(ui.dialAngle, SIGNAL(valueChanged(int)), SLOT(slotDialAngleChanged(int))); connect(ui.intAngle, SIGNAL(valueChanged(int)), SLOT(slotIntAngleChanged(int))); connect(ui.cmbCompositeOp, SIGNAL(currentIndexChanged(int)), SIGNAL(configChanged())); connect(ui.intOpacity, SIGNAL(valueChanged(int)), SIGNAL(configChanged())); connect(ui.cmbGradient, SIGNAL(gradientChanged(KoAbstractGradient*)), SIGNAL(configChanged())); connect(ui.chkReverse, SIGNAL(toggled(bool)), SIGNAL(configChanged())); connect(ui.cmbStyle, SIGNAL(currentIndexChanged(int)), SIGNAL(configChanged())); connect(ui.chkAlignWithLayer, SIGNAL(toggled(bool)), SIGNAL(configChanged())); connect(ui.dialAngle, SIGNAL(valueChanged(int)), SIGNAL(configChanged())); connect(ui.intAngle, SIGNAL(valueChanged(int)), SIGNAL(configChanged())); connect(ui.intScale, SIGNAL(valueChanged(int)), SIGNAL(configChanged())); } void GradientOverlay::setGradientOverlay(const psd_layer_effects_gradient_overlay *config) { ui.cmbCompositeOp->selectCompositeOp(KoID(config->blendMode())); ui.intOpacity->setValue(config->opacity()); KoAbstractGradient *gradient = fetchGradientLazy( GradientPointerConverter::styleToResource(config->gradient()), m_resourceProvider); if (gradient) { ui.cmbGradient->setGradient(gradient); } ui.chkReverse->setChecked(config->antiAliased()); ui.cmbStyle->setCurrentIndex((int)config->style()); ui.chkAlignWithLayer->setCheckable(config->alignWithLayer()); ui.dialAngle->setValue(config->angle()); ui.intAngle->setValue(config->angle()); ui.intScale->setValue(config->scale()); } void GradientOverlay::fetchGradientOverlay(psd_layer_effects_gradient_overlay *config) const { config->setBlendMode(ui.cmbCompositeOp->selectedCompositeOp().id()); config->setOpacity(ui.intOpacity->value()); config->setGradient(GradientPointerConverter::resourceToStyle(ui.cmbGradient->gradient())); config->setReverse(ui.chkReverse->isChecked()); config->setStyle((psd_gradient_style)ui.cmbStyle->currentIndex()); config->setAlignWithLayer(ui.chkAlignWithLayer->isChecked()); config->setAngle(ui.dialAngle->value()); config->setScale(ui.intScale->value()); } void GradientOverlay::slotDialAngleChanged(int value) { KisSignalsBlocker b(ui.intAngle); ui.intAngle->setValue(value); } void GradientOverlay::slotIntAngleChanged(int value) { KisSignalsBlocker b(ui.dialAngle); ui.dialAngle->setValue(value); } /********************************************************************/ /***** Innner Glow *********************************************/ /********************************************************************/ InnerGlow::InnerGlow(Mode mode, KisCanvasResourceProvider *resourceProvider, QWidget *parent) : QWidget(parent), m_mode(mode), m_resourceProvider(resourceProvider) { ui.setupUi(this); ui.intOpacity->setRange(0, 100); ui.intOpacity->setSuffix(i18n(" %")); ui.intNoise->setRange(0, 100); ui.intNoise->setSuffix(i18n(" %")); ui.intChoke->setRange(0, 100); ui.intChoke->setSuffix(i18n(" %")); ui.intSize->setRange(0, 250); ui.intSize->setSuffix(i18n(" px")); ui.intRange->setRange(1, 100); ui.intRange->setSuffix(i18n(" %")); ui.intJitter->setRange(0, 100); ui.intJitter->setSuffix(i18n(" %")); connect(ui.cmbCompositeOp, SIGNAL(currentIndexChanged(int)), SIGNAL(configChanged())); connect(ui.intOpacity, SIGNAL(valueChanged(int)), SIGNAL(configChanged())); connect(ui.intNoise, SIGNAL(valueChanged(int)), SIGNAL(configChanged())); connect(ui.radioColor, SIGNAL(toggled(bool)), SIGNAL(configChanged())); - connect(ui.bnColor, SIGNAL(changed(QColor)), SIGNAL(configChanged())); + connect(ui.bnColor, SIGNAL(changed(KoColor)), SIGNAL(configChanged())); connect(ui.radioGradient, SIGNAL(toggled(bool)), SIGNAL(configChanged())); connect(ui.cmbGradient, SIGNAL(gradientChanged(KoAbstractGradient*)), SIGNAL(configChanged())); connect(ui.cmbTechnique, SIGNAL(currentIndexChanged(int)), SIGNAL(configChanged())); connect(ui.cmbSource, SIGNAL(currentIndexChanged(int)), SIGNAL(configChanged())); connect(ui.intChoke, SIGNAL(valueChanged(int)), SIGNAL(configChanged())); connect(ui.intSize, SIGNAL(valueChanged(int)), SIGNAL(configChanged())); connect(ui.cmbContour, SIGNAL(currentIndexChanged(int)), SIGNAL(configChanged())); connect(ui.chkAntiAliased, SIGNAL(toggled(bool)), SIGNAL(configChanged())); connect(ui.intRange, SIGNAL(valueChanged(int)), SIGNAL(configChanged())); connect(ui.intJitter, SIGNAL(valueChanged(int)), SIGNAL(configChanged())); if (m_mode == OuterGlowMode) { ui.cmbSource->hide(); ui.lblSource->hide(); ui.lblChoke->setText(i18nc("layer styles parameter", "Spread:")); } } void InnerGlow::setConfig(const psd_layer_effects_glow_common *config) { ui.cmbCompositeOp->selectCompositeOp(KoID(config->blendMode())); ui.intOpacity->setValue(config->opacity()); ui.intNoise->setValue(config->noise()); ui.radioColor->setChecked(config->fillType() == psd_fill_solid_color); - ui.bnColor->setColor(config->color()); + KoColor color(KoColorSpaceRegistry::instance()->rgb8()); + color.fromQColor(config->color()); + ui.bnColor->setColor(color); ui.radioGradient->setChecked(config->fillType() == psd_fill_gradient); KoAbstractGradient *gradient = fetchGradientLazy( GradientPointerConverter::styleToResource(config->gradient()), m_resourceProvider); if (gradient) { ui.cmbGradient->setGradient(gradient); } ui.cmbTechnique->setCurrentIndex((int)config->technique()); ui.intChoke->setValue(config->spread()); ui.intSize->setValue(config->size()); if (m_mode == InnerGlowMode) { const psd_layer_effects_inner_glow *iglow = dynamic_cast(config); KIS_ASSERT_RECOVER_RETURN(iglow); ui.cmbSource->setCurrentIndex(iglow->source() == psd_glow_edge); } // FIXME: Curve editing //ui.cmbContour; ui.chkAntiAliased->setChecked(config->antiAliased()); ui.intRange->setValue(config->range()); ui.intJitter->setValue(config->jitter()); } void InnerGlow::fetchConfig(psd_layer_effects_glow_common *config) const { config->setBlendMode(ui.cmbCompositeOp->selectedCompositeOp().id()); config->setOpacity(ui.intOpacity->value()); config->setNoise(ui.intNoise->value()); if (ui.radioColor->isChecked()) { config->setFillType(psd_fill_solid_color); } else { config->setFillType(psd_fill_gradient); } - config->setColor(ui.bnColor->color()); + config->setColor(ui.bnColor->color().toQColor()); config->setGradient(GradientPointerConverter::resourceToStyle(ui.cmbGradient->gradient())); config->setTechnique((psd_technique_type)ui.cmbTechnique->currentIndex()); config->setSpread(ui.intChoke->value()); config->setSize(ui.intSize->value()); if (m_mode == InnerGlowMode) { psd_layer_effects_inner_glow *iglow = dynamic_cast(config); KIS_ASSERT_RECOVER_RETURN(iglow); iglow->setSource((psd_glow_source)ui.cmbSource->currentIndex()); } // FIXME: Curve editing //ui.cmbContour; config->setAntiAliased(ui.chkAntiAliased->isChecked()); config->setRange(ui.intRange->value()); config->setJitter(ui.intJitter->value()); } /********************************************************************/ /***** Pattern Overlay *********************************************/ /********************************************************************/ PatternOverlay::PatternOverlay(QWidget *parent) : QWidget(parent) { ui.setupUi(this); ui.intOpacity->setRange(0, 100); ui.intOpacity->setSuffix(i18n(" %")); ui.intScale->setRange(0, 100); ui.intScale->setSuffix(i18n(" %")); connect(ui.cmbCompositeOp, SIGNAL(currentIndexChanged(int)), SIGNAL(configChanged())); connect(ui.intOpacity, SIGNAL(valueChanged(int)), SIGNAL(configChanged())); connect(ui.patternChooser, SIGNAL(resourceSelected(KoResource*)), SIGNAL(configChanged())); connect(ui.chkLinkWithLayer, SIGNAL(toggled(bool)), SIGNAL(configChanged())); connect(ui.intScale, SIGNAL(valueChanged(int)), SIGNAL(configChanged())); } void PatternOverlay::setPatternOverlay(const psd_layer_effects_pattern_overlay *pattern) { ui.cmbCompositeOp->selectCompositeOp(KoID(pattern->blendMode())); ui.intOpacity->setValue(pattern->opacity()); ui.patternChooser->setCurrentPattern(pattern->pattern()); ui.chkLinkWithLayer->setChecked(pattern->alignWithLayer()); ui.intScale->setValue(pattern->scale()); } void PatternOverlay::fetchPatternOverlay(psd_layer_effects_pattern_overlay *pattern) const { pattern->setBlendMode(ui.cmbCompositeOp->selectedCompositeOp().id()); pattern->setOpacity(ui.intOpacity->value()); pattern->setPattern(static_cast(ui.patternChooser->currentResource())); pattern->setAlignWithLayer(ui.chkLinkWithLayer->isChecked()); pattern->setScale(ui.intScale->value()); } /********************************************************************/ /***** Satin *********************************************/ /********************************************************************/ Satin::Satin(QWidget *parent) : QWidget(parent) { ui.setupUi(this); ui.intOpacity->setRange(0, 100); ui.intOpacity->setSuffix(i18n(" %")); ui.intDistance->setRange(0, 250); ui.intDistance->setSuffix(i18n(" px")); ui.intSize->setRange(0, 250); ui.intSize->setSuffix(i18n(" px")); connect(ui.dialAngle, SIGNAL(valueChanged(int)), SLOT(slotDialAngleChanged(int))); connect(ui.intAngle, SIGNAL(valueChanged(int)), SLOT(slotIntAngleChanged(int))); connect(ui.cmbCompositeOp, SIGNAL(currentIndexChanged(int)), SIGNAL(configChanged())); - connect(ui.bnColor, SIGNAL(changed(QColor)), SIGNAL(configChanged())); + connect(ui.bnColor, SIGNAL(changed(KoColor)), SIGNAL(configChanged())); connect(ui.intOpacity, SIGNAL(valueChanged(int)), SIGNAL(configChanged())); connect(ui.dialAngle, SIGNAL(valueChanged(int)), SIGNAL(configChanged())); connect(ui.intAngle, SIGNAL(valueChanged(int)), SIGNAL(configChanged())); connect(ui.intDistance, SIGNAL(valueChanged(int)), SIGNAL(configChanged())); connect(ui.intSize, SIGNAL(valueChanged(int)), SIGNAL(configChanged())); connect(ui.cmbContour, SIGNAL(currentIndexChanged(int)), SIGNAL(configChanged())); connect(ui.chkAntiAliased, SIGNAL(toggled(bool)), SIGNAL(configChanged())); connect(ui.chkInvert, SIGNAL(toggled(bool)), SIGNAL(configChanged())); } void Satin::slotDialAngleChanged(int value) { KisSignalsBlocker b(ui.intAngle); ui.intAngle->setValue(value); } void Satin::slotIntAngleChanged(int value) { KisSignalsBlocker b(ui.dialAngle); ui.dialAngle->setValue(value); } void Satin::setSatin(const psd_layer_effects_satin *satin) { ui.cmbCompositeOp->selectCompositeOp(KoID(satin->blendMode())); - ui.bnColor->setColor(satin->color()); + KoColor color(KoColorSpaceRegistry::instance()->rgb8()); + color.fromQColor(satin->color()); + ui.bnColor->setColor(color); ui.intOpacity->setValue(satin->opacity()); ui.dialAngle->setValue(satin->angle()); ui.intAngle->setValue(satin->angle()); ui.intDistance->setValue(satin->distance()); ui.intSize->setValue(satin->size()); // FIXME: Curve editing //ui.cmbContour; ui.chkAntiAliased->setChecked(satin->antiAliased()); ui.chkInvert->setChecked(satin->invert()); } void Satin::fetchSatin(psd_layer_effects_satin *satin) const { satin->setBlendMode(ui.cmbCompositeOp->selectedCompositeOp().id()); satin->setOpacity(ui.intOpacity->value()); - satin->setColor(ui.bnColor->color()); + satin->setColor(ui.bnColor->color().toQColor()); satin->setAngle(ui.dialAngle->value()); satin->setDistance(ui.intDistance->value()); satin->setSize(ui.intSize->value()); // FIXME: curve editing // ui.cmbContour; satin->setAntiAliased(ui.chkAntiAliased->isChecked()); satin->setInvert(ui.chkInvert->isChecked()); } /********************************************************************/ /***** Stroke *********************************************/ /********************************************************************/ Stroke::Stroke(KisCanvasResourceProvider *resourceProvider, QWidget *parent) : QWidget(parent), m_resourceProvider(resourceProvider) { ui.setupUi(this); ui.intSize->setRange(0, 250); ui.intSize->setSuffix(i18n(" px")); ui.intOpacity->setRange(0, 100); ui.intOpacity->setSuffix(i18n(" %")); ui.intScale->setRange(0, 100); ui.intScale->setSuffix(i18n(" %")); ui.intScale_2->setRange(0, 100); ui.intScale_2->setSuffix(i18n(" %")); connect(ui.cmbFillType, SIGNAL(currentIndexChanged(int)), ui.fillStack, SLOT(setCurrentIndex(int))); connect(ui.intSize, SIGNAL(valueChanged(int)), SIGNAL(configChanged())); connect(ui.cmbPosition, SIGNAL(currentIndexChanged(int)), SIGNAL(configChanged())); connect(ui.cmbCompositeOp, SIGNAL(currentIndexChanged(int)), SIGNAL(configChanged())); connect(ui.intOpacity, SIGNAL(valueChanged(int)), SIGNAL(configChanged())); connect(ui.cmbFillType, SIGNAL(currentIndexChanged(int)), SIGNAL(configChanged())); - connect(ui.bnColor, SIGNAL(changed(QColor)), SIGNAL(configChanged())); + connect(ui.bnColor, SIGNAL(changed(KoColor)), SIGNAL(configChanged())); connect(ui.cmbGradient, SIGNAL(gradientChanged(KoAbstractGradient*)), SIGNAL(configChanged())); connect(ui.chkReverse, SIGNAL(toggled(bool)), SIGNAL(configChanged())); connect(ui.cmbStyle, SIGNAL(currentIndexChanged(int)), SIGNAL(configChanged())); connect(ui.chkAlignWithLayer, SIGNAL(toggled(bool)), SIGNAL(configChanged())); connect(ui.dialAngle, SIGNAL(valueChanged(int)), SLOT(slotDialAngleChanged(int))); connect(ui.intAngle, SIGNAL(valueChanged(int)), SLOT(slotIntAngleChanged(int))); connect(ui.intScale, SIGNAL(valueChanged(int)), SIGNAL(configChanged())); connect(ui.patternChooser, SIGNAL(resourceSelected(KoResource*)), SIGNAL(configChanged())); connect(ui.chkLinkWithLayer, SIGNAL(toggled(bool)), SIGNAL(configChanged())); connect(ui.intScale_2, SIGNAL(valueChanged(int)), SIGNAL(configChanged())); // cold initialization ui.fillStack->setCurrentIndex(ui.cmbFillType->currentIndex()); } void Stroke::slotDialAngleChanged(int value) { KisSignalsBlocker b(ui.intAngle); ui.intAngle->setValue(value); } void Stroke::slotIntAngleChanged(int value) { KisSignalsBlocker b(ui.dialAngle); ui.dialAngle->setValue(value); } void Stroke::setStroke(const psd_layer_effects_stroke *stroke) { ui.intSize->setValue(stroke->size()); ui.cmbPosition->setCurrentIndex((int)stroke->position()); ui.cmbCompositeOp->selectCompositeOp(KoID(stroke->blendMode())); ui.intOpacity->setValue(stroke->opacity()); ui.cmbFillType->setCurrentIndex((int)stroke->fillType()); - - ui.bnColor->setColor(stroke->color()); + KoColor color(KoColorSpaceRegistry::instance()->rgb8()); + color.fromQColor(stroke->color()); + ui.bnColor->setColor(color); KoAbstractGradient *gradient = fetchGradientLazy(GradientPointerConverter::styleToResource(stroke->gradient()), m_resourceProvider); if (gradient) { ui.cmbGradient->setGradient(gradient); } ui.chkReverse->setChecked(stroke->antiAliased()); ui.cmbStyle->setCurrentIndex((int)stroke->style()); ui.chkAlignWithLayer->setCheckable(stroke->alignWithLayer()); ui.dialAngle->setValue(stroke->angle()); ui.intAngle->setValue(stroke->angle()); ui.intScale->setValue(stroke->scale()); ui.patternChooser->setCurrentPattern(stroke->pattern()); ui.chkLinkWithLayer->setChecked(stroke->alignWithLayer()); ui.intScale_2->setValue(stroke->scale()); } void Stroke::fetchStroke(psd_layer_effects_stroke *stroke) const { stroke->setSize(ui.intSize->value()); stroke->setPosition((psd_stroke_position)ui.cmbPosition->currentIndex()); stroke->setBlendMode(ui.cmbCompositeOp->selectedCompositeOp().id()); stroke->setOpacity(ui.intOpacity->value()); stroke->setFillType((psd_fill_type)ui.cmbFillType->currentIndex()); - stroke->setColor(ui.bnColor->color()); + stroke->setColor(ui.bnColor->color().toQColor()); stroke->setGradient(GradientPointerConverter::resourceToStyle(ui.cmbGradient->gradient())); stroke->setReverse(ui.chkReverse->isChecked()); stroke->setStyle((psd_gradient_style)ui.cmbStyle->currentIndex()); stroke->setAlignWithLayer(ui.chkAlignWithLayer->isChecked()); stroke->setAngle(ui.dialAngle->value()); stroke->setScale(ui.intScale->value()); stroke->setPattern(static_cast(ui.patternChooser->currentResource())); stroke->setAlignWithLayer(ui.chkLinkWithLayer->isChecked()); stroke->setScale(ui.intScale->value()); } diff --git a/libs/ui/dialogs/kis_dlg_preferences.cc b/libs/ui/dialogs/kis_dlg_preferences.cc index 8c1ceabd67..f97411e5ce 100644 --- a/libs/ui/dialogs/kis_dlg_preferences.cc +++ b/libs/ui/dialogs/kis_dlg_preferences.cc @@ -1,1036 +1,1053 @@ /* * preferencesdlg.cc - part of KImageShop * * Copyright (c) 1999 Michael Koch * Copyright (c) 2003-2011 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_dlg_preferences.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "KoID.h" #include #include #include #include #include #include "kis_action_registry.h" #include "widgets/squeezedcombobox.h" #include "kis_clipboard.h" #include "widgets/kis_cmb_idlist.h" #include "KoColorSpace.h" #include "KoColorSpaceRegistry.h" #include "KoColorConversionTransformation.h" #include "kis_cursor.h" #include "kis_config.h" #include "kis_canvas_resource_provider.h" #include "kis_preference_set_registry.h" #include "kis_color_manager.h" #include "KisProofingConfiguration.h" #include "kis_image_config.h" #include "slider_and_spin_box_sync.h" // for the performance update #include #include "input/config/kis_input_configuration_page.h" GeneralTab::GeneralTab(QWidget *_parent, const char *_name) : WdgGeneralSettings(_parent, _name) { KisConfig cfg; m_cmbCursorShape->addItem(i18n("No Cursor")); m_cmbCursorShape->addItem(i18n("Tool Icon")); m_cmbCursorShape->addItem(i18n("Arrow")); m_cmbCursorShape->addItem(i18n("Small Circle")); m_cmbCursorShape->addItem(i18n("Crosshair")); m_cmbCursorShape->addItem(i18n("Triangle Righthanded")); m_cmbCursorShape->addItem(i18n("Triangle Lefthanded")); m_cmbCursorShape->addItem(i18n("Black Pixel")); m_cmbCursorShape->addItem(i18n("White Pixel")); m_cmbOutlineShape->addItem(i18n("No Outline")); m_cmbOutlineShape->addItem(i18n("Circle Outline")); m_cmbOutlineShape->addItem(i18n("Preview Outline")); m_cmbOutlineShape->addItem(i18n("Tilt Outline")); m_cmbCursorShape->setCurrentIndex(cfg.newCursorStyle()); m_cmbOutlineShape->setCurrentIndex(cfg.newOutlineStyle()); chkShowRootLayer->setChecked(cfg.showRootLayer()); int autosaveInterval = cfg.autoSaveInterval(); //convert to minutes m_autosaveSpinBox->setValue(autosaveInterval / 60); m_autosaveCheckBox->setChecked(autosaveInterval > 0); m_undoStackSize->setValue(cfg.undoStackLimit()); m_backupFileCheckBox->setChecked(cfg.backupFile()); m_showOutlinePainting->setChecked(cfg.showOutlineWhilePainting()); m_hideSplashScreen->setChecked(cfg.hideSplashScreen()); m_cmbMDIType->setCurrentIndex(cfg.readEntry("mdi_viewmode", (int)QMdiArea::TabbedView)); m_chkRubberBand->setChecked(cfg.readEntry("mdi_rubberband", cfg.useOpenGL())); m_favoritePresetsSpinBox->setValue(cfg.favoritePresets()); - m_mdiColor->setColor(cfg.getMDIBackgroundColor()); + KoColor mdiColor; + mdiColor.fromQColor(cfg.getMDIBackgroundColor()); + m_mdiColor->setColor(mdiColor); m_backgroundimage->setText(cfg.getMDIBackgroundImage()); m_chkCanvasMessages->setChecked(cfg.showCanvasMessages()); m_chkCompressKra->setChecked(cfg.compressKra()); m_radioToolOptionsInDocker->setChecked(cfg.toolOptionsInDocker()); m_chkSwitchSelectionCtrlAlt->setChecked(cfg.switchSelectionCtrlAlt()); m_chkConvertOnImport->setChecked(cfg.convertToImageColorspaceOnImport()); connect(m_bnFileName, SIGNAL(clicked()), SLOT(getBackgroundImage())); connect(clearBgImageButton, SIGNAL(clicked()), SLOT(clearBackgroundImage())); } void GeneralTab::setDefault() { KisConfig cfg; m_cmbCursorShape->setCurrentIndex(cfg.newCursorStyle(true)); m_cmbOutlineShape->setCurrentIndex(cfg.newOutlineStyle(true)); chkShowRootLayer->setChecked(cfg.showRootLayer(true)); m_autosaveCheckBox->setChecked(cfg.autoSaveInterval(true) > 0); //convert to minutes m_autosaveSpinBox->setValue(cfg.autoSaveInterval(true) / 60); m_undoStackSize->setValue(cfg.undoStackLimit(true)); m_backupFileCheckBox->setChecked(cfg.backupFile(true)); m_showOutlinePainting->setChecked(cfg.showOutlineWhilePainting(true)); m_hideSplashScreen->setChecked(cfg.hideSplashScreen(true)); m_cmbMDIType->setCurrentIndex((int)QMdiArea::TabbedView); m_chkRubberBand->setChecked(cfg.useOpenGL(true)); m_favoritePresetsSpinBox->setValue(cfg.favoritePresets(true)); - m_mdiColor->setColor(cfg.getMDIBackgroundColor(true)); + KoColor mdiColor; + mdiColor.fromQColor(cfg.getMDIBackgroundColor(true)); + m_mdiColor->setColor(mdiColor); m_backgroundimage->setText(cfg.getMDIBackgroundImage(true)); m_chkCanvasMessages->setChecked(cfg.showCanvasMessages(true)); m_chkCompressKra->setChecked(cfg.compressKra(true)); m_radioToolOptionsInDocker->setChecked(cfg.toolOptionsInDocker(true)); m_chkSwitchSelectionCtrlAlt->setChecked(cfg.switchSelectionCtrlAlt(true)); m_chkConvertOnImport->setChecked(cfg.convertToImageColorspaceOnImport(true)); } CursorStyle GeneralTab::cursorStyle() { return (CursorStyle)m_cmbCursorShape->currentIndex(); } OutlineStyle GeneralTab::outlineStyle() { return (OutlineStyle)m_cmbOutlineShape->currentIndex(); } bool GeneralTab::showRootLayer() { return chkShowRootLayer->isChecked(); } int GeneralTab::autoSaveInterval() { //convert to seconds return m_autosaveCheckBox->isChecked() ? m_autosaveSpinBox->value()*60 : 0; } int GeneralTab::undoStackSize() { return m_undoStackSize->value(); } bool GeneralTab::showOutlineWhilePainting() { return m_showOutlinePainting->isChecked(); } bool GeneralTab::hideSplashScreen() { return m_hideSplashScreen->isChecked(); } int GeneralTab::mdiMode() { return m_cmbMDIType->currentIndex(); } int GeneralTab::favoritePresets() { return m_favoritePresetsSpinBox->value(); } bool GeneralTab::showCanvasMessages() { return m_chkCanvasMessages->isChecked(); } bool GeneralTab::compressKra() { return m_chkCompressKra->isChecked(); } bool GeneralTab::toolOptionsInDocker() { return m_radioToolOptionsInDocker->isChecked(); } bool GeneralTab::switchSelectionCtrlAlt() { return m_chkSwitchSelectionCtrlAlt->isChecked(); } bool GeneralTab::convertToImageColorspaceOnImport() { return m_chkConvertOnImport->isChecked(); } void GeneralTab::getBackgroundImage() { KoFileDialog dialog(this, KoFileDialog::OpenFile, "BackgroundImages"); dialog.setCaption(i18n("Select a Background Image")); dialog.setDefaultDir(QDesktopServices::storageLocation(QDesktopServices::PicturesLocation)); dialog.setImageFilters(); QString fn = dialog.filename(); // dialog box was canceled or somehow no file was selected if (fn.isEmpty()) { return; } QImage image(fn); if (image.isNull()) { QMessageBox::warning(this, i18nc("@title:window", "Krita"), i18n("%1 is not a valid image file!", fn)); } else { m_backgroundimage->setText(fn); } } void GeneralTab::clearBackgroundImage() { // clearing the background image text will implicitly make the background color be used m_backgroundimage->setText(""); } ShortcutSettingsTab::ShortcutSettingsTab(QWidget *parent, const char *name) : QWidget(parent) { setObjectName(name); QGridLayout * l = new QGridLayout(this); l->setMargin(0); m_page = new WdgShortcutSettings(this); l->addWidget(m_page, 0, 0); KisPart::instance()->loadActions(); KisActionRegistry::instance()->setupDialog(m_page); } void ShortcutSettingsTab::setDefault() { m_page->allDefault(); } void ShortcutSettingsTab::saveChanges() { m_page->save(); KisActionRegistry::instance()->settingsPageSaved(); } void ShortcutSettingsTab::revertChanges() { m_page->allDefault(); } ColorSettingsTab::ColorSettingsTab(QWidget *parent, const char *name) : QWidget(parent) { setObjectName(name); // XXX: Make sure only profiles that fit the specified color model // are shown in the profile combos QGridLayout * l = new QGridLayout(this); l->setMargin(0); m_page = new WdgColorSettings(this); l->addWidget(m_page, 0, 0); KisConfig cfg; m_page->chkUseSystemMonitorProfile->setChecked(cfg.useSystemMonitorProfile()); connect(m_page->chkUseSystemMonitorProfile, SIGNAL(toggled(bool)), this, SLOT(toggleAllowMonitorProfileSelection(bool))); if (KisColorManager::instance()->devices().size() > 0) { m_page->chkUseSystemMonitorProfile->setVisible(false); } m_page->cmbWorkingColorSpace->setIDList(KoColorSpaceRegistry::instance()->listKeys()); m_page->cmbWorkingColorSpace->setCurrent(cfg.workingColorSpace()); m_page->bnAddColorProfile->setIcon(KisIconUtils::loadIcon("document-open")); m_page->bnAddColorProfile->setToolTip( i18n("Open Color Profile") ); connect(m_page->bnAddColorProfile, SIGNAL(clicked()), SLOT(installProfile())); QGridLayout *monitorProfileGrid = new QGridLayout(m_page->monitorprofileholder); for(int i = 0; i < QApplication::desktop()->screenCount(); ++i) { QLabel *lbl = new QLabel(i18nc("The number of the screen", "Screen %1:", i + 1)); monitorProfileGrid->addWidget(lbl, i, 0); m_monitorProfileLabels << lbl; SqueezedComboBox *cmb = new SqueezedComboBox(); monitorProfileGrid->addWidget(cmb, i, 1); m_monitorProfileWidgets << cmb; } refillMonitorProfiles(KoID("RGBA", "")); for(int i = 0; i < QApplication::desktop()->screenCount(); ++i) { if (m_monitorProfileWidgets[i]->contains(cfg.monitorProfile(i))) { m_monitorProfileWidgets[i]->setCurrent(cfg.monitorProfile(i)); } } m_page->chkBlackpoint->setChecked(cfg.useBlackPointCompensation()); m_page->chkAllowLCMSOptimization->setChecked(cfg.allowLCMSOptimization()); KisImageConfig cfgImage; KisProofingConfigurationSP proofingConfig = cfgImage.defaultProofingconfiguration(); - m_gamutWarning = new KoColorPopupAction(this); - m_gamutWarning->setToolTip(i18n("Set default color used for out of Gamut Warning")); - m_gamutWarning->setCurrentColor(proofingConfig->warningColor); - m_page->gamutAlarm->setDefaultAction(m_gamutWarning); m_page->sldAdaptationState->setMaximum(20); m_page->sldAdaptationState->setMinimum(0); m_page->sldAdaptationState->setValue((int)proofingConfig->adaptationState*20); const KoColorSpace *proofingSpace = KoColorSpaceRegistry::instance()->colorSpace(proofingConfig->proofingModel,proofingConfig->proofingDepth,proofingConfig->proofingProfile); m_page->proofingSpaceSelector->setCurrentColorSpace(proofingSpace); m_page->cmbProofingIntent->setCurrentIndex((int)proofingConfig->intent); m_page->ckbProofBlackPoint->setChecked(proofingConfig->conversionFlags.testFlag(KoColorConversionTransformation::BlackpointCompensation)); m_pasteBehaviourGroup.addButton(m_page->radioPasteWeb, PASTE_ASSUME_WEB); m_pasteBehaviourGroup.addButton(m_page->radioPasteMonitor, PASTE_ASSUME_MONITOR); m_pasteBehaviourGroup.addButton(m_page->radioPasteAsk, PASTE_ASK); QAbstractButton *button = m_pasteBehaviourGroup.button(cfg.pasteBehaviour()); Q_ASSERT(button); if (button) { button->setChecked(true); } m_page->cmbMonitorIntent->setCurrentIndex(cfg.monitorRenderIntent()); toggleAllowMonitorProfileSelection(cfg.useSystemMonitorProfile()); } void ColorSettingsTab::installProfile() { KoFileDialog dialog(this, KoFileDialog::OpenFiles, "OpenDocumentICC"); dialog.setCaption(i18n("Install Color Profiles")); dialog.setDefaultDir(QDesktopServices::storageLocation(QDesktopServices::HomeLocation)); dialog.setMimeTypeFilters(QStringList() << "application/vnd.iccprofile", "application/vnd.iccprofile"); QStringList profileNames = dialog.filenames(); KoColorSpaceEngine *iccEngine = KoColorSpaceEngineRegistry::instance()->get("icc"); Q_ASSERT(iccEngine); QString saveLocation = KoResourcePaths::saveLocation("icc_profiles"); Q_FOREACH (const QString &profileName, profileNames) { QUrl file(profileName); if (!QFile::copy(profileName, saveLocation + file.fileName())) { dbgKrita << "Could not install profile!"; return; } iccEngine->addProfile(saveLocation + file.fileName()); } KisConfig cfg; refillMonitorProfiles(KoID("RGBA", "")); for(int i = 0; i < QApplication::desktop()->screenCount(); ++i) { if (m_monitorProfileWidgets[i]->contains(cfg.monitorProfile(i))) { m_monitorProfileWidgets[i]->setCurrent(cfg.monitorProfile(i)); } } } void ColorSettingsTab::toggleAllowMonitorProfileSelection(bool useSystemProfile) { if (useSystemProfile) { KisConfig cfg; QStringList devices = KisColorManager::instance()->devices(); if (devices.size() == QApplication::desktop()->screenCount()) { for(int i = 0; i < QApplication::desktop()->screenCount(); ++i) { m_monitorProfileWidgets[i]->clear(); QString monitorForScreen = cfg.monitorForScreen(i, devices[i]); Q_FOREACH (const QString &device, devices) { m_monitorProfileLabels[i]->setText(i18nc("The display/screen we got from Qt", "Screen %1:", i + 1)); m_monitorProfileWidgets[i]->addSqueezedItem(KisColorManager::instance()->deviceName(device), device); if (devices[i] == monitorForScreen) { m_monitorProfileWidgets[i]->setCurrentIndex(i); } } } } } else { KisConfig cfg; refillMonitorProfiles(KoID("RGBA", "")); for(int i = 0; i < QApplication::desktop()->screenCount(); ++i) { if (m_monitorProfileWidgets[i]->contains(cfg.monitorProfile(i))) { m_monitorProfileWidgets[i]->setCurrent(cfg.monitorProfile(i)); } } } } void ColorSettingsTab::setDefault() { m_page->cmbWorkingColorSpace->setCurrent("RGBA"); refillMonitorProfiles(KoID("RGBA", "")); KisConfig cfg; KisImageConfig cfgImage; KisProofingConfigurationSP proofingConfig = cfgImage.defaultProofingconfiguration(); const KoColorSpace *proofingSpace = KoColorSpaceRegistry::instance()->colorSpace(proofingConfig->proofingModel,proofingConfig->proofingDepth,proofingConfig->proofingProfile); m_page->proofingSpaceSelector->setCurrentColorSpace(proofingSpace); m_page->cmbProofingIntent->setCurrentIndex((int)proofingConfig->intent); m_page->ckbProofBlackPoint->setChecked(proofingConfig->conversionFlags.testFlag(KoColorConversionTransformation::BlackpointCompensation)); m_page->sldAdaptationState->setValue(0); - m_gamutWarning->setCurrentColor(proofingConfig->warningColor); + //probably this should become the screenprofile? + KoColor ga(KoColorSpaceRegistry::instance()->rgb8()); + ga.fromKoColor(proofingConfig->warningColor); + m_page->gamutAlarm->setColor(ga); m_page->chkBlackpoint->setChecked(cfg.useBlackPointCompensation(true)); m_page->chkAllowLCMSOptimization->setChecked(cfg.allowLCMSOptimization(true)); m_page->cmbMonitorIntent->setCurrentIndex(cfg.monitorRenderIntent(true)); m_page->chkUseSystemMonitorProfile->setChecked(cfg.useSystemMonitorProfile(true)); QAbstractButton *button = m_pasteBehaviourGroup.button(cfg.pasteBehaviour(true)); Q_ASSERT(button); if (button) { button->setChecked(true); } } void ColorSettingsTab::refillMonitorProfiles(const KoID & s) { const KoColorSpaceFactory * csf = KoColorSpaceRegistry::instance()->colorSpaceFactory(s.id()); for (int i = 0; i < QApplication::desktop()->screenCount(); ++i) { m_monitorProfileWidgets[i]->clear(); } if (!csf) return; QList profileList = KoColorSpaceRegistry::instance()->profilesFor(csf); Q_FOREACH (const KoColorProfile *profile, profileList) { // //dbgKrita << "Profile" << profile->name() << profile->isSuitableForDisplay() << csf->defaultProfile(); if (profile->isSuitableForDisplay()) { for (int i = 0; i < QApplication::desktop()->screenCount(); ++i) { m_monitorProfileWidgets[i]->addSqueezedItem(profile->name()); } } } for (int i = 0; i < QApplication::desktop()->screenCount(); ++i) { m_monitorProfileLabels[i]->setText(i18nc("The number of the screen", "Screen %1:", i + 1)); m_monitorProfileWidgets[i]->setCurrent(csf->defaultProfile()); } } //--------------------------------------------------------------------------------------------------- void TabletSettingsTab::setDefault() { KisCubicCurve curve; curve.fromString(DEFAULT_CURVE_STRING); m_page->pressureCurve->setCurve(curve); } TabletSettingsTab::TabletSettingsTab(QWidget* parent, const char* name): QWidget(parent) { setObjectName(name); QGridLayout * l = new QGridLayout(this); l->setMargin(0); m_page = new WdgTabletSettings(this); l->addWidget(m_page, 0, 0); KisConfig cfg; KisCubicCurve curve; curve.fromString( cfg.pressureTabletCurve() ); m_page->pressureCurve->setMaximumSize(QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)); m_page->pressureCurve->setCurve(curve); } //--------------------------------------------------------------------------------------------------- #include "kis_acyclic_signal_connector.h" int getTotalRAM() { KisImageConfig cfg; return cfg.totalRAM(); } int PerformanceTab::realTilesRAM() { return intMemoryLimit->value() - intPoolLimit->value(); } PerformanceTab::PerformanceTab(QWidget *parent, const char *name) : WdgPerformanceSettings(parent, name) { KisImageConfig cfg; const int totalRAM = cfg.totalRAM(); lblTotalMemory->setText(i18n("%1 MiB", totalRAM)); sliderMemoryLimit->setSuffix(i18n(" %")); sliderMemoryLimit->setRange(1, 100, 2); sliderMemoryLimit->setSingleStep(0.01); sliderPoolLimit->setSuffix(i18n(" %")); sliderPoolLimit->setRange(0, 20, 2); sliderMemoryLimit->setSingleStep(0.01); sliderUndoLimit->setSuffix(i18n(" %")); sliderUndoLimit->setRange(0, 50, 2); sliderMemoryLimit->setSingleStep(0.01); intMemoryLimit->setMinimumWidth(80); intPoolLimit->setMinimumWidth(80); intUndoLimit->setMinimumWidth(80); SliderAndSpinBoxSync *sync1 = new SliderAndSpinBoxSync(sliderMemoryLimit, intMemoryLimit, getTotalRAM); sync1->slotParentValueChanged(); m_syncs << sync1; SliderAndSpinBoxSync *sync2 = new SliderAndSpinBoxSync(sliderPoolLimit, intPoolLimit, std::bind(&KisIntParseSpinBox::value, intMemoryLimit)); connect(intMemoryLimit, SIGNAL(valueChanged(int)), sync2, SLOT(slotParentValueChanged())); sync2->slotParentValueChanged(); m_syncs << sync2; SliderAndSpinBoxSync *sync3 = new SliderAndSpinBoxSync(sliderUndoLimit, intUndoLimit, std::bind(&PerformanceTab::realTilesRAM, this)); connect(intPoolLimit, SIGNAL(valueChanged(int)), sync3, SLOT(slotParentValueChanged())); sync3->slotParentValueChanged(); m_syncs << sync3; sliderSwapSize->setSuffix(i18n(" GiB")); sliderSwapSize->setRange(1, 64); intSwapSize->setRange(1, 64); KisAcyclicSignalConnector *swapSizeConnector = new KisAcyclicSignalConnector(this); swapSizeConnector->connectForwardInt(sliderSwapSize, SIGNAL(valueChanged(int)), intSwapSize, SLOT(setValue(int))); swapSizeConnector->connectBackwardInt(intSwapSize, SIGNAL(valueChanged(int)), sliderSwapSize, SLOT(setValue(int))); lblSwapFileLocation->setText(cfg.swapDir()); connect(bnSwapFile, SIGNAL(clicked()), SLOT(selectSwapDir())); load(false); } PerformanceTab::~PerformanceTab() { qDeleteAll(m_syncs); } void PerformanceTab::load(bool requestDefault) { KisImageConfig cfg; sliderMemoryLimit->setValue(cfg.memoryHardLimitPercent(requestDefault)); sliderPoolLimit->setValue(cfg.memoryPoolLimitPercent(requestDefault)); sliderUndoLimit->setValue(cfg.memorySoftLimitPercent(requestDefault)); chkPerformanceLogging->setChecked(cfg.enablePerfLog(requestDefault)); chkProgressReporting->setChecked(cfg.enableProgressReporting(requestDefault)); sliderSwapSize->setValue(cfg.maxSwapSize(requestDefault) / 1024); lblSwapFileLocation->setText(cfg.swapDir(requestDefault)); { KisConfig cfg2; chkOpenGLLogging->setChecked(cfg2.enableOpenGLDebugging(requestDefault)); chkDisableVectorOptimizations->setChecked(cfg2.enableAmdVectorizationWorkaround(requestDefault)); } } void PerformanceTab::save() { KisImageConfig cfg; cfg.setMemoryHardLimitPercent(sliderMemoryLimit->value()); cfg.setMemorySoftLimitPercent(sliderUndoLimit->value()); cfg.setMemoryPoolLimitPercent(sliderPoolLimit->value()); cfg.setEnablePerfLog(chkPerformanceLogging->isChecked()); cfg.setEnableProgressReporting(chkProgressReporting->isChecked()); cfg.setMaxSwapSize(sliderSwapSize->value() * 1024); cfg.setSwapDir(lblSwapFileLocation->text()); { KisConfig cfg2; cfg2.setEnableOpenGLDebugging(chkOpenGLLogging->isChecked()); cfg2.setEnableAmdVectorizationWorkaround(chkDisableVectorOptimizations->isChecked()); } } void PerformanceTab::selectSwapDir() { KisImageConfig cfg; QString swapDir = cfg.swapDir(); swapDir = QFileDialog::getExistingDirectory(0, i18nc("@title:window", "Select a swap directory"), swapDir); lblSwapFileLocation->setText(swapDir); } //--------------------------------------------------------------------------------------------------- #include "KoColor.h" -#include "KoColorPopupAction.h" DisplaySettingsTab::DisplaySettingsTab(QWidget *parent, const char *name) : WdgDisplaySettings(parent, name) { KisConfig cfg; if (!KisOpenGL::hasOpenGL()) { grpOpenGL->setEnabled(false); grpOpenGL->setChecked(false); chkUseTextureBuffer->setEnabled(false); chkDisableVsync->setEnabled(false); cmbFilterMode->setEnabled(false); } else { grpOpenGL->setEnabled(true); grpOpenGL->setChecked(cfg.useOpenGL()); chkUseTextureBuffer->setEnabled(cfg.useOpenGL()); chkUseTextureBuffer->setChecked(cfg.useOpenGLTextureBuffer()); chkDisableVsync->setVisible(cfg.showAdvancedOpenGLSettings()); chkDisableVsync->setEnabled(cfg.useOpenGL()); chkDisableVsync->setChecked(cfg.disableVSync()); cmbFilterMode->setEnabled(cfg.useOpenGL()); cmbFilterMode->setCurrentIndex(cfg.openGLFilteringMode()); // Don't show the high quality filtering mode if it's not available if (!KisOpenGL::supportsGLSL13()) { cmbFilterMode->removeItem(3); } } if (qApp->applicationName() == "kritasketch" || qApp->applicationName() == "kritagemini") { grpOpenGL->setVisible(false); grpOpenGL->setMaximumHeight(0); } KoColor c; c.fromQColor(cfg.selectionOverlayMaskColor()); - m_selectionOverlayColorAction = new KoColorPopupAction(this); - m_selectionOverlayColorAction->setCurrentColor(c); - m_selectionOverlayColorAction->setToolTip(i18n("Change the background color of the image")); - btnSelectionOverlayColor->setDefaultAction(m_selectionOverlayColorAction); + c.setOpacity(1.0); + btnSelectionOverlayColor->setColor(c); + sldSelectionOverlayOpacity->setRange(0.0, 1.0, 2); + sldSelectionOverlayOpacity->setSingleStep(0.05); + sldSelectionOverlayOpacity->setValue(cfg.selectionOverlayMaskColor().alphaF()); intCheckSize->setValue(cfg.checkSize()); chkMoving->setChecked(cfg.scrollCheckers()); - colorChecks1->setColor(cfg.checkersColor1()); - colorChecks2->setColor(cfg.checkersColor2()); - canvasBorder->setColor(cfg.canvasBorderColor()); + KoColor ck1(KoColorSpaceRegistry::instance()->rgb8()); + ck1.fromQColor(cfg.checkersColor1()); + colorChecks1->setColor(ck1); + KoColor ck2(KoColorSpaceRegistry::instance()->rgb8()); + ck2.fromQColor(cfg.checkersColor2()); + colorChecks2->setColor(ck2); + KoColor cb(KoColorSpaceRegistry::instance()->rgb8()); + cb.fromQColor(cfg.canvasBorderColor()); + canvasBorder->setColor(cb); hideScrollbars->setChecked(cfg.hideScrollbars()); chkCurveAntialiasing->setChecked(cfg.antialiasCurves()); chkSelectionOutlineAntialiasing->setChecked(cfg.antialiasSelectionOutline()); chkChannelsAsColor->setChecked(cfg.showSingleChannelAsColor()); chkHidePopups->setChecked(cfg.hidePopups()); connect(grpOpenGL, SIGNAL(toggled(bool)), SLOT(slotUseOpenGLToggled(bool))); } void DisplaySettingsTab::setDefault() { KisConfig cfg; if (!KisOpenGL::hasOpenGL()) { grpOpenGL->setEnabled(false); grpOpenGL->setChecked(false); chkUseTextureBuffer->setEnabled(false); chkDisableVsync->setEnabled(false); cmbFilterMode->setEnabled(false); } else { grpOpenGL->setEnabled(true); grpOpenGL->setChecked(cfg.useOpenGL(true)); chkUseTextureBuffer->setChecked(cfg.useOpenGLTextureBuffer(true)); chkUseTextureBuffer->setEnabled(true); chkDisableVsync->setEnabled(true); chkDisableVsync->setChecked(cfg.disableVSync(true)); cmbFilterMode->setEnabled(true); cmbFilterMode->setCurrentIndex(cfg.openGLFilteringMode(true)); } chkMoving->setChecked(cfg.scrollCheckers(true)); intCheckSize->setValue(cfg.checkSize(true)); - colorChecks1->setColor(cfg.checkersColor1(true)); - colorChecks2->setColor(cfg.checkersColor2(true)); - canvasBorder->setColor(cfg.canvasBorderColor(true)); + KoColor ck1(KoColorSpaceRegistry::instance()->rgb8()); + ck1.fromQColor(cfg.checkersColor1(true)); + colorChecks1->setColor(ck1); + KoColor ck2(KoColorSpaceRegistry::instance()->rgb8()); + ck2.fromQColor(cfg.checkersColor2(true)); + colorChecks2->setColor(ck2); + KoColor cvb(KoColorSpaceRegistry::instance()->rgb8()); + cvb.fromQColor(cfg.canvasBorderColor(true)); + canvasBorder->setColor(cvb); hideScrollbars->setChecked(cfg.hideScrollbars(true)); chkCurveAntialiasing->setChecked(cfg.antialiasCurves(true)); chkSelectionOutlineAntialiasing->setChecked(cfg.antialiasSelectionOutline(true)); chkChannelsAsColor->setChecked(cfg.showSingleChannelAsColor(true)); chkHidePopups->setChecked(cfg.hidePopups(true)); } void DisplaySettingsTab::slotUseOpenGLToggled(bool isChecked) { chkUseTextureBuffer->setEnabled(isChecked); chkDisableVsync->setEnabled(isChecked); cmbFilterMode->setEnabled(isChecked); } //--------------------------------------------------------------------------------------------------- FullscreenSettingsTab::FullscreenSettingsTab(QWidget* parent) : WdgFullscreenSettingsBase(parent) { KisConfig cfg; chkDockers->setChecked(cfg.hideDockersFullscreen()); chkMenu->setChecked(cfg.hideMenuFullscreen()); chkScrollbars->setChecked(cfg.hideScrollbarsFullscreen()); chkStatusbar->setChecked(cfg.hideStatusbarFullscreen()); chkTitlebar->setChecked(cfg.hideTitlebarFullscreen()); chkToolbar->setChecked(cfg.hideToolbarFullscreen()); } void FullscreenSettingsTab::setDefault() { KisConfig cfg; chkDockers->setChecked(cfg.hideDockersFullscreen(true)); chkMenu->setChecked(cfg.hideMenuFullscreen(true)); chkScrollbars->setChecked(cfg.hideScrollbarsFullscreen(true)); chkStatusbar->setChecked(cfg.hideStatusbarFullscreen(true)); chkTitlebar->setChecked(cfg.hideTitlebarFullscreen(true)); chkToolbar->setChecked(cfg.hideToolbarFullscreen(true)); } //--------------------------------------------------------------------------------------------------- KisDlgPreferences::KisDlgPreferences(QWidget* parent, const char* name) : KPageDialog(parent) { Q_UNUSED(name); setWindowTitle(i18n("Preferences")); // QT5TODO: help button needs custom wiring up to whatever help should be shown setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Help | QDialogButtonBox::RestoreDefaults); button(QDialogButtonBox::Ok)->setDefault(true); setFaceType(KPageDialog::List); // General KoVBox *vbox = new KoVBox(); KPageWidgetItem *page = new KPageWidgetItem(vbox, i18n("General")); page->setObjectName("general"); page->setHeader(i18n("General")); page->setIcon(KisIconUtils::loadIcon("go-home")); addPage(page); m_general = new GeneralTab(vbox); // Shortcuts vbox = new KoVBox(); page = new KPageWidgetItem(vbox, i18n("Keyboard Shortcuts")); page->setObjectName("shortcuts"); page->setHeader(i18n("Shortcuts")); page->setIcon(KisIconUtils::loadIcon("document-export")); addPage(page); m_shortcutSettings = new ShortcutSettingsTab(vbox); connect(this, SIGNAL(accepted()), m_shortcutSettings, SLOT(saveChanges())); // Canvas input settings m_inputConfiguration = new KisInputConfigurationPage(); page = addPage(m_inputConfiguration, i18n("Canvas Input Settings")); page->setHeader(i18n("Canvas Input")); page->setObjectName("canvasinput"); page->setIcon(KisIconUtils::loadIcon("configure")); // Display vbox = new KoVBox(); page = new KPageWidgetItem(vbox, i18n("Display")); page->setObjectName("display"); page->setHeader(i18n("Display")); page->setIcon(KisIconUtils::loadIcon("preferences-desktop-display")); addPage(page); m_displaySettings = new DisplaySettingsTab(vbox); // Color vbox = new KoVBox(); page = new KPageWidgetItem(vbox, i18n("Color Management")); page->setObjectName("colormanagement"); page->setHeader(i18n("Color")); page->setIcon(KisIconUtils::loadIcon("preferences-desktop-color")); addPage(page); m_colorSettings = new ColorSettingsTab(vbox); // Performance vbox = new KoVBox(); page = new KPageWidgetItem(vbox, i18n("Performance")); page->setObjectName("performance"); page->setHeader(i18n("Performance")); page->setIcon(KisIconUtils::loadIcon("applications-system")); addPage(page); m_performanceSettings = new PerformanceTab(vbox); // Tablet vbox = new KoVBox(); page = new KPageWidgetItem(vbox, i18n("Tablet settings")); page->setObjectName("tablet"); page->setHeader(i18n("Tablet")); page->setIcon(KisIconUtils::loadIcon("document-edit")); addPage(page); m_tabletSettings = new TabletSettingsTab(vbox); // full-screen mode vbox = new KoVBox(); page = new KPageWidgetItem(vbox, i18n("Canvas-only settings")); page->setObjectName("canvasonly"); page->setHeader(i18n("Canvas-only")); page->setIcon(KisIconUtils::loadIcon("folder-pictures")); addPage(page); m_fullscreenSettings = new FullscreenSettingsTab(vbox); // Author profiles m_authorPage = new KoConfigAuthorPage(); page = addPage(m_authorPage, i18nc("@title:tab Author page", "Author" )); page->setObjectName("author"); page->setHeader(i18n("Author")); page->setIcon(KisIconUtils::loadIcon("im-user")); QPushButton *restoreDefaultsButton = button(QDialogButtonBox::RestoreDefaults); connect(this, SIGNAL(accepted()), m_inputConfiguration, SLOT(saveChanges())); connect(this, SIGNAL(rejected()), m_inputConfiguration, SLOT(revertChanges())); KisPreferenceSetRegistry *preferenceSetRegistry = KisPreferenceSetRegistry::instance(); Q_FOREACH (KisAbstractPreferenceSetFactory *preferenceSetFactory, preferenceSetRegistry->values()) { KisPreferenceSet* preferenceSet = preferenceSetFactory->createPreferenceSet(); vbox = new KoVBox(); page = new KPageWidgetItem(vbox, preferenceSet->name()); page->setHeader(preferenceSet->header()); page->setIcon(preferenceSet->icon()); addPage(page); preferenceSet->setParent(vbox); preferenceSet->loadPreferences(); connect(restoreDefaultsButton, SIGNAL(clicked(bool)), preferenceSet, SLOT(loadDefaultPreferences()), Qt::UniqueConnection); connect(this, SIGNAL(accepted()), preferenceSet, SLOT(savePreferences()), Qt::UniqueConnection); } connect(restoreDefaultsButton, SIGNAL(clicked(bool)), this, SLOT(slotDefault())); } KisDlgPreferences::~KisDlgPreferences() { } void KisDlgPreferences::slotDefault() { if (currentPage()->objectName() == "general") { m_general->setDefault(); } else if (currentPage()->objectName() == "shortcuts") { m_shortcutSettings->setDefault(); } else if (currentPage()->objectName() == "display") { m_displaySettings->setDefault(); } else if (currentPage()->objectName() == "colormanagement") { m_colorSettings->setDefault(); } else if (currentPage()->objectName() == "performance") { m_performanceSettings->load(true); } else if (currentPage()->objectName() == "tablet") { m_tabletSettings->setDefault(); } else if (currentPage()->objectName() == "canvasonly") { m_fullscreenSettings->setDefault(); } else if (currentPage()->objectName() == "canvasinput") { m_inputConfiguration->setDefaults(); } } bool KisDlgPreferences::editPreferences() { KisDlgPreferences* dialog; dialog = new KisDlgPreferences(); bool baccept = (dialog->exec() == Accepted); if (baccept) { // General settings KisConfig cfg; cfg.setNewCursorStyle(dialog->m_general->cursorStyle()); cfg.setNewOutlineStyle(dialog->m_general->outlineStyle()); cfg.setShowRootLayer(dialog->m_general->showRootLayer()); cfg.setShowOutlineWhilePainting(dialog->m_general->showOutlineWhilePainting()); cfg.setHideSplashScreen(dialog->m_general->hideSplashScreen()); cfg.writeEntry("mdi_viewmode", dialog->m_general->mdiMode()); - cfg.setMDIBackgroundColor(dialog->m_general->m_mdiColor->color()); + cfg.setMDIBackgroundColor(dialog->m_general->m_mdiColor->color().toQColor()); cfg.setMDIBackgroundImage(dialog->m_general->m_backgroundimage->text()); cfg.setAutoSaveInterval(dialog->m_general->autoSaveInterval()); cfg.setBackupFile(dialog->m_general->m_backupFileCheckBox->isChecked()); cfg.setShowCanvasMessages(dialog->m_general->showCanvasMessages()); cfg.setCompressKra(dialog->m_general->compressKra()); cfg.setToolOptionsInDocker(dialog->m_general->toolOptionsInDocker()); cfg.setSwitchSelectionCtrlAlt(dialog->m_general->switchSelectionCtrlAlt()); cfg.setConvertToImageColorspaceOnImport(dialog->m_general->convertToImageColorspaceOnImport()); KisPart *part = KisPart::instance(); if (part) { Q_FOREACH (QPointer doc, part->documents()) { if (doc) { doc->setAutoSave(dialog->m_general->autoSaveInterval()); doc->setBackupFile(dialog->m_general->m_backupFileCheckBox->isChecked()); doc->undoStack()->setUndoLimit(dialog->m_general->undoStackSize()); } } } cfg.setUndoStackLimit(dialog->m_general->undoStackSize()); cfg.setFavoritePresets(dialog->m_general->favoritePresets()); // Color settings cfg.setUseSystemMonitorProfile(dialog->m_colorSettings->m_page->chkUseSystemMonitorProfile->isChecked()); for (int i = 0; i < QApplication::desktop()->screenCount(); ++i) { if (dialog->m_colorSettings->m_page->chkUseSystemMonitorProfile->isChecked()) { int currentIndex = dialog->m_colorSettings->m_monitorProfileWidgets[i]->currentIndex(); QString monitorid = dialog->m_colorSettings->m_monitorProfileWidgets[i]->itemData(currentIndex).toString(); cfg.setMonitorForScreen(i, monitorid); } else { cfg.setMonitorProfile(i, dialog->m_colorSettings->m_monitorProfileWidgets[i]->itemHighlighted(), dialog->m_colorSettings->m_page->chkUseSystemMonitorProfile->isChecked()); } } cfg.setWorkingColorSpace(dialog->m_colorSettings->m_page->cmbWorkingColorSpace->currentItem().id()); KisImageConfig cfgImage; - cfgImage.setDefaultProofingConfig(dialog->m_colorSettings->m_page->proofingSpaceSelector->currentColorSpace(), dialog->m_colorSettings->m_page->cmbProofingIntent->currentIndex(), dialog->m_colorSettings->m_page->ckbProofBlackPoint->isChecked(), dialog->m_colorSettings->m_gamutWarning->currentKoColor(), (double)dialog->m_colorSettings->m_page->sldAdaptationState->value()/20); + cfgImage.setDefaultProofingConfig(dialog->m_colorSettings->m_page->proofingSpaceSelector->currentColorSpace(), dialog->m_colorSettings->m_page->cmbProofingIntent->currentIndex(), dialog->m_colorSettings->m_page->ckbProofBlackPoint->isChecked(), dialog->m_colorSettings->m_page->gamutAlarm->color(), (double)dialog->m_colorSettings->m_page->sldAdaptationState->value()/20); cfg.setUseBlackPointCompensation(dialog->m_colorSettings->m_page->chkBlackpoint->isChecked()); cfg.setAllowLCMSOptimization(dialog->m_colorSettings->m_page->chkAllowLCMSOptimization->isChecked()); cfg.setPasteBehaviour(dialog->m_colorSettings->m_pasteBehaviourGroup.checkedId()); cfg.setRenderIntent(dialog->m_colorSettings->m_page->cmbMonitorIntent->currentIndex()); // Tablet settings cfg.setPressureTabletCurve( dialog->m_tabletSettings->m_page->pressureCurve->curve().toString() ); dialog->m_performanceSettings->save(); if (!cfg.useOpenGL() && dialog->m_displaySettings->grpOpenGL->isChecked()) cfg.setCanvasState("TRY_OPENGL"); cfg.setUseOpenGL(dialog->m_displaySettings->grpOpenGL->isChecked()); cfg.setUseOpenGLTextureBuffer(dialog->m_displaySettings->chkUseTextureBuffer->isChecked()); cfg.setOpenGLFilteringMode(dialog->m_displaySettings->cmbFilterMode->currentIndex()); cfg.setDisableVSync(dialog->m_displaySettings->chkDisableVsync->isChecked()); cfg.setCheckSize(dialog->m_displaySettings->intCheckSize->value()); cfg.setScrollingCheckers(dialog->m_displaySettings->chkMoving->isChecked()); - cfg.setCheckersColor1(dialog->m_displaySettings->colorChecks1->color()); - cfg.setCheckersColor2(dialog->m_displaySettings->colorChecks2->color()); - cfg.setCanvasBorderColor(dialog->m_displaySettings->canvasBorder->color()); + cfg.setCheckersColor1(dialog->m_displaySettings->colorChecks1->color().toQColor()); + cfg.setCheckersColor2(dialog->m_displaySettings->colorChecks2->color().toQColor()); + cfg.setCanvasBorderColor(dialog->m_displaySettings->canvasBorder->color().toQColor()); cfg.setHideScrollbars(dialog->m_displaySettings->hideScrollbars->isChecked()); - cfg.setSelectionOverlayMaskColor(dialog->m_displaySettings->m_selectionOverlayColorAction->currentKoColor().toQColor()); + KoColor c = dialog->m_displaySettings->btnSelectionOverlayColor->color(); + c.setOpacity(dialog->m_displaySettings->sldSelectionOverlayOpacity->value()); + cfg.setSelectionOverlayMaskColor(c.toQColor()); cfg.setAntialiasCurves(dialog->m_displaySettings->chkCurveAntialiasing->isChecked()); cfg.setAntialiasSelectionOutline(dialog->m_displaySettings->chkSelectionOutlineAntialiasing->isChecked()); cfg.setShowSingleChannelAsColor(dialog->m_displaySettings->chkChannelsAsColor->isChecked()); cfg.setHidePopups(dialog->m_displaySettings->chkHidePopups->isChecked()); cfg.setHideDockersFullscreen(dialog->m_fullscreenSettings->chkDockers->checkState()); cfg.setHideMenuFullscreen(dialog->m_fullscreenSettings->chkMenu->checkState()); cfg.setHideScrollbarsFullscreen(dialog->m_fullscreenSettings->chkScrollbars->checkState()); cfg.setHideStatusbarFullscreen(dialog->m_fullscreenSettings->chkStatusbar->checkState()); cfg.setHideTitlebarFullscreen(dialog->m_fullscreenSettings->chkTitlebar->checkState()); cfg.setHideToolbarFullscreen(dialog->m_fullscreenSettings->chkToolbar->checkState()); dialog->m_authorPage->apply(); } delete dialog; return baccept; } diff --git a/libs/ui/dialogs/kis_dlg_preferences.h b/libs/ui/dialogs/kis_dlg_preferences.h index ea0449425c..1fdcccbc4c 100644 --- a/libs/ui/dialogs/kis_dlg_preferences.h +++ b/libs/ui/dialogs/kis_dlg_preferences.h @@ -1,329 +1,326 @@ /* * preferencesdlg.h - part of KImageShop^WKrita * * Copyright (c) 1999 Michael Koch * Copyright (c) 2003-2011 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_DLG_PREFERENCES_H_ #define _KIS_DLG_PREFERENCES_H_ #include #include -#include "KoColorPopupAction.h" #include "kis_global.h" +#include "widgets/squeezedcombobox.h" #include "ui_wdggeneralsettings.h" #include "ui_wdgdisplaysettings.h" #include "ui_wdgcolorsettings.h" #include "ui_wdgtabletsettings.h" #include "ui_wdgperformancesettings.h" #include "ui_wdgfullscreensettings.h" #include "KisShortcutsDialog.h" class KoID; class KisInputConfigurationPage; class KoConfigAuthorPage; /** * "General"-tab for preferences dialog */ class WdgGeneralSettings : public QWidget, public Ui::WdgGeneralSettings { Q_OBJECT public: WdgGeneralSettings(QWidget *parent, const char *name) : QWidget(parent) { setObjectName(name); setupUi(this); chkShowRootLayer->setVisible(false); } }; class GeneralTab : public WdgGeneralSettings { Q_OBJECT public: GeneralTab(QWidget *parent = 0, const char *name = 0); CursorStyle cursorStyle(); OutlineStyle outlineStyle(); bool showRootLayer(); int autoSaveInterval(); void setDefault(); int undoStackSize(); bool showOutlineWhilePainting(); bool hideSplashScreen(); int mdiMode(); int favoritePresets(); bool showCanvasMessages(); bool compressKra(); bool toolOptionsInDocker(); bool switchSelectionCtrlAlt(); bool convertToImageColorspaceOnImport(); private Q_SLOTS: void getBackgroundImage(); void clearBackgroundImage(); }; /** * "Shortcuts" tab for preferences dialog */ class WdgShortcutSettings : public KisShortcutsDialog { Q_OBJECT public: WdgShortcutSettings(QWidget *parent) : KisShortcutsDialog(KisShortcutsEditor::AllActions, KisShortcutsEditor::LetterShortcutsAllowed, parent) { } }; class ShortcutSettingsTab : public QWidget { Q_OBJECT public: ShortcutSettingsTab(QWidget *parent = 0, const char *name = 0); public: void setDefault(); WdgShortcutSettings *m_page; public Q_SLOTS: void saveChanges(); void revertChanges(); }; /** * "Color" tab for preferences dialog */ class WdgColorSettings : public QWidget, public Ui::WdgColorSettings { Q_OBJECT public: WdgColorSettings(QWidget *parent) : QWidget(parent) { setupUi(this); } }; class ColorSettingsTab : public QWidget { Q_OBJECT public: ColorSettingsTab(QWidget *parent = 0, const char *name = 0); private Q_SLOTS: void refillMonitorProfiles(const KoID & s); void installProfile(); void toggleAllowMonitorProfileSelection(bool useSystemProfile); public: void setDefault(); WdgColorSettings *m_page; - KoColorPopupAction *m_gamutWarning; QButtonGroup m_pasteBehaviourGroup; QList m_monitorProfileLabels; QList m_monitorProfileWidgets; }; //======================= class WdgTabletSettings : public QWidget, public Ui::WdgTabletSettings { Q_OBJECT public: WdgTabletSettings(QWidget *parent) : QWidget(parent) { setupUi(this); } }; class TabletSettingsTab : public QWidget { Q_OBJECT public: TabletSettingsTab(QWidget *parent = 0, const char *name = 0); public: void setDefault(); WdgTabletSettings *m_page; }; //======================= /** * "Performance"-tab for preferences dialog */ class SliderAndSpinBoxSync; class WdgPerformanceSettings : public QWidget, public Ui::WdgPerformanceSettings { Q_OBJECT public: WdgPerformanceSettings(QWidget *parent, const char *name) : QWidget(parent) { setObjectName(name); setupUi(this); } }; class PerformanceTab : public WdgPerformanceSettings { Q_OBJECT public: PerformanceTab(QWidget *parent = 0, const char *name = 0); ~PerformanceTab(); void load(bool requestDefault); void save(); private Q_SLOTS: void selectSwapDir(); private: int realTilesRAM(); private: QVector m_syncs; }; //======================= class WdgDisplaySettings : public QWidget, public Ui::WdgDisplaySettings { Q_OBJECT public: WdgDisplaySettings(QWidget *parent, const char *name) : QWidget(parent) { setObjectName(name); setupUi(this); } }; /** * Display settings tab for preferences dialog */ -class KoColorPopupAction; class DisplaySettingsTab : public WdgDisplaySettings { Q_OBJECT public: DisplaySettingsTab(QWidget *parent = 0, const char *name = 0); public: void setDefault(); protected Q_SLOTS: void slotUseOpenGLToggled(bool isChecked); public: - KoColorPopupAction *m_selectionOverlayColorAction; }; //======================= /** * Full screen settings tab for preferences dialog */ class WdgFullscreenSettingsBase : public QWidget, public Ui::WdgFullscreenSettings { Q_OBJECT public: WdgFullscreenSettingsBase(QWidget *parent) : QWidget(parent) { setupUi(this); } }; class FullscreenSettingsTab : public WdgFullscreenSettingsBase { Q_OBJECT public: FullscreenSettingsTab(QWidget *parent); public: void setDefault(); }; //======================= /** * Preferences dialog of KImageShop^WKrayon^WKrita */ class KisDlgPreferences : public KPageDialog { Q_OBJECT public: static bool editPreferences(); protected: KisDlgPreferences(QWidget *parent = 0, const char *name = 0); ~KisDlgPreferences(); protected: GeneralTab *m_general; ShortcutSettingsTab *m_shortcutSettings; ColorSettingsTab *m_colorSettings; PerformanceTab *m_performanceSettings; DisplaySettingsTab *m_displaySettings; TabletSettingsTab *m_tabletSettings; FullscreenSettingsTab *m_fullscreenSettings; KisInputConfigurationPage *m_inputConfiguration; KoConfigAuthorPage *m_authorPage; protected Q_SLOTS: void slotDefault(); }; #endif diff --git a/libs/ui/forms/wdgautogradient.ui b/libs/ui/forms/wdgautogradient.ui index e6c2ee7608..cb25376aec 100644 --- a/libs/ui/forms/wdgautogradient.ui +++ b/libs/ui/forms/wdgautogradient.ui @@ -1,390 +1,389 @@ KisWdgAutogradient 0 0 500 250 500 250 Name: 0 1 Qt::ClickFocus Sans Serif 9 50 false false false false Segment Color Sans Serif 9 50 false false false false Opacity: Sans Serif 9 50 false false false false Left: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 0 0 0 30 Sans Serif 9 50 false false false false Qt::ClickFocus 0 0 Sans Serif 9 50 false false false false Qt::ClickFocus 100 100 Sans Serif 9 50 false false false false Right: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 0 0 0 30 Sans Serif 9 50 false false false false Qt::ClickFocus 255 255 255 255 255 255 0 0 Sans Serif 9 50 false false false false Qt::ClickFocus 100 100 0 0 0 0 Qt::Horizontal 40 20 Sans Serif 9 50 false false false false Qt::ClickFocus Linear Curved Sine Sphere Inc. Sphere Dec. Sans Serif 9 50 false false false false Qt::ClickFocus RGB HSV CW HSV CCW KisIntParseSpinBox QSpinBox
kis_int_parse_spin_box.h
- KColorButton + KisColorButton QPushButton -
kcolorbutton.h
- 1 +
kis_color_button.h
KisGradientSliderWidget
widgets/kis_gradient_slider_widget.h
diff --git a/libs/ui/forms/wdgcolorsettings.ui b/libs/ui/forms/wdgcolorsettings.ui index e06a24f2ea..c51dc04f02 100644 --- a/libs/ui/forms/wdgcolorsettings.ui +++ b/libs/ui/forms/wdgcolorsettings.ui @@ -1,389 +1,389 @@ WdgColorSettings 0 0 586 613 Color Settings 0 0 0 0 Default color model for new images: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 0 20 Display Use system monitor profile false 0 0 0 0 0 0 0 0 The icm profile for your calibrated monitor &Rendering intent: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter cmbMonitorIntent 0 0 Perceptual Relative Colorimetric Saturation Absolute Colorimetric Add new color profile: 24 24 true Soft Proof Options - - - - ... - - - Proofing Rendering Intent: Black Point Compensation Gamut Warning: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Perceptual Relative Colorimetric Saturation Absolute Colorimetric Qt::Horizontal Adaptation State: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + When Pasting Into Krita From Other Applications Assume sRGB (like images from the web are supposed to be seen) Assume monitor profile (like you see it in the other application) Ask each time Note: When copying/pasting inside Krita color info is always preserved. 6 0 0 0 0 Use Blackpoint Compensation true Allow Little CMS optimizations (uncheck when using linear light RGB or XYZ) true Qt::Vertical QSizePolicy::Expanding 20 16 + + KisColorButton + QPushButton +
kis_color_button.h
+
KisColorSpaceSelector QWidget
widgets/kis_color_space_selector.h
1
KComboBox QComboBox
kcombobox.h
KisCmbIDList QComboBox
widgets/kis_cmb_idlist.h
- - SqueezedComboBox - QComboBox -
widgets/squeezedcombobox.h
-
diff --git a/libs/ui/forms/wdgdisplaysettings.ui b/libs/ui/forms/wdgdisplaysettings.ui index 0bbd7ed23a..deb5017970 100644 --- a/libs/ui/forms/wdgdisplaysettings.ui +++ b/libs/ui/forms/wdgdisplaysettings.ui @@ -1,360 +1,362 @@ WdgDisplaySettings 0 0 504 685 0 0 Display Miscellaneous Color channels in color false Enable curve anti-aliasing Enable selection outline anti-aliasing Hide layer thumbnail popup Transparency Checkerboard Pattern S&ize: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter intCheckSize px 256 32 Qt::Horizontal 40 20 Colors: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + - + Qt::Horizontal 40 20 If checked, the checkers will move when scrolling the canvas. Determines whether the checks will stay put or whether they will scroll together with the canvas &Move checkers when scrolling true Qt::Vertical 20 40 0 0 Open&GL true 0 0 0 Nearest Neighbour Bilinear Filtering Trilinear Filtering High Quality Filtering <html><head/><body><p>Try to disable vsync for Krita. This makes painting more responsive. Uncheck only when experiencing crashes with some GPU/driver combinations.</p></body></html> Disable vsync (needs restart) true 0 0 <html><head/><body><p>Use Texture Buffering. This can be faster on some GPU/Driver combinations (like Intel) or broken on some others (like AMD/Radeon).</p></body></html> Use texture buffer 0 0 Scaling Mode: Canvas border Color: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + Qt::Horizontal 40 20 Hide Scrollbars false Selection Overlay Color: - + - ... + - - - Qt::Horizontal - - - - 358 - 20 - + + + + 0 + 0 + - + KisIntParseSpinBox QSpinBox
kis_int_parse_spin_box.h
- KColorButton + KisColorButton QPushButton -
kcolorbutton.h
+
kis_color_button.h
+
+ + KisDoubleSliderSpinBox + QWidget +
kis_slider_spin_box.h
1
diff --git a/libs/ui/forms/wdgdlginternalcolorselector.ui b/libs/ui/forms/wdgdlginternalcolorselector.ui new file mode 100644 index 0000000000..4ad1fb8e03 --- /dev/null +++ b/libs/ui/forms/wdgdlginternalcolorselector.ui @@ -0,0 +1,237 @@ + + + WdgDlgInternalColorSelector + + + + 0 + 0 + 505 + 483 + + + + Dialog + + + + + + + + + + + 0 + 0 + + + + + 90 + 90 + + + + + + + + + 0 + 0 + + + + + 0 + 50 + + + + + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + 2 + + + 2 + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 50 + 70 + + + + + + + + + 0 + 0 + + + + + 25 + 25 + + + + + + + + + + + + + + + + 0 + 0 + + + + + 225 + 50 + + + + + + + + + 0 + 0 + + + + + 50 + 50 + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + KisSpinboxColorSelector + QWidget +
kis_spinbox_color_selector.h
+ 1 +
+ + KisScreenColorPicker + QWidget +
kis_screen_color_picker.h
+ 1 +
+ + KisVisualColorSelector + QWidget +
kis_visual_color_selector.h
+ 1 +
+ + KoColorPatch + QWidget +
KoColorPatch.h
+ 1 +
+ + KoColorSetWidget + QFrame +
KoColorSetWidget.h
+ 1 +
+
+ + + + buttonBox + accepted() + WdgDlgInternalColorSelector + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + WdgDlgInternalColorSelector + reject() + + + 316 + 260 + + + 286 + 274 + + + + +
diff --git a/libs/ui/forms/wdggeneralsettings.ui b/libs/ui/forms/wdggeneralsettings.ui index f27eed6a6d..aaa37d1498 100644 --- a/libs/ui/forms/wdggeneralsettings.ui +++ b/libs/ui/forms/wdggeneralsettings.ui @@ -1,715 +1,705 @@ WdgGeneralSettings 0 0 552 295 0 0 552 295 Qt::LeftToRight 0 Cursor 10 10 10 10 10 10 0 0 Cursor Shape: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 Outline Shape: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 200 0 Show brush outline while painting Qt::Horizontal 40 20 Qt::Vertical 20 40 Window Qt::Vertical 20 40 10 10 10 10 10 0 0 Multiple Document Mode: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Window Background: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 200 0 QFrame::StyledPanel QFrame::Sunken ... 0 0 Clear - + 0 0 - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - Background Image (overrides color): 0 0 1 Subwindows Tabs 0 0 Don't show contents when moving sub-windows Qt::Horizontal 40 20 Show on-canvas popup messages: Qt::Horizontal 40 20 Qt::Horizontal 40 20 Tools 10 10 10 10 10 Tool Options Location (needs restart) In Doc&ker In Tool&bar true Switch Control/Alt Selection Modifiers Qt::Vertical 20 40 Qt::Horizontal 40 20 Miscellaneous 10 10 10 10 10 0 0 Qt::RightToLeft Autosave every: true 0 0 Undo stack size: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Compress .kra files more (slows loading/saving) Create backup file 0 0 75 0 10 30 0 0 Favorite presets: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 75 0 min 1 1440 5 15 0 0 75 0 0 1000 5 30 Show root layer Hide splash screen on startup On importing images as layers, convert to the image colorspace Qt::Vertical 20 40 Qt::Vertical 20 40 - KColorButton + KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
+
+ + KisColorButton QPushButton -
kcolorbutton.h
- 1 +
kis_color_button.h
KisIntParseSpinBox QSpinBox
kis_int_parse_spin_box.h
diff --git a/libs/ui/forms/wdgimageproperties.ui b/libs/ui/forms/wdgimageproperties.ui index 8a03c544e5..eb1196f2f0 100644 --- a/libs/ui/forms/wdgimageproperties.ui +++ b/libs/ui/forms/wdgimageproperties.ui @@ -1,332 +1,350 @@ WdgImageProperties 0 0 448 568 New Image Qt::Horizontal 95 61 Width: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter TextLabel Height: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter TextLabel Resolution: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter TextLabel pixels-per-inch ppi Background Color - + - ... + - - QToolButton::InstantPopup + + + + + + + 0 + 20 + Qt::Horizontal QSizePolicy::Expanding 95 61 Annotations Type: 0 0 TextLabel true Qt::Vertical 20 40 0 Image Color Space <html><head/><body><p><span style=" font-weight:600;">Note:</span> This changes only the colorspace of the rendered image. To convert the colorspace of the layers, use Convert Image Colorspace.</p></body></html> Qt::RichText true Softproofing - - - - ... - - - Gamut Warning: Qt::LeftToRight Adaptation State: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter <html><head/><body><p>Set how much you wish to correct the adaptation state. This will affect how <span style=" font-style:italic;">Absolute Colorimetric</span> changes the whites of your image. In Layman's terms: how much do you wish to have the color management correct the paper-color to screen white while using <span style=" font-style:italic;">Absolute Colorimetric</span>?</p></body></html> Qt::Horizontal <html><head/><body><p>Black Point compensation matches the darkest color of the source device to the darkest color of the destination device. Relative Colorimetric without Black Point Compensation will show the difference between the darkest values. With blackpoint compensation, black is black.</p></body></html> Black Point Compensation Rendering Intent 0 Perceptual Relative Colorimetric Saturation Absolute Colorimetric + + + + + + + + + KisDoubleSliderSpinBox + QWidget +
kis_slider_spin_box.h
+ 1 +
+ + KisColorButton + QPushButton +
kis_color_button.h
+
KisColorSpaceSelector QWidget
widgets/kis_color_space_selector.h
1
diff --git a/libs/ui/forms/wdgnewimage.ui b/libs/ui/forms/wdgnewimage.ui index 4d5ee82786..c4841f5ac0 100644 --- a/libs/ui/forms/wdgnewimage.ui +++ b/libs/ui/forms/wdgnewimage.ui @@ -1,698 +1,697 @@ WdgNewImage 0 0 600 422 0 0 600 0 16777215 16777215 New Image 0 0 0 0 0 Dimensions 0 140 16777215 16777215 Image Size Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter false false P&redefined: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter cmbPredefined 0 0 Save As: 0 0 Save the current dimensions &Save Landscape ... true true true 2 1.000000000000000 100000000.000000000000000 &Height: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter doubleHeight 0 1.000000000000000 9999.000000000000000 Resolution: 1.000000000000000 100000000.000000000000000 pixels-per-inch ppi W&idth: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter doubleWidth Portrait ... true true true true Qt::Horizontal QSizePolicy::Expanding 191 61 Clipboard 75 75 250 250 QFrame::StyledPanel TextLabel Qt::Vertical 20 40 &Name: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter txtName untitled-1 0 0 Color 0 0 Content Layers: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Ima&ge Background Opacity: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter sliderOpacity 0 0 1 200 2 &Image Background Color: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter cmbColor Background: Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing &Description: Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing txtDescription 0 0 16777215 100 As fi&rst layer As ca&nvas color - + 0 0 50 0 Reset the image background color in the Image Properties dialog 255 255 255 255 255 255 QFrame::NoFrame QFrame::Plain 0 0 0 0 Qt::Vertical 20 40 label_4 lblBackgroundStyle txtDescription lblDescription intNumLayers opacityPanel lblColor cmbColor lblOpacity Qt::Vertical QSizePolicy::Expanding 10 10 Qt::Horizontal QSizePolicy::Expanding 480 10 &Create true true - KisColorSpaceSelector - QWidget -
widgets/kis_color_space_selector.h
- 1 -
- - KisDoubleParseSpinBox - QDoubleSpinBox -
kis_double_parse_spin_box.h
+ KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
- KColorButton + KisColorButton QPushButton -
kcolorbutton.h
- 1 +
kis_color_button.h
KisDoubleSliderSpinBox QWidget
kis_slider_spin_box.h
1
- KisIntParseSpinBox - QSpinBox -
kis_int_parse_spin_box.h
+ KisColorSpaceSelector + QWidget +
widgets/kis_color_space_selector.h
+ 1 +
+ + KisDoubleParseSpinBox + QDoubleSpinBox +
kis_double_parse_spin_box.h
tabWidget txtName cmbPredefined txtPredefinedName bnSaveAsPredefined doubleWidth doubleHeight doubleResolution cmbWidthUnit cmbHeightUnit bnLandscape bnPortrait createButton intNumLayers cmbColor radioBackgroundAsLayer radioBackgroundAsProjection txtDescription
diff --git a/libs/ui/forms/wdgpaintactioneditor.ui b/libs/ui/forms/wdgpaintactioneditor.ui index 5e82cc60a0..deac79f578 100644 --- a/libs/ui/forms/wdgpaintactioneditor.ui +++ b/libs/ui/forms/wdgpaintactioneditor.ui @@ -1,202 +1,207 @@ WdgPaintActionEditor 0 0 405 376 0 Options Paint color: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - 0 - 0 - - - - ... - - - Background color: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - 0 - 0 - - - - ... - - - Qt::Vertical 236 147 Opacity: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 0 100 true + + + + + 0 + 0 + + + + ... + + + + + + + + 0 + 0 + + + + ... + + + Current preset Paint op: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 0 4 QFrame::StyledPanel QFrame::Raised Preset Collection 4 4 + + KisColorButton + QPushButton +
kis_color_button.h
+
KisIntParseSpinBox QSpinBox
kis_int_parse_spin_box.h
KisPresetChooser QWidget
widgets/kis_preset_chooser.h
1
KisNodeQueryPathEditor QWidget
recorder/kis_node_query_path_editor.h
1
diff --git a/libs/ui/kis_autogradient.cc b/libs/ui/kis_autogradient.cc index 733a8ce970..8786ee5e94 100644 --- a/libs/ui/kis_autogradient.cc +++ b/libs/ui/kis_autogradient.cc @@ -1,177 +1,171 @@ /* * Copyright (c) 2004 Cyrille Berger * 2004 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_autogradient.h" #include #include #include #include #include #include #include "kis_debug.h" #include "widgets/kis_gradient_slider_widget.h" /****************************** KisAutogradient ******************************/ KisAutogradient::KisAutogradient(KoSegmentGradient* gradient, QWidget *parent, const char* name, const QString& caption) : QWidget(parent), m_autogradientResource(gradient) { setObjectName(name); setupUi(this); setWindowTitle(caption); gradientSlider->setGradientResource(m_autogradientResource); nameedit->setText(gradient->name()); KoGradientSegment* segment = gradientSlider->selectedSegment(); if (segment) { slotSelectedSegment(segment); } connect(nameedit, SIGNAL(editingFinished()), this, SLOT(slotChangedName())); connect(gradientSlider, SIGNAL(sigSelectedSegment(KoGradientSegment*)), SLOT(slotSelectedSegment(KoGradientSegment*))); connect(gradientSlider, SIGNAL(sigChangedSegment(KoGradientSegment*)), SLOT(slotChangedSegment(KoGradientSegment*))); connect(comboBoxColorInterpolationType, SIGNAL(activated(int)), SLOT(slotChangedColorInterpolation(int))); connect(comboBoxInterpolationType, SIGNAL(activated(int)), SLOT(slotChangedInterpolation(int))); - connect(leftColorButton, SIGNAL(changed(const QColor&)), SLOT(slotChangedLeftColor(const QColor&))); - connect(rightColorButton, SIGNAL(changed(const QColor&)), SLOT(slotChangedRightColor(const QColor&))); + connect(leftColorButton, SIGNAL(changed(const KoColor&)), SLOT(slotChangedLeftColor(const KoColor&))); + connect(rightColorButton, SIGNAL(changed(const KoColor&)), SLOT(slotChangedRightColor(const KoColor&))); connect(intNumInputLeftOpacity, SIGNAL(valueChanged(int)), SLOT(slotChangedLeftOpacity(int))); connect(intNumInputRightOpacity, SIGNAL(valueChanged(int)), SLOT(slotChangedRightOpacity(int))); } void KisAutogradient::activate() { paramChanged(); } void KisAutogradient::slotSelectedSegment(KoGradientSegment* segment) { - QColor startColor; - QColor endColor; - segment->startColor().toQColor(&startColor); - segment->endColor().toQColor(&endColor); - - leftColorButton->setColor(startColor); - rightColorButton->setColor(endColor); + leftColorButton->setColor(segment->startColor()); + rightColorButton->setColor(segment->endColor()); comboBoxColorInterpolationType->setCurrentIndex(segment->colorInterpolation()); comboBoxInterpolationType->setCurrentIndex(segment->interpolation()); - int leftOpacity = (startColor.alpha() * 100) / OPACITY_OPAQUE_U8; + int leftOpacity = segment->startColor().opacityF(); intNumInputLeftOpacity->setValue(leftOpacity); intNumInputLeftOpacity->setSuffix(i18n(" %")); - int rightOpacity = (endColor.alpha() * 100) / OPACITY_OPAQUE_U8; + int rightOpacity = segment->endColor().opacityF(); intNumInputRightOpacity->setValue(rightOpacity); intNumInputRightOpacity->setSuffix(i18n(" %")); paramChanged(); } void KisAutogradient::slotChangedSegment(KoGradientSegment*) { paramChanged(); } void KisAutogradient::slotChangedInterpolation(int type) { KoGradientSegment* segment = gradientSlider->selectedSegment(); if (segment) segment->setInterpolation(type); gradientSlider->update(); paramChanged(); } void KisAutogradient::slotChangedColorInterpolation(int type) { KoGradientSegment* segment = gradientSlider->selectedSegment(); if (segment) segment->setColorInterpolation(type); gradientSlider->update(); paramChanged(); } -void KisAutogradient::slotChangedLeftColor(const QColor& color) +void KisAutogradient::slotChangedLeftColor(const KoColor& color) { KoGradientSegment* segment = gradientSlider->selectedSegment(); if (segment) { KoColor c(color, segment->startColor().colorSpace()); c.setOpacity(segment->startColor().opacityU8()); segment->setStartColor(c); } gradientSlider->update(); paramChanged(); } -void KisAutogradient::slotChangedRightColor(const QColor& color) +void KisAutogradient::slotChangedRightColor(const KoColor& color) { KoGradientSegment* segment = gradientSlider->selectedSegment(); if (segment) { - QColor unused; KoColor c(color, segment->endColor().colorSpace()); c.setOpacity(segment->endColor().opacityU8()); segment->setEndColor(c); } gradientSlider->repaint(); paramChanged(); } void KisAutogradient::slotChangedLeftOpacity(int value) { KoGradientSegment* segment = gradientSlider->selectedSegment(); if (segment) { - KoColor c(segment->startColor().toQColor(), segment->startColor().colorSpace()); + KoColor c(segment->startColor(), segment->startColor().colorSpace()); c.setOpacity(qreal(value) / qreal(100.0)); segment->setStartColor(c); } gradientSlider->repaint(); paramChanged(); } void KisAutogradient::slotChangedRightOpacity(int value) { KoGradientSegment* segment = gradientSlider->selectedSegment(); if (segment) { - KoColor c(segment->endColor().toQColor(), segment->endColor().colorSpace()); + KoColor c(segment->endColor(), segment->endColor().colorSpace()); c.setOpacity(quint8((value *OPACITY_OPAQUE_U8) / 100)); segment->setEndColor(c); } gradientSlider->repaint(); paramChanged(); } void KisAutogradient::slotChangedName() { m_autogradientResource->setName(nameedit->text()); } void KisAutogradient::paramChanged() { m_autogradientResource->updatePreview(); } diff --git a/libs/ui/kis_autogradient.h b/libs/ui/kis_autogradient.h index 2228fdc315..0684fe7a80 100644 --- a/libs/ui/kis_autogradient.h +++ b/libs/ui/kis_autogradient.h @@ -1,50 +1,50 @@ /* * Copyright (c) 2004 Cyrille Berger * 2004 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_AUTOGRADIENT_H_ #define _KIS_AUTOGRADIENT_H_ #include "ui_wdgautogradient.h" class KoGradientSegment; class KoSegmentGradient; class KisAutogradient : public QWidget, public Ui::KisWdgAutogradient { Q_OBJECT public: KisAutogradient(KoSegmentGradient* gradient, QWidget *parent, const char* name, const QString& caption); void activate(); private: KoSegmentGradient* m_autogradientResource; private Q_SLOTS: void slotSelectedSegment(KoGradientSegment* segment); void slotChangedSegment(KoGradientSegment* segment); void slotChangedInterpolation(int type); void slotChangedColorInterpolation(int type); - void slotChangedLeftColor(const QColor& color); - void slotChangedRightColor(const QColor& color); + void slotChangedLeftColor(const KoColor& color); + void slotChangedRightColor(const KoColor& color); void slotChangedLeftOpacity(int value); void slotChangedRightOpacity(int value); void slotChangedName(); void paramChanged(); }; #endif diff --git a/libs/ui/kis_control_frame.cpp b/libs/ui/kis_control_frame.cpp index e55ed00475..f4c1818cce 100644 --- a/libs/ui/kis_control_frame.cpp +++ b/libs/ui/kis_control_frame.cpp @@ -1,224 +1,239 @@ /* * kis_control_frame.cc - part of Krita * * Copyright (c) 1999 Matthias Elter * Copyright (c) 2003 Patrick Julien * Copyright (c) 2004 Sven Langkamp * Copyright (c) 2006 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details.g * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_control_frame.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include #include #include "kis_resource_server_provider.h" #include "kis_canvas_resource_provider.h" #include "widgets/kis_iconwidget.h" #include "widgets/kis_gradient_chooser.h" #include "KisViewManager.h" #include "kis_config.h" #include "kis_paintop_box.h" #include "kis_custom_pattern.h" #include "widgets/kis_pattern_chooser.h" #include "kis_favorite_resource_manager.h" #include "kis_display_color_converter.h" #include +#include KisControlFrame::KisControlFrame(KisViewManager *view, QWidget *parent, const char* name) : QObject(view) , m_viewManager(view) , m_patternWidget(0) , m_gradientWidget(0) , m_patternChooserPopup(0) , m_gradientChooserPopup(0) , m_paintopBox(0) { setObjectName(name); KisConfig cfg; m_font = QFontDatabase::systemFont(QFontDatabase::GeneralFont); m_patternWidget = new KisIconWidget(parent, "patterns"); m_patternWidget->setToolTip(i18n("Fill Patterns")); m_patternWidget->setFixedSize(32, 32); m_gradientWidget = new KisIconWidget(parent, "gradients"); m_gradientWidget->setToolTip(i18n("Gradients")); m_gradientWidget->setFixedSize(32, 32); KoResourceServer * rserver = KoResourceServerProvider::instance()->gradientServer(false); QSharedPointer adapter (new KoResourceServerAdapter(rserver)); m_gradientWidget->setResourceAdapter(adapter); } void KisControlFrame::setup(QWidget *parent) { createPatternsChooser(m_viewManager); createGradientsChooser(m_viewManager); QWidgetAction *action = new QWidgetAction(this); action->setText(i18n("&Patterns")); m_viewManager->actionCollection()->addAction("patterns", action); action->setDefaultWidget(m_patternWidget); action = new QWidgetAction(this); action->setText(i18n("&Gradients")); m_viewManager->actionCollection()->addAction("gradients", action); action->setDefaultWidget(m_gradientWidget); // XXX: KOMVC we don't have a canvas here yet, needs a setImageView const KoColorDisplayRendererInterface *displayRenderer = \ KisDisplayColorConverter::dumbConverterInstance()->displayRendererInterface(); - KoDualColorButton * dual = new KoDualColorButton(m_viewManager->resourceProvider()->fgColor(), + m_dual = new KoDualColorButton(m_viewManager->resourceProvider()->fgColor(), m_viewManager->resourceProvider()->bgColor(), displayRenderer, m_viewManager->mainWindow(), m_viewManager->mainWindow()); - dual->setPopDialog(true); + m_dual->setPopDialog(true); action = new QWidgetAction(this); action->setText(i18n("&Color")); m_viewManager->actionCollection()->addAction("dual", action); - action->setDefaultWidget(dual); - connect(dual, SIGNAL(foregroundColorChanged(KoColor)), m_viewManager->resourceProvider(), SLOT(slotSetFGColor(KoColor))); - connect(dual, SIGNAL(backgroundColorChanged(KoColor)), m_viewManager->resourceProvider(), SLOT(slotSetBGColor(KoColor))); - connect(m_viewManager->resourceProvider(), SIGNAL(sigFGColorChanged(KoColor)), dual, SLOT(setForegroundColor(KoColor))); - connect(m_viewManager->resourceProvider(), SIGNAL(sigBGColorChanged(KoColor)), dual, SLOT(setBackgroundColor(KoColor))); + action->setDefaultWidget(m_dual); + connect(m_dual, SIGNAL(foregroundColorChanged(KoColor)), m_viewManager->resourceProvider(), SLOT(slotSetFGColor(KoColor))); + connect(m_dual, SIGNAL(backgroundColorChanged(KoColor)), m_viewManager->resourceProvider(), SLOT(slotSetBGColor(KoColor))); + connect(m_viewManager->resourceProvider(), SIGNAL(sigFGColorChanged(KoColor)), m_dual, SLOT(setForegroundColor(KoColor))); + connect(m_viewManager->resourceProvider(), SIGNAL(sigBGColorChanged(KoColor)), m_dual, SLOT(setBackgroundColor(KoColor))); connect(m_viewManager->resourceProvider(), SIGNAL(sigFGColorChanged(KoColor)), m_gradientWidget, SLOT(update())); connect(m_viewManager->resourceProvider(), SIGNAL(sigBGColorChanged(KoColor)), m_gradientWidget, SLOT(update())); - dual->setFixedSize(28, 28); + m_dual->setFixedSize(28, 28); + connect(m_viewManager, SIGNAL(viewChanged()), SLOT(slotUpdateDisplayRenderer())); m_paintopBox = new KisPaintopBox(m_viewManager, parent, "paintopbox"); action = new QWidgetAction(this); action->setText(i18n("&Painter's Tools")); m_viewManager->actionCollection()->addAction("paintops", action); action->setDefaultWidget(m_paintopBox); } +void KisControlFrame::slotUpdateDisplayRenderer() +{ + if (m_viewManager->canvasBase()){ + m_dual->setDisplayRenderer(m_viewManager->canvasBase()->displayColorConverter()->displayRendererInterface()); + m_dual->setColorSpace(m_viewManager->canvasBase()->image()->colorSpace()); + m_viewManager->canvasBase()->image()->disconnect(m_dual); + connect(m_viewManager->canvasBase()->image(), SIGNAL(sigColorSpaceChanged(const KoColorSpace*)), m_dual, SLOT(setColorSpace(const KoColorSpace*)), Qt::UniqueConnection); + } else if (m_viewManager->viewCount()==0) { + m_dual->setDisplayRenderer(); + } +} + void KisControlFrame::slotSetPattern(KoPattern * pattern) { m_patternWidget->slotSetItem(pattern); m_patternChooser->setCurrentPattern(pattern); } void KisControlFrame::slotSetGradient(KoAbstractGradient * gradient) { m_gradientWidget->slotSetItem(gradient); } void KisControlFrame::createPatternsChooser(KisViewManager * view) { if (m_patternChooserPopup) delete m_patternChooserPopup; m_patternChooserPopup = new QWidget(m_patternWidget); m_patternChooserPopup->setObjectName("pattern_chooser_popup"); QHBoxLayout * l2 = new QHBoxLayout(m_patternChooserPopup); l2->setObjectName("patternpopuplayout"); m_patternsTab = new QTabWidget(m_patternChooserPopup); m_patternsTab->setObjectName("patternstab"); m_patternsTab->setFocusPolicy(Qt::NoFocus); m_patternsTab->setFont(m_font); l2->addWidget(m_patternsTab); m_patternChooser = new KisPatternChooser(m_patternChooserPopup); m_patternChooser->setFont(m_font); QWidget *patternChooserPage = new QWidget(m_patternChooserPopup); QHBoxLayout *patternChooserPageLayout = new QHBoxLayout(patternChooserPage); patternChooserPageLayout->addWidget(m_patternChooser); m_patternsTab->addTab(patternChooserPage, i18n("Patterns")); KisCustomPattern* customPatterns = new KisCustomPattern(0, "custompatterns", i18n("Custom Pattern"), m_viewManager); customPatterns->setFont(m_font); m_patternsTab->addTab(customPatterns, i18n("Custom Pattern")); connect(m_patternChooser, SIGNAL(resourceSelected(KoResource*)), view->resourceProvider(), SLOT(slotPatternActivated(KoResource*))); connect(customPatterns, SIGNAL(activatedResource(KoResource*)), view->resourceProvider(), SLOT(slotPatternActivated(KoResource*))); connect(view->resourceProvider(), SIGNAL(sigPatternChanged(KoPattern*)), this, SLOT(slotSetPattern(KoPattern*))); m_patternChooser->setCurrentItem(0, 0); if (m_patternChooser->currentResource() && view->resourceProvider()) { view->resourceProvider()->slotPatternActivated(m_patternChooser->currentResource()); } m_patternWidget->setPopupWidget(m_patternChooserPopup); } void KisControlFrame::createGradientsChooser(KisViewManager * view) { if (m_gradientChooserPopup) delete m_gradientChooserPopup; m_gradientChooserPopup = new QWidget(m_gradientWidget); m_gradientChooserPopup->setObjectName("gradient_chooser_popup"); QHBoxLayout * l2 = new QHBoxLayout(m_gradientChooserPopup); l2->setObjectName("gradientpopuplayout"); m_gradientTab = new QTabWidget(m_gradientChooserPopup); m_gradientTab->setObjectName("gradientstab"); m_gradientTab->setFocusPolicy(Qt::NoFocus); m_gradientTab->setFont(m_font); l2->addWidget(m_gradientTab); m_gradientChooser = new KisGradientChooser(m_gradientChooserPopup); m_gradientChooser->setFont(m_font); m_gradientTab->addTab(m_gradientChooser, i18n("Gradients")); connect(m_gradientChooser, SIGNAL(resourceSelected(KoResource*)), view->resourceProvider(), SLOT(slotGradientActivated(KoResource*))); connect(view->resourceProvider(), SIGNAL(sigGradientChanged(KoAbstractGradient*)), this, SLOT(slotSetGradient(KoAbstractGradient*))); m_gradientChooser->setCurrentItem(0, 0); if (m_gradientChooser->currentResource() && view->resourceProvider()) view->resourceProvider()->slotGradientActivated(m_gradientChooser->currentResource()); m_gradientWidget->setPopupWidget(m_gradientChooserPopup); } diff --git a/libs/ui/kis_control_frame.h b/libs/ui/kis_control_frame.h index dea70f740e..f07c7246c7 100644 --- a/libs/ui/kis_control_frame.h +++ b/libs/ui/kis_control_frame.h @@ -1,91 +1,95 @@ /* * kis_control_frame.h - part of Krita * * Copyright (c) 1999 Matthias Elter * Copyright (c) 2003 Patrick Julien * Copyright (c) 2004 Sven Langkamp * Copyright (c) 2003-2008 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __kis_control_frame_h__ #define __kis_control_frame_h__ #include #include #include class QWidget; class QTabWidget; class KoAbstractGradient; class KisGradientChooser; class KisPatternChooser; class KisPaintopBox; class KisViewManager; class KisIconWidget; class KoPattern; +class KoDualColorButton; /** * Control Frame - status display with access to * color selector, gradient, patterns, and paintop presets */ class KisControlFrame : public QObject { Q_OBJECT public: KisControlFrame(KisViewManager *view, QWidget *parent = 0, const char *name = 0); virtual ~KisControlFrame() {} void setup(QWidget *parent); KisPaintopBox* paintopBox() { return m_paintopBox; } private Q_SLOTS: void slotSetPattern(KoPattern * pattern); void slotSetGradient(KoAbstractGradient * gradient); + void slotUpdateDisplayRenderer(); private: void createPatternsChooser(KisViewManager * view); void createGradientsChooser(KisViewManager * view); private: QFont m_font; KisViewManager *m_viewManager; QTabWidget *m_gradientTab; QTabWidget *m_patternsTab; KisIconWidget *m_patternWidget; KisIconWidget *m_gradientWidget; QWidget *m_patternChooserPopup; QWidget *m_gradientChooserPopup; KisGradientChooser *m_gradientChooser; KisPatternChooser *m_patternChooser; KisPaintopBox *m_paintopBox; + KoDualColorButton *m_dual; + }; #endif diff --git a/libs/ui/kis_custom_pattern.cc b/libs/ui/kis_custom_pattern.cc index 2ff668991d..dc0e15a8ba 100644 --- a/libs/ui/kis_custom_pattern.cc +++ b/libs/ui/kis_custom_pattern.cc @@ -1,175 +1,193 @@ /* * Copyright (c) 2006 Bart Coppens * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_custom_pattern.h" #include #include #include #include #include #include #include #include #include #include "KisDocument.h" #include "KisViewManager.h" #include "kis_image.h" #include "kis_layer.h" #include "kis_paint_device.h" +#include "kis_selection.h" +#include "kis_painter.h" #include #include "kis_resource_server_provider.h" #include "kis_paint_layer.h" KisCustomPattern::KisCustomPattern(QWidget *parent, const char* name, const QString& caption, KisViewManager* view) : KisWdgCustomPattern(parent, name), m_view(view) { Q_ASSERT(m_view); setWindowTitle(caption); m_pattern = 0; preview->setScaledContents(true); KoResourceServer* rServer = KoResourceServerProvider::instance()->patternServer(false); m_rServerAdapter = QSharedPointer(new KoResourceServerAdapter(rServer)); connect(addButton, SIGNAL(pressed()), this, SLOT(slotAddPredefined())); connect(patternButton, SIGNAL(pressed()), this, SLOT(slotUsePattern())); connect(updateButton, SIGNAL(pressed()), this, SLOT(slotUpdateCurrentPattern())); connect(cmbSource, SIGNAL(currentIndexChanged(int)), this, SLOT(slotUpdateCurrentPattern())); } KisCustomPattern::~KisCustomPattern() { delete m_pattern; } void KisCustomPattern::slotUpdateCurrentPattern() { delete m_pattern; m_pattern = 0; if (m_view && m_view->image()) { createPattern(); if (m_pattern) { const qint32 maxSize = 150; if ((m_pattern->width() > maxSize) || (m_pattern->height() > maxSize)) { float aspectRatio = (float)m_pattern->width() / m_pattern->height(); qint32 scaledWidth, scaledHeight; if (m_pattern->width() > m_pattern->height()) { scaledWidth = maxSize; scaledHeight = maxSize / aspectRatio; } else { scaledWidth = maxSize * aspectRatio; scaledHeight = maxSize; } if (scaledWidth == 0) scaledWidth++; if (scaledHeight == 0) scaledHeight++; QPixmap scaledPixmap = QPixmap::fromImage(m_pattern->pattern()); preview->setPixmap(scaledPixmap.scaled(scaledWidth, scaledHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation)); } else { preview->setPixmap(QPixmap::fromImage(m_pattern->pattern())); } } } } void KisCustomPattern::slotAddPredefined() { if (!m_pattern) return; // Save in the directory that is likely to be: ~/.kde/share/apps/krita/patterns // a unique file with this pattern name QString dir = KoResourceServerProvider::instance()->patternServer()->saveLocation(); QString extension; QString tempFileName; { QTemporaryFile file(dir + QLatin1String("/krita_XXXXXX") + QLatin1String(".pat") ); file.setAutoRemove(false); file.open(); tempFileName = file.fileName(); } // Save it to that file m_pattern->setFilename(tempFileName); // Add it to the pattern server, so that it automatically gets to the mediators, and // so to the other pattern choosers can pick it up, if they want to m_rServerAdapter->addResource(m_pattern->clone()); } void KisCustomPattern::slotUsePattern() { if (!m_pattern) return; KoPattern* copy = m_pattern->clone(); Q_CHECK_PTR(copy); emit(activatedResource(copy)); } void KisCustomPattern::createPattern() { if (!m_view) return; KisPaintDeviceSP dev; + KisPaintDeviceSP cache; QString name; KisImageWSP image = m_view->image(); if (!image) return; QRect rc = image->bounds(); if (cmbSource->currentIndex() == 0) { dev = m_view->activeNode()->projection(); name = m_view->activeNode()->name(); QRect rc2 = dev->exactBounds(); rc = rc.intersected(rc2); } else { image->lock(); dev = image->projection(); image->unlock(); name = image->objectName(); } if (!dev) return; + + if(m_view->selection()) { + KisSelectionSP selection = m_view->selection(); + QRect selectionRect = selection->selectedExactRect(); + cache = dev->createCompositionSourceDevice(); + KisPainter gc(cache); + gc.setSelection(selection); + gc.bitBlt(selectionRect.topLeft(), dev, selectionRect); + rc = selectionRect; + } else { + cache = dev; + } + if (!cache) return; + + // warn when creating large patterns QSize size = rc.size(); if (size.width() > 1000 || size.height() > 1000) { lblWarning->setText(i18n("The current image is too big to create a pattern. " "The pattern will be scaled down.")); size.scale(1000, 1000, Qt::KeepAspectRatio); } QString dir = KoResourceServerProvider::instance()->patternServer()->saveLocation(); - m_pattern = new KoPattern(dev->createThumbnail(size.width(), size.height(), rc, /*oversample*/ 1, + m_pattern = new KoPattern(cache->createThumbnail(size.width(), size.height(), rc, /*oversample*/ 1, KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags()), name, dir); } diff --git a/libs/ui/kis_popup_palette.cpp b/libs/ui/kis_popup_palette.cpp index e7c8988417..98db88bf13 100644 --- a/libs/ui/kis_popup_palette.cpp +++ b/libs/ui/kis_popup_palette.cpp @@ -1,610 +1,627 @@ /* This file is part of the KDE project Copyright 2009 Vera Lukman Copyright 2011 Sven Langkamp This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_config.h" #include "kis_popup_palette.h" #include "kis_paintop_box.h" #include "kis_favorite_resource_manager.h" #include "kis_icon_utils.h" #include #include "kis_resource_server_provider.h" #include +#include +#include #include "KoColorSpaceRegistry.h" #include #include #include #include #include #include #include #include #include "kis_signal_compressor.h" #include #include "brushhud/kis_brush_hud.h" #include "brushhud/kis_round_hud_button.h" #define colorInnerRadius 72.0 #define colorOuterRadius 92.0 #define maxbrushRadius 42.0 #define widgetSize (colorOuterRadius*2+maxbrushRadius*4) #define widgetMargin 20.0 #define hudMargin 30.0 #define _USE_MATH_DEFINES 1 #include class PopupColorTriangle : public KoTriangleColorSelector { public: PopupColorTriangle(const KoColorDisplayRendererInterface *displayRenderer, QWidget* parent) : KoTriangleColorSelector(displayRenderer, parent) , m_dragging(false) { } virtual ~PopupColorTriangle() {} void tabletEvent(QTabletEvent* event) { event->accept(); QMouseEvent* mouseEvent = 0; switch (event->type()) { case QEvent::TabletPress: mouseEvent = new QMouseEvent(QEvent::MouseButtonPress, event->pos(), Qt::LeftButton, Qt::LeftButton, event->modifiers()); m_dragging = true; mousePressEvent(mouseEvent); break; case QEvent::TabletMove: mouseEvent = new QMouseEvent(QEvent::MouseMove, event->pos(), (m_dragging) ? Qt::LeftButton : Qt::NoButton, (m_dragging) ? Qt::LeftButton : Qt::NoButton, event->modifiers()); mouseMoveEvent(mouseEvent); break; case QEvent::TabletRelease: mouseEvent = new QMouseEvent(QEvent::MouseButtonRelease, event->pos(), Qt::LeftButton, Qt::LeftButton, event->modifiers()); m_dragging = false; mouseReleaseEvent(mouseEvent); break; default: break; } delete mouseEvent; } private: bool m_dragging; }; KisPopupPalette::KisPopupPalette(KisFavoriteResourceManager* manager, const KoColorDisplayRendererInterface *displayRenderer, KisCanvasResourceProvider *provider, QWidget *parent) : QWidget(parent, Qt::FramelessWindowHint) , m_resourceManager(manager) , m_triangleColorSelector(0) , m_timer(0) , m_displayRenderer(displayRenderer) , m_colorChangeCompressor(new KisSignalCompressor(50, KisSignalCompressor::POSTPONE)) , m_brushHud(0) { const int borderWidth = 3; - m_triangleColorSelector = new PopupColorTriangle(displayRenderer, this); + //m_triangleColorSelector = new PopupColorTriangle(displayRenderer, this); + m_triangleColorSelector = new KisVisualColorSelector(this); + m_triangleColorSelector->setDisplayRenderer(displayRenderer); + m_triangleColorSelector->setConfig(true,false); m_triangleColorSelector->move(widgetSize/2-colorInnerRadius+borderWidth, widgetSize/2-colorInnerRadius+borderWidth); m_triangleColorSelector->resize(colorInnerRadius*2-borderWidth*2, colorInnerRadius*2-borderWidth*2); m_triangleColorSelector->setVisible(true); + m_triangleColorSelector->slotSetColor(KoColor()); QRegion maskedRegion(0, 0, m_triangleColorSelector->width(), m_triangleColorSelector->height(), QRegion::Ellipse ); m_triangleColorSelector->setMask(maskedRegion); //setAttribute(Qt::WA_TranslucentBackground, true); - connect(m_triangleColorSelector, SIGNAL(realColorChanged(KoColor)), + connect(m_triangleColorSelector, SIGNAL(sigNewColor(KoColor)), m_colorChangeCompressor.data(), SLOT(start())); connect(m_colorChangeCompressor.data(), SIGNAL(timeout()), SLOT(slotEmitColorChanged())); + connect(KisConfigNotifier::instance(), SIGNAL(configChanged()), m_triangleColorSelector, SLOT(ConfigurationChanged())); + connect(m_resourceManager, SIGNAL(sigChangeFGColorSelector(KoColor)), SLOT(slotExternalFgColorChanged(KoColor))); connect(this, SIGNAL(sigChangefGColor(KoColor)), m_resourceManager, SIGNAL(sigSetFGColor(KoColor))); connect(this, SIGNAL(sigChangeActivePaintop(int)), m_resourceManager, SLOT(slotChangeActivePaintop(int))); connect(this, SIGNAL(sigUpdateRecentColor(int)), m_resourceManager, SLOT(slotUpdateRecentColor(int))); connect(m_resourceManager, SIGNAL(setSelectedColor(int)), SLOT(slotSetSelectedColor(int))); connect(m_resourceManager, SIGNAL(updatePalettes()), SLOT(slotUpdate())); connect(m_resourceManager, SIGNAL(hidePalettes()), SLOT(slotHide())); // This is used to handle a bug: // If pop up palette is visible and a new colour is selected, the new colour // will be added when the user clicks on the canvas to hide the palette // In general, we want to be able to store recent color if the pop up palette // is not visible m_timer = new QTimer(this); m_timer->setSingleShot(true); connect(this, SIGNAL(sigTriggerTimer()), this, SLOT(slotTriggerTimer())); connect(m_timer, SIGNAL(timeout()), this, SLOT(slotEnableChangeFGColor())); connect(this, SIGNAL(sigEnableChangeFGColor(bool)), m_resourceManager, SIGNAL(sigEnableChangeColor(bool))); setCursor(Qt::ArrowCursor); setMouseTracking(true); setHoveredPreset(-1); setHoveredColor(-1); setSelectedColor(-1); m_brushHud = new KisBrushHud(provider, parent); m_brushHud->setMaximumHeight(widgetSize); m_brushHud->setVisible(false); const int auxButtonSize = 35; m_settingsButton = new KisRoundHudButton(this); m_settingsButton->setIcon(KisIconUtils::loadIcon("configure")); m_settingsButton->setGeometry(widgetSize - 2.2 * auxButtonSize, widgetSize - auxButtonSize, auxButtonSize, auxButtonSize); connect(m_settingsButton, SIGNAL(clicked()), SLOT(slotShowTagsPopup())); KisConfig cfg; m_brushHudButton = new KisRoundHudButton(this); m_brushHudButton->setCheckable(true); m_brushHudButton->setOnOffIcons(KisIconUtils::loadIcon("arrow-left"), KisIconUtils::loadIcon("arrow-right")); m_brushHudButton->setGeometry(widgetSize - 1.0 * auxButtonSize, widgetSize - auxButtonSize, auxButtonSize, auxButtonSize); connect(m_brushHudButton, SIGNAL(toggled(bool)), SLOT(showHudWidget(bool))); m_brushHudButton->setChecked(cfg.showBrushHud()); setVisible(true); setVisible(false); } void KisPopupPalette::slotExternalFgColorChanged(const KoColor &color) { - m_triangleColorSelector->setRealColor(color); + //m_triangleColorSelector->setRealColor(color); + //hack to get around cmyk for now. + if (color.colorSpace()->colorChannelCount()>3) { + KoColor c(KoColorSpaceRegistry::instance()->rgb8()); + c.fromKoColor(color); + m_triangleColorSelector->slotSetColor(c); + } else { + m_triangleColorSelector->slotSetColor(color); + } + } void KisPopupPalette::slotEmitColorChanged() { if (isVisible()) { update(); - emit sigChangefGColor(m_triangleColorSelector->realColor()); + emit sigChangefGColor(m_triangleColorSelector->getCurrentColor()); } } //setting KisPopupPalette properties int KisPopupPalette::hoveredPreset() const { return m_hoveredPreset; } void KisPopupPalette::setHoveredPreset(int x) { m_hoveredPreset = x; } int KisPopupPalette::hoveredColor() const { return m_hoveredColor; } void KisPopupPalette::setHoveredColor(int x) { m_hoveredColor = x; } int KisPopupPalette::selectedColor() const { return m_selectedColor; } void KisPopupPalette::setSelectedColor(int x) { m_selectedColor = x; } void KisPopupPalette::slotTriggerTimer() { m_timer->start(750); } void KisPopupPalette::slotEnableChangeFGColor() { emit sigEnableChangeFGColor(true); } void KisPopupPalette::adjustLayout(const QPoint &p) { KIS_ASSERT_RECOVER_RETURN(m_brushHud); if (isVisible() && parentWidget()) { const QRect fitRect = kisGrowRect(parentWidget()->rect(), -widgetMargin); const QPoint paletteCenterOffset(width() / 2, height() / 2); QRect paletteRect = rect(); paletteRect.moveTo(p - paletteCenterOffset); if (m_brushHudButton->isChecked()) { m_brushHud->updateGeometry(); paletteRect.adjust(0, 0, m_brushHud->width() + hudMargin, 0); } paletteRect = kisEnsureInRect(paletteRect, fitRect); move(paletteRect.topLeft()); m_brushHud->move(paletteRect.topLeft() + QPoint(widgetSize + hudMargin, 0)); m_lastCenterPoint = p; } } void KisPopupPalette::showHudWidget(bool visible) { KIS_ASSERT_RECOVER_RETURN(m_brushHud); const bool reallyVisible = visible && m_brushHudButton->isChecked(); if (reallyVisible) { m_brushHud->updateProperties(); } m_brushHud->setVisible(reallyVisible); adjustLayout(m_lastCenterPoint); KisConfig cfg; cfg.setShowBrushHud(visible); } void KisPopupPalette::showPopupPalette(const QPoint &p) { showPopupPalette(!isVisible()); adjustLayout(p); } void KisPopupPalette::showPopupPalette(bool show) { if (show) { emit sigEnableChangeFGColor(!show); } else { emit sigTriggerTimer(); } setVisible(show); m_brushHud->setVisible(show && m_brushHudButton->isChecked()); } //redefinition of setVariable function to change the scope to private void KisPopupPalette::setVisible(bool b) { QWidget::setVisible(b); } QSize KisPopupPalette::sizeHint() const { return QSize(widgetSize, widgetSize); } void KisPopupPalette::resizeEvent(QResizeEvent*) { } void KisPopupPalette::paintEvent(QPaintEvent* e) { Q_UNUSED(e); float rotationAngle = 0.0; QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); painter.setRenderHint(QPainter::SmoothPixmapTransform); painter.translate(width() / 2, height() / 2); //painting background color QPainterPath bgColor; bgColor.addEllipse(QPoint(-width() / 2 + 24, -height() / 2 + 60), 20, 20); painter.fillPath(bgColor, m_displayRenderer->toQColor(m_resourceManager->bgColor())); painter.drawPath(bgColor); //painting foreground color QPainterPath fgColor; fgColor.addEllipse(QPoint(-width() / 2 + 50, -height() / 2 + 32), 30, 30); - painter.fillPath(fgColor, m_displayRenderer->toQColor(m_triangleColorSelector->realColor())); + painter.fillPath(fgColor, m_displayRenderer->toQColor(m_triangleColorSelector->getCurrentColor())); painter.drawPath(fgColor); // create an ellipse for the background that is slightly // smaller than the clipping mask. This will prevent aliasing QPainterPath backgroundContainer; backgroundContainer.addEllipse( -colorOuterRadius, -colorOuterRadius, colorOuterRadius*2, colorOuterRadius*2 ); painter.fillPath(backgroundContainer,palette().brush(QPalette::Window)); painter.drawPath(backgroundContainer); //painting favorite brushes QList images(m_resourceManager->favoritePresetImages()); //painting favorite brushes pixmap/icon QPainterPath path; for (int pos = 0; pos < numSlots(); pos++) { painter.save(); path = pathFromPresetIndex(pos); if (pos < images.size()) { painter.setClipPath(path); QRect bounds = path.boundingRect().toAlignedRect(); painter.drawImage(bounds.topLeft() , images.at(pos).scaled(bounds.size() , Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation)); } else { painter.fillPath(path, palette().brush(QPalette::Window)); } QPen pen = painter.pen(); pen.setWidth(3); painter.setPen(pen); painter.drawPath(path); painter.restore(); } if (hoveredPreset() > -1) { path = pathFromPresetIndex(hoveredPreset()); QPen pen(palette().color(QPalette::Highlight)); pen.setWidth(3); painter.setPen(pen); painter.drawPath(path); } //painting recent colors painter.setPen(Qt::NoPen); rotationAngle = -360.0 / m_resourceManager->recentColorsTotal(); KoColor kocolor; for (int pos = 0; pos < m_resourceManager->recentColorsTotal(); pos++) { QPainterPath path(drawDonutPathAngle(colorInnerRadius, colorOuterRadius, m_resourceManager->recentColorsTotal())); //accessing recent color of index pos kocolor = m_resourceManager->recentColorAt(pos); painter.fillPath(path, m_displayRenderer->toQColor(kocolor)); painter.drawPath(path); painter.rotate(rotationAngle); } painter.setBrush(Qt::transparent); if (m_resourceManager->recentColorsTotal() == 0) { QPainterPath path_ColorDonut(drawDonutPathFull(0, 0, colorInnerRadius, colorOuterRadius)); painter.setPen(QPen(palette().color(QPalette::Window).darker(130), 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin)); painter.drawPath(path_ColorDonut); } //painting hovered color if (hoveredColor() > -1) { painter.setPen(QPen(palette().color(QPalette::Highlight), 2, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin)); if (m_resourceManager->recentColorsTotal() == 1) { QPainterPath path_ColorDonut(drawDonutPathFull(0, 0, colorInnerRadius, colorOuterRadius)); painter.drawPath(path_ColorDonut); } else { painter.rotate((m_resourceManager->recentColorsTotal() + hoveredColor()) *rotationAngle); QPainterPath path(drawDonutPathAngle(colorInnerRadius, colorOuterRadius, m_resourceManager->recentColorsTotal())); painter.drawPath(path); painter.rotate(hoveredColor() * -1 * rotationAngle); } } //painting selected color if (selectedColor() > -1) { painter.setPen(QPen(palette().color(QPalette::Highlight).darker(130), 2, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin)); if (m_resourceManager->recentColorsTotal() == 1) { QPainterPath path_ColorDonut(drawDonutPathFull(0, 0, colorInnerRadius, colorOuterRadius)); painter.drawPath(path_ColorDonut); } else { painter.rotate((m_resourceManager->recentColorsTotal() + selectedColor()) *rotationAngle); QPainterPath path(drawDonutPathAngle(colorInnerRadius, colorOuterRadius, m_resourceManager->recentColorsTotal())); painter.drawPath(path); painter.rotate(selectedColor() * -1 * rotationAngle); } } } QPainterPath KisPopupPalette::drawDonutPathFull(int x, int y, int inner_radius, int outer_radius) { QPainterPath path; path.addEllipse(QPointF(x, y), outer_radius, outer_radius); path.addEllipse(QPointF(x, y), inner_radius, inner_radius); path.setFillRule(Qt::OddEvenFill); return path; } QPainterPath KisPopupPalette::drawDonutPathAngle(int inner_radius, int outer_radius, int limit) { QPainterPath path; path.moveTo(-0.999 * outer_radius * sin(M_PI / limit), 0.999 * outer_radius * cos(M_PI / limit)); path.arcTo(-1 * outer_radius, -1 * outer_radius, 2 * outer_radius, 2 * outer_radius, -90.0 - 180.0 / limit, 360.0 / limit); path.arcTo(-1 * inner_radius, -1 * inner_radius, 2 * inner_radius, 2 * inner_radius, -90.0 + 180.0 / limit, - 360.0 / limit); path.closeSubpath(); return path; } void KisPopupPalette::mouseMoveEvent(QMouseEvent* event) { QPointF point = event->posF(); event->accept(); QPainterPath pathColor(drawDonutPathFull(width() / 2, height() / 2, colorInnerRadius, colorOuterRadius)); setToolTip(""); setHoveredPreset(-1); setHoveredColor(-1); { int pos = calculatePresetIndex(point, m_resourceManager->numFavoritePresets()); if (pos >= 0 && pos < m_resourceManager->numFavoritePresets()) { setToolTip(m_resourceManager->favoritePresetList().at(pos).data()->name()); setHoveredPreset(pos); } } if (pathColor.contains(point)) { int pos = calculateIndex(point, m_resourceManager->recentColorsTotal()); if (pos >= 0 && pos < m_resourceManager->recentColorsTotal()) { setHoveredColor(pos); } } update(); } void KisPopupPalette::mousePressEvent(QMouseEvent* event) { QPointF point = event->posF(); event->accept(); if (event->button() == Qt::LeftButton) { //in favorite brushes area int pos = calculateIndex(point, m_resourceManager->numFavoritePresets()); if (pos >= 0 && pos < m_resourceManager->numFavoritePresets() && isPointInPixmap(point, pos)) { //setSelectedBrush(pos); update(); } } } void KisPopupPalette::slotShowTagsPopup() { KisPaintOpPresetResourceServer* rServer = KisResourceServerProvider::instance()->paintOpPresetServer(); QStringList tags = rServer->tagNamesList(); qSort(tags); if (!tags.isEmpty()) { QMenu menu; Q_FOREACH (const QString& tag, tags) { menu.addAction(tag); } QAction* action = menu.exec(QCursor::pos()); if (action) { m_resourceManager->setCurrentTag(action->text()); } } else { QWhatsThis::showText(QCursor::pos(), i18n("There are no tags available to show in this popup. To add presets, you need to tag them and then select the tag here.")); } } void KisPopupPalette::tabletEvent(QTabletEvent* /*event*/) { } void KisPopupPalette::mouseReleaseEvent(QMouseEvent * event) { QPointF point = event->posF(); event->accept(); if (event->button() == Qt::LeftButton || event->button() == Qt::RightButton) { QPainterPath pathColor(drawDonutPathFull(width() / 2, height() / 2, colorInnerRadius, colorOuterRadius)); //in favorite brushes area if (hoveredPreset() > -1) { //setSelectedBrush(hoveredBrush()); emit sigChangeActivePaintop(hoveredPreset()); } if (pathColor.contains(point)) { int pos = calculateIndex(point, m_resourceManager->recentColorsTotal()); if (pos >= 0 && pos < m_resourceManager->recentColorsTotal()) { emit sigUpdateRecentColor(pos); } } } } int KisPopupPalette::calculateIndex(QPointF point, int n) { calculatePresetIndex(point, n); //translate to (0,0) point.setX(point.x() - width() / 2); point.setY(point.y() - height() / 2); //rotate float smallerAngle = M_PI / 2 + M_PI / n - atan2(point.y(), point.x()); float radius = sqrt((float)point.x() * point.x() + point.y() * point.y()); point.setX(radius * cos(smallerAngle)); point.setY(radius * sin(smallerAngle)); //calculate brush index int pos = floor(acos(point.x() / radius) * n / (2 * M_PI)); if (point.y() < 0) pos = n - pos - 1; return pos; } bool KisPopupPalette::isPointInPixmap(QPointF& point, int pos) { if (pathFromPresetIndex(pos).contains(point + QPointF(-width() / 2, -height() / 2))) { return true; } return false; } KisPopupPalette::~KisPopupPalette() { } QPainterPath KisPopupPalette::pathFromPresetIndex(int index) { qreal angleLength = 360.0 / numSlots() / 180 * M_PI; qreal angle = index * angleLength; qreal r = colorOuterRadius * sin(angleLength/2) / ( 1 - sin(angleLength/2)); QPainterPath path; path.addEllipse((colorOuterRadius+r) * cos(angle)-r, -(colorOuterRadius+r) * sin(angle)-r, 2*r, 2*r); path.closeSubpath(); return path; } int KisPopupPalette::calculatePresetIndex(QPointF point, int /*n*/) { for(int i = 0; i < numSlots(); i++) { QPointF adujustedPoint = point - QPointF(width()/2, height()/2); if(pathFromPresetIndex(i).contains(adujustedPoint)) { return i; } } return -1; } int KisPopupPalette::numSlots() { KisConfig config; return qMax(config.favoritePresets(), 10); } diff --git a/libs/ui/kis_popup_palette.h b/libs/ui/kis_popup_palette.h index 0c6f73faf1..a45e3757f8 100644 --- a/libs/ui/kis_popup_palette.h +++ b/libs/ui/kis_popup_palette.h @@ -1,138 +1,139 @@ /* This file is part of the KDE project Copyright 2009 Vera Lukman This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_POPUP_PALETTE_H #define KIS_POPUP_PALETTE_H #include #include #include #include class KisFavoriteResourceManager; class QWidget; class KoColor; class KoTriangleColorSelector; class KisSignalCompressor; class KisBrushHud; class KisRoundHudButton; class KisCanvasResourceProvider; +class KisVisualColorSelector; class KisPopupPalette : public QWidget { Q_OBJECT Q_PROPERTY(int hoveredPreset READ hoveredPreset WRITE setHoveredPreset) Q_PROPERTY(int hoveredColor READ hoveredColor WRITE setHoveredColor) Q_PROPERTY(int selectedColor READ selectedColor WRITE setSelectedColor) public: KisPopupPalette(KisFavoriteResourceManager*, const KoColorDisplayRendererInterface *displayRenderer, KisCanvasResourceProvider *provider, QWidget *parent = 0); ~KisPopupPalette(); QSize sizeHint() const; void showPopupPalette(const QPoint&); void showPopupPalette(bool b); //functions to set up selectedBrush void setSelectedBrush(int x); int selectedBrush() const; //functions to set up selectedColor void setSelectedColor(int x); int selectedColor() const; virtual void tabletEvent(QTabletEvent * event); protected: void paintEvent(QPaintEvent*); void resizeEvent(QResizeEvent*); void mouseReleaseEvent(QMouseEvent*); void mouseMoveEvent(QMouseEvent*); void mousePressEvent(QMouseEvent*); //functions to calculate index of favorite brush or recent color in array //n is the total number of favorite brushes or recent colors int calculateIndex(QPointF, int n); int calculatePresetIndex(QPointF, int n); //functions to set up hoveredBrush void setHoveredPreset(int x); int hoveredPreset() const; //functions to set up hoveredColor void setHoveredColor(int x); int hoveredColor() const; private: void setVisible(bool b); QPainterPath drawDonutPathFull(int, int, int, int); QPainterPath drawDonutPathAngle(int, int, int); bool isPointInPixmap(QPointF&, int pos); QPainterPath pathFromPresetIndex(int index); int numSlots(); void adjustLayout(const QPoint &p); private: int m_hoveredPreset; int m_hoveredColor; int m_selectedColor; KisFavoriteResourceManager* m_resourceManager; - KoTriangleColorSelector* m_triangleColorSelector; + KisVisualColorSelector* m_triangleColorSelector; QTimer* m_timer; const KoColorDisplayRendererInterface *m_displayRenderer; QScopedPointer m_colorChangeCompressor; KisBrushHud *m_brushHud; KisRoundHudButton *m_settingsButton; KisRoundHudButton *m_brushHudButton; QPoint m_lastCenterPoint; Q_SIGNALS: void sigChangeActivePaintop(int); void sigUpdateRecentColor(int); void sigChangefGColor(const KoColor&); // These are used to handle a bug: // If pop up palette is visible and a new colour is selected, the new colour // will be added when the user clicks on the canvas to hide the palette // In general, we want to be able to store recent color if the pop up palette // is not visible void sigEnableChangeFGColor(bool); void sigTriggerTimer(); private Q_SLOTS: void slotExternalFgColorChanged(const KoColor &color); void slotEmitColorChanged(); void slotSetSelectedColor(int x) { setSelectedColor(x); update(); } void slotTriggerTimer(); void slotEnableChangeFGColor(); void slotUpdate() { update(); } void slotHide() { showPopupPalette(false); } void slotShowTagsPopup(); void showHudWidget(bool visible); }; #endif // KIS_POPUP_PALETTE_H diff --git a/libs/ui/layerstyles/WdgColorOverlay.ui b/libs/ui/layerstyles/WdgColorOverlay.ui index cc49103d07..8c71bf73a5 100644 --- a/libs/ui/layerstyles/WdgColorOverlay.ui +++ b/libs/ui/layerstyles/WdgColorOverlay.ui @@ -1,137 +1,136 @@ WdgColorOverlay 0 0 400 300 Color Overlay Color QFormLayout::AllNonFixedFieldsGrow Ble&nd Mode: cmbCompositeOp 0 0 Set the blend mode for the layer - + ... &Opacity: intOpacity 0 0 10 15 Set the master opacity for the layer Adjust the transparency of the layer Qt::Vertical 20 151 - KColorButton + KisColorButton QPushButton -
kcolorbutton.h
- 1 -
- - KisCompositeOpComboBox - QComboBox -
kis_cmb_composite.h
+
kis_color_button.h
KisSliderSpinBox QWidget
kis_slider_spin_box.h
1
+ + KisCompositeOpComboBox + QComboBox +
kis_cmb_composite.h
+
diff --git a/libs/ui/layerstyles/WdgSatin.ui b/libs/ui/layerstyles/WdgSatin.ui index d40f0c8632..31d2567bc3 100644 --- a/libs/ui/layerstyles/WdgSatin.ui +++ b/libs/ui/layerstyles/WdgSatin.ui @@ -1,279 +1,278 @@ WdgSatin 0 0 400 345 Satin Structure Ble&nd Mode: cmbCompositeOp 0 0 Set the blend mode for the layer - + ... Opaci&ty: intOpacity 0 0 10 15 Set the master opacity for the layer Adjust the transparency of the layer An&gle: dialAngle Set the angle of the light source -179 180 true -179 180 &Distance: intDistance 0 0 S&ize: intSize 0 0 Contour: Smooth the contour Anti-aliased &Invert cmbContour chkAntiAliased intOpacity label_13 label_14 label_4 intDistance intSize label label_2 label_6 chkInvert Qt::Vertical 20 40 Qt::Vertical 20 40 + + KisColorButton + QPushButton +
kis_color_button.h
+
KisIntParseSpinBox QSpinBox
kis_int_parse_spin_box.h
KisSliderSpinBox QWidget
kis_slider_spin_box.h
1
- - KColorButton - QPushButton -
kcolorbutton.h
- 1 -
KisCompositeOpComboBox QComboBox
kis_cmb_composite.h
KisCmbContour QWidget
kis_cmb_contour.h
diff --git a/libs/ui/layerstyles/WdgStroke.ui b/libs/ui/layerstyles/WdgStroke.ui index 513eff70e9..bc7a5531b2 100644 --- a/libs/ui/layerstyles/WdgStroke.ui +++ b/libs/ui/layerstyles/WdgStroke.ui @@ -1,441 +1,440 @@ WdgStroke 0 0 - 401 + 406 642 Stroke Structure S&ize: intSize 0 0 Positio&n: cmbPosition 0 0 Outside Inside Center &Blend Mode: cmbCompositeOp 0 0 Opacit&y: intOpacity 0 0 Fill Color Gradient Pattern - 1 + 0 Color: - + ... &Gradient: cmbGradient 0 0 &Reverse St&yle: cmbStyle 0 0 Linear Radial Angle Reflected Diamond Ali&gn with Layer &Angle: dialAngle Set the angle of the light source -179 180 true -179 180 S&cale: intScale 0 0 Set size of gradation Pattern: 0 0 250 250 QFrame::StyledPanel QFrame::Raised Sn&ap to Origin S&cale: intScale Set size of gradation Lin&k with Layer - KColorButton + KisColorButton QPushButton -
kcolorbutton.h
- 1 +
kis_color_button.h
- KisCompositeOpComboBox - QComboBox -
kis_cmb_composite.h
+ KisIntParseSpinBox + QSpinBox +
kis_int_parse_spin_box.h
KisSliderSpinBox QWidget
kis_slider_spin_box.h
1
+ + KisCompositeOpComboBox + QComboBox +
kis_cmb_composite.h
+
KisCmbGradient QToolButton
kis_cmb_gradient.h
KisPatternChooser QFrame
kis_pattern_chooser.h
1
- - KisIntParseSpinBox - QSpinBox -
kis_int_parse_spin_box.h
-
diff --git a/libs/ui/layerstyles/wdgBevelAndEmboss.ui b/libs/ui/layerstyles/wdgBevelAndEmboss.ui index 1f918c085f..1bd4462532 100644 --- a/libs/ui/layerstyles/wdgBevelAndEmboss.ui +++ b/libs/ui/layerstyles/wdgBevelAndEmboss.ui @@ -1,482 +1,481 @@ WdgBevelAndEmboss 0 0 399 541 Bevel and Emboss Structure St&yle: cmbStyle 0 0 Outer Bevel Inner Bevel Emboss Pillow Emboss Stroke Emboss &Technique: cmbTechnique 0 0 Smooth Chisel Hard Chisel Soft &Depth: intDepth 0 0 Direction: 0 0 Up Down Si&ze: intSize 0 0 So&ften: intSoften 0 0 Shading &Angle: dialAngle Set the angle of the light source -179 180 true -179 180 Qt::Vertical 20 18 Use &Global Light -179 180 &Gloss Contour: cmbContour Anti-aliased H&ighlight Mode: cmbHighlightMode Set the blend mode for the layer - + ... &Opacity: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter intOpacity 0 0 10 15 Set the master opacity for the layer Adjust the transparency of the layer Set the blend mode for the layer - + ... &Opacity: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter intOpacity2 0 0 10 15 Set the master opacity for the layer Adjust the transparency of the layer Altitude: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter dialAngle Sh&adow Mode: cmbShadowMode Qt::Vertical 20 40 + + KisColorButton + QPushButton +
kis_color_button.h
+
KisIntParseSpinBox QSpinBox
kis_int_parse_spin_box.h
KisSliderSpinBox QWidget
kis_slider_spin_box.h
1
- - KColorButton - QPushButton -
kcolorbutton.h
- 1 -
KisCompositeOpComboBox QComboBox
kis_cmb_composite.h
diff --git a/libs/ui/layerstyles/wdgInnerGlow.ui b/libs/ui/layerstyles/wdgInnerGlow.ui index fcf66016ba..ce23fc693f 100644 --- a/libs/ui/layerstyles/wdgInnerGlow.ui +++ b/libs/ui/layerstyles/wdgInnerGlow.ui @@ -1,406 +1,405 @@ WdgInnerGlow 0 0 298 476 Inner Glow Structure Ble&nd Mode: cmbCompositeOp 0 0 Set the blend mode for the layer &Opacity: intOpacity 0 0 10 15 Set the master opacity for the layer Adjust the transparency of the layer &Noise: intNoise 0 0 10 15 Set the master opacity for the layer Adjust the transparency of the layer - + ... 0 0 Elements &Technique: cmbTechnique 0 0 Softer Precise &Source: cmbSource &Choke: intChoke 0 0 % 100 &Size: intSize 0 0 px 250 0 0 Center Edge Quality Contour: Anti-aliased &Range: intRange 0 0 % 1 100 &Jitter: intJitter 0 0 % 100 Qt::Vertical 20 40 - KColorButton + KisColorButton QPushButton -
kcolorbutton.h
- 1 -
- - KisCompositeOpComboBox - QComboBox -
kis_cmb_composite.h
+
kis_color_button.h
KisSliderSpinBox QWidget
kis_slider_spin_box.h
1
+ + KisCompositeOpComboBox + QComboBox +
kis_cmb_composite.h
+
KisCmbContour QWidget
kis_cmb_contour.h
KisCmbGradient QToolButton
kis_cmb_gradient.h
diff --git a/libs/ui/layerstyles/wdgdropshadow.ui b/libs/ui/layerstyles/wdgdropshadow.ui index d1f81dc6cd..3074d05833 100644 --- a/libs/ui/layerstyles/wdgdropshadow.ui +++ b/libs/ui/layerstyles/wdgdropshadow.ui @@ -1,319 +1,318 @@ WdgDropShadow 0 0 435 390 Drop Shadow Use to obscure the shadow when fill is transparent Layer knocks O&ut Drop Shadow Quality Contour: 0 0 Smooth the contour Anti-aliased &Noise: intNoise 0 0 Add noise to shadow Structure &Blend Mode: cmbCompositeOp 0 0 Set the blend mode for the layer - + Opaci&ty: intOpacity 0 0 10 15 Set the master opacity for the layer Adjust the transparency of the layer An&gle: dialAngle Set the angle of the light source -179 180 true -179 180 Use current setting for global light source Use &Global light &Distance: intDistance 0 0 Sp&read: intSpread 0 0 S&ize: intSize 0 0 Qt::Vertical 20 40 + + KisColorButton + QPushButton +
kis_color_button.h
+
KisIntParseSpinBox QSpinBox
kis_int_parse_spin_box.h
KisSliderSpinBox QWidget
kis_slider_spin_box.h
1
- - KColorButton - QPushButton -
kcolorbutton.h
- 1 -
KisCompositeOpComboBox QComboBox
kis_cmb_composite.h
KisCmbContour QWidget
kis_cmb_contour.h
diff --git a/libs/ui/recorder/kis_recorded_paint_action_editor.cc b/libs/ui/recorder/kis_recorded_paint_action_editor.cc index 00816b3354..f9e29ff542 100644 --- a/libs/ui/recorder/kis_recorded_paint_action_editor.cc +++ b/libs/ui/recorder/kis_recorded_paint_action_editor.cc @@ -1,176 +1,170 @@ /* * Copyright (c) 2010 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_recorded_paint_action_editor.h" #include #include #include -#include - #include "recorder/kis_recorded_paint_action.h" #include #include #include #include "ui_wdgpaintactioneditor.h" #include #include #include "kis_node_query_path_editor.h" #include KisRecordedPaintActionEditor::KisRecordedPaintActionEditor(QWidget* parent, KisRecordedAction* action) : QWidget(parent), m_action(dynamic_cast(action)), m_actionEditor(new Ui_WdgPaintActionEditor), m_configWidget(0) { Q_ASSERT(m_action); m_actionEditor->setupUi(this); // Setup paint color editor - m_paintColorPopup = new KoColorPopupAction(this); - m_paintColorPopup->setCurrentColor(m_action->paintColor()); - m_actionEditor->paintColor->setDefaultAction(m_paintColorPopup); - connect(m_paintColorPopup, SIGNAL(colorChanged(const KoColor &)), + m_actionEditor->paintColor->setColor(m_action->paintColor()); + connect(m_actionEditor->paintColor, SIGNAL(changed(KoColor)), this, SLOT(configurationUpdated())); // Setup background color editor - m_backgroundColorPopup = new KoColorPopupAction(this); - m_backgroundColorPopup->setCurrentColor(m_action->backgroundColor()); - m_actionEditor->backgroundColor->setDefaultAction(m_backgroundColorPopup); - connect(m_backgroundColorPopup, SIGNAL(colorChanged(const KoColor &)), + m_actionEditor->backgroundColor->setColor(m_action->backgroundColor()); + connect(m_actionEditor->backgroundColor, SIGNAL(changed(KoColor)), this, SLOT(configurationUpdated())); // Setup opacity m_actionEditor->opacity->setValue(m_action->opacity() * 100.0); connect(m_actionEditor->opacity, SIGNAL(valueChanged(int)), SLOT(configurationUpdated())); // Setup paint ops QList keys = KisPaintOpRegistry::instance()->listKeys(); Q_FOREACH (const KoID& paintopId, keys) { QString pixmapName = KisPaintOpRegistry::instance()->pixmap(paintopId); QPixmap pm; if (!pixmapName.isEmpty()) { QString fname = KoResourcePaths::findResource("kis_images", pixmapName); pm = QPixmap(fname); } if (pm.isNull()) { pm = QPixmap(16, 16); pm.fill(); } m_actionEditor->paintOps->addItem(QIcon(pm), paintopId.name()); m_paintops.append(paintopId.id()); } connect(m_actionEditor->paintOps, SIGNAL(activated(int)), SLOT(paintOpChanged(int))); // Setup configuration widget for paint op settings m_gridLayout = new QGridLayout(m_actionEditor->frmOptionWidgetContainer); setPaintOpPreset(); m_actionEditor->paintOps->setCurrentIndex(m_paintops.indexOf(m_action->paintOpPreset()->paintOp().id())); m_paintOpsToPreset[m_action->paintOpPreset()->paintOp().id()] = m_action->paintOpPreset(); connect(m_actionEditor->wdgPresetChooser, SIGNAL(resourceSelected(KoResource*)), SLOT(resourceSelected(KoResource*))); // Setup the query path editor m_actionEditor->nodeQueryPathEditor->setNodeQueryPath(m_action->nodeQueryPath()); connect(m_actionEditor->nodeQueryPathEditor, SIGNAL(nodeQueryPathChanged()), SLOT(nodeQueryPathChanged())); } KisRecordedPaintActionEditor::~KisRecordedPaintActionEditor() { delete m_actionEditor; } void KisRecordedPaintActionEditor::configurationUpdated() { m_configWidget->writeConfigurationSafe(const_cast(m_action->paintOpPreset()->settings().data())); - m_action->setPaintColor(m_paintColorPopup->currentKoColor()); - m_action->setBackgroundColor(m_backgroundColorPopup->currentKoColor()); + m_action->setPaintColor(m_actionEditor->paintColor->color()); + m_action->setBackgroundColor(m_actionEditor->backgroundColor->color()); m_action->setOpacity(m_actionEditor->opacity->value() / qreal(100.0)); emit(actionEdited()); } void KisRecordedPaintActionEditor::paintOpChanged(int index) { QString id = m_paintops[index]; KisPaintOpPresetSP preset = m_paintOpsToPreset[id]; if (!preset) { preset = KisPaintOpRegistry::instance()->defaultPreset(KoID(id, "")); m_paintOpsToPreset[id] = preset; } m_action->setPaintOpPreset(preset); setPaintOpPreset(); } void KisRecordedPaintActionEditor::resourceSelected(KoResource* resource) { KisPaintOpPresetSP preset = static_cast(resource); m_paintOpsToPreset[preset->paintOp().id()] = preset; m_action->setPaintOpPreset(preset); setPaintOpPreset(); } void KisRecordedPaintActionEditor::nodeQueryPathChanged() { m_action->setNodeQueryPath(m_actionEditor->nodeQueryPathEditor->nodeQueryPath()); emit(actionEdited()); } void KisRecordedPaintActionEditor::setPaintOpPreset() { delete m_configWidget; m_configWidget = KisPaintOpRegistry::instance()->get(m_action->paintOpPreset()->paintOp().id())->createConfigWidget(m_actionEditor->frmOptionWidgetContainer); if (m_configWidget) { m_gridLayout->addWidget(m_configWidget); //TODO use default configuration instead? //m_configWidget->setConfiguration(m_action->paintOpPreset()->settings()); connect(m_configWidget, SIGNAL(sigConfigurationUpdated()), SLOT(configurationUpdated())); } else { m_gridLayout->addWidget(new QLabel(i18n("No configuration option."), this)); } } KisRecordedPaintActionEditorFactory::KisRecordedPaintActionEditorFactory() { } KisRecordedPaintActionEditorFactory::~KisRecordedPaintActionEditorFactory() { } QWidget* KisRecordedPaintActionEditorFactory::createEditor(QWidget* parent, KisRecordedAction* action) const { return new KisRecordedPaintActionEditor(parent, action); } bool KisRecordedPaintActionEditorFactory::canEdit(const KisRecordedAction* action) const { return dynamic_cast(action); } diff --git a/libs/ui/recorder/kis_recorded_paint_action_editor.h b/libs/ui/recorder/kis_recorded_paint_action_editor.h index 2b55c27142..50f907a7b7 100644 --- a/libs/ui/recorder/kis_recorded_paint_action_editor.h +++ b/libs/ui/recorder/kis_recorded_paint_action_editor.h @@ -1,70 +1,68 @@ /* * Copyright (c) 2010 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_RECORDED_PAINT_ACTION_EDITOR_H_ #define _KIS_RECORDED_PAINT_ACTION_EDITOR_H_ #include #include "kis_recorded_action_editor_factory.h" #include "kis_types.h" class QGridLayout; class KoColorPopupAction; class KisPaintOpConfigWidget; class KisRecordedPaintAction; class Ui_WdgPaintActionEditor; class KoResource; /** * This is the editor for all \ref KisRecordedPaintAction */ class KisRecordedPaintActionEditor : public QWidget { Q_OBJECT public: KisRecordedPaintActionEditor(QWidget* parent, KisRecordedAction* action); ~KisRecordedPaintActionEditor(); private Q_SLOTS: void configurationUpdated(); void paintOpChanged(int index); void resourceSelected(KoResource* resource); void nodeQueryPathChanged(); Q_SIGNALS: void actionEdited(); private: void setPaintOpPreset(); KisRecordedPaintAction* m_action; Ui_WdgPaintActionEditor* m_actionEditor; KisPaintOpConfigWidget* m_configWidget; - KoColorPopupAction* m_paintColorPopup; - KoColorPopupAction* m_backgroundColorPopup; QGridLayout* m_gridLayout; QList m_paintops; QMap m_paintOpsToPreset; }; class KisRecordedPaintActionEditorFactory : public KisRecordedActionEditorFactory { public: KisRecordedPaintActionEditorFactory(); virtual ~KisRecordedPaintActionEditorFactory(); virtual QWidget* createEditor(QWidget* parent, KisRecordedAction* action) const; virtual bool canEdit(const KisRecordedAction* action) const; }; #endif diff --git a/libs/widgets/KoDualColorButton.cpp b/libs/ui/widgets/KoDualColorButton.cpp similarity index 76% rename from libs/widgets/KoDualColorButton.cpp rename to libs/ui/widgets/KoDualColorButton.cpp index 991341908c..ad7fb11cdb 100644 --- a/libs/widgets/KoDualColorButton.cpp +++ b/libs/ui/widgets/KoDualColorButton.cpp @@ -1,336 +1,387 @@ /* This file is part of the KDE libraries Copyright (C) 1999 Daniel M. Duley This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "KoDualColorButton.h" #include "KoColor.h" #include "KoColorDisplayRendererInterface.h" #include #include "dcolorarrow.xbm" #include "dcolorreset.xpm" #include +#include "dialogs/kis_dlg_internal_color_selector.h" #include #include #include #include #include #include class Q_DECL_HIDDEN KoDualColorButton::Private { public: Private(const KoColor &fgColor, const KoColor &bgColor, QWidget *_dialogParent, const KoColorDisplayRendererInterface *_displayRenderer) : dialogParent(_dialogParent) , dragFlag( false ) , miniCtlFlag( false ) , foregroundColor(fgColor) , backgroundColor(bgColor) , displayRenderer(_displayRenderer) { updateArrows(); resetPixmap = QPixmap( (const char **)dcolorreset_xpm ); popDialog = true; } void updateArrows() { arrowBitmap = QPixmap(12,12); arrowBitmap.fill(Qt::transparent); QPainter p(&arrowBitmap); p.setPen(dialogParent->palette().foreground().color()); // arrow pointing left p.drawLine(0, 3, 7, 3); p.drawLine(1, 2, 1, 4); p.drawLine(2, 1, 2, 5); p.drawLine(3, 0, 3, 6); // arrow pointing down p.drawLine(8, 4, 8, 11); p.drawLine(5, 8, 11, 8); p.drawLine(6, 9, 10, 9); p.drawLine(7, 10, 9, 10); } QWidget* dialogParent; QPixmap arrowBitmap; QPixmap resetPixmap; bool dragFlag, miniCtlFlag; KoColor foregroundColor; KoColor backgroundColor; + KisDlgInternalColorSelector *colorSelectorDialog; QPoint dragPosition; Selection tmpSelection; bool popDialog; const KoColorDisplayRendererInterface *displayRenderer; void init(KoDualColorButton *q); }; void KoDualColorButton::Private::init(KoDualColorButton *q) { if ( q->sizeHint().isValid() ) q->setMinimumSize( q->sizeHint() ); q->setAcceptDrops( true ); + QString caption = i18n("Select a color"); + KisDlgInternalColorSelector::Config config = KisDlgInternalColorSelector::Config(); + config.modal = false; + colorSelectorDialog = new KisDlgInternalColorSelector(q, foregroundColor, config, caption, displayRenderer); + connect(colorSelectorDialog, SIGNAL(signalForegroundColorChosen(KoColor)), q, SLOT(slotSetForeGroundColorFromDialog(KoColor))); + connect(q, SIGNAL(foregroundColorChanged(KoColor)), colorSelectorDialog, SLOT(slotColorUpdated(KoColor))); } KoDualColorButton::KoDualColorButton(const KoColor &foregroundColor, const KoColor &backgroundColor, QWidget *parent, QWidget* dialogParent ) : QWidget( parent ), d( new Private(foregroundColor, backgroundColor, dialogParent, KoDumbColorDisplayRenderer::instance()) ) { d->init(this); } KoDualColorButton::KoDualColorButton(const KoColor &foregroundColor, const KoColor &backgroundColor, const KoColorDisplayRendererInterface *displayRenderer, QWidget *parent, QWidget* dialogParent) : QWidget( parent ), d( new Private(foregroundColor, backgroundColor, dialogParent, displayRenderer) ) { d->init(this); } KoDualColorButton::~KoDualColorButton() { delete d; } KoColor KoDualColorButton::foregroundColor() const { return d->foregroundColor; } KoColor KoDualColorButton::backgroundColor() const { return d->backgroundColor; } bool KoDualColorButton::popDialog() const { return d->popDialog; } QSize KoDualColorButton::sizeHint() const { return QSize( 34, 34 ); } void KoDualColorButton::setForegroundColor( const KoColor &color ) { d->foregroundColor = color; + d->colorSelectorDialog->slotColorUpdated(color); repaint(); } void KoDualColorButton::setBackgroundColor( const KoColor &color ) { d->backgroundColor = color; repaint(); } +void KoDualColorButton::setDisplayRenderer(const KoColorDisplayRendererInterface *displayRenderer) +{ + if (displayRenderer) { + d->displayRenderer = displayRenderer; + d->colorSelectorDialog->setDisplayRenderer(displayRenderer); + connect(d->displayRenderer, SIGNAL(destroyed()), this, SLOT(setDisplayRenderer()), Qt::UniqueConnection); + } else { + d->displayRenderer = KoDumbColorDisplayRenderer::instance(); + } +} + +void KoDualColorButton::setColorSpace(const KoColorSpace *cs) +{ + d->colorSelectorDialog->lockUsedColorSpace(cs); +} + +QColor KoDualColorButton::getColorFromDisplayRenderer(KoColor c) +{ + QColor col; + if (d->displayRenderer) { + c.convertTo(d->displayRenderer->getPaintingColorSpace()); + col = d->displayRenderer->toQColor(c); + } else { + col = c.toQColor(); + } + return col; +} + void KoDualColorButton::setPopDialog( bool popDialog ) { d->popDialog = popDialog; } void KoDualColorButton::metrics( QRect &foregroundRect, QRect &backgroundRect ) { foregroundRect = QRect( 0, 0, width() - 14, height() - 14 ); backgroundRect = QRect( 14, 14, width() - 14, height() - 14 ); } void KoDualColorButton::paintEvent(QPaintEvent *) { QRect foregroundRect; QRect backgroundRect; QPainter painter( this ); metrics( foregroundRect, backgroundRect ); QBrush defBrush = palette().brush( QPalette::Button ); - QBrush foregroundBrush( d->displayRenderer->toQColor(d->foregroundColor), Qt::SolidPattern ); - QBrush backgroundBrush( d->displayRenderer->toQColor(d->backgroundColor), Qt::SolidPattern ); + QBrush foregroundBrush( getColorFromDisplayRenderer(d->foregroundColor), Qt::SolidPattern ); + QBrush backgroundBrush( getColorFromDisplayRenderer(d->backgroundColor), Qt::SolidPattern ); qDrawShadeRect( &painter, backgroundRect, palette(), false, 1, 0, isEnabled() ? &backgroundBrush : &defBrush ); qDrawShadeRect( &painter, foregroundRect, palette(), false, 1, 0, isEnabled() ? &foregroundBrush : &defBrush ); painter.setPen( palette().color( QPalette::Shadow ) ); painter.drawPixmap( foregroundRect.right() + 2, 1, d->arrowBitmap ); painter.drawPixmap( 1, foregroundRect.bottom() + 2, d->resetPixmap ); } void KoDualColorButton::dragEnterEvent( QDragEnterEvent *event ) { event->setAccepted( isEnabled() && KColorMimeData::canDecode( event->mimeData() ) ); } void KoDualColorButton::dropEvent( QDropEvent *event ) { Q_UNUSED(event); /* QColor color = KColorMimeData::fromMimeData( event->mimeData() ); if ( color.isValid() ) { if ( d->selection == Foreground ) { d->foregroundColor = color; emit foregroundColorChanged( color ); } else { d->backgroundColor = color; emit backgroundColorChanged( color ); } repaint(); } */ } +void KoDualColorButton::slotSetForeGroundColorFromDialog(const KoColor color) +{ + d->foregroundColor = color; + repaint(); + emit foregroundColorChanged(d->foregroundColor); +} + void KoDualColorButton::mousePressEvent( QMouseEvent *event ) { QRect foregroundRect; QRect backgroundRect; metrics( foregroundRect, backgroundRect ); d->dragPosition = event->pos(); d->dragFlag = false; if ( foregroundRect.contains( d->dragPosition ) ) { d->tmpSelection = Foreground; d->miniCtlFlag = false; } else if( backgroundRect.contains( d->dragPosition ) ) { d->tmpSelection = Background; d->miniCtlFlag = false; } else if ( event->pos().x() > foregroundRect.width() ) { // We handle the swap and reset controls as soon as the mouse is // is pressed and ignore further events on this click (mosfet). KoColor tmp = d->foregroundColor; d->foregroundColor = d->backgroundColor; d->backgroundColor = tmp; emit backgroundColorChanged( d->backgroundColor ); emit foregroundColorChanged( d->foregroundColor ); d->miniCtlFlag = true; } else if ( event->pos().x() < backgroundRect.x() ) { d->foregroundColor = d->displayRenderer->approximateFromRenderedQColor(Qt::black); d->backgroundColor = d->displayRenderer->approximateFromRenderedQColor(Qt::white); emit backgroundColorChanged( d->backgroundColor ); emit foregroundColorChanged( d->foregroundColor ); d->miniCtlFlag = true; } repaint(); } void KoDualColorButton::mouseMoveEvent( QMouseEvent *event ) { if ( !d->miniCtlFlag ) { int delay = QApplication::startDragDistance(); if ( event->x() >= d->dragPosition.x() + delay || event->x() <= d->dragPosition.x() - delay || event->y() >= d->dragPosition.y() + delay || event->y() <= d->dragPosition.y() - delay ) { KColorMimeData::createDrag( d->tmpSelection == Foreground ? - d->displayRenderer->toQColor(d->foregroundColor) : - d->displayRenderer->toQColor(d->backgroundColor), + getColorFromDisplayRenderer(d->foregroundColor) : + getColorFromDisplayRenderer(d->backgroundColor), this )->start(); d->dragFlag = true; } } } void KoDualColorButton::mouseReleaseEvent( QMouseEvent *event ) { d->dragFlag = false; if ( d->miniCtlFlag ) return; d->miniCtlFlag = false; QRect foregroundRect; QRect backgroundRect; metrics( foregroundRect, backgroundRect ); if ( foregroundRect.contains( event->pos() )) { if(d->tmpSelection == Foreground ) { if( d->popDialog) { - QColor c = d->displayRenderer->toQColor(d->foregroundColor); - c = QColorDialog::getColor(c, this) ; - if (c.isValid()) { - d->foregroundColor = d->displayRenderer->approximateFromRenderedQColor(c); - emit foregroundColorChanged(d->foregroundColor); - } + d->colorSelectorDialog->show(); + + //QColor c = d->displayRenderer->toQColor(d->foregroundColor); + //c = QColorDialog::getColor(c, this) ; + + //if (c.isValid()) { + // d->foregroundColor = d->displayRenderer->approximateFromRenderedQColor(c); + // emit foregroundColorChanged(d->foregroundColor); + //} } else emit pleasePopDialog( d->foregroundColor); } else { d->foregroundColor = d->backgroundColor; emit foregroundColorChanged( d->foregroundColor ); } } else if ( backgroundRect.contains( event->pos() )) { if(d->tmpSelection == Background ) { if( d->popDialog) { - QColor c = d->displayRenderer->toQColor(d->backgroundColor); + KoColor c = d->backgroundColor; + c = KisDlgInternalColorSelector::getModalColorDialog(c, this); + d->backgroundColor = c; + emit backgroundColorChanged(d->backgroundColor); + /*QColor c = d->displayRenderer->toQColor(d->backgroundColor); c = QColorDialog::getColor(c, this); if (c.isValid()) { d->backgroundColor = d->displayRenderer->approximateFromRenderedQColor(c); emit backgroundColorChanged(d->backgroundColor); - } + }*/ } else emit pleasePopDialog( d->backgroundColor); } else { d->backgroundColor = d->foregroundColor; emit backgroundColorChanged( d->backgroundColor ); } } repaint(); } void KoDualColorButton::changeEvent(QEvent *event) { QWidget::changeEvent(event); switch (event->type()) { case QEvent::StyleChange: case QEvent::PaletteChange: d->updateArrows(); default: break; } } diff --git a/libs/widgets/KoDualColorButton.h b/libs/ui/widgets/KoDualColorButton.h similarity index 87% rename from libs/widgets/KoDualColorButton.h rename to libs/ui/widgets/KoDualColorButton.h index be53059e11..dada703c2a 100644 --- a/libs/widgets/KoDualColorButton.h +++ b/libs/ui/widgets/KoDualColorButton.h @@ -1,167 +1,186 @@ /* This file is part of the KDE libraries Copyright (C) 1999 Daniel M. Duley 2006 Tobias Koenig This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KODUALCOLORBUTTON_H #define KODUALCOLORBUTTON_H #include "kritawidgets_export.h" - +#include #include class KoColor; -class KoColorDisplayRendererInterface; - +class KoColorSpace; /** * @short A widget for selecting two related colors. * * KoDualColorButton allows the user to select two cascaded colors (usually a * foreground and background color). Other features include drag and drop * from other KDE color widgets, a reset to black and white control, and a * swap colors control. * * When the user clicks on the foreground or background rectangle the * rectangle is first sunken and the selectionChanged() signal is emitted. * Further clicks will present a color dialog and emit either the foregroundColorChanged() * or backgroundColorChanged() if a new color is selected. * * Note: With drag and drop when dropping a color the current selected color * will be set, while when dragging a color it will use whatever color * rectangle the mouse was pressed inside. * * @author Daniel M. Duley */ class KRITAWIDGETS_EXPORT KoDualColorButton : public QWidget { Q_OBJECT Q_ENUMS( Selection ) Q_PROPERTY( KoColor foregroundColor READ foregroundColor WRITE setForegroundColor ) Q_PROPERTY( KoColor backgroundColor READ backgroundColor WRITE setBackgroundColor ) Q_PROPERTY( bool popDialog READ popDialog WRITE setPopDialog ) public: enum Selection { Foreground, Background }; /** * Constructs a new KoDualColorButton with the supplied foreground and * background colors. * * @param parent The parent widget of the KoDualColorButton. * @param dialogParent The parent widget of the color selection dialog. */ KoDualColorButton(const KoColor &foregroundColor, const KoColor &backgroundColor, QWidget *parent = 0, QWidget* dialogParent = 0 ); KoDualColorButton(const KoColor &foregroundColor, const KoColor &backgroundColor, const KoColorDisplayRendererInterface *displayRenderer, QWidget *parent = 0, QWidget* dialogParent = 0 ); /** * Destroys the KoDualColorButton. */ ~KoDualColorButton(); /** * Returns the current foreground color. */ KoColor foregroundColor() const; /** * Returns the current background color. */ KoColor backgroundColor() const; /** * Returns if a dialog with a color chooser will be popped up when clicking * If false then you could/should connect to the pleasePopDialog signal * and pop your own dialog. Just set the current color afterwards. */ bool popDialog() const; /** * Returns the minimum size needed to display the widget and all its * controls. */ virtual QSize sizeHint() const; public Q_SLOTS: /** * Sets the foreground color. */ void setForegroundColor( const KoColor &color ); /** * Sets the background color. */ void setBackgroundColor( const KoColor &color ); + void slotSetForeGroundColorFromDialog (const KoColor color); + + void setDisplayRenderer(const KoColorDisplayRendererInterface *displayRenderer = KoDumbColorDisplayRenderer::instance()); + + /** + * @brief setColorSpace + * set ColorSpace so we can lock the selector. Right now this'll be changed per view-change. + * @param cs + */ + void setColorSpace(const KoColorSpace *cs); + + /** + * @brief getColorFromDisplayRenderer + * convenience function to get the right qcolor from the display renderer, including checking + * whether the display renderer actually exists. + * @param c the kocolor to convert. + * @return the qcolor to use for display. + */ + QColor getColorFromDisplayRenderer(KoColor c); + /** * Sets if a dialog with a color chooser should be popped up when clicking * If you set this to false then you could connect to the pleasePopDialog signal * and pop your own dialog. Just set the current color afterwards. */ void setPopDialog( bool popDialog ); Q_SIGNALS: /** * Emitted when the foreground color is changed. */ void foregroundColorChanged( const KoColor &color ); /** * Emitted when the background color is changed. */ void backgroundColorChanged( const KoColor &color ); /** * Emitted when the user clicks one of the two color patches. * You should/could pop you own color chooser dialog in response. * Also see the popDialog attribute. */ void pleasePopDialog( const KoColor &color ); protected: /** * Sets the supplied rectangles to the proper size and position for the * current widget size. You can reimplement this to change the layout * of the widget. Restrictions are that the swap control will always * be at the top right, the reset control will always be at the bottom * left, and you must leave at least a 14x14 space in those corners. */ virtual void metrics( QRect &foregroundRect, QRect &backgroundRect ); virtual void paintEvent( QPaintEvent *event ); virtual void mousePressEvent( QMouseEvent *event ); virtual void mouseMoveEvent( QMouseEvent *event ); virtual void mouseReleaseEvent( QMouseEvent *event ); virtual void dragEnterEvent( QDragEnterEvent *event ); virtual void dropEvent( QDropEvent *event ); virtual void changeEvent(QEvent *event); private: class Private; Private *const d; }; #endif diff --git a/libs/ui/widgets/kis_color_button.cpp b/libs/ui/widgets/kis_color_button.cpp new file mode 100644 index 0000000000..d6b077763c --- /dev/null +++ b/libs/ui/widgets/kis_color_button.cpp @@ -0,0 +1,340 @@ +/* This file is part of the KDE libraries + Copyright (C) 1997 Martin Jones (mjones@kde.org) + Copyright (C) 1999 Cristian Tibirna (ctibirna@kde.org) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "kis_color_button.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +class KisColorButton::KisColorButtonPrivate +{ +public: + KisColorButtonPrivate(KisColorButton *q); + + void _k_chooseColor(); + void _k_colorChosen(); + + KisColorButton *q; + KoColor m_defaultColor; + bool m_bdefaultColor : 1; + bool m_alphaChannel : 1; + + KoColor col; + QPoint mPos; + + QPointer dialogPtr; + + void initStyleOption(QStyleOptionButton *opt) const; +}; + +///////////////////////////////////////////////////////////////////// +// Functions duplicated from KColorMimeData +// Should be kept in sync +void _k_populateMimeData(QMimeData *mimeData, const KoColor &color) +{ + mimeData->setColorData(color.toQColor()); + mimeData->setText(color.toQColor().name()); +} + +bool _k_canDecode(const QMimeData *mimeData) +{ + if (mimeData->hasColor()) { + return true; + } + if (mimeData->hasText()) { + const QString colorName = mimeData->text(); + if ((colorName.length() >= 4) && (colorName[0] == QLatin1Char('#'))) { + return true; + } + } + return false; +} + +QColor _k_fromMimeData(const QMimeData *mimeData) +{ + if (mimeData->hasColor()) { + return mimeData->colorData().value(); + } + if (_k_canDecode(mimeData)) { + return QColor(mimeData->text()); + } + return QColor(); +} + +QDrag *_k_createDrag(const KoColor &color, QObject *dragsource) +{ + QDrag *drag = new QDrag(dragsource); + QMimeData *mime = new QMimeData; + _k_populateMimeData(mime, color); + drag->setMimeData(mime); + QPixmap colorpix(25, 20); + colorpix.fill(color.toQColor()); + QPainter p(&colorpix); + p.setPen(Qt::black); + p.drawRect(0, 0, 24, 19); + p.end(); + drag->setPixmap(colorpix); + drag->setHotSpot(QPoint(-5, -7)); + return drag; +} +///////////////////////////////////////////////////////////////////// + +KisColorButton::KisColorButtonPrivate::KisColorButtonPrivate(KisColorButton *q) + : q(q) +{ + m_bdefaultColor = false; + m_alphaChannel = false; + q->setAcceptDrops(true); + + connect(q, SIGNAL(clicked()), q, SLOT(_k_chooseColor())); +} + +KisColorButton::KisColorButton(QWidget *parent) + : QPushButton(parent) + , d(new KisColorButtonPrivate(this)) +{ +} + +KisColorButton::KisColorButton(const KoColor &c, QWidget *parent) + : QPushButton(parent) + , d(new KisColorButtonPrivate(this)) +{ + d->col = c; +} + +KisColorButton::KisColorButton(const KoColor &c, const KoColor &defaultColor, QWidget *parent) + : QPushButton(parent) + , d(new KisColorButtonPrivate(this)) +{ + d->col = c; + setDefaultColor(defaultColor); +} + +KisColorButton::~KisColorButton() +{ + delete d; +} + +KoColor KisColorButton::color() const +{ + return d->col; +} + +void KisColorButton::setColor(const KoColor &c) +{ + d->col = c; + update(); + emit changed(d->col); +} + +void KisColorButton::setAlphaChannelEnabled(bool alpha) +{ + d->m_alphaChannel = alpha; +} + +bool KisColorButton::isAlphaChannelEnabled() const +{ + return d->m_alphaChannel; +} + +KoColor KisColorButton::defaultColor() const +{ + return d->m_defaultColor; +} + +void KisColorButton::setDefaultColor(const KoColor &c) +{ + d->m_bdefaultColor = true; + d->m_defaultColor = c; +} + +void KisColorButton::KisColorButtonPrivate::initStyleOption(QStyleOptionButton *opt) const +{ + opt->initFrom(q); + opt->state |= q->isDown() ? QStyle::State_Sunken : QStyle::State_Raised; + opt->features = QStyleOptionButton::None; + if (q->isDefault()) { + opt->features |= QStyleOptionButton::DefaultButton; + } + opt->text.clear(); + opt->icon = QIcon(); +} + +void KisColorButton::paintEvent(QPaintEvent *) +{ + QPainter painter(this); + QStyle *style = QWidget::style(); + + //First, we need to draw the bevel. + QStyleOptionButton butOpt; + d->initStyleOption(&butOpt); + style->drawControl(QStyle::CE_PushButtonBevel, &butOpt, &painter, this); + + //OK, now we can muck around with drawing out pretty little color box + //First, sort out where it goes + QRect labelRect = style->subElementRect(QStyle::SE_PushButtonContents, + &butOpt, this); + int shift = style->pixelMetric(QStyle::PM_ButtonMargin, &butOpt, this) / 2; + labelRect.adjust(shift, shift, -shift, -shift); + int x, y, w, h; + labelRect.getRect(&x, &y, &w, &h); + + if (isChecked() || isDown()) { + x += style->pixelMetric(QStyle::PM_ButtonShiftHorizontal, &butOpt, this); + y += style->pixelMetric(QStyle::PM_ButtonShiftVertical, &butOpt, this); + } + + QColor fillCol = isEnabled() ? d->col.toQColor() : palette().color(backgroundRole()); + qDrawShadePanel(&painter, x, y, w, h, palette(), true, 1, NULL); + if (fillCol.isValid()) { + const QRect rect(x + 1, y + 1, w - 2, h - 2); + if (fillCol.alpha() < 255) { + QPixmap chessboardPattern(16, 16); + QPainter patternPainter(&chessboardPattern); + patternPainter.fillRect(0, 0, 8, 8, Qt::black); + patternPainter.fillRect(8, 8, 8, 8, Qt::black); + patternPainter.fillRect(0, 8, 8, 8, Qt::white); + patternPainter.fillRect(8, 0, 8, 8, Qt::white); + patternPainter.end(); + painter.fillRect(rect, QBrush(chessboardPattern)); + } + painter.fillRect(rect, fillCol); + } + + if (hasFocus()) { + QRect focusRect = style->subElementRect(QStyle::SE_PushButtonFocusRect, &butOpt, this); + QStyleOptionFocusRect focusOpt; + focusOpt.init(this); + focusOpt.rect = focusRect; + focusOpt.backgroundColor = palette().background().color(); + style->drawPrimitive(QStyle::PE_FrameFocusRect, &focusOpt, &painter, this); + } +} + +QSize KisColorButton::sizeHint() const +{ + QStyleOptionButton opt; + d->initStyleOption(&opt); + return style()->sizeFromContents(QStyle::CT_PushButton, &opt, QSize(40, 15), this). + expandedTo(QApplication::globalStrut()); +} + +QSize KisColorButton::minimumSizeHint() const +{ + QStyleOptionButton opt; + d->initStyleOption(&opt); + return style()->sizeFromContents(QStyle::CT_PushButton, &opt, QSize(3, 3), this). + expandedTo(QApplication::globalStrut()); +} + +void KisColorButton::dragEnterEvent(QDragEnterEvent *event) +{ + event->setAccepted(_k_canDecode(event->mimeData()) && isEnabled()); +} + +void KisColorButton::dropEvent(QDropEvent *event) +{ + QColor c = _k_fromMimeData(event->mimeData()); + if (c.isValid()) { + KoColor col; + col.fromQColor(c); + setColor(col); + } +} + +void KisColorButton::keyPressEvent(QKeyEvent *e) +{ + int key = e->key() | e->modifiers(); + + if (QKeySequence::keyBindings(QKeySequence::Copy).contains(key)) { + QMimeData *mime = new QMimeData; + _k_populateMimeData(mime, color()); + QApplication::clipboard()->setMimeData(mime, QClipboard::Clipboard); + } else if (QKeySequence::keyBindings(QKeySequence::Paste).contains(key)) { + QColor color = _k_fromMimeData(QApplication::clipboard()->mimeData(QClipboard::Clipboard)); + KoColor col; + col.fromQColor(color); + setColor(col); + } else { + QPushButton::keyPressEvent(e); + } +} + +void KisColorButton::mousePressEvent(QMouseEvent *e) +{ + d->mPos = e->pos(); + QPushButton::mousePressEvent(e); +} + +void KisColorButton::mouseMoveEvent(QMouseEvent *e) +{ + if ((e->buttons() & Qt::LeftButton) && + (e->pos() - d->mPos).manhattanLength() > QApplication::startDragDistance()) { + _k_createDrag(color(), this)->start(); + setDown(false); + } +} + +void KisColorButton::KisColorButtonPrivate::_k_chooseColor() +{ + KisDlgInternalColorSelector *dialog = dialogPtr.data(); + if (dialog) { + dialog->show(); + dialog->raise(); + dialog->activateWindow(); + return; + } + + KisDlgInternalColorSelector::Config cfg; + + dialog = new KisDlgInternalColorSelector(q, + q->color(), + cfg, + i18n("Choose a color")); + //dialog->setOption(QColorDialog::ShowAlphaChannel, m_alphaChannel); + dialog->setAttribute(Qt::WA_DeleteOnClose); + connect(dialog, SIGNAL(accepted()), q, SLOT(_k_colorChosen())); + dialogPtr = dialog; + dialog->show(); +} + +void KisColorButton::KisColorButtonPrivate::_k_colorChosen() +{ + KisDlgInternalColorSelector *dialog = dialogPtr.data(); + if (!dialog) { + return; + } + + q->setColor(dialog->getCurrentColor()); +} + +#include "moc_kis_color_button.cpp" diff --git a/libs/ui/widgets/kis_color_button.h b/libs/ui/widgets/kis_color_button.h new file mode 100644 index 0000000000..5c974a3ad9 --- /dev/null +++ b/libs/ui/widgets/kis_color_button.h @@ -0,0 +1,124 @@ +/* + * Copyright (C) Wolthera van Hovell tot Westerflier , (C) 2016 + * This file is forked from the KF5 KColorButton + Copyright (C) 1997 Martin Jones (mjones@kde.org) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KisColorButton_H +#define KisColorButton_H +#include + +#include +#include + +class KisColorButtonPrivate; +/** +* @short A pushbutton to display or allow user selection of a color. +* +* This widget can be used to display or allow user selection of a color. +* +* @see QColorDialog +* +* \image html KisColorButton.png "KDE Color Button" +*/ +class KRITAUI_EXPORT KisColorButton : public QPushButton +{ + Q_OBJECT + Q_PROPERTY(KoColor color READ color WRITE setColor NOTIFY changed USER true) + Q_PROPERTY(KoColor defaultColor READ defaultColor WRITE setDefaultColor) + Q_PROPERTY(bool alphaChannelEnabled READ isAlphaChannelEnabled WRITE setAlphaChannelEnabled) + +public: + /** + * Creates a color button. + */ + explicit KisColorButton(QWidget *parent = 0); + + /** + * Creates a color button with an initial color @p c. + */ + explicit KisColorButton(const KoColor &c, QWidget *parent = 0); + + /** + * Creates a color button with an initial color @p c and default color @p defaultColor. + */ + KisColorButton(const KoColor &c, const KoColor &defaultColor, QWidget *parent = 0); + + virtual ~KisColorButton(); + + /** + * Returns the currently chosen color. + */ + KoColor color() const; + + /** + * Sets the current color to @p c. + */ + void setColor(const KoColor &c); + + /** + * When set to true, allow the user to change the alpha component + * of the color. The default value is false. + * @since 4.5 + */ + void setAlphaChannelEnabled(bool alpha); + + /** + * Returns true if the user is allowed to change the alpha component. + * @since 4.5 + */ + bool isAlphaChannelEnabled() const; + + /** + * Returns the default color or an invalid color + * if no default color is set. + */ + KoColor defaultColor() const; + + /** + * Sets the default color to @p c. + */ + void setDefaultColor(const KoColor &c); + + QSize sizeHint() const Q_DECL_OVERRIDE; + QSize minimumSizeHint() const Q_DECL_OVERRIDE; + +Q_SIGNALS: + /** + * Emitted when the color of the widget + * is changed, either with setColor() or via user selection. + */ + void changed(const KoColor &newColor); + +protected: + void paintEvent(QPaintEvent *pe) Q_DECL_OVERRIDE; + void dragEnterEvent(QDragEnterEvent *) Q_DECL_OVERRIDE; + void dropEvent(QDropEvent *) Q_DECL_OVERRIDE; + void mousePressEvent(QMouseEvent *e) Q_DECL_OVERRIDE; + void mouseMoveEvent(QMouseEvent *e) Q_DECL_OVERRIDE; + void keyPressEvent(QKeyEvent *e) Q_DECL_OVERRIDE; + +private: + class KisColorButtonPrivate; + KisColorButtonPrivate *const d; + + Q_PRIVATE_SLOT(d, void _k_chooseColor()) + Q_PRIVATE_SLOT(d, void _k_colorChosen()) +}; + +#endif diff --git a/plugins/dockers/specificcolorselector/kis_color_input.cc b/libs/ui/widgets/kis_color_input.cpp similarity index 100% rename from plugins/dockers/specificcolorselector/kis_color_input.cc rename to libs/ui/widgets/kis_color_input.cpp diff --git a/plugins/dockers/specificcolorselector/kis_color_input.h b/libs/ui/widgets/kis_color_input.h similarity index 77% rename from plugins/dockers/specificcolorselector/kis_color_input.h rename to libs/ui/widgets/kis_color_input.h index 45a3267c46..412b500c6a 100644 --- a/plugins/dockers/specificcolorselector/kis_color_input.h +++ b/libs/ui/widgets/kis_color_input.h @@ -1,98 +1,99 @@ /* * Copyright (c) 2008 Cyrille Berger * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_COLOR_INPUT_H_ #define _KIS_COLOR_INPUT_H_ #include class KoChannelInfo; class KoColor; class QWidget; class QSpinBox; class QDoubleSpinBox; class KisIntParseSpinBox; class KisDoubleParseSpinBox; class KoColorSlider; class QLineEdit; -#include "KoColorDisplayRendererInterface.h" +#include +#include "kritaui_export.h" -class KisColorInput : public QWidget +class KRITAUI_EXPORT KisColorInput : public QWidget { Q_OBJECT public: - KisColorInput(QWidget* parent, const KoChannelInfo*, KoColor* color, KoColorDisplayRendererInterface *displayRenderer); + KisColorInput(QWidget* parent, const KoChannelInfo*, KoColor* color, KoColorDisplayRendererInterface *displayRenderer = KoDumbColorDisplayRenderer::instance()); protected: void init(); virtual QWidget* createInput() = 0; Q_SIGNALS: void updated(); protected: const KoChannelInfo* m_channelInfo; KoColor* m_color; KoColorSlider* m_colorSlider; KoColorDisplayRendererInterface *m_displayRenderer; }; -class KisIntegerColorInput : public KisColorInput +class KRITAUI_EXPORT KisIntegerColorInput : public KisColorInput { Q_OBJECT public: - KisIntegerColorInput(QWidget* parent, const KoChannelInfo*, KoColor* color, KoColorDisplayRendererInterface *displayRenderer); + KisIntegerColorInput(QWidget* parent, const KoChannelInfo*, KoColor* color, KoColorDisplayRendererInterface *displayRenderer = KoDumbColorDisplayRenderer::instance()); protected: virtual QWidget* createInput(); public Q_SLOTS: void setValue(int); void update(); private: KisIntParseSpinBox* m_intNumInput; }; -class KisFloatColorInput : public KisColorInput +class KRITAUI_EXPORT KisFloatColorInput : public KisColorInput { Q_OBJECT public: - KisFloatColorInput(QWidget* parent, const KoChannelInfo*, KoColor* color, KoColorDisplayRendererInterface *displayRenderer); + KisFloatColorInput(QWidget* parent, const KoChannelInfo*, KoColor* color, KoColorDisplayRendererInterface *displayRenderer = KoDumbColorDisplayRenderer::instance()); protected: virtual QWidget* createInput(); public Q_SLOTS: void setValue(double); void sliderChanged(int); void update(); private: KisDoubleParseSpinBox* m_dblNumInput; qreal m_minValue; qreal m_maxValue; }; -class KisHexColorInput : public KisColorInput +class KRITAUI_EXPORT KisHexColorInput : public KisColorInput { Q_OBJECT public: - KisHexColorInput(QWidget* parent, KoColor* color, KoColorDisplayRendererInterface *displayRenderer); + KisHexColorInput(QWidget* parent, KoColor* color, KoColorDisplayRendererInterface *displayRenderer = KoDumbColorDisplayRenderer::instance()); protected: virtual QWidget* createInput(); public Q_SLOTS: void setValue(); void update(); private: QLineEdit* m_hexInput; }; #endif diff --git a/libs/ui/widgets/kis_custom_image_widget.cc b/libs/ui/widgets/kis_custom_image_widget.cc index cd63954727..2269c8a6ba 100644 --- a/libs/ui/widgets/kis_custom_image_widget.cc +++ b/libs/ui/widgets/kis_custom_image_widget.cc @@ -1,467 +1,469 @@ /* This file is part of the Calligra project * Copyright (C) 2005 Thomas Zander * Copyright (C) 2005 C. Boemann * Copyright (C) 2007 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "widgets/kis_custom_image_widget.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_config.h" #include "KisPart.h" #include "kis_clipboard.h" #include "KisDocument.h" #include "widgets/kis_cmb_idlist.h" #include "widgets/squeezedcombobox.h" KisCustomImageWidget::KisCustomImageWidget(QWidget* parent, qint32 defWidth, qint32 defHeight, double resolution, const QString& defColorModel, const QString& defColorDepth, const QString& defColorProfile, const QString& imageName) : WdgNewImage(parent) { setObjectName("KisCustomImageWidget"); m_openPane = qobject_cast(parent); Q_ASSERT(m_openPane); txtName->setText(imageName); m_widthUnit = KoUnit(KoUnit::Pixel, resolution); doubleWidth->setValue(defWidth); doubleWidth->setDecimals(0); m_width = m_widthUnit.fromUserValue(defWidth); cmbWidthUnit->addItems(KoUnit::listOfUnitNameForUi(KoUnit::ListAll)); cmbWidthUnit->setCurrentIndex(m_widthUnit.indexInListForUi(KoUnit::ListAll)); m_heightUnit = KoUnit(KoUnit::Pixel, resolution); doubleHeight->setValue(defHeight); doubleHeight->setDecimals(0); m_height = m_heightUnit.fromUserValue(defHeight); cmbHeightUnit->addItems(KoUnit::listOfUnitNameForUi(KoUnit::ListAll)); cmbHeightUnit->setCurrentIndex(m_heightUnit.indexInListForUi(KoUnit::ListAll)); doubleResolution->setValue(72.0 * resolution); doubleResolution->setDecimals(0); imageGroupSpacer->changeSize(0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed); grpClipboard->hide(); sliderOpacity->setRange(0, 100, 0); sliderOpacity->setValue(100); sliderOpacity->setSuffix("%"); connect(cmbPredefined, SIGNAL(activated(int)), SLOT(predefinedClicked(int))); connect(doubleResolution, SIGNAL(valueChanged(double)), this, SLOT(resolutionChanged(double))); connect(cmbWidthUnit, SIGNAL(activated(int)), this, SLOT(widthUnitChanged(int))); connect(doubleWidth, SIGNAL(valueChanged(double)), this, SLOT(widthChanged(double))); connect(cmbHeightUnit, SIGNAL(activated(int)), this, SLOT(heightUnitChanged(int))); connect(doubleHeight, SIGNAL(valueChanged(double)), this, SLOT(heightChanged(double))); connect(createButton, SIGNAL(clicked()), this, SLOT(createImage())); createButton->setDefault(true); bnPortrait->setIcon(KisIconUtils::loadIcon("portrait")); connect(bnPortrait, SIGNAL(clicked()), SLOT(setPortrait())); connect(bnLandscape, SIGNAL(clicked()), SLOT(setLandscape())); bnLandscape->setIcon(KisIconUtils::loadIcon("landscape")); connect(doubleWidth, SIGNAL(valueChanged(double)), this, SLOT(switchPortraitLandscape())); connect(doubleHeight, SIGNAL(valueChanged(double)), this, SLOT(switchPortraitLandscape())); connect(bnSaveAsPredefined, SIGNAL(clicked()), this, SLOT(saveAsPredefined())); colorSpaceSelector->setCurrentColorModel(KoID(defColorModel)); colorSpaceSelector->setCurrentColorDepth(KoID(defColorDepth)); colorSpaceSelector->setCurrentProfile(defColorProfile); //connect(chkFromClipboard,SIGNAL(stateChanged(int)),this,SLOT(clipboardDataChanged())); connect(QApplication::clipboard(), SIGNAL(dataChanged()), this, SLOT(clipboardDataChanged())); connect(QApplication::clipboard(), SIGNAL(selectionChanged()), this, SLOT(clipboardDataChanged())); connect(QApplication::clipboard(), SIGNAL(changed(QClipboard::Mode)), this, SLOT(clipboardDataChanged())); connect(colorSpaceSelector, SIGNAL(selectionChanged(bool)), createButton, SLOT(setEnabled(bool))); KisConfig cfg; intNumLayers->setValue(cfg.numDefaultLayers()); - cmbColor->setColor(cfg.defaultBackgroundColor()); + KoColor bcol(KoColorSpaceRegistry::instance()->rgb8()); + bcol.fromQColor(cfg.defaultBackgroundColor()); + cmbColor->setColor(bcol); setBackgroundOpacity(cfg.defaultBackgroundOpacity()); KisConfig::BackgroundStyle bgStyle = cfg.defaultBackgroundStyle(); if (bgStyle == KisConfig::LAYER) { radioBackgroundAsLayer->setChecked(true); } else { radioBackgroundAsProjection->setChecked(true); } fillPredefined(); switchPortraitLandscape(); // this makes the portrait and landscape buttons more // obvious what is selected by changing the higlight color QPalette p = QApplication::palette(); QPalette palette_highlight(p ); QColor c = p.color(QPalette::Highlight); palette_highlight.setColor(QPalette::Button, c); bnLandscape->setPalette(palette_highlight); bnPortrait->setPalette(palette_highlight); } void KisCustomImageWidget::showEvent(QShowEvent *) { fillPredefined(); this->createButton->setFocus(); this->createButton->setEnabled(true); } KisCustomImageWidget::~KisCustomImageWidget() { qDeleteAll(m_predefined); m_predefined.clear(); } void KisCustomImageWidget::resolutionChanged(double res) { if (m_widthUnit.type() == KoUnit::Pixel) { m_widthUnit.setFactor(res / 72.0); m_width = m_widthUnit.fromUserValue(doubleWidth->value()); } if (m_heightUnit.type() == KoUnit::Pixel) { m_heightUnit.setFactor(res / 72.0); m_height = m_heightUnit.fromUserValue(doubleHeight->value()); } } void KisCustomImageWidget::widthUnitChanged(int index) { doubleWidth->blockSignals(true); m_widthUnit = KoUnit::fromListForUi(index, KoUnit::ListAll); if (m_widthUnit.type() == KoUnit::Pixel) { doubleWidth->setDecimals(0); m_widthUnit.setFactor(doubleResolution->value() / 72.0); } else { doubleWidth->setDecimals(2); } doubleWidth->setValue(KoUnit::ptToUnit(m_width, m_widthUnit)); doubleWidth->blockSignals(false); } void KisCustomImageWidget::widthChanged(double value) { m_width = m_widthUnit.fromUserValue(value); } void KisCustomImageWidget::heightUnitChanged(int index) { doubleHeight->blockSignals(true); m_heightUnit = KoUnit::fromListForUi(index, KoUnit::ListAll); if (m_heightUnit.type() == KoUnit::Pixel) { doubleHeight->setDecimals(0); m_heightUnit.setFactor(doubleResolution->value() / 72.0); } else { doubleHeight->setDecimals(2); } doubleHeight->setValue(KoUnit::ptToUnit(m_height, m_heightUnit)); doubleHeight->blockSignals(false); } void KisCustomImageWidget::heightChanged(double value) { m_height = m_heightUnit.fromUserValue(value); } void KisCustomImageWidget::createImage() { createButton->setEnabled(false); KisDocument *doc = createNewImage(); if (doc) { doc->setModified(false); emit m_openPane->documentSelected(doc); } } KisDocument* KisCustomImageWidget::createNewImage() { const KoColorSpace * cs = colorSpaceSelector->currentColorSpace(); if (cs->colorModelId() == RGBAColorModelID && cs->colorDepthId() == Integer8BitsColorDepthID) { const KoColorProfile *profile = cs->profile(); if (profile->name().contains("linear") || profile->name().contains("scRGB") || profile->info().contains("linear") || profile->info().contains("scRGB")) { int result = QMessageBox::warning(this, i18nc("@title:window", "Krita"), i18n("Linear gamma RGB color spaces are not supposed to be used " "in 8-bit integer modes. It is suggested to use 16-bit integer " "or any floating point colorspace for linear profiles.\n\n" "Press \"Continue\" to create a 8-bit integer linear RGB color space " "or \"Cancel\" to return to the settings dialog."), QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Cancel); if (result == QMessageBox::Cancel) { dbgKrita << "Model RGB8" << "NOT SUPPORTED"; dbgKrita << ppVar(cs->name()); dbgKrita << ppVar(cs->profile()->name()); dbgKrita << ppVar(cs->profile()->info()); return 0; } } } KisDocument *doc = static_cast(KisPart::instance()->createDocument()); qint32 width, height; double resolution; resolution = doubleResolution->value() / 72.0; // internal resolution is in pixels per pt width = static_cast(0.5 + KoUnit::ptToUnit(m_width, KoUnit(KoUnit::Pixel, resolution))); height = static_cast(0.5 + KoUnit::ptToUnit(m_height, KoUnit(KoUnit::Pixel, resolution))); - QColor qc = cmbColor->color(); + QColor qc = cmbColor->color().toQColor(); qc.setAlpha(backgroundOpacity()); KoColor bgColor(qc, cs); bool backgroundAsLayer = radioBackgroundAsLayer->isChecked(); doc->newImage(txtName->text(), width, height, cs, bgColor, backgroundAsLayer, intNumLayers->value(), txtDescription->toPlainText(), resolution); KisConfig cfg; cfg.setNumDefaultLayers(intNumLayers->value()); cfg.setDefaultBackgroundOpacity(backgroundOpacity()); - cfg.setDefaultBackgroundColor(cmbColor->color()); + cfg.setDefaultBackgroundColor(cmbColor->color().toQColor()); cfg.setDefaultBackgroundStyle(backgroundAsLayer ? KisConfig::LAYER : KisConfig::PROJECTION); return doc; } void KisCustomImageWidget::setNumberOfLayers(int layers) { intNumLayers->setValue(layers); } quint8 KisCustomImageWidget::backgroundOpacity() const { qint32 opacity = sliderOpacity->value(); if (!opacity) return 0; return (opacity * 255) / 100; } void KisCustomImageWidget::setBackgroundOpacity(quint8 value) { sliderOpacity->setValue((value * 100) / 255); } void KisCustomImageWidget::clipboardDataChanged() { } void KisCustomImageWidget::fillPredefined() { cmbPredefined->clear(); qDeleteAll(m_predefined); m_predefined.clear(); cmbPredefined->addItem(""); QStringList definitions = KoResourcePaths::findAllResources("data", "predefined_image_sizes/*.predefinedimage", KoResourcePaths::Recursive); definitions.sort(); if (!definitions.empty()) { Q_FOREACH (const QString &definition, definitions) { QFile f(definition); f.open(QIODevice::ReadOnly); if (f.exists()) { QString xml = QString::fromUtf8(f.readAll()); KisPropertiesConfiguration *predefined = new KisPropertiesConfiguration; predefined->fromXML(xml); if (predefined->hasProperty("name") && predefined->hasProperty("width") && predefined->hasProperty("height") && predefined->hasProperty("resolution") && predefined->hasProperty("x-unit") && predefined->hasProperty("y-unit")) { m_predefined << predefined; cmbPredefined->addItem(predefined->getString("name")); } } } } cmbPredefined->setCurrentIndex(0); } void KisCustomImageWidget::predefinedClicked(int index) { if (index < 1 || index > m_predefined.size()) return; KisPropertiesConfiguration *predefined = m_predefined[index - 1]; txtPredefinedName->setText(predefined->getString("name")); doubleResolution->setValue(predefined->getDouble("resolution")); cmbWidthUnit->setCurrentIndex(predefined->getInt("x-unit")); cmbHeightUnit->setCurrentIndex(predefined->getInt("y-unit")); widthUnitChanged(cmbWidthUnit->currentIndex()); heightUnitChanged(cmbHeightUnit->currentIndex()); doubleWidth->setValue(predefined->getDouble("width")); doubleHeight->setValue(predefined->getDouble("height")); } void KisCustomImageWidget::saveAsPredefined() { QString fileName = txtPredefinedName->text(); if (fileName.isEmpty()) { return; } QString saveLocation = KoResourcePaths::saveLocation("data", "predefined_image_sizes/", true); QFile f(saveLocation + '/' + fileName.replace(' ', '_').replace('(', '_').replace(')', '_') + ".predefinedimage"); f.open(QIODevice::WriteOnly | QIODevice::Truncate); KisPropertiesConfiguration *predefined = new KisPropertiesConfiguration(); predefined->setProperty("name", txtPredefinedName->text()); predefined->setProperty("width", doubleWidth->value()); predefined->setProperty("height", doubleHeight->value()); predefined->setProperty("resolution", doubleResolution->value()); predefined->setProperty("x-unit", cmbWidthUnit->currentIndex()); predefined->setProperty("y-unit", cmbHeightUnit->currentIndex()); QString xml = predefined->toXML(); f.write(xml.toUtf8()); f.flush(); f.close(); int i = 0; bool found = false; Q_FOREACH (KisPropertiesConfiguration *pr, m_predefined) { if (pr->getString("name") == txtPredefinedName->text()) { found = true; break; } ++i; } if (found) { m_predefined[i] = predefined; } else { m_predefined.append(predefined); cmbPredefined->addItem(txtPredefinedName->text()); } } void KisCustomImageWidget::setLandscape() { if (doubleWidth->value() < doubleHeight->value()) { switchWidthHeight(); } } void KisCustomImageWidget::setPortrait() { if (doubleWidth->value() > doubleHeight->value()) { switchWidthHeight(); } } void KisCustomImageWidget::switchWidthHeight() { double width = doubleWidth->value(); double height = doubleHeight->value(); doubleHeight->blockSignals(true); doubleWidth->blockSignals(true); cmbWidthUnit->blockSignals(true); cmbHeightUnit->blockSignals(true); doubleWidth->setValue(height); doubleHeight->setValue(width); cmbWidthUnit->setCurrentIndex(m_heightUnit.indexInListForUi(KoUnit::ListAll)); cmbHeightUnit->setCurrentIndex(m_widthUnit.indexInListForUi(KoUnit::ListAll)); doubleHeight->blockSignals(false); doubleWidth->blockSignals(false); cmbWidthUnit->blockSignals(false); cmbHeightUnit->blockSignals(false); switchPortraitLandscape(); widthChanged(doubleWidth->value()); heightChanged(doubleHeight->value()); } void KisCustomImageWidget::switchPortraitLandscape() { if(doubleWidth->value() > doubleHeight->value()) bnLandscape->setChecked(true); else bnPortrait->setChecked(true); } diff --git a/libs/ui/widgets/kis_screen_color_picker.cpp b/libs/ui/widgets/kis_screen_color_picker.cpp new file mode 100644 index 0000000000..975bddbbf1 --- /dev/null +++ b/libs/ui/widgets/kis_screen_color_picker.cpp @@ -0,0 +1,269 @@ +/* + * Copyright (C) Wolthera van Hovell tot Westerflier , (C) 2016 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kis_icon.h" +#include "kis_screen_color_picker.h" +#include "KisMainWindow.h" +#include +#include "kis_wrapped_rect.h" +#include "KisPart.h" + +struct KisScreenColorPicker::Private +{ + + QPushButton *screenColorPickerButton = 0; + QLabel *lblScreenColorInfo = 0; + + KoColor currentColor = KoColor(); + KoColor beforeScreenColorPicking = KoColor(); + + KisScreenColorPickingEventFilter *colorPickingEventFilter = 0; + +#ifdef Q_OS_WIN32 + QTimer *updateTimer = 0; + QWindow dummyTransparentWindow; +#endif +}; + +KisScreenColorPicker::KisScreenColorPicker(QWidget *parent) : QWidget(parent), m_d(new Private) +{ + QVBoxLayout *layout = new QVBoxLayout(); + this->setLayout(layout); + m_d->screenColorPickerButton = new QPushButton(); + m_d->screenColorPickerButton->setIcon(kisIcon("krita_tool_color_picker")); + m_d->screenColorPickerButton->setMinimumHeight(25); + this->layout()->addWidget(m_d->screenColorPickerButton); + m_d->lblScreenColorInfo = new QLabel(QLatin1String("\n")); + this->layout()->addWidget(m_d->lblScreenColorInfo); + connect(m_d->screenColorPickerButton, SIGNAL(clicked()), SLOT(pickScreenColor())); +#ifdef Q_OS_WIN32 + m_d->updateTimer = new QTimer(q); + m_d->dummyTransparentWindow.resize(1, 1); + m_d->dummyTransparentWindow.setFlags(Qt::Tool | Qt::FramelessWindowHint); + connect(m_d->updateTimer, SIGNAL(timeout()), SLOT(updateColorPicking())); +#endif +} + +KisScreenColorPicker::~KisScreenColorPicker() +{ +} + +KoColor KisScreenColorPicker::currentColor() +{ + return m_d->currentColor; +} + +void KisScreenColorPicker::pickScreenColor() +{ + if (!m_d->colorPickingEventFilter) + m_d->colorPickingEventFilter = new KisScreenColorPickingEventFilter(this); + this->installEventFilter(m_d->colorPickingEventFilter); + // If user pushes Escape, the last color before picking will be restored. + m_d->beforeScreenColorPicking = currentColor(); +#ifndef QT_NO_CURSOR + grabMouse(Qt::CrossCursor); +#else + grabMouse(); +#endif + +#ifdef Q_OS_WIN32 // excludes WinCE and WinRT + // On Windows mouse tracking doesn't work over other processes's windows + m_d->updateTimer->start(30); + + // HACK: Because mouse grabbing doesn't work across processes, we have to have a dummy, + // invisible window to catch the mouse click, otherwise we will click whatever we clicked + // and loose focus. + m_d->dummyTransparentWindow.show(); +#endif + grabKeyboard(); + /* With setMouseTracking(true) the desired color can be more precisely picked up, + * and continuously pushing the mouse button is not necessary. + */ + setMouseTracking(true); + + //emit to the rest of the dialog to disable. + Q_EMIT sigPleaseDisableEverything(true); + m_d->screenColorPickerButton->setDisabled(true); + + const QPoint globalPos = QCursor::pos(); + setCurrentColor(grabScreenColor(globalPos)); + updateColorLabelText(globalPos); +} + +void KisScreenColorPicker::setCurrentColor(KoColor c) +{ + m_d->currentColor = c; +} + +KoColor KisScreenColorPicker::grabScreenColor(const QPoint &p) +{ + // First check whether we're clicking on a Krita window for some real color picking + Q_FOREACH(KisView *view, KisPart::instance()->views()) { + QWidget *canvasWidget = view->canvasBase()->canvasWidget(); + QPoint widgetPoint = canvasWidget->mapFromGlobal(p); + + if (canvasWidget->rect().contains(widgetPoint)) { + QPointF imagePoint = view->canvasBase()->coordinatesConverter()->widgetToImage(widgetPoint); + KisImageWSP image = view->image(); + + if (image) { + if (image->wrapAroundModePermitted()) { + imagePoint = KisWrappedRect::ptToWrappedPt(imagePoint.toPoint(), image->bounds()); + } + KoColor pickedColor = KoColor(); + image->projection()->pixel(imagePoint.x(), imagePoint.y(), &pickedColor); + return pickedColor; + } + } + } + + // And otherwise, we'll check the desktop + const QDesktopWidget *desktop = QApplication::desktop(); + const QPixmap pixmap = QGuiApplication::screens().at(desktop->screenNumber())->grabWindow(desktop->winId(), + p.x(), p.y(), 1, 1); + QImage i = pixmap.toImage(); + KoColor col = KoColor(); + col.fromQColor(QColor::fromRgb(i.pixel(0, 0))); + return col; +} + +void KisScreenColorPicker::updateColorLabelText(const QPoint &globalPos) +{ + KoColor col = grabScreenColor(globalPos); + QString colname = KoColor::toQString(col); + QString location = QString::number(globalPos.x())+QString(", ")+QString::number(globalPos.y()); + m_d->lblScreenColorInfo->setWordWrap(true); + m_d->lblScreenColorInfo->setText(location+QString(": ")+colname); +} + +bool KisScreenColorPicker::handleColorPickingMouseMove(QMouseEvent *e) +{ + // If the cross is visible the grabbed color will be black most of the times + //cp->setCrossVisible(!cp->geometry().contains(e->pos())); + + + continueUpdateColorPicking(e->globalPos()); + return true; +} + +bool KisScreenColorPicker::handleColorPickingMouseButtonRelease(QMouseEvent *e) +{ + setCurrentColor(grabScreenColor(e->globalPos())); + Q_EMIT sigNewColorPicked(currentColor()); + releaseColorPicking(); + return true; +} + +bool KisScreenColorPicker::handleColorPickingKeyPress(QKeyEvent *e) +{ + //Q_Q(QColorDialog); + if (e->matches(QKeySequence::Cancel)) { + releaseColorPicking(); + setCurrentColor(m_d->beforeScreenColorPicking); + } else if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) { + setCurrentColor(grabScreenColor(QCursor::pos())); + releaseColorPicking(); + } + e->accept(); + return true; +} + +void KisScreenColorPicker::releaseColorPicking() +{ + //Q_Q(QColorDialog); + //cp->setCrossVisible(true); + removeEventFilter(m_d->colorPickingEventFilter); + releaseMouse(); +#ifdef Q_OS_WIN32 + m_d->updateTimer->stop(); + m_d->dummyTransparentWindow.setVisible(false); +#endif + releaseKeyboard(); + setMouseTracking(false); + m_d->lblScreenColorInfo->setText(QLatin1String("\n")); + //emit enable signal + Q_EMIT sigPleaseDisableEverything(false); + m_d->screenColorPickerButton->setDisabled(false); +} + +void KisScreenColorPicker::changeEvent(QEvent *e) +{ + QWidget::changeEvent(e); +} + +void KisScreenColorPicker::updateColorPicking() +{ +#ifndef QT_NO_CURSOR + //Q_Q(QColorDialog); + static QPoint lastGlobalPos; + QPoint newGlobalPos = QCursor::pos(); + if (lastGlobalPos == newGlobalPos) + return; + lastGlobalPos = newGlobalPos; + + if (!rect().contains(mapFromGlobal(newGlobalPos))) { // Inside the dialog mouse tracking works, handleColorPickingMouseMove will be called + continueUpdateColorPicking(newGlobalPos); +#ifdef Q_OS_WIN32 + m_dummyTransparentWindow.setPosition(newGlobalPos); +#endif + } +#endif // ! QT_NO_CURSOR +} + +void KisScreenColorPicker::continueUpdateColorPicking(const QPoint &globalPos) +{ + const KoColor color = grabScreenColor(globalPos); + // QTBUG-39792, do not change standard, custom color selectors while moving as + // otherwise it is not possible to pre-select a custom cell for assignment. + setCurrentColor(color); + updateColorLabelText(globalPos); + +} + +// Event filter to be installed on the dialog while in color-picking mode. +KisScreenColorPickingEventFilter::KisScreenColorPickingEventFilter(KisScreenColorPicker *w, QObject *parent) : QObject(parent), m_w(w) +{} + +bool KisScreenColorPickingEventFilter::eventFilter(QObject *, QEvent *event) +{ + switch (event->type()) { + case QEvent::MouseMove: + return m_w->handleColorPickingMouseMove(static_cast(event)); + case QEvent::MouseButtonRelease: + return m_w->handleColorPickingMouseButtonRelease(static_cast(event)); + case QEvent::KeyPress: + return m_w->handleColorPickingKeyPress(static_cast(event)); + default: + break; + } + return false; +} + + +#include "kis_screen_color_picker.moc" diff --git a/libs/ui/widgets/kis_screen_color_picker.h b/libs/ui/widgets/kis_screen_color_picker.h new file mode 100644 index 0000000000..3fdb6a7745 --- /dev/null +++ b/libs/ui/widgets/kis_screen_color_picker.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) Wolthera van Hovell tot Westerflier , (C) 2016 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef KISSCREENCOLORPICKER_H +#define KISSCREENCOLORPICKER_H + +#include +#include +#include + +#include "KoColor.h" + +#include "kritaui_export.h" + +/** + * @brief The KisScreenColorPicker class + * Based on the original QColorDialog's screen color picker, this class provides a button + * that can be used to activate a colorpicker that can pick from anywhere on the screen. + */ +class KRITAUI_EXPORT KisScreenColorPicker : public QWidget +{ + Q_OBJECT +public: + explicit KisScreenColorPicker(QWidget *parent = 0); + ~KisScreenColorPicker(); + + KoColor currentColor(); + + bool handleColorPickingMouseMove(QMouseEvent *e); + bool handleColorPickingMouseButtonRelease(QMouseEvent *e); + bool handleColorPickingKeyPress(QKeyEvent *e); + +Q_SIGNALS: + void sigNewColorPicked(KoColor c); + void sigPleaseDisableEverything(bool disable); + +public Q_SLOTS: + void pickScreenColor(); + +private Q_SLOTS: + void updateColorPicking(); +protected: + void changeEvent(QEvent *event) Q_DECL_OVERRIDE; +private: + struct Private; //The private struct + const QScopedPointer m_d; //the private pointer + + void setCurrentColor(KoColor c); + KoColor grabScreenColor(const QPoint &p); + void updateColorLabelText(const QPoint &globalPos); + void releaseColorPicking(); + void continueUpdateColorPicking(const QPoint &globalPos); +}; + +class KisScreenColorPickingEventFilter : public QObject { +public: + explicit KisScreenColorPickingEventFilter(KisScreenColorPicker *w, QObject *parent = 0); + + bool eventFilter(QObject *, QEvent *event) Q_DECL_OVERRIDE; +private: + KisScreenColorPicker *m_w; +}; + +#endif // KISSCREENCOLORPICKER_H diff --git a/libs/ui/widgets/kis_spinbox_color_selector.cpp b/libs/ui/widgets/kis_spinbox_color_selector.cpp new file mode 100644 index 0000000000..1d8f211bd4 --- /dev/null +++ b/libs/ui/widgets/kis_spinbox_color_selector.cpp @@ -0,0 +1,241 @@ +/* + * Copyright (C) Wolthera van Hovell tot Westerflier , (C) 2016 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "kis_spinbox_color_selector.h" +#include +#include +#include "kis_double_parse_spin_box.h" +#include "kis_int_parse_spin_box.h" +#include "kis_signal_compressor.h" + +#include "KoChannelInfo.h" +#include "KoColorSpaceTraits.h" +#include "KoColorSpaceMaths.h" +#include "KoColorSpaceRegistry.h" + +struct KisSpinboxColorSelector::Private +{ + QList spinBoxList; + QList doubleSpinBoxList; + KoColor color; + const KoColorSpace *cs; + bool chooseAlpha = false; +}; + +KisSpinboxColorSelector::KisSpinboxColorSelector(QWidget *parent) : QWidget(parent) , m_d(new Private) +{ + this->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); + + KoColor color = KoColor(); + m_d->color = color; + slotSetColorSpace(m_d->color.colorSpace()); +} +KisSpinboxColorSelector::~KisSpinboxColorSelector() +{ + +} + +void KisSpinboxColorSelector::slotSetColor(KoColor color) +{ + m_d->color = color; + if (m_d->color.colorSpace() != m_d->cs) { + slotSetColorSpace(m_d->color.colorSpace()); + } + updateSpinboxesWithNewValues(); +} + +void KisSpinboxColorSelector::slotSetColorSpace(const KoColorSpace *cs) +{ + if (cs == m_d->cs) { + return; + } + + m_d->cs = KoColorSpaceRegistry::instance()->colorSpace(cs->colorModelId().id(), cs->colorDepthId().id(), cs->profile()); + + //remake spinboxes + if (this->layout()) { + qDeleteAll(this->children()); + } + m_d->spinBoxList.clear(); + m_d->doubleSpinBoxList.clear(); + + QFormLayout *layout = new QFormLayout(this); + QList channels = KoChannelInfo::displayOrderSorted(m_d->cs->channels()); + Q_FOREACH (KoChannelInfo* channel, channels) { + QString inputLabel = channel->name(); + switch (channel->channelValueType()) { + case KoChannelInfo::UINT8: { + KisIntParseSpinBox *input = new KisIntParseSpinBox(this); + input->setMinimum(0); + input->setMaximum(0xFF); + m_d->spinBoxList.append(input); + layout->addRow(inputLabel,input); + if (input) { + connect(input, SIGNAL(valueChanged(int)), this, SLOT(slotUpdateFromSpinBoxes())); + } + if (channel->channelType()==KoChannelInfo::ALPHA && m_d->chooseAlpha == false) { + input->setEnabled(false); + input->blockSignals(true); + } + } + break; + case KoChannelInfo::UINT16: { + KisIntParseSpinBox *input = new KisIntParseSpinBox(this); + input->setMinimum(0); + input->setMaximum(0xFFFF); + m_d->spinBoxList.append(input); + layout->addRow(inputLabel,input); + if (input) { + connect(input, SIGNAL(valueChanged(int)), this, SLOT(slotUpdateFromSpinBoxes())); + } + if (channel->channelType()==KoChannelInfo::ALPHA && m_d->chooseAlpha == false) { + input->setEnabled(false); + input->blockSignals(true); + } + } + break; + case KoChannelInfo::UINT32: { + KisIntParseSpinBox *input = new KisIntParseSpinBox(this); + input->setMinimum(0); + input->setMaximum(0xFFFFFFFF); + m_d->spinBoxList.append(input); + layout->addRow(inputLabel,input); + if (input) { + connect(input, SIGNAL(valueChanged(int)), this, SLOT(slotUpdateFromSpinBoxes())); + } + if (channel->channelType()==KoChannelInfo::ALPHA && m_d->chooseAlpha == false) { + input->setEnabled(false); + input->blockSignals(true); + } + } + break; + case KoChannelInfo::FLOAT16: + case KoChannelInfo::FLOAT32: { + KisDoubleParseSpinBox *input = new KisDoubleParseSpinBox(this); + input->setMinimum(0); + input->setMaximum(KoColorSpaceMathsTraits::max); + input->setSingleStep(0.1); + m_d->doubleSpinBoxList.append(input); + qDebug()<<"add "<name()<<"doubleSpinBoxList "<doubleSpinBoxList.size(); + layout->addRow(inputLabel,input); + if (input) { + connect(input, SIGNAL(valueChanged(double)), this, SLOT(slotUpdateFromSpinBoxes())); + } + if (channel->channelType()==KoChannelInfo::ALPHA && m_d->chooseAlpha == false) { + input->setEnabled(false); + input->blockSignals(true); + } + } + break; + default: + Q_ASSERT(false); + } + + } + this->setLayout(layout); +} + +void KisSpinboxColorSelector::createColorFromSpinboxValues() +{ + KoColor newColor; + int channelcount = m_d->cs->channelCount(); + quint8 *data = new quint8[m_d->cs->pixelSize()]; + QVector channelValues(channelcount); + channelValues.fill(1.0); + QList channels = KoChannelInfo::displayOrderSorted(m_d->cs->channels()); + + for (int i=0; ics->colorChannelCount()); i++) { + int channelposition = KoChannelInfo::displayPositionToChannelIndex(i, m_d->cs->channels()); + + if (channels.at(i)->channelValueType()==KoChannelInfo::UINT8 && m_d->spinBoxList.at(i)){ + + int value = m_d->spinBoxList.at(i)->value(); + channelValues[channelposition] = KoColorSpaceMaths::scaleToA(value); + + } else if (channels.at(i)->channelValueType()==KoChannelInfo::UINT16 && m_d->spinBoxList.at(i)){ + + channelValues[channelposition] = KoColorSpaceMaths::scaleToA(m_d->spinBoxList.at(i)->value()); + + } else if ((channels.at(i)->channelValueType()==KoChannelInfo::FLOAT16 || + channels.at(i)->channelValueType()==KoChannelInfo::FLOAT32 || + channels.at(i)->channelValueType()==KoChannelInfo::FLOAT64) && m_d->doubleSpinBoxList.at(i)) { + + channelValues[channelposition] = m_d->doubleSpinBoxList.at(i)->value(); + + } + } + + m_d->cs->fromNormalisedChannelsValue(data, channelValues); + newColor.setColor(data, m_d->cs); + newColor.setOpacity(m_d->color.opacityU8()); + + m_d->color = newColor; +} + +void KisSpinboxColorSelector::slotUpdateFromSpinBoxes() +{ + createColorFromSpinboxValues(); + emit sigNewColor(m_d->color); +} + +void KisSpinboxColorSelector::updateSpinboxesWithNewValues() +{ + int channelcount = m_d->cs->channelCount(); + QVector channelValues(channelcount); + channelValues.fill(1.0); + m_d->cs->normalisedChannelsValue(m_d->color.data(), channelValues); + QList channels = KoChannelInfo::displayOrderSorted(m_d->cs->channels()); + + int i; + /*while (QLayoutItem *item = this->layout()->takeAt(0)) + { + item->widget()->blockSignals(true); + }*/ + for (i=0; ispinBoxList.size(); i++) { + m_d->spinBoxList.at(i)->blockSignals(true); + } + for (i=0; idoubleSpinBoxList.size(); i++) { + m_d->doubleSpinBoxList.at(i)->blockSignals(true); + } + + for (i=0; ics->colorChannelCount()); i++) { + int channelposition = KoChannelInfo::displayPositionToChannelIndex(i, m_d->cs->channels()); + if (channels.at(i)->channelValueType() == KoChannelInfo::UINT8 && m_d->spinBoxList.at(i)) { + int value = KoColorSpaceMaths::scaleToA(channelValues[channelposition]); + m_d->spinBoxList.at(i)->setValue(value); + } else if (channels.at(i)->channelValueType() == KoChannelInfo::UINT16 && m_d->spinBoxList.at(i)) { + m_d->spinBoxList.at(i)->setValue(KoColorSpaceMaths::scaleToA(channelValues[channelposition])); + } else if ((channels.at(i)->channelValueType()==KoChannelInfo::FLOAT16 || + channels.at(i)->channelValueType()==KoChannelInfo::FLOAT32 || + channels.at(i)->channelValueType()==KoChannelInfo::FLOAT64) && m_d->doubleSpinBoxList.at(i)) { + m_d->doubleSpinBoxList.at(i)->setValue(channelValues[channelposition]); + } + } + + for (i=0; ispinBoxList.size(); i++) { + m_d->spinBoxList.at(i)->blockSignals(false); + } + for (i=0; idoubleSpinBoxList.size(); i++) { + m_d->doubleSpinBoxList.at(i)->blockSignals(false); + } + /*while (QLayoutItem *item = this->layout()->takeAt(0)) + { + item->widget()->blockSignals(false); + }*/ +} + + diff --git a/libs/ui/widgets/kis_spinbox_color_selector.h b/libs/ui/widgets/kis_spinbox_color_selector.h new file mode 100644 index 0000000000..7c3106f485 --- /dev/null +++ b/libs/ui/widgets/kis_spinbox_color_selector.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) Wolthera van Hovell tot Westerflier , (C) 2016 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KISSPINBOXCOLORSELECTOR_H +#define KISSPINBOXCOLORSELECTOR_H + +#include +#include "kritaui_export.h" +#include +#include "KoColor.h" +#include "KoColorSpace.h" + +/** + * @brief The KisSpinboxColorSelector class + * This will give a widget with spinboxes depending on the color space + * Take responsibility for changing the color space. + */ +class KRITAUI_EXPORT KisSpinboxColorSelector : public QWidget +{ + Q_OBJECT +public: + explicit KisSpinboxColorSelector(QWidget *parent); + ~KisSpinboxColorSelector(); + + void chooseAlpha(bool chooseAlpha); + +Q_SIGNALS: + + void sigNewColor(KoColor color); + +public Q_SLOTS: + + void slotSetColorSpace(const KoColorSpace *cs); + void slotSetColor(KoColor color); +private Q_SLOTS: + void slotUpdateFromSpinBoxes(); +private: + struct Private; + const QScopedPointer m_d; + void createColorFromSpinboxValues(); + void updateSpinboxesWithNewValues(); +}; + +#endif // KISSPINBOXCOLORSELECTOR_H diff --git a/libs/ui/widgets/kis_visual_color_selector.cpp b/libs/ui/widgets/kis_visual_color_selector.cpp new file mode 100644 index 0000000000..ab01388906 --- /dev/null +++ b/libs/ui/widgets/kis_visual_color_selector.cpp @@ -0,0 +1,1602 @@ +/* + * Copyright (C) Wolthera van Hovell tot Westerflier , (C) 2016 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "kis_visual_color_selector.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "KoColorConversions.h" +#include "KoColorDisplayRendererInterface.h" +#include "KoChannelInfo.h" +#include +#include +#include "kis_signal_compressor.h" + +struct KisVisualColorSelector::Private +{ + KoColor currentcolor; + const KoColorSpace *currentCS; + QList widgetlist; + bool updateSelf = false; + bool updateLonesome = false; //for Modal dialogs. + bool circular = false; + const KoColorDisplayRendererInterface *displayRenderer = 0; + KisVisualColorSelector::Configuration acs_config; + //Current coordinates. + KisSignalCompressor *updateTimer = 0; + QVector currentCoordinates; +}; + +KisVisualColorSelector::KisVisualColorSelector(QWidget *parent) : QWidget(parent), m_d(new Private) +{ + this->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); + QVBoxLayout *layout = new QVBoxLayout; + this->setLayout(layout); + + KConfigGroup cfg = KSharedConfig::openConfig()->group("advancedColorSelector"); + m_d->acs_config = Configuration::fromString(cfg.readEntry("colorSelectorConfiguration", KisVisualColorSelector::Configuration().toString())); + +} + +KisVisualColorSelector::~KisVisualColorSelector() +{ + +} + +void KisVisualColorSelector::slotSetColor(KoColor c) +{ + if (m_d->updateSelf==false) { + m_d->currentcolor = c; + if (m_d->currentCS != c.colorSpace()) { + slotsetColorSpace(c.colorSpace()); + } + } + updateSelectorElements(QObject::sender()); +} + +void KisVisualColorSelector::slotsetColorSpace(const KoColorSpace *cs) +{ + if (m_d->currentCS != cs) + { + m_d->currentCS = cs; + slotRebuildSelectors(); + } + +} + +void KisVisualColorSelector::setConfig(bool forceCircular, bool forceSelfUpdate) +{ + m_d->updateLonesome = forceSelfUpdate; + m_d->circular = forceCircular; +} + +KoColor KisVisualColorSelector::getCurrentColor() +{ + return m_d->currentcolor; +} + +void KisVisualColorSelector::ConfigurationChanged() +{ + m_d->updateTimer = new KisSignalCompressor(100 /* ms */, KisSignalCompressor::POSTPONE, this); + m_d->updateTimer->start(); + connect(m_d->updateTimer, SIGNAL(timeout()), SLOT(slotRebuildSelectors()), Qt::UniqueConnection); +} + +void KisVisualColorSelector::slotRebuildSelectors() +{ + KConfigGroup cfg = KSharedConfig::openConfig()->group("advancedColorSelector"); + m_d->acs_config = Configuration::fromString(cfg.readEntry("colorSelectorConfiguration", KisVisualColorSelector::Configuration().toString())); + + if (this->children().at(0)) { + qDeleteAll(this->children()); + } + m_d->widgetlist.clear(); + QLayout *layout = new QHBoxLayout; + //redraw all the widgets. + int sizeValue = qMin(width(), height()); + int borderWidth = qMax(sizeValue*0.1, 20.0); + + if (m_d->currentCS->colorChannelCount() == 1) { + KisVisualColorSelectorShape *bar; + if (m_d->circular==false) { + bar = new KisVisualRectangleSelectorShape(this, KisVisualColorSelectorShape::onedimensional,KisVisualColorSelectorShape::Channel, m_d->currentCS, 0, 0,m_d->displayRenderer, borderWidth); + bar->setMaximumWidth(width()*0.1); + bar->setMaximumHeight(height()); + + } else { + bar= new KisVisualEllipticalSelectorShape(this, KisVisualColorSelectorShape::onedimensional,KisVisualColorSelectorShape::Channel, m_d->currentCS, 0, 0,m_d->displayRenderer, borderWidth, KisVisualEllipticalSelectorShape::borderMirrored); + layout->setMargin(0); + } + connect (bar, SIGNAL(sigNewColor(KoColor)), this, SLOT(updateFromWidgets(KoColor))); + layout->addWidget(bar); + m_d->widgetlist.append(bar); + } else if (m_d->currentCS->colorChannelCount() == 3) { + QRect newrect(0,0, this->geometry().width(), this->geometry().height()); + + + KisVisualColorSelectorShape::ColorModel modelS = KisVisualColorSelectorShape::HSV; + int channel1 = 0; + int channel2 = 1; + int channel3 = 2; + + switch(m_d->acs_config.subTypeParameter) + { + case H: + channel1 = 0; break; + case hsyS: + case hsiS: + case hslS: + case hsvS: + channel1 = 1; break; + case V: + case L: + case I: + case Y: + channel1 = 2; break; + } + + switch(m_d->acs_config.mainTypeParameter) + { + case hsySH: + modelS = KisVisualColorSelectorShape::HSY; + channel2 = 0; + channel3 = 1; + break; + case hsiSH: + modelS = KisVisualColorSelectorShape::HSI; + channel2 = 0; + channel3 = 1; + break; + case hslSH: + modelS = KisVisualColorSelectorShape::HSL; + channel2 = 0; + channel3 = 1; + break; + case hsvSH: + modelS = KisVisualColorSelectorShape::HSV; + channel2 = 0; + channel3 = 1; + break; + case YH: + modelS = KisVisualColorSelectorShape::HSY; + channel2 = 0; + channel3 = 2; + break; + case LH: + modelS = KisVisualColorSelectorShape::HSL; + channel2 = 0; + channel3 = 2; + break; + case IH: + modelS = KisVisualColorSelectorShape::HSL; + channel2 = 0; + channel3 = 2; + break; + case VH: + modelS = KisVisualColorSelectorShape::HSV; + channel2 = 0; + channel3 = 2; + break; + case SY: + modelS = KisVisualColorSelectorShape::HSY; + channel2 = 1; + channel3 = 2; + break; + case SI: + modelS = KisVisualColorSelectorShape::HSI; + channel2 = 1; + channel3 = 2; + break; + case SL: + modelS = KisVisualColorSelectorShape::HSL; + channel2 = 1; + channel3 = 2; + break; + case SV: + case SV2: + modelS = KisVisualColorSelectorShape::HSV; + channel2 = 1; + channel3 = 2; + break; + } + if (m_d->acs_config.mainType==Triangle) { + modelS = KisVisualColorSelectorShape::HSV; + //Triangle only really works in HSV mode. + } + KisVisualColorSelectorShape *bar; + if (m_d->acs_config.subType==Ring) { + bar = new KisVisualEllipticalSelectorShape(this, + KisVisualColorSelectorShape::onedimensional, + modelS, + m_d->currentCS, channel1, channel1, + m_d->displayRenderer, borderWidth,KisVisualEllipticalSelectorShape::border); + bar->resize(sizeValue, sizeValue); + } else if (m_d->acs_config.subType==Slider && m_d->circular==false) { + bar = new KisVisualRectangleSelectorShape(this, + KisVisualColorSelectorShape::onedimensional, + modelS, + m_d->currentCS, channel1, channel1, + m_d->displayRenderer, borderWidth); + bar->setMaximumWidth(borderWidth); + bar->setMinimumWidth(borderWidth); + bar->setMinimumHeight(sizeValue); + } else if (m_d->acs_config.subType==Slider && m_d->circular==true) { + bar = new KisVisualEllipticalSelectorShape(this, + KisVisualColorSelectorShape::onedimensional, + modelS, + m_d->currentCS, channel1, channel1, + m_d->displayRenderer, borderWidth, KisVisualEllipticalSelectorShape::borderMirrored); + bar->resize(sizeValue, sizeValue); + } + + bar->setColor(m_d->currentcolor); + m_d->widgetlist.append(bar); + + KisVisualColorSelectorShape *block; + if (m_d->acs_config.mainType==Triangle) { + block = new KisVisualTriangleSelectorShape(this, KisVisualColorSelectorShape::twodimensional, + modelS, + m_d->currentCS, channel2, channel3, + m_d->displayRenderer); + block->setGeometry(bar->getSpaceForTriangle(newrect)); + } else if (m_d->acs_config.mainType==Square) { + block = new KisVisualRectangleSelectorShape(this, KisVisualColorSelectorShape::twodimensional, + modelS, + m_d->currentCS, channel2, channel3, + m_d->displayRenderer); + block->setGeometry(bar->getSpaceForSquare(newrect)); + } else { + block = new KisVisualEllipticalSelectorShape(this, KisVisualColorSelectorShape::twodimensional, + modelS, + m_d->currentCS, channel2, channel3, + m_d->displayRenderer); + block->setGeometry(bar->getSpaceForCircle(newrect)); + + } + + block->setColor(m_d->currentcolor); + connect (bar, SIGNAL(sigNewColor(KoColor)), block, SLOT(setColorFromSibling(KoColor))); + connect (block, SIGNAL(sigNewColor(KoColor)), SLOT(updateFromWidgets(KoColor))); + connect (bar, SIGNAL(sigHSXchange()), SLOT(HSXwrangler())); + connect (block, SIGNAL(sigHSXchange()), SLOT(HSXwrangler())); + m_d->widgetlist.append(block); + + + } else if (m_d->currentCS->colorChannelCount() == 4) { + KisVisualRectangleSelectorShape *block = new KisVisualRectangleSelectorShape(this, KisVisualRectangleSelectorShape::twodimensional,KisVisualColorSelectorShape::Channel, m_d->currentCS, 0, 1); + KisVisualRectangleSelectorShape *block2 = new KisVisualRectangleSelectorShape(this, KisVisualRectangleSelectorShape::twodimensional,KisVisualColorSelectorShape::Channel, m_d->currentCS, 2, 3); + block->setMaximumWidth(width()*0.5); + block->setMaximumHeight(height()); + block2->setMaximumWidth(width()*0.5); + block2->setMaximumHeight(height()); + block->setColor(m_d->currentcolor); + block2->setColor(m_d->currentcolor); + connect (block, SIGNAL(sigNewColor(KoColor)), block2, SLOT(setColorFromSibling(KoColor))); + connect (block2, SIGNAL(sigNewColor(KoColor)), SLOT(updateFromWidgets(KoColor))); + layout->addWidget(block); + layout->addWidget(block2); + m_d->widgetlist.append(block); + m_d->widgetlist.append(block2); + } + this->setLayout(layout); +} + +void KisVisualColorSelector::setDisplayRenderer (const KoColorDisplayRendererInterface *displayRenderer) { + m_d->displayRenderer = displayRenderer; + if (m_d->widgetlist.size()>0) { + Q_FOREACH (KisVisualColorSelectorShape *shape, m_d->widgetlist) { + shape->setDisplayRenderer(displayRenderer); + } + } +} + +void KisVisualColorSelector::updateSelectorElements(QObject *source) +{ + //first lock all elements from sending updates, then update all elements. + Q_FOREACH (KisVisualColorSelectorShape *shape, m_d->widgetlist) { + shape->blockSignals(true); + } + + Q_FOREACH (KisVisualColorSelectorShape *shape, m_d->widgetlist) { + if (shape!=source) { + if (m_d->updateSelf) { + shape->setColorFromSibling(m_d->currentcolor); + } else { + shape->setColor(m_d->currentcolor); + } + } + } + Q_FOREACH (KisVisualColorSelectorShape *shape, m_d->widgetlist) { + shape->blockSignals(false); + } + +} + +void KisVisualColorSelector::updateFromWidgets(KoColor c) +{ + m_d->currentcolor = c; + m_d->updateSelf = true; + if (m_d->updateLonesome) { + slotSetColor(c); + } else { + Q_EMIT sigNewColor(c); + } +} + +void KisVisualColorSelector::leaveEvent(QEvent *) +{ + m_d->updateSelf = false; +} + +void KisVisualColorSelector::resizeEvent(QResizeEvent *) { + int sizeValue = qMin(width(), height()); + int borderWidth = qMax(sizeValue*0.1, 20.0); + QRect newrect(0,0, this->geometry().width(), this->geometry().height()); + if (!m_d->currentCS) { + slotsetColorSpace(m_d->currentcolor.colorSpace()); + } + if (m_d->currentCS->colorChannelCount()==3) { + if (m_d->acs_config.subType==Ring) { + m_d->widgetlist.at(0)->resize(sizeValue,sizeValue); + } else if (m_d->acs_config.subType==Slider && m_d->circular==false) { + m_d->widgetlist.at(0)->setMaximumWidth(borderWidth); + m_d->widgetlist.at(0)->setMinimumWidth(borderWidth); + m_d->widgetlist.at(0)->setMinimumHeight(sizeValue); + m_d->widgetlist.at(0)->setMaximumHeight(sizeValue); + } else if (m_d->acs_config.subType==Slider && m_d->circular==true) { + m_d->widgetlist.at(0)->resize(sizeValue,sizeValue); + } + m_d->widgetlist.at(0)->setBorderWidth(borderWidth); + + if (m_d->acs_config.mainType==Triangle) { + m_d->widgetlist.at(1)->setGeometry(m_d->widgetlist.at(0)->getSpaceForTriangle(newrect)); + } else if (m_d->acs_config.mainType==Square) { + m_d->widgetlist.at(1)->setGeometry(m_d->widgetlist.at(0)->getSpaceForSquare(newrect)); + } else if (m_d->acs_config.mainType==Wheel) { + m_d->widgetlist.at(1)->setGeometry(m_d->widgetlist.at(0)->getSpaceForCircle(newrect)); + } + } + Q_FOREACH (KisVisualColorSelectorShape *shape, m_d->widgetlist) { + shape->update(); + } +} + +void KisVisualColorSelector::HSXwrangler() +{ + m_d->currentCoordinates = QVector (3); + + QVector w1 = m_d->widgetlist.at(0)->getHSX(m_d->currentCoordinates, true); + QVector w2 = m_d->widgetlist.at(1)->getHSX(m_d->currentCoordinates, true); + QVector ch(3); + + ch[0] = m_d->widgetlist.at(0)->getChannels().at(0); + ch[1] = m_d->widgetlist.at(1)->getChannels().at(0); + ch[2] = m_d->widgetlist.at(1)->getChannels().at(1); + + m_d->currentCoordinates[ch[0]] = w1[ch[0]]; + m_d->currentCoordinates[ch[1]] = w2[ch[1]]; + m_d->currentCoordinates[ch[2]] = w2[ch[2]]; + + m_d->widgetlist.at(0)->setHSX(m_d->currentCoordinates, true); + m_d->widgetlist.at(1)->setHSX(m_d->currentCoordinates, true); +} + +/*------------Selector shape------------*/ +struct KisVisualColorSelectorShape::Private +{ + QImage gradient; + QImage fullSelector; + bool imagesNeedUpdate= true; + QPointF currentCoordinates; + Dimensions dimension; + ColorModel model; + const KoColorSpace *cs; + KoColor currentColor; + int channel1; + int channel2; + KisSignalCompressor *updateTimer; + KisSignalCompressor *siblingTimer; + bool mousePressActive = false; + const KoColorDisplayRendererInterface *displayRenderer = 0; + qreal hue = 0.0; + qreal sat = 0.0; + qreal tone = 0.0; + +}; + +KisVisualColorSelectorShape::KisVisualColorSelectorShape(QWidget *parent, + KisVisualColorSelectorShape::Dimensions dimension, + KisVisualColorSelectorShape::ColorModel model, + const KoColorSpace *cs, + int channel1, + int channel2, + const KoColorDisplayRendererInterface *displayRenderer): QWidget(parent), m_d(new Private) +{ + m_d->dimension = dimension; + m_d->model = model; + m_d->cs = cs; + m_d->currentColor = KoColor(); + m_d->currentColor.setOpacity(1.0); + m_d->currentColor.convertTo(cs); + int maxchannel = m_d->cs->colorChannelCount()-1; + m_d->channel1 = qBound(0, channel1, maxchannel); + m_d->channel2 = qBound(0, channel2, maxchannel); + this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + m_d->updateTimer = new KisSignalCompressor(100 /* ms */, KisSignalCompressor::POSTPONE, this); + m_d->siblingTimer = new KisSignalCompressor(30 /* ms */, KisSignalCompressor::POSTPONE, this); + setDisplayRenderer(displayRenderer); + show(); + +} + +KisVisualColorSelectorShape::~KisVisualColorSelectorShape() +{ + +} + +void KisVisualColorSelectorShape::updateCursor() +{ + QPointF point1 = convertKoColorToShapeCoordinate(m_d->currentColor); + if (point1 != m_d->currentCoordinates) { + m_d->currentCoordinates = point1; + } +} + +QPointF KisVisualColorSelectorShape::getCursorPosition() { + return m_d->currentCoordinates; +} + +void KisVisualColorSelectorShape::setColor(KoColor c) +{ + if (c.colorSpace() != m_d->cs) { + c.convertTo(m_d->cs); + } + m_d->currentColor = c; + updateCursor(); + m_d->imagesNeedUpdate = true; + update(); +} + +void KisVisualColorSelectorShape::setColorFromSibling(KoColor c) +{ + if (c.colorSpace() != m_d->cs) { + c.convertTo(m_d->cs); + } + m_d->currentColor = c; + Q_EMIT sigNewColor(c); + m_d->imagesNeedUpdate = true; + update(); +} + +void KisVisualColorSelectorShape::setDisplayRenderer (const KoColorDisplayRendererInterface *displayRenderer) +{ + if (displayRenderer) { + if (m_d->displayRenderer) { + m_d->displayRenderer->disconnect(this); + } + m_d->displayRenderer = displayRenderer; + } else { + m_d->displayRenderer = KoDumbColorDisplayRenderer::instance(); + } + connect(m_d->displayRenderer, SIGNAL(displayConfigurationChanged()), + SLOT(updateFromChangedDisplayRenderer()), Qt::UniqueConnection); + +} + +void KisVisualColorSelectorShape::updateFromChangedDisplayRenderer() +{ + m_d->imagesNeedUpdate = true; + updateCursor(); + //m_d->currentColor = convertShapeCoordinateToKoColor(getCursorPosition()); + update(); +} + +void KisVisualColorSelectorShape::forceImageUpdate() +{ + m_d->imagesNeedUpdate = true; +} + +QColor KisVisualColorSelectorShape::getColorFromConverter(KoColor c){ + QColor col; + KoColor color = c; + if (m_d->displayRenderer) { + color.convertTo(m_d->displayRenderer->getPaintingColorSpace()); + col = m_d->displayRenderer->toQColor(c); + } else { + col = c.toQColor(); + } + return col; +} + +void KisVisualColorSelectorShape::slotSetActiveChannels(int channel1, int channel2) +{ + int maxchannel = m_d->cs->colorChannelCount()-1; + m_d->channel1 = qBound(0, channel1, maxchannel); + m_d->channel2 = qBound(0, channel2, maxchannel); + m_d->imagesNeedUpdate = true; + update(); +} + +QImage KisVisualColorSelectorShape::getImageMap() +{ + if (m_d->imagesNeedUpdate == true) { + m_d->imagesNeedUpdate = false; + m_d->gradient = QImage(width(), height(), QImage::Format_ARGB32); + m_d->gradient.fill(Qt::transparent); + QImage img(width(), height(), QImage::Format_ARGB32); + img.fill(Qt::transparent); + for (int y = 0; y(img.scanLine(y)); + for (int x=0; xgradient = img; + } + return m_d->gradient; +} + +KoColor KisVisualColorSelectorShape::convertShapeCoordinateToKoColor(QPointF coordinates, bool cursor) +{ + KoColor c = m_d->currentColor; + QVector channelValues (c.colorSpace()->channelCount()); + channelValues.fill(1.0); + c.colorSpace()->normalisedChannelsValue(c.data(), channelValues); + QVector channelValuesDisplay = channelValues; + QVector maxvalue(c.colorSpace()->channelCount()); + maxvalue.fill(1.0); + if (m_d->displayRenderer + && (m_d->cs->colorDepthId() == Float16BitsColorDepthID + || m_d->cs->colorDepthId() == Float32BitsColorDepthID + || m_d->cs->colorDepthId() == Float64BitsColorDepthID) + && m_d->cs->colorModelId() != LABAColorModelID + && m_d->cs->colorModelId() != CMYKAColorModelID) { + for (int ch = 0; chcs->channels()[ch]; + maxvalue[ch] = m_d->displayRenderer->maxVisibleFloatValue(channel); + channelValues[ch] = channelValues[ch]/(maxvalue[ch]); + channelValuesDisplay[KoChannelInfo::displayPositionToChannelIndex(ch, m_d->cs->channels())] = channelValues[ch]; + } + } else { + for (int i =0; ics->channels())] = qBound((float)0.0,channelValues[i], (float)1.0); + } + } + qreal huedivider = 1.0; + qreal huedivider2 = 1.0; + + if (m_d->channel1==0) { + huedivider = 360.0; + } + if (m_d->channel2==0) { + huedivider2 = 360.0; + } + if (m_d->model != ColorModel::Channel && c.colorSpace()->colorModelId().id() == "RGBA") { + if (c.colorSpace()->colorModelId().id() == "RGBA") { + if (m_d->model == ColorModel::HSV){ + /* + * RGBToHSV has a undefined hue possibility. This means that hue will be -1. + * This can be annoying for dealing with a selector, but I understand it is being + * used for the KoColorSelector... For now implement a qMax here. + */ + QVector inbetween(3); + RGBToHSV(channelValuesDisplay[0],channelValuesDisplay[1], channelValuesDisplay[2], &inbetween[0], &inbetween[1], &inbetween[2]); + inbetween = convertvectorqrealTofloat(getHSX(convertvectorfloatToqreal(inbetween))); + inbetween[m_d->channel1] = coordinates.x()*huedivider; + if (m_d->dimension == Dimensions::twodimensional) { + inbetween[m_d->channel2] = coordinates.y()*huedivider2; + } + if (cursor==true){setHSX(convertvectorfloatToqreal(inbetween));Q_EMIT sigHSXchange();} + HSVToRGB(qMax(inbetween[0],(float)0.0), inbetween[1], inbetween[2], &channelValuesDisplay[0], &channelValuesDisplay[1], &channelValuesDisplay[2]); + } else if (m_d->model == ColorModel::HSL) { + /* + * HSLToRGB can give negative values on the grey. I fixed the fromNormalisedChannel function to clamp, + * but you might want to manually clamp for floating point values. + */ + QVector inbetween(3); + RGBToHSL(channelValuesDisplay[0],channelValuesDisplay[1], channelValuesDisplay[2], &inbetween[0], &inbetween[1], &inbetween[2]); + inbetween = convertvectorqrealTofloat(getHSX(convertvectorfloatToqreal(inbetween))); + inbetween[m_d->channel1] = fmod(coordinates.x()*huedivider, 360.0); + if (m_d->dimension == Dimensions::twodimensional) { + inbetween[m_d->channel2] = coordinates.y()*huedivider2; + } + if (cursor==true){setHSX(convertvectorfloatToqreal(inbetween));Q_EMIT sigHSXchange();} + HSLToRGB(qMax(inbetween[0],(float)0.0), inbetween[1], inbetween[2],&channelValuesDisplay[0],&channelValuesDisplay[1], &channelValuesDisplay[2]); + } else if (m_d->model == ColorModel::HSI) { + /* + * HSI is a modified HSY function. + */ + QVector chan2 = convertvectorfloatToqreal(channelValuesDisplay); + QVector inbetween(3); + RGBToHSI(chan2[0],chan2[1], chan2[2], &inbetween[0], &inbetween[1], &inbetween[2]); + inbetween = getHSX(inbetween); + inbetween[m_d->channel1] = coordinates.x(); + if (m_d->dimension == Dimensions::twodimensional) { + inbetween[m_d->channel2] = coordinates.y(); + } + if (cursor==true){setHSX(inbetween);Q_EMIT sigHSXchange();} + HSIToRGB(inbetween[0], inbetween[1], inbetween[2],&chan2[0],&chan2[1], &chan2[2]); + channelValuesDisplay = convertvectorqrealTofloat(chan2); + } else /*if (m_d->model == ColorModel::HSY)*/ { + /* + * HSY is pretty slow to render due being a pretty over-the-top function. + * Might be worth investigating whether HCY can be used instead, but I have had + * some weird results with that. + */ + QVector luma= m_d->cs->lumaCoefficients(); + QVector chan2 = convertvectorfloatToqreal(channelValuesDisplay); + QVector inbetween(3); + RGBToHSY(chan2[0],chan2[1], chan2[2], &inbetween[0], &inbetween[1], &inbetween[2], + luma[0], luma[1], luma[2]); + inbetween = getHSX(inbetween); + inbetween[m_d->channel1] = coordinates.x(); + if (m_d->dimension == Dimensions::twodimensional) { + inbetween[m_d->channel2] = coordinates.y(); + } + if (cursor==true){setHSX(inbetween);Q_EMIT sigHSXchange();} + HSYToRGB(inbetween[0], inbetween[1], inbetween[2],&chan2[0],&chan2[1], &chan2[2], + luma[0], luma[1], luma[2]); + channelValuesDisplay = convertvectorqrealTofloat(chan2); + } + } + } else { + channelValuesDisplay[m_d->channel1] = coordinates.x(); + if (m_d->dimension == Dimensions::twodimensional) { + channelValuesDisplay[m_d->channel2] = coordinates.y(); + } + } + for (int i=0; ics->channels())]*(maxvalue[i]); + } + c.colorSpace()->fromNormalisedChannelsValue(c.data(), channelValues); + return c; +} + +QPointF KisVisualColorSelectorShape::convertKoColorToShapeCoordinate(KoColor c) +{ + if (c.colorSpace() != m_d->cs) { + c.convertTo(m_d->cs); + } + QVector channelValues (m_d->currentColor.colorSpace()->channelCount()); + channelValues.fill(1.0); + m_d->cs->normalisedChannelsValue(c.data(), channelValues); + QVector channelValuesDisplay = channelValues; + QVector maxvalue(c.colorSpace()->channelCount()); + maxvalue.fill(1.0); + if (m_d->displayRenderer + && (m_d->cs->colorDepthId() == Float16BitsColorDepthID + || m_d->cs->colorDepthId() == Float32BitsColorDepthID + || m_d->cs->colorDepthId() == Float64BitsColorDepthID) + && m_d->cs->colorModelId() != LABAColorModelID + && m_d->cs->colorModelId() != CMYKAColorModelID) { + for (int ch = 0; chcs->channels()[ch]; + maxvalue[ch] = m_d->displayRenderer->maxVisibleFloatValue(channel); + channelValues[ch] = channelValues[ch]/(maxvalue[ch]); + channelValuesDisplay[KoChannelInfo::displayPositionToChannelIndex(ch, m_d->cs->channels())] = channelValues[ch]; + } + } else { + for (int i =0; ics->channels())] = qBound((float)0.0,channelValues[i], (float)1.0); + } + } + QPointF coordinates(0.0,0.0); + qreal huedivider = 1.0; + qreal huedivider2 = 1.0; + if (m_d->channel1==0) { + huedivider = 360.0; + } + if (m_d->channel2==0) { + huedivider2 = 360.0; + } + if (m_d->model != ColorModel::Channel && c.colorSpace()->colorModelId().id() == "RGBA") { + if (c.colorSpace()->colorModelId().id() == "RGBA") { + if (m_d->model == ColorModel::HSV){ + QVector inbetween(3); + RGBToHSV(channelValuesDisplay[0],channelValuesDisplay[1], channelValuesDisplay[2], &inbetween[0], &inbetween[1], &inbetween[2]); + inbetween = convertvectorqrealTofloat(getHSX(convertvectorfloatToqreal(inbetween))); + coordinates.setX(inbetween[m_d->channel1]/huedivider); + if (m_d->dimension == Dimensions::twodimensional) { + coordinates.setY(inbetween[m_d->channel2]/huedivider2); + } + } else if (m_d->model == ColorModel::HSL) { + QVector inbetween(3); + RGBToHSL(channelValuesDisplay[0],channelValuesDisplay[1], channelValuesDisplay[2], &inbetween[0], &inbetween[1], &inbetween[2]); + inbetween = convertvectorqrealTofloat(getHSX(convertvectorfloatToqreal(inbetween))); + coordinates.setX(inbetween[m_d->channel1]/huedivider); + if (m_d->dimension == Dimensions::twodimensional) { + coordinates.setY(inbetween[m_d->channel2]/huedivider2); + } + } else if (m_d->model == ColorModel::HSI) { + QVector chan2 = convertvectorfloatToqreal(channelValuesDisplay); + QVector inbetween(3); + RGBToHSI(channelValuesDisplay[0],channelValuesDisplay[1], channelValuesDisplay[2], &inbetween[0], &inbetween[1], &inbetween[2]); + inbetween = getHSX(inbetween); + coordinates.setX(inbetween[m_d->channel1]); + if (m_d->dimension == Dimensions::twodimensional) { + coordinates.setY(inbetween[m_d->channel2]); + } + } else if (m_d->model == ColorModel::HSY) { + QVector luma = m_d->cs->lumaCoefficients(); + QVector chan2 = convertvectorfloatToqreal(channelValuesDisplay); + QVector inbetween(3); + RGBToHSY(channelValuesDisplay[0],channelValuesDisplay[1], channelValuesDisplay[2], &inbetween[0], &inbetween[1], &inbetween[2], luma[0], luma[1], luma[2]); + inbetween = getHSX(inbetween); + coordinates.setX(inbetween[m_d->channel1]); + if (m_d->dimension == Dimensions::twodimensional) { + coordinates.setY(inbetween[m_d->channel2]); + } + } + } + } else { + coordinates.setX(qBound((float)0.0, channelValuesDisplay[m_d->channel1], (float)1.0)); + if (m_d->dimension == Dimensions::twodimensional) { + coordinates.setY(qBound((float)0.0, channelValuesDisplay[m_d->channel2], (float)1.0)); + } + } + return coordinates; +} + +QVector KisVisualColorSelectorShape::convertvectorqrealTofloat(QVector real) +{ + QVector vloat(real.size()); + for (int i=0; i KisVisualColorSelectorShape::convertvectorfloatToqreal(QVector vloat) +{ + QVector real(vloat.size()); + for (int i=0; imousePressActive = true; + QPointF coordinates = convertWidgetCoordinateToShapeCoordinate(e->pos()); + KoColor col = convertShapeCoordinateToKoColor(coordinates, true); + setColor(col); + Q_EMIT sigNewColor(col); + m_d->updateTimer->start(); +} + +void KisVisualColorSelectorShape::mouseMoveEvent(QMouseEvent *e) +{ + if (m_d->mousePressActive==true && this->mask().contains(e->pos())) { + QPointF coordinates = convertWidgetCoordinateToShapeCoordinate(e->pos()); + KoColor col = convertShapeCoordinateToKoColor(coordinates, true); + setColor(col); + if (!m_d->updateTimer->isActive()) { + Q_EMIT sigNewColor(col); + m_d->updateTimer->start(); + } + } else { + e->ignore(); + } +} + +void KisVisualColorSelectorShape::mouseReleaseEvent(QMouseEvent *) +{ + m_d->mousePressActive = false; +} +void KisVisualColorSelectorShape::paintEvent(QPaintEvent*) +{ + QPainter painter(this); + + //check if old and new colors differ. + + if (m_d->imagesNeedUpdate) { + setMask(getMaskMap()); + } + drawCursor(); + painter.drawImage(0,0,m_d->fullSelector); +} + +KisVisualColorSelectorShape::Dimensions KisVisualColorSelectorShape::getDimensions() +{ + return m_d->dimension; +} + +KisVisualColorSelectorShape::ColorModel KisVisualColorSelectorShape::getColorModel() +{ + return m_d->model; +} + +void KisVisualColorSelectorShape::setFullImage(QImage full) +{ + m_d->fullSelector = full; +} +KoColor KisVisualColorSelectorShape::getCurrentColor() +{ + return m_d->currentColor; +} + +QVector KisVisualColorSelectorShape::getHSX(QVector hsx, bool wrangler) +{ + QVector ihsx = hsx; + if (!wrangler){ + //Ok, so this docker will not update luminosity if there's not at the least 3% more variation. + //This is necessary for 8bit. + if (m_d->cs->colorDepthId()==Integer8BitsColorDepthID){ + if (hsx[2]>m_d->tone-0.03 && hsx[2]tone+0.03) { + ihsx[2] = m_d->tone; + } + } else { + if (hsx[2]>m_d->tone-0.005 && hsx[2]tone+0.005) { + ihsx[2] = m_d->tone; + } + } + if (m_d->model==HSV){ + if (hsx[2]<=0.0) { + ihsx[1] = m_d->sat; + } + } else { + if ((hsx[2]<=0.0 || hsx[2]>=1.0)) { + ihsx[1] = m_d->sat; + } + } + if ((hsx[1]<=0.0 || hsx[0]<0.0)){ + ihsx[0]=m_d->hue; + } + } else { + ihsx[0]=m_d->hue; + ihsx[1]=m_d->sat; + ihsx[2]=m_d->tone; + } + return ihsx; +} + +void KisVisualColorSelectorShape::setHSX(QVector hsx, bool wrangler) +{ + if (wrangler){ + m_d->tone = hsx[2]; + m_d->sat = hsx[1]; + m_d->hue = hsx[0]; + } else { + if (m_d->channel1==2 || m_d->channel2==2){ + m_d->tone=hsx[2]; + } + if (m_d->model==HSV){ + if (hsx[2]>0.0) { + m_d->sat = hsx[1]; + } + } else { + if ((hsx[2]>0.0 || hsx[2]<1.0)) { + m_d->sat = hsx[1]; + } + } + if ((hsx[1]>0.0 && hsx[0]>=0.0)){ + m_d->hue = hsx[0]; + } + } +} + +QVector KisVisualColorSelectorShape::getChannels() +{ + QVector channels(2); + channels[0] = m_d->channel1; + channels[1] = m_d->channel2; + return channels; +} + +/*-----------Rectangle Shape------------*/ + +KisVisualRectangleSelectorShape::KisVisualRectangleSelectorShape(QWidget *parent, + Dimensions dimension, + ColorModel model, + const KoColorSpace *cs, + int channel1, int channel2, + const KoColorDisplayRendererInterface *displayRenderer, + int width, + singelDTypes d) + : KisVisualColorSelectorShape(parent, dimension, model, cs, channel1, channel2, displayRenderer) +{ + m_type = d; + m_barWidth = width; +} + +KisVisualRectangleSelectorShape::~KisVisualRectangleSelectorShape() +{ + +} + +void KisVisualRectangleSelectorShape::setBorderWidth(int width) +{ + m_barWidth = width; +} + +QRect KisVisualRectangleSelectorShape::getSpaceForSquare(QRect geom) +{ + QPointF tl; + QPointF br; + + if (m_type==KisVisualRectangleSelectorShape::vertical) { + br = geom.bottomRight(); + tl = QPoint(geom.topLeft().x()+m_barWidth, geom.topLeft().y()); + } else if (m_type==KisVisualRectangleSelectorShape::horizontal) { + br = geom.bottomRight(); + tl = QPoint(geom.topLeft().x(), geom.topLeft().y()+m_barWidth); + } else { + tl = QPointF (geom.topLeft().x()+m_barWidth, geom.topLeft().y()+m_barWidth); + br = QPointF (geom.bottomRight().x()-m_barWidth, geom.bottomRight().y()-m_barWidth); + + } + QRect a(tl.toPoint(), br.toPoint()); + QRect r(a.left(), a.top(), qMin(a.height(), a.width()), qMin(a.height(), a.width())); + return r; +} + +QRect KisVisualRectangleSelectorShape::getSpaceForCircle(QRect geom) +{ + return getSpaceForSquare(geom); +} + +QRect KisVisualRectangleSelectorShape::getSpaceForTriangle(QRect geom) +{ + return getSpaceForSquare(geom); +} + +QPointF KisVisualRectangleSelectorShape::convertShapeCoordinateToWidgetCoordinate(QPointF coordinate) +{ + qreal x = m_barWidth/2; + qreal y = m_barWidth/2; + qreal offset = 5.0; + KisVisualColorSelectorShape::Dimensions dimension = getDimensions(); + if (dimension == KisVisualColorSelectorShape::onedimensional) { + if ( m_type == KisVisualRectangleSelectorShape::vertical) { + y = qMin(coordinate.x()*(height()-offset*2)+offset, (qreal)height()); + } else if (m_type == KisVisualRectangleSelectorShape::horizontal) { + x = qMin(coordinate.x()*(width()-offset*2)+offset, (qreal)width()); + } else if (m_type == KisVisualRectangleSelectorShape::border) { + + QRectF innerRect(m_barWidth/2, m_barWidth/2, width()-m_barWidth, height()-m_barWidth); + QPointF left (innerRect.left(),innerRect.center().y()); + QList polygonLines; + polygonLines.append(QLineF(left, innerRect.topLeft())); + polygonLines.append(QLineF(innerRect.topLeft(), innerRect.topRight())); + polygonLines.append(QLineF(innerRect.topRight(), innerRect.bottomRight())); + polygonLines.append(QLineF(innerRect.bottomRight(), innerRect.bottomLeft())); + polygonLines.append(QLineF(innerRect.bottomLeft(), left)); + + qreal totalLength =0.0; + Q_FOREACH(QLineF line, polygonLines) { + totalLength += line.length(); + } + + qreal length = coordinate.x()*totalLength; + QPointF intersect(x,y); + Q_FOREACH(QLineF line, polygonLines) { + if (line.length()>length && length>0){ + intersect = line.pointAt(length/line.length()); + + } + length-=line.length(); + } + x = qRound(intersect.x()); + y = qRound(intersect.y()); + + } else /*if (m_type == KisVisualRectangleSelectorShape::borderMirrored)*/ { + + QRectF innerRect(m_barWidth/2, m_barWidth/2, width()-m_barWidth, height()-m_barWidth); + QPointF bottom (innerRect.center().x(), innerRect.bottom()); + QList polygonLines; + polygonLines.append(QLineF(bottom, innerRect.bottomLeft())); + polygonLines.append(QLineF(innerRect.bottomLeft(), innerRect.topLeft())); + polygonLines.append(QLineF(innerRect.topLeft(), innerRect.topRight())); + polygonLines.append(QLineF(innerRect.topRight(), innerRect.bottomRight())); + polygonLines.append(QLineF(innerRect.bottomRight(), bottom)); + + qreal totalLength =0.0; + Q_FOREACH(QLineF line, polygonLines) { + totalLength += line.length(); + } + + qreal length = coordinate.x()*(totalLength/2); + QPointF intersect(x,y); + if (coordinate.y()==1) { + for (int i = polygonLines.size()-1; i==0; i--) { + QLineF line = polygonLines.at(i); + if (line.length()>length && length>0){ + intersect = line.pointAt(length/line.length()); + + } + length-=line.length(); + } + } else { + Q_FOREACH(QLineF line, polygonLines) { + if (line.length()>length && length>0){ + intersect = line.pointAt(length/line.length()); + + } + length-=line.length(); + } + } + x = qRound(intersect.x()); + y = qRound(intersect.y()); + + } + } else { + x = qMin(coordinate.x()*(height()-offset*2)+offset, (qreal)height()); + y = qMin(coordinate.y()*(width()-offset*2)+offset, (qreal)width()); + } + return QPointF(x,y); +} + +QPointF KisVisualRectangleSelectorShape::convertWidgetCoordinateToShapeCoordinate(QPoint coordinate) +{ + //default implementation: + qreal x = 0.5; + qreal y = 0.5; + qreal offset = 5.0; + KisVisualColorSelectorShape::Dimensions dimension = getDimensions(); + if (getMaskMap().contains(coordinate)) { + if (dimension == KisVisualColorSelectorShape::onedimensional ) { + if (m_type == KisVisualRectangleSelectorShape::vertical) { + x = qMax(((qreal)coordinate.y()-offset)/((qreal)height()-offset*2), 0.0); + } else if (m_type == KisVisualRectangleSelectorShape::horizontal) { + x = qMax(((qreal)coordinate.x()-offset)/((qreal)width()-offset*2),0.0); + } else if (m_type == KisVisualRectangleSelectorShape::border) { + //border + + QRectF innerRect(m_barWidth, m_barWidth, width()-(m_barWidth*2), height()-(m_barWidth*2)); + QPointF left (innerRect.left(),innerRect.center().y()); + QList polygonLines; + polygonLines.append(QLineF(left, innerRect.topLeft())); + polygonLines.append(QLineF(innerRect.topLeft(), innerRect.topRight())); + polygonLines.append(QLineF(innerRect.topRight(), innerRect.bottomRight())); + polygonLines.append(QLineF(innerRect.bottomRight(), innerRect.bottomLeft())); + polygonLines.append(QLineF(innerRect.bottomLeft(), left)); + + QLineF radius(coordinate, this->geometry().center()); + QPointF intersect(0.5,0.5); + qreal length = 0.0; + qreal totalLength = 0.0; + bool foundIntersect = false; + Q_FOREACH(QLineF line, polygonLines) { + if (line.intersect(radius,&intersect)==QLineF::BoundedIntersection && foundIntersect==false) + { + foundIntersect = true; + length+=QLineF(line.p1(), intersect).length(); + + } + if (foundIntersect==false) { + length+=line.length(); + } + totalLength+=line.length(); + } + + x = length/totalLength; + + } else /*if (m_type == KisVisualRectangleSelectorShape::borderMirrored)*/ { + //border + + QRectF innerRect(m_barWidth, m_barWidth, width()-(m_barWidth*2), height()-(m_barWidth*2)); + QPointF bottom (innerRect.center().x(), innerRect.bottom()); + QList polygonLines; + polygonLines.append(QLineF(bottom, innerRect.bottomLeft())); + polygonLines.append(QLineF(innerRect.bottomLeft(), innerRect.topLeft())); + polygonLines.append(QLineF(innerRect.topLeft(), innerRect.topRight())); + polygonLines.append(QLineF(innerRect.topRight(), innerRect.bottomRight())); + polygonLines.append(QLineF(innerRect.bottomRight(), bottom)); + + QLineF radius(coordinate, this->geometry().center()); + QPointF intersect(0.5,0.5); + qreal length = 0.0; + qreal totalLength = 0.0; + bool foundIntersect = false; + Q_FOREACH(QLineF line, polygonLines) { + if (line.intersect(radius,&intersect)==QLineF::BoundedIntersection && foundIntersect==false) + { + foundIntersect = true; + length+=QLineF(line.p1(), intersect).length(); + + } + if (foundIntersect==false) { + length+=line.length(); + } + totalLength+=line.length(); + } + int halflength = totalLength/2; + + if (length>halflength) { + x = (halflength - (length-halflength))/halflength; + y = 1.0; + } else { + x = length/halflength; + y = 0.0; + } + } + } + else { + x = qMax(((qreal)coordinate.x()-offset)/((qreal)width()-offset*2), 0.0); + y = qMax(((qreal)coordinate.y()-offset)/((qreal)height()-offset*2), 0.0);; + } + } + return QPointF(x, y); +} + +QRegion KisVisualRectangleSelectorShape::getMaskMap() +{ + QRegion mask = QRegion(0,0,width(),height()); + if (m_type==KisVisualRectangleSelectorShape::border || m_type==KisVisualRectangleSelectorShape::borderMirrored) { + mask = mask.subtracted(QRegion(m_barWidth, m_barWidth, width()-(m_barWidth*2), height()-(m_barWidth*2))); + } + return mask; +} +void KisVisualRectangleSelectorShape::resizeEvent(QResizeEvent *) +{ + forceImageUpdate(); +} + +void KisVisualRectangleSelectorShape::drawCursor() +{ + QPointF cursorPoint = convertShapeCoordinateToWidgetCoordinate(getCursorPosition()); + QImage fullSelector = getImageMap(); + QColor col = getColorFromConverter(getCurrentColor()); + QPainter painter; + painter.begin(&fullSelector); + painter.setRenderHint(QPainter::Antialiasing); + //QPainterPath path; + QBrush fill; + fill.setStyle(Qt::SolidPattern); + + int cursorwidth = 5; + QRect rect(cursorPoint.toPoint().x()-cursorwidth,cursorPoint.toPoint().y()-cursorwidth, + cursorwidth*2,cursorwidth*2); + if (m_type==KisVisualRectangleSelectorShape::vertical){ + int x = ( cursorPoint.x()-(width()/2)+1 ); + int y = ( cursorPoint.y()-cursorwidth ); + rect.setCoords(x, y, x+width()-2, y+(cursorwidth*2)); + painter.save(); + painter.setCompositionMode(QPainter::CompositionMode_Clear); + QPen pen; + pen.setWidth(5); + painter.setPen(pen); + painter.drawLine(QLine(QPoint(0.0,0.0), QPoint(0.0,height()))); + painter.drawLine(QLine(QPoint(width(),0.0), QPoint(width(),height()))); + painter.restore(); + } else { + int x = cursorPoint.x()-cursorwidth; + int y = cursorPoint.y()-(height()/2)+1; + rect.setCoords(x, y, x+(cursorwidth*2), y+cursorwidth-2); + } + QRectF innerRect(m_barWidth, m_barWidth, width()-(m_barWidth*2), height()-(m_barWidth*2)); + if (getDimensions() == KisVisualColorSelectorShape::onedimensional && m_type!=KisVisualRectangleSelectorShape::border && m_type!=KisVisualRectangleSelectorShape::borderMirrored) { + painter.setPen(Qt::white); + fill.setColor(Qt::white); + painter.setBrush(fill); + painter.drawRect(rect); + //set filter conversion! + fill.setColor(col); + painter.setPen(Qt::black); + painter.setBrush(fill); + rect.setCoords(rect.topLeft().x()+1, rect.topLeft().y()+1, + rect.topLeft().x()+rect.width()-2, rect.topLeft().y()+rect.height()-2); + painter.drawRect(rect); + + }else if(m_type==KisVisualRectangleSelectorShape::borderMirrored){ + painter.setPen(Qt::white); + fill.setColor(Qt::white); + painter.setBrush(fill); + painter.drawEllipse(cursorPoint, cursorwidth, cursorwidth); + QPoint mirror(innerRect.center().x()+(innerRect.center().x()-cursorPoint.x()),cursorPoint.y()); + painter.drawEllipse(mirror, cursorwidth, cursorwidth); + fill.setColor(col); + painter.setPen(Qt::black); + painter.setBrush(fill); + painter.drawEllipse(cursorPoint, cursorwidth-1, cursorwidth-1); + painter.drawEllipse(mirror, cursorwidth-1, cursorwidth-1); + + } else { + painter.save(); + painter.setCompositionMode(QPainter::CompositionMode_Clear); + QPen pen; + pen.setWidth(5); + painter.setPen(pen); + painter.drawRect(QRect(0,0,width(),height())); + painter.restore(); + + painter.setPen(Qt::white); + fill.setColor(Qt::white); + painter.setBrush(fill); + painter.drawEllipse(cursorPoint, cursorwidth, cursorwidth); + fill.setColor(col); + painter.setPen(Qt::black); + painter.setBrush(fill); + painter.drawEllipse(cursorPoint, cursorwidth-1.0, cursorwidth-1.0); + } + painter.end(); + setFullImage(fullSelector); +} + +//----------------Elliptical--------------------------// +KisVisualEllipticalSelectorShape::KisVisualEllipticalSelectorShape(QWidget *parent, + Dimensions dimension, + ColorModel model, + const KoColorSpace *cs, + int channel1, int channel2, + const KoColorDisplayRendererInterface *displayRenderer, + int borwidth, + singelDTypes d) + : KisVisualColorSelectorShape(parent, dimension, model, cs, channel1, channel2, displayRenderer) +{ + m_type = d; + m_barWidth = borwidth; +} + +KisVisualEllipticalSelectorShape::~KisVisualEllipticalSelectorShape() +{ + +} + +QSize KisVisualEllipticalSelectorShape::sizeHint() const +{ + return QSize(180,180); +} +void KisVisualEllipticalSelectorShape::setBorderWidth(int width) +{ + m_barWidth = width; +} + +QRect KisVisualEllipticalSelectorShape::getSpaceForSquare(QRect geom) +{ + int sizeValue = qMin(width(),height()); + QRect b(geom.left(), geom.top(), sizeValue, sizeValue); + QLineF radius(b.center(), QPointF(b.left()+m_barWidth, b.center().y()) ); + radius.setAngle(135); + QPointF tl = radius.p2(); + radius.setAngle(315); + QPointF br = radius.p2(); + QRect r(tl.toPoint(), br.toPoint()); + return r; +} + +QRect KisVisualEllipticalSelectorShape::getSpaceForCircle(QRect geom) +{ + int sizeValue = qMin(width(),height()); + QRect b(geom.left(), geom.top(), sizeValue, sizeValue); + QPointF tl = QPointF (b.topLeft().x()+m_barWidth, b.topLeft().y()+m_barWidth); + QPointF br = QPointF (b.bottomRight().x()-m_barWidth, b.bottomRight().y()-m_barWidth); + QRect r(tl.toPoint(), br.toPoint()); + return r; +} + +QRect KisVisualEllipticalSelectorShape::getSpaceForTriangle(QRect geom) +{ + int sizeValue = qMin(width(),height()); + QRect b(geom.left(), geom.top(), sizeValue, sizeValue); + QLineF radius(b.center(), QPointF(b.left()+m_barWidth, b.center().y()) ); + radius.setAngle(90);//point at yellowgreen :) + QPointF t = radius.p2(); + radius.setAngle(330);//point to purple :) + QPointF br = radius.p2(); + radius.setAngle(210);//point to cerulean :) + QPointF bl = radius.p2(); + QPointF tl = QPoint(bl.x(),t.y()); + QRect r(tl.toPoint(), br.toPoint()); + return r; +} + +QPointF KisVisualEllipticalSelectorShape::convertShapeCoordinateToWidgetCoordinate(QPointF coordinate) +{ + qreal x; + qreal y; + qreal offset=7.0; + qreal a = (qreal)width()*0.5; + QPointF center(a, a); + QLineF line(center, QPoint((m_barWidth*0.5),a)); + qreal angle = coordinate.x()*360.0; + angle = fmod(angle+180.0,360.0); + angle = 180.0-angle; + angle = angle+180.0; + if (m_type==KisVisualEllipticalSelectorShape::borderMirrored) { + angle = (coordinate.x()/2)*360.0; + angle = fmod((angle+90.0), 360.0); + } + line.setAngle(angle); + if (getDimensions()!=KisVisualColorSelectorShape::onedimensional) { + line.setLength(qMin(coordinate.y()*(a-offset), a-offset)); + } + x = qRound(line.p2().x()); + y = qRound(line.p2().y()); + return QPointF(x,y); +} + +QPointF KisVisualEllipticalSelectorShape::convertWidgetCoordinateToShapeCoordinate(QPoint coordinate) +{ + //default implementation: + qreal x = 0.5; + qreal y = 1.0; + qreal offset = 7.0; + QRect total(0, 0, width(), height()); + QLineF line(total.center(), coordinate); + qreal a = (total.width()/2); + qreal angle; + + if (m_type!=KisVisualEllipticalSelectorShape::borderMirrored){ + angle = fmod((line.angle()+180.0), 360.0); + angle = 180.0-angle; + angle = angle+180.0; + x = angle/360.0; + if (getDimensions()==KisVisualColorSelectorShape::twodimensional) { + y = qBound(0.0,line.length()/(a-offset), 1.0); + } + + } else { + angle = fmod((line.angle()+270.0), 360.0); + if (angle>180.0) { + angle = 180.0-angle; + angle = angle+180; + } + x = (angle/360.0)*2; + if (getDimensions()==KisVisualColorSelectorShape::twodimensional) { + y = qBound(0.0,(line.length()+offset)/a, 1.0); + } + } + + return QPointF(x, y); +} + +QRegion KisVisualEllipticalSelectorShape::getMaskMap() +{ + QRegion mask = QRegion(0,0,width(),height(), QRegion::Ellipse); + if (getDimensions()==KisVisualColorSelectorShape::onedimensional) { + mask = mask.subtracted(QRegion(m_barWidth, m_barWidth, width()-(m_barWidth*2), height()-(m_barWidth*2), QRegion::Ellipse)); + } + return mask; +} + +void KisVisualEllipticalSelectorShape::resizeEvent(QResizeEvent *) +{ + forceImageUpdate(); +} + +void KisVisualEllipticalSelectorShape::drawCursor() +{ + QPointF cursorPoint = convertShapeCoordinateToWidgetCoordinate(getCursorPosition()); + QImage fullSelector = getImageMap(); + QColor col = getColorFromConverter(getCurrentColor()); + QPainter painter; + painter.begin(&fullSelector); + painter.setRenderHint(QPainter::Antialiasing); + QRect innerRect(m_barWidth, m_barWidth, width()-(m_barWidth*2), height()-(m_barWidth*2)); + + painter.save(); + painter.setCompositionMode(QPainter::CompositionMode_Clear); + QPen pen; + pen.setWidth(5); + painter.setPen(pen); + painter.drawEllipse(QRect(0,0,width(),height())); + if (getDimensions()==KisVisualColorSelectorShape::onedimensional) { + painter.setBrush(Qt::SolidPattern); + painter.drawEllipse(innerRect); + } + painter.restore(); + + QBrush fill; + fill.setStyle(Qt::SolidPattern); + + int cursorwidth = 5; + if(m_type==KisVisualEllipticalSelectorShape::borderMirrored){ + painter.setPen(Qt::white); + fill.setColor(Qt::white); + painter.setBrush(fill); + painter.drawEllipse(cursorPoint, cursorwidth, cursorwidth); + QPoint mirror(innerRect.center().x()+(innerRect.center().x()-cursorPoint.x()),cursorPoint.y()); + painter.drawEllipse(mirror, cursorwidth, cursorwidth); + fill.setColor(col); + painter.setPen(Qt::black); + painter.setBrush(fill); + painter.drawEllipse(cursorPoint, cursorwidth-1, cursorwidth-1); + painter.drawEllipse(mirror, cursorwidth-1, cursorwidth-1); + + } else { + painter.setPen(Qt::white); + fill.setColor(Qt::white); + painter.setBrush(fill); + painter.drawEllipse(cursorPoint, cursorwidth, cursorwidth); + fill.setColor(col); + painter.setPen(Qt::black); + painter.setBrush(fill); + painter.drawEllipse(cursorPoint, cursorwidth-1.0, cursorwidth-1.0); + } + painter.end(); + setFullImage(fullSelector); +} + +//----------------Triangle--------------------------// +KisVisualTriangleSelectorShape::KisVisualTriangleSelectorShape(QWidget *parent, + Dimensions dimension, + ColorModel model, + const KoColorSpace *cs, + int channel1, int channel2, + const KoColorDisplayRendererInterface *displayRenderer, + int borwidth) + : KisVisualColorSelectorShape(parent, dimension, model, cs, channel1, channel2, displayRenderer) +{ + m_barWidth = borwidth; + QRect total(0,0,width()*0.9,width()*0.9); + setTriangle(); +} + +KisVisualTriangleSelectorShape::~KisVisualTriangleSelectorShape() +{ + +} + +void KisVisualTriangleSelectorShape::setBorderWidth(int width) +{ + m_barWidth = width; +} + +QRect KisVisualTriangleSelectorShape::getSpaceForSquare(QRect geom) +{ + return geom; +} + +QRect KisVisualTriangleSelectorShape::getSpaceForCircle(QRect geom) +{ + return geom; +} + +QRect KisVisualTriangleSelectorShape::getSpaceForTriangle(QRect geom) +{ + return geom; +} +void KisVisualTriangleSelectorShape::setTriangle() +{ + QPoint apex = QPoint (width()*0.5,0); + QPolygon triangle; + triangle<< QPoint(0,height()) << apex << QPoint(width(),height()) << QPoint(0,height()); + m_triangle = triangle; + QLineF a(triangle.at(0),triangle.at(1)); + QLineF b(triangle.at(0),triangle.at(2)); + QLineF ap(triangle.at(2), a.pointAt(0.5)); + QLineF bp(triangle.at(1), b.pointAt(0.5)); + QPointF intersect; + ap.intersect(bp,&intersect); + m_center = intersect; + QLineF r(triangle.at(0), intersect); + m_radius = r.length(); +} + +QPointF KisVisualTriangleSelectorShape::convertShapeCoordinateToWidgetCoordinate(QPointF coordinate) +{ + qreal offset=7.0;//the offset is so we get a nice little border that allows selecting extreme colors better. + qreal y = qMin(coordinate.y()*(height()-offset*2)+offset+5.0, (qreal)height()-offset); + + qreal triWidth = width(); + qreal horizontalLineLength = y*(2./sqrt(3.)); + qreal horizontalLineStart = triWidth/2.-horizontalLineLength/2.; + qreal relativeX = coordinate.x()*(horizontalLineLength-offset*2); + qreal x = qMin(relativeX + horizontalLineStart + offset, (qreal)width()-offset*2); + if (y, (C) 2016 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef KISVISUALCOLORSELECTOR_H +#define KISVISUALCOLORSELECTOR_H + +#include +#include +#include +#include +#include + +#include +#include +#include "KoColorDisplayRendererInterface.h" + + +#include "kritaui_export.h" + +/** + * @brief The KisVisualColorSelector class + * this gives a color selector box that draws gradients and everything. + * Unlike other color selectors, this one draws the full gamut of the given colorspace. + */ +class KRITAUI_EXPORT KisVisualColorSelector : public QWidget +{ + Q_OBJECT +public: + //Copied directly from the advanced color selector: + enum Type {Ring, Square, Wheel, Triangle, Slider}; + enum Parameters {H, hsvS, V, hslS, L, SL, SV, SV2, hsvSH, hslSH, VH, LH, SI, SY, hsiSH, hsySH, I, Y, IH, YH, hsiS, hsyS}; + struct Configuration { + Type mainType; + Type subType; + Parameters mainTypeParameter; + Parameters subTypeParameter; + Configuration(Type mainT = Triangle, + Type subT = Ring, + Parameters mainTP = SL, + Parameters subTP = H) + : mainType(mainT), + subType(subT), + mainTypeParameter(mainTP), + subTypeParameter(subTP) + {} + Configuration(QString string) + { + readString(string); + } + + QString toString() const + { + return QString("%1|%2|%3|%4").arg(mainType).arg(subType).arg(mainTypeParameter).arg(subTypeParameter); + } + void readString(QString string) + { + QStringList strili = string.split('|'); + if(strili.length()!=4) return; + + int imt=strili.at(0).toInt(); + int ist=strili.at(1).toInt(); + int imtp=strili.at(2).toInt(); + int istp=strili.at(3).toInt(); + + if(imt>Slider || ist>Slider || imtp>hsyS || istp>hsyS)//this was LH before + return; + + mainType = Type(imt); + subType = Type(ist); + mainTypeParameter = Parameters(imtp); + subTypeParameter = Parameters(istp); + } + static Configuration fromString(QString string) + { + Configuration ret; + ret.readString(string); + return ret; + } + }; + + explicit KisVisualColorSelector(QWidget *parent = 0); + ~KisVisualColorSelector(); + + /** + * @brief setConfig + * @param forceCircular + * Force circular is for space where you only have room for a circular selector. + * @param forceSelfUpdate + * force self-update is for making it update itself when using a modal dialog. + */ + void setConfig(bool forceCircular, bool forceSelfUpdate); + KoColor getCurrentColor(); + +Q_SIGNALS: + void sigNewColor(KoColor c); + +public Q_SLOTS: + + void slotSetColor(KoColor c); + void slotsetColorSpace(const KoColorSpace *cs); + void slotRebuildSelectors(); + void ConfigurationChanged(); + void setDisplayRenderer (const KoColorDisplayRendererInterface *displayRenderer); +private Q_SLOTS: + void updateFromWidgets(KoColor c); + void HSXwrangler(); +protected: + void leaveEvent(QEvent *); + void resizeEvent(QResizeEvent *); +private: + struct Private; + const QScopedPointer m_d; + + void updateSelectorElements(QObject *source); + void drawGradients(); + +}; + +//kis_visual_color_selector_shape + +/** + * @brief The KisVisualColorSelectorShape class + * A 2d widget can represent at maximum 2 coordinates. + * So first decide howmany coordinates you need. (onedimensional, or twodimensional) + * Then the model, (Channel, HSV, HSL, HSI, YUV). Channel is the raw color channels. + * When it finds a non-implemented feature it'll return to Channel. + * Then, select the channels you wish to be affected. This uses the model, so for cmyk + * the channel is c=0, m=1, y=2, k=3, but for hsv, hue=0, sat=1, and val=2 + * These can also be set with 'slotsetactive channels'. + * Then finally, connect the displayrenderer, you can also do this with 'setdisplayrenderer' + * + * Either way, this class is made to be subclassed, with a few virtuals so that the geometry + * can be calculated properly. + */ + +class KisVisualColorSelectorShape : public QWidget +{ + Q_OBJECT +public: + /** + * @brief The Dimensions enum + * Wether or not the shape is single or two dimensional. + **/ + enum Dimensions{onedimensional, twodimensional}; + enum ColorModel{Channel, HSV, HSL, HSI, HSY, YUV}; + explicit KisVisualColorSelectorShape(QWidget *parent, + KisVisualColorSelectorShape::Dimensions dimension, + KisVisualColorSelectorShape::ColorModel model, + const KoColorSpace *cs, + int channel1, int channel2, + const KoColorDisplayRendererInterface *displayRenderer = KoDumbColorDisplayRenderer::instance()); + ~KisVisualColorSelectorShape(); + + /** + * @brief getCursorPosition + * @return current cursor position in shape-coordinates. + */ + QPointF getCursorPosition(); + /** + * @brief getDimensions + * @return whether this is a single or twodimensional widget. + */ + Dimensions getDimensions(); + /** + * @brief getColorModel + * @return the model of this widget. + */ + ColorModel getColorModel(); + /** + * @brief getPixmap + * @return the pixmap of the gradient, for drawing on with a subclass. + * the pixmap will not change unless 'm_d->setPixmap=true' which is toggled by + * refresh and update functions. + */ + QImage getImageMap(); + /** + * @brief setFullImage + * Set the full widget image to be painted. + * @param full this should be the full image. + */ + void setFullImage(QImage full); + /** + * @brief getCurrentColor + * @return the current kocolor + */ + KoColor getCurrentColor(); + /** + * @brief setDisplayRenderer + * disconnect the old display renderer if needed and connect the new one. + * @param displayRenderer + */ + void setDisplayRenderer (const KoColorDisplayRendererInterface *displayRenderer); + /** + * @brief getColorFromConverter + * @param c a koColor. + * @return get the qcolor from the given kocolorusing this widget's display renderer. + */ + QColor getColorFromConverter(KoColor c); + + /** + * @brief getSpaceForSquare + * @param geom the full widget rectangle + * @return rectangle with enough space for second widget + */ + virtual QRect getSpaceForSquare(QRect geom) = 0; + virtual QRect getSpaceForCircle(QRect geom) = 0; + virtual QRect getSpaceForTriangle(QRect geom) = 0; + + /** + * @brief forceImageUpdate + * force the image to recache. + */ + void forceImageUpdate(); + + /** + * @brief setBorderWidth + * set the border of the single dimensional selector. + * @param width + */ + virtual void setBorderWidth(int width) = 0; + + /** + * @brief getChannels + * get used channels + * @return + */ + QVector getChannels(); + + /** + * @brief setHSX + * This is for the cursor not to change when selecting + * black, white, and desaturated values. Will not change the non-native values. + * @param hsx the hsx value. + */ + void setHSX(QVector hsx, bool wrangler=false); + /** + * @brief getHSX sets the sat and hue so they won't + * switch around much. + * @param hsx the hsx values. + * @return returns hsx, corrected. + */ + QVector getHSX(QVector hsx, bool wrangler= false); + + +Q_SIGNALS: + void sigNewColor(KoColor col); + void sigHSXchange(); + +public Q_SLOTS: + /** + * @brief setColor + * Set this widget's current color and change the cursor position. + * @param c + */ + void setColor(KoColor c); + /** + * @brief setColorFromSibling + * set this widget's current color, but don't change the cursor position, + * instead sent out a signal of the new color. + * @param c + */ + void setColorFromSibling(KoColor c); + /** + * @brief slotSetActiveChannels + * Change the active channels if necessary. + * @param channel1 used by single and twodimensional widgets. + * @param channel2 only used by twodimensional widgets. + */ + void slotSetActiveChannels(int channel1, int channel2); + /** + * @brief updateFromChangedDisplayRenderer + * for updating from the display renderer... not sure why this one is public. + */ + void updateFromChangedDisplayRenderer(); +protected: + void mousePressEvent(QMouseEvent *e); + void mouseMoveEvent(QMouseEvent *e); + void mouseReleaseEvent(QMouseEvent *e); + void paintEvent(QPaintEvent*); +private: + struct Private; + const QScopedPointer m_d; + + /** + * @brief convertShapeCoordinateToWidgetCoordinate + * @return take the position in the shape and convert it to screen coordinates. + */ + virtual QPointF convertShapeCoordinateToWidgetCoordinate(QPointF) = 0; + + /** + * @brief convertWidgetCoordinateToShapeCoordinate + * Convert a coordinate in the widget's height/width to a shape coordinate. + * @param coordinate the position your wish to have the shape coordinates of. + */ + virtual QPointF convertWidgetCoordinateToShapeCoordinate(QPoint coordinate) = 0; + + /** + * @brief updateCursor + * Update the cursor position. + */ + void updateCursor(); + + QPointF convertKoColorToShapeCoordinate(KoColor c); + KoColor convertShapeCoordinateToKoColor(QPointF coordinates, bool cursor=false); + + /** + * @brief getPixmap + * @return the pixmap of this shape. + */ + virtual QRegion getMaskMap() = 0; + virtual void drawCursor() = 0; + + QVector convertvectorqrealTofloat(QVector real); + QVector convertvectorfloatToqreal(QVector vloat); +}; + +class KisVisualRectangleSelectorShape : public KisVisualColorSelectorShape +{ + Q_OBJECT +public: + enum singelDTypes{vertical, horizontal, border, borderMirrored}; + explicit KisVisualRectangleSelectorShape(QWidget *parent, + Dimensions dimension, + ColorModel model, + const KoColorSpace *cs, + int channel1, int channel2, + const KoColorDisplayRendererInterface *displayRenderer = KoDumbColorDisplayRenderer::instance(), int width=20, + KisVisualRectangleSelectorShape::singelDTypes d = KisVisualRectangleSelectorShape::vertical + ); + ~KisVisualRectangleSelectorShape(); + + void setBorderWidth(int width); + + /** + * @brief getSpaceForSquare + * @param geom the full widget rectangle + * @return rectangle with enough space for second widget + */ + virtual QRect getSpaceForSquare(QRect geom); + virtual QRect getSpaceForCircle(QRect geom); + virtual QRect getSpaceForTriangle(QRect geom); +protected: + void resizeEvent(QResizeEvent *); +private: + virtual QPointF convertShapeCoordinateToWidgetCoordinate(QPointF coordinate); + virtual QPointF convertWidgetCoordinateToShapeCoordinate(QPoint coordinate); + + singelDTypes m_type; + int m_barWidth; + virtual QRegion getMaskMap(); + virtual void drawCursor(); +}; + +class KisVisualEllipticalSelectorShape : public KisVisualColorSelectorShape +{ + Q_OBJECT +public: + enum singelDTypes{border, borderMirrored}; + explicit KisVisualEllipticalSelectorShape(QWidget *parent, + Dimensions dimension, + ColorModel model, + const KoColorSpace *cs, + int channel1, int channel2, + const KoColorDisplayRendererInterface *displayRenderer = KoDumbColorDisplayRenderer::instance(), int borwidth=20, + KisVisualEllipticalSelectorShape::singelDTypes d = KisVisualEllipticalSelectorShape::border + ); + ~KisVisualEllipticalSelectorShape(); + + void setBorderWidth(int width); + + /** + * @brief getSpaceForSquare + * @param geom the full widget rectangle + * @return rectangle with enough space for second widget + */ + virtual QRect getSpaceForSquare(QRect geom); + virtual QRect getSpaceForCircle(QRect geom); + virtual QRect getSpaceForTriangle(QRect geom); +protected: + void resizeEvent(QResizeEvent *); +private: + virtual QPointF convertShapeCoordinateToWidgetCoordinate(QPointF coordinate); + virtual QPointF convertWidgetCoordinateToShapeCoordinate(QPoint coordinate); + + + singelDTypes m_type; + int m_barWidth; + virtual QRegion getMaskMap(); + virtual void drawCursor(); + QSize sizeHint() const; +}; + +class KisVisualTriangleSelectorShape : public KisVisualColorSelectorShape +{ + Q_OBJECT +public: + enum singelDTypes{border, borderMirrored}; + explicit KisVisualTriangleSelectorShape(QWidget *parent, + Dimensions dimension, + ColorModel model, + const KoColorSpace *cs, + int channel1, int channel2, + const KoColorDisplayRendererInterface *displayRenderer = KoDumbColorDisplayRenderer::instance(), + int borwidth=20 + ); + ~KisVisualTriangleSelectorShape(); + + void setBorderWidth(int width); + void setTriangle(); + + /** + * @brief getSpaceForSquare + * @param geom the full widget rectangle + * @return rectangle with enough space for second widget + */ + virtual QRect getSpaceForSquare(QRect geom); + virtual QRect getSpaceForCircle(QRect geom); + virtual QRect getSpaceForTriangle(QRect geom); +protected: + void resizeEvent(QResizeEvent *); +private: + virtual QPointF convertShapeCoordinateToWidgetCoordinate(QPointF coordinate); + virtual QPointF convertWidgetCoordinateToShapeCoordinate(QPoint coordinate); + + singelDTypes m_type; + int m_barWidth; + QPolygon m_triangle; + QPointF m_center; + qreal m_radius; + virtual QRegion getMaskMap(); + virtual void drawCursor(); +}; +#endif // KISVISUALCOLORSELECTOR_H diff --git a/libs/widgets/CMakeLists.txt b/libs/widgets/CMakeLists.txt index c141267ef5..6d53be629a 100644 --- a/libs/widgets/CMakeLists.txt +++ b/libs/widgets/CMakeLists.txt @@ -1,113 +1,112 @@ add_subdirectory( tests ) include_directories(${CMAKE_CURRENT_BINARY_DIR}) set(kritawidgets_LIB_SRCS KoGradientEditWidget.cpp KoVBox.cpp KoDialog.cpp KoGlobal.cpp KoZoomWidget.cpp KoTagToolButton.cpp KoTagChooserWidget.cpp KoTagFilterWidget.cpp KoResourceTaggingManager.cpp KoResourceItemChooserContextMenu.cpp KoAspectButton.cpp KoPagePreviewWidget.cpp KoPositionSelector.cpp KoSliderCombo.cpp KoColorPopupButton.cpp KoConfigAuthorPage.cpp KoUnitDoubleSpinBox.cpp KoZoomAction.cpp KoZoomController.cpp KoZoomInput.cpp KoZoomHandler.cpp KoZoomMode.cpp KoDpi.cpp KoGlobal.cpp KoColorPatch.cpp KoColorPopupAction.cpp KoColorSetWidget.cpp KoColorSlider.cpp - KoDualColorButton.cpp KoEditColorSetDialog.cpp KoTriangleColorSelector.cpp KoResourcePopupAction.cpp KoFillConfigWidget.cpp KoIconToolTip.cpp KoResourceItemChooser.cpp KoResourceItemChooserSync.cpp KoResourceSelector.cpp KoResourceModel.cpp KoResourceItemDelegate.cpp KoResourceItemView.cpp KoResourceTagStore.cpp KoRuler.cpp #KoRulerController.cpp KoItemToolTip.cpp KoCheckerBoardPainter.cpp KoResourceServerAdapter.cpp KoResourceServerProvider.cpp KoLineStyleSelector.cpp KoLineStyleItemDelegate.cpp KoLineStyleModel.cpp KoDockWidgetTitleBar.cpp KoDockWidgetTitleBarButton.cpp KoResourceFiltering.cpp KoResourceModelBase.cpp KoToolBoxButton.cpp KoToolBox.cpp KoToolBoxDocker.cpp KoToolBoxFactory.cpp KoToolDocker.cpp KoPageLayoutWidget.cpp KoPageLayoutDialog.cpp KoShadowConfigWidget.cpp KoStrokeConfigWidget.cpp KoMarkerSelector.cpp KoMarkerModel.cpp KoMarkerItemDelegate.cpp KoDocumentInfoDlg.cpp KoGlobal.cpp KoTableView.cpp WidgetsDebug.cpp kis_file_name_requester.cpp kis_double_parse_spin_box.cpp kis_double_parse_unit_spin_box.cpp kis_int_parse_spin_box.cpp ) ki18n_wrap_ui( kritawidgets_LIB_SRCS KoConfigAuthorPage.ui koDocumentInfoAboutWidget.ui koDocumentInfoAuthorWidget.ui KoEditColorSet.ui wdg_file_name_requester.ui KoPageLayoutWidget.ui KoShadowConfigWidget.ui ) add_library(kritawidgets SHARED ${kritawidgets_LIB_SRCS}) generate_export_header(kritawidgets BASE_NAME kritawidgets) target_link_libraries(kritawidgets kritaodf kritaflake kritapigment kritawidgetutils Qt5::PrintSupport KF5::CoreAddons KF5::ConfigGui KF5::GuiAddons KF5::WidgetsAddons KF5::ConfigCore KF5::Completion) if(X11_FOUND) target_link_libraries(kritawidgets Qt5::X11Extras ${X11_LIBRARIES}) endif() target_link_libraries(kritawidgets LINK_INTERFACE_LIBRARIES kritaodf kritaflake kritapigment kritawidgetutils Qt5::PrintSupport KF5::CoreAddons KF5::ConfigGui KF5::GuiAddons KF5::WidgetsAddons KF5::ConfigCore KF5::Completion) set_target_properties(kritawidgets PROPERTIES VERSION ${GENERIC_KRITA_LIB_VERSION} SOVERSION ${GENERIC_KRITA_LIB_SOVERSION} ) install(TARGETS kritawidgets ${INSTALL_TARGETS_DEFAULT_ARGS}) diff --git a/libs/widgets/KoColorPatch.cpp b/libs/widgets/KoColorPatch.cpp index 6b000686a5..0d2b53402c 100644 --- a/libs/widgets/KoColorPatch.cpp +++ b/libs/widgets/KoColorPatch.cpp @@ -1,66 +1,93 @@ /** * Copyright (c) 2006 C. Boemann (cbo@boemann.dk) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "KoColorPatch.h" #include KoColorPatch::KoColorPatch( QWidget *parent ) : QFrame( parent ) { + m_displayRenderer = KoDumbColorDisplayRenderer::instance(); + connect(m_displayRenderer, SIGNAL(displayConfigurationChanged()), + SLOT(update()), Qt::UniqueConnection); setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); } KoColorPatch::~KoColorPatch() { } QSize KoColorPatch::sizeHint() const { return QSize(12,12); } void KoColorPatch::setColor(const KoColor& c) { m_color = c; update(); } +void KoColorPatch::setDisplayRenderer(const KoColorDisplayRendererInterface *displayRenderer) +{ + if (displayRenderer) { + if (m_displayRenderer) { + m_displayRenderer->disconnect(this); + } + m_displayRenderer = displayRenderer; + } else { + m_displayRenderer = KoDumbColorDisplayRenderer::instance(); + } + connect(m_displayRenderer, SIGNAL(displayConfigurationChanged()), + SLOT(update()), Qt::UniqueConnection); + +} + +QColor KoColorPatch::getColorFromDisplayRenderer(KoColor c) +{ + QColor col; + if (m_displayRenderer) { + c.convertTo(m_displayRenderer->getPaintingColorSpace()); + col = m_displayRenderer->toQColor(c); + } else { + col = c.toQColor(); + } + return col; +} KoColor KoColorPatch::color() const { return m_color; } void KoColorPatch::mousePressEvent (QMouseEvent *e ) { Q_UNUSED( e ); emit triggered(this); } void KoColorPatch::paintEvent(QPaintEvent *pe) { - QColor qc; - m_color.toQColor(&qc); - + QColor qc = getColorFromDisplayRenderer(m_color); QFrame::paintEvent(pe); QPainter painter( this ); painter.setPen(qc); painter.setBrush(QBrush(qc)); painter.drawRect(contentsRect()); } diff --git a/libs/widgets/KoColorPatch.h b/libs/widgets/KoColorPatch.h index c30b72f673..fd3ead420f 100644 --- a/libs/widgets/KoColorPatch.h +++ b/libs/widgets/KoColorPatch.h @@ -1,65 +1,81 @@ /** * Copyright (c) 2006 C. Boemann (cbo@boemann.dk) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KOCOLORPATCH_H #define KOCOLORPATCH_H #include #include #include "kritawidgets_export.h" +#include /** * The small widget showing the selected color */ class KRITAWIDGETS_EXPORT KoColorPatch : public QFrame { Q_OBJECT public: explicit KoColorPatch( QWidget *parent ); virtual ~KoColorPatch(); /** * Set the color of this color patch * @param c the new color */ void setColor( const KoColor &c ); + /** + * @brief setDisplayRenderer + * Set the display renderer of this object. + * @param displayRenderer + */ + void setDisplayRenderer(const KoColorDisplayRendererInterface *displayRenderer); + + /** + * @brief getColorFromDisplayRenderer + * Get QColor from the display renderers + * @param c + */ + QColor getColorFromDisplayRenderer(KoColor c); + /** * @return current color shown by this patch */ KoColor color() const; protected: virtual void mousePressEvent(QMouseEvent *e ); ///< reimplemented from QFrame virtual void paintEvent(QPaintEvent *e); ///< reimplemented from QFrame virtual QSize sizeHint() const; ///< reimplemented from QFrame Q_SIGNALS: /** * Emitted when the mouse is released. * @param widget a pointer to this widget */ void triggered(KoColorPatch *widget); private: KoColor m_color; + const KoColorDisplayRendererInterface *m_displayRenderer; }; #endif diff --git a/libs/widgets/KoColorSetWidget.cpp b/libs/widgets/KoColorSetWidget.cpp index 5a5307c3e9..c8e9758060 100644 --- a/libs/widgets/KoColorSetWidget.cpp +++ b/libs/widgets/KoColorSetWidget.cpp @@ -1,239 +1,286 @@ /* This file is part of the KDE project Copyright (c) 2007, 2012 C. Boemann Copyright (c) 2007-2008 Fredy Yanardi This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "KoColorSetWidget.h" #include "KoColorSetWidget_p.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include void KoColorSetWidget::KoColorSetWidgetPrivate::fillColors() { delete colorSetContainer; colorSetContainer = new QWidget(); colorSetLayout = new QGridLayout(); colorSetLayout->setMargin(3); colorSetLayout->setSpacing(0); // otherwise the use can click where there is none colorSetContainer->setBackgroundRole(QPalette::Dark); - for(int i = 0; i<16; i++) { + + int columns = 16; + if (colorSet) { + columns = colorSet->columnCount(); + } + for(int i = 0; isetColumnMinimumWidth(i, 12); } + colorSetContainer->setMinimumWidth(columns*12+6); colorSetContainer->setLayout(colorSetLayout); + patchWidgetList.clear(); + colornames.clear(); + colorNameCmb->clear(); if (colorSet) { for( int i = 0, p= 0; i < colorSet->nColors(); i++) { KoColorPatch *patch = new KoColorPatch(colorSetContainer); patch->setFrameStyle(QFrame::Plain | QFrame::Box); patch->setLineWidth(1); patch->setColor(colorSet->getColor(i).color); + patch->setToolTip(colorSet->getColor(i).name); connect(patch, SIGNAL(triggered(KoColorPatch *)), thePublic, SLOT(colorTriggered(KoColorPatch *))); - colorSetLayout->addWidget(patch, p/16, p%16); + colorSetLayout->addWidget(patch, p/columns, p%columns); + patch->setDisplayRenderer(displayRenderer); + patchWidgetList.append(patch); + colornames.append(colorSet->getColor(i).name); + QPixmap colorsquare = QPixmap(12,12); + colorsquare.fill(colorSet->getColor(i).color.toQColor()); + colorNameCmb->addItem(QIcon(colorsquare), colorSet->getColor(i).name); ++p; } } scrollArea->setWidget(colorSetContainer); + connect(colorNameCmb, SIGNAL(activated(QString)), thePublic, SLOT(setColorFromString(QString)), Qt::UniqueConnection); } void KoColorSetWidget::KoColorSetWidgetPrivate::addRemoveColors() { KoResourceServer* srv = KoResourceServerProvider::instance()->paletteServer(); QList palettes = srv->resources(); Q_ASSERT(colorSet); KoEditColorSetDialog *dlg = new KoEditColorSetDialog(palettes, colorSet->name(), thePublic); if (dlg->exec() == KoDialog::Accepted ) { // always reload the color set KoColorSet * cs = dlg->activeColorSet(); // check if the selected colorset is predefined if( cs && !palettes.contains( cs ) ) { int i = 1; QFileInfo fileInfo; QString savePath = srv->saveLocation(); do { fileInfo.setFile( savePath + QString("%1.gpl").arg( i++, 4, 10, QChar('0') ) ); } while (fileInfo.exists()); cs->setFilename( fileInfo.filePath() ); cs->setValid( true ); // add new colorset to predefined colorsets if (!srv->addResource(cs)) { delete cs; cs = 0; } } if (cs) { thePublic->setColorSet(cs); } } delete dlg; } void KoColorSetWidget::KoColorSetWidgetPrivate::addRecent(const KoColor &color) { if(numRecents<6) { recentPatches[numRecents] = new KoColorPatch(thePublic); - recentPatches[numRecents]->setFrameShape(QFrame::Box); + recentPatches[numRecents]->setFrameShape(QFrame::StyledPanel); + recentPatches[numRecents]->setDisplayRenderer(displayRenderer); recentsLayout->insertWidget(numRecents+1, recentPatches[numRecents]); connect(recentPatches[numRecents], SIGNAL(triggered(KoColorPatch *)), thePublic, SLOT(colorTriggered(KoColorPatch *))); numRecents++; } // shift colors to the right for (int i = numRecents- 1; i >0; i--) { recentPatches[i]->setColor(recentPatches[i-1]->color()); } //Finally set the recent color recentPatches[0]->setColor(color); } void KoColorSetWidget::KoColorSetWidgetPrivate::activateRecent(int i) { KoColor color = recentPatches[i]->color(); while (i >0) { recentPatches[i]->setColor(recentPatches[i-1]->color()); i--; } recentPatches[0]->setColor(color); } KoColorSetWidget::KoColorSetWidget(QWidget *parent) : QFrame(parent) ,d(new KoColorSetWidgetPrivate()) { d->thePublic = this; d->colorSet = 0; d->firstShowOfContainer = true; d->mainLayout = new QVBoxLayout(); d->mainLayout->setMargin(4); d->mainLayout->setSpacing(2); d->colorSetContainer = 0; d->numRecents = 0; d->recentsLayout = new QHBoxLayout(); d->mainLayout->addLayout(d->recentsLayout); d->recentsLayout->setMargin(0); d->recentsLayout->addWidget(new QLabel(i18n("Recent:"))); d->recentsLayout->addStretch(1); KoColor color(KoColorSpaceRegistry::instance()->rgb8()); color.fromQColor(QColor(128,0,0)); d->addRecent(color); d->scrollArea = new QScrollArea(); d->scrollArea->setBackgroundRole(QPalette::Dark); d->mainLayout->addWidget(d->scrollArea); + d->colorNameCmb = new QComboBox(this); + d->colorNameCmb->setEditable(true); + d->colorNameCmb->setInsertPolicy(QComboBox::NoInsert); + d->mainLayout->addWidget(d->colorNameCmb); d->fillColors(); + d->addRemoveButton = new QToolButton(this); d->addRemoveButton->setText(i18n("Add / Remove Colors...")); d->addRemoveButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); connect(d->addRemoveButton, SIGNAL(clicked()), SLOT(addRemoveColors())); d->mainLayout->addWidget(d->addRemoveButton); setLayout(d->mainLayout); KoColorSet *colorSet = new KoColorSet(); d->colorSet = colorSet; d->fillColors(); } KoColorSetWidget::~KoColorSetWidget() { KoResourceServer* srv = KoResourceServerProvider::instance()->paletteServer(); QList palettes = srv->resources(); if (!palettes.contains(d->colorSet)) { delete d->colorSet; } delete d; } void KoColorSetWidget::KoColorSetWidgetPrivate::colorTriggered(KoColorPatch *patch) { int i; emit thePublic->colorChanged(patch->color(), true); + colorNameCmb->setCurrentIndex(colornames.indexOf(QRegExp(patch->toolTip()+"|Fixed"))); + for(i = 0; i color()); } +void KoColorSetWidget::KoColorSetWidgetPrivate::setColorFromString(QString s) +{ + int i = colornames.indexOf(QRegExp(s+"|Fixed")); + i = qMax(i,0); + colorTriggered(patchWidgetList.at(i)); +} + void KoColorSetWidget::setColorSet(KoColorSet *colorSet) { if (colorSet == d->colorSet) return; KoResourceServer* srv = KoResourceServerProvider::instance()->paletteServer(); QList palettes = srv->resources(); if (!palettes.contains(d->colorSet)) { delete d->colorSet; } d->colorSet = colorSet; d->fillColors(); } KoColorSet* KoColorSetWidget::colorSet() { return d->colorSet; } +void KoColorSetWidget::setDisplayRenderer(const KoColorDisplayRendererInterface *displayRenderer) +{ + if (displayRenderer) { + d->displayRenderer = displayRenderer; + Q_FOREACH(KoColorPatch *p, d->patchWidgetList) { + p->setDisplayRenderer(displayRenderer); + } + for (int i=0; i<6; i++) { + if (d->recentPatches[i]) { + d->recentPatches[i]->setDisplayRenderer(displayRenderer); + } + } + } +} + void KoColorSetWidget::resizeEvent(QResizeEvent *event) { emit widgetSizeChanged(event->size()); QFrame::resizeEvent(event); } //have to include this because of Q_PRIVATE_SLOT #include "moc_KoColorSetWidget.cpp" diff --git a/libs/widgets/KoColorSetWidget.h b/libs/widgets/KoColorSetWidget.h index 07dbe26287..6a26963fda 100644 --- a/libs/widgets/KoColorSetWidget.h +++ b/libs/widgets/KoColorSetWidget.h @@ -1,98 +1,107 @@ /* This file is part of the KDE project Copyright (c) 2007 C. Boemann Copyright (c) 2007 Fredy Yanardi This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KOCOLORSETWIDGET_H_ #define KOCOLORSETWIDGET_H_ #include #include #include "kritawidgets_export.h" +#include class KoColor; class KoColorSet; /** * @short A colormanaged widget for choosing a color from a colorset * * KoColorSetWidget is a widget for choosing a color (colormanaged via pigment). It shows a color * set plus optionally a checkbox to filter away bad matching colors. */ class KRITAWIDGETS_EXPORT KoColorSetWidget : public QFrame { Q_OBJECT public: /** * Constructor for the widget, where color is initially blackpoint of sRGB * * @param parent parent QWidget */ explicit KoColorSetWidget(QWidget *parent=0); /** * Destructor */ virtual ~KoColorSetWidget(); /** * Sets the color set that this widget shows. * @param colorSet pointer to the color set */ void setColorSet(KoColorSet *colorSet); + /** + * @brief setDisplayRenderer + * Set the display renderer of this object. + * @param displayRenderer + */ + void setDisplayRenderer(const KoColorDisplayRendererInterface *displayRenderer); + /** * Gets the current color set * @returns current color set,, 0 if none set */ KoColorSet* colorSet(); protected: virtual void resizeEvent(QResizeEvent *event); ///< reimplemented from QFrame Q_SIGNALS: /** * Emitted every time the color changes (by calling setColor() or * by user interaction. * @param color the new color * @param final if the value is final (ie not produced by the pointer moving over around) */ void colorChanged(const KoColor &color, bool final); /** * Emitted every time the size of this widget changes because of new colorset with * different number of colors is loaded. This is useful for KoColorSetAction to update * correct size of the menu showing this widget. * @param size the new size */ void widgetSizeChanged(const QSize &size); private: Q_PRIVATE_SLOT(d, void colorTriggered(KoColorPatch *)) Q_PRIVATE_SLOT(d, void addRemoveColors()) + Q_PRIVATE_SLOT(d, void setColorFromString(QString s)) class KoColorSetWidgetPrivate; KoColorSetWidgetPrivate * const d; }; #endif diff --git a/libs/widgets/KoColorSetWidget_p.h b/libs/widgets/KoColorSetWidget_p.h index 0a85e98b65..867dadf774 100644 --- a/libs/widgets/KoColorSetWidget_p.h +++ b/libs/widgets/KoColorSetWidget_p.h @@ -1,69 +1,78 @@ /* This file is part of the KDE project Copyright (c) 2007, 2012 C. Boemann Copyright (c) 2007-2008 Fredy Yanardi This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KoColorSetWidget_p_h #define KoColorSetWidget_p_h #include "KoColorSetWidget.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include #include #include #include +#include class KoColorPatch; class Q_DECL_HIDDEN KoColorSetWidget::KoColorSetWidgetPrivate { public: KoColorSetWidget *thePublic; QPointer colorSet; QTimer m_timer; QVBoxLayout *mainLayout; bool firstShowOfContainer; QWidget *colorSetContainer; QScrollArea *scrollArea; QGridLayout *colorSetLayout; QHBoxLayout *recentsLayout; KoColorPatch *recentPatches[6]; QToolButton *addRemoveButton; + QComboBox *colorNameCmb; + QStringList colornames; int numRecents; void colorTriggered(KoColorPatch *patch); void addRecent(const KoColor &); void activateRecent(int i); void fillColors(); void addRemoveColors(); + void setColorFromString(QString s); + + QList patchWidgetList; + const KoColorDisplayRendererInterface *displayRenderer; + }; #endif diff --git a/libs/widgets/KoEditColorSetDialog.cpp b/libs/widgets/KoEditColorSetDialog.cpp index c76eead87b..b5e8e6f212 100644 --- a/libs/widgets/KoEditColorSetDialog.cpp +++ b/libs/widgets/KoEditColorSetDialog.cpp @@ -1,226 +1,239 @@ /* This file is part of the KDE project * Copyright (C) 2007 Fredy Yanardi * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "KoEditColorSetDialog.h" #include #include #include #include #include #include #include #include #include #include #include #include // debug #include KoEditColorSetWidget::KoEditColorSetWidget(const QList &palettes, const QString &activePalette, QWidget *parent) : QWidget(parent), m_colorSets(palettes), m_gridLayout(0), m_activeColorSet(0), m_activePatch(0), m_initialColorSetCount(palettes.count()), m_activeColorSetRequested(false) { widget.setupUi(this); foreach (KoColorSet *colorSet, m_colorSets) { colorSet->load(); widget.selector->addItem(colorSet->name()); } connect(widget.selector, SIGNAL(currentIndexChanged(int)), this, SLOT(setActiveColorSet(int))); // A widget that shows all colors from active palette // FIXME no need to handcode the QScrollArea if designer can add QScrollArea (Qt 4.4?) m_scrollArea = new QScrollArea(widget.patchesFrame); int index = 0; foreach (KoColorSet *set, m_colorSets) { if (set->name() == activePalette) { m_activeColorSet = set; index = widget.selector->findText(set->name()); widget.selector->setCurrentIndex(index); } } if (!m_activeColorSet && !palettes.isEmpty()) { m_activeColorSet = palettes.first(); index = widget.selector->findText(m_activeColorSet->name()); } - m_scrollArea->setMinimumWidth(16*(12+2)); + int columns = 16; + if(m_activeColorSet) { + columns = m_activeColorSet->columnCount(); + if (columns==0){ + columns = 16; + } + } + m_scrollArea->setMinimumWidth(columns*(12+2)); QHBoxLayout *layout = new QHBoxLayout(); layout->setContentsMargins(0, 0, 0, 0); layout->addWidget(m_scrollArea); widget.patchesFrame->setLayout(layout); widget.add->setIcon(koIcon("list-add")); widget.remove->setIcon(koIcon("list-remove")); widget.open->setIcon(koIcon("document-open")); widget.save->setIcon(koIcon("document-save")); setEnabled(m_activeColorSet != 0); setActiveColorSet(index); widget.remove->setEnabled(false); // initially no color selected connect(widget.add, SIGNAL(clicked()), this, SLOT(addColor())); connect(widget.remove, SIGNAL(clicked()), this, SLOT(removeColor())); connect(widget.open, SIGNAL(clicked()), this, SLOT(open())); connect(widget.save, SIGNAL(clicked()), this, SLOT(save())); } KoEditColorSetWidget::~KoEditColorSetWidget() { // only delete new color sets uint colorSetCount = m_colorSets.count(); for( uint i = m_initialColorSetCount; i < colorSetCount; ++i ) { KoColorSet * cs = m_colorSets[i]; // if the active color set was requested by activeColorSet() // the caller takes ownership and then we do not delete it here if( cs == m_activeColorSet && m_activeColorSetRequested ) continue; delete cs; } } void KoEditColorSetWidget::setActiveColorSet(int index) { if (m_gridLayout) { delete m_gridLayout; m_activePatch = 0; } QWidget *wdg = new QWidget(m_scrollArea); m_gridLayout = new QGridLayout(); m_gridLayout->setMargin(0); m_gridLayout->setSpacing(2); m_activeColorSet = m_colorSets.value(index); setEnabled(m_activeColorSet != 0); + int columns = 16; if (m_activeColorSet) { + columns = m_activeColorSet->columnCount(); + if (columns==0){columns=16;} widget.remove->setEnabled(false); for (int i = 0; i < m_activeColorSet->nColors(); i++) { KoColorPatch *patch = new KoColorPatch(widget.patchesFrame); patch->setColor(m_activeColorSet->getColor(i).color); + patch->setToolTip(m_activeColorSet->getColor(i).name); connect(patch, SIGNAL(triggered(KoColorPatch *)), this, SLOT(setTextLabel(KoColorPatch *))); - m_gridLayout->addWidget(patch, i/16, i%16); + m_gridLayout->addWidget(patch, i/columns, i%columns); } } + m_scrollArea->setMinimumWidth(columns*(12+2)); wdg->setLayout(m_gridLayout); m_scrollArea->setWidget(wdg); } void KoEditColorSetWidget::setTextLabel(KoColorPatch *patch) { - widget.colorName->setText(patch->color().toQColor().name()); + widget.colorName->setText(patch->toolTip()); if (m_activePatch) { m_activePatch->setFrameShape(QFrame::NoFrame); m_activePatch->setFrameShadow(QFrame::Plain); } m_activePatch = patch; m_activePatch->setFrameShape(QFrame::Panel); m_activePatch->setFrameShadow(QFrame::Raised); widget.remove->setEnabled(true); } void KoEditColorSetWidget::addColor() { QColor color; color = QColorDialog::getColor(color); if (color.isValid()) { KoColorSetEntry newEntry; newEntry.color = KoColor(color, KoColorSpaceRegistry::instance()->rgb8()); newEntry.name = QInputDialog::getText(this, i18n("Add Color To Palette"), i18n("Color name:")); KoColorPatch *patch = new KoColorPatch(widget.patchesFrame); patch->setColor(newEntry.color); + patch->setToolTip(newEntry.name); connect(patch, SIGNAL(triggered(KoColorPatch *)), this, SLOT(setTextLabel(KoColorPatch *))); Q_ASSERT(m_gridLayout); Q_ASSERT(m_activeColorSet); - m_gridLayout->addWidget(patch, m_activeColorSet->nColors()/16, m_activeColorSet->nColors()%16); + m_gridLayout->addWidget(patch, m_activeColorSet->nColors()/m_activeColorSet->columnCount(), m_activeColorSet->nColors()%m_activeColorSet->columnCount()); m_activeColorSet->add(newEntry); } } void KoEditColorSetWidget::removeColor() { Q_ASSERT(m_activeColorSet); for (int i = 0; i < m_activeColorSet->nColors(); i++) { if (m_activePatch->color() == m_activeColorSet->getColor(i).color) { m_activeColorSet->remove(m_activeColorSet->getColor(i)); setActiveColorSet(widget.selector->currentIndex()); break; } } } void KoEditColorSetWidget::open() { Q_ASSERT(m_activeColorSet); KoFileDialog dialog(this, KoFileDialog::OpenFile, "OpenColorSet"); dialog.setDefaultDir(m_activeColorSet->filename()); dialog.setMimeTypeFilters(QStringList() << "application/x-gimp-color-palette", "application/x-gimp-color-palette"); QString fileName = dialog.filename(); KoColorSet *colorSet = new KoColorSet(fileName); colorSet->load(); m_colorSets.append(colorSet); widget.selector->addItem(colorSet->name()); widget.selector->setCurrentIndex(widget.selector->count() - 1); } void KoEditColorSetWidget::save() { Q_ASSERT(m_activeColorSet); if (!m_activeColorSet->save()) KMessageBox::error(0, i18n("Cannot write to palette file %1. Maybe it is read-only. ", m_activeColorSet->filename()), i18n("Palette")); } KoColorSet *KoEditColorSetWidget::activeColorSet() { m_activeColorSetRequested = true; return m_activeColorSet; } KoEditColorSetDialog::KoEditColorSetDialog(const QList &palettes, const QString &activePalette, QWidget *parent) : KoDialog(parent) { ui = new KoEditColorSetWidget(palettes, activePalette, this); setMainWidget(ui); setCaption(i18n("Add/Remove Colors")); enableButton(KoDialog::Ok, ui->isEnabled()); } KoEditColorSetDialog::~KoEditColorSetDialog() { delete ui; } KoColorSet *KoEditColorSetDialog::activeColorSet() { return ui->activeColorSet(); } diff --git a/plugins/dockers/animation/onion_skins_docker.cpp b/plugins/dockers/animation/onion_skins_docker.cpp index 230f49091c..ab0879a74a 100644 --- a/plugins/dockers/animation/onion_skins_docker.cpp +++ b/plugins/dockers/animation/onion_skins_docker.cpp @@ -1,183 +1,187 @@ /* * Copyright (c) 2015 Jouni Pentikäinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "onion_skins_docker.h" #include "ui_onion_skins_docker.h" #include #include #include #include "kis_icon_utils.h" #include "kis_image_config.h" #include "kis_onion_skin_compositor.h" #include "kis_signals_blocker.h" #include "KisViewManager.h" #include "kis_action_manager.h" #include "kis_action.h" +#include #include "kis_equalizer_widget.h" static const int MAX_SKIN_COUNT = 10; OnionSkinsDocker::OnionSkinsDocker(QWidget *parent) : QDockWidget(i18n("Onion Skins"), parent), ui(new Ui::OnionSkinsDocker), m_updatesCompressor(300, KisSignalCompressor::FIRST_ACTIVE), m_toggleOnionSkinsAction(0) { QWidget* mainWidget = new QWidget(this); setWidget(mainWidget); KisImageConfig config; ui->setupUi(mainWidget); ui->doubleTintFactor->setMinimum(0); ui->doubleTintFactor->setMaximum(100); ui->doubleTintFactor->setPrefix(i18n("Tint: ")); ui->doubleTintFactor->setSuffix("%"); ui->btnBackwardColor->setToolTip(i18n("Tint color for past frames")); ui->btnForwardColor->setToolTip(i18n("Tint color for future frames")); QVBoxLayout *layout = ui->slidersLayout; m_equalizerWidget = new KisEqualizerWidget(10, this); connect(m_equalizerWidget, SIGNAL(sigConfigChanged()), &m_updatesCompressor, SLOT(start())); layout->addWidget(m_equalizerWidget, 1); - connect(ui->btnBackwardColor, SIGNAL(changed(QColor)), &m_updatesCompressor, SLOT(start())); - connect(ui->btnForwardColor, SIGNAL(changed(QColor)), &m_updatesCompressor, SLOT(start())); + connect(ui->btnBackwardColor, SIGNAL(changed(KoColor)), &m_updatesCompressor, SLOT(start())); + connect(ui->btnForwardColor, SIGNAL(changed(KoColor)), &m_updatesCompressor, SLOT(start())); connect(ui->doubleTintFactor, SIGNAL(valueChanged(qreal)), &m_updatesCompressor, SLOT(start())); connect(&m_updatesCompressor, SIGNAL(timeout()), SLOT(changed())); { const bool isShown = config.showAdditionalOnionSkinsSettings(); ui->btnShowHide->setChecked(isShown); connect(ui->btnShowHide, SIGNAL(toggled(bool)), SLOT(slotShowAdditionalSettings(bool))); slotShowAdditionalSettings(isShown); } loadSettings(); KisOnionSkinCompositor::instance()->configChanged(); resize(sizeHint()); } OnionSkinsDocker::~OnionSkinsDocker() { delete ui; } void OnionSkinsDocker::setCanvas(KoCanvasBase *canvas) { Q_UNUSED(canvas); } void OnionSkinsDocker::unsetCanvas() { } void OnionSkinsDocker::setMainWindow(KisViewManager *view) { KisActionManager *actionManager = view->actionManager(); m_toggleOnionSkinsAction = actionManager->createAction("toggle_onion_skin"); connect(m_toggleOnionSkinsAction, SIGNAL(triggered()), SLOT(slotToggleOnionSkins())); slotUpdateIcons(); connect(view->mainWindow(), SIGNAL(themeChanged()), this, SLOT(slotUpdateIcons())); } void OnionSkinsDocker::slotToggleOnionSkins() { m_equalizerWidget->toggleMasterSwitch(); } void OnionSkinsDocker::slotUpdateIcons() { if (m_toggleOnionSkinsAction) { m_toggleOnionSkinsAction->setIcon(KisIconUtils::loadIcon("onion_skin_options")); } } void OnionSkinsDocker::slotShowAdditionalSettings(bool value) { ui->lblPrevColor->setVisible(value); ui->lblNextColor->setVisible(value); ui->btnBackwardColor->setVisible(value); ui->btnForwardColor->setVisible(value); ui->doubleTintFactor->setVisible(value); QIcon icon = KisIconUtils::loadIcon(value ? "arrow-down" : "arrow-up"); ui->btnShowHide->setIcon(icon); KisImageConfig config; config.setShowAdditionalOnionSkinsSettings(value); } void OnionSkinsDocker::changed() { KisImageConfig config; KisEqualizerWidget::EqualizerValues v = m_equalizerWidget->getValues(); config.setNumberOfOnionSkins(v.maxDistance); for (int i = -v.maxDistance; i <= v.maxDistance; i++) { config.setOnionSkinOpacity(i, v.value[i] * 255.0 / 100.0); config.setOnionSkinState(i, v.state[i]); } config.setOnionSkinTintFactor(ui->doubleTintFactor->value() * 255.0 / 100.0); - config.setOnionSkinTintColorBackward(ui->btnBackwardColor->color()); - config.setOnionSkinTintColorForward(ui->btnForwardColor->color()); + config.setOnionSkinTintColorBackward(ui->btnBackwardColor->color().toQColor()); + config.setOnionSkinTintColorForward(ui->btnForwardColor->color().toQColor()); KisOnionSkinCompositor::instance()->configChanged(); } void OnionSkinsDocker::loadSettings() { KisImageConfig config; KisSignalsBlocker b(ui->doubleTintFactor, ui->btnBackwardColor, ui->btnForwardColor, m_equalizerWidget); ui->doubleTintFactor->setValue(config.onionSkinTintFactor() * 100.0 / 255); - ui->btnBackwardColor->setColor(config.onionSkinTintColorBackward()); - ui->btnForwardColor->setColor(config.onionSkinTintColorForward()); + KoColor bcol(KoColorSpaceRegistry::instance()->rgb8()); + bcol.fromQColor(config.onionSkinTintColorBackward()); + ui->btnBackwardColor->setColor(bcol); + bcol.fromQColor(config.onionSkinTintColorForward()); + ui->btnForwardColor->setColor(bcol); KisEqualizerWidget::EqualizerValues v; v.maxDistance = 10; for (int i = -v.maxDistance; i <= v.maxDistance; i++) { v.value.insert(i, config.onionSkinOpacity(i) * 100.0 / 255.0); v.state.insert(i, config.onionSkinState(i)); } m_equalizerWidget->setValues(v); } diff --git a/plugins/dockers/animation/onion_skins_docker.ui b/plugins/dockers/animation/onion_skins_docker.ui index e232c231df..001b8ccf52 100644 --- a/plugins/dockers/animation/onion_skins_docker.ui +++ b/plugins/dockers/animation/onion_skins_docker.ui @@ -1,135 +1,130 @@ OnionSkinsDocker 0 0 - 299 + 356 368 Onion skin options 0 6 Qt::Horizontal + true false true - + 50 0 - + Previous frames Qt::Horizontal 13 13 Next frames - + - lblPrevColor - btnBackwardColor - btnForwardColor - lblNextColor - - KColorButton - QPushButton -
kcolorbutton.h
- 1 -
KisDoubleSliderSpinBox QWidget
kis_slider_spin_box.h
1
+ + KisColorButton + QPushButton +
kis_color_button.h
+
diff --git a/plugins/dockers/digitalmixer/digitalmixer_dock.cc b/plugins/dockers/digitalmixer/digitalmixer_dock.cc index 8cb19dcbb4..6da7c7138d 100644 --- a/plugins/dockers/digitalmixer/digitalmixer_dock.cc +++ b/plugins/dockers/digitalmixer/digitalmixer_dock.cc @@ -1,161 +1,167 @@ /* * Copyright (c) 2009 Cyrille Berger * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "digitalmixer_dock.h" #include #include #include #include #include #include #include #include #include #include +#include + class DigitalMixerPatch : public KoColorPatch { public: DigitalMixerPatch(QWidget* parent) : KoColorPatch(parent) {} QSize sizeHint() const { return QSize(24,24); } }; DigitalMixerDock::DigitalMixerDock( ) : QDockWidget(i18n("Digital Colors Mixer")), m_canvas(0) , m_tellCanvas(true) { - QColor initColors[6] = { Qt::black, Qt::white, Qt::red, Qt::green, Qt::blue, Qt::yellow }; + const KoColorSpace *sRGB = KoColorSpaceRegistry::instance()->rgb8(); + KoColor initColors[6] = { KoColor(Qt::black, sRGB), + KoColor(Qt::white, sRGB), + KoColor(Qt::red, sRGB), + KoColor(Qt::green, sRGB), + KoColor(Qt::blue, sRGB), + KoColor(Qt::yellow, sRGB) }; QWidget* widget = new QWidget(this); QGridLayout* layout = new QGridLayout( widget ); // Current Color m_currentColorPatch = new KoColorPatch(this); m_currentColorPatch->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); m_currentColorPatch->setMinimumWidth(48); layout->addWidget(m_currentColorPatch, 0, 0,3,1); // Create the sliders QSignalMapper* signalMapperSelectColor = new QSignalMapper(this); connect(signalMapperSelectColor, SIGNAL(mapped(int)), SLOT(popupColorChanged(int))); QSignalMapper* signalMapperColorSlider = new QSignalMapper(this); connect(signalMapperColorSlider, SIGNAL(mapped(int)), SLOT(colorSliderChanged(int))); QSignalMapper* signalMapperTargetColor = new QSignalMapper(this); connect(signalMapperTargetColor, SIGNAL(mapped(int)), SLOT(targetColorChanged(int))); for(int i = 0; i < 6; ++i) { Mixer mixer; mixer.targetColor = new DigitalMixerPatch(this); mixer.targetColor->setFixedSize(32, 22); layout->addWidget(mixer.targetColor, 0, i + 1); mixer.targetSlider = new KoColorSlider(Qt::Vertical, this); mixer.targetSlider->setFixedWidth(22); mixer.targetSlider->setMinimumHeight(66); layout->addWidget(mixer.targetSlider, 1, i + 1); - QToolButton* colorSelector = new QToolButton( this ); - mixer.actionColor = new KoColorPopupAction(this); - mixer.actionColor->setCurrentColor(initColors[i]); - colorSelector->setDefaultAction(mixer.actionColor); - colorSelector->setFixedSize(colorSelector->sizeHint()); - layout->addWidget(colorSelector, 2, i + 1); + mixer.actionColor = new KisColorButton( this ); + mixer.actionColor->setColor(initColors[i]); + mixer.actionColor->setFixedWidth(22); + layout->addWidget(mixer.actionColor, 2, i + 1); m_mixers.push_back(mixer); - connect(mixer.actionColor, SIGNAL(colorChanged(KoColor)), signalMapperSelectColor, SLOT(map())); + connect(mixer.actionColor, SIGNAL(changed(KoColor)), signalMapperSelectColor, SLOT(map())); signalMapperSelectColor->setMapping(mixer.actionColor, i); connect(mixer.targetSlider, SIGNAL(valueChanged(int)), signalMapperColorSlider, SLOT(map())); signalMapperColorSlider->setMapping(mixer.targetSlider, i); mixer.targetSlider->setValue(125); connect(mixer.targetColor, SIGNAL(triggered(KoColorPatch*)), signalMapperTargetColor, SLOT(map())); signalMapperTargetColor->setMapping(mixer.targetColor, i); } setCurrentColor(KoColor(Qt::black, KoColorSpaceRegistry::instance()->rgb8())); setWidget( widget ); } void DigitalMixerDock::setCanvas(KoCanvasBase * canvas) { setEnabled(canvas != 0); if (m_canvas) { m_canvas->disconnectCanvasObserver(this); } m_canvas = canvas; if (m_canvas) { connect(m_canvas->resourceManager(), SIGNAL(canvasResourceChanged(int, const QVariant&)), this, SLOT(canvasResourceChanged(int, const QVariant&))); m_tellCanvas=false; setCurrentColor(m_canvas->resourceManager()->foregroundColor()); m_tellCanvas=true; } } void DigitalMixerDock::popupColorChanged(int i) { - KoColor color = m_mixers[i].actionColor->currentKoColor(); + KoColor color = m_mixers[i].actionColor->color(); color.convertTo(m_currentColor.colorSpace()); m_mixers[i].targetSlider->setColors( color, m_currentColor); colorSliderChanged(i); } void DigitalMixerDock::colorSliderChanged(int i) { m_mixers[i].targetColor->setColor(m_mixers[i].targetSlider->currentColor()); } void DigitalMixerDock::targetColorChanged(int i) { setCurrentColor(m_mixers[i].targetColor->color()); } void DigitalMixerDock::setCurrentColor(const KoColor& color) { m_currentColor = color; m_currentColorPatch->setColor(color); for(int i = 0; i < m_mixers.size(); ++i) { popupColorChanged(i); colorSliderChanged(i); } if (m_canvas && m_tellCanvas) { m_canvas->resourceManager()->setForegroundColor(m_currentColor); } } void DigitalMixerDock::canvasResourceChanged(int key, const QVariant& v) { m_tellCanvas = false; if (key == KoCanvasResourceManager::ForegroundColor) setCurrentColor(v.value()); m_tellCanvas = true; } diff --git a/plugins/dockers/digitalmixer/digitalmixer_dock.h b/plugins/dockers/digitalmixer/digitalmixer_dock.h index 1604b4b55f..21677b3d54 100644 --- a/plugins/dockers/digitalmixer/digitalmixer_dock.h +++ b/plugins/dockers/digitalmixer/digitalmixer_dock.h @@ -1,58 +1,59 @@ /* * Copyright (c) 2009 Cyrille Berger * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _DIGITALMIXER_DOCK_H_ #define _DIGITALMIXER_DOCK_H_ #include #include #include class KoColorPopupAction; class KoColorSlider; class KoColorPatch; +class KisColorButton; class DigitalMixerDock : public QDockWidget, public KoCanvasObserverBase { Q_OBJECT public: DigitalMixerDock( ); QString observerName() { return "DigitalMixerDock"; } /// reimplemented from KoCanvasObserverBase virtual void setCanvas(KoCanvasBase *canvas); virtual void unsetCanvas() { m_canvas = 0; setEnabled(false);} public Q_SLOTS: void setCurrentColor(const KoColor& ); void canvasResourceChanged(int, const QVariant&); private Q_SLOTS: void popupColorChanged(int i); void colorSliderChanged(int i); void targetColorChanged(int); private: KoCanvasBase* m_canvas; KoColor m_currentColor; KoColorPatch* m_currentColorPatch; struct Mixer { KoColorPatch* targetColor; KoColorSlider* targetSlider; - KoColorPopupAction* actionColor; + KisColorButton* actionColor; }; QList m_mixers; bool m_tellCanvas; }; #endif diff --git a/plugins/dockers/palettedocker/palettedocker_dock.cpp b/plugins/dockers/palettedocker/palettedocker_dock.cpp index a4363560b8..d641835b57 100644 --- a/plugins/dockers/palettedocker/palettedocker_dock.cpp +++ b/plugins/dockers/palettedocker/palettedocker_dock.cpp @@ -1,334 +1,335 @@ /* * Copyright (c) 2013 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "palettedocker_dock.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "KisPaletteModel.h" #include "KisColorsetChooser.h" #include "ui_wdgpalettedock.h" /// The resource item delegate for rendering the resource preview class PaletteDelegate : public QAbstractItemDelegate { public: PaletteDelegate(QObject * parent = 0) : QAbstractItemDelegate(parent), m_showText(false) {} virtual ~PaletteDelegate() {} /// reimplemented virtual void paint(QPainter *, const QStyleOptionViewItem &, const QModelIndex &) const; /// reimplemented QSize sizeHint(const QStyleOptionViewItem & option, const QModelIndex &) const { return option.decorationSize; } void setShowText(bool showText) { m_showText = showText; } private: bool m_showText; }; void PaletteDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const { painter->save(); if (! index.isValid()) return; if (option.state & QStyle::State_Selected) { painter->setPen(QPen(option.palette.highlightedText(), 2.0)); painter->fillRect(option.rect, option.palette.highlight()); } else { painter->setPen(QPen(option.palette.text(), 2.0)); } QRect paintRect = option.rect.adjusted(1, 1, -1, -1); QBrush brush = qVariantValue(index.data(Qt::BackgroundRole)); painter->fillRect(paintRect, brush); painter->restore(); } bool PaletteDockerDock::eventFilter(QObject* object, QEvent* event) { if (object == m_wdgPaletteDock->paletteView->viewport() && event->type() == QEvent::Wheel) { QWheelEvent* qwheel = dynamic_cast(event); if (qwheel->modifiers() & Qt::ControlModifier) { int numDegrees = qwheel->delta() / 8; int numSteps = numDegrees / 7; int curSize = m_wdgPaletteDock->paletteView->horizontalHeader()->sectionSize(0); int setSize = numSteps + curSize; if ( setSize >= 12 ) { m_wdgPaletteDock->paletteView->horizontalHeader()->setDefaultSectionSize(setSize); m_wdgPaletteDock->paletteView->verticalHeader()->setDefaultSectionSize(setSize); KisConfig cfg; cfg.setPaletteDockerPaletteViewSectionSize(setSize); } return true; } else { return false; } } else { return QWidget::eventFilter(object, event); } } PaletteDockerDock::PaletteDockerDock( ) : QDockWidget(i18n("Palette")) , m_wdgPaletteDock(new Ui_WdgPaletteDock()) , m_currentColorSet(0) , m_resourceProvider(0) , m_canvas(0) { QWidget* mainWidget = new QWidget(this); setWidget(mainWidget); m_wdgPaletteDock->setupUi(mainWidget); m_wdgPaletteDock->bnAdd->setIcon(KisIconUtils::loadIcon("list-add")); m_wdgPaletteDock->bnAdd->setIconSize(QSize(16, 16)); m_wdgPaletteDock->bnAddDialog->setIcon(KisIconUtils::loadIcon("document-new")); m_wdgPaletteDock->bnAddDialog->setIconSize(QSize(16, 16)); m_wdgPaletteDock->bnRemove->setIcon(KisIconUtils::loadIcon("edit-delete")); m_wdgPaletteDock->bnRemove->setIconSize(QSize(16, 16)); m_wdgPaletteDock->bnAdd->setEnabled(false); m_wdgPaletteDock->bnRemove->setEnabled(false); connect(m_wdgPaletteDock->bnAdd, SIGNAL(clicked(bool)), this, SLOT(addColorForeground())); connect(m_wdgPaletteDock->bnAddDialog, SIGNAL(clicked(bool)), this, SLOT(addColor())); connect(m_wdgPaletteDock->bnRemove, SIGNAL(clicked(bool)), this, SLOT(removeColor())); m_model = new KisPaletteModel(this); m_wdgPaletteDock->paletteView->setModel(m_model); m_wdgPaletteDock->paletteView->setShowGrid(false); m_wdgPaletteDock->paletteView->horizontalHeader()->setVisible(false); m_wdgPaletteDock->paletteView->verticalHeader()->setVisible(false); m_wdgPaletteDock->paletteView->setItemDelegate(new PaletteDelegate()); KisConfig cfg; QPalette pal(palette()); pal.setColor(QPalette::Base, cfg.getMDIBackgroundColor()); m_wdgPaletteDock->paletteView->setAutoFillBackground(true); m_wdgPaletteDock->paletteView->setPalette(pal); connect(m_wdgPaletteDock->paletteView, SIGNAL(clicked(QModelIndex)), this, SLOT(entrySelected(QModelIndex))); m_wdgPaletteDock->paletteView->viewport()->installEventFilter(this); KoResourceServer* rServer = KoResourceServerProvider::instance()->paletteServer(false); m_serverAdapter = QSharedPointer(new KoResourceServerAdapter(rServer)); m_serverAdapter->connectToResourceServer(); rServer->addObserver(this); m_colorSetChooser = new KisColorsetChooser(this); connect(m_colorSetChooser, SIGNAL(paletteSelected(KoColorSet*)), this, SLOT(setColorSet(KoColorSet*))); m_wdgPaletteDock->bnColorSets->setIcon(KisIconUtils::loadIcon("hi16-palette_library")); m_wdgPaletteDock->bnColorSets->setToolTip(i18n("Choose palette")); m_wdgPaletteDock->bnColorSets->setPopupWidget(m_colorSetChooser); int defaultSectionSize = cfg.paletteDockerPaletteViewSectionSize(); m_wdgPaletteDock->paletteView->horizontalHeader()->setDefaultSectionSize(defaultSectionSize); m_wdgPaletteDock->paletteView->verticalHeader()->setDefaultSectionSize(defaultSectionSize); QString defaultPalette = cfg.defaultPalette(); KoColorSet* defaultColorSet = rServer->resourceByName(defaultPalette); if (defaultColorSet) { setColorSet(defaultColorSet); } } PaletteDockerDock::~PaletteDockerDock() { KoResourceServer* rServer = KoResourceServerProvider::instance()->paletteServer(); rServer->removeObserver(this); if (m_currentColorSet) { KisConfig cfg; cfg.setDefaultPalette(m_currentColorSet->name()); } delete m_wdgPaletteDock->paletteView->itemDelegate(); delete m_wdgPaletteDock; } void PaletteDockerDock::setMainWindow(KisViewManager* kisview) { m_resourceProvider = kisview->resourceProvider(); connect(m_resourceProvider, SIGNAL(sigSavingWorkspace(KisWorkspaceResource*)), SLOT(saveToWorkspace(KisWorkspaceResource*))); connect(m_resourceProvider, SIGNAL(sigLoadingWorkspace(KisWorkspaceResource*)), SLOT(loadFromWorkspace(KisWorkspaceResource*))); kisview->nodeManager()->disconnect(m_model); } void PaletteDockerDock::setCanvas(KoCanvasBase *canvas) { setEnabled(canvas != 0); if (canvas) { KisCanvas2 *cv = dynamic_cast(canvas); m_model->setDisplayRenderer(cv->displayColorConverter()->displayRendererInterface()); } m_canvas = static_cast(canvas); } void PaletteDockerDock::unsetCanvas() { setEnabled(false); m_model->setDisplayRenderer(0); m_canvas = 0; } void PaletteDockerDock::unsetResourceServer() { KoResourceServer* rServer = KoResourceServerProvider::instance()->paletteServer(); rServer->removeObserver(this); } void PaletteDockerDock::removingResource(KoColorSet *resource) { if (resource == m_currentColorSet) { setColorSet(0); } } void PaletteDockerDock::resourceChanged(KoColorSet *resource) { setColorSet(resource); } void PaletteDockerDock::setColorSet(KoColorSet* colorSet) { m_model->setColorSet(colorSet); if (colorSet && colorSet->removable()) { m_wdgPaletteDock->bnAdd->setEnabled(true); m_wdgPaletteDock->bnRemove->setEnabled(false); } else { m_wdgPaletteDock->bnAdd->setEnabled(false); m_wdgPaletteDock->bnRemove->setEnabled(false); } m_currentColorSet = colorSet; } void PaletteDockerDock::addColorForeground() { if (m_resourceProvider) { KoColorSetEntry newEntry; newEntry.color = m_resourceProvider->fgColor(); m_currentColorSet->add(newEntry); m_currentColorSet->save(); setColorSet(m_currentColorSet); // update model } } void PaletteDockerDock::addColor() { if (m_currentColorSet && m_resourceProvider) { const KoColorDisplayRendererInterface *displayRenderer = m_canvas->displayColorConverter()->displayRendererInterface(); KoColor currentFgColor = m_canvas->resourceManager()->foregroundColor(); QColor color = QColorDialog::getColor(displayRenderer->toQColor(currentFgColor)); if (color.isValid()) { KoColorSetEntry newEntry; newEntry.color = displayRenderer->approximateFromRenderedQColor(color); m_currentColorSet->add(newEntry); m_currentColorSet->save(); setColorSet(m_currentColorSet); // update model } } } void PaletteDockerDock::removeColor() { QModelIndex index = m_wdgPaletteDock->paletteView->currentIndex(); if (!index.isValid()) { return; } int i = index.row()*m_model->columnCount()+index.column(); m_currentColorSet->removeAt(i); m_currentColorSet->save(); setColorSet(m_currentColorSet); // update model } void PaletteDockerDock::entrySelected(QModelIndex index) { if (!index.isValid()) { return; } int i = index.row()*m_model->columnCount()+index.column(); if (i < m_currentColorSet->nColors()) { KoColorSetEntry entry = m_currentColorSet->getColor(i); + m_wdgPaletteDock->lblColorName->setText(entry.name); if (m_resourceProvider) { m_resourceProvider->setFGColor(entry.color); } if (m_currentColorSet->removable()) { m_wdgPaletteDock->bnRemove->setEnabled(true); } } } void PaletteDockerDock::saveToWorkspace(KisWorkspaceResource* workspace) { if (m_currentColorSet) { workspace->setProperty("palette", m_currentColorSet->name()); } } void PaletteDockerDock::loadFromWorkspace(KisWorkspaceResource* workspace) { if (workspace->hasProperty("palette")) { KoResourceServer* rServer = KoResourceServerProvider::instance()->paletteServer(); KoColorSet* colorSet = rServer->resourceByName(workspace->getString("palette")); if (colorSet) { setColorSet(colorSet); } } } diff --git a/plugins/dockers/palettedocker/wdgpalettedock.ui b/plugins/dockers/palettedocker/wdgpalettedock.ui index 0154b44a81..28e41e6a5b 100644 --- a/plugins/dockers/palettedocker/wdgpalettedock.ui +++ b/plugins/dockers/palettedocker/wdgpalettedock.ui @@ -1,130 +1,155 @@ WdgPaletteDock 0 0 256 219 1 - + + 0 + + + 0 + + + 0 + + 0 0 16 - + + + + Add color + + + ... + + + + 22 + 22 + + + + false + + + + Qt::Horizontal 40 20 - + + + + + + + + Delete color ... 22 22 false - + Add foreground color ... 22 22 false - - - - Add color - - - ... - - + + + - 22 - 22 + 60 + 0 - - false + + QFrame::StyledPanel - - - - KisPopupButton QPushButton
kis_popup_button.h
KoTableView QTableView
KoTableView.h
bnRemove
diff --git a/plugins/dockers/specificcolorselector/CMakeLists.txt b/plugins/dockers/specificcolorselector/CMakeLists.txt index 98359c542f..b05aff26e3 100644 --- a/plugins/dockers/specificcolorselector/CMakeLists.txt +++ b/plugins/dockers/specificcolorselector/CMakeLists.txt @@ -1,4 +1,8 @@ -set(KRITA_SPECIFICCOLORSELECTOR_SOURCES specificcolorselector.cc specificcolorselector_dock.cc kis_specific_color_selector_widget.cc kis_color_input.cc ) +set(KRITA_SPECIFICCOLORSELECTOR_SOURCES + specificcolorselector.cc + specificcolorselector_dock.cc + kis_specific_color_selector_widget.cc +) add_library(kritaspecificcolorselector MODULE ${KRITA_SPECIFICCOLORSELECTOR_SOURCES}) target_link_libraries(kritaspecificcolorselector kritaui ${OPENEXR_LIBRARIES}) install(TARGETS kritaspecificcolorselector DESTINATION ${KRITA_PLUGIN_INSTALL_DIR}) diff --git a/plugins/dockers/specificcolorselector/kis_specific_color_selector_widget.cc b/plugins/dockers/specificcolorselector/kis_specific_color_selector_widget.cc index c6dc9bea51..f5bb7e7104 100644 --- a/plugins/dockers/specificcolorselector/kis_specific_color_selector_widget.cc +++ b/plugins/dockers/specificcolorselector/kis_specific_color_selector_widget.cc @@ -1,236 +1,236 @@ /* * Copyright (c) 2008 Cyrille Berger * Copyright (c) 2015 Moritz Molch * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_specific_color_selector_widget.h" #include #include #include #include #include #include #include #include #include #include #include -#include "kis_color_input.h" +#include #include -#include "kis_debug.h" -#include "kis_color_space_selector.h" -#include "kis_signal_compressor.h" -#include "kis_display_color_converter.h" +#include +#include +#include +#include KisSpecificColorSelectorWidget::KisSpecificColorSelectorWidget(QWidget* parent) : QWidget(parent) , m_colorSpace(0) , m_spacer(0) , m_updateCompressor(new KisSignalCompressor(10, KisSignalCompressor::POSTPONE, this)) , m_customColorSpaceSelected(false) , m_displayConverter(0) { m_layout = new QVBoxLayout(this); m_layout->setContentsMargins(0,0,0,0); m_layout->setSpacing(1); m_updateAllowed = true; connect(m_updateCompressor, SIGNAL(timeout()), SLOT(updateTimeout())); m_colorspaceSelector = new KisColorSpaceSelector(this); m_colorspaceSelector->layout()->setSpacing(1); connect(m_colorspaceSelector, SIGNAL(colorSpaceChanged(const KoColorSpace*)), this, SLOT(setCustomColorSpace(const KoColorSpace*))); m_chkShowColorSpaceSelector = new QCheckBox(i18n("Show Colorspace Selector"), this); connect(m_chkShowColorSpaceSelector, SIGNAL(toggled(bool)), m_colorspaceSelector, SLOT(setVisible(bool))); KConfigGroup cfg = KSharedConfig::openConfig()->group(""); m_chkShowColorSpaceSelector->setChecked(cfg.readEntry("SpecificColorSelector/ShowColorSpaceSelector", true)); m_colorspaceSelector->setVisible(m_chkShowColorSpaceSelector->isChecked()); m_colorspaceSelector->showColorBrowserButton(false); m_layout->addWidget(m_chkShowColorSpaceSelector); m_layout->addWidget(m_colorspaceSelector); m_spacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Expanding); m_layout->addItem(m_spacer); } KisSpecificColorSelectorWidget::~KisSpecificColorSelectorWidget() { KConfigGroup cfg = KSharedConfig::openConfig()->group(""); cfg.writeEntry("SpecificColorSelector/ShowColorSpaceSelector", m_chkShowColorSpaceSelector->isChecked()); } bool KisSpecificColorSelectorWidget::customColorSpaceUsed() { return m_customColorSpaceSelected; } void KisSpecificColorSelectorWidget::setDisplayConverter(KisDisplayColorConverter *displayConverter) { const bool needsForceUpdate = m_displayConverter != displayConverter; m_displayConverter = displayConverter; if (m_displayConverter) { m_converterConnection.clear(); m_converterConnection.addConnection(m_displayConverter, SIGNAL(displayConfigurationChanged()), this, SLOT(rereadCurrentColorSpace())); } rereadCurrentColorSpace(needsForceUpdate); } void KisSpecificColorSelectorWidget::rereadCurrentColorSpace(bool force) { if (m_displayConverter && !m_customColorSpaceSelected) { m_colorSpace = m_displayConverter->paintingColorSpace(); } setColorSpace(m_colorSpace, force); setColor(m_color); } void KisSpecificColorSelectorWidget::setColorSpace(const KoColorSpace* cs, bool force) { Q_ASSERT(cs); dbgPlugins << cs->id() << " " << cs->profile()->name(); if (*m_colorSpace == *cs && !force) { Q_FOREACH (KisColorInput* input, m_inputs) { input->update(); } return; } m_colorSpace = KoColorSpaceRegistry::instance()->colorSpace(cs->colorModelId().id(), cs->colorDepthId().id(), cs->profile()); Q_ASSERT(m_colorSpace); Q_ASSERT(*m_colorSpace == *cs); m_color = KoColor(m_color, m_colorSpace); Q_FOREACH (KisColorInput* input, m_inputs) { delete input; } m_inputs.clear(); m_layout->removeItem(m_spacer); QList channels = KoChannelInfo::displayOrderSorted(m_colorSpace->channels()); KoColorDisplayRendererInterface *displayRenderer = m_displayConverter ? m_displayConverter->displayRendererInterface() : KisDisplayColorConverter::dumbConverterInstance()->displayRendererInterface(); Q_FOREACH (KoChannelInfo* channel, channels) { if (channel->channelType() == KoChannelInfo::COLOR) { KisColorInput* input = 0; switch (channel->channelValueType()) { case KoChannelInfo::UINT8: case KoChannelInfo::UINT16: case KoChannelInfo::UINT32: { input = new KisIntegerColorInput(this, channel, &m_color, displayRenderer); } break; case KoChannelInfo::FLOAT16: case KoChannelInfo::FLOAT32: { input = new KisFloatColorInput(this, channel, &m_color, displayRenderer); } break; default: Q_ASSERT(false); input = 0; } if (input) { connect(input, SIGNAL(updated()), this, SLOT(update())); connect(this, SIGNAL(updated()), input, SLOT(update())); m_inputs.append(input); m_layout->addWidget(input); } } } QList labels; int labelWidth = 0; Q_FOREACH (KisColorInput* input, m_inputs) { Q_FOREACH (QLabel* label, input->findChildren()) { labels.append(label); labelWidth = qMax(labelWidth, label->sizeHint().width()); } } Q_FOREACH (QLabel *label, labels) { label->setMinimumWidth(labelWidth); } bool allChannels8Bit = true; Q_FOREACH (KoChannelInfo* channel, channels) { if (channel->channelType() == KoChannelInfo::COLOR && channel->channelValueType() != KoChannelInfo::UINT8) { allChannels8Bit = false; } } if (allChannels8Bit) { KisColorInput* input = new KisHexColorInput(this, &m_color, displayRenderer); m_inputs.append(input); m_layout->addWidget(input); connect(input, SIGNAL(updated()), this, SLOT(update())); connect(this, SIGNAL(updated()), input, SLOT(update())); } m_layout->addItem(m_spacer); m_colorspaceSelector->blockSignals(true); m_colorspaceSelector->setCurrentColorSpace(cs); m_colorspaceSelector->blockSignals(false); m_updateAllowed = false; emit(updated()); m_updateAllowed = true; } void KisSpecificColorSelectorWidget::update() { if (m_updateAllowed) { m_updateCompressor->start(); } } void KisSpecificColorSelectorWidget::setColor(const KoColor& c) { m_updateAllowed = false; m_color.fromKoColor(c); emit(updated()); m_updateAllowed = true; } void KisSpecificColorSelectorWidget::updateTimeout() { emit(colorChanged(m_color)); } void KisSpecificColorSelectorWidget::setCustomColorSpace(const KoColorSpace *colorSpace) { m_customColorSpaceSelected = true; setColorSpace(colorSpace); setColor(m_color); } #include "moc_kis_specific_color_selector_widget.cpp" diff --git a/plugins/extensions/layersplit/dlg_layersplit.cpp b/plugins/extensions/layersplit/dlg_layersplit.cpp index cb55361d59..165683405d 100644 --- a/plugins/extensions/layersplit/dlg_layersplit.cpp +++ b/plugins/extensions/layersplit/dlg_layersplit.cpp @@ -1,117 +1,148 @@ /* * Copyright (C) 2014 Boudewijn Rempt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "dlg_layersplit.h" #include + +#include #include #include #include #include #include "kis_slider_spin_box.h" #include #include #include DlgLayerSplit::DlgLayerSplit() : KoDialog() { m_page = new WdgLayerSplit(this); setCaption(i18n("Split Layer")); setButtons(Apply | Cancel); setDefaultButton(Apply); m_page->intFuzziness->setRange(0, 200); m_page->intFuzziness->setSingleStep(1); + + m_colorSetChooser = new KisColorsetChooser(); + m_page->paletteChooser->setPopupWidget(m_colorSetChooser); + connect(m_colorSetChooser, SIGNAL(paletteSelected(KoColorSet*)), this, SLOT(slotSetPalette(KoColorSet*))); + KisConfig cfg; m_page->intFuzziness->setValue(cfg.readEntry("layersplit/fuzziness", 20)); m_page->chkCreateGroupLayer->setChecked(cfg.readEntry("layerspit/createmastergroup", true)); m_page->chkSeparateGroupLayers->setChecked(cfg.readEntry("layerspit/separategrouplayers", false)); m_page->chkAlphaLock->setChecked(cfg.readEntry("layerspit/alphalock", true)); m_page->chkHideOriginal->setChecked(cfg.readEntry("layerspit/hideoriginal", false)); m_page->chkSortLayers->setChecked(cfg.readEntry("layerspit/sortlayers", true)); m_page->chkDisregardOpacity->setChecked(cfg.readEntry("layerspit/disregardopacity", true)); + QString paletteName = cfg.readEntry("layersplit/paletteName", "Default"); + KoResourceServer *pserver = KoResourceServerProvider::instance()->paletteServer(false); + KoColorSet *pal = pserver->resourceByName(paletteName); + if (pal) { + m_palette = pal; + m_page->paletteChooser->setText(pal->name()); + QIcon icon(QPixmap::fromImage(pal->image())); + m_page->paletteChooser->setIcon(icon); + } + + connect(this, SIGNAL(applyClicked()), this, SLOT(applyClicked())); setMainWidget(m_page); } DlgLayerSplit::~DlgLayerSplit() { } void DlgLayerSplit::applyClicked() { KisConfig cfg; cfg.writeEntry("layersplit/fuzziness", m_page->intFuzziness->value()); cfg.writeEntry("layerspit/createmastergroup", m_page->chkCreateGroupLayer->isChecked()); cfg.writeEntry("layerspit/separategrouplayers", m_page->chkSeparateGroupLayers->isChecked()); cfg.writeEntry("layerspit/alphalock", m_page->chkAlphaLock->isChecked()); cfg.writeEntry("layerspit/hideoriginal", m_page->chkHideOriginal->isChecked()); cfg.writeEntry("layerspit/sortlayers", m_page->chkSortLayers->isChecked()); cfg.writeEntry("layerspit/disregardopacity", m_page->chkDisregardOpacity->isChecked()); + cfg.writeEntry("layersplit/paletteName", m_palette->name()); accept(); } bool DlgLayerSplit::createBaseGroup() const { return m_page->chkCreateGroupLayer->isChecked(); } bool DlgLayerSplit::createSeparateGroups() const { return m_page->chkSeparateGroupLayers->isChecked(); } bool DlgLayerSplit::lockAlpha() const { return m_page->chkAlphaLock->isChecked(); } bool DlgLayerSplit::hideOriginal() const { return m_page->chkHideOriginal->isChecked(); } bool DlgLayerSplit::sortLayers() const { return m_page->chkSortLayers->isChecked(); } bool DlgLayerSplit::disregardOpacity() const { return m_page->chkDisregardOpacity->isChecked(); } int DlgLayerSplit::fuzziness() const { return m_page->intFuzziness->value(); } +KoColorSet *DlgLayerSplit::palette() const +{ + return m_palette; +} - +void DlgLayerSplit::slotSetPalette(KoColorSet *pal) +{ + if (pal) { + m_palette = pal; + m_page->paletteChooser->setText(pal->name()); + QIcon icon(QPixmap::fromImage(pal->image())); + m_page->paletteChooser->setIcon(icon); + } +} diff --git a/plugins/extensions/layersplit/dlg_layersplit.h b/plugins/extensions/layersplit/dlg_layersplit.h index aced7bf338..5f354258db 100644 --- a/plugins/extensions/layersplit/dlg_layersplit.h +++ b/plugins/extensions/layersplit/dlg_layersplit.h @@ -1,58 +1,63 @@ /* * Copyright (C) 2014 Boudewijn Rempt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef DLG_LAYERSPLIT #define DLG_LAYERSPLIT #include - +#include +#include #include #include "wdg_layersplit.h" /** * This dialog allows the user to create a selection mask based * on a (range of) colors. */ class DlgLayerSplit: public KoDialog { Q_OBJECT public: DlgLayerSplit(); ~DlgLayerSplit(); bool createBaseGroup() const; bool createSeparateGroups() const; bool lockAlpha() const; bool hideOriginal() const; bool sortLayers() const; bool disregardOpacity() const; int fuzziness() const; + KoColorSet* palette() const; private Q_SLOTS: void applyClicked(); + void slotSetPalette(KoColorSet *pal); private: WdgLayerSplit* m_page; + KisColorsetChooser *m_colorSetChooser; + KoColorSet *m_palette; }; #endif // DLG_LAYERSPLIT diff --git a/plugins/extensions/layersplit/layersplit.cpp b/plugins/extensions/layersplit/layersplit.cpp index 15d60aa57a..6d01d05c04 100644 --- a/plugins/extensions/layersplit/layersplit.cpp +++ b/plugins/extensions/layersplit/layersplit.cpp @@ -1,220 +1,224 @@ /* * Copyright (C) 2014 Boudewijn Rempt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "layersplit.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dlg_layersplit.h" #include "kis_node_manager.h" #include "kis_node_commands_adapter.h" #include "kis_undo_adapter.h" #include #include K_PLUGIN_FACTORY_WITH_JSON(LayerSplitFactory, "kritalayersplit.json", registerPlugin();) LayerSplit::LayerSplit(QObject *parent, const QVariantList &) : KisViewPlugin(parent) { KisAction *action = createAction("layersplit"); connect(action, SIGNAL(triggered()), this, SLOT(slotLayerSplit())); } LayerSplit::~LayerSplit() { } struct Layer { KoColor color; KisPaintDeviceSP device; KisRandomAccessorSP accessor; int pixelsWritten; bool operator<(const Layer& other) const { return pixelsWritten < other.pixelsWritten; } }; void LayerSplit::slotLayerSplit() { DlgLayerSplit dlg; if (dlg.exec() == QDialog::Accepted) { dlg.hide(); QApplication::setOverrideCursor(Qt::WaitCursor); KoProgressUpdater* pu = m_view->createProgressUpdater(KoProgressUpdater::Unthreaded); pu->start(100, i18n("Split into Layers")); QPointer updater = pu->startSubtask(); KisImageSP image = m_view->image(); if (!image) return; image->lock(); KisNodeSP node = m_view->activeNode(); if (!node) return; KisPaintDeviceSP projection = node->projection(); if (!projection) return; QList colorMap; const KoColorSpace *cs = projection->colorSpace(); QRect rc = image->bounds(); int fuzziness = dlg.fuzziness(); updater->setProgress(0); KisRandomConstAccessorSP acc = projection->createRandomConstAccessorNG(rc.x(), rc.y()); for (int row = rc.y(); row < rc.height(); ++row) { for (int col = rc.x(); col < rc.width(); ++col) { acc->moveTo(col, row); KoColor c(cs); c.setColor(acc->rawDataConst(), cs); if (c.opacityU8() == OPACITY_TRANSPARENT_U8) { continue; } if (dlg.disregardOpacity()) { c.setOpacity(OPACITY_OPAQUE_U8); } bool found = false; Q_FOREACH (const Layer &l, colorMap) { if (fuzziness == 0) { found = (l.color == c); } else { quint8 match = cs->difference(l.color.data(), c.data()); found = (match <= fuzziness); } if (found) { KisRandomAccessorSP dstAcc = l.accessor; dstAcc->moveTo(col, row); memcpy(dstAcc->rawData(), acc->rawDataConst(), cs->pixelSize()); const_cast(&l)->pixelsWritten++; break; } } if (!found) { + QString name = dlg.palette()->closestColorName(c); + if (name.toLower() == "untitled" || name.toLower() == "none" || name.toLower() == "") { + name = KoColor::toQString(c); + } Layer l; l.color = c; - l.device = new KisPaintDevice(cs, KoColor::toQString(c)); + l.device = new KisPaintDevice(cs, name); l.accessor = l.device->createRandomAccessorNG(col, row); l.accessor->moveTo(col, row); memcpy(l.accessor->rawData(), acc->rawDataConst(), cs->pixelSize()); l.pixelsWritten = 1; colorMap << l; } } if (updater->interrupted()) { return; } updater->setProgress((row - rc.y()) * 100 / rc.height() - rc.y()); } updater->setProgress(100); dbgKrita << "Created" << colorMap.size() << "layers"; // Q_FOREACH (const Layer &l, colorMap) { // dbgKrita << "\t" << l.device->objectName() << ":" << l.pixelsWritten; // } if (dlg.sortLayers()) { qSort(colorMap); } KisUndoAdapter *undo = image->undoAdapter(); undo->beginMacro(kundo2_i18n("Split Layer")); KisNodeCommandsAdapter adapter(m_view); KisGroupLayerSP baseGroup = dynamic_cast(node->parent().data()); if (!baseGroup) { // Masks are never nested baseGroup = dynamic_cast(node->parent()->parent().data()); } if (dlg.hideOriginal()) { node->setVisible(false); } if (dlg.createBaseGroup()) { KisGroupLayerSP grp = new KisGroupLayer(image, i18n("Color"), OPACITY_OPAQUE_U8); adapter.addNode(grp, baseGroup, 1); baseGroup = grp; } Q_FOREACH (const Layer &l, colorMap) { KisGroupLayerSP grp = baseGroup; if (dlg.createSeparateGroups()) { grp = new KisGroupLayer(image, l.device->objectName(), OPACITY_OPAQUE_U8); adapter.addNode(grp, baseGroup, 1); } KisPaintLayerSP paintLayer = new KisPaintLayer(image, l.device->objectName(), OPACITY_OPAQUE_U8, l.device); adapter.addNode(paintLayer, grp, 0); paintLayer->setAlphaLocked(dlg.lockAlpha()); } undo->endMacro(); image->unlock(); image->setModified(); } QApplication::restoreOverrideCursor(); } #include "layersplit.moc" diff --git a/plugins/extensions/layersplit/wdg_layersplit.ui b/plugins/extensions/layersplit/wdg_layersplit.ui index 6b48346ce6..927b6704ee 100644 --- a/plugins/extensions/layersplit/wdg_layersplit.ui +++ b/plugins/extensions/layersplit/wdg_layersplit.ui @@ -1,142 +1,161 @@ WdgLayerSplit 0 0 449 - 271 + 273 Image Size QFormLayout::AllNonFixedFieldsGrow Put all new layers in a group layer true Put every layer in its own, separate group layer Alpha-lock every new layer true Hide the original layer true Sort layers by amount of non-transparent pixels true Fuzziness: intFuzziness - + Disregard opacity + + + + Palette to use for naming the layers: + + + + + + + Choose Palette + + + QFrame::Box <html><head/><body><p><span style=" font-weight:600;">Split a layer according to color</span></p><p>Creates a new layer for every color in the active layer.</p></body></html> Qt::RichText Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop true Qt::Vertical 20 40 + + KisPopupButton + QPushButton +
kis_popup_button.h
+
KisSliderSpinBox QWidget
kis_slider_spin_box.h
1
chkCreateGroupLayer chkSeparateGroupLayers chkAlphaLock chkHideOriginal chkSortLayers
diff --git a/plugins/filters/colors/kis_wdg_color_to_alpha.cpp b/plugins/filters/colors/kis_wdg_color_to_alpha.cpp index e45e7b08ac..1d13900252 100644 --- a/plugins/filters/colors/kis_wdg_color_to_alpha.cpp +++ b/plugins/filters/colors/kis_wdg_color_to_alpha.cpp @@ -1,119 +1,127 @@ /* * This file is part of Krita * * Copyright (c) 2006 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_wdg_color_to_alpha.h" #include #include #include #include #include #include #include #include #include #include #include #include +#include #include "ui_wdgcolortoalphabase.h" KisWdgColorToAlpha::KisWdgColorToAlpha(QWidget * parent) : KisConfigWidget(parent), m_view(0) { m_widget = new Ui_WdgColorToAlphaBase(); m_widget->setupUi(this); m_widget->textLabel1->hide(); m_widget->intThreshold->setRange(1, 255, 0); - connect(m_widget->colorSelector, SIGNAL(colorChanged(const QColor&)), SLOT(slotColorSelectorChanged(const QColor&))); + connect(m_widget->colorSelector, SIGNAL(sigNewColor(KoColor)), SLOT(slotColorSelectorChanged(const KoColor&))); connect(m_widget->intThreshold, SIGNAL(valueChanged(qreal)), SIGNAL(sigConfigurationItemChanged())); - connect(m_widget->btnCustomColor, SIGNAL(changed(const QColor&)), SLOT(slotCustomColorSelected(const QColor&))); + connect(m_widget->btnCustomColor, SIGNAL(changed(const KoColor)), SLOT(slotCustomColorSelected(const KoColor&))); - m_widget->btnCustomColor->setColor(Qt::white); + KoColor c(Qt::white, KoColorSpaceRegistry::instance()->rgb8()); + m_widget->btnCustomColor->setColor(c); } KisWdgColorToAlpha::~KisWdgColorToAlpha() { delete m_widget; } void KisWdgColorToAlpha::setView(KisViewManager *view) { m_view = view; } void KisWdgColorToAlpha::slotFgColorChanged(const KoColor &color) { - m_widget->btnCustomColor->setColor(color.toQColor()); + m_widget->btnCustomColor->setColor(color); } -void KisWdgColorToAlpha::slotColorSelectorChanged(const QColor &color) +void KisWdgColorToAlpha::slotColorSelectorChanged(const KoColor &color) { m_widget->btnCustomColor->setColor(color); } -void KisWdgColorToAlpha::slotCustomColorSelected(const QColor &color) +void KisWdgColorToAlpha::slotCustomColorSelected(const KoColor &color) { - m_widget->colorSelector->setQColor(color); + m_widget->colorSelector->slotSetColor(color); emit sigConfigurationItemChanged(); } void KisWdgColorToAlpha::setConfiguration(const KisPropertiesConfiguration* config) { QVariant value; if (config->getProperty("targetcolor", value)) { - m_widget->colorSelector->setQColor(value.value()); + KoColor c; + if (value.value().isValid()) { + c.fromQColor(value.value()); + } else { + c = value.value(); + } + m_widget->colorSelector->slotSetColor(c); } if (config->getProperty("threshold", value)) { m_widget->intThreshold->setValue(value.toInt()); } } KisPropertiesConfiguration* KisWdgColorToAlpha::configuration() const { KisFilterConfiguration* config = new KisFilterConfiguration("colortoalpha", 1); - config->setProperty("targetcolor", widget()->colorSelector->color()); + config->setProperty("targetcolor", widget()->colorSelector->getCurrentColor().toQColor()); config->setProperty("threshold", widget()->intThreshold->value()); return config; } void KisWdgColorToAlpha::hideEvent(QHideEvent *) { if (m_view) { disconnect(m_view->resourceProvider(), SIGNAL(sigFGColorChanged(const KoColor&)), this, SLOT(slotFgColorChanged(const KoColor&))); KoToolManager::instance()->switchBackRequested(); } } void KisWdgColorToAlpha::showEvent(QShowEvent *) { if (m_view) { connect(m_view->resourceProvider(), SIGNAL(sigFGColorChanged(const KoColor&)), this, SLOT(slotFgColorChanged(const KoColor&))); KoToolManager::instance()->switchToolTemporaryRequested("KritaSelected/KisToolColorPicker"); } } diff --git a/plugins/filters/colors/kis_wdg_color_to_alpha.h b/plugins/filters/colors/kis_wdg_color_to_alpha.h index 2b7a7cf980..2a2937d253 100644 --- a/plugins/filters/colors/kis_wdg_color_to_alpha.h +++ b/plugins/filters/colors/kis_wdg_color_to_alpha.h @@ -1,60 +1,60 @@ /* * This file is part of Krita * * Copyright (c) 2006 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_WDG_COLOR_TO_ALPHA_H_ #define _KIS_WDG_COLOR_TO_ALPHA_H_ #include class KoColor; class Ui_WdgColorToAlphaBase; class KisWdgColorToAlpha : public KisConfigWidget { Q_OBJECT public: KisWdgColorToAlpha(QWidget * parent); virtual ~KisWdgColorToAlpha(); inline const Ui_WdgColorToAlphaBase* widget() const { return m_widget; } void setView(KisViewManager *view); virtual void setConfiguration(const KisPropertiesConfiguration*); virtual KisPropertiesConfiguration* configuration() const; protected: void hideEvent(QHideEvent *); void showEvent(QShowEvent *); private Q_SLOTS: void slotFgColorChanged(const KoColor &color); - void slotColorSelectorChanged(const QColor &color); - void slotCustomColorSelected(const QColor &color); + void slotColorSelectorChanged(const KoColor &color); + void slotCustomColorSelected(const KoColor &color); private: Ui_WdgColorToAlphaBase* m_widget; KisViewManager *m_view; }; #endif diff --git a/plugins/filters/colors/wdgcolortoalphabase.ui b/plugins/filters/colors/wdgcolortoalphabase.ui index 4d7c8b3af7..961c7726db 100644 --- a/plugins/filters/colors/wdgcolortoalphabase.ui +++ b/plugins/filters/colors/wdgcolortoalphabase.ui @@ -1,218 +1,217 @@ WdgColorToAlphaBase 0 0 335 362 0 0 6 0 0 0 0 Color: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false Qt::Horizontal 20 0 - + 0 0 180 180 0 0 0 0 0 Qt::Horizontal 40 20 15 0 0 0 Threshold: Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter false - + 0 0 0 0 Color Picker: - + 0 0 16777215 16777215 false false false - KColorButton - QPushButton -
kcolorbutton.h
+ KisVisualColorSelector + QWidget +
kis_visual_color_selector.h
1
- KoTriangleColorSelector - QWidget -
KoTriangleColorSelector.h
- 1 + KisColorButton + QPushButton +
kis_color_button.h
KisDoubleSliderSpinBox QWidget
kis_slider_spin_box.h
1
kcolorbutton.h
diff --git a/plugins/filters/indexcolors/kiswdgindexcolors.cpp b/plugins/filters/indexcolors/kiswdgindexcolors.cpp index 22a57c9ff9..c375e6ee8b 100644 --- a/plugins/filters/indexcolors/kiswdgindexcolors.cpp +++ b/plugins/filters/indexcolors/kiswdgindexcolors.cpp @@ -1,190 +1,192 @@ /* * Copyright 2014 Manuel Riecke * * Permission to use, copy, modify, and distribute this software * and its documentation for any purpose and without fee is hereby * granted, provided that the above copyright notice appear in all * copies and that both that the copyright notice and this * permission notice and warranty disclaimer appear in supporting * documentation, and that the name of the author not be used in * advertising or publicity pertaining to distribution of the * software without specific, written prior permission. * * The author disclaim all warranties with regard to this * software, including all implied warranties of merchantability * and fitness. In no event shall the author be liable for any * special, indirect or consequential damages or any damages * whatsoever resulting from loss of use, data or profits, whether * in an action of contract, negligence or other tortious action, * arising out of or in connection with the use or performance of * this software. */ #include "filter/kis_color_transformation_configuration.h" #include "kiswdgindexcolors.h" #include "palettegeneratorconfig.h" #include "ui_kiswdgindexcolors.h" #include "kis_int_parse_spin_box.h" -#include +#include KisWdgIndexColors::KisWdgIndexColors(QWidget* parent, Qt::WFlags f, int delay): KisConfigWidget(parent, f, delay) { ui = new Ui::KisWdgIndexColors; ui->setupUi(this); connect(ui->diagCheck, SIGNAL(toggled(bool)), SIGNAL(sigConfigurationItemChanged())); connect(ui->inbetweenSpinBox, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); connect(ui->alphaStepsSpinBox, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); connect(ui->colorLimit, SIGNAL(valueChanged(int)), SLOT(slotColorLimitChanged(int))); connect(ui->colorLimit, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); connect(ui->colorLimitCheck, SIGNAL(toggled(bool)), SIGNAL(sigConfigurationItemChanged())); connect(ui->luminanceSlider, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); connect(ui->aSlider, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); connect(ui->bSlider, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); } void KisWdgIndexColors::slotColorLimitChanged(int value) { ui->colorLimit->setSuffix(i18ncp("suffix for a spinbox", " color", " colors", value)); } void KisWdgIndexColors::setup(QStringList shadesLabels, int ramps) { int rows = shadesLabels.length(); int collumns = ramps; m_colorSelectors.resize(rows); m_stepSpinners.resize(rows-1); // Labels for the shades for(int row = 0; row < rows; ++row) { QLabel* l = new QLabel(shadesLabels[row], ui->colorsBox); ui->layoutColors->addWidget(l, row+1, 0); m_colorSelectors[row].resize(collumns); } // Labels for the ramps /*for(int col = 0; col < collumns; ++col) { QLabel* l = new QLabel(rampsLabels[col], ui->colorsBox); l->setAlignment(Qt::AlignRight | Qt::AlignVCenter); ui->layoutColors->addWidget(l, 0, col+1); }*/ // Step selectors for the shade gradients for(int row = 0; row < (rows-1); ++row) { QLabel* l0 = new QLabel(shadesLabels[row+1]); QLabel* l1 = new QLabel(QString::fromUtf8("↔")); QLabel* l2 = new QLabel(shadesLabels[row]); QSpinBox* s = new KisIntParseSpinBox(); s->setMinimum(0); s->setMaximum(32); s->setValue(2); connect(s, SIGNAL(valueChanged(int)), this, SIGNAL(sigConfigurationItemChanged())); m_stepSpinners[row] = s; ui->layoutRowSteps->addWidget(l0, row, 0); ui->layoutRowSteps->addWidget(l1, row, 1); ui->layoutRowSteps->addWidget(l2, row, 2); ui->layoutRowSteps->addWidget(s, row, 3); } // Color selectors for(int y = 0; y < rows; ++y) for(int x = 0; x < collumns; ++x) { - KColorButton* b = new KColorButton; + KisColorButton* b = new KisColorButton; QCheckBox* c = new QCheckBox; c->setChecked(false); b->setEnabled(false); b->setMaximumWidth(50); c->setMaximumWidth(21); // Ugh. I hope this won't be causing any issues. Trying to get rid of the unnecessary spacing after it. connect(c, SIGNAL(toggled(bool)), b, SLOT(setEnabled(bool))); connect(c, SIGNAL(toggled(bool)), this, SIGNAL(sigConfigurationItemChanged())); - connect(b, SIGNAL(changed(QColor)), this, SIGNAL(sigConfigurationItemChanged())); + connect(b, SIGNAL(changed(KoColor)), this, SIGNAL(sigConfigurationItemChanged())); QHBoxLayout* cell = new QHBoxLayout(); cell->setSpacing(0); cell->setContentsMargins(0, 0, 0, 0); cell->addWidget(c); cell->addWidget(b); ui->layoutColors->addLayout(cell, 1+y, 1+x); m_colorSelectors[y][x].button = b; m_colorSelectors[y][x].checkbox = c; } } KisPropertiesConfiguration* KisWdgIndexColors::configuration() const { KisColorTransformationConfiguration* config = new KisColorTransformationConfiguration("indexcolors", 1); PaletteGeneratorConfig palCfg; for(int y = 0; y < 4; ++y) for(int x = 0; x < 4; ++x) { - palCfg.colors[y][x] = m_colorSelectors[y][x].button->color(); + palCfg.colors[y][x] = m_colorSelectors[y][x].button->color().toQColor(); palCfg.colorsEnabled[y][x] = m_colorSelectors[y][x].button->isEnabled(); } for(int y = 0; y < 3; ++y) palCfg.gradientSteps[y] = m_stepSpinners[y]->value(); palCfg.diagonalGradients = ui->diagCheck->isChecked(); palCfg.inbetweenRampSteps = ui->inbetweenSpinBox->value(); IndexColorPalette pal = palCfg.generate(); ui->colorCount->setText(QString::number(pal.numColors())); config->setProperty("paletteGen", palCfg.toByteArray()); config->setProperty("LFactor", ui->luminanceSlider->value() / 100.f); config->setProperty("aFactor", ui->aSlider->value() / 100.f); config->setProperty("bFactor", ui->bSlider->value() / 100.f); config->setProperty("reduceColorsEnabled", ui->colorLimitCheck->isChecked()); config->setProperty("colorLimit", ui->colorLimit->value()); config->setProperty("alphaSteps", ui->alphaStepsSpinBox->value()); return config; } void KisWdgIndexColors::setConfiguration(const KisPropertiesConfiguration* config) { PaletteGeneratorConfig palCfg; palCfg.fromByteArray(config->getProperty("paletteGen").toByteArray()); ui->luminanceSlider->setValue(config->getFloat("LFactor")*100); ui->aSlider->setValue(config->getFloat("aFactor")*100); ui->bSlider->setValue(config->getFloat("bFactor")*100); ui->alphaStepsSpinBox->setValue(config->getInt("alphaSteps")); ui->colorLimitCheck->setChecked(config->getBool("reduceColorsEnabled")); ui->colorLimit->setEnabled(config->getBool("reduceColorsEnabled")); ui->colorLimit->setValue(config->getInt("colorLimit")); ui->diagCheck->setChecked(palCfg.diagonalGradients); ui->inbetweenSpinBox->setValue(palCfg.inbetweenRampSteps); for(int y = 0; y < 4; ++y) for(int x = 0; x < 4; ++x) { m_colorSelectors[y][x].checkbox->setChecked(palCfg.colorsEnabled[y][x]); m_colorSelectors[y][x].button->setEnabled(palCfg.colorsEnabled[y][x]); - m_colorSelectors[y][x].button->setColor(palCfg.colors[y][x]); + KoColor c; + c.fromQColor(palCfg.colors[y][x]); + m_colorSelectors[y][x].button->setColor(c); } for(int y = 0; y < 3; ++y) m_stepSpinners[y]->setValue(palCfg.gradientSteps[y]); IndexColorPalette pal = palCfg.generate(); ui->colorCount->setText(QString::number(pal.numColors())); } diff --git a/plugins/filters/indexcolors/kiswdgindexcolors.h b/plugins/filters/indexcolors/kiswdgindexcolors.h index 4f32831db7..f1d4605f3a 100644 --- a/plugins/filters/indexcolors/kiswdgindexcolors.h +++ b/plugins/filters/indexcolors/kiswdgindexcolors.h @@ -1,59 +1,59 @@ /* * Copyright 2014 Manuel Riecke * * Permission to use, copy, modify, and distribute this software * and its documentation for any purpose and without fee is hereby * granted, provided that the above copyright notice appear in all * copies and that both that the copyright notice and this * permission notice and warranty disclaimer appear in supporting * documentation, and that the name of the author not be used in * advertising or publicity pertaining to distribution of the * software without specific, written prior permission. * * The author disclaim all warranties with regard to this * software, including all implied warranties of merchantability * and fitness. In no event shall the author be liable for any * special, indirect or consequential damages or any damages * whatsoever resulting from loss of use, data or profits, whether * in an action of contract, negligence or other tortious action, * arising out of or in connection with the use or performance of * this software. */ #ifndef KISWDGINDEXCOLORS_H #define KISWDGINDEXCOLORS_H #include #include class QCheckBox; -class KColorButton; +class KisColorButton; namespace Ui { class KisWdgIndexColors; } class KisWdgIndexColors : public KisConfigWidget { Q_OBJECT public: KisWdgIndexColors(QWidget* parent = 0, Qt::WFlags f = 0, int delay = 500); virtual KisPropertiesConfiguration* configuration() const; virtual void setConfiguration(const KisPropertiesConfiguration* config); void setup(QStringList shadesLabels, int ramps); private Q_SLOTS: void slotColorLimitChanged(int value); private: struct ColorWidgets { - KColorButton* button; + KisColorButton* button; QCheckBox* checkbox; }; QVector< QVector > m_colorSelectors; QVector< QSpinBox* > m_stepSpinners; Ui::KisWdgIndexColors* ui; }; #endif // KISWDGINDEXCOLORS_H diff --git a/plugins/generators/pattern/wdgpatternoptions.ui b/plugins/generators/pattern/wdgpatternoptions.ui index bc75be6b05..47e3dd0916 100644 --- a/plugins/generators/pattern/wdgpatternoptions.ui +++ b/plugins/generators/pattern/wdgpatternoptions.ui @@ -1,86 +1,86 @@ WdgPatternOptions 0 0 158 78 0 0 0 0 &Pattern: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter patternChooser &Color: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter bnColor - + - + 0 0 - KColorButton + KisColorButton QPushButton -
kcolorbutton.h
+
kis_color_button.h
KisPatternChooser QWidget
kis_pattern_chooser.h
1
diff --git a/plugins/generators/solid/colorgenerator.cpp b/plugins/generators/solid/colorgenerator.cpp index d147d74b7a..67268884fc 100644 --- a/plugins/generators/solid/colorgenerator.cpp +++ b/plugins/generators/solid/colorgenerator.cpp @@ -1,103 +1,103 @@ /* * This file is part of the KDE project * * Copyright (c) 2008 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "colorgenerator.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_wdg_color.h" #include "ui_wdgcoloroptions.h" K_PLUGIN_FACTORY_WITH_JSON(KritaColorGeneratorFactory, "kritacolorgenerator.json", registerPlugin();) KritaColorGenerator::KritaColorGenerator(QObject *parent, const QVariantList &) : QObject(parent) { KisGeneratorRegistry::instance()->add(new KisColorGenerator()); } KritaColorGenerator::~KritaColorGenerator() { } KisColorGenerator::KisColorGenerator() : KisGenerator(id(), KoID("basic"), i18n("&Solid Color...")) { setColorSpaceIndependence(FULLY_INDEPENDENT); setSupportsPainting(true); } KisFilterConfiguration* KisColorGenerator::factoryConfiguration(const KisPaintDeviceSP) const { KisFilterConfiguration* config = new KisFilterConfiguration("color", 1); QVariant v; v.setValue(KoColor()); config->setProperty("color", v); return config; } KisConfigWidget * KisColorGenerator::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const { Q_UNUSED(dev); return new KisWdgColor(parent); } void KisColorGenerator::generate(KisProcessingInformation dstInfo, const QSize& size, const KisFilterConfiguration* config, KoUpdater* progressUpdater) const { KisPaintDeviceSP dst = dstInfo.paintDevice(); Q_ASSERT(!dst.isNull()); Q_ASSERT(config); KoColor c; if (config) { c = config->getColor("color"); KisFillPainter gc(dst); gc.setProgress(progressUpdater); gc.setChannelFlags(config->channelFlags()); gc.setOpacity(100); gc.setSelection(dstInfo.selection()); gc.fillRect(QRect(dstInfo.topLeft(), size), c); gc.end(); } } -#include "colorgenerator.moc" \ No newline at end of file +#include "colorgenerator.moc" diff --git a/plugins/generators/solid/kis_wdg_color.cpp b/plugins/generators/solid/kis_wdg_color.cpp index a48e1f1eda..83624ece1b 100644 --- a/plugins/generators/solid/kis_wdg_color.cpp +++ b/plugins/generators/solid/kis_wdg_color.cpp @@ -1,60 +1,63 @@ /* * This file is part of Krita * * Copyright (c) 2006 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_wdg_color.h" #include #include #include #include "ui_wdgcoloroptions.h" -KisWdgColor::KisWdgColor(QWidget* parent) +KisWdgColor::KisWdgColor(QWidget* parent, const KoColorSpace *cs) : KisConfigWidget(parent) { m_widget = new Ui_WdgColorOptions(); m_widget->setupUi(this); + m_cs = cs; } KisWdgColor::~KisWdgColor() { delete m_widget; } void KisWdgColor::setConfiguration(const KisPropertiesConfiguration* config) { QVariant value; - widget()->bnColor->setColor(config->getColor("color").toQColor()); + KoColor c =config->getColor("color"); + c.convertTo(m_cs); + widget()->bnColor->setColor(c); } KisPropertiesConfiguration* KisWdgColor::configuration() const { KisFilterConfiguration* config = new KisFilterConfiguration("color", 1); KoColor c; - c.fromQColor(this->widget()->bnColor->color()); + c.fromKoColor(this->widget()->bnColor->color()); QVariant v; v.setValue(c); config->setProperty("color", v); return config; } diff --git a/plugins/generators/solid/kis_wdg_color.h b/plugins/generators/solid/kis_wdg_color.h index 2410a144c3..55ce1e54f1 100644 --- a/plugins/generators/solid/kis_wdg_color.h +++ b/plugins/generators/solid/kis_wdg_color.h @@ -1,45 +1,48 @@ /* * This file is part of Krita * * Copyright (c) 2006 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_WDG_COLOR_H #define KIS_WDG_COLOR_H #include +#include +#include class Ui_WdgColorOptions; class KisWdgColor : public KisConfigWidget { Q_OBJECT public: - KisWdgColor(QWidget* parent = 0); + KisWdgColor(QWidget* parent = 0, const KoColorSpace *cs = KoColorSpaceRegistry::instance()->rgb8()); ~KisWdgColor(); public: inline const Ui_WdgColorOptions* widget() const { return m_widget; } virtual void setConfiguration(const KisPropertiesConfiguration*); virtual KisPropertiesConfiguration* configuration() const; private: Ui_WdgColorOptions* m_widget; + const KoColorSpace *m_cs; }; #endif diff --git a/plugins/generators/solid/wdgcoloroptions.ui b/plugins/generators/solid/wdgcoloroptions.ui index a28c4adea6..b1f3e5e03a 100644 --- a/plugins/generators/solid/wdgcoloroptions.ui +++ b/plugins/generators/solid/wdgcoloroptions.ui @@ -1,73 +1,73 @@ WdgColorOptions 0 0 158 78 &Color: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter bnColor - + Qt::Horizontal QSizePolicy::Expanding 21 20 Qt::Vertical QSizePolicy::Expanding 20 21 - KColorButton + KisColorButton QPushButton -
kcolorbutton.h
+
kis_color_button.h
diff --git a/plugins/impex/jpeg/kis_jpeg_export.cc b/plugins/impex/jpeg/kis_jpeg_export.cc index 8169266783..c252383de6 100644 --- a/plugins/impex/jpeg/kis_jpeg_export.cc +++ b/plugins/impex/jpeg/kis_jpeg_export.cc @@ -1,226 +1,230 @@ /* * Copyright (c) 2005 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kis_jpeg_export.h" #include #include #include #include #include #include #include #include #include #include +#include #include #include #include #include #include "kis_slider_spin_box.h" #include #include #include #include #include #include #include #include #include #include #include #include "kis_jpeg_converter.h" #include #include "ui_kis_wdg_options_jpeg.h" class KisExternalLayer; K_PLUGIN_FACTORY_WITH_JSON(KisJPEGExportFactory, "krita_jpeg_export.json", registerPlugin();) KisJPEGExport::KisJPEGExport(QObject *parent, const QVariantList &) : KisImportExportFilter(parent) { } KisJPEGExport::~KisJPEGExport() { } KisImportExportFilter::ConversionStatus KisJPEGExport::convert(const QByteArray& from, const QByteArray& to) { dbgFile << "JPEG export! From:" << from << ", To:" << to << ""; if (from != "application/x-krita") return KisImportExportFilter::NotImplemented; KisDocument *input = inputDocument(); if (!input) return KisImportExportFilter::NoDocumentCreated; KisImageWSP image = input->image(); Q_CHECK_PTR(image); KoDialog* kdb = new KoDialog(0); kdb->setWindowTitle(i18n("JPEG Export Options")); kdb->setButtons(KoDialog::Ok | KoDialog::Cancel); Ui::WdgOptionsJPEG wdgUi; QWidget* wdg = new QWidget(kdb); wdgUi.setupUi(wdg); KisMetaData::FilterRegistryModel frm; wdgUi.metaDataFilters->setModel(&frm); QString filterConfig = KisConfig().exportConfiguration("JPEG"); KisPropertiesConfiguration cfg; cfg.fromXML(filterConfig); wdgUi.progressive->setChecked(cfg.getBool("progressive", false)); wdgUi.qualityLevel->setValue(cfg.getInt("quality", 80)); wdgUi.qualityLevel->setRange(0, 100, 0); wdgUi.qualityLevel->setSuffix("%"); wdgUi.optimize->setChecked(cfg.getBool("optimize", true)); wdgUi.smoothLevel->setValue(cfg.getInt("smoothing", 0)); wdgUi.smoothLevel->setRange(0, 100, 0); wdgUi.smoothLevel->setSuffix("%"); wdgUi.baseLineJPEG->setChecked(cfg.getBool("baseline", true)); wdgUi.subsampling->setCurrentIndex(cfg.getInt("subsampling", 0)); wdgUi.exif->setChecked(cfg.getBool("exif", true)); wdgUi.iptc->setChecked(cfg.getBool("iptc", true)); wdgUi.xmp->setChecked(cfg.getBool("xmp", true)); const KoColorSpace* cs = image->projection()->colorSpace(); bool sRGB = cs->profile()->name().contains(QLatin1String("srgb"), Qt::CaseInsensitive); wdgUi.chkForceSRGB->setVisible(!sRGB); wdgUi.chkForceSRGB->setChecked(cfg.getBool("forceSRGB", false)); wdgUi.chkSaveProfile->setChecked(cfg.getBool("saveProfile", true)); QStringList rgb = cfg.getString("transparencyFillcolor", "255,255,255").split(','); - wdgUi.bnTransparencyFillColor->setDefaultColor(Qt::white); - wdgUi.bnTransparencyFillColor->setColor(QColor(rgb[0].toInt(), rgb[1].toInt(), rgb[2].toInt())); + KoColor background(KoColorSpaceRegistry::instance()->rgb8()); + background.fromQColor(Qt::white); + wdgUi.bnTransparencyFillColor->setDefaultColor(background); + background.fromQColor(QColor(rgb[0].toInt(), rgb[1].toInt(), rgb[2].toInt())); + wdgUi.bnTransparencyFillColor->setColor(background); frm.setEnabledFilters(cfg.getString("filters").split(',')); kdb->setMainWidget(wdg); QApplication::restoreOverrideCursor(); if (!getBatchMode()) { if (kdb->exec() == QDialog::Rejected) { delete kdb; return KisImportExportFilter::UserCancelled; } } KisJPEGOptions options; options.progressive = wdgUi.progressive->isChecked(); cfg.setProperty("progressive", options.progressive); options.quality = (int)wdgUi.qualityLevel->value(); cfg.setProperty("quality", options.quality); options.forceSRGB = wdgUi.chkForceSRGB->isChecked(); cfg.setProperty("forceSRGB", options.forceSRGB); options.saveProfile = wdgUi.chkSaveProfile->isChecked(); cfg.setProperty("saveProfile", options.saveProfile); // Advanced options.optimize = wdgUi.optimize->isChecked(); cfg.setProperty("optimize", options.optimize); options.smooth = (int)wdgUi.smoothLevel->value(); cfg.setProperty("smoothing", options.smooth); options.baseLineJPEG = wdgUi.baseLineJPEG->isChecked(); cfg.setProperty("baseline", options.baseLineJPEG); options.subsampling = wdgUi.subsampling->currentIndex(); cfg.setProperty("subsampling", options.subsampling); // Jpeg options.exif = wdgUi.exif->isChecked(); cfg.setProperty("exif", options.exif); options.iptc = wdgUi.iptc->isChecked(); cfg.setProperty("iptc", options.iptc); options.xmp = wdgUi.xmp->isChecked(); cfg.setProperty("xmp", options.xmp); - QColor c = wdgUi.bnTransparencyFillColor->color(); + QColor c = wdgUi.bnTransparencyFillColor->color().toQColor(); options.transparencyFillColor = c; cfg.setProperty("transparencyFillcolor", QString("%1,%2,%3").arg(c.red()).arg(c.green()).arg(c.blue())); options.filters = frm.enabledFilters(); QString enabledFilters; Q_FOREACH (const KisMetaData::Filter* filter, options.filters) { enabledFilters = enabledFilters + filter->id() + ','; } cfg.setProperty("filters", enabledFilters); KisConfig().setExportConfiguration("JPEG", cfg); delete kdb; // XXX: Add dialog about flattening layers here QString filename = outputFile(); if (filename.isEmpty()) return KisImportExportFilter::FileNotFound; // the image must be locked at the higher levels KIS_SAFE_ASSERT_RECOVER_NOOP(input->image()->locked()); KisPaintDeviceSP pd = new KisPaintDevice(*image->projection()); KisJPEGConverter kpc(input, getBatchMode()); KisPaintLayerSP l = new KisPaintLayer(image, "projection", OPACITY_OPAQUE_U8, pd); vKisAnnotationSP_it beginIt = image->beginAnnotations(); vKisAnnotationSP_it endIt = image->endAnnotations(); KisImageBuilder_Result res; KisExifInfoVisitor eIV; eIV.visit(image->rootLayer().data()); KisMetaData::Store* eI = 0; if (eIV.countPaintLayer() == 1) eI = eIV.exifInfo(); if (eI) { KisMetaData::Store* copy = new KisMetaData::Store(*eI); eI = copy; } if ((res = kpc.buildFile(filename, l, beginIt, endIt, options, eI)) == KisImageBuilder_RESULT_OK) { dbgFile << "success !"; delete eI; return KisImportExportFilter::OK; } delete eI; dbgFile << " Result =" << res; return KisImportExportFilter::InternalError; } #include diff --git a/plugins/impex/jpeg/kis_wdg_options_jpeg.ui b/plugins/impex/jpeg/kis_wdg_options_jpeg.ui index eb0dbbd183..c1596513af 100644 --- a/plugins/impex/jpeg/kis_wdg_options_jpeg.ui +++ b/plugins/impex/jpeg/kis_wdg_options_jpeg.ui @@ -1,368 +1,368 @@ WdgOptionsJPEG 0 0 - 537 + 545 390 0 Basic Progressive Force convert to sRGB 20 - + 0 0 0 0 <html><head/><body><p>These settings determine how much information is lost during compression. Low: small files, bad quality. High: big files, good quality.</p></body></html> 0 0 Compression: 0 0 Transparent pixel fill color: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 0 0 25 0 <html><head/><body><p>Background color to replace transparent pixels with.</p></body></html> Qt::Vertical 20 40 Save ICC Profile false Advanced quality 20 - + 0 0 60 20 0 0 Smooth: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 Subsampling: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 2x2, 1x1, 1x1 (smallest file) 2x1, 1x1, 1x1 1x2, 1x1, 1x1 1x1, 1x1, 1x1 (best quality) Force baseline JPEG true Optimize true Qt::Vertical 20 40 Metadata Formats: Exif true IPTC true XMP true Qt::Vertical 20 40 Filters: Qt::Vertical 505 16 - - KColorButton - QPushButton -
kcolorbutton.h
-
KisDoubleSliderSpinBox QWidget
kis_slider_spin_box.h
1
+ + KisColorButton + QPushButton +
kis_color_button.h
+
tabWidget progressive baseLineJPEG metaDataFilters exif iptc xmp
diff --git a/plugins/impex/png/kis_png_export.cc b/plugins/impex/png/kis_png_export.cc index 7edb7cdda6..0f3aaf0ef2 100644 --- a/plugins/impex/png/kis_png_export.cc +++ b/plugins/impex/png/kis_png_export.cc @@ -1,252 +1,256 @@ /* * Copyright (c) 2005 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kis_png_export.h" #include #include #include #include #include #include #include +#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_png_converter.h" #include K_PLUGIN_FACTORY_WITH_JSON(KisPNGExportFactory, "krita_png_export.json", registerPlugin();) KisPNGExport::KisPNGExport(QObject *parent, const QVariantList &) : KisImportExportFilter(parent) { } KisPNGExport::~KisPNGExport() { } bool hasVisibleWidgets() { QWidgetList wl = QApplication::allWidgets(); Q_FOREACH (QWidget* w, wl) { if (w->isVisible() && strcmp(w->metaObject()->className(), "QDesktopWidget")) { dbgFile << "Widget " << w << " " << w->objectName() << " " << w->metaObject()->className() << " is visible"; return true; } } return false; } KisImportExportFilter::ConversionStatus KisPNGExport::convert(const QByteArray& from, const QByteArray& to) { dbgFile << "Png export! From:" << from << ", To:" << to << ""; KisDocument *input = inputDocument(); QString filename = outputFile(); if (!input) return KisImportExportFilter::NoDocumentCreated; if (filename.isEmpty()) return KisImportExportFilter::FileNotFound; if (from != "application/x-krita") return KisImportExportFilter::NotImplemented; KoDialog* kdb = new KoDialog(0); kdb->setCaption(i18n("PNG Export Options")); kdb->setModal(false); kdb->setButtons(KoDialog::Ok | KoDialog::Cancel); KisImageWSP image = input->image(); // the image must be locked at the higher levels KIS_SAFE_ASSERT_RECOVER_NOOP(image->locked()); KisPaintDeviceSP pd; pd = new KisPaintDevice(*image->projection()); KisPaintLayerSP l = new KisPaintLayer(image, "projection", OPACITY_OPAQUE_U8, pd); if (!KisPNGConverter::isColorSpaceSupported(pd->colorSpace())) { if (!getBatchMode()) { QMessageBox::critical(0, i18nc("@title:window", "Krita PNG Export"), i18n("You can only save grayscale and RGB images to PNG. Convert your image before exporting to PNG.")); } return KisImportExportFilter::UsageError; } KisSequentialConstIterator it(l->paintDevice(), image->bounds()); const KoColorSpace* cs = l->paintDevice()->colorSpace(); KisPNGOptions options; bool isThereAlpha = false; do { if (cs->opacityU8(it.oldRawData()) != OPACITY_OPAQUE_U8) { isThereAlpha = true; break; } } while (it.nextPixel()); if (!qApp->applicationName().toLower().contains("test")) { bool sRGB = (cs->profile()->name().contains(QLatin1String("srgb"), Qt::CaseInsensitive) && !cs->profile()->name().contains(QLatin1String("g10"))); KisWdgOptionsPNG* wdg = new KisWdgOptionsPNG(kdb); QString filterConfig = KisConfig().exportConfiguration("PNG"); KisPropertiesConfiguration cfg; cfg.fromXML(filterConfig); wdg->alpha->setChecked(cfg.getBool("alpha", isThereAlpha)); if (cs->colorModelId() == RGBAColorModelID) { wdg->tryToSaveAsIndexed->setVisible(true); if (wdg->alpha->isChecked()) { wdg->tryToSaveAsIndexed->setChecked(false); } else { wdg->tryToSaveAsIndexed->setChecked(cfg.getBool("indexed", false)); } } else { wdg->tryToSaveAsIndexed->setVisible(false); } wdg->interlacing->setChecked(cfg.getBool("interlaced", false)); wdg->compressionLevel->setValue(cfg.getInt("compression", 9)); wdg->compressionLevel->setRange(1, 9 , 0); wdg->alpha->setEnabled(isThereAlpha); wdg->tryToSaveAsIndexed->setVisible(!isThereAlpha); wdg->bnTransparencyFillColor->setEnabled(!wdg->alpha->isChecked()); //This used to be 'cfg.getBool("saveSRGBProfile", true)' but firefox and ColorD are incredibly awkward about sRGB management //on Linux devices, as indicated by the same distorted colours with using the sRGB chunk, meaning it's unrelated to the profile. //We can somewhat assume sRGB is the default color space for the web, but it's still a darn pity we cannot rely on firefox and colord //to manage sRGB-marked images properly. wdg->chkSRGB->setEnabled(sRGB); wdg->chkSRGB->setChecked(cfg.getBool("saveSRGBProfile", false)); wdg->chkForceSRGB->setEnabled(!sRGB); wdg->chkForceSRGB->setChecked(cfg.getBool("forceSRGB", false)); QStringList rgb = cfg.getString("transparencyFillcolor", "0,0,0").split(','); - wdg->bnTransparencyFillColor->setDefaultColor(Qt::white); - wdg->bnTransparencyFillColor->setColor(QColor(rgb[0].toInt(), rgb[1].toInt(), rgb[2].toInt())); + KoColor background(KoColorSpaceRegistry::instance()->rgb8()); + background.fromQColor(Qt::white); + wdg->bnTransparencyFillColor->setDefaultColor(background); + background.fromQColor(QColor(rgb[0].toInt(), rgb[1].toInt(), rgb[2].toInt())); + wdg->bnTransparencyFillColor->setColor(background); kdb->setMainWidget(wdg); QApplication::restoreOverrideCursor(); if (hasVisibleWidgets()) { if (!getBatchMode()) { if (kdb->exec() == QDialog::Rejected) { return KisImportExportFilter::UserCancelled; } } } bool alpha = wdg->alpha->isChecked(); bool interlace = wdg->interlacing->isChecked(); int compression = (int)wdg->compressionLevel->value(); bool tryToSaveAsIndexed = wdg->tryToSaveAsIndexed->isChecked(); - QColor c = wdg->bnTransparencyFillColor->color(); + QColor c = wdg->bnTransparencyFillColor->color().toQColor(); bool saveSRGB = wdg->chkSRGB->isChecked(); bool forceSRGB = wdg->chkForceSRGB->isChecked(); cfg.setProperty("alpha", alpha); cfg.setProperty("indexed", tryToSaveAsIndexed); cfg.setProperty("compression", compression); cfg.setProperty("interlaced", interlace); cfg.setProperty("transparencyFillcolor", QString("%1,%2,%3").arg(c.red()).arg(c.green()).arg(c.blue())); cfg.setProperty("saveSRGBProfile", saveSRGB); cfg.setProperty("forceSRGB", forceSRGB); KisConfig().setExportConfiguration("PNG", cfg); options.alpha = alpha; options.interlace = interlace; options.compression = compression; options.tryToSaveAsIndexed = tryToSaveAsIndexed; options.transparencyFillColor = c; options.saveSRGBProfile = saveSRGB; options.forceSRGB = forceSRGB; } else { options.alpha = true; options.interlace = false; options.compression = 9; options.tryToSaveAsIndexed = false; options.transparencyFillColor = QColor(0,0,0); options.saveSRGBProfile = false; options.forceSRGB = false; } delete kdb; KisPNGConverter kpc(input); vKisAnnotationSP_it beginIt = image->beginAnnotations(); vKisAnnotationSP_it endIt = image->endAnnotations(); KisImageBuilder_Result res; KisExifInfoVisitor eIV; eIV.visit(image->rootLayer().data()); KisMetaData::Store* eI = 0; if (eIV.countPaintLayer() == 1) eI = eIV.exifInfo(); if (eI) { KisMetaData::Store* copy = new KisMetaData::Store(*eI); eI = copy; } if ((res = kpc.buildFile(filename, image->bounds(), image->xRes(), image->yRes(), l->paintDevice(), beginIt, endIt, options, eI)) == KisImageBuilder_RESULT_OK) { dbgFile << "success !"; delete eI; return KisImportExportFilter::OK; } delete eI; dbgFile << " Result =" << res; return KisImportExportFilter::InternalError; } #include "kis_png_export.moc" void KisWdgOptionsPNG::on_alpha_toggled(bool checked) { bnTransparencyFillColor->setEnabled(!checked); } diff --git a/plugins/impex/png/kis_wdg_options_png.ui b/plugins/impex/png/kis_wdg_options_png.ui index 3e4eb99bc6..405c28ee77 100644 --- a/plugins/impex/png/kis_wdg_options_png.ui +++ b/plugins/impex/png/kis_wdg_options_png.ui @@ -1,215 +1,215 @@ KisWdgOptionsPNG 0 0 - 476 + 546 243 PNG Options 0 0 0 0 0 6 <html><head/><body><p><span style=" font-weight:600;">PNG</span> files have <span style=" font-style:italic;">two</span> options to save <span style=" font-weight:600;">sRGB</span> information: as a tag or as an explicit profile. For use with in websites, <span style=" font-style:italic;">disable</span> this option. For interchange with other applications, <span style=" font-style:italic;">enable</span> this option.</p></body></html> Embed sRGB profile Force convert to sRGB - + Note: the compression level does not change the quality of the result <p>Adjust the compression time. Better compression takes longer. <br>Note: the compression level does not change the quality of the result.</p> Note: the compression level does not change the quality of the result <p>Adjust the compression time. Better compression takes longer. <br>Note: the compression level does not change the quality of the result.</p> Compression (Lossless): Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing <p>Adjust the compression time. Better compression takes longer. <br>Note: the compression level does not change the quality of the result.</p> Small File Size Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter <p>Adjust the compression time. Better compression takes longer. <br>Note: the compression level does not change the quality of the result.</p> Large file size Disable to get smaller files if your image has no transparency <p>The Portable Network Graphics (PNG) file format allows transparency in your image to be stored by saving an alpha channel. You can uncheck the box if you are not using transparency and you want to make the resulting file smaller .<br>Always saving the alpha channel is recommended.</p> Store alpha channel (transparency) true Use interlacing when publishing on the Internet. <p>Interlacing is useful if you intend to publish your image on the Internet.<br> Enabling interlacing will cause the image to be displayed by the browser even while downloading.</p> Interlacing Indexed PNG images are smaller. If you enabled this option, your image will be analyzed to see whether it is possible to save as an indexed PNG. Save as indexed PNG, if possible true Transparent color: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + 0 0 50 0 <html><head/><body><p>Background color to replace transparent pixels with.</p></body></html> Qt::Vertical QSizePolicy::Expanding 414 16 KisDoubleSliderSpinBox QWidget
kis_slider_spin_box.h
1
- KColorButton + KisColorButton QPushButton -
kcolorbutton.h
+
kis_color_button.h