File indexing completed on 2024-04-28 11:36:26
0001 /* This file is part of the KDE libraries 0002 Copyright (C) 1997 Martin Jones (mjones@kde.org) 0003 Copyright (C) 2007 Roberto Raggi (roberto@kdevelop.org) 0004 0005 This library is free software; you can redistribute it and/or 0006 modify it under the terms of the GNU Library General Public 0007 License as published by the Free Software Foundation; either 0008 version 2 of the License, or (at your option) any later version. 0009 0010 This library is distributed in the hope that it will be useful, 0011 but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0013 Library General Public License for more details. 0014 0015 You should have received a copy of the GNU Library General Public License 0016 along with this library; see the file COPYING.LIB. If not, write to 0017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0018 Boston, MA 02110-1301, USA. 0019 */ 0020 //----------------------------------------------------------------------------- 0021 // KDE color selection dialog. 0022 // 0023 // 1999-09-27 Espen Sand <espensa@online.no> 0024 // KColorDialog is now subclassed from KDialog. I have also extended 0025 // KColorDialog::getColor() so that it contains a parent argument. This 0026 // improves centering capability. 0027 // 0028 // layout management added Oct 1997 by Mario Weilguni 0029 // <mweilguni@sime.com> 0030 // 0031 0032 #include "kcolordialog.h" 0033 #include "kcolordialog_p.h" 0034 0035 #include <config-kdelibs4support.h> 0036 0037 #include <stdio.h> 0038 #include <stdlib.h> 0039 0040 #include <QButtonGroup> 0041 #include <QCheckBox> 0042 #include <QDesktopWidget> 0043 #include <QRadioButton> 0044 #include <QFrame> 0045 #include <qdrawutil.h> 0046 #include <QActionEvent> 0047 #include <QFile> 0048 #include <QHeaderView> 0049 #include <QImage> 0050 #include <QHBoxLayout> 0051 #include <QDrag> 0052 #include <QStyledItemDelegate> 0053 #include <QLabel> 0054 #include <QLayout> 0055 #include <QPainter> 0056 #include <QPushButton> 0057 #include <QScrollBar> 0058 #include <QTimer> 0059 #include <QListWidget> 0060 #include <QApplication> 0061 #include <QSpinBox> 0062 0063 #include <kcombobox.h> 0064 #include <kconfig.h> 0065 #include <klineedit.h> 0066 #include <klocalizedstring.h> 0067 #include <kmessagebox.h> 0068 #include <kseparator.h> 0069 #include <qstandardpaths.h> 0070 #include <kcolorcollection.h> 0071 #include <kcolorutils.h> 0072 0073 #include "kcolormimedata.h" 0074 #include <kdebug.h> 0075 0076 #include "kcolorchoosermode_p.h" 0077 #include "kcolorhelpers_p.h" 0078 #include "kselector.h" 0079 #include "kcolorvalueselector.h" 0080 #include "khuesaturationselect.h" 0081 #include "kxyselector.h" 0082 #include <kconfiggroup.h> 0083 #include <ksharedconfig.h> 0084 0085 #if HAVE_X11 0086 #include <X11/Xlib.h> 0087 #include <X11/Xutil.h> 0088 #include <QX11Info> 0089 #include <fixx11h.h> 0090 #endif 0091 0092 using namespace KDEPrivate; 0093 0094 using KDEPrivate::KColorTable; 0095 0096 struct ColorCollectionNameType { 0097 const char *const m_fileName; 0098 const char *const m_displayName; 0099 }; 0100 0101 static const ColorCollectionNameType colorCollectionName[] = { 0102 { "Recent_Colors", I18N_NOOP2("palette name", "* Recent Colors *") }, 0103 { "Custom_Colors", I18N_NOOP2("palette name", "* Custom Colors *") }, 0104 { "40.colors", I18N_NOOP2("palette name", "Forty Colors") }, 0105 { "Oxygen.colors", I18N_NOOP2("palette name", "Oxygen Colors") }, 0106 { "Rainbow.colors", I18N_NOOP2("palette name", "Rainbow Colors") }, 0107 { "Royal.colors", I18N_NOOP2("palette name", "Royal Colors") }, 0108 { "Web.colors", I18N_NOOP2("palette name", "Web Colors") }, 0109 { nullptr, nullptr } // end of data 0110 }; 0111 0112 enum ColorCollectionIndices { 0113 recentColorIndex, 0114 customColorIndex, 0115 fortyColorIndex 0116 }; 0117 0118 //----------------------------------------------------------------------------- 0119 0120 class Q_DECL_HIDDEN KColorCells::KColorCellsPrivate 0121 { 0122 public: 0123 KColorCellsPrivate(KColorCells *q): q(q) 0124 { 0125 inMouse = false; 0126 selected = -1; 0127 shade = false; 0128 } 0129 0130 KColorCells *q; 0131 QPoint mousePos; 0132 int selected; 0133 bool shade; 0134 bool inMouse; 0135 }; 0136 0137 class KColorCellsItemDelegate: public QStyledItemDelegate 0138 { 0139 public: 0140 KColorCellsItemDelegate(KColorCells *parent): QStyledItemDelegate(parent) {} 0141 void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override 0142 { 0143 QStyleOptionViewItem opt(option); 0144 initStyleOption(&opt, index); 0145 0146 //Get the current cell color 0147 QColor backgroundColor = index.data(Qt::BackgroundRole).value<QColor>(); 0148 if (backgroundColor.isValid()) { 0149 //Paint the general background 0150 painter->fillRect(opt.rect, backgroundColor); 0151 //Paint the selection mark (circle) 0152 if (opt.state & QStyle::State_Selected) { 0153 //Use black or white, depending on the contrast 0154 QColor color = QColor(0, 0, 0, 220); 0155 if (KColorUtils::contrastRatio(color, backgroundColor) < 5) { 0156 color = QColor(255, 255, 255, 220); 0157 } 0158 //Draw the selection (radiobutton-like) circle 0159 painter->save(); 0160 painter->setRenderHint(QPainter::Antialiasing, true); 0161 painter->setRenderHint(QPainter::HighQualityAntialiasing, true); 0162 painter->setPen(QPen(color, 1.2, Qt::SolidLine)); 0163 painter->setBrush(QBrush()); 0164 painter->drawEllipse(opt.rect.adjusted(2, 2, -2, -2)); 0165 painter->restore(); 0166 } 0167 } else { 0168 //Paint the "X" (missing) cross on empty background color 0169 backgroundColor = opt.palette.color(QPalette::Window); 0170 painter->fillRect(opt.rect, backgroundColor); 0171 painter->save(); 0172 QColor crossColor = qGray(backgroundColor.rgb()) > 192 ? backgroundColor.darker(106) : 0173 backgroundColor.lighter(106); 0174 painter->setPen(QPen(crossColor, 1.5)); 0175 painter->drawLine(opt.rect.topLeft(), opt.rect.bottomRight()); 0176 painter->drawLine(opt.rect.topRight(), opt.rect.bottomLeft()); 0177 painter->restore(); 0178 } 0179 } 0180 }; 0181 0182 KColorCells::KColorCells(QWidget *parent, int rows, int cols) 0183 : QTableWidget(parent), d(new KColorCellsPrivate(this)) 0184 { 0185 setItemDelegate(new KColorCellsItemDelegate(this)); 0186 0187 setFrameShape(QFrame::NoFrame); 0188 d->shade = true; 0189 setRowCount(rows); 0190 setColumnCount(cols); 0191 0192 verticalHeader()->hide(); 0193 horizontalHeader()->hide(); 0194 0195 d->selected = 0; 0196 d->inMouse = false; 0197 0198 // Drag'n'Drop 0199 setAcceptDrops(true); 0200 0201 setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 0202 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 0203 viewport()->setBackgroundRole(QPalette::Window); 0204 setBackgroundRole(QPalette::Window); 0205 0206 setSelectionMode(QAbstractItemView::SingleSelection); 0207 setDragEnabled(false); 0208 } 0209 0210 KColorCells::~KColorCells() 0211 { 0212 delete d; 0213 } 0214 0215 QColor KColorCells::color(int index) const 0216 { 0217 QTableWidgetItem *tmpItem = item(index / columnCount(), index % columnCount()); 0218 0219 if (tmpItem != nullptr) { 0220 return tmpItem->data(Qt::BackgroundRole).value<QColor>(); 0221 } 0222 0223 return QColor(); 0224 } 0225 0226 int KColorCells::count() const 0227 { 0228 return rowCount() * columnCount(); 0229 } 0230 0231 void KColorCells::setShading(bool _shade) 0232 { 0233 d->shade = _shade; 0234 } 0235 0236 bool KColorCells::shading() const 0237 { 0238 return d->shade; 0239 } 0240 0241 void KColorCells::setAcceptDrags(bool _acceptDrags) 0242 { 0243 this->setDragEnabled(_acceptDrags); 0244 } 0245 0246 bool KColorCells::acceptDrags() const 0247 { 0248 return this->dragEnabled(); 0249 } 0250 0251 void KColorCells::setSelected(int index) 0252 { 0253 Q_ASSERT(index >= 0 && index < count()); 0254 0255 d->selected = index; 0256 } 0257 0258 int KColorCells::selectedIndex() const 0259 { 0260 return d->selected; 0261 } 0262 0263 void KColorCells::setColor(int column, const QColor &color) 0264 { 0265 const int tableRow = column / columnCount(); 0266 const int tableColumn = column % columnCount(); 0267 0268 Q_ASSERT(tableRow >= 0 && tableRow < rowCount()); 0269 Q_ASSERT(tableColumn >= 0 && tableColumn < columnCount()); 0270 0271 QTableWidgetItem *tableItem = item(tableRow, tableColumn); 0272 0273 if (tableItem == nullptr) { 0274 tableItem = new QTableWidgetItem(); 0275 setItem(tableRow, tableColumn, tableItem); 0276 } 0277 0278 tableItem->setData(Qt::BackgroundRole, color); 0279 } 0280 0281 /*void KColorCells::paintCell( QPainter *painter, int row, int col ) 0282 { 0283 painter->setRenderHint( QPainter::Antialiasing , true ); 0284 0285 QBrush brush; 0286 int w = 1; 0287 0288 if (shade) 0289 { 0290 qDrawShadePanel( painter, 1, 1, cellWidth()-2, 0291 cellHeight()-2, palette(), true, 1, &brush ); 0292 w = 2; 0293 } 0294 QColor color = colors[ row * numCols() + col ]; 0295 if (!color.isValid()) 0296 { 0297 if (!shade) return; 0298 color = palette().color(backgroundRole()); 0299 } 0300 0301 const QRect colorRect( w, w, cellWidth()-w*2, cellHeight()-w*2 ); 0302 painter->fillRect( colorRect, color ); 0303 0304 if ( row * numCols() + col == selected ) { 0305 painter->setPen( qGray(color.rgb())>=127 ? Qt::black : Qt::white ); 0306 painter->drawLine( colorRect.topLeft(), colorRect.bottomRight() ); 0307 painter->drawLine( colorRect.topRight(), colorRect.bottomLeft() ); 0308 } 0309 }*/ 0310 0311 void KColorCells::resizeEvent(QResizeEvent *) 0312 { 0313 // According to the Qt doc: 0314 // If you need to set the width of a given column to a fixed value, call 0315 // QHeaderView::resizeSection() on the table's {horizontal,vertical} 0316 // header. 0317 // Therefore we iterate over each row and column and set the header section 0318 // size, as the sizeHint does indeed appear to be ignored in favor of a 0319 // minimum size that is larger than what we want. 0320 for (int index = 0; index < columnCount(); index++) { 0321 horizontalHeader()->resizeSection(index, sizeHintForColumn(index)); 0322 } 0323 for (int index = 0; index < rowCount(); index++) { 0324 verticalHeader()->resizeSection(index, sizeHintForRow(index)); 0325 } 0326 } 0327 0328 int KColorCells::sizeHintForColumn(int /*column*/) const 0329 { 0330 return width() / columnCount(); 0331 } 0332 0333 int KColorCells::sizeHintForRow(int /*row*/) const 0334 { 0335 return height() / rowCount(); 0336 } 0337 0338 void KColorCells::mousePressEvent(QMouseEvent *e) 0339 { 0340 d->inMouse = true; 0341 d->mousePos = e->pos(); 0342 0343 QTableWidget::mousePressEvent(e); 0344 } 0345 0346 int KColorCells::positionToCell(const QPoint &pos, bool ignoreBorders) const 0347 { 0348 //TODO ignoreBorders not yet handled 0349 Q_UNUSED(ignoreBorders) 0350 0351 QTableWidgetItem *tableItem = itemAt(pos); 0352 0353 if (!tableItem) { 0354 return -1; 0355 } 0356 0357 const int itemRow = row(tableItem); 0358 const int itemColumn = column(tableItem); 0359 int cell = itemRow * columnCount() + itemColumn; 0360 0361 /*if (!ignoreBorders) 0362 { 0363 int border = 2; 0364 int x = pos.x() - col * cellWidth(); 0365 int y = pos.y() - row * cellHeight(); 0366 if ( (x < border) || (x > cellWidth()-border) || 0367 (y < border) || (y > cellHeight()-border)) 0368 return -1; 0369 }*/ 0370 0371 return cell; 0372 } 0373 0374 void KColorCells::mouseMoveEvent(QMouseEvent *e) 0375 { 0376 if (this->dragEnabled() || this->acceptDrops()) { 0377 if (!(e->buttons() & Qt::LeftButton)) { 0378 return; 0379 } 0380 0381 if (d->inMouse) { 0382 int delay = QApplication::startDragDistance(); 0383 if (e->x() > d->mousePos.x() + delay || e->x() < d->mousePos.x() - delay || 0384 e->y() > d->mousePos.y() + delay || e->y() < d->mousePos.y() - delay) { 0385 // Drag color object 0386 QTableWidgetItem *tableItem = itemAt(d->mousePos); 0387 0388 if (tableItem) { 0389 QVariant var = tableItem->data(Qt::BackgroundRole); 0390 QColor tmpCol = var.value<QColor>(); 0391 if (tmpCol.isValid()) { 0392 KColorMimeData::createDrag(tmpCol, this)->start(); 0393 } 0394 } 0395 } 0396 } 0397 } else { 0398 QTableWidget::mouseMoveEvent(e); 0399 } 0400 } 0401 0402 void KColorCells::dragEnterEvent(QDragEnterEvent *event) 0403 { 0404 kDebug() << "KColorCells::dragEnterEvent() acceptDrags=" 0405 << this->dragEnabled() 0406 << " canDecode=" << KColorMimeData::canDecode(event->mimeData()) 0407 << endl; 0408 event->setAccepted(this->dragEnabled() && KColorMimeData::canDecode(event->mimeData())); 0409 } 0410 0411 // Reimplemented to override QTableWidget's override. Else dropping doesn't work. 0412 void KColorCells::dragMoveEvent(QDragMoveEvent *event) 0413 { 0414 kDebug() << "KColorCells::dragMoveEvent() acceptDrags=" 0415 << this->dragEnabled() 0416 << " canDecode=" << KColorMimeData::canDecode(event->mimeData()) 0417 << endl; 0418 event->setAccepted(this->dragEnabled() && KColorMimeData::canDecode(event->mimeData())); 0419 } 0420 0421 void KColorCells::dropEvent(QDropEvent *event) 0422 { 0423 QColor c = KColorMimeData::fromMimeData(event->mimeData()); 0424 0425 kDebug() << "KColorCells::dropEvent() color.isValid=" << c.isValid(); 0426 if (c.isValid()) { 0427 QTableWidgetItem *tableItem = itemAt(event->pos()); 0428 0429 if (tableItem) { 0430 tableItem->setData(Qt::BackgroundRole, c); 0431 } 0432 } 0433 } 0434 0435 void KColorCells::mouseReleaseEvent(QMouseEvent *e) 0436 { 0437 if (selectionMode() != QAbstractItemView::NoSelection) { 0438 int cell = positionToCell(d->mousePos); 0439 int currentCell = positionToCell(e->pos()); 0440 0441 // If we release the mouse in another cell and we don't have 0442 // a drag we should ignore this event. 0443 if (currentCell != cell) { 0444 cell = -1; 0445 } 0446 0447 if ((cell != -1) && (d->selected != cell)) { 0448 d->selected = cell; 0449 0450 const int newRow = cell / columnCount(); 0451 const int newColumn = cell % columnCount(); 0452 0453 clearSelection(); // we do not want old violet selected cells 0454 0455 item(newRow, newColumn)->setSelected(true); 0456 } 0457 0458 d->inMouse = false; 0459 if (cell != -1) { 0460 emit colorSelected(cell, color(cell)); 0461 } 0462 } 0463 0464 QTableWidget::mouseReleaseEvent(e); 0465 } 0466 0467 void KColorCells::mouseDoubleClickEvent(QMouseEvent * /*e*/) 0468 { 0469 int cell = positionToCell(d->mousePos); 0470 0471 if (cell != -1) { 0472 emit colorDoubleClicked(cell, color(cell)); 0473 } 0474 } 0475 0476 //----------------------------------------------------------------------------- 0477 0478 class Q_DECL_HIDDEN KColorPatch::KColorPatchPrivate 0479 { 0480 public: 0481 KColorPatchPrivate(KColorPatch *q): q(q) {} 0482 0483 KColorPatch *q; 0484 QColor color; 0485 }; 0486 0487 KColorPatch::KColorPatch(QWidget *parent) : QFrame(parent), d(new KColorPatchPrivate(this)) 0488 { 0489 setFrameStyle(QFrame::StyledPanel | QFrame::Sunken); 0490 setAcceptDrops(true); 0491 setMinimumSize(12, 12); 0492 } 0493 0494 KColorPatch::~KColorPatch() 0495 { 0496 delete d; 0497 } 0498 0499 QColor KColorPatch::color() const 0500 { 0501 return d->color; 0502 } 0503 0504 void KColorPatch::setColor(const QColor &col) 0505 { 0506 d->color = col.toRgb(); 0507 0508 update(); 0509 } 0510 0511 void KColorPatch::paintEvent(QPaintEvent *pe) 0512 { 0513 QFrame::paintEvent(pe); 0514 QPainter painter(this); 0515 0516 fillOpaqueRect(&painter, contentsRect(), d->color); 0517 } 0518 0519 void KColorPatch::mouseMoveEvent(QMouseEvent *e) 0520 { 0521 // Drag color object 0522 if (!(e->buttons() & Qt::LeftButton)) { 0523 return; 0524 } 0525 KColorMimeData::createDrag(d->color, this)->start(); 0526 } 0527 0528 void KColorPatch::dragEnterEvent(QDragEnterEvent *event) 0529 { 0530 event->setAccepted(KColorMimeData::canDecode(event->mimeData())); 0531 } 0532 0533 void KColorPatch::dropEvent(QDropEvent *event) 0534 { 0535 QColor c = KColorMimeData::fromMimeData(event->mimeData()); 0536 if (c.isValid()) { 0537 setColor(c); 0538 emit colorChanged(c); 0539 } 0540 } 0541 0542 class KColorTable::KColorTablePrivate 0543 { 0544 public: 0545 KColorTablePrivate(KColorTable *q): q(q) {} 0546 0547 void slotColorCellSelected(int index, const QColor &); 0548 void slotColorCellDoubleClicked(int index, const QColor &); 0549 void slotColorTextSelected(const QString &colorText); 0550 void slotSetColors(const QString &_collectionName); 0551 void slotShowNamedColorReadError(void); 0552 0553 KColorTable *q; 0554 QString i18n_namedColors; 0555 KComboBox *combo; 0556 KColorCells *cells; 0557 QScrollArea *sv; 0558 QListWidget *mNamedColorList; 0559 KColorCollection *mPalette; 0560 int mMinWidth; 0561 int mCols; 0562 QMap<QString, QColor> m_namedColorMap; 0563 }; 0564 0565 KColorTable::KColorTable(QWidget *parent, int minWidth, int cols) 0566 : QWidget(parent), d(new KColorTablePrivate(this)) 0567 { 0568 d->cells = nullptr; 0569 d->mPalette = nullptr; 0570 d->mMinWidth = minWidth; 0571 d->mCols = cols; 0572 d->i18n_namedColors = i18n("Named Colors"); 0573 0574 QStringList diskPaletteList = KColorCollection::installedCollections(); 0575 QStringList paletteList; 0576 0577 // We must replace the untranslated file names by translate names (of course only for KDE's standard palettes) 0578 for (int i = 0; colorCollectionName[i].m_fileName; ++i) { 0579 diskPaletteList.removeAll(colorCollectionName[i].m_fileName); 0580 paletteList.append(i18nc("palette name", colorCollectionName[i].m_displayName)); 0581 } 0582 paletteList += diskPaletteList; 0583 paletteList.append(d->i18n_namedColors); 0584 0585 QVBoxLayout *layout = new QVBoxLayout(this); 0586 0587 d->combo = new KComboBox(this); 0588 d->combo->setEditable(false); 0589 d->combo->addItems(paletteList); 0590 layout->addWidget(d->combo); 0591 0592 d->sv = new QScrollArea(this); 0593 QSize cellSize = QSize(d->mMinWidth, 120); 0594 d->sv->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 0595 d->sv->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); 0596 QSize minSize = QSize(d->sv->verticalScrollBar()->sizeHint().width(), 0); 0597 minSize += QSize(d->sv->frameWidth() * 2, 0); 0598 minSize += QSize(cellSize); 0599 d->sv->setFixedSize(minSize); 0600 layout->addWidget(d->sv); 0601 0602 d->mNamedColorList = new QListWidget(this); 0603 d->mNamedColorList->setObjectName("namedColorList"); 0604 d->mNamedColorList->setFixedSize(minSize); 0605 d->mNamedColorList->hide(); 0606 layout->addWidget(d->mNamedColorList); 0607 connect(d->mNamedColorList, SIGNAL(currentTextChanged(QString)), 0608 this, SLOT(slotColorTextSelected(QString))); 0609 0610 setFixedSize(sizeHint()); 0611 connect(d->combo, SIGNAL(activated(QString)), 0612 this, SLOT(slotSetColors(QString))); 0613 } 0614 0615 KColorTable::~KColorTable() 0616 { 0617 delete d->mPalette; 0618 delete d; 0619 } 0620 0621 QString 0622 KColorTable::name() const 0623 { 0624 return d->combo->currentText(); 0625 } 0626 0627 static const char *const *namedColorFilePath(void) 0628 { 0629 // 0630 // 2000-02-05 Espen Sand. 0631 // Add missing filepaths here. Make sure the last entry is 0, 0! 0632 // 0633 // 2009-06-16 Pino Toscano 0634 // 0635 // You can specify either absolute paths or relative locations. 0636 // Relative locations are relative to GenericDataLocation (XDG_DATA_DIRS). 0637 // 0638 static const char *const path[] = { 0639 #if HAVE_X11 0640 #ifdef X11_RGBFILE 0641 X11_RGBFILE, 0642 #endif 0643 "/usr/share/X11/rgb.txt", 0644 "/usr/X11R6/lib/X11/rgb.txt", 0645 "/usr/openwin/lib/X11/rgb.txt", // for Solaris. 0646 #else /* systems without X11 */ 0647 "kf5/kdeui/rgb.txt", 0648 #endif 0649 nullptr 0650 }; 0651 return path; 0652 } 0653 0654 void 0655 KColorTable::readNamedColor(void) 0656 { 0657 if (d->mNamedColorList->count() != 0) { 0658 return; // Strings already present 0659 } 0660 0661 // 0662 // Code somewhat inspired by KColorCollection. 0663 // 0664 0665 const char *const *path = namedColorFilePath(); 0666 for (int i = 0; path[i]; ++i) { 0667 QString file; 0668 if (path[i][0] != '/') { // relative path 0669 file = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QString::fromLatin1(path[i])); 0670 if (file.isEmpty()) { 0671 continue; 0672 } 0673 } else { // absolute path 0674 file = QString::fromLatin1(path[i]); 0675 } 0676 0677 QFile paletteFile(file); 0678 if (!paletteFile.open(QIODevice::ReadOnly)) { 0679 continue; 0680 } 0681 0682 QByteArray line; 0683 QStringList list; 0684 while (!paletteFile.atEnd()) { 0685 line = paletteFile.readLine(); 0686 0687 int red, green, blue; 0688 int pos = 0; 0689 0690 if (sscanf(line, "%d %d %d%n", &red, &green, &blue, &pos) == 3) { 0691 // 0692 // Remove duplicates. Every name with a space and every name 0693 // that start with "gray". 0694 // 0695 QString name = line.mid(pos).trimmed(); 0696 QByteArray s1 = line.mid(pos); 0697 if (name.isNull() || name.indexOf(' ') != -1 || 0698 name.indexOf("gray") != -1 || name.indexOf("grey") != -1) { 0699 continue; 0700 } 0701 0702 const QColor color(red, green, blue); 0703 if (color.isValid()) { 0704 const QString colorName(i18nc("color", name.toLatin1().data())); 0705 list.append(colorName); 0706 d->m_namedColorMap[ colorName ] = color; 0707 } 0708 } 0709 } 0710 0711 list.sort(); 0712 d->mNamedColorList->addItems(list); 0713 break; 0714 } 0715 0716 if (d->mNamedColorList->count() == 0) { 0717 // 0718 // Give the error dialog box a chance to center above the 0719 // widget (or dialog). If we had displayed it now we could get a 0720 // situation where the (modal) error dialog box pops up first 0721 // preventing the real dialog to become visible until the 0722 // error dialog box is removed (== bad UI). 0723 // 0724 QTimer::singleShot(10, this, SLOT(slotShowNamedColorReadError())); 0725 } 0726 } 0727 0728 void 0729 KColorTable::KColorTablePrivate::slotShowNamedColorReadError(void) 0730 { 0731 if (mNamedColorList->count() == 0) { 0732 QString pathMsg; 0733 int pathCount = 0; 0734 0735 const char *const *path = namedColorFilePath(); 0736 for (int i = 0; path[i]; i += 2, ++pathCount) { 0737 if (path[i + 1]) { 0738 pathMsg += QLatin1String(path[i + 1]) + ", " + QString::fromLatin1(path[i]); 0739 } else { 0740 pathMsg += QLatin1String(path[i]); 0741 } 0742 pathMsg += '\n'; 0743 } 0744 0745 QString finalMsg = i18ncp("%1 is the number of paths, %2 is the list of paths (with newlines between them)", 0746 "Unable to read X11 RGB color strings. The following " 0747 "file location was examined:\n%2", 0748 "Unable to read X11 RGB color strings. The following " 0749 "file locations were examined:\n%2", 0750 pathCount, pathMsg); 0751 0752 KMessageBox::error(q, finalMsg); 0753 } 0754 } 0755 0756 // 0757 // 2000-02-12 Espen Sand 0758 // Set the color in two steps. The setColors() slot will not emit a signal 0759 // with the current color setting. The reason is that setColors() is used 0760 // by the color selector dialog on startup. In the color selector dialog 0761 // we normally want to display a startup color which we specify 0762 // when the dialog is started. The slotSetColors() slot below will 0763 // set the palette and then use the information to emit a signal with the 0764 // new color setting. It is only used by the combobox widget. 0765 // 0766 void 0767 KColorTable::KColorTablePrivate::slotSetColors(const QString &_collectionName) 0768 { 0769 q->setColors(_collectionName); 0770 if (mNamedColorList->count() && mNamedColorList->isVisible()) { 0771 int item = mNamedColorList->currentRow(); 0772 mNamedColorList->setCurrentRow(item < 0 ? 0 : item); 0773 slotColorTextSelected(mNamedColorList->currentItem()->text()); 0774 } else { 0775 slotColorCellSelected(0, QColor()); // FIXME: We need to save the current value!! 0776 } 0777 } 0778 0779 void 0780 KColorTable::setColors(const QString &_collectionName) 0781 { 0782 QString collectionName(_collectionName); 0783 0784 if (d->combo->currentText() != collectionName) { 0785 bool found = false; 0786 for (int i = 0; i < d->combo->count(); i++) { 0787 if (d->combo->itemText(i) == collectionName) { 0788 d->combo->setCurrentIndex(i); 0789 found = true; 0790 break; 0791 } 0792 } 0793 if (!found) { 0794 d->combo->addItem(collectionName); 0795 d->combo->setCurrentIndex(d->combo->count() - 1); 0796 } 0797 } 0798 0799 // We must again find the file name of the palette from the eventual translation 0800 for (int i = 0; colorCollectionName[i].m_fileName; ++i) { 0801 if (collectionName == i18nc("palette name", colorCollectionName[i].m_displayName)) { 0802 collectionName = colorCollectionName[i].m_fileName; 0803 break; 0804 } 0805 } 0806 0807 // 0808 // 2000-02-12 Espen Sand 0809 // The palette mode "i18n_namedColors" does not use the KColorCollection 0810 // class. In fact, 'mPalette' and 'cells' are 0 when in this mode. The reason 0811 // for this is maninly that KColorCollection reads from and writes to files 0812 // using "locate()". The colors used in "i18n_namedColors" mode comes from 0813 // the X11 diretory and is not writable. I don't think this fit in 0814 // KColorCollection. 0815 // 0816 if (!d->mPalette || d->mPalette->name() != collectionName) { 0817 if (collectionName == d->i18n_namedColors) { 0818 d->sv->hide(); 0819 d->mNamedColorList->show(); 0820 readNamedColor(); 0821 0822 delete d->cells; d->cells = nullptr; 0823 delete d->mPalette; d->mPalette = nullptr; 0824 } else { 0825 d->mNamedColorList->hide(); 0826 d->sv->show(); 0827 0828 delete d->cells; 0829 delete d->mPalette; 0830 d->mPalette = new KColorCollection(collectionName); 0831 int rows = (d->mPalette->count() + d->mCols - 1) / d->mCols; 0832 if (rows < 1) { 0833 rows = 1; 0834 } 0835 d->cells = new KColorCells(d->sv->viewport(), rows, d->mCols); 0836 d->cells->setShading(false); 0837 d->cells->setAcceptDrags(false); 0838 QSize cellSize = QSize(d->mMinWidth, d->mMinWidth * rows / d->mCols); 0839 d->cells->setFixedSize(cellSize); 0840 for (int i = 0; i < d->mPalette->count(); i++) { 0841 d->cells->setColor(i, d->mPalette->color(i)); 0842 } 0843 connect(d->cells, SIGNAL(colorSelected(int,QColor)), 0844 SLOT(slotColorCellSelected(int,QColor))); 0845 connect(d->cells, SIGNAL(colorDoubleClicked(int,QColor)), 0846 SLOT(slotColorCellDoubleClicked(int,QColor))); 0847 d->sv->setWidget(d->cells); 0848 d->cells->show(); 0849 0850 //d->sv->updateScrollBars(); 0851 } 0852 } 0853 } 0854 0855 void 0856 KColorTable::KColorTablePrivate::slotColorCellSelected(int index, const QColor & /*color*/) 0857 { 0858 if (!mPalette || (index >= mPalette->count())) { 0859 return; 0860 } 0861 emit q->colorSelected(mPalette->color(index), mPalette->name(index)); 0862 } 0863 0864 void 0865 KColorTable::KColorTablePrivate::slotColorCellDoubleClicked(int index, const QColor & /*color*/) 0866 { 0867 if (!mPalette || (index >= mPalette->count())) { 0868 return; 0869 } 0870 emit q->colorDoubleClicked(mPalette->color(index), mPalette->name(index)); 0871 } 0872 0873 void 0874 KColorTable::KColorTablePrivate::slotColorTextSelected(const QString &colorText) 0875 { 0876 emit q->colorSelected(m_namedColorMap[ colorText ], colorText); 0877 } 0878 0879 void 0880 KColorTable::addToCustomColors(const QColor &color) 0881 { 0882 setColors(i18nc("palette name", colorCollectionName[customColorIndex].m_displayName)); 0883 d->mPalette->addColor(color); 0884 d->mPalette->save(); 0885 delete d->mPalette; 0886 d->mPalette = nullptr; 0887 setColors(i18nc("palette name", colorCollectionName[customColorIndex].m_displayName)); 0888 } 0889 0890 void 0891 KColorTable::addToRecentColors(const QColor &color) 0892 { 0893 // 0894 // 2000-02-12 Espen Sand. 0895 // The 'mPalette' is always 0 when current mode is i18n_namedColors 0896 // 0897 bool recentIsSelected = false; 0898 if (d->mPalette && d->mPalette->name() == colorCollectionName[ recentColorIndex ].m_fileName) { 0899 delete d->mPalette; 0900 d->mPalette = nullptr; 0901 recentIsSelected = true; 0902 } 0903 KColorCollection *recentPal = new KColorCollection(colorCollectionName[ recentColorIndex ].m_fileName); 0904 if (recentPal->findColor(color) == -1) { 0905 recentPal->addColor(color); 0906 recentPal->save(); 0907 } 0908 delete recentPal; 0909 if (recentIsSelected) { 0910 setColors(i18nc("palette name", colorCollectionName[ recentColorIndex ].m_displayName)); 0911 } 0912 } 0913 0914 class KCDPickerFilter; 0915 0916 class Q_DECL_HIDDEN KColorDialog::KColorDialogPrivate 0917 { 0918 public: 0919 KColorDialogPrivate(KColorDialog *q): q(q) {} 0920 0921 void setRgbEdit(const QColor &col); 0922 void setHsvEdit(const QColor &col); 0923 void setHtmlEdit(const QColor &col); 0924 void _setColor(const QColor &col, const QString &name = QString()); 0925 void showColor(const QColor &color, const QString &name); 0926 0927 void slotRGBChanged(void); 0928 void slotAlphaChanged(void); 0929 void slotHSVChanged(void); 0930 void slotHtmlChanged(void); 0931 void slotHSChanged(int, int); 0932 void slotVChanged(int); 0933 void slotAChanged(int); 0934 void slotModeChanged(int); 0935 0936 void slotColorSelected(const QColor &col); 0937 void slotColorSelected(const QColor &col, const QString &name); 0938 void slotColorDoubleClicked(const QColor &col, const QString &name); 0939 void slotColorPicker(); 0940 void slotAddToCustomColors(); 0941 void slotDefaultColorClicked(); 0942 /** 0943 * Write the settings of the dialog to config file. 0944 **/ 0945 void slotWriteSettings(); 0946 0947 /** 0948 * Returns the mode. 0949 */ 0950 KColorChooserMode chooserMode(); 0951 0952 /** 0953 * Sets a mode. Updates the color picker and the color bar. 0954 */ 0955 void setChooserMode(KColorChooserMode c); 0956 0957 KColorDialog *q; 0958 KColorTable *table; 0959 QString originalPalette; 0960 bool bRecursion; 0961 bool bEditRgb; 0962 bool bEditHsv; 0963 bool bEditHtml; 0964 bool bColorPicking; 0965 bool bAlphaEnabled; 0966 QLabel *colorName; 0967 KLineEdit *htmlName; 0968 QSpinBox *hedit; 0969 QSpinBox *sedit; 0970 QSpinBox *vedit; 0971 QSpinBox *redit; 0972 QSpinBox *gedit; 0973 QSpinBox *bedit; 0974 QWidget *alphaLabel; 0975 QSpinBox *aedit; 0976 0977 KColorPatch *patch; 0978 KColorPatch *comparePatch; 0979 0980 KColorChooserMode _mode; 0981 QButtonGroup *modeGroup; 0982 0983 KHueSaturationSelector *hsSelector; 0984 KColorCollection *palette; 0985 KColorValueSelector *valuePal; 0986 KGradientSelector *alphaSelector; 0987 QVBoxLayout *l_right; 0988 QGridLayout *tl_layout; 0989 QCheckBox *cbDefaultColor; 0990 QColor defaultColor; 0991 QColor selColor; 0992 }; 0993 0994 KColorDialog::KColorDialog(QWidget *parent, bool modal) 0995 : KDialog(parent), d(new KColorDialogPrivate(this)) 0996 { 0997 setCaption(i18n("Select Color")); 0998 setButtons(modal ? Ok | Cancel : Close); 0999 setModal(modal); 1000 d->bRecursion = true; 1001 d->bColorPicking = false; 1002 d->bAlphaEnabled = false; 1003 d->cbDefaultColor = nullptr; 1004 d->_mode = ChooserClassic; 1005 connect(this, SIGNAL(okClicked()), this, SLOT(slotWriteSettings())); 1006 connect(this, SIGNAL(closeClicked()), this, SLOT(slotWriteSettings())); 1007 1008 QLabel *label; 1009 1010 // 1011 // Create the top level page and its layout 1012 // 1013 QWidget *page = new QWidget(this); 1014 setMainWidget(page); 1015 1016 QGridLayout *tl_layout = new QGridLayout(page); 1017 tl_layout->setContentsMargins(0, 0, 0, 0); 1018 d->tl_layout = tl_layout; 1019 tl_layout->addItem(new QSpacerItem(spacingHint() * 2, 0), 0, 1); 1020 1021 // 1022 // the more complicated part: the left side 1023 // add a V-box 1024 // 1025 QVBoxLayout *l_left = new QVBoxLayout(); 1026 tl_layout->addLayout(l_left, 0, 0); 1027 1028 // 1029 // add a H-Box for the XY-Selector and a grid for the 1030 // entry fields 1031 // 1032 QHBoxLayout *l_ltop = new QHBoxLayout(); 1033 l_left->addLayout(l_ltop); 1034 1035 // 1036 // the palette and value selector go into the H-box 1037 // 1038 d->hsSelector = new KHueSaturationSelector(page); 1039 d->hsSelector->setMinimumSize(256, 256); 1040 l_ltop->addWidget(d->hsSelector, 8); 1041 connect(d->hsSelector, SIGNAL(valueChanged(int,int)), 1042 SLOT(slotHSChanged(int,int))); 1043 1044 d->valuePal = new KColorValueSelector(page); 1045 d->valuePal->setMinimumSize(26, 70); 1046 d->valuePal->setIndent(false); 1047 d->valuePal->setArrowDirection(Qt::RightArrow); 1048 l_ltop->addWidget(d->valuePal, 1); 1049 connect(d->valuePal, SIGNAL(valueChanged(int)), 1050 SLOT(slotVChanged(int))); 1051 1052 d->alphaSelector = new KGradientSelector(Qt::Horizontal, page); 1053 d->alphaSelector->setFixedSize(256, 26); 1054 d->alphaSelector->setIndent(false); 1055 d->alphaSelector->setArrowDirection(Qt::DownArrow); 1056 d->alphaSelector->setRange(0, 255); 1057 l_left->addWidget(d->alphaSelector, 1); 1058 connect(d->alphaSelector, SIGNAL(valueChanged(int)), 1059 SLOT(slotAChanged(int))); 1060 1061 // a little space between 1062 l_left->addSpacing(10); // FIXME: remove hardcoded values 1063 1064 QGridLayout *l_lbot = new QGridLayout(); 1065 l_left->addLayout(l_lbot); 1066 1067 // button group that manages the radio buttons 1068 QRadioButton *modeButton; 1069 d->modeGroup = new QButtonGroup(page); 1070 connect(d->modeGroup, SIGNAL(buttonClicked(int)), SLOT(slotModeChanged(int))); 1071 1072 // 1073 // add the HSV fields 1074 // 1075 l_lbot->setColumnStretch(2, 10); 1076 1077 modeButton = new QRadioButton(i18n("Hue:"), page); 1078 l_lbot->addWidget(modeButton, 0, 0); 1079 d->modeGroup->addButton(modeButton, ChooserHue); 1080 1081 d->hedit = new QSpinBox(page); 1082 d->hedit->setMaximum(359); 1083 d->hedit->setSuffix(i18nc("The angular degree unit (for hue)", "\302\260")); // U+00B0 DEGREE SIGN 1084 l_lbot->addWidget(d->hedit, 0, 1); 1085 connect(d->hedit, SIGNAL(valueChanged(int)), 1086 SLOT(slotHSVChanged())); 1087 1088 modeButton = new QRadioButton(i18n("Saturation:"), page); 1089 l_lbot->addWidget(modeButton, 1, 0); 1090 d->modeGroup->addButton(modeButton, ChooserSaturation); 1091 1092 d->sedit = new QSpinBox(page); 1093 d->sedit->setMaximum(255); 1094 l_lbot->addWidget(d->sedit, 1, 1); 1095 connect(d->sedit, SIGNAL(valueChanged(int)), 1096 SLOT(slotHSVChanged())); 1097 1098 modeButton = new QRadioButton(i18nc("This is the V of HSV", "Value:"), page); 1099 l_lbot->addWidget(modeButton, 2, 0); 1100 d->modeGroup->addButton(modeButton, ChooserValue); 1101 1102 d->vedit = new QSpinBox(page); 1103 d->vedit->setMaximum(255); 1104 l_lbot->addWidget(d->vedit, 2, 1); 1105 connect(d->vedit, SIGNAL(valueChanged(int)), 1106 SLOT(slotHSVChanged())); 1107 1108 // 1109 // add the RGB fields 1110 // 1111 modeButton = new QRadioButton(i18n("Red:"), page); 1112 l_lbot->addWidget(modeButton, 0, 3); 1113 d->modeGroup->addButton(modeButton, ChooserRed); 1114 1115 d->redit = new QSpinBox(page); 1116 d->redit->setMaximum(255); 1117 l_lbot->addWidget(d->redit, 0, 4); 1118 connect(d->redit, SIGNAL(valueChanged(int)), 1119 SLOT(slotRGBChanged())); 1120 1121 modeButton = new QRadioButton(i18n("Green:"), page); 1122 l_lbot->addWidget(modeButton, 1, 3); 1123 d->modeGroup->addButton(modeButton, ChooserGreen); 1124 1125 d->gedit = new QSpinBox(page); 1126 d->gedit->setMaximum(255); 1127 l_lbot->addWidget(d->gedit, 1, 4); 1128 connect(d->gedit, SIGNAL(valueChanged(int)), 1129 SLOT(slotRGBChanged())); 1130 1131 modeButton = new QRadioButton(i18n("Blue:"), page); 1132 l_lbot->addWidget(modeButton, 2, 3); 1133 d->modeGroup->addButton(modeButton, ChooserBlue); 1134 1135 d->bedit = new QSpinBox(page); 1136 d->bedit->setMaximum(255); 1137 l_lbot->addWidget(d->bedit, 2, 4); 1138 connect(d->bedit, SIGNAL(valueChanged(int)), 1139 SLOT(slotRGBChanged())); 1140 1141 //the layout 1142 QHBoxLayout *layout = new QHBoxLayout(this); 1143 layout->setSpacing(0); 1144 layout->setContentsMargins(0, 0, 0, 0); 1145 1146 //the frame 1147 QFrame *frame = new QFrame(page); 1148 frame->setLayout(layout); 1149 1150 d->alphaLabel = frame; 1151 QWidget *spacer = new QWidget(d->alphaLabel); 1152 label = new QLabel(i18n("Alpha:"), d->alphaLabel); 1153 QStyleOptionButton option; 1154 option.initFrom(modeButton); 1155 QRect labelRect = modeButton->style()->subElementRect(QStyle::SE_RadioButtonContents, &option, modeButton); 1156 int indent = layoutDirection() == Qt::LeftToRight ? labelRect.left() : modeButton->geometry().right() - labelRect.right(); 1157 spacer->setFixedWidth(indent); 1158 l_lbot->addWidget(d->alphaLabel, 3, 3); 1159 1160 d->aedit = new QSpinBox(page); 1161 d->aedit->setMaximum(255); 1162 label->setBuddy(d->aedit); 1163 l_lbot->addWidget(d->aedit, 3, 4); 1164 connect(d->aedit, SIGNAL(valueChanged(int)), 1165 SLOT(slotAlphaChanged())); 1166 1167 d->aedit->setVisible(false); 1168 d->alphaLabel->setVisible(false); 1169 d->alphaSelector->setVisible(false); 1170 1171 // 1172 // add a layout for the right side 1173 // 1174 d->l_right = new QVBoxLayout; 1175 tl_layout->addLayout(d->l_right, 0, 2); 1176 1177 // 1178 // Add the palette table 1179 // 1180 d->table = new KColorTable(page); 1181 d->l_right->addWidget(d->table, 10); 1182 1183 connect(d->table, SIGNAL(colorSelected(QColor,QString)), 1184 SLOT(slotColorSelected(QColor,QString))); 1185 1186 connect( 1187 d->table, 1188 SIGNAL(colorDoubleClicked(QColor,QString)), 1189 SLOT(slotColorDoubleClicked(QColor,QString)) 1190 ); 1191 // Store the default value for saving time. 1192 d->originalPalette = d->table->name(); 1193 1194 // 1195 // a little space between 1196 // 1197 d->l_right->addSpacing(10); 1198 1199 QHBoxLayout *l_hbox = new QHBoxLayout(); 1200 d->l_right->addItem(l_hbox); 1201 1202 // 1203 // The add to custom colors button 1204 // 1205 QPushButton *addButton = new QPushButton(page); 1206 addButton->setText(i18n("&Add to Custom Colors")); 1207 l_hbox->addWidget(addButton, 0, Qt::AlignLeft); 1208 connect(addButton, SIGNAL(clicked()), SLOT(slotAddToCustomColors())); 1209 1210 // 1211 // The color picker button 1212 // 1213 QPushButton *button = new QPushButton(page); 1214 button->setIcon(QIcon::fromTheme("color-picker")); 1215 int commonHeight = addButton->sizeHint().height(); 1216 button->setFixedSize(commonHeight, commonHeight); 1217 l_hbox->addWidget(button, 0, Qt::AlignHCenter); 1218 connect(button, SIGNAL(clicked()), SLOT(slotColorPicker())); 1219 1220 // 1221 // a little space between 1222 // 1223 d->l_right->addSpacing(10); 1224 1225 // 1226 // and now the entry fields and the patch (=colored box) 1227 // 1228 QGridLayout *l_grid = new QGridLayout(); 1229 d->l_right->addLayout(l_grid); 1230 1231 l_grid->setColumnStretch(2, 1); 1232 1233 label = new QLabel(page); 1234 label->setText(i18n("Name:")); 1235 l_grid->addWidget(label, 0, 1, Qt::AlignLeft); 1236 1237 d->colorName = new QLabel(page); 1238 l_grid->addWidget(d->colorName, 0, 2, Qt::AlignLeft); 1239 1240 label = new QLabel(page); 1241 label->setText(i18n("HTML:")); 1242 l_grid->addWidget(label, 1, 1, Qt::AlignLeft); 1243 1244 d->htmlName = new KLineEdit(page); 1245 d->htmlName->setMaxLength(13); // Qt's QColor allows 12 hexa-digits 1246 d->htmlName->setText("#FFFFFF"); // But HTML uses only 6, so do not worry about the size 1247 int w = d->htmlName->fontMetrics().width(QLatin1String("#DDDDDDD")); 1248 d->htmlName->setFixedWidth(w); 1249 l_grid->addWidget(d->htmlName, 1, 2, Qt::AlignLeft); 1250 1251 connect(d->htmlName, SIGNAL(textChanged(QString)), 1252 SLOT(slotHtmlChanged())); 1253 1254 d->patch = new KColorPatch(page); 1255 d->patch->setFixedSize(48, 48); 1256 l_grid->addWidget(d->patch, 0, 0, 2, 1, Qt::AlignHCenter | Qt::AlignVCenter); 1257 connect(d->patch, SIGNAL(colorChanged(QColor)), 1258 SLOT(setColor(QColor))); 1259 1260 // 1261 // chain fields together 1262 // 1263 setTabOrder(d->hedit, d->sedit); 1264 setTabOrder(d->sedit, d->vedit); 1265 setTabOrder(d->vedit, d->redit); 1266 setTabOrder(d->redit, d->gedit); 1267 setTabOrder(d->gedit, d->bedit); 1268 setTabOrder(d->bedit, d->aedit); 1269 1270 tl_layout->activate(); 1271 page->setMinimumSize(page->sizeHint()); 1272 1273 readSettings(); 1274 d->bRecursion = false; 1275 d->bEditHsv = false; 1276 d->bEditRgb = false; 1277 d->bEditHtml = false; 1278 1279 setFixedSize(sizeHint()); 1280 QColor col; 1281 col.setHsv(0, 0, 255); 1282 d->_setColor(col); 1283 1284 // FIXME: with enabled event filters, it crashes after ever enter of a drag. 1285 // better disable drag and drop than crashing it... 1286 // d->htmlName->installEventFilter(this); 1287 // d->hsSelector->installEventFilter(this); 1288 d->hsSelector->setAcceptDrops(true); 1289 1290 d->setChooserMode(ChooserValue); 1291 } 1292 1293 KColorDialog::~KColorDialog() 1294 { 1295 delete d; 1296 } 1297 1298 bool 1299 KColorDialog::eventFilter(QObject *obj, QEvent *ev) 1300 { 1301 if ((obj == d->htmlName) || (obj == d->hsSelector)) 1302 switch (ev->type()) { 1303 case QEvent::DragEnter: 1304 case QEvent::DragMove: 1305 case QEvent::DragLeave: 1306 case QEvent::Drop: 1307 case QEvent::DragResponse: 1308 qApp->sendEvent(d->patch, ev); 1309 return true; 1310 default: 1311 break; 1312 } 1313 return KDialog::eventFilter(obj, ev); 1314 } 1315 1316 void 1317 KColorDialog::setDefaultColor(const QColor &col) 1318 { 1319 if (!d->cbDefaultColor) { 1320 // 1321 // a little space between 1322 // 1323 d->l_right->addSpacing(10); 1324 1325 // 1326 // and the "default color" checkbox, under all items on the right side 1327 // 1328 d->cbDefaultColor = new QCheckBox(i18n("Default color"), mainWidget()); 1329 1330 d->l_right->addWidget(d->cbDefaultColor); 1331 1332 mainWidget()->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); // cancel setFixedSize() 1333 d->tl_layout->activate(); 1334 mainWidget()->setMinimumSize(mainWidget()->sizeHint()); 1335 setFixedSize(sizeHint()); 1336 1337 connect(d->cbDefaultColor, SIGNAL(clicked()), SLOT(slotDefaultColorClicked())); 1338 } 1339 1340 d->defaultColor = col; 1341 1342 d->slotDefaultColorClicked(); 1343 } 1344 1345 QColor KColorDialog::defaultColor() const 1346 { 1347 return d->defaultColor; 1348 } 1349 1350 void KColorDialog::setAlphaChannelEnabled(bool alpha) 1351 { 1352 if (d->bAlphaEnabled != alpha) { 1353 d->bAlphaEnabled = alpha; 1354 d->aedit->setVisible(d->bAlphaEnabled); 1355 d->alphaLabel->setVisible(d->bAlphaEnabled); 1356 d->alphaSelector->setVisible(d->bAlphaEnabled); 1357 1358 mainWidget()->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); // cancel setFixedSize() 1359 d->tl_layout->activate(); 1360 mainWidget()->setMinimumSize(mainWidget()->sizeHint()); 1361 setFixedSize(sizeHint()); 1362 } 1363 } 1364 1365 bool KColorDialog::isAlphaChannelEnabled() const 1366 { 1367 return d->bAlphaEnabled; 1368 } 1369 1370 void KColorDialog::KColorDialogPrivate::setChooserMode(KColorChooserMode c) 1371 { 1372 _mode = c; 1373 hsSelector->setChooserMode(c); 1374 valuePal->setChooserMode(c); 1375 1376 modeGroup->button(valuePal->chooserMode())->setChecked(true); 1377 valuePal->updateContents(); 1378 hsSelector->updateContents(); 1379 valuePal->update(); 1380 hsSelector->update(); 1381 slotHSVChanged(); 1382 } 1383 1384 KColorChooserMode KColorDialog::KColorDialogPrivate::chooserMode() 1385 { 1386 return _mode; 1387 } 1388 1389 void KColorDialog::KColorDialogPrivate::slotDefaultColorClicked() 1390 { 1391 if (cbDefaultColor->isChecked()) { 1392 selColor = defaultColor; 1393 showColor(selColor, i18n("-default-")); 1394 } else { 1395 showColor(selColor, QString()); 1396 } 1397 emit q->colorSelected(selColor); 1398 } 1399 1400 void 1401 KColorDialog::KColorDialogPrivate::slotModeChanged(int id) 1402 { 1403 setChooserMode(KColorChooserMode(id)); 1404 } 1405 1406 void 1407 KColorDialog::readSettings() 1408 { 1409 KConfigGroup group(KSharedConfig::openConfig(), "Colors"); 1410 1411 QString collectionName = group.readEntry("CurrentPalette"); 1412 if (collectionName.isEmpty()) { 1413 collectionName = i18nc("palette name", colorCollectionName[fortyColorIndex].m_displayName); 1414 } else { 1415 for (int i = 0; colorCollectionName[i].m_fileName; ++i) { 1416 if (collectionName == colorCollectionName[i].m_displayName) { 1417 collectionName = i18nc("palette name", colorCollectionName[i].m_displayName); 1418 break; 1419 } 1420 } 1421 } 1422 1423 d->table->setColors(collectionName); 1424 } 1425 1426 void 1427 KColorDialog::KColorDialogPrivate::slotWriteSettings() 1428 { 1429 KConfigGroup group(KSharedConfig::openConfig(), "Colors"); 1430 1431 QString collectionName = table->name(); 1432 if (!group.hasDefault("CurrentPalette") && table->name() == originalPalette) { 1433 group.revertToDefault("CurrentPalette"); 1434 } else { 1435 QString collectionName(table->name()); 1436 for (int i = 0; colorCollectionName[i].m_fileName; ++i) { 1437 if (collectionName == i18nc("palette name", colorCollectionName[i].m_displayName)) { 1438 collectionName = colorCollectionName[i].m_displayName; 1439 break; 1440 } 1441 } 1442 group.writeEntry("CurrentPalette", collectionName); //Make sure the untranslated name is saved, assuming there is one 1443 } 1444 } 1445 1446 QColor 1447 KColorDialog::color() const 1448 { 1449 if (d->cbDefaultColor && d->cbDefaultColor->isChecked()) { 1450 return QColor(); 1451 } 1452 if (d->selColor.isValid()) { 1453 d->table->addToRecentColors(d->selColor); 1454 } 1455 return d->selColor; 1456 } 1457 1458 void KColorDialog::setColor(const QColor &col) 1459 { 1460 d->_setColor(col); 1461 } 1462 1463 // 1464 // static function to display dialog and return color 1465 // 1466 int KColorDialog::getColor(QColor &theColor, QWidget *parent) 1467 { 1468 KColorDialog dlg(parent, true); 1469 dlg.setObjectName("Color Selector"); 1470 if (theColor.isValid()) { 1471 dlg.setColor(theColor); 1472 } 1473 int result = dlg.exec(); 1474 1475 if (result == Accepted) { 1476 theColor = dlg.color(); 1477 } 1478 1479 return result; 1480 } 1481 1482 // 1483 // static function to display dialog and return color 1484 // 1485 int KColorDialog::getColor(QColor &theColor, const QColor &defaultCol, QWidget *parent) 1486 { 1487 KColorDialog dlg(parent, true); 1488 dlg.setObjectName("Color Selector"); 1489 dlg.setDefaultColor(defaultCol); 1490 dlg.setColor(theColor); 1491 int result = dlg.exec(); 1492 1493 if (result == Accepted) { 1494 theColor = dlg.color(); 1495 } 1496 1497 return result; 1498 } 1499 1500 void KColorDialog::KColorDialogPrivate::slotRGBChanged(void) 1501 { 1502 if (bRecursion) { 1503 return; 1504 } 1505 int red = redit->value(); 1506 int grn = gedit->value(); 1507 int blu = bedit->value(); 1508 1509 if (red > 255 || red < 0) { 1510 return; 1511 } 1512 if (grn > 255 || grn < 0) { 1513 return; 1514 } 1515 if (blu > 255 || blu < 0) { 1516 return; 1517 } 1518 1519 QColor col; 1520 col.setRgb(red, grn, blu, aedit->value()); 1521 bEditRgb = true; 1522 _setColor(col); 1523 bEditRgb = false; 1524 } 1525 1526 void KColorDialog::KColorDialogPrivate::slotAlphaChanged(void) 1527 { 1528 if (bRecursion) { 1529 return; 1530 } 1531 int alpha = aedit->value(); 1532 1533 if (alpha > 255 || alpha < 0) { 1534 return; 1535 } 1536 1537 QColor col = selColor; 1538 col.setAlpha(alpha); 1539 _setColor(col); 1540 } 1541 1542 void KColorDialog::KColorDialogPrivate::slotHtmlChanged(void) 1543 { 1544 if (bRecursion || htmlName->text().isEmpty()) { 1545 return; 1546 } 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) { 1571 return; 1572 } 1573 int hue = hedit->value(); 1574 int sat = sedit->value(); 1575 int val = vedit->value(); 1576 1577 if (hue > 359 || hue < 0) { 1578 return; 1579 } 1580 if (sat > 255 || sat < 0) { 1581 return; 1582 } 1583 if (val > 255 || val < 0) { 1584 return; 1585 } 1586 1587 QColor col; 1588 col.setHsv(hue, sat, val, aedit->value()); 1589 bEditHsv = true; 1590 _setColor(col); 1591 bEditHsv = false; 1592 } 1593 1594 void KColorDialog::KColorDialogPrivate::slotHSChanged(int x, int y) 1595 { 1596 QColor col = selColor; 1597 KColorChooserMode xMode = chooserXMode(chooserMode()); 1598 KColorChooserMode yMode = chooserYMode(chooserMode()); 1599 setComponentValue(col, xMode, x / (xMode == ChooserHue ? 360.0 : 255.0)); 1600 setComponentValue(col, yMode, y / (yMode == ChooserHue ? 360.0 : 255.0)); 1601 _setColor(col); 1602 } 1603 1604 void KColorDialog::KColorDialogPrivate::slotVChanged(int v) 1605 { 1606 QColor col = selColor; 1607 setComponentValue(col, chooserMode(), v / (chooserMode() == ChooserHue ? 360.0 : 255.0)); 1608 _setColor(col); 1609 } 1610 1611 void KColorDialog::KColorDialogPrivate::slotAChanged(int value) 1612 { 1613 QColor col = selColor; 1614 col.setAlpha(value); 1615 _setColor(col); 1616 } 1617 1618 void KColorDialog::KColorDialogPrivate::slotColorSelected(const QColor &color) 1619 { 1620 _setColor(color); 1621 } 1622 1623 void KColorDialog::KColorDialogPrivate::slotAddToCustomColors() 1624 { 1625 table->addToCustomColors(selColor); 1626 } 1627 1628 void KColorDialog::KColorDialogPrivate::slotColorSelected(const QColor &color, const QString &name) 1629 { 1630 _setColor(color, name); 1631 } 1632 1633 void KColorDialog::KColorDialogPrivate::slotColorDoubleClicked 1634 ( 1635 const QColor &color, 1636 const QString &name 1637 ) 1638 { 1639 _setColor(color, name); 1640 q->accept(); 1641 } 1642 1643 void KColorDialog::KColorDialogPrivate::_setColor(const QColor &color, const QString &name) 1644 { 1645 if (color.isValid()) { 1646 if (cbDefaultColor && cbDefaultColor->isChecked()) { 1647 cbDefaultColor->setChecked(false); 1648 } 1649 selColor = color; 1650 } else { 1651 if (cbDefaultColor && cbDefaultColor->isChecked()) { 1652 cbDefaultColor->setChecked(true); 1653 } 1654 selColor = defaultColor; 1655 } 1656 1657 showColor(selColor, name); 1658 1659 emit q->colorSelected(selColor); 1660 } 1661 1662 // show but don't set into selColor, nor emit colorSelected 1663 void KColorDialog::KColorDialogPrivate::showColor(const QColor &color, const QString &name) 1664 { 1665 bRecursion = true; 1666 1667 if (name.isEmpty()) { 1668 colorName->setText(i18n("-unnamed-")); 1669 } else { 1670 colorName->setText(name); 1671 } 1672 1673 patch->setColor(color); 1674 1675 setRgbEdit(color); 1676 setHsvEdit(color); 1677 setHtmlEdit(color); 1678 aedit->setValue(color.alpha()); 1679 1680 QColor rgbColor = color.toRgb(); 1681 bool ltr = q->layoutDirection() == Qt::LeftToRight; 1682 rgbColor.setAlpha(ltr ? 0 : 255); 1683 alphaSelector->setFirstColor(rgbColor); 1684 rgbColor.setAlpha(ltr ? 255 : 0); 1685 alphaSelector->setSecondColor(rgbColor); 1686 alphaSelector->setValue(color.alpha()); 1687 1688 KColorChooserMode xMode = chooserXMode(chooserMode()); 1689 KColorChooserMode yMode = chooserYMode(chooserMode()); 1690 int xValue = qRound(getComponentValue(color, xMode) * (xMode == ChooserHue ? 360.0 : 255.0)); 1691 int yValue = qRound(getComponentValue(color, yMode) * (yMode == ChooserHue ? 360.0 : 255.0)); 1692 int value = qRound(getComponentValue(color, chooserMode()) * (chooserMode() == ChooserHue ? 360.0 : 255.0)); 1693 hsSelector->setValues(xValue, yValue); 1694 valuePal->setValue(value); 1695 1696 bool blocked = valuePal->blockSignals(true); 1697 1698 valuePal->setHue(color.hue()); 1699 valuePal->setSaturation(color.saturation()); 1700 valuePal->setColorValue(color.value()); 1701 valuePal->updateContents(); 1702 valuePal->blockSignals(blocked); 1703 valuePal->update(); 1704 1705 blocked = hsSelector->blockSignals(true); 1706 1707 hsSelector->setHue(color.hue()); 1708 hsSelector->setSaturation(color.saturation()); 1709 hsSelector->setColorValue(color.value()); 1710 hsSelector->updateContents(); 1711 hsSelector->blockSignals(blocked); 1712 hsSelector->update(); 1713 1714 bRecursion = false; 1715 } 1716 1717 void 1718 KColorDialog::KColorDialogPrivate::slotColorPicker() 1719 { 1720 bColorPicking = true; 1721 q->grabMouse(Qt::CrossCursor); 1722 q->grabKeyboard(); 1723 } 1724 1725 void 1726 KColorDialog::mouseMoveEvent(QMouseEvent *e) 1727 { 1728 if (d->bColorPicking) { 1729 d->_setColor(grabColor(e->globalPos())); 1730 return; 1731 } 1732 1733 KDialog::mouseMoveEvent(e); 1734 } 1735 1736 void 1737 KColorDialog::mouseReleaseEvent(QMouseEvent *e) 1738 { 1739 if (d->bColorPicking) { 1740 d->bColorPicking = false; 1741 releaseMouse(); 1742 releaseKeyboard(); 1743 d->_setColor(grabColor(e->globalPos())); 1744 return; 1745 } 1746 KDialog::mouseReleaseEvent(e); 1747 } 1748 1749 QColor 1750 KColorDialog::grabColor(const QPoint &p) 1751 { 1752 auto fallback = [p]() { 1753 QWidget *desktop = QApplication::desktop(); 1754 QPixmap pm = QPixmap::grabWindow(desktop->winId(), p.x(), p.y(), 1, 1); 1755 QImage i = pm.toImage(); 1756 return i.pixel(0, 0); 1757 }; 1758 #if HAVE_X11 1759 if (!QX11Info::isPlatformX11()) { 1760 return fallback(); 1761 } 1762 // we use the X11 API directly in this case as we are not getting back a valid 1763 // return from QPixmap::grabWindow in the case where the application is using 1764 // an argb visual 1765 if (!qApp->desktop()->geometry().contains(p)) { 1766 return QColor(); 1767 } 1768 Window root = RootWindow(QX11Info::display(), QX11Info::appScreen()); 1769 XImage *ximg = XGetImage(QX11Info::display(), root, p.x(), p.y(), 1, 1, -1, ZPixmap); 1770 unsigned long xpixel = XGetPixel(ximg, 0, 0); 1771 XDestroyImage(ximg); 1772 XColor xcol; 1773 xcol.pixel = xpixel; 1774 xcol.flags = DoRed | DoGreen | DoBlue; 1775 XQueryColor(QX11Info::display(), 1776 DefaultColormap(QX11Info::display(), QX11Info::appScreen()), 1777 &xcol); 1778 return QColor::fromRgbF(xcol.red / 65535.0, xcol.green / 65535.0, xcol.blue / 65535.0); 1779 #else 1780 return fallback(); 1781 #endif 1782 } 1783 1784 void 1785 KColorDialog::keyPressEvent(QKeyEvent *e) 1786 { 1787 if (d->bColorPicking) { 1788 if (e->key() == Qt::Key_Escape) { 1789 d->bColorPicking = false; 1790 releaseMouse(); 1791 releaseKeyboard(); 1792 } 1793 e->accept(); 1794 return; 1795 } 1796 KDialog::keyPressEvent(e); 1797 } 1798 1799 void KColorDialog::KColorDialogPrivate::setRgbEdit(const QColor &col) 1800 { 1801 if (bEditRgb) { 1802 return; 1803 } 1804 int r, g, b; 1805 col.getRgb(&r, &g, &b); 1806 1807 redit->setValue(r); 1808 gedit->setValue(g); 1809 bedit->setValue(b); 1810 } 1811 1812 void KColorDialog::KColorDialogPrivate::setHtmlEdit(const QColor &col) 1813 { 1814 if (bEditHtml) { 1815 return; 1816 } 1817 int r, g, b; 1818 col.getRgb(&r, &g, &b); 1819 QString num; 1820 1821 num.sprintf("#%02X%02X%02X", r, g, b); 1822 htmlName->setText(num); 1823 } 1824 1825 void KColorDialog::KColorDialogPrivate::setHsvEdit(const QColor &col) 1826 { 1827 if (bEditHsv) { 1828 return; 1829 } 1830 int h, s, v; 1831 col.getHsv(&h, &s, &v); 1832 1833 hedit->setValue(h); 1834 sedit->setValue(s); 1835 vedit->setValue(v); 1836 } 1837 1838 #include "moc_kcolordialog.cpp" 1839 #include "moc_kcolordialog_p.cpp"