[KLF Backend][KLF Tools][KLF Home]
KLatexFormula Project
klfcolorchooser.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * file klfcolorchooser.cpp
3  * This file is part of the KLatexFormula Project.
4  * Copyright (C) 2011 by Philippe Faist
5  * philippe.faist at bluewin.ch
6  * *
7  * This program is free software; you can redistribute it and/or modify *
8  * it under the terms of the GNU General Public License as published by *
9  * the Free Software Foundation; either version 2 of the License, or *
10  * (at your option) any later version. *
11  * *
12  * This program is distributed in the hope that it will be useful, *
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15  * GNU General Public License for more details. *
16  * *
17  * You should have received a copy of the GNU General Public License *
18  * along with this program; if not, write to the *
19  * Free Software Foundation, Inc., *
20  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
21  ***************************************************************************/
22 /* $Id$ */
23 
24 #include <stdio.h>
25 
26 #include <QAction>
27 #include <QMenu>
28 #include <QDebug>
29 #include <QColorDialog>
30 #include <QPaintEvent>
31 #include <QStyle>
32 #include <QStylePainter>
33 #include <QStyleFactory>
34 #include <QStyleOptionButton>
35 #include <QRegExp>
36 
37 #include <klfdefs.h>
38 #include "klfflowlayout.h"
39 #include "klfguiutil.h"
40 #include "klfrelativefont.h"
41 #include "klfcolorchooser.h"
42 #include "klfcolorchooser_p.h"
43 
44 #include <ui_klfcolorchoosewidget.h>
45 #include <ui_klfcolordialog.h>
46 
47 
48 
49 // -------------------------------------------------------------------
50 
51 
52 KLFColorDialog::KLFColorDialog(QWidget *parent) : QDialog(parent)
53 {
54  u = new Ui::KLFColorDialog;
55  u->setupUi(this);
56  setObjectName("KLFColorDialog");
57 }
59 {
60  delete u;
61 }
62 
64 {
65  return u->mColorChooseWidget;
66 }
67 
68 QColor KLFColorDialog::getColor(QColor startwith, bool alphaenabled, QWidget *parent)
69 {
70  KLFColorDialog dlg(parent);
71  dlg.u->mColorChooseWidget->setAlphaEnabled(alphaenabled);
72  dlg.u->mColorChooseWidget->setColor(startwith);
73  int r = dlg.exec();
74  if ( r != QDialog::Accepted )
75  return QColor();
76  QColor color = dlg.u->mColorChooseWidget->color();
77  return color;
78 }
79 
81 {
82  return u->mColorChooseWidget->color();
83 }
84 void KLFColorDialog::setColor(const QColor& color)
85 {
86  u->mColorChooseWidget->setColor(color);
87 }
88 void KLFColorDialog::slotAccepted()
89 {
91 }
92 
93 // -------------------------------------------------------------------
94 
95 KLFColorClickSquare::KLFColorClickSquare(QColor color, int size, bool removable, QWidget *parent)
96  : QWidget(parent), _color(color), _removable(removable)
97 {
98  initwidget();
99  setSqSize(size);
100 }
102  : QWidget(parent), _color(Qt::white), _removable(false)
103 {
104  initwidget();
105  setSqSize(16);
106 }
107 void KLFColorClickSquare::initwidget()
108 {
109  setFocusPolicy(Qt::StrongFocus);
110  setContextMenuPolicy(Qt::DefaultContextMenu);
111  // setAutoFillBackground(true);
112  // update();
113 }
114 
116 {
117  if (_size == sz)
118  return;
119 
120  _size = sz;
121  setFixedSize(_size, _size);
122 }
123 
125 {
126  _removable = removable;
127 }
128 
130 {
132  Q_UNUSED(event) ;
133  klfDbg("event->rect="<<event->rect()) ;
134  {
135  QPainter p(this);
136  p.fillRect(0, 0, width(), height(), QBrush(_color));
137  }
138  if (hasFocus()) {
139  QStylePainter p(this);
140  QStyleOptionFocusRect option;
141  option.initFrom(this);
142  option.backgroundColor = QColor(0,0,0,0);
143  p.drawPrimitive(QStyle::PE_FrameFocusRect, option);
144  }
145 }
147 {
148  Q_UNUSED(event) ;
149 }
150 
152 {
153  activate();
154 }
156 {
157  if (kev->key() == Qt::Key_Space) {
158  activate();
159  }
160  return QWidget::keyPressEvent(kev);
161 }
163 {
164  if (_removable) {
165  QMenu *menu = new QMenu(this);
166  menu->addAction("Remove", this, SLOT(internalWantRemove()));
167  menu->popup(event->globalPos());
168  }
169 }
170 void KLFColorClickSquare::internalWantRemove()
171 {
172  emit wantRemove();
173  emit wantRemoveColor(_color);
174 }
175 
176 // -------------------------------------------------------------------
177 
179  : QWidget(parent), _img()
180 {
181  setPaneType("red+fix");
182  _color = Qt::black;
183 }
184 
186 {
187  return QSize((_colorcomponent == "fix") ? 16 : 50, (_colorcomponent_b == "fix") ? 16 : 50);
188 }
190 {
191  return QSize(16, 16);
192 }
193 
195 {
196  if (_color == newcolor)
197  return;
198 
199  _color = newcolor;
200  update();
201  emit colorChanged(_color);
202 }
204 {
205  static QStringList okvals =
206  QStringList() << "hue"<<"sat"<<"val"<<"red"<<"green"<<"blue"<<"alpha"<<"fix";
207 
208  QStringList strlist = panetype.split("+");
209  if (strlist.size() != 2) {
210  qWarning()<<KLF_FUNC_NAME<<": expected a pane-type string \"<pane1type>+<pane2type>\"!";
211  return;
212  }
213  _colorcomponent = strlist[0].toLower();
214  _colorcomponent_b = strlist[1].toLower();
215  if (!okvals.contains(_colorcomponent))
216  _colorcomponent = "fix";
217  if (!okvals.contains(_colorcomponent_b))
218  _colorcomponent_b = "fix";
219 
220  if (_colorcomponent == "fix" && _colorcomponent_b == "fix")
221  setFocusPolicy(Qt::NoFocus);
222  else
223  setFocusPolicy(Qt::WheelFocus);
224 }
226 {
227  QStylePainter p(this);
228  // background: a checker grid to distinguish transparency
229  p.fillRect(0,0,width(),height(), QBrush(QPixmap(":/pics/checker.png")));
230  // then prepare an image for our gradients
231  int x;
232  int y;
233  _img = QImage(width(), height(), QImage::Format_ARGB32);
234  double xfac = (double)valueAMax() / (_img.width()-1);
235  double yfac = (double)valueBMax() / (_img.height()-1);
236  for (x = 0; x < _img.width(); ++x) {
237  for (y = 0; y < _img.height(); ++y) {
238  _img.setPixel(x, _img.height()-y-1, colorFromValues(_color, (int)(xfac*x), (int)(yfac*y)).rgba());
239  }
240  }
241  p.drawImage(0, 0, _img);
242  // draw crosshairs
243  QColor hairscol = qGray(_color.rgb()) > 80 ? QColor(0,0,0,180) : QColor(255,255,255,180);
244  if ( _colorcomponent != "fix" ) {
245  p.setPen(QPen(hairscol, 1.f, Qt::DotLine));
246  x = (int)(valueA()/xfac);
247  if (x < 0) { x = 0; }
248  if (x >= width()) { x = width()-1; }
249  p.drawLine(x, 0, x, height());
250  }
251  if ( _colorcomponent_b != "fix" ) {
252  p.setPen(QPen(hairscol, 1.f, Qt::DotLine));
253  y = (int)(valueB()/yfac);
254  if (y < 0) { y = 0; }
255  if (y >= height()) { y = height()-1; }
256  p.drawLine(0, height()-y-1, width(), height()-y-1);
257  }
258  // draw a focus rectangle if we have focus
259  if (hasFocus()) {
260  QStyleOptionFocusRect option;
261  option.initFrom(this);
262  option.backgroundColor = QColor(0,0,0,0);
263  p.drawPrimitive(QStyle::PE_FrameFocusRect, option);
264  }
265 }
267 {
268  double xfac = (double)valueAMax() / (_img.width()-1);
269  double yfac = (double)valueBMax() / (_img.height()-1);
270  int x = e->pos().x();
271  int y = height() - e->pos().y() - 1;
272 
273  setColor(colorFromValues(_color, (int)(x*xfac), (int)(y*yfac)));
274 }
276 {
277  double xfac = (double)valueAMax() / (_img.width()-1);
278  double yfac = (double)valueBMax() / (_img.height()-1);
279  int x = e->pos().x();
280  int y = height() - e->pos().y() - 1;
281  if (x < 0) { x = 0; }
282  if (x >= width()) { x = width()-1; }
283  if (y < 0) { y = 0; } if (y >= height()) { y = height()-1; }
284 
285  setColor(colorFromValues(_color, (int)(x*xfac), (int)(y*yfac)));
286 }
288 {
289  double step = - 7.5 * e->delta() / 120;
290 
291  if (e->modifiers() == Qt::ShiftModifier)
292  step = step / 5.0;
293  if (e->modifiers() == Qt::ControlModifier)
294  step = step * 2.5;
295 
296  // isA: TRUE if we are modifying component A, if FALSE then modifying component B
297  bool isA = (e->orientation() == Qt::Horizontal);
298  if (isA && _colorcomponent=="fix")
299  isA = false;
300  if (!isA && _colorcomponent_b=="fix")
301  isA = true;
302  if (isA) {
303  // the first component
304  int x = (int)(valueA()+step);
305  if (x < 0) x = 0;
306  if (x > valueAMax()) x = valueAMax();
308  } else {
309  int x = (int)(valueB() - step);
310  if (x < 0) x = 0;
311  if (x > valueBMax()) x = valueBMax();
313  }
314  e->accept();
315 }
317 {
318  const int dir_step = 5;
319  double xstep = 0;
320  double ystep = 0;
321 
322  if (e->key() == Qt::Key_Left)
323  xstep -= dir_step;
324  if (e->key() == Qt::Key_Right)
325  xstep += dir_step;
326  if (e->key() == Qt::Key_Up)
327  ystep += dir_step;
328  if (e->key() == Qt::Key_Down)
329  ystep -= dir_step;
330  if (e->key() == Qt::Key_Home)
331  xstep = -10000;
332  if (e->key() == Qt::Key_End)
333  xstep = 10000;
334  if (e->key() == Qt::Key_PageUp)
335  ystep = 10000;
336  if (e->key() == Qt::Key_PageDown)
337  ystep = -10000;
338 
339  // if a component is set to 'fix', add the deltas to the other component...
340  if (_colorcomponent == "fix") {
341  ystep += xstep;
342  xstep = 0;
343  } else if (_colorcomponent_b == "fix") {
344  xstep += ystep;
345  ystep = 0;
346  }
347 
348  if (e->modifiers() == Qt::ShiftModifier) {
349  xstep = xstep / 5; ystep = ystep / 5;
350  }
351  if (e->modifiers() == Qt::ControlModifier) {
352  xstep = xstep * 2.5; ystep = ystep * 2.5;
353  }
354 
355  int x = (int)(valueA() + xstep);
356  int y = (int)(valueB() + ystep);
357  if (x < 0) x = 0;
358  if (x > valueAMax()) x = valueAMax();
359  if (y < 0) y = 0;
360  if (y > valueBMax()) y = valueBMax();
361 
363 }
364 
365 
366 // -------------------------------------------------------------------
367 
368 
369 KLFGridFlowLayout::KLFGridFlowLayout(int columns, QWidget *parent)
370  : QGridLayout(parent), _ncols(columns),
371  _currow(0), _curcol(0)
372 {
373  addItem(new QSpacerItem(1,1, QSizePolicy::Expanding, QSizePolicy::Fixed), 0, _ncols);
374 }
376 {
378  QGridLayout::addWidget(w, _currow, _curcol, align);
379  _curcol++;
380  if (_curcol >= _ncols) {
381  _curcol = 0;
382  _currow++;
383  }
384 }
386 {
387  int k;
388  for (k = 0; k < mGridFlowWidgets.size(); ++k) {
389  // because KLFColorClickSquare::wantRemoveColor() can call this by a chain of
390  // signal/slots; and we shouldn't delete an object inside one of its handlers
391  //delete mGridFlowWidgets[k];
392  mGridFlowWidgets[k]->deleteLater();
393  }
395  _currow = _curcol = 0;
396 }
397 
398 
399 // -------------------------------------------------------------------
400 
401 
403 {
404  return valueFromNewColor(color, _colorcomponent);
405 }
407 {
408  return valueFromNewColor(color, _colorcomponent_b);
409 }
411 {
412  int value = -1;
413  if (component == "hue") {
414  value = color.hue();
415  } else if (component == "sat") {
416  value = color.saturation();
417  } else if (component == "val") {
418  value = color.value();
419  } else if (component == "red") {
420  value = color.red();
421  } else if (component == "green") {
422  value = color.green();
423  } else if (component == "blue") {
424  value = color.blue();
425  } else if (component == "alpha") {
426  value = color.alpha();
427  } else if (component == "fix" || component.isEmpty()) {
428  value = -1;
429  } else {
430  qWarning("Unknown color component property : %s", component.toLocal8Bit().constData());
431  }
432  return value;
433 }
434 
436 {
437  if (component == "hue")
438  return 359;
439  else if (component == "sat" || component == "val" ||
440  component == "red" || component == "green" ||
441  component == "blue" || component == "alpha")
442  return 255;
443  else if (component == "fix" || component.isEmpty())
444  return -1;
445 
446  qWarning("Unknown color component property : %s", component.toLocal8Bit().constData());
447  return -1;
448 }
449 
451 {
452  QColor col = base;
453  /* printf("colorFromValues(%s/alpha=%d, %d, %d): My components:(%s+%s);\n", qPrintable(col.name()),
454  col.alpha(), a, b, qPrintable(_colorcomponent), qPrintable(_colorcomponent_b)); */
455  if (_colorcomponent == "hue") {
456  col.setHsv(a, col.saturation(), col.value());
457  col.setAlpha(base.alpha());
458  } else if (_colorcomponent == "sat") {
459  col.setHsv(col.hue(), a, col.value());
460  col.setAlpha(base.alpha());
461  } else if (_colorcomponent == "val") {
462  col.setHsv(col.hue(), col.saturation(), a);
463  col.setAlpha(base.alpha());
464  } else if (_colorcomponent == "red") {
465  col.setRgb(a, col.green(), col.blue());
466  col.setAlpha(base.alpha());
467  } else if (_colorcomponent == "green") {
468  col.setRgb(col.red(), a, col.blue());
469  col.setAlpha(base.alpha());
470  } else if (_colorcomponent == "blue") {
471  col.setRgb(col.red(), col.green(), a);
472  col.setAlpha(base.alpha());
473  } else if (_colorcomponent == "alpha") {
474  col.setAlpha(a);
475  } else if (_colorcomponent == "fix") {
476  // no change to col
477  } else {
478  qWarning("Unknown color component property : %s", _colorcomponent.toLocal8Bit().constData());
479  }
480  QColor base2 = col;
481  // printf("\tnew color is (%s/alpha=%d);\n", qPrintable(col.name()), col.alpha());
482  if ( ! _colorcomponent_b.isEmpty() && _colorcomponent_b != "fix" ) {
483  // printf("\twe have a second component\n");
484  if (_colorcomponent_b == "hue") {
485  col.setHsv(b, col.saturation(), col.value());
486  col.setAlpha(base2.alpha());
487  } else if (_colorcomponent_b == "sat") {
488  col.setHsv(col.hue(), b, col.value());
489  col.setAlpha(base2.alpha());
490  } else if (_colorcomponent_b == "val") {
491  col.setHsv(col.hue(), col.saturation(), b);
492  col.setAlpha(base2.alpha());
493  } else if (_colorcomponent_b == "red") {
494  col.setRgb(b, col.green(), col.blue());
495  col.setAlpha(base2.alpha());
496  } else if (_colorcomponent_b == "green") {
497  col.setRgb(col.red(), b, col.blue());
498  col.setAlpha(base2.alpha());
499  } else if (_colorcomponent_b == "blue") {
500  col.setRgb(col.red(), col.blue(), b);
501  col.setAlpha(base2.alpha());
502  } else if (_colorcomponent_b == "alpha") {
503  col.setAlpha(b);
504  } else {
505  qWarning("Unknown color component property : %s", _colorcomponent_b.toLocal8Bit().constData());
506  }
507  }
508  // printf("\tand color is finally %s/alpha=%d\n", qPrintable(col.name()), col.alpha());
509  return col;
510 }
512 {
513  QColor oldcolor = _color;
514  _color = colorFromValues(_color, a, b);
515  /* printf("My components:(%s+%s); New color is %s/alpha=%d\n", _colorcomponent.toLocal8Bit().constData(),
516  _colorcomponent_b.toLocal8Bit().constData(), _color.name().toLocal8Bit().constData(), _color.alpha()); */
517  if ( oldcolor != _color )
518  return true;
519  return false;
520 }
521 
522 
523 // -------------------------------------------------------------------
524 
525 
527  : QSpinBox(parent)
528 {
529  _color = Qt::black;
530 
531  setColorComponent("hue");
532  setColor(_color);
533 
534  connect(this, SIGNAL(valueChanged(int)), this, SLOT(internalChanged(int)));
535 
536  setValue(valueAFromNewColor(_color));
537 }
538 
540 {
541  _colorcomponent = comp.toLower();
542  setMinimum(0);
543  setMaximum(valueAMax());
544 }
545 
546 void KLFColorComponentSpinBox::internalChanged(int newvalue)
547 {
548  if ( refreshColorFromInternalValues(newvalue) )
549  emit colorChanged(_color);
550 }
551 
553 {
554  if (_color == color)
555  return;
556  int value = valueAFromNewColor(color);
557  /* printf("My components:(%s+%s); setColor(%s/alpha=%d); new value = %d\n",
558  _colorcomponent.toLocal8Bit().constData(), _colorcomponent_b.toLocal8Bit().constData(),
559  color.name().toLocal8Bit().constData(), color.alpha(), value); */
560  _color = color;
561  setValue(value); // will emit QSpinBox::valueChanged() --> internalChanged() --> colorChanged()
562 }
563 
564 
565 // -------------------------------------------------------------------
566 
567 
568 KLFColorList * KLFColorChooseWidget::_recentcolors = 0;
569 KLFColorList * KLFColorChooseWidget::_standardcolors = 0;
570 KLFColorList * KLFColorChooseWidget::_customcolors = 0;
571 
572 // static
574 {
576  _recentcolors->list = recentcolors;
577  _recentcolors->notifyListChanged();
578  _customcolors->list = customcolors;
579  _customcolors->notifyListChanged();
580 }
581 // static
583 {
585  return _recentcolors->list;
586 }
587 // static
589 {
591  return _customcolors->list;
592 }
593 
594 
596  : QWidget(parent)
597 {
598  u = new Ui::KLFColorChooseWidget;
599  u->setupUi(this);
600  setObjectName("KLFColorChooseWidget");
601 
602  _alphaenabled = true;
603 
605 
606  if (_standardcolors->list.size() == 0) {
607  // add a few standard colors.
608  QList<QRgb> rgbs;
609  // inspired from the "Forty Colors" Palette in KDE3 color dialog
610  rgbs << 0x000000 << 0x303030 << 0x585858 << 0x808080 << 0xa0a0a0 << 0xc3c3c3
611  << 0xdcdcdc << 0xffffff << 0x400000 << 0x800000 << 0xc00000 << 0xff0000
612  << 0xffc0c0 << 0x004000 << 0x008000 << 0x00c000 << 0x00ff00 << 0xc0ffc0
613  << 0x000040 << 0x000080 << 0x0000c0 << 0x0000ff << 0xc0c0ff << 0x404000
614  << 0x808000 << 0xc0c000 << 0xffff00 << 0xffffc0 << 0x004040 << 0x008080
615  << 0x00c0c0 << 0x00ffff << 0xc0ffff << 0x400040 << 0x800080 << 0xc000c0
616  << 0xff00ff << 0xffc0ff << 0xc05800 << 0xff8000 << 0xffa858 << 0xffdca8 ;
617  for (int k = 0; k < rgbs.size(); ++k)
618  _standardcolors->list.append(QColor(QRgb(rgbs[k])));
619  }
620 
621  _connectedColorChoosers.append(u->mDisplayColor);
622  _connectedColorChoosers.append(u->mHueSatPane);
623  _connectedColorChoosers.append(u->mValPane);
624  _connectedColorChoosers.append(u->mAlphaPane);
625  _connectedColorChoosers.append(u->mColorTriangle);
626  _connectedColorChoosers.append(u->mHueSlider);
627  _connectedColorChoosers.append(u->mSatSlider);
628  _connectedColorChoosers.append(u->mValSlider);
629  _connectedColorChoosers.append(u->mRedSlider);
630  _connectedColorChoosers.append(u->mGreenSlider);
631  _connectedColorChoosers.append(u->mBlueSlider);
632  _connectedColorChoosers.append(u->mAlphaSlider);
633  _connectedColorChoosers.append(u->spnHue);
634  _connectedColorChoosers.append(u->spnSat);
635  _connectedColorChoosers.append(u->spnVal);
636  _connectedColorChoosers.append(u->spnRed);
637  _connectedColorChoosers.append(u->spnGreen);
638  _connectedColorChoosers.append(u->spnBlue);
639  _connectedColorChoosers.append(u->spnAlpha);
640 
641  /* KLFGridFlowLayout *lytRecent = new KLFGridFlowLayout(12, u->mRecentColorsPalette);
642  lytRecent->setSpacing(2);
643  // lytRecent->setSizeConstraint(QLayout::SetMinAndMaxSize);
644  KLFGridFlowLayout *lytStandard = new KLFGridFlowLayout(12, u->mStandardColorsPalette);
645  lytStandard->setSpacing(2);
646  // lytStandard->setSizeConstraint(QLayout::SetFixedSize);
647  KLFGridFlowLayout *lytCustom = new KLFGridFlowLayout(12, u->mCustomColorsPalette);
648  lytCustom->setSpacing(2);
649  // lytCustom->setSizeConstraint(QLayout::SetFixedSize);
650  */
651  KLFFlowLayout *lytRecent = new KLFFlowLayout(u->mRecentColorsPalette, 11, 2, 2);
653  KLFFlowLayout *lytStandard = new KLFFlowLayout(u->mStandardColorsPalette, 11, 2, 2);
654  lytStandard->setFlush(KLFFlowLayout::FlushBegin);
655  KLFFlowLayout *lytCustom = new KLFFlowLayout(u->mCustomColorsPalette, 11, 2, 2);
657 
658  connect(_recentcolors, SIGNAL(listChanged()), this, SLOT(updatePaletteRecent()));
659  connect(_standardcolors, SIGNAL(listChanged()), this, SLOT(updatePaletteStandard()));
660  connect(_customcolors, SIGNAL(listChanged()), this, SLOT(updatePaletteCustom()));
661 
662  updatePalettes();
663 
664  int k;
665  for (k = 0; k < _connectedColorChoosers.size(); ++k) {
666  connect(_connectedColorChoosers[k], SIGNAL(colorChanged(const QColor&)),
667  this, SLOT(internalColorChanged(const QColor&)));
668  }
669 
670  connect(u->lstNames, SIGNAL(itemClicked(QListWidgetItem*)),
671  this, SLOT(internalColorNameSelected(QListWidgetItem*)));
672  connect(u->txtHex, SIGNAL(textChanged(const QString&)),
673  this, SLOT(internalColorNameSet(const QString&)));
674 
675  QPalette p = u->txtHex->palette();
676  u->txtHex->setProperty("paletteDefault", QVariant::fromValue<QPalette>(p));
677  p.setColor(QPalette::Base, QColor(255,169, 184,128));
678  u->txtHex->setProperty("paletteInvalidInput", QVariant::fromValue<QPalette>(p));
679 
680 
681  connect(u->btnAddCustomColor, SIGNAL(clicked()),
682  this, SLOT(setCurrentToCustomColor()));
683 
684  QStringList colornames = QColor::colorNames();
685  for (k = 0; k < colornames.size(); ++k) {
686  QPixmap colsample(16, 16);
687  colsample.fill(QColor(colornames[k]));
688  new QListWidgetItem(QIcon(colsample), colornames[k], u->lstNames);
689  }
690 
691  internalColorChanged(_color);
692 }
693 
695 {
696  QColor newcolor = wanted_newcolor;
697  if (!_alphaenabled)
698  newcolor.setAlpha(255);
699 
700  int k;
701  for (k = 0; k < _connectedColorChoosers.size(); ++k) {
702  _connectedColorChoosers[k]->blockSignals(true);
703  _connectedColorChoosers[k]->setProperty("color", QVariant(newcolor));
704  _connectedColorChoosers[k]->blockSignals(false);
705  }
706  QString newcolorname = newcolor.name();
707  if (u->txtHex->text() != newcolorname) {
708  u->txtHex->blockSignals(true);
709  u->txtHex->setText(newcolorname);
710  u->txtHex->blockSignals(false);
711  }
712 
713  _color = newcolor;
714 
715  emit colorChanged(newcolor);
716 }
717 
719 {
720  if (!item)
721  return;
722  QColor color(item->text());
724 }
725 
727 {
728  klfDbg("name set: "<<n) ;
729  QString name = n;
730  static QRegExp rx("\\#?[0-9A-Fa-f]{6}");
731  bool validinput = false;
732  bool setcolor = false;
733  int listselect = -1;
734  QColor color;
735  if (rx.exactMatch(name)) {
736  if (name[0] != QLatin1Char('#'))
737  name = "#"+name;
738  validinput = setcolor = true;
739  color = QColor(name);
740  } else {
741  // try to match a color name, or the beginning of a color name
742  int k;
743  for (k = 0; k < u->lstNames->count(); ++k) {
744  QString s = u->lstNames->item(k)->text();
745  if (s == name) {
746  // found an exact match. Select it and set color
747  validinput = true;
748  listselect = k;
749  setcolor = true;
750  color = QColor(name);
751  break;
752  }
753  if (s.startsWith(n)) {
754  // found a matching name. Just select it for user feedback
755  validinput = true;
756  listselect = k;
757  setcolor = false;
758  break;
759  }
760  }
761  }
762  // now set the background color of the text input correctly (valid input or not)
763  if (!validinput) {
764  u->txtHex->setProperty("invalidInput", true);
765  u->txtHex->setStyleSheet(u->txtHex->styleSheet()); // style sheet recalc
766  u->txtHex->setPalette(u->txtHex->property("paletteInvalidInput").value<QPalette>());
767  } else {
768  u->txtHex->setProperty("invalidInput", QVariant());
769  u->txtHex->setStyleSheet(u->txtHex->styleSheet()); // style sheet recalc
770  u->txtHex->setPalette(u->txtHex->property("paletteDefault").value<QPalette>());
771  }
772  // select the appropriate list item if needed
773  if (listselect >= 0) {
774  u->lstNames->blockSignals(true);
775  u->lstNames->setCurrentRow(listselect, QItemSelectionModel::ClearAndSelect);
776  u->lstNames->blockSignals(false);
777  }
778  if (setcolor)
780 }
781 
783 {
784  if (color == _color)
785  return;
786  if (!_alphaenabled && color.rgb() == _color.rgb())
787  return;
788 
790 }
791 
793 {
794  _alphaenabled = enabled;
795  u->spnAlpha->setVisible(enabled);
796  u->lblAlpha->setVisible(enabled);
797  u->mAlphaPane->setVisible(enabled);
798  u->lblsAlpha->setVisible(enabled);
799  u->mAlphaSlider->setVisible(enabled);
800  if (!enabled) {
801  _color.setAlpha(255);
802  setColor(_color);
803  }
804 }
805 
806 void KLFColorChooseWidget::fillPalette(KLFColorList *colorlist, QWidget *w)
807 {
809  klfDbg("colorlist is "<<colorlist<<", _customcolors is "<<_customcolors<<", _recentcolors is "<<_recentcolors) ;
810  int k;
811  // KLFGridFlowLayout *lyt = dynamic_cast<KLFGridFlowLayout*>( w->layout() );
812  // KLF_ASSERT_NOT_NULL(lyt, "Layout is not a KLFGridFlowLayout !", return; ) ;
813  KLFFlowLayout *lyt = dynamic_cast<KLFFlowLayout*>( w->layout() );
814  KLF_ASSERT_NOT_NULL(lyt, "Layout is not a KLFFlowLayout !", return; ) ;
815 
816  lyt->clearAll();
817  for (k = 0; k < colorlist->list.size(); ++k) {
818  klfDbg("Adding a KLFColorClickSquare for color: "<<colorlist->list[k]) ;
819 
820  KLFColorClickSquare *sq = new KLFColorClickSquare(colorlist->list[k], 12,
821  (colorlist == _customcolors ||
822  colorlist == _recentcolors),
823  w);
824  connect(sq, SIGNAL(colorActivated(const QColor&)),
825  this, SLOT(internalColorChanged(const QColor&)));
826  connect(sq, SIGNAL(wantRemoveColor(const QColor&)),
827  colorlist, SLOT(removeColor(const QColor&)));
828  // lyt->insertGridFlowWidget(sq);
829  lyt->addWidget(sq);
830  sq->show();
831  }
832  w->adjustSize(); // the widget is inside a scroll area
833 }
834 
836 {
837  _customcolors->addColor(_color);
839 }
840 
842 {
846 }
847 
849 {
850  fillPalette(_recentcolors, u->mRecentColorsPalette);
851 }
853 {
854  fillPalette(_standardcolors, u->mStandardColorsPalette);
855 }
857 {
858  fillPalette(_customcolors, u->mCustomColorsPalette);
859 }
860 
861 
862 
863 // static
865 {
866  if ( _recentcolors == 0 )
867  _recentcolors = new KLFColorList(128);
868  if ( _standardcolors == 0 )
869  _standardcolors = new KLFColorList(256);
870  if ( _customcolors == 0 )
871  _customcolors = new KLFColorList(128);
872 }
873 
874 // static
876 {
878  QList<QColor>::iterator it = _recentcolors->list.begin();
879  while (it != _recentcolors->list.end()) {
880  if ( (*it) == col )
881  it = _recentcolors->list.erase(it);
882  else
883  ++it;
884  }
885  _recentcolors->list.append(col);
886 
887  if (_recentcolors->list.size() > MAX_RECENT_COLORS) {
888  _recentcolors->list.removeAt(0);
889  }
890  _recentcolors->notifyListChanged();
891 }
892 
893 
894 
895 // -------------------------------------------------------------------
896 
897 
898 
899 void KLFColorList::addColor(const QColor& color)
900 {
901  int i;
902  if ( (i = list.indexOf(color)) >= 0 )
903  list.removeAt(i);
904 
905  list.append(color);
906  while (list.size() >= _maxsize)
907  list.pop_front();
908 
909  emit listChanged();
910 }
911 
912 void KLFColorList::removeColor(const QColor& color)
913 {
914  bool changed = false;
915  int i;
916  if ( (i = list.indexOf(color)) >= 0 ) {
917  list.removeAt(i);
918  changed = true;
919  }
920  if (changed)
921  emit listChanged();
922 }
923 
924 // static
925 KLFColorList *KLFColorChooser::_colorlist = NULL;
926 
927 QStyle *KLFColorChooser::mReplaceButtonStyle = NULL;
928 
930  : QPushButton(parent), _color(0,0,0,255), _pix(), _allowdefaultstate(false),
931  _defaultstatestring(tr("[ Default ]")), _autoadd(true), _size(120, 20),
932  _xalignfactor(0.5f), _yalignfactor(0.5f), _alphaenabled(true), mMenu(NULL), menuRelFont(NULL)
933 {
934  ensureColorListInstance();
935  connect(_colorlist, SIGNAL(listChanged()), this, SLOT(_makemenu()));
936 
937  _makemenu();
938  _setpix();
939 
940 #ifdef KLF_WS_MAC
941  if ( mReplaceButtonStyle == NULL ) {
942  mReplaceButtonStyle = QStyleFactory::create("fusion");//new QPlastiqueStyle; // deprecated in Qt5
943  }
944  setStyle(mReplaceButtonStyle);
945 #endif
946 }
947 
948 
950 {
951 }
952 
953 
955 {
956  return _color;
957 }
958 
960 {
961  //KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
962 
963  // inspired by QPushButton::sizeHint() in qpushbutton.cpp
964 
965  ensurePolished();
966 
967  int w = 0, h = 0;
968  QStyleOptionButton opt;
969  initStyleOption(&opt);
970 
971  // calculate contents size...
972  w = _pix.width()+4;
973  h = _pix.height()+2;
974 
975  opt.rect.setSize(QSize(w,h));
976 
977  if (menu())
978  w += KLF_DEBUG_TEE( style()->pixelMetric(QStyle::PM_MenuButtonIndicator, &opt, this) );
979 
980  //klfDbg("itermediate stage: w="<<w);
981 
982  QSize hint = style()->sizeFromContents(QStyle::CT_PushButton, &opt, QSize(w, h), this);
983  //klfDbg("before expansion to app/globalstrut; hint="<<hint) ;
984  hint = hint.expandedTo(QApplication::globalStrut());
985  //klfDbg("mename="<<objectName()<<" _pix size="<<_pix.size()<<" _size="<<_size<<" color="<<_color<<"; sizeHint="<<hint) ;
986  return hint;
987 }
988 
990 {
991  if ( ! _allowdefaultstate && ! col.isValid() )
992  return;
993 
994  if (_color == col)
995  return;
996 
997  _color = col;
998  _setpix();
999 
1000  if (_autoadd && _color.isValid()) {
1001  _colorlist->addColor(_color);
1002  }
1003  emit colorChanged(_color);
1004 }
1005 
1007 {
1008  setColor(QColor());
1009 }
1010 
1012 {
1013  _allowdefaultstate = allow;
1014  _makemenu();
1015 }
1017 {
1018  _defaultstatestring = str;
1019  _makemenu();
1020 }
1021 
1023 {
1024  _autoadd = autoadd;
1025 }
1027 {
1028  _size = size;
1029  _setpix();
1030  if (size.isValid())
1031  setMinimumSize(sizeHint());
1032  else
1033  setMinimumSize(QSize());
1034 }
1035 void KLFColorChooser::setPixXAlignFactor(float xalignfactor)
1036 {
1037  _xalignfactor = xalignfactor;
1038 }
1039 void KLFColorChooser::setPixYAlignFactor(float yalignfactor) {
1040  _yalignfactor = yalignfactor;
1041 }
1042 
1044 {
1045  _alphaenabled = on;
1046  _makemenu();
1047 }
1048 
1050 {
1051  // prefer our own color selection dialog
1052  QColor col = KLFColorDialog::getColor(_color, _alphaenabled, this);
1053  // QColor col = QColorDialog::getColor(_color, this);
1054  if ( ! col.isValid() )
1055  return;
1056 
1057  setColor(col);
1058 }
1059 
1061 {
1062  QColor c = sender()->property("setColor").value<QColor>();
1063  setColor(c);
1064 }
1065 
1067 {
1068  if (mMenu) {
1069  setMenu(0);
1070  mMenu->deleteLater();
1071  }
1072 
1073  QSize menuIconSize = QSize(16,16);
1074 
1075  mMenu = new QMenu(this);
1076 
1077  if (_allowdefaultstate) {
1078  mMenu->addAction(QIcon(colorPixmap(QColor(), menuIconSize)), _defaultstatestring,
1079  this, SLOT(setDefaultColor()));
1080  mMenu->addSeparator();
1081  }
1082 
1083  int n, k, nk;
1084  ensureColorListInstance();
1085  n = _colorlist->list.size();
1086  for (k = 0; k < n; ++k) {
1087  nk = n - k - 1;
1088  QColor col = _colorlist->list[nk];
1089  if (!_alphaenabled)
1090  col.setAlpha(255);
1091  QString collabel;
1092  if (col.alpha() == 255)
1093  collabel = QString("%1").arg(col.name());
1094  else
1095  collabel = QString("%1 (%2%)").arg(col.name()).arg((int)(100.0*col.alpha()/255.0+0.5));
1096 
1097  QAction *a = mMenu->addAction(QIcon(colorPixmap(col, menuIconSize)), collabel,
1098  this, SLOT(setSenderPropertyColor()));
1099  a->setIconVisibleInMenu(true);
1100  a->setProperty("setColor", QVariant::fromValue<QColor>(col));
1101  }
1102  if (k > 0)
1103  mMenu->addSeparator();
1104 
1105  mMenu->addAction(tr("Custom ..."), this, SLOT(requestColor()));
1106 
1107  if (menuRelFont != NULL)
1108  delete menuRelFont;
1109  menuRelFont = new KLFRelativeFont(this, mMenu);
1110  menuRelFont->setRelPointSize(-1);
1111  setMenu(mMenu);
1112 }
1113 
1115 {
1116  QPushButton::paintEvent(e);
1117  QPainter p(this);
1118  p.setClipRect(e->rect());
1119  p.drawPixmap(QPointF(_xalignfactor*(width()-_pix.width()), _yalignfactor*(height()-_pix.height())), _pix);
1120 }
1121 
1122 void KLFColorChooser::_setpix()
1123 {
1124  // if (_color.isValid()) {
1125  _pix = colorPixmap(_color, _size);
1126  // DON'T setIcon() because we draw ourselves ! see paintEvent() !
1127  // setIconSize(_pix.size());
1128  // setIcon(_pix);
1129  setText("");
1130  // } else {
1131  // _pix = QPixmap();
1132  // setIcon(QIcon());
1133  // setIconSize(QSize(0,0));
1134  // setText("");
1135  // }
1136 }
1137 
1138 
1139 QPixmap KLFColorChooser::colorPixmap(const QColor& color, const QSize& size)
1140 {
1141  QPixmap pix = QPixmap(size);
1142  pix.fill(Qt::transparent);
1143  if (color.isValid()) {
1144  pix.fill(Qt::black);
1145  QPainter p(&pix);
1146  // background: a checker grid to distinguish transparency
1147  p.fillRect(0,0,pix.width(),pix.height(), QBrush(QPixmap(":/pics/checker.png")));
1148  // and fill with color
1149  p.fillRect(0,0,pix.width(),pix.height(), QBrush(color));
1150  // pix.fill(color);
1151  } else {
1152  /*
1153  // draw "transparent"-representing pixmap
1154  pix.fill(QColor(127,127,127,80));
1155  QPainter p(&pix);
1156  p.setPen(QPen(QColor(255,0,0), 2));
1157  p.drawLine(0,0,size.width(),size.height());
1158  */
1159  // draw "default"/"transparent" pixmap
1160  QPainter p(&pix);
1161  p.setRenderHint(QPainter::Antialiasing);
1162  // QLinearGradient pgrad(0, 0, 0, 1);
1163  // pgrad.setColorAt(0, QColor(160,160,185));
1164  // pgrad.setColorAt(1, QColor(220,220,230));
1165  // pgrad.setCoordinateMode(QGradient::StretchToDeviceMode);
1166  // p.fillRect(0, 0, pix.width(), pix.height(), pgrad);
1167 
1168  QPen pen(QColor(127,0,0), 2.f, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
1169  p.setPen(pen);
1170  // p.drawLine(QPointF(0,0), QPointF(pix.width(), pix.height()));
1171  p.drawLine(QPointF(0,pix.height()), QPointF(pix.width(), 0));
1172 
1173  /*
1174  // p.scale((qreal)pix.width(), (qreal)pix.height());
1175 
1176  QRectF dashrect(QPointF(0.34*pix.width(), 0.40*pix.height()),
1177  QPointF(0.67*pix.width(), 0.60*pix.height()));
1178  // QRectF dashrect(QPointF(0.1*pix.width(), 0.10*pix.height()),
1179  // QPointF(0.9*pix.width(), 0.90*pix.height()));
1180  p.setClipRect(dashrect);
1181  p.translate(dashrect.topLeft());
1182  p.scale(dashrect.width(), dashrect.height());
1183 
1184  p.drawLine(0,0,1,1);
1185 
1186  QRadialGradient dashgrad(QPointF(0.75, 0.3), 0.4, QPointF(0.95, 0.2));
1187  dashgrad.setColorAt(0, QColor(180, 180, 240));
1188  dashgrad.setColorAt(1, QColor(40, 40, 50));
1189  dashgrad.setCoordinateMode(QGradient::LogicalMode);
1190  p.setPen(Qt::NoPen);
1191  p.setBrush(dashgrad);
1192  p.fillRect(QRectF(0,0,1,1), dashgrad);
1193  */
1194 
1195  // qreal yrad = 2;
1196  // qreal xrad = 2;//yrad * dashrect.height()/dashrect.width();
1197  // p.drawRoundedRect(QRectF(0,0,1,1), xrad, yrad, Qt::AbsoluteSize);
1198 
1199  /*
1200  // QLinearGradient pdashgrad(0, 0, 1, 0);
1201  // pdashgrad.setColorAt(0, QColor(120, 0, 40));
1202  // pdashgrad.setColorAt(1, QColor(120, 0, 40));
1203  QRadialGradient dashgrad(QPointF(1.75, 1.9), 0.6, QPointF(1.9, 1.8));
1204  // QLinearGradient dashgrad(QPointF(0,0), QPointF(1,0));
1205  dashgrad.setColorAt(0, QColor(255, 0, 0));
1206  dashgrad.setColorAt(1, QColor(0, 255, 0));
1207  dashgrad.setCoordinateMode(QGradient::StretchToDeviceMode);
1208  // dashgrad.setColorAt(0, QColor(255, 255, 255));
1209  // dashgrad.setColorAt(1, QColor(40, 40, 50));
1210  // QPen pen(QBrush(dashgrad), pix.height()/5.f, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
1211  p.setPen(Qt::NoPen);
1212  p.setBrush(dashgrad);
1213  QRectF dashrect(QPointF(0.34*pix.width(), 0.40*pix.height()),
1214  QPointF(0.67*pix.width(), 0.65*pix.height()));
1215  qreal rad = pix.height()/8.;
1216  p.drawRoundedRect(dashrect, 1.2*rad, rad, Qt::AbsoluteSize);
1217  // p.drawLine(pix.width()*3./8., pix.height()/2., pix.width()*5./8., pix.height()/2.);
1218  // p.fillRect(0, 0, pix.width(), pix.height(), dashgrad); // debug this gradient
1219  */
1220  }
1221  return pix;
1222 }
1223 
1224 
1225 
1226 // static
1227 int KLFColorChooser::staticUserMaxColors = 10; // default of 10 colors
1228 
1229 
1230 // static
1232 {
1233  staticUserMaxColors = maxColors;
1234 }
1235 
1236 // static
1237 void KLFColorChooser::ensureColorListInstance()
1238 {
1239  if ( _colorlist == 0 )
1240  _colorlist = new KLFColorList(staticUserMaxColors);
1241 }
1242 // static
1244 {
1245  ensureColorListInstance();
1246  _colorlist->list = colors;
1247  _colorlist->notifyListChanged();
1248 }
1249 
1250 // static
1252 {
1253  ensureColorListInstance();
1254  QList<QColor> l = _colorlist->list;
1255  return l;
1256 }
1257 
1258 
1259 
1260 
virtual void internalColorNameSet(const QString &colorname)
virtual void internalColorChanged(const QColor &newcolor)
void colorChanged(const QColor &color)
static void setRecentCustomColors(QList< QColor > recentcolors, QList< QColor > customcolors)
static QList< QColor > customColors()
static QList< QColor > recentColors()
static void addRecentColor(const QColor &col)
void setAlphaEnabled(bool alpha_enabled)
static void ensureColorListsInstance()
void setColor(const QColor &color)
virtual void internalColorNameSelected(QListWidgetItem *item)
KLFColorChooseWidget(QWidget *parent=0)
virtual void mousePressEvent(QMouseEvent *e)
void colorChanged(const QColor &color)
void setPaneType(const QString &panetype)
virtual void paintEvent(QPaintEvent *e)
virtual void mouseMoveEvent(QMouseEvent *e)
virtual void keyPressEvent(QKeyEvent *e)
void setColor(const QColor &newcolor)
KLFColorChooseWidgetPane(QWidget *parent=0)
virtual void wheelEvent(QWheelEvent *e)
void setAlphaEnabled(bool alpha_enabled)
KLFColorChooser(QWidget *parent)
void setAutoAddToList(bool autoadd)
void paintEvent(QPaintEvent *event)
void setPixXAlignFactor(float xalignfactor)
void setAllowDefaultState(bool allow)
void colorChanged(const QColor &newcolor)
void setShowSize(const QSize &size)
static QList< QColor > colorList()
static void setUserMaxColors(int maxcolors)
void setPixYAlignFactor(float yalignfactor)
void setColor(const QColor &color)
virtual QSize sizeHint() const
void setDefaultStateString(const QString &str)
static void setColorList(const QList< QColor > &colorlist)
void setSqSize(int sqsize)
void paintEvent(QPaintEvent *event)
void resizeEvent(QResizeEvent *event)
void mousePressEvent(QMouseEvent *event)
void wantRemoveColor(const QColor &color)
void keyPressEvent(QKeyEvent *event)
void setRemovable(bool removable)
KLFColorClickSquare(QColor color=Qt::white, int size=16, bool removable=true, QWidget *parent=0)
void contextMenuEvent(QContextMenuEvent *event)
void setColorComponent(const QString &component)
KLFColorComponentSpinBox(QWidget *parent)
void colorChanged(const QColor &color)
void setColor(const QColor &color)
static int valueMax(const QString &component)
QColor colorFromValues(QColor color_base, int value_a, int value_b=-1)
static int valueFromNewColor(const QColor &color, const QString &component)
int valueAFromNewColor(const QColor &color) const
bool refreshColorFromInternalValues(int value_a, int value_b=-1)
int valueBFromNewColor(const QColor &color) const
A dialog to let the user select a color.
KLFColorChooseWidget * colorChooseWidget()
static QColor getColor(QColor startwith=Qt::black, bool alphaenabled=true, QWidget *parent=0)
void setColor(const QColor &color)
virtual ~KLFColorDialog()
KLFColorDialog(QWidget *parent=0)
A Layout that places widgets left to right, top to bottom.
Definition: klfflowlayout.h:39
void clearAll(bool deleteItems=true)
virtual void addWidget(QWidget *w, int hstretch=0, int vstretch=0, Qt::Alignment align=0)
void setFlush(Flush f)
@ FlushBegin
Leave all extra space at end of line.
Definition: klfflowlayout.h:52
KLFGridFlowLayout(int columns, QWidget *parent)
virtual void insertGridFlowWidget(QWidget *w, Qt::Alignment align=0)
QList< QWidget * > mGridFlowWidgets
Definition: klfguiutil.h:395
void setRelPointSize(int relps)
const char * style
Definition: klfdatautil.cpp:56
#define KLF_DEBUG_BLOCK(msg)
Utility to debug the execution of a block.
#define KLF_ASSERT_NOT_NULL(ptr, msg, failaction)
Asserting Non-NULL pointers (NON-FATAL)
#define KLF_DEBUG_TEE(expr)
Print the value of expression and return it.
#define KLF_FUNC_NAME
#define klfDbg(streamableItems)
print debug stream items
Base declarations for klatexformula and some utilities.
const char * constData() const
int alpha() const
int blue() const
QStringList colorNames()
int green() const
int hue() const
bool isValid() const
QString name() const
int red() const
QRgb rgb() const
QRgb rgba() const
int saturation() const
void setAlpha(int alpha)
void setHsv(int h, int s, int v, int a)
void setRgb(int r, int g, int b, int a)
int value() const
const QPoint & globalPos() const
void accept()
int height() const
void setPixel(int x, int y, uint index_or_rgb)
int width() const
Qt::KeyboardModifiers modifiers() const
int key() const
Qt::KeyboardModifiers modifiers() const
void append(const T &value)
void clear()
int size() const
QPoint pos() const
void drawPixmap(const QRectF &target, const QPixmap &pixmap, const QRectF &source)
void fillRect(const QRectF &rectangle, const QBrush &brush)
void setClipRect(const QRectF &rectangle, Qt::ClipOperation operation)
const QRect & rect() const
void setColor(ColorGroup group, ColorRole role, const QColor &color)
void fill(const QColor &color)
int height() const
int width() const
int x() const
int y() const
bool exactMatch(const QString &str) const
QSize expandedTo(const QSize &otherSize) const
bool isValid() const
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const
bool isEmpty() const
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
QByteArray toLocal8Bit() const
QString toLower() const
bool contains(const QString &str, Qt::CaseSensitivity cs) const
typedef Alignment
int delta() const
Qt::Orientation orientation() const

Generated by doxygen 1.9.1