1 /****************************************************************************
2 * MeshLab o o *
3 * A versatile mesh processing toolbox o o *
4 * _ O _ *
5 * Copyright(C) 2005-2008 \/)\/ *
6 * Visual Computing Lab /\/| *
7 * ISTI - Italian National Research Council | *
8 * \ *
9 * All rights reserved. *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
20 * for more details. *
21 * *
22 ****************************************************************************/
23
24 #include "rfx_colorbox.h"
25
26 const QString RfxColorBox::_BASE_RGB_BOX_STYLE = QString("margin-left: 25px;border-top-left-radius: 5px;border-bottom-left-radius: 5px;border-left: 1px solid black;border-top: 1px solid black;border-bottom: 1px solid black;padding: 2px;");
27 const QString RfxColorBox::_BASE_RGBA_BOX_STYLE = QString("margin-left: 25px;margin-right: 25px;border: 1px solid black;border-radius: 5px;padding: 2px;");
28
29 /* Constructor
30 @param w the width of the widget.
31 @param h the height of the widget.
32 @param first the start color of the box.
33 @param parent the parent widget. Default to 0.
34 */
RfxColorBox(const int & w,const int & h,const QColor & first,QWidget * parent)35 RfxColorBox::RfxColorBox(const int& w, const int& h, const QColor& first, QWidget* parent)
36 : QWidget(parent)
37 {
38 int r,g,b,a;
39 r = first.red();
40 g = first.green();
41 b = first.blue();
42 a = first.alpha();
43
44 this->_rgbaBox = new QPushButton(this);
45 this->_rgbaBox->setObjectName("rgbaBox");
46 this->_rgbaBox->setFixedSize (w, h);
47 this->_rgbaBox->setStyleSheet(RfxColorBox::_BASE_RGBA_BOX_STYLE + QString("background-color: rgba(%1,%2,%3,%4);").arg(r).arg(g).arg(b).arg(a));
48
49 this->_rgbBox = new QFrame(this);
50 this->_rgbBox->setObjectName("rgbBox");
51 this->_rgbBox->setFixedSize ((w/2), h);
52 this->_rgbBox->setStyleSheet(RfxColorBox::_BASE_RGB_BOX_STYLE + QString("background-color: rgb(%1,%2,%3);").arg(r).arg(g).arg(b));
53
54 this->_scacchiera = new QFrame(this);
55 this->_scacchiera->setObjectName("scacchiera");
56 this->_scacchiera->setStyleSheet(RfxColorBox::_BASE_RGBA_BOX_STYLE + QString("background-image: url(:/images/scacchiera.png);"));
57 this->_scacchiera->setFixedSize (w, h);
58
59
60 this->_rgbBox->raise();
61 this->_rgbaBox->raise();
62
63 QVBoxLayout *verticalLayout = new QVBoxLayout();
64
65
66 /* the sliders and text boxes */
67 this->_redS = new QSlider();
68 initSlider(_redS, r);
69 this->_redT = new QLineEdit(QString().setNum(r));
70 initTextBox(this->_redT);
71 connect(this->_redT, SIGNAL(editingFinished()), this, SLOT(setR()));
72
73 this->_greenS = new QSlider();
74 initSlider(_greenS, g);
75 this->_greenT = new QLineEdit(QString().setNum(g));
76 initTextBox(this->_greenT);
77 connect(this->_greenT, SIGNAL(editingFinished()), this, SLOT(setG()));
78
79 this->_blueS = new QSlider();
80 initSlider(_blueS, b);
81 this->_blueT = new QLineEdit(QString().setNum(b));
82 initTextBox(this->_blueT);
83 connect(this->_blueT, SIGNAL(editingFinished()), this, SLOT(setB()));
84
85 this->_alphaS = new QSlider();
86 initSlider(_alphaS, a);
87 this->_alphaT = new QLineEdit(QString().setNum(a));
88 initTextBox(this->_alphaT);
89 connect(this->_alphaT, SIGNAL(editingFinished()), this, SLOT(setA()));
90
91 connectSliders();
92
93 QHBoxLayout *redLayout = new QHBoxLayout();
94 QWidget* redBox = new QWidget();
95 redBox->setFixedSize (10, 10);
96 redBox->setStyleSheet("background-color: rgb(255,0,0);");
97 redLayout->addWidget(redBox);
98 redLayout->addWidget(this->_redS);
99 redLayout->addWidget(this->_redT);
100 redLayout->setSpacing(3);
101
102 QHBoxLayout *greenLayout = new QHBoxLayout();
103 QWidget* greenBox = new QWidget();
104 greenBox->setFixedSize (10, 10);
105 greenBox->setStyleSheet("background-color: rgb(0,255,0);");
106 greenLayout->addWidget(greenBox);
107 greenLayout->addWidget(this->_greenS);
108 greenLayout->addWidget(this->_greenT);
109 greenLayout->setSpacing(3);
110
111 QHBoxLayout *blueLayout = new QHBoxLayout();
112 QWidget* blueBox = new QWidget();
113 blueBox->setFixedSize (10, 10);
114 blueBox->setStyleSheet("background-color: rgb(0,0,255);");
115 blueLayout->addWidget(blueBox);
116 blueLayout->addWidget(this->_blueS);
117 blueLayout->addWidget(this->_blueT);
118 blueLayout->setSpacing(3);
119
120 QHBoxLayout *alphaLayout = new QHBoxLayout();
121 QWidget* alphaBox = new QWidget();
122 alphaBox->setFixedSize (10, 10);
123 alphaBox->setStyleSheet("background-color: rgb(100,100,100);");
124 alphaLayout->addWidget(alphaBox);
125 alphaLayout->addWidget(this->_alphaS);
126 alphaLayout->addWidget(this->_alphaT);
127 alphaLayout->setSpacing(3);
128
129 QGridLayout *colorDialogLayout = new QGridLayout();
130 colorDialogLayout->setVerticalSpacing(0);
131 colorDialogLayout->setHorizontalSpacing(0);
132 colorDialogLayout->setMargin(0);
133 colorDialogLayout->setSpacing(0);
134
135 verticalLayout->addLayout(redLayout);
136 verticalLayout->addLayout(greenLayout);
137 verticalLayout->addLayout(blueLayout);
138 verticalLayout->addLayout(alphaLayout);
139
140 connect(this->_rgbaBox, SIGNAL(clicked()), this, SLOT(setBoxColorFromDialog()));
141
142 QGridLayout *layout = new QGridLayout();
143 layout->addWidget(_scacchiera, 0, 0);
144 layout->addWidget(_rgbBox, 0, 0);
145 layout->addWidget(_rgbaBox, 0, 0);
146 this->_rgbBox->raise();
147 this->_rgbaBox->raise();
148
149 colorDialogLayout->addLayout(verticalLayout, 0,0);
150 colorDialogLayout->addLayout(layout, 0,1);
151
152 setLayout(colorDialogLayout);
153 }
154
~RfxColorBox()155 RfxColorBox::~RfxColorBox()
156 {
157 if(this->_rgbaBox)
158 delete _rgbaBox;
159 if(this->_rgbBox)
160 delete _rgbBox;
161 if(this->_scacchiera)
162 delete _scacchiera;
163
164 if(this->_redS)
165 delete _redS;
166 if(this->_greenS)
167 delete _greenS;
168 if(this->_blueS)
169 delete _blueS;
170 if(this->_alphaS)
171 delete _alphaS;
172
173 if(this->_redT)
174 delete _redT;
175 if(this->_greenT)
176 delete _greenT;
177 if(this->_blueT)
178 delete _blueT;
179 if(this->_alphaT)
180 delete _alphaT;
181 }
182
183 /* Receives button click and shows a default system dialog for color selection.
184 Once the color has been selected sets it as the color of the widget and emits the color changes signals.
185 */
setBoxColorFromDialog()186 void RfxColorBox::setBoxColorFromDialog(){
187
188 QColor c = QColorDialog::getColor(QColor(_redS->value(), _greenS->value(), _blueS->value()));//(*(this->_color));
189 if(c.isValid()){
190 disconnectSliders();
191 this->_redS->setValue(c.red());
192 this->_redS->setToolTip(QString().setNum(c.red()));
193 this->_redT->setText(QString().setNum(c.red()));
194
195 this->_greenS->setValue(c.green());
196 this->_greenS->setToolTip(QString().setNum(c.green()));
197 this->_greenT->setText(QString().setNum(c.green()));
198
199 this->_blueS->setValue(c.blue());
200 this->_blueS->setToolTip(QString().setNum(c.blue()));
201 this->_blueT->setText(QString().setNum(c.blue()));
202
203 emit colorChanged();
204 int r, g, b, a;
205 r = c.red();
206 g = c.green();
207 b = c.blue();
208 a = this->_alphaS->value();
209
210 int* vals[4] = {&r, &g, &b, &a};
211 this->_rgbaBox->setStyleSheet(getNewRGBAStylesheet(this->_rgbaBox->styleSheet(), CHANNEL_ALL, vals));
212 this->_rgbBox->setStyleSheet(getNewRGBStylesheet(this->_rgbBox->styleSheet(), CHANNEL_ALL, vals));
213 connectSliders();
214 }
215 }
216
217 /* Sets just the red channel.
218 @param r The new red value.
219 */
setR(int r)220 void RfxColorBox::setR(int r){
221 this->_redS->setToolTip(QString().setNum(r));
222 this->_redT->setText(QString().setNum(r));
223 emit colorChanged();
224 int* vals[1] = {&r};
225 this->_rgbaBox->setStyleSheet(getNewRGBAStylesheet(this->_rgbaBox->styleSheet(), CHANNEL_R, vals));
226 this->_rgbBox->setStyleSheet(getNewRGBStylesheet(this->_rgbBox->styleSheet(), CHANNEL_R, vals));
227 }
228
229 /* Sets just the green channel.
230 @param g The new green value.
231 */
setG(int g)232 void RfxColorBox::setG(int g){
233 this->_greenS->setToolTip(QString().setNum(g));
234 this->_greenT->setText(QString().setNum(g));
235 emit colorChanged();
236 int* vals[1] = {&g};
237 this->_rgbaBox->setStyleSheet(getNewRGBAStylesheet(this->_rgbaBox->styleSheet(), CHANNEL_G, vals));
238 this->_rgbBox->setStyleSheet(getNewRGBStylesheet(this->_rgbBox->styleSheet(), CHANNEL_G, vals));
239 }
240
241 /* Sets just the blue channel.
242 @param b The new blue value.
243 */
setB(int b)244 void RfxColorBox::setB(int b){
245 this->_blueS->setToolTip(QString().setNum(b));
246 this->_blueT->setText(QString().setNum(b));
247 emit colorChanged();
248 int* vals[1] = {&b};
249 this->_rgbaBox->setStyleSheet(getNewRGBAStylesheet(this->_rgbaBox->styleSheet(), CHANNEL_B, vals));
250 this->_rgbBox->setStyleSheet(getNewRGBStylesheet(this->_rgbBox->styleSheet(), CHANNEL_B, vals));
251 }
252
253 /* Sets just the alpha channel.
254 @param a The new alpha value.
255 */
setA(int a)256 void RfxColorBox::setA(int a){
257 this->_alphaS->setToolTip(QString().setNum(a));
258 this->_alphaT->setText(QString().setNum(a));
259 emit colorChanged();
260 int* vals[1] = {&a};
261 this->_rgbaBox->setStyleSheet(getNewRGBAStylesheet(this->_rgbaBox->styleSheet(), CHANNEL_A, vals));
262 }
263
264 /* Sets just the red channel.*/
setR()265 void RfxColorBox::setR(){
266 bool res = false;
267 int val = this->_redT->text().toInt(&res);
268 if (!res){
269 this->_redT->setText(QString().setNum(this->_redS->value()));
270 return;
271 }
272
273 if (val > 255)
274 this->_redS->setValue(255);
275 else if (val < 0)
276 this->_redS->setValue(0);
277 else
278 this->_redS->setValue(val);
279 }
280
281 /* Sets just the green channel.*/
setG()282 void RfxColorBox::setG(){
283 bool res = false;
284 int val = this->_greenT->text().toInt(&res);
285 if (!res){
286 this->_redT->setText(QString().setNum(this->_greenS->value()));
287 return;
288 }
289
290 if (val > 255)
291 this->_greenS->setValue(255);
292 else if (val < 0)
293 this->_greenS->setValue(0);
294 else
295 this->_greenS->setValue(val);
296 }
297
298 /* Sets just the blue channel.*/
setB()299 void RfxColorBox::setB(){
300 bool res = false;
301 int val = this->_blueT->text().toInt(&res);
302 if (!res){
303 this->_blueT->setText(QString().setNum(this->_blueS->value()));
304 return;
305 }
306
307 if (val > 255)
308 this->_blueS->setValue(255);
309 else if (val < 0)
310 this->_blueS->setValue(0);
311 else
312 this->_blueS->setValue(val);
313 }
314
315 /* Sets just the alpha channel.*/
setA()316 void RfxColorBox::setA(){
317 bool res = false;
318 int val = this->_alphaT->text().toInt(&res);
319 if (!res){
320 this->_alphaT->setText(QString().setNum(this->_alphaS->value()));
321 return;
322 }
323
324 if (val > 255)
325 this->_alphaS->setValue(255);
326 else if (val < 0)
327 this->_alphaS->setValue(0);
328 else
329 this->_alphaS->setValue(val);
330 }
331
332 /*
333 Returns a string rapresenting a new stylesheet(with alpha channel)
334 @param stykeSheet the old stylesheet.
335 @param channels The channel that have to be modified.
336 @param vals the new values
337 @return the new stylesheet
338
339 */
getNewRGBAStylesheet(const QString & styleSheet,RfxColorBox::Channels channels,int * vals[])340 QString RfxColorBox::getNewRGBAStylesheet(const QString& styleSheet, RfxColorBox::Channels channels, int* vals[]){
341 int openBracket = styleSheet.indexOf("(");
342 int closedBracket = styleSheet.indexOf(")");
343 QStringList list = styleSheet.mid(openBracket + 1, closedBracket - openBracket).split(",");
344 QString newStyleSheet = RfxColorBox::_BASE_RGBA_BOX_STYLE + QString("background-color: rgba(");
345
346 switch(channels){
347 case CHANNEL_R :
348 newStyleSheet = newStyleSheet+QString("%1,").arg(*vals[0])+list[1]+','+list[2]+','+list[3]+';';
349 break;
350
351 case CHANNEL_G:
352 newStyleSheet = newStyleSheet+list[0]+','+QString("%1,").arg(*vals[0])+list[2]+','+list[3]+';';
353 break;
354
355 case CHANNEL_B:
356 newStyleSheet = newStyleSheet+list[0]+','+list[1]+','+QString("%1,").arg(*vals[0])+list[3]+';';
357 break;
358
359 case CHANNEL_A:
360 newStyleSheet = newStyleSheet+list[0]+','+list[1]+','+list[2]+','+QString("%1);").arg(*vals[0]);
361 break;
362
363 case CHANNEL_ALL:
364 newStyleSheet = newStyleSheet+QString("%1,").arg(*vals[0])+QString("%1,").arg(*vals[1])+QString("%1,").arg(*vals[2])+QString("%1);").arg(*vals[3]);
365 break;
366 }
367
368 return newStyleSheet;
369 }
370
371 /*
372 Returns a string rapresenting a new stylesheet(without alpha channel)
373 @param stykeSheet the old stylesheet.
374 @param channels The channel that have to be modified.
375 @param vals the new values
376 @return the new stylesheet
377
378 */
getNewRGBStylesheet(const QString & styleSheet,RfxColorBox::Channels channels,int * vals[])379 QString RfxColorBox::getNewRGBStylesheet(const QString& styleSheet, RfxColorBox::Channels channels, int* vals[]){
380 int openBracket = styleSheet.indexOf("(");
381 int closedBracket = styleSheet.indexOf(")");
382 QStringList list = styleSheet.mid(openBracket + 1, closedBracket - openBracket).split(",");
383 QString newStyleSheet = RfxColorBox::_BASE_RGB_BOX_STYLE + QString("background-color: rgb(");
384
385 switch(channels){
386 case CHANNEL_R :
387 newStyleSheet = newStyleSheet+QString("%1,").arg(*vals[0])+list[1]+','+list[2]+';';
388 break;
389
390 case CHANNEL_G:
391 newStyleSheet = newStyleSheet+list[0]+','+QString("%1,").arg(*vals[0])+list[2]+';';
392 break;
393
394 case CHANNEL_B:
395 newStyleSheet = newStyleSheet+list[0]+','+list[1]+','+QString("%1);").arg(*vals[0]);
396 break;
397
398 case CHANNEL_A:
399 break;
400
401 case CHANNEL_ALL:
402 newStyleSheet = newStyleSheet+QString("%1,").arg(*vals[0])+QString("%1,").arg(*vals[1])+QString("%1);").arg(*vals[2]);
403 break;
404 }
405 return newStyleSheet;
406 }
407
408
409 /* Initialize a slider
410 @param slider the slider to initialize
411 @param value the initial value
412 */
initSlider(QSlider * slider,int value)413 void RfxColorBox::initSlider(QSlider* slider, int value){
414 slider->setTickPosition(QSlider::NoTicks);
415 slider->setOrientation(Qt::Horizontal);
416 slider->setMaximumSize(100, 15);
417
418 slider->setTickInterval(1);
419 slider->setRange(0,255);
420 slider->setValue(value);
421 slider->setToolTip(QString().setNum(value));
422 }
423
424 /* Initialize a text box.
425 @param box the text box to initialize
426 */
initTextBox(QLineEdit * box)427 void RfxColorBox::initTextBox(QLineEdit* box){
428 box->setAlignment(Qt::AlignRight);
429 box->setMaximumWidth(75);
430 box->setMaximumHeight(15);
431 box->setFont(QFont("verdana", 7));
432 }
433
434 /* Connects all the slider to the color box. */
connectSliders()435 void RfxColorBox::connectSliders(){
436 connect(this->_redS, SIGNAL(valueChanged(int)), this, SLOT(setR(int)));
437 connect(this->_greenS, SIGNAL(valueChanged(int)), this, SLOT(setG(int)));
438 connect(this->_blueS, SIGNAL(valueChanged(int)), this, SLOT(setB(int)));
439 connect(this->_alphaS, SIGNAL(valueChanged(int)), this, SLOT(setA(int)));
440 }
441
442 /* Disconnects all the slider to the color box. */
disconnectSliders()443 void RfxColorBox::disconnectSliders(){
444 disconnect(this->_redS, SIGNAL(valueChanged(int)), this, SLOT(setR(int)));
445 disconnect(this->_greenS, SIGNAL(valueChanged(int)), this, SLOT(setG(int)));
446 disconnect(this->_blueS, SIGNAL(valueChanged(int)), this, SLOT(setB(int)));
447 disconnect(this->_alphaS, SIGNAL(valueChanged(int)), this, SLOT(setA(int)));
448 }