• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.8.5 API Reference
  • KDE Home
  • Contact Us
 

KDEUI

  • kdeui
  • colors
kcolordialog.cpp
Go to the documentation of this file.
1 /* This file is part of the KDE libraries
2  Copyright (C) 1997 Martin Jones (mjones@kde.org)
3  Copyright (C) 2007 Roberto Raggi (roberto@kdevelop.org)
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Library General Public
7  License as published by the Free Software Foundation; either
8  version 2 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Library General Public License for more details.
14 
15  You should have received a copy of the GNU Library General Public License
16  along with this library; see the file COPYING.LIB. If not, write to
17  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  Boston, MA 02110-1301, USA.
19 */
20 //-----------------------------------------------------------------------------
21 // KDE color selection dialog.
22 //
23 // 1999-09-27 Espen Sand <espensa@online.no>
24 // KColorDialog is now subclassed from KDialog. I have also extended
25 // KColorDialog::getColor() so that it contains a parent argument. This
26 // improves centering capability.
27 //
28 // layout management added Oct 1997 by Mario Weilguni
29 // <mweilguni@sime.com>
30 //
31 
32 #include "kcolordialog.h"
33 #include "kcolordialog_p.h"
34 
35 
36 #include <stdio.h>
37 #include <stdlib.h>
38 
39 #include <QtGui/QButtonGroup>
40 #include <QtGui/QCheckBox>
41 #include <QtGui/QDesktopWidget>
42 #include <QtGui/QRadioButton>
43 #include <QtGui/qdrawutil.h>
44 #include <QtGui/QActionEvent>
45 #include <QtCore/QFile>
46 #include <QtGui/QHeaderView>
47 #include <QtGui/QImage>
48 #include <QtGui/QStyledItemDelegate>
49 #include <QtGui/QLabel>
50 #include <QtGui/QLayout>
51 #include <QtGui/QPainter>
52 #include <QtGui/QPushButton>
53 #include <QtGui/QScrollBar>
54 #include <QtCore/QTimer>
55 
56 #include <kapplication.h>
57 #include <kcombobox.h>
58 #include <kconfig.h>
59 #include <kglobal.h>
60 #include <kglobalsettings.h>
61 #include <khbox.h>
62 #include <kiconloader.h>
63 #include <klineedit.h>
64 #include <klistwidget.h>
65 #include <klocale.h>
66 #include <kmessagebox.h>
67 #include <knuminput.h>
68 #include <kseparator.h>
69 #include <kstandarddirs.h>
70 #include <kcolorcollection.h>
71 #include <kcolorutils.h>
72 
73 #include "kcolormimedata.h"
74 #include <config.h>
75 #include <kdebug.h>
76 
77 #include "kcolorchoosermode_p.h"
78 #include "kcolorhelpers_p.h"
79 #include "kselector.h"
80 #include "kcolorvalueselector.h"
81 #include "khuesaturationselect.h"
82 #include "kxyselector.h"
83 #include <kconfiggroup.h>
84 
85 #ifdef Q_WS_X11
86 #include <X11/Xlib.h>
87 #include <X11/Xutil.h>
88 #include <QX11Info>
89 #include <fixx11h.h>
90 #endif
91 
92 using namespace KDEPrivate;
93 
94 using KDEPrivate::KColorTable;
95 
96 struct ColorCollectionNameType {
97  const char* const m_fileName;
98  const char* const m_displayName;
99 };
100 
101 static const ColorCollectionNameType colorCollectionName[] = {
102  { "Recent_Colors", I18N_NOOP2("palette name", "* Recent Colors *") },
103  { "Custom_Colors", I18N_NOOP2("palette name", "* Custom Colors *") },
104  { "40.colors", I18N_NOOP2("palette name", "Forty Colors") },
105  { "Oxygen.colors", I18N_NOOP2("palette name", "Oxygen Colors") },
106  { "Rainbow.colors", I18N_NOOP2("palette name", "Rainbow Colors") },
107  { "Royal.colors", I18N_NOOP2("palette name", "Royal Colors") },
108  { "Web.colors", I18N_NOOP2("palette name", "Web Colors") },
109  { 0, 0 } // end of data
110 };
111 
112 enum ColorCollectionIndices
113 {
114  recentColorIndex,
115  customColorIndex,
116  fortyColorIndex
117 };
118 
119 //-----------------------------------------------------------------------------
120 
121 class KColorCells::KColorCellsPrivate
122 {
123 public:
124  KColorCellsPrivate(KColorCells *q): q(q) {
125  inMouse = false;
126  selected = -1;
127  shade = false;
128  }
129 
130  KColorCells *q;
131  QPoint mousePos;
132  int selected;
133  bool shade;
134  bool inMouse;
135 };
136 
137 class KColorCellsItemDelegate: public QStyledItemDelegate
138 {
139 public:
140  KColorCellsItemDelegate(KColorCells *parent): QStyledItemDelegate(parent) {}
141  virtual void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const
142  {
143  QStyleOptionViewItemV4 opt(option);
144  initStyleOption(&opt,index);
145 
146  //Get the current cell color
147  QColor backgroundColor = index.data(Qt::BackgroundRole).value<QColor>();
148  if (backgroundColor.isValid()) {
149  //Paint the general background
150  painter->fillRect(opt.rect, backgroundColor);
151  //Paint the selection mark (circle)
152  if (opt.state & QStyle::State_Selected) {
153  //Use black or white, depending on the contrast
154  QColor color = QColor(0, 0, 0, 220);
155  if (KColorUtils::contrastRatio(color, backgroundColor) < 5) {
156  color = QColor(255, 255, 255, 220);
157  }
158  //Draw the selection (radiobutton-like) circle
159  painter->save();
160  painter->setRenderHint(QPainter::Antialiasing, true);
161  painter->setRenderHint(QPainter::HighQualityAntialiasing, true);
162  painter->setPen(QPen(color, 1.2, Qt::SolidLine));
163  painter->setBrush(QBrush());
164  painter->drawEllipse(opt.rect.adjusted(2,2,-2,-2));
165  painter->restore();
166  }
167  } else {
168  //Paint the "X" (missing) cross on empty background color
169  backgroundColor = opt.palette.color(QPalette::Window);
170  painter->fillRect(opt.rect, backgroundColor);
171  painter->save();
172  QColor crossColor = qGray(backgroundColor.rgb()) > 192 ? backgroundColor.darker(106) :
173  backgroundColor.lighter(106);
174  painter->setPen(QPen(crossColor, 1.5));
175  painter->drawLine(opt.rect.topLeft(), opt.rect.bottomRight());
176  painter->drawLine(opt.rect.topRight(), opt.rect.bottomLeft());
177  painter->restore();
178  }
179  }
180 };
181 
182 KColorCells::KColorCells(QWidget *parent, int rows, int cols)
183  : QTableWidget(parent), d(new KColorCellsPrivate(this))
184 {
185  setItemDelegate(new KColorCellsItemDelegate(this));
186 
187  setFrameShape(QFrame::NoFrame);
188  d->shade = true;
189  setRowCount(rows);
190  setColumnCount(cols);
191 
192  verticalHeader()->hide();
193  horizontalHeader()->hide();
194 
195  d->selected = 0;
196  d->inMouse = false;
197 
198  // Drag'n'Drop
199  setAcceptDrops(true);
200 
201  setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
202  setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
203  viewport()->setBackgroundRole(QPalette::Background);
204  setBackgroundRole(QPalette::Background);
205 
206 
207  setSelectionMode(QAbstractItemView::SingleSelection);
208  setDragEnabled(false);
209 }
210 
211 KColorCells::~KColorCells()
212 {
213  delete d;
214 }
215 
216 QColor KColorCells::color(int index) const
217 {
218  QTableWidgetItem * tmpItem = item(index / columnCount(), index % columnCount());
219 
220  if (tmpItem != 0)
221  return tmpItem->data(Qt::BackgroundRole).value<QColor>();
222 
223  return QColor();
224 }
225 
226 int KColorCells::count() const
227 {
228  return rowCount() * columnCount();
229 }
230 
231 void KColorCells::setShading(bool _shade)
232 {
233  d->shade = _shade;
234 }
235 
236 void KColorCells::setAcceptDrags(bool _acceptDrags)
237 {
238  this->setDragEnabled(_acceptDrags);
239 }
240 
241 void KColorCells::setSelected(int index)
242 {
243  Q_ASSERT(index >= 0 && index < count());
244 
245  d->selected = index;
246 }
247 
248 int KColorCells::selectedIndex() const
249 {
250  return d->selected;
251 }
252 
253 void KColorCells::setColor(int column, const QColor &color)
254 {
255  const int tableRow = column / columnCount();
256  const int tableColumn = column % columnCount();
257 
258  Q_ASSERT(tableRow >= 0 && tableRow < rowCount());
259  Q_ASSERT(tableColumn >= 0 && tableColumn < columnCount());
260 
261  QTableWidgetItem * tableItem = item(tableRow, tableColumn);
262 
263  if (tableItem == 0) {
264  tableItem = new QTableWidgetItem();
265  setItem(tableRow, tableColumn, tableItem);
266  }
267 
268  tableItem->setData(Qt::BackgroundRole , color);
269 }
270 
271 /*void KColorCells::paintCell( QPainter *painter, int row, int col )
272 {
273  painter->setRenderHint( QPainter::Antialiasing , true );
274 
275  QBrush brush;
276  int w = 1;
277 
278  if (shade)
279  {
280  qDrawShadePanel( painter, 1, 1, cellWidth()-2,
281  cellHeight()-2, palette(), true, 1, &brush );
282  w = 2;
283  }
284  QColor color = colors[ row * numCols() + col ];
285  if (!color.isValid())
286  {
287  if (!shade) return;
288  color = palette().color(backgroundRole());
289  }
290 
291  const QRect colorRect( w, w, cellWidth()-w*2, cellHeight()-w*2 );
292  painter->fillRect( colorRect, color );
293 
294  if ( row * numCols() + col == selected ) {
295  painter->setPen( qGray(color.rgb())>=127 ? Qt::black : Qt::white );
296  painter->drawLine( colorRect.topLeft(), colorRect.bottomRight() );
297  painter->drawLine( colorRect.topRight(), colorRect.bottomLeft() );
298  }
299 }*/
300 
301 void KColorCells::resizeEvent(QResizeEvent*)
302 {
303  // According to the Qt doc:
304  // If you need to set the width of a given column to a fixed value, call
305  // QHeaderView::resizeSection() on the table's {horizontal,vertical}
306  // header.
307  // Therefore we iterate over each row and column and set the header section
308  // size, as the sizeHint does indeed appear to be ignored in favor of a
309  // minimum size that is larger than what we want.
310  for (int index = 0 ; index < columnCount() ; index++)
311  horizontalHeader()->resizeSection(index, sizeHintForColumn(index));
312  for (int index = 0 ; index < rowCount() ; index++)
313  verticalHeader()->resizeSection(index, sizeHintForRow(index));
314 }
315 
316 int KColorCells::sizeHintForColumn(int /*column*/) const
317 {
318  return width() / columnCount() ;
319 }
320 
321 int KColorCells::sizeHintForRow(int /*row*/) const
322 {
323  return height() / rowCount() ;
324 }
325 
326 void KColorCells::mousePressEvent(QMouseEvent *e)
327 {
328  d->inMouse = true;
329  d->mousePos = e->pos();
330 
331  QTableWidget::mousePressEvent(e);
332 }
333 
334 
335 int KColorCells::positionToCell(const QPoint &pos, bool ignoreBorders) const
336 {
337  //TODO ignoreBorders not yet handled
338  Q_UNUSED(ignoreBorders)
339 
340  QTableWidgetItem* tableItem = itemAt(pos);
341 
342  if (!tableItem)
343  return -1;
344 
345  const int itemRow = row(tableItem);
346  const int itemColumn = column(tableItem);
347  int cell = itemRow * columnCount() + itemColumn;
348 
349  /*if (!ignoreBorders)
350  {
351  int border = 2;
352  int x = pos.x() - col * cellWidth();
353  int y = pos.y() - row * cellHeight();
354  if ( (x < border) || (x > cellWidth()-border) ||
355  (y < border) || (y > cellHeight()-border))
356  return -1;
357  }*/
358 
359  return cell;
360 }
361 
362 void KColorCells::mouseMoveEvent(QMouseEvent *e)
363 {
364  if (this->dragEnabled() || this->acceptDrops()) {
365  if (!(e->buttons() & Qt::LeftButton)) return;
366 
367  if (d->inMouse) {
368  int delay = KGlobalSettings::dndEventDelay();
369  if (e->x() > d->mousePos.x() + delay || e->x() < d->mousePos.x() - delay ||
370  e->y() > d->mousePos.y() + delay || e->y() < d->mousePos.y() - delay) {
371  // Drag color object
372  QTableWidgetItem * tableItem = itemAt(d->mousePos);
373 
374  if (tableItem) {
375  QVariant var = tableItem->data(Qt::BackgroundRole);
376  QColor tmpCol = var.value<QColor>();
377  if (tmpCol.isValid())
378  KColorMimeData::createDrag(tmpCol, this)->start();
379  }
380  }
381  }
382  } else
383  QTableWidget::mouseMoveEvent(e);
384 }
385 
386 void KColorCells::dragEnterEvent(QDragEnterEvent *event)
387 {
388  kDebug() << "KColorCells::dragEnterEvent() acceptDrags="
389  << this->dragEnabled()
390  << " canDecode=" << KColorMimeData::canDecode(event->mimeData())
391  << endl;
392  event->setAccepted(this->dragEnabled() && KColorMimeData::canDecode(event->mimeData()));
393 }
394 
395 // Reimplemented to override QTableWidget's override. Else dropping doesn't work.
396 void KColorCells::dragMoveEvent(QDragMoveEvent *event)
397 {
398  kDebug() << "KColorCells::dragMoveEvent() acceptDrags="
399  << this->dragEnabled()
400  << " canDecode=" << KColorMimeData::canDecode(event->mimeData())
401  << endl;
402  event->setAccepted(this->dragEnabled() && KColorMimeData::canDecode(event->mimeData()));
403 }
404 
405 void KColorCells::dropEvent(QDropEvent *event)
406 {
407  QColor c = KColorMimeData::fromMimeData(event->mimeData());
408 
409  kDebug() << "KColorCells::dropEvent() color.isValid=" << c.isValid();
410  if (c.isValid()) {
411  QTableWidgetItem * tableItem = itemAt(event->pos());
412 
413  if (tableItem)
414  tableItem->setData(Qt::BackgroundRole , c);
415  }
416 }
417 
418 void KColorCells::mouseReleaseEvent(QMouseEvent *e)
419 {
420  if (selectionMode() != QAbstractItemView::NoSelection) {
421  int cell = positionToCell(d->mousePos);
422  int currentCell = positionToCell(e->pos());
423 
424  // If we release the mouse in another cell and we don't have
425  // a drag we should ignore this event.
426  if (currentCell != cell)
427  cell = -1;
428 
429  if ((cell != -1) && (d->selected != cell)) {
430  d->selected = cell;
431 
432  const int newRow = cell / columnCount();
433  const int newColumn = cell % columnCount();
434 
435  clearSelection(); // we do not want old violet selected cells
436 
437  item(newRow, newColumn)->setSelected(true);
438  }
439 
440  d->inMouse = false;
441  if (cell != -1)
442  emit colorSelected(cell , color(cell));
443  }
444 
445  QTableWidget::mouseReleaseEvent(e);
446 }
447 
448 void KColorCells::mouseDoubleClickEvent(QMouseEvent * /*e*/)
449 {
450  int cell = positionToCell(d->mousePos);
451 
452  if (cell != -1)
453  emit colorDoubleClicked(cell , color(cell));
454 }
455 
456 
457 //-----------------------------------------------------------------------------
458 
459 class KColorPatch::KColorPatchPrivate
460 {
461 public:
462  KColorPatchPrivate(KColorPatch *q): q(q) {}
463 
464  KColorPatch *q;
465  QColor color;
466 };
467 
468 KColorPatch::KColorPatch(QWidget *parent) : QFrame(parent), d(new KColorPatchPrivate(this))
469 {
470  setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
471  setAcceptDrops(true);
472  setMinimumSize(12, 12);
473 }
474 
475 KColorPatch::~KColorPatch()
476 {
477  delete d;
478 }
479 
480 QColor KColorPatch::color() const
481 {
482  return d->color;
483 }
484 
485 void KColorPatch::setColor(const QColor &col)
486 {
487  d->color = col.toRgb();
488 
489  update();
490 }
491 
492 void KColorPatch::paintEvent(QPaintEvent* pe)
493 {
494  QFrame::paintEvent(pe);
495  QPainter painter(this);
496 
497  fillOpaqueRect(&painter, contentsRect(), d->color);
498 }
499 
500 void KColorPatch::mouseMoveEvent(QMouseEvent *e)
501 {
502  // Drag color object
503  if (!(e->buttons() & Qt::LeftButton))
504  return;
505  KColorMimeData::createDrag(d->color, this)->start();
506 }
507 
508 void KColorPatch::dragEnterEvent(QDragEnterEvent *event)
509 {
510  event->setAccepted(KColorMimeData::canDecode(event->mimeData()));
511 }
512 
513 void KColorPatch::dropEvent(QDropEvent *event)
514 {
515  QColor c = KColorMimeData::fromMimeData(event->mimeData());
516  if (c.isValid()) {
517  setColor(c);
518  emit colorChanged(c);
519  }
520 }
521 
522 class KColorTable::KColorTablePrivate
523 {
524 public:
525  KColorTablePrivate(KColorTable *q): q(q) {}
526 
527  void slotColorCellSelected(int index , const QColor&);
528  void slotColorCellDoubleClicked(int index , const QColor&);
529  void slotColorTextSelected(const QString &colorText);
530  void slotSetColors(const QString &_collectionName);
531  void slotShowNamedColorReadError(void);
532 
533  KColorTable *q;
534  QString i18n_namedColors;
535  KComboBox *combo;
536  KColorCells *cells;
537  QScrollArea *sv;
538  KListWidget *mNamedColorList;
539  KColorCollection *mPalette;
540  int mMinWidth;
541  int mCols;
542  QMap<QString, QColor> m_namedColorMap;
543 };
544 
545 KColorTable::KColorTable(QWidget *parent, int minWidth, int cols)
546  : QWidget(parent), d(new KColorTablePrivate(this))
547 {
548  d->cells = 0;
549  d->mPalette = 0;
550  d->mMinWidth = minWidth;
551  d->mCols = cols;
552  d->i18n_namedColors = i18n("Named Colors");
553 
554  QStringList diskPaletteList = KColorCollection::installedCollections();
555  QStringList paletteList;
556 
557  // We must replace the untranslated file names by translate names (of course only for KDE's standard palettes)
558  for (int i = 0; colorCollectionName[i].m_fileName; ++i) {
559  diskPaletteList.removeAll(colorCollectionName[i].m_fileName);
560  paletteList.append(i18nc("palette name", colorCollectionName[i].m_displayName));
561  }
562  paletteList += diskPaletteList;
563  paletteList.append(d->i18n_namedColors);
564 
565  QVBoxLayout *layout = new QVBoxLayout(this);
566 
567  d->combo = new KComboBox(this);
568  d->combo->setEditable(false);
569  d->combo->addItems(paletteList);
570  layout->addWidget(d->combo);
571 
572  d->sv = new QScrollArea(this);
573  QSize cellSize = QSize(d->mMinWidth, 120);
574  d->sv->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
575  d->sv->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
576  QSize minSize = QSize(d->sv->verticalScrollBar()->sizeHint().width(), 0);
577  minSize += QSize(d->sv->frameWidth() * 2, 0);
578  minSize += QSize(cellSize);
579  d->sv->setFixedSize(minSize);
580  layout->addWidget(d->sv);
581 
582  d->mNamedColorList = new KListWidget(this);
583  d->mNamedColorList->setObjectName("namedColorList");
584  d->mNamedColorList->setFixedSize(minSize);
585  d->mNamedColorList->hide();
586  layout->addWidget(d->mNamedColorList);
587  connect(d->mNamedColorList, SIGNAL(currentTextChanged(QString)),
588  this, SLOT(slotColorTextSelected(QString)));
589 
590  setFixedSize(sizeHint());
591  connect(d->combo, SIGNAL(activated(QString)),
592  this, SLOT(slotSetColors(QString)));
593 }
594 
595 KColorTable::~KColorTable()
596 {
597  delete d->mPalette;
598  delete d;
599 }
600 
601 QString
602 KColorTable::name() const
603 {
604  return d->combo->currentText();
605 }
606 
607 
608 static const char * const *namedColorFilePath(void)
609 {
610  //
611  // 2000-02-05 Espen Sand.
612  // Add missing filepaths here. Make sure the last entry is 0, 0!
613  //
614  // 2009-06-16 Pino Toscano
615  //
616  // You can specify either absolute paths or relative locations
617  // wrt KStandardDirs resources. In either way, there should be two
618  // "strings" for each path.
619  // - absolute path: specify it directly, then add 0 as second item
620  // * example: "/usr/share/X11/rgb.txt", 0,
621  // - KStandardDirs location: specify the filename as first item,
622  // then add the resource as second
623  // * example: "kdeui/rgb.txt", "data",
624  //
625  static const char * const path[] = {
626 #ifdef Q_WS_X11
627 #ifdef X11_RGBFILE
628  X11_RGBFILE, 0,
629 #endif
630  "/usr/share/X11/rgb.txt", 0,
631  "/usr/X11R6/lib/X11/rgb.txt", 0,
632  "/usr/openwin/lib/X11/rgb.txt", 0, // for Solaris.
633 #else /* systems without X11 */
634  "kdeui/rgb.txt", "data",
635 #endif
636  0, 0
637  };
638  return path;
639 }
640 
641 
642 
643 
644 void
645 KColorTable::readNamedColor(void)
646 {
647  if (d->mNamedColorList->count() != 0) {
648  return; // Strings already present
649  }
650 
651  KGlobal::locale()->insertCatalog("kdelibs_colors4");
652 
653  //
654  // Code somewhat inspired by KColorCollection.
655  //
656 
657  const char * const *path = namedColorFilePath();
658  for (int i = 0; path[i]; i += 2) {
659  QString file;
660  if (path[i + 1]) {
661  file = KStandardDirs::locate(path[i + 1], QString::fromLatin1(path[i]));
662  if (file.isEmpty()) {
663  continue;
664  }
665  } else {
666  file = QString::fromLatin1(path[i]);
667  }
668 
669  QFile paletteFile(file);
670  if (!paletteFile.open(QIODevice::ReadOnly)) {
671  continue;
672  }
673 
674  QByteArray line;
675  QStringList list;
676  while (!paletteFile.atEnd()) {
677  line = paletteFile.readLine();
678 
679  int red, green, blue;
680  int pos = 0;
681 
682  if (sscanf(line, "%d %d %d%n", &red, &green, &blue, &pos) == 3) {
683  //
684  // Remove duplicates. Every name with a space and every name
685  // that start with "gray".
686  //
687  QString name = line.mid(pos).trimmed();
688  QByteArray s1 = line.mid(pos);
689  if (name.isNull() || name.indexOf(' ') != -1 ||
690  name.indexOf("gray") != -1 || name.indexOf("grey") != -1) {
691  continue;
692  }
693 
694  const QColor color(red, green, blue);
695  if (color.isValid()) {
696  const QString colorName(i18nc("color", name.toLatin1().data()));
697  list.append(colorName);
698  d->m_namedColorMap[ colorName ] = color;
699  }
700  }
701  }
702 
703  list.sort();
704  d->mNamedColorList->addItems(list);
705  break;
706  }
707 
708  if (d->mNamedColorList->count() == 0) {
709  //
710  // Give the error dialog box a chance to center above the
711  // widget (or dialog). If we had displayed it now we could get a
712  // situation where the (modal) error dialog box pops up first
713  // preventing the real dialog to become visible until the
714  // error dialog box is removed (== bad UI).
715  //
716  QTimer::singleShot(10, this, SLOT(slotShowNamedColorReadError()));
717  }
718 }
719 
720 
721 void
722 KColorTable::KColorTablePrivate::slotShowNamedColorReadError(void)
723 {
724  if (mNamedColorList->count() == 0) {
725  QString pathMsg;
726  int pathCount = 0;
727 
728  const char * const *path = namedColorFilePath();
729  for (int i = 0; path[i]; i += 2, ++pathCount) {
730  if (path[i + 1]) {
731  pathMsg += QLatin1String(path[i + 1]) + ", " + QString::fromLatin1(path[i]);
732  } else {
733  pathMsg += QLatin1String(path[i]);
734  }
735  pathMsg += '\n';
736  }
737 
738  QString finalMsg = i18ncp("%1 is the number of paths, %2 is the list of paths (with newlines between them)",
739  "Unable to read X11 RGB color strings. The following "
740  "file location was examined:\n%2",
741  "Unable to read X11 RGB color strings. The following "
742  "file locations were examined:\n%2",
743  pathCount, pathMsg );
744 
745  KMessageBox::sorry(q, finalMsg);
746  }
747 }
748 
749 
750 //
751 // 2000-02-12 Espen Sand
752 // Set the color in two steps. The setColors() slot will not emit a signal
753 // with the current color setting. The reason is that setColors() is used
754 // by the color selector dialog on startup. In the color selector dialog
755 // we normally want to display a startup color which we specify
756 // when the dialog is started. The slotSetColors() slot below will
757 // set the palette and then use the information to emit a signal with the
758 // new color setting. It is only used by the combobox widget.
759 //
760 void
761 KColorTable::KColorTablePrivate::slotSetColors(const QString &_collectionName)
762 {
763  q->setColors(_collectionName);
764  if (mNamedColorList->count() && mNamedColorList->isVisible()) {
765  int item = mNamedColorList->currentRow();
766  mNamedColorList->setCurrentRow(item < 0 ? 0 : item);
767  slotColorTextSelected(mNamedColorList->currentItem()->text());
768  } else {
769  slotColorCellSelected(0, QColor()); // FIXME: We need to save the current value!!
770  }
771 }
772 
773 
774 void
775 KColorTable::setColors(const QString &_collectionName)
776 {
777  QString collectionName(_collectionName);
778 
779  if (d->combo->currentText() != collectionName) {
780  bool found = false;
781  for (int i = 0; i < d->combo->count(); i++) {
782  if (d->combo->itemText(i) == collectionName) {
783  d->combo->setCurrentIndex(i);
784  found = true;
785  break;
786  }
787  }
788  if (!found) {
789  d->combo->addItem(collectionName);
790  d->combo->setCurrentIndex(d->combo->count() - 1);
791  }
792  }
793 
794  // We must again find the file name of the palette from the eventual translation
795  for (int i = 0; colorCollectionName[i].m_fileName; ++i) {
796  if (collectionName == i18nc("palette name", colorCollectionName[i].m_displayName)) {
797  collectionName = colorCollectionName[i].m_fileName;
798  break;
799  }
800  }
801 
802 
803  //
804  // 2000-02-12 Espen Sand
805  // The palette mode "i18n_namedColors" does not use the KColorCollection
806  // class. In fact, 'mPalette' and 'cells' are 0 when in this mode. The reason
807  // for this is maninly that KColorCollection reads from and writes to files
808  // using "locate()". The colors used in "i18n_namedColors" mode comes from
809  // the X11 diretory and is not writable. I don't think this fit in
810  // KColorCollection.
811  //
812  if (!d->mPalette || d->mPalette->name() != collectionName) {
813  if (collectionName == d->i18n_namedColors) {
814  d->sv->hide();
815  d->mNamedColorList->show();
816  readNamedColor();
817 
818  delete d->cells; d->cells = 0;
819  delete d->mPalette; d->mPalette = 0;
820  } else {
821  d->mNamedColorList->hide();
822  d->sv->show();
823 
824  delete d->cells;
825  delete d->mPalette;
826  d->mPalette = new KColorCollection(collectionName);
827  int rows = (d->mPalette->count() + d->mCols - 1) / d->mCols;
828  if (rows < 1) rows = 1;
829  d->cells = new KColorCells(d->sv->viewport(), rows, d->mCols);
830  d->cells->setShading(false);
831  d->cells->setAcceptDrags(false);
832  QSize cellSize = QSize(d->mMinWidth, d->mMinWidth * rows / d->mCols);
833  d->cells->setFixedSize(cellSize);
834  for (int i = 0; i < d->mPalette->count(); i++) {
835  d->cells->setColor(i, d->mPalette->color(i));
836  }
837  connect(d->cells, SIGNAL(colorSelected(int,QColor)),
838  SLOT(slotColorCellSelected(int,QColor)));
839  connect(d->cells, SIGNAL(colorDoubleClicked(int,QColor)),
840  SLOT(slotColorCellDoubleClicked(int,QColor)));
841  d->sv->setWidget(d->cells);
842  d->cells->show();
843 
844  //d->sv->updateScrollBars();
845  }
846  }
847 }
848 
849 
850 
851 void
852 KColorTable::KColorTablePrivate::slotColorCellSelected(int index , const QColor& /*color*/)
853 {
854  if (!mPalette || (index >= mPalette->count()))
855  return;
856  emit q->colorSelected(mPalette->color(index), mPalette->name(index));
857 }
858 
859 void
860 KColorTable::KColorTablePrivate::slotColorCellDoubleClicked(int index , const QColor& /*color*/)
861 {
862  if (!mPalette || (index >= mPalette->count()))
863  return;
864  emit q->colorDoubleClicked(mPalette->color(index), mPalette->name(index));
865 }
866 
867 
868 void
869 KColorTable::KColorTablePrivate::slotColorTextSelected(const QString &colorText)
870 {
871  emit q->colorSelected(m_namedColorMap[ colorText ], colorText);
872 }
873 
874 
875 void
876 KColorTable::addToCustomColors(const QColor &color)
877 {
878  setColors(i18nc("palette name", colorCollectionName[customColorIndex].m_displayName));
879  d->mPalette->addColor(color);
880  d->mPalette->save();
881  delete d->mPalette;
882  d->mPalette = 0;
883  setColors(i18nc("palette name", colorCollectionName[customColorIndex].m_displayName));
884 }
885 
886 void
887 KColorTable::addToRecentColors(const QColor &color)
888 {
889  //
890  // 2000-02-12 Espen Sand.
891  // The 'mPalette' is always 0 when current mode is i18n_namedColors
892  //
893  bool recentIsSelected = false;
894  if (d->mPalette && d->mPalette->name() == colorCollectionName[ recentColorIndex ].m_fileName) {
895  delete d->mPalette;
896  d->mPalette = 0;
897  recentIsSelected = true;
898  }
899  KColorCollection *recentPal = new KColorCollection(colorCollectionName[ recentColorIndex ].m_fileName);
900  if (recentPal->findColor(color) == -1) {
901  recentPal->addColor(color);
902  recentPal->save();
903  }
904  delete recentPal;
905  if (recentIsSelected)
906  setColors(i18nc("palette name", colorCollectionName[ recentColorIndex ].m_displayName));
907 }
908 
909 class KCDPickerFilter;
910 
911 class KColorDialog::KColorDialogPrivate
912 {
913 public:
914  KColorDialogPrivate(KColorDialog *q): q(q) {}
915 
916  void setRgbEdit(const QColor &col);
917  void setHsvEdit(const QColor &col);
918  void setHtmlEdit(const QColor &col);
919  void _setColor(const QColor &col, const QString &name = QString());
920  void showColor(const QColor &color, const QString &name);
921 
922  void slotRGBChanged(void);
923  void slotAlphaChanged(void);
924  void slotHSVChanged(void);
925  void slotHtmlChanged(void);
926  void slotHSChanged(int, int);
927  void slotVChanged(int);
928  void slotAChanged(int);
929  void slotModeChanged(int);
930 
931  void slotColorSelected(const QColor &col);
932  void slotColorSelected(const QColor &col, const QString &name);
933  void slotColorDoubleClicked(const QColor &col, const QString &name);
934  void slotColorPicker();
935  void slotAddToCustomColors();
936  void slotDefaultColorClicked();
940  void slotWriteSettings();
941 
945  KColorChooserMode chooserMode();
946 
950  void setChooserMode(KColorChooserMode c);
951 
952  KColorDialog *q;
953  KColorTable *table;
954  QString originalPalette;
955  bool bRecursion;
956  bool bEditRgb;
957  bool bEditHsv;
958  bool bEditHtml;
959  bool bColorPicking;
960  bool bAlphaEnabled;
961  QLabel *colorName;
962  KLineEdit *htmlName;
963  KIntSpinBox *hedit;
964  KIntSpinBox *sedit;
965  KIntSpinBox *vedit;
966  KIntSpinBox *redit;
967  KIntSpinBox *gedit;
968  KIntSpinBox *bedit;
969  QWidget *alphaLabel;
970  KIntSpinBox *aedit;
971 
972  KColorPatch *patch;
973  KColorPatch *comparePatch;
974 
975  KColorChooserMode _mode;
976  QButtonGroup *modeGroup;
977 
978  KHueSaturationSelector *hsSelector;
979  KColorCollection *palette;
980  KColorValueSelector *valuePal;
981  KGradientSelector *alphaSelector;
982  QVBoxLayout* l_right;
983  QGridLayout* tl_layout;
984  QCheckBox *cbDefaultColor;
985  QColor defaultColor;
986  QColor selColor;
987 #ifdef Q_WS_X11
988  KCDPickerFilter* filter;
989 #endif
990 };
991 
992 #ifdef Q_WS_X11
993 class KCDPickerFilter: public QWidget
994 {
995 public:
996  KCDPickerFilter(QWidget* parent): QWidget(parent) {}
997 
998  virtual bool x11Event(XEvent* event) {
999  if (event->type == ButtonRelease) {
1000  QMouseEvent e(QEvent::MouseButtonRelease, QPoint(),
1001  QPoint(event->xmotion.x_root, event->xmotion.y_root) , Qt::NoButton, Qt::NoButton, Qt::NoModifier);
1002  QApplication::sendEvent(parentWidget(), &e);
1003  return true;
1004  } else return false;
1005  }
1006 };
1007 
1008 #endif
1009 
1010 
1011 KColorDialog::KColorDialog(QWidget *parent, bool modal)
1012  : KDialog(parent), d(new KColorDialogPrivate(this))
1013 {
1014  setCaption(i18n("Select Color"));
1015  setButtons(modal ? Ok | Cancel : Close);
1016  setModal(modal);
1017  d->bRecursion = true;
1018  d->bColorPicking = false;
1019  d->bAlphaEnabled = false;
1020 #ifdef Q_WS_X11
1021  d->filter = 0;
1022 #endif
1023  d->cbDefaultColor = 0L;
1024  d->_mode = ChooserClassic;
1025  connect(this, SIGNAL(okClicked()), this, SLOT(slotWriteSettings()));
1026  connect(this, SIGNAL(closeClicked()), this, SLOT(slotWriteSettings()));
1027 
1028  QLabel *label;
1029 
1030  //
1031  // Create the top level page and its layout
1032  //
1033  QWidget *page = new QWidget(this);
1034  setMainWidget(page);
1035 
1036  QGridLayout *tl_layout = new QGridLayout(page);
1037  tl_layout->setMargin(0);
1038  d->tl_layout = tl_layout;
1039  tl_layout->addItem(new QSpacerItem(spacingHint()*2, 0), 0, 1);
1040 
1041  //
1042  // the more complicated part: the left side
1043  // add a V-box
1044  //
1045  QVBoxLayout *l_left = new QVBoxLayout();
1046  tl_layout->addLayout(l_left, 0, 0);
1047 
1048  //
1049  // add a H-Box for the XY-Selector and a grid for the
1050  // entry fields
1051  //
1052  QHBoxLayout *l_ltop = new QHBoxLayout();
1053  l_left->addLayout(l_ltop);
1054 
1055  //
1056  // the palette and value selector go into the H-box
1057  //
1058  d->hsSelector = new KHueSaturationSelector(page);
1059  d->hsSelector->setMinimumSize(256, 256);
1060  l_ltop->addWidget(d->hsSelector, 8);
1061  connect(d->hsSelector, SIGNAL(valueChanged(int,int)),
1062  SLOT(slotHSChanged(int,int)));
1063 
1064  d->valuePal = new KColorValueSelector(page);
1065  d->valuePal->setMinimumSize(26, 70);
1066  d->valuePal->setIndent(false);
1067  d->valuePal->setArrowDirection(Qt::RightArrow);
1068  l_ltop->addWidget(d->valuePal, 1);
1069  connect(d->valuePal, SIGNAL(valueChanged(int)),
1070  SLOT(slotVChanged(int)));
1071 
1072  d->alphaSelector = new KGradientSelector(Qt::Horizontal, page);
1073  d->alphaSelector->setFixedSize(256, 26);
1074  d->alphaSelector->setIndent(false);
1075  d->alphaSelector->setArrowDirection(Qt::DownArrow);
1076  d->alphaSelector->setRange(0, 255);
1077  l_left->addWidget(d->alphaSelector, 1);
1078  connect(d->alphaSelector, SIGNAL(valueChanged(int)),
1079  SLOT(slotAChanged(int)));
1080 
1081  // a little space between
1082  l_left->addSpacing(10); // FIXME: remove hardcoded values
1083 
1084  QGridLayout *l_lbot = new QGridLayout();
1085  l_left->addLayout(l_lbot);
1086 
1087  // button group that manages the radio buttons
1088  QRadioButton *modeButton;
1089  d->modeGroup = new QButtonGroup(page);
1090  connect(d->modeGroup, SIGNAL(buttonClicked(int)), SLOT(slotModeChanged(int)));
1091 
1092  //
1093  // add the HSV fields
1094  //
1095  l_lbot->setColumnStretch(2, 10);
1096 
1097  modeButton = new QRadioButton(i18n("Hue:"), page);
1098  l_lbot->addWidget(modeButton, 0, 0);
1099  d->modeGroup->addButton(modeButton, ChooserHue);
1100 
1101  d->hedit = new KIntSpinBox(page);
1102  d->hedit->setMaximum(359);
1103  d->hedit->setSuffix(i18nc("The angular degree unit (for hue)", "\302\260")); // U+00B0 DEGREE SIGN
1104  l_lbot->addWidget(d->hedit, 0, 1);
1105  connect(d->hedit, SIGNAL(valueChanged(int)),
1106  SLOT(slotHSVChanged()));
1107 
1108  modeButton = new QRadioButton(i18n("Saturation:"), page);
1109  l_lbot->addWidget(modeButton, 1, 0);
1110  d->modeGroup->addButton(modeButton, ChooserSaturation);
1111 
1112  d->sedit = new KIntSpinBox(page);
1113  d->sedit->setMaximum(255);
1114  l_lbot->addWidget(d->sedit, 1, 1);
1115  connect(d->sedit, SIGNAL(valueChanged(int)),
1116  SLOT(slotHSVChanged()));
1117 
1118  modeButton = new QRadioButton(i18nc("This is the V of HSV", "Value:"), page);
1119  l_lbot->addWidget(modeButton, 2, 0);
1120  d->modeGroup->addButton(modeButton, ChooserValue);
1121 
1122  d->vedit = new KIntSpinBox(page);
1123  d->vedit->setMaximum(255);
1124  l_lbot->addWidget(d->vedit, 2, 1);
1125  connect(d->vedit, SIGNAL(valueChanged(int)),
1126  SLOT(slotHSVChanged()));
1127 
1128 
1129  //
1130  // add the RGB fields
1131  //
1132  modeButton = new QRadioButton(i18n("Red:"), page);
1133  l_lbot->addWidget(modeButton, 0, 3);
1134  d->modeGroup->addButton(modeButton, ChooserRed);
1135 
1136  d->redit = new KIntSpinBox(page);
1137  d->redit->setMaximum(255);
1138  l_lbot->addWidget(d->redit, 0, 4);
1139  connect(d->redit, SIGNAL(valueChanged(int)),
1140  SLOT(slotRGBChanged()));
1141 
1142  modeButton = new QRadioButton(i18n("Green:"), page);
1143  l_lbot->addWidget(modeButton, 1, 3);
1144  d->modeGroup->addButton(modeButton, ChooserGreen);
1145 
1146  d->gedit = new KIntSpinBox(page);
1147  d->gedit->setMaximum(255);
1148  l_lbot->addWidget(d->gedit, 1, 4);
1149  connect(d->gedit, SIGNAL(valueChanged(int)),
1150  SLOT(slotRGBChanged()));
1151 
1152  modeButton = new QRadioButton(i18n("Blue:"), page);
1153  l_lbot->addWidget(modeButton, 2, 3);
1154  d->modeGroup->addButton(modeButton, ChooserBlue);
1155 
1156  d->bedit = new KIntSpinBox(page);
1157  d->bedit->setMaximum(255);
1158  l_lbot->addWidget(d->bedit, 2, 4);
1159  connect(d->bedit, SIGNAL(valueChanged(int)),
1160  SLOT(slotRGBChanged()));
1161 
1162  d->alphaLabel = new KHBox(page);
1163  QWidget *spacer = new QWidget(d->alphaLabel);
1164  label = new QLabel(i18n("Alpha:"), d->alphaLabel);
1165  QStyleOptionButton option;
1166  option.initFrom(modeButton);
1167  QRect labelRect = modeButton->style()->subElementRect(QStyle::SE_RadioButtonContents, &option, modeButton);
1168  int indent = layoutDirection() == Qt::LeftToRight ? labelRect.left() : modeButton->geometry().right() - labelRect.right();
1169  spacer->setFixedWidth(indent);
1170  l_lbot->addWidget(d->alphaLabel, 3, 3);
1171 
1172  d->aedit = new KIntSpinBox(page);
1173  d->aedit->setMaximum(255);
1174  label->setBuddy(d->aedit);
1175  l_lbot->addWidget(d->aedit, 3, 4);
1176  connect(d->aedit, SIGNAL(valueChanged(int)),
1177  SLOT(slotAlphaChanged()));
1178 
1179  d->aedit->setVisible(false);
1180  d->alphaLabel->setVisible(false);
1181  d->alphaSelector->setVisible(false);
1182 
1183  //
1184  // add a layout for the right side
1185  //
1186  d->l_right = new QVBoxLayout;
1187  tl_layout->addLayout(d->l_right, 0, 2);
1188 
1189  //
1190  // Add the palette table
1191  //
1192  d->table = new KColorTable(page);
1193  d->l_right->addWidget(d->table, 10);
1194 
1195  connect(d->table, SIGNAL(colorSelected(QColor,QString)),
1196  SLOT(slotColorSelected(QColor,QString)));
1197 
1198  connect(
1199  d->table,
1200  SIGNAL(colorDoubleClicked(QColor,QString)),
1201  SLOT(slotColorDoubleClicked(QColor,QString))
1202  );
1203  // Store the default value for saving time.
1204  d->originalPalette = d->table->name();
1205 
1206  //
1207  // a little space between
1208  //
1209  d->l_right->addSpacing(10);
1210 
1211  QHBoxLayout *l_hbox = new QHBoxLayout();
1212  d->l_right->addItem(l_hbox);
1213 
1214  //
1215  // The add to custom colors button
1216  //
1217  QPushButton *addButton = new QPushButton(page);
1218  addButton->setText(i18n("&Add to Custom Colors"));
1219  l_hbox->addWidget(addButton, 0, Qt::AlignLeft);
1220  connect(addButton, SIGNAL(clicked()), SLOT(slotAddToCustomColors()));
1221 
1222  //
1223  // The color picker button
1224  //
1225  QPushButton* button = new QPushButton(page);
1226  button->setIcon(KIcon("color-picker"));
1227  int commonHeight = addButton->sizeHint().height();
1228  button->setFixedSize(commonHeight, commonHeight);
1229  l_hbox->addWidget(button, 0, Qt::AlignHCenter);
1230  connect(button, SIGNAL(clicked()), SLOT(slotColorPicker()));
1231 
1232  //
1233  // a little space between
1234  //
1235  d->l_right->addSpacing(10);
1236 
1237  //
1238  // and now the entry fields and the patch (=colored box)
1239  //
1240  QGridLayout *l_grid = new QGridLayout();
1241  d->l_right->addLayout(l_grid);
1242 
1243  l_grid->setColumnStretch(2, 1);
1244 
1245  label = new QLabel(page);
1246  label->setText(i18n("Name:"));
1247  l_grid->addWidget(label, 0, 1, Qt::AlignLeft);
1248 
1249  d->colorName = new QLabel(page);
1250  l_grid->addWidget(d->colorName, 0, 2, Qt::AlignLeft);
1251 
1252  label = new QLabel(page);
1253  label->setText(i18n("HTML:"));
1254  l_grid->addWidget(label, 1, 1, Qt::AlignLeft);
1255 
1256  d->htmlName = new KLineEdit(page);
1257  d->htmlName->setMaxLength(13); // Qt's QColor allows 12 hexa-digits
1258  d->htmlName->setText("#FFFFFF"); // But HTML uses only 6, so do not worry about the size
1259  int w = d->htmlName->fontMetrics().width(QLatin1String("#DDDDDDD"));
1260  d->htmlName->setFixedWidth(w);
1261  l_grid->addWidget(d->htmlName, 1, 2, Qt::AlignLeft);
1262 
1263  connect(d->htmlName, SIGNAL(textChanged(QString)),
1264  SLOT(slotHtmlChanged()));
1265 
1266  d->patch = new KColorPatch(page);
1267  d->patch->setFixedSize(48, 48);
1268  l_grid->addWidget(d->patch, 0, 0, 2, 1, Qt::AlignHCenter | Qt::AlignVCenter);
1269  connect(d->patch, SIGNAL(colorChanged(QColor)),
1270  SLOT(setColor(QColor)));
1271 
1272  //
1273  // chain fields together
1274  //
1275  setTabOrder(d->hedit, d->sedit);
1276  setTabOrder(d->sedit, d->vedit);
1277  setTabOrder(d->vedit, d->redit);
1278  setTabOrder(d->redit, d->gedit);
1279  setTabOrder(d->gedit, d->bedit);
1280  setTabOrder(d->bedit, d->aedit);
1281 
1282  tl_layout->activate();
1283  page->setMinimumSize(page->sizeHint());
1284 
1285  readSettings();
1286  d->bRecursion = false;
1287  d->bEditHsv = false;
1288  d->bEditRgb = false;
1289  d->bEditHtml = false;
1290 
1291  setFixedSize(sizeHint());
1292  QColor col;
1293  col.setHsv(0, 0, 255);
1294  d->_setColor(col);
1295 
1296 // FIXME: with enabled event filters, it crashes after ever enter of a drag.
1297 // better disable drag and drop than crashing it...
1298 // d->htmlName->installEventFilter(this);
1299 // d->hsSelector->installEventFilter(this);
1300  d->hsSelector->setAcceptDrops(true);
1301 
1302  d->setChooserMode(ChooserValue);
1303 }
1304 
1305 KColorDialog::~KColorDialog()
1306 {
1307 #ifdef Q_WS_X11
1308  if (d->bColorPicking && kapp)
1309  kapp->removeX11EventFilter(d->filter);
1310 #endif
1311  delete d;
1312 }
1313 
1314 bool
1315 KColorDialog::eventFilter(QObject *obj, QEvent *ev)
1316 {
1317  if ((obj == d->htmlName) || (obj == d->hsSelector))
1318  switch (ev->type()) {
1319  case QEvent::DragEnter:
1320  case QEvent::DragMove:
1321  case QEvent::DragLeave:
1322  case QEvent::Drop:
1323  case QEvent::DragResponse:
1324  qApp->sendEvent(d->patch, ev);
1325  return true;
1326  default:
1327  break;
1328  }
1329  return KDialog::eventFilter(obj, ev);
1330 }
1331 
1332 void
1333 KColorDialog::setDefaultColor(const QColor& col)
1334 {
1335  if (!d->cbDefaultColor) {
1336  //
1337  // a little space between
1338  //
1339  d->l_right->addSpacing(10);
1340 
1341  //
1342  // and the "default color" checkbox, under all items on the right side
1343  //
1344  d->cbDefaultColor = new QCheckBox(i18n("Default color"), mainWidget());
1345 
1346  d->l_right->addWidget(d->cbDefaultColor);
1347 
1348  mainWidget()->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); // cancel setFixedSize()
1349  d->tl_layout->activate();
1350  mainWidget()->setMinimumSize(mainWidget()->sizeHint());
1351  setFixedSize(sizeHint());
1352 
1353  connect(d->cbDefaultColor, SIGNAL(clicked()), SLOT(slotDefaultColorClicked()));
1354  }
1355 
1356  d->defaultColor = col;
1357 
1358  d->slotDefaultColorClicked();
1359 }
1360 
1361 QColor KColorDialog::defaultColor() const
1362 {
1363  return d->defaultColor;
1364 }
1365 
1366 void KColorDialog::setAlphaChannelEnabled(bool alpha)
1367 {
1368  if (d->bAlphaEnabled != alpha) {
1369  d->bAlphaEnabled = alpha;
1370  d->aedit->setVisible(d->bAlphaEnabled);
1371  d->alphaLabel->setVisible(d->bAlphaEnabled);
1372  d->alphaSelector->setVisible(d->bAlphaEnabled);
1373 
1374  mainWidget()->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); // cancel setFixedSize()
1375  d->tl_layout->activate();
1376  mainWidget()->setMinimumSize(mainWidget()->sizeHint());
1377  setFixedSize(sizeHint());
1378  }
1379 }
1380 
1381 bool KColorDialog::isAlphaChannelEnabled() const
1382 {
1383  return d->bAlphaEnabled;
1384 }
1385 
1386 
1387 void KColorDialog::KColorDialogPrivate::setChooserMode(KColorChooserMode c)
1388 {
1389  _mode = c;
1390  hsSelector->setChooserMode(c);
1391  valuePal->setChooserMode(c);
1392 
1393  modeGroup->button(valuePal->chooserMode())->setChecked(true);
1394  valuePal->updateContents();
1395  hsSelector->updateContents();
1396  valuePal->update();
1397  hsSelector->update();
1398  slotHSVChanged();
1399 }
1400 
1401 
1402 KColorChooserMode KColorDialog::KColorDialogPrivate::chooserMode()
1403 {
1404  return _mode;
1405 }
1406 
1407 void KColorDialog::KColorDialogPrivate::slotDefaultColorClicked()
1408 {
1409  if (cbDefaultColor->isChecked()) {
1410  selColor = defaultColor;
1411  showColor(selColor, i18n("-default-"));
1412  } else {
1413  showColor(selColor, QString());
1414  }
1415  emit q->colorSelected(selColor);
1416 }
1417 
1418 void
1419 KColorDialog::KColorDialogPrivate::slotModeChanged(int id)
1420 {
1421  setChooserMode(KColorChooserMode(id));
1422 }
1423 
1424 void
1425 KColorDialog::readSettings()
1426 {
1427  KConfigGroup group(KGlobal::config(), "Colors");
1428 
1429  QString collectionName = group.readEntry("CurrentPalette");
1430  if (collectionName.isEmpty()) {
1431  collectionName = i18nc("palette name", colorCollectionName[fortyColorIndex].m_displayName);
1432  } else {
1433  for (int i = 0; colorCollectionName[i].m_fileName; ++i) {
1434  if (collectionName == colorCollectionName[i].m_displayName) {
1435  collectionName = i18nc("palette name", colorCollectionName[i].m_displayName);
1436  break;
1437  }
1438  }
1439  }
1440 
1441  d->table->setColors(collectionName);
1442 }
1443 
1444 void
1445 KColorDialog::KColorDialogPrivate::slotWriteSettings()
1446 {
1447  KConfigGroup group(KGlobal::config(), "Colors");
1448 
1449  QString collectionName = table->name();
1450  if (!group.hasDefault("CurrentPalette") && table->name() == originalPalette) {
1451  group.revertToDefault("CurrentPalette");
1452  } else {
1453  QString collectionName(table->name());
1454  for (int i = 0; colorCollectionName[i].m_fileName; ++i) {
1455  if (collectionName == i18nc("palette name", colorCollectionName[i].m_displayName)) {
1456  collectionName = colorCollectionName[i].m_displayName;
1457  break;
1458  }
1459  }
1460  group.writeEntry("CurrentPalette", collectionName); //Make sure the untranslated name is saved, assuming there is one
1461  }
1462 }
1463 
1464 QColor
1465 KColorDialog::color() const
1466 {
1467  if (d->cbDefaultColor && d->cbDefaultColor->isChecked())
1468  return QColor();
1469  if (d->selColor.isValid())
1470  d->table->addToRecentColors(d->selColor);
1471  return d->selColor;
1472 }
1473 
1474 void KColorDialog::setColor(const QColor &col)
1475 {
1476  d->_setColor(col);
1477 }
1478 
1479 //
1480 // static function to display dialog and return color
1481 //
1482 int KColorDialog::getColor(QColor &theColor, QWidget *parent)
1483 {
1484  KColorDialog dlg(parent, true);
1485  dlg.setObjectName("Color Selector");
1486  if (theColor.isValid())
1487  dlg.setColor(theColor);
1488  int result = dlg.exec();
1489 
1490  if (result == Accepted) {
1491  theColor = dlg.color();
1492  }
1493 
1494  return result;
1495 }
1496 
1497 //
1498 // static function to display dialog and return color
1499 //
1500 int KColorDialog::getColor(QColor &theColor, const QColor& defaultCol, QWidget *parent)
1501 {
1502  KColorDialog dlg(parent, true);
1503  dlg.setObjectName("Color Selector");
1504  dlg.setDefaultColor(defaultCol);
1505  dlg.setColor(theColor);
1506  int result = dlg.exec();
1507 
1508  if (result == Accepted)
1509  theColor = dlg.color();
1510 
1511  return result;
1512 }
1513 
1514 void KColorDialog::KColorDialogPrivate::slotRGBChanged(void)
1515 {
1516  if (bRecursion) return;
1517  int red = redit->value();
1518  int grn = gedit->value();
1519  int blu = bedit->value();
1520 
1521  if (red > 255 || red < 0) return;
1522  if (grn > 255 || grn < 0) return;
1523  if (blu > 255 || blu < 0) return;
1524 
1525  QColor col;
1526  col.setRgb(red, grn, blu, aedit->value());
1527  bEditRgb = true;
1528  _setColor(col);
1529  bEditRgb = false;
1530 }
1531 
1532 void KColorDialog::KColorDialogPrivate::slotAlphaChanged(void)
1533 {
1534  if (bRecursion) return;
1535  int alpha = aedit->value();
1536 
1537  if (alpha > 255 || alpha < 0) return;
1538 
1539  QColor col = selColor;
1540  col.setAlpha(alpha);
1541  _setColor(col);
1542 }
1543 
1544 void KColorDialog::KColorDialogPrivate::slotHtmlChanged(void)
1545 {
1546  if (bRecursion || htmlName->text().isEmpty()) return;
1547 
1548  QString strColor(htmlName->text());
1549 
1550  // Assume that a user does not want to type the # all the time
1551  if (strColor[0] != '#') {
1552  bool signalsblocked = htmlName->blockSignals(true);
1553  strColor.prepend("#");
1554  htmlName->setText(strColor);
1555  htmlName->blockSignals(signalsblocked);
1556  }
1557 
1558  const QColor color(strColor);
1559 
1560  if (color.isValid()) {
1561  QColor col(color);
1562  bEditHtml = true;
1563  _setColor(col);
1564  bEditHtml = false;
1565  }
1566 }
1567 
1568 void KColorDialog::KColorDialogPrivate::slotHSVChanged(void)
1569 {
1570  if (bRecursion) return;
1571  int hue = hedit->value();
1572  int sat = sedit->value();
1573  int val = vedit->value();
1574 
1575  if (hue > 359 || hue < 0) return;
1576  if (sat > 255 || sat < 0) return;
1577  if (val > 255 || val < 0) return;
1578 
1579  QColor col;
1580  col.setHsv(hue, sat, val, aedit->value());
1581  bEditHsv = true;
1582  _setColor(col);
1583  bEditHsv = false;
1584 }
1585 
1586 void KColorDialog::KColorDialogPrivate::slotHSChanged(int x, int y)
1587 {
1588  QColor col = selColor;
1589  KColorChooserMode xMode = chooserXMode(chooserMode());
1590  KColorChooserMode yMode = chooserYMode(chooserMode());
1591  setComponentValue(col, xMode, x / (xMode == ChooserHue ? 360.0 : 255.0));
1592  setComponentValue(col, yMode, y / (yMode == ChooserHue ? 360.0 : 255.0));
1593  _setColor(col);
1594 }
1595 
1596 void KColorDialog::KColorDialogPrivate::slotVChanged(int v)
1597 {
1598  QColor col = selColor;
1599  setComponentValue(col, chooserMode(), v / (chooserMode() == ChooserHue ? 360.0 : 255.0));
1600  _setColor(col);
1601 }
1602 
1603 void KColorDialog::KColorDialogPrivate::slotAChanged(int value)
1604 {
1605  QColor col = selColor;
1606  col.setAlpha(value);
1607  _setColor(col);
1608 }
1609 
1610 void KColorDialog::KColorDialogPrivate::slotColorSelected(const QColor &color)
1611 {
1612  _setColor(color);
1613 }
1614 
1615 void KColorDialog::KColorDialogPrivate::slotAddToCustomColors()
1616 {
1617  table->addToCustomColors(selColor);
1618 }
1619 
1620 void KColorDialog::KColorDialogPrivate::slotColorSelected(const QColor &color, const QString &name)
1621 {
1622  _setColor(color, name);
1623 }
1624 
1625 void KColorDialog::KColorDialogPrivate::slotColorDoubleClicked
1626 (
1627  const QColor & color,
1628  const QString & name
1629 )
1630 {
1631  _setColor(color, name);
1632  q->accept();
1633 }
1634 
1635 void KColorDialog::KColorDialogPrivate::_setColor(const QColor &color, const QString &name)
1636 {
1637  if (color.isValid()) {
1638  if (cbDefaultColor && cbDefaultColor->isChecked())
1639  cbDefaultColor->setChecked(false);
1640  selColor = color;
1641  } else {
1642  if (cbDefaultColor && cbDefaultColor->isChecked())
1643  cbDefaultColor->setChecked(true);
1644  selColor = defaultColor;
1645  }
1646 
1647  showColor(selColor, name);
1648 
1649  emit q->colorSelected(selColor);
1650 }
1651 
1652 // show but don't set into selColor, nor emit colorSelected
1653 void KColorDialog::KColorDialogPrivate::showColor(const QColor &color, const QString &name)
1654 {
1655  bRecursion = true;
1656 
1657  if (name.isEmpty())
1658  colorName->setText(i18n("-unnamed-"));
1659  else
1660  colorName->setText(name);
1661 
1662  patch->setColor(color);
1663 
1664  setRgbEdit(color);
1665  setHsvEdit(color);
1666  setHtmlEdit(color);
1667  aedit->setValue(color.alpha());
1668 
1669  QColor rgbColor = color.toRgb();
1670  bool ltr = q->layoutDirection() == Qt::LeftToRight;
1671  rgbColor.setAlpha(ltr ? 0 : 255);
1672  alphaSelector->setFirstColor(rgbColor);
1673  rgbColor.setAlpha(ltr ? 255 : 0);
1674  alphaSelector->setSecondColor(rgbColor);
1675  alphaSelector->setValue(color.alpha());
1676 
1677  KColorChooserMode xMode = chooserXMode(chooserMode());
1678  KColorChooserMode yMode = chooserYMode(chooserMode());
1679  int xValue = qRound(getComponentValue(color, xMode) * (xMode == ChooserHue ? 360.0 : 255.0));
1680  int yValue = qRound(getComponentValue(color, yMode) * (yMode == ChooserHue ? 360.0 : 255.0));
1681  int value = qRound(getComponentValue(color, chooserMode()) * (chooserMode() == ChooserHue ? 360.0 : 255.0));
1682  hsSelector->setValues(xValue, yValue);
1683  valuePal->setValue(value);
1684 
1685  bool blocked = valuePal->blockSignals(true);
1686 
1687  valuePal->setHue(color.hue());
1688  valuePal->setSaturation(color.saturation());
1689  valuePal->setColorValue(color.value());
1690  valuePal->updateContents();
1691  valuePal->blockSignals(blocked);
1692  valuePal->update();
1693 
1694  blocked = hsSelector->blockSignals(true);
1695 
1696  hsSelector->setHue(color.hue());
1697  hsSelector->setSaturation(color.saturation());
1698  hsSelector->setColorValue(color.value());
1699  hsSelector->updateContents();
1700  hsSelector->blockSignals(blocked);
1701  hsSelector->update();
1702 
1703  bRecursion = false;
1704 }
1705 
1706 
1707 
1708 void
1709 KColorDialog::KColorDialogPrivate::slotColorPicker()
1710 {
1711  bColorPicking = true;
1712 #ifdef Q_WS_X11
1713  filter = new KCDPickerFilter(q);
1714  kapp->installX11EventFilter(filter);
1715 #endif
1716  q->grabMouse(Qt::CrossCursor);
1717  q->grabKeyboard();
1718 }
1719 
1720 void
1721 KColorDialog::mouseMoveEvent(QMouseEvent *e)
1722 {
1723  if (d->bColorPicking) {
1724  d->_setColor(grabColor(e->globalPos()));
1725  return;
1726  }
1727 
1728  KDialog::mouseMoveEvent(e);
1729 }
1730 
1731 void
1732 KColorDialog::mouseReleaseEvent(QMouseEvent *e)
1733 {
1734  if (d->bColorPicking) {
1735  d->bColorPicking = false;
1736 #ifdef Q_WS_X11
1737  kapp->removeX11EventFilter(d->filter);
1738  delete d->filter; d->filter = 0;
1739 #endif
1740  releaseMouse();
1741  releaseKeyboard();
1742  d->_setColor(grabColor(e->globalPos()));
1743  return;
1744  }
1745  KDialog::mouseReleaseEvent(e);
1746 }
1747 
1748 QColor
1749 KColorDialog::grabColor(const QPoint &p)
1750 {
1751 #ifdef Q_WS_X11
1752  // we use the X11 API directly in this case as we are not getting back a valid
1753  // return from QPixmap::grabWindow in the case where the application is using
1754  // an argb visual
1755  if( !qApp->desktop()->geometry().contains( p ))
1756  return QColor();
1757  Window root = RootWindow(QX11Info::display(), QX11Info::appScreen());
1758  XImage *ximg = XGetImage(QX11Info::display(), root, p.x(), p.y(), 1, 1, -1, ZPixmap);
1759  unsigned long xpixel = XGetPixel(ximg, 0, 0);
1760  XDestroyImage(ximg);
1761  XColor xcol;
1762  xcol.pixel = xpixel;
1763  xcol.flags = DoRed | DoGreen | DoBlue;
1764  XQueryColor(QX11Info::display(),
1765  DefaultColormap(QX11Info::display(), QX11Info::appScreen()),
1766  &xcol);
1767  return QColor::fromRgbF(xcol.red / 65535.0, xcol.green / 65535.0, xcol.blue / 65535.0);
1768 #else
1769  QWidget *desktop = QApplication::desktop();
1770  QPixmap pm = QPixmap::grabWindow(desktop->winId(), p.x(), p.y(), 1, 1);
1771  QImage i = pm.toImage();
1772  return i.pixel(0, 0);
1773 #endif
1774 }
1775 
1776 void
1777 KColorDialog::keyPressEvent(QKeyEvent *e)
1778 {
1779  if (d->bColorPicking) {
1780  if (e->key() == Qt::Key_Escape) {
1781  d->bColorPicking = false;
1782 #ifdef Q_WS_X11
1783  kapp->removeX11EventFilter(d->filter);
1784  delete d->filter; d->filter = 0;
1785 #endif
1786  releaseMouse();
1787  releaseKeyboard();
1788  }
1789  e->accept();
1790  return;
1791  }
1792  KDialog::keyPressEvent(e);
1793 }
1794 
1795 void KColorDialog::KColorDialogPrivate::setRgbEdit(const QColor &col)
1796 {
1797  if (bEditRgb) return;
1798  int r, g, b;
1799  col.getRgb(&r, &g, &b);
1800 
1801  redit->setValue(r);
1802  gedit->setValue(g);
1803  bedit->setValue(b);
1804 }
1805 
1806 void KColorDialog::KColorDialogPrivate::setHtmlEdit(const QColor &col)
1807 {
1808  if (bEditHtml) return;
1809  int r, g, b;
1810  col.getRgb(&r, &g, &b);
1811  QString num;
1812 
1813  num.sprintf("#%02X%02X%02X", r, g, b);
1814  htmlName->setText(num);
1815 }
1816 
1817 
1818 void KColorDialog::KColorDialogPrivate::setHsvEdit(const QColor &col)
1819 {
1820  if (bEditHsv) return;
1821  int h, s, v;
1822  col.getHsv(&h, &s, &v);
1823 
1824  hedit->setValue(h);
1825  sedit->setValue(s);
1826  vedit->setValue(v);
1827 }
1828 
1829 #include "kcolordialog.moc"
1830 #include "kcolordialog_p.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Fri Dec 7 2012 16:04:37 by doxygen 1.8.1 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDEUI

Skip menu "KDEUI"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs-4.8.5 API Reference

Skip menu "kdelibs-4.8.5 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal