KDEUI
kcolordialog.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE libraries 00002 Copyright (C) 1997 Martin Jones (mjones@kde.org) 00003 Copyright (C) 2007 Roberto Raggi (roberto@kdevelop.org) 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License as published by the Free Software Foundation; either 00008 version 2 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public License 00016 along with this library; see the file COPYING.LIB. If not, write to 00017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00018 Boston, MA 02110-1301, USA. 00019 */ 00020 //----------------------------------------------------------------------------- 00021 // KDE color selection dialog. 00022 // 00023 // 1999-09-27 Espen Sand <espensa@online.no> 00024 // KColorDialog is now subclassed from KDialog. I have also extended 00025 // KColorDialog::getColor() so that it contains a parent argument. This 00026 // improves centering capability. 00027 // 00028 // layout management added Oct 1997 by Mario Weilguni 00029 // <mweilguni@sime.com> 00030 // 00031 00032 #include "kcolordialog.h" 00033 #include "kcolordialog_p.h" 00034 00035 00036 #include <stdio.h> 00037 #include <stdlib.h> 00038 00039 #include <QtGui/QButtonGroup> 00040 #include <QtGui/QCheckBox> 00041 #include <QtGui/QDesktopWidget> 00042 #include <QtGui/QRadioButton> 00043 #include <QtGui/qdrawutil.h> 00044 #include <QtGui/QActionEvent> 00045 #include <QtCore/QFile> 00046 #include <QtGui/QHeaderView> 00047 #include <QtGui/QImage> 00048 #include <QtGui/QStyledItemDelegate> 00049 #include <QtGui/QLabel> 00050 #include <QtGui/QLayout> 00051 #include <QtGui/QPainter> 00052 #include <QtGui/QPushButton> 00053 #include <QtGui/QScrollBar> 00054 #include <QtCore/QTimer> 00055 00056 #include <kapplication.h> 00057 #include <kcombobox.h> 00058 #include <kconfig.h> 00059 #include <kglobal.h> 00060 #include <kglobalsettings.h> 00061 #include <khbox.h> 00062 #include <kiconloader.h> 00063 #include <klineedit.h> 00064 #include <klistwidget.h> 00065 #include <klocale.h> 00066 #include <kmessagebox.h> 00067 #include <knuminput.h> 00068 #include <kseparator.h> 00069 #include <kstandarddirs.h> 00070 #include <kcolorcollection.h> 00071 #include <kcolorutils.h> 00072 00073 #include "kcolormimedata.h" 00074 #include <config.h> 00075 #include <kdebug.h> 00076 00077 #include "kcolorchoosermode_p.h" 00078 #include "kcolorhelpers_p.h" 00079 #include "kselector.h" 00080 #include "kcolorvalueselector.h" 00081 #include "khuesaturationselect.h" 00082 #include "kxyselector.h" 00083 #include <kconfiggroup.h> 00084 00085 #ifdef Q_WS_X11 00086 #include <X11/Xlib.h> 00087 #include <X11/Xutil.h> 00088 #include <QX11Info> 00089 #include <fixx11h.h> 00090 #endif 00091 00092 using namespace KDEPrivate; 00093 00094 using KDEPrivate::KColorTable; 00095 00096 struct ColorCollectionNameType { 00097 const char* const m_fileName; 00098 const char* const m_displayName; 00099 }; 00100 00101 static const ColorCollectionNameType colorCollectionName[] = { 00102 { "Recent_Colors", I18N_NOOP2("palette name", "* Recent Colors *") }, 00103 { "Custom_Colors", I18N_NOOP2("palette name", "* Custom Colors *") }, 00104 { "40.colors", I18N_NOOP2("palette name", "Forty Colors") }, 00105 { "Oxygen.colors", I18N_NOOP2("palette name", "Oxygen Colors") }, 00106 { "Rainbow.colors", I18N_NOOP2("palette name", "Rainbow Colors") }, 00107 { "Royal.colors", I18N_NOOP2("palette name", "Royal Colors") }, 00108 { "Web.colors", I18N_NOOP2("palette name", "Web Colors") }, 00109 { 0, 0 } // end of data 00110 }; 00111 00112 enum ColorCollectionIndices 00113 { 00114 recentColorIndex, 00115 customColorIndex, 00116 fortyColorIndex 00117 }; 00118 00119 //----------------------------------------------------------------------------- 00120 00121 class KColorCells::KColorCellsPrivate 00122 { 00123 public: 00124 KColorCellsPrivate(KColorCells *q): q(q) { 00125 inMouse = false; 00126 selected = -1; 00127 shade = false; 00128 } 00129 00130 KColorCells *q; 00131 QPoint mousePos; 00132 int selected; 00133 bool shade; 00134 bool inMouse; 00135 }; 00136 00137 class KColorCellsItemDelegate: public QStyledItemDelegate 00138 { 00139 public: 00140 KColorCellsItemDelegate(KColorCells *parent): QStyledItemDelegate(parent) {} 00141 virtual void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const 00142 { 00143 QStyleOptionViewItemV4 opt(option); 00144 initStyleOption(&opt,index); 00145 00146 //Get the current cell color 00147 QColor backgroundColor = index.data(Qt::BackgroundRole).value<QColor>(); 00148 if (backgroundColor.isValid()) { 00149 //Paint the general background 00150 painter->fillRect(opt.rect, backgroundColor); 00151 //Paint the selection mark (circle) 00152 if (opt.state & QStyle::State_Selected) { 00153 //Use black or white, depending on the contrast 00154 QColor color = QColor(0, 0, 0, 220); 00155 if (KColorUtils::contrastRatio(color, backgroundColor) < 5) { 00156 color = QColor(255, 255, 255, 220); 00157 } 00158 //Draw the selection (radiobutton-like) circle 00159 painter->save(); 00160 painter->setRenderHint(QPainter::Antialiasing, true); 00161 painter->setRenderHint(QPainter::HighQualityAntialiasing, true); 00162 painter->setPen(QPen(color, 1.2, Qt::SolidLine)); 00163 painter->setBrush(QBrush()); 00164 painter->drawEllipse(opt.rect.adjusted(2,2,-2,-2)); 00165 painter->restore(); 00166 } 00167 } else { 00168 //Paint the "X" (missing) cross on empty background color 00169 backgroundColor = opt.palette.color(QPalette::Window); 00170 painter->fillRect(opt.rect, backgroundColor); 00171 painter->save(); 00172 QColor crossColor = qGray(backgroundColor.rgb()) > 192 ? backgroundColor.darker(106) : 00173 backgroundColor.lighter(106); 00174 painter->setPen(QPen(crossColor, 1.5)); 00175 painter->drawLine(opt.rect.topLeft(), opt.rect.bottomRight()); 00176 painter->drawLine(opt.rect.topRight(), opt.rect.bottomLeft()); 00177 painter->restore(); 00178 } 00179 } 00180 }; 00181 00182 KColorCells::KColorCells(QWidget *parent, int rows, int cols) 00183 : QTableWidget(parent), d(new KColorCellsPrivate(this)) 00184 { 00185 setItemDelegate(new KColorCellsItemDelegate(this)); 00186 00187 setFrameShape(QFrame::NoFrame); 00188 d->shade = true; 00189 setRowCount(rows); 00190 setColumnCount(cols); 00191 00192 verticalHeader()->hide(); 00193 horizontalHeader()->hide(); 00194 00195 d->selected = 0; 00196 d->inMouse = false; 00197 00198 // Drag'n'Drop 00199 setAcceptDrops(true); 00200 00201 setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 00202 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 00203 viewport()->setBackgroundRole(QPalette::Background); 00204 setBackgroundRole(QPalette::Background); 00205 00206 00207 setSelectionMode(QAbstractItemView::SingleSelection); 00208 setDragEnabled(false); 00209 } 00210 00211 KColorCells::~KColorCells() 00212 { 00213 delete d; 00214 } 00215 00216 QColor KColorCells::color(int index) const 00217 { 00218 QTableWidgetItem * tmpItem = item(index / columnCount(), index % columnCount()); 00219 00220 if (tmpItem != 0) 00221 return tmpItem->data(Qt::BackgroundRole).value<QColor>(); 00222 00223 return QColor(); 00224 } 00225 00226 int KColorCells::count() const 00227 { 00228 return rowCount() * columnCount(); 00229 } 00230 00231 void KColorCells::setShading(bool _shade) 00232 { 00233 d->shade = _shade; 00234 } 00235 00236 void KColorCells::setAcceptDrags(bool _acceptDrags) 00237 { 00238 this->setDragEnabled(_acceptDrags); 00239 } 00240 00241 void KColorCells::setSelected(int index) 00242 { 00243 Q_ASSERT(index >= 0 && index < count()); 00244 00245 d->selected = index; 00246 } 00247 00248 int KColorCells::selectedIndex() const 00249 { 00250 return d->selected; 00251 } 00252 00253 void KColorCells::setColor(int column, const QColor &color) 00254 { 00255 const int tableRow = column / columnCount(); 00256 const int tableColumn = column % columnCount(); 00257 00258 Q_ASSERT(tableRow >= 0 && tableRow < rowCount()); 00259 Q_ASSERT(tableColumn >= 0 && tableColumn < columnCount()); 00260 00261 QTableWidgetItem * tableItem = item(tableRow, tableColumn); 00262 00263 if (tableItem == 0) { 00264 tableItem = new QTableWidgetItem(); 00265 setItem(tableRow, tableColumn, tableItem); 00266 } 00267 00268 tableItem->setData(Qt::BackgroundRole , color); 00269 } 00270 00271 /*void KColorCells::paintCell( QPainter *painter, int row, int col ) 00272 { 00273 painter->setRenderHint( QPainter::Antialiasing , true ); 00274 00275 QBrush brush; 00276 int w = 1; 00277 00278 if (shade) 00279 { 00280 qDrawShadePanel( painter, 1, 1, cellWidth()-2, 00281 cellHeight()-2, palette(), true, 1, &brush ); 00282 w = 2; 00283 } 00284 QColor color = colors[ row * numCols() + col ]; 00285 if (!color.isValid()) 00286 { 00287 if (!shade) return; 00288 color = palette().color(backgroundRole()); 00289 } 00290 00291 const QRect colorRect( w, w, cellWidth()-w*2, cellHeight()-w*2 ); 00292 painter->fillRect( colorRect, color ); 00293 00294 if ( row * numCols() + col == selected ) { 00295 painter->setPen( qGray(color.rgb())>=127 ? Qt::black : Qt::white ); 00296 painter->drawLine( colorRect.topLeft(), colorRect.bottomRight() ); 00297 painter->drawLine( colorRect.topRight(), colorRect.bottomLeft() ); 00298 } 00299 }*/ 00300 00301 void KColorCells::resizeEvent(QResizeEvent*) 00302 { 00303 // According to the Qt doc: 00304 // If you need to set the width of a given column to a fixed value, call 00305 // QHeaderView::resizeSection() on the table's {horizontal,vertical} 00306 // header. 00307 // Therefore we iterate over each row and column and set the header section 00308 // size, as the sizeHint does indeed appear to be ignored in favor of a 00309 // minimum size that is larger than what we want. 00310 for (int index = 0 ; index < columnCount() ; index++) 00311 horizontalHeader()->resizeSection(index, sizeHintForColumn(index)); 00312 for (int index = 0 ; index < rowCount() ; index++) 00313 verticalHeader()->resizeSection(index, sizeHintForRow(index)); 00314 } 00315 00316 int KColorCells::sizeHintForColumn(int /*column*/) const 00317 { 00318 return width() / columnCount() ; 00319 } 00320 00321 int KColorCells::sizeHintForRow(int /*row*/) const 00322 { 00323 return height() / rowCount() ; 00324 } 00325 00326 void KColorCells::mousePressEvent(QMouseEvent *e) 00327 { 00328 d->inMouse = true; 00329 d->mousePos = e->pos(); 00330 00331 QTableWidget::mousePressEvent(e); 00332 } 00333 00334 00335 int KColorCells::positionToCell(const QPoint &pos, bool ignoreBorders) const 00336 { 00337 //TODO ignoreBorders not yet handled 00338 Q_UNUSED(ignoreBorders) 00339 00340 QTableWidgetItem* tableItem = itemAt(pos); 00341 00342 if (!tableItem) 00343 return -1; 00344 00345 const int itemRow = row(tableItem); 00346 const int itemColumn = column(tableItem); 00347 int cell = itemRow * columnCount() + itemColumn; 00348 00349 /*if (!ignoreBorders) 00350 { 00351 int border = 2; 00352 int x = pos.x() - col * cellWidth(); 00353 int y = pos.y() - row * cellHeight(); 00354 if ( (x < border) || (x > cellWidth()-border) || 00355 (y < border) || (y > cellHeight()-border)) 00356 return -1; 00357 }*/ 00358 00359 return cell; 00360 } 00361 00362 void KColorCells::mouseMoveEvent(QMouseEvent *e) 00363 { 00364 if (this->dragEnabled() || this->acceptDrops()) { 00365 if (!(e->buttons() & Qt::LeftButton)) return; 00366 00367 if (d->inMouse) { 00368 int delay = KGlobalSettings::dndEventDelay(); 00369 if (e->x() > d->mousePos.x() + delay || e->x() < d->mousePos.x() - delay || 00370 e->y() > d->mousePos.y() + delay || e->y() < d->mousePos.y() - delay) { 00371 // Drag color object 00372 QTableWidgetItem * tableItem = itemAt(d->mousePos); 00373 00374 if (tableItem) { 00375 QVariant var = tableItem->data(Qt::BackgroundRole); 00376 QColor tmpCol = var.value<QColor>(); 00377 if (tmpCol.isValid()) 00378 KColorMimeData::createDrag(tmpCol, this)->start(); 00379 } 00380 } 00381 } 00382 } else 00383 QTableWidget::mouseMoveEvent(e); 00384 } 00385 00386 void KColorCells::dragEnterEvent(QDragEnterEvent *event) 00387 { 00388 kDebug() << "KColorCells::dragEnterEvent() acceptDrags=" 00389 << this->dragEnabled() 00390 << " canDecode=" << KColorMimeData::canDecode(event->mimeData()) 00391 << endl; 00392 event->setAccepted(this->dragEnabled() && KColorMimeData::canDecode(event->mimeData())); 00393 } 00394 00395 // Reimplemented to override QTableWidget's override. Else dropping doesn't work. 00396 void KColorCells::dragMoveEvent(QDragMoveEvent *event) 00397 { 00398 kDebug() << "KColorCells::dragMoveEvent() acceptDrags=" 00399 << this->dragEnabled() 00400 << " canDecode=" << KColorMimeData::canDecode(event->mimeData()) 00401 << endl; 00402 event->setAccepted(this->dragEnabled() && KColorMimeData::canDecode(event->mimeData())); 00403 } 00404 00405 void KColorCells::dropEvent(QDropEvent *event) 00406 { 00407 QColor c = KColorMimeData::fromMimeData(event->mimeData()); 00408 00409 kDebug() << "KColorCells::dropEvent() color.isValid=" << c.isValid(); 00410 if (c.isValid()) { 00411 QTableWidgetItem * tableItem = itemAt(event->pos()); 00412 00413 if (tableItem) 00414 tableItem->setData(Qt::BackgroundRole , c); 00415 } 00416 } 00417 00418 void KColorCells::mouseReleaseEvent(QMouseEvent *e) 00419 { 00420 if (selectionMode() != QAbstractItemView::NoSelection) { 00421 int cell = positionToCell(d->mousePos); 00422 int currentCell = positionToCell(e->pos()); 00423 00424 // If we release the mouse in another cell and we don't have 00425 // a drag we should ignore this event. 00426 if (currentCell != cell) 00427 cell = -1; 00428 00429 if ((cell != -1) && (d->selected != cell)) { 00430 d->selected = cell; 00431 00432 const int newRow = cell / columnCount(); 00433 const int newColumn = cell % columnCount(); 00434 00435 clearSelection(); // we do not want old violet selected cells 00436 00437 item(newRow, newColumn)->setSelected(true); 00438 } 00439 00440 d->inMouse = false; 00441 if (cell != -1) 00442 emit colorSelected(cell , color(cell)); 00443 } 00444 00445 QTableWidget::mouseReleaseEvent(e); 00446 } 00447 00448 void KColorCells::mouseDoubleClickEvent(QMouseEvent * /*e*/) 00449 { 00450 int cell = positionToCell(d->mousePos); 00451 00452 if (cell != -1) 00453 emit colorDoubleClicked(cell , color(cell)); 00454 } 00455 00456 00457 //----------------------------------------------------------------------------- 00458 00459 class KColorPatch::KColorPatchPrivate 00460 { 00461 public: 00462 KColorPatchPrivate(KColorPatch *q): q(q) {} 00463 00464 KColorPatch *q; 00465 QColor color; 00466 }; 00467 00468 KColorPatch::KColorPatch(QWidget *parent) : QFrame(parent), d(new KColorPatchPrivate(this)) 00469 { 00470 setFrameStyle(QFrame::StyledPanel | QFrame::Sunken); 00471 setAcceptDrops(true); 00472 setMinimumSize(12, 12); 00473 } 00474 00475 KColorPatch::~KColorPatch() 00476 { 00477 delete d; 00478 } 00479 00480 QColor KColorPatch::color() const 00481 { 00482 return d->color; 00483 } 00484 00485 void KColorPatch::setColor(const QColor &col) 00486 { 00487 d->color = col.toRgb(); 00488 00489 update(); 00490 } 00491 00492 void KColorPatch::paintEvent(QPaintEvent* pe) 00493 { 00494 QFrame::paintEvent(pe); 00495 QPainter painter(this); 00496 00497 fillOpaqueRect(&painter, contentsRect(), d->color); 00498 } 00499 00500 void KColorPatch::mouseMoveEvent(QMouseEvent *e) 00501 { 00502 // Drag color object 00503 if (!(e->buttons() & Qt::LeftButton)) 00504 return; 00505 KColorMimeData::createDrag(d->color, this)->start(); 00506 } 00507 00508 void KColorPatch::dragEnterEvent(QDragEnterEvent *event) 00509 { 00510 event->setAccepted(KColorMimeData::canDecode(event->mimeData())); 00511 } 00512 00513 void KColorPatch::dropEvent(QDropEvent *event) 00514 { 00515 QColor c = KColorMimeData::fromMimeData(event->mimeData()); 00516 if (c.isValid()) { 00517 setColor(c); 00518 emit colorChanged(c); 00519 } 00520 } 00521 00522 class KColorTable::KColorTablePrivate 00523 { 00524 public: 00525 KColorTablePrivate(KColorTable *q): q(q) {} 00526 00527 void slotColorCellSelected(int index , const QColor&); 00528 void slotColorCellDoubleClicked(int index , const QColor&); 00529 void slotColorTextSelected(const QString &colorText); 00530 void slotSetColors(const QString &_collectionName); 00531 void slotShowNamedColorReadError(void); 00532 00533 KColorTable *q; 00534 QString i18n_namedColors; 00535 KComboBox *combo; 00536 KColorCells *cells; 00537 QScrollArea *sv; 00538 KListWidget *mNamedColorList; 00539 KColorCollection *mPalette; 00540 int mMinWidth; 00541 int mCols; 00542 QMap<QString, QColor> m_namedColorMap; 00543 }; 00544 00545 KColorTable::KColorTable(QWidget *parent, int minWidth, int cols) 00546 : QWidget(parent), d(new KColorTablePrivate(this)) 00547 { 00548 d->cells = 0; 00549 d->mPalette = 0; 00550 d->mMinWidth = minWidth; 00551 d->mCols = cols; 00552 d->i18n_namedColors = i18n("Named Colors"); 00553 00554 QStringList diskPaletteList = KColorCollection::installedCollections(); 00555 QStringList paletteList; 00556 00557 // We must replace the untranslated file names by translate names (of course only for KDE's standard palettes) 00558 for (int i = 0; colorCollectionName[i].m_fileName; ++i) { 00559 diskPaletteList.removeAll(colorCollectionName[i].m_fileName); 00560 paletteList.append(i18nc("palette name", colorCollectionName[i].m_displayName)); 00561 } 00562 paletteList += diskPaletteList; 00563 paletteList.append(d->i18n_namedColors); 00564 00565 QVBoxLayout *layout = new QVBoxLayout(this); 00566 00567 d->combo = new KComboBox(this); 00568 d->combo->setEditable(false); 00569 d->combo->addItems(paletteList); 00570 layout->addWidget(d->combo); 00571 00572 d->sv = new QScrollArea(this); 00573 QSize cellSize = QSize(d->mMinWidth, 120); 00574 d->sv->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 00575 d->sv->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); 00576 QSize minSize = QSize(d->sv->verticalScrollBar()->sizeHint().width(), 0); 00577 minSize += QSize(d->sv->frameWidth() * 2, 0); 00578 minSize += QSize(cellSize); 00579 d->sv->setFixedSize(minSize); 00580 layout->addWidget(d->sv); 00581 00582 d->mNamedColorList = new KListWidget(this); 00583 d->mNamedColorList->setObjectName("namedColorList"); 00584 d->mNamedColorList->setFixedSize(minSize); 00585 d->mNamedColorList->hide(); 00586 layout->addWidget(d->mNamedColorList); 00587 connect(d->mNamedColorList, SIGNAL(currentTextChanged(const QString &)), 00588 this, SLOT(slotColorTextSelected(const QString &))); 00589 00590 setFixedSize(sizeHint()); 00591 connect(d->combo, SIGNAL(activated(const QString &)), 00592 this, SLOT(slotSetColors(const QString &))); 00593 } 00594 00595 KColorTable::~KColorTable() 00596 { 00597 delete d->mPalette; 00598 delete d; 00599 } 00600 00601 QString 00602 KColorTable::name() const 00603 { 00604 return d->combo->currentText(); 00605 } 00606 00607 00608 static const char * const *namedColorFilePath(void) 00609 { 00610 // 00611 // 2000-02-05 Espen Sand. 00612 // Add missing filepaths here. Make sure the last entry is 0, 0! 00613 // 00614 // 2009-06-16 Pino Toscano 00615 // 00616 // You can specify either absolute paths or relative locations 00617 // wrt KStandardDirs resources. In either way, there should be two 00618 // "strings" for each path. 00619 // - absolute path: specify it directly, then add 0 as second item 00620 // * example: "/usr/share/X11/rgb.txt", 0, 00621 // - KStandardDirs location: specify the filename as first item, 00622 // then add the resource as second 00623 // * example: "kdeui/rgb.txt", "data", 00624 // 00625 static const char * const path[] = { 00626 #ifdef Q_WS_X11 00627 #ifdef X11_RGBFILE 00628 X11_RGBFILE, 0, 00629 #endif 00630 "/usr/share/X11/rgb.txt", 0, 00631 "/usr/X11R6/lib/X11/rgb.txt", 0, 00632 "/usr/openwin/lib/X11/rgb.txt", 0, // for Solaris. 00633 #else /* systems without X11 */ 00634 "kdeui/rgb.txt", "data", 00635 #endif 00636 0, 0 00637 }; 00638 return path; 00639 } 00640 00641 00642 00643 00644 void 00645 KColorTable::readNamedColor(void) 00646 { 00647 if (d->mNamedColorList->count() != 0) { 00648 return; // Strings already present 00649 } 00650 00651 KGlobal::locale()->insertCatalog("kdelibs_colors4"); 00652 00653 // 00654 // Code somewhat inspired by KColorCollection. 00655 // 00656 00657 const char * const *path = namedColorFilePath(); 00658 for (int i = 0; path[i]; i += 2) { 00659 QString file; 00660 if (path[i + 1]) { 00661 file = KStandardDirs::locate(path[i + 1], QString::fromLatin1(path[i])); 00662 if (file.isEmpty()) { 00663 continue; 00664 } 00665 } else { 00666 file = QString::fromLatin1(path[i]); 00667 } 00668 00669 QFile paletteFile(file); 00670 if (!paletteFile.open(QIODevice::ReadOnly)) { 00671 continue; 00672 } 00673 00674 QByteArray line; 00675 QStringList list; 00676 while (!paletteFile.atEnd()) { 00677 line = paletteFile.readLine(); 00678 00679 int red, green, blue; 00680 int pos = 0; 00681 00682 if (sscanf(line, "%d %d %d%n", &red, &green, &blue, &pos) == 3) { 00683 // 00684 // Remove duplicates. Every name with a space and every name 00685 // that start with "gray". 00686 // 00687 QString name = line.mid(pos).trimmed(); 00688 QByteArray s1 = line.mid(pos); 00689 if (name.isNull() || name.indexOf(' ') != -1 || 00690 name.indexOf("gray") != -1 || name.indexOf("grey") != -1) { 00691 continue; 00692 } 00693 00694 const QColor color(red, green, blue); 00695 if (color.isValid()) { 00696 const QString colorName(i18nc("color", name.toLatin1().data())); 00697 list.append(colorName); 00698 d->m_namedColorMap[ colorName ] = color; 00699 } 00700 } 00701 } 00702 00703 list.sort(); 00704 d->mNamedColorList->addItems(list); 00705 break; 00706 } 00707 00708 if (d->mNamedColorList->count() == 0) { 00709 // 00710 // Give the error dialog box a chance to center above the 00711 // widget (or dialog). If we had displayed it now we could get a 00712 // situation where the (modal) error dialog box pops up first 00713 // preventing the real dialog to become visible until the 00714 // error dialog box is removed (== bad UI). 00715 // 00716 QTimer::singleShot(10, this, SLOT(slotShowNamedColorReadError())); 00717 } 00718 } 00719 00720 00721 void 00722 KColorTable::KColorTablePrivate::slotShowNamedColorReadError(void) 00723 { 00724 if (mNamedColorList->count() == 0) { 00725 QString pathMsg; 00726 int pathCount = 0; 00727 00728 const char * const *path = namedColorFilePath(); 00729 for (int i = 0; path[i]; i += 2, ++pathCount) { 00730 if (path[i + 1]) { 00731 pathMsg += QLatin1String(path[i + 1]) + ", " + QString::fromLatin1(path[i]); 00732 } else { 00733 pathMsg += QLatin1String(path[i]); 00734 } 00735 pathMsg += '\n'; 00736 } 00737 00738 QString finalMsg = i18ncp("%1 is the number of paths, %2 is the list of paths (with newlines between them)", 00739 "Unable to read X11 RGB color strings. The following " 00740 "file location was examined:\n%2", 00741 "Unable to read X11 RGB color strings. The following " 00742 "file locations were examined:\n%2", 00743 pathCount, pathMsg ); 00744 00745 KMessageBox::sorry(q, finalMsg); 00746 } 00747 } 00748 00749 00750 // 00751 // 2000-02-12 Espen Sand 00752 // Set the color in two steps. The setColors() slot will not emit a signal 00753 // with the current color setting. The reason is that setColors() is used 00754 // by the color selector dialog on startup. In the color selector dialog 00755 // we normally want to display a startup color which we specify 00756 // when the dialog is started. The slotSetColors() slot below will 00757 // set the palette and then use the information to emit a signal with the 00758 // new color setting. It is only used by the combobox widget. 00759 // 00760 void 00761 KColorTable::KColorTablePrivate::slotSetColors(const QString &_collectionName) 00762 { 00763 q->setColors(_collectionName); 00764 if (mNamedColorList->count() && mNamedColorList->isVisible()) { 00765 int item = mNamedColorList->currentRow(); 00766 mNamedColorList->setCurrentRow(item < 0 ? 0 : item); 00767 slotColorTextSelected(mNamedColorList->currentItem()->text()); 00768 } else { 00769 slotColorCellSelected(0, QColor()); // FIXME: We need to save the current value!! 00770 } 00771 } 00772 00773 00774 void 00775 KColorTable::setColors(const QString &_collectionName) 00776 { 00777 QString collectionName(_collectionName); 00778 00779 if (d->combo->currentText() != collectionName) { 00780 bool found = false; 00781 for (int i = 0; i < d->combo->count(); i++) { 00782 if (d->combo->itemText(i) == collectionName) { 00783 d->combo->setCurrentIndex(i); 00784 found = true; 00785 break; 00786 } 00787 } 00788 if (!found) { 00789 d->combo->addItem(collectionName); 00790 d->combo->setCurrentIndex(d->combo->count() - 1); 00791 } 00792 } 00793 00794 // We must again find the file name of the palette from the eventual translation 00795 for (int i = 0; colorCollectionName[i].m_fileName; ++i) { 00796 if (collectionName == i18nc("palette name", colorCollectionName[i].m_displayName)) { 00797 collectionName = colorCollectionName[i].m_fileName; 00798 break; 00799 } 00800 } 00801 00802 00803 // 00804 // 2000-02-12 Espen Sand 00805 // The palette mode "i18n_namedColors" does not use the KColorCollection 00806 // class. In fact, 'mPalette' and 'cells' are 0 when in this mode. The reason 00807 // for this is maninly that KColorCollection reads from and writes to files 00808 // using "locate()". The colors used in "i18n_namedColors" mode comes from 00809 // the X11 diretory and is not writable. I don't think this fit in 00810 // KColorCollection. 00811 // 00812 if (!d->mPalette || d->mPalette->name() != collectionName) { 00813 if (collectionName == d->i18n_namedColors) { 00814 d->sv->hide(); 00815 d->mNamedColorList->show(); 00816 readNamedColor(); 00817 00818 delete d->cells; d->cells = 0; 00819 delete d->mPalette; d->mPalette = 0; 00820 } else { 00821 d->mNamedColorList->hide(); 00822 d->sv->show(); 00823 00824 delete d->cells; 00825 delete d->mPalette; 00826 d->mPalette = new KColorCollection(collectionName); 00827 int rows = (d->mPalette->count() + d->mCols - 1) / d->mCols; 00828 if (rows < 1) rows = 1; 00829 d->cells = new KColorCells(d->sv->viewport(), rows, d->mCols); 00830 d->cells->setShading(false); 00831 d->cells->setAcceptDrags(false); 00832 QSize cellSize = QSize(d->mMinWidth, d->mMinWidth * rows / d->mCols); 00833 d->cells->setFixedSize(cellSize); 00834 for (int i = 0; i < d->mPalette->count(); i++) { 00835 d->cells->setColor(i, d->mPalette->color(i)); 00836 } 00837 connect(d->cells, SIGNAL(colorSelected(int , const QColor&)), 00838 SLOT(slotColorCellSelected(int , const QColor&))); 00839 connect(d->cells, SIGNAL(colorDoubleClicked(int , const QColor&)), 00840 SLOT(slotColorCellDoubleClicked(int , const QColor&))); 00841 d->sv->setWidget(d->cells); 00842 d->cells->show(); 00843 00844 //d->sv->updateScrollBars(); 00845 } 00846 } 00847 } 00848 00849 00850 00851 void 00852 KColorTable::KColorTablePrivate::slotColorCellSelected(int index , const QColor& /*color*/) 00853 { 00854 if (!mPalette || (index >= mPalette->count())) 00855 return; 00856 emit q->colorSelected(mPalette->color(index), mPalette->name(index)); 00857 } 00858 00859 void 00860 KColorTable::KColorTablePrivate::slotColorCellDoubleClicked(int index , const QColor& /*color*/) 00861 { 00862 if (!mPalette || (index >= mPalette->count())) 00863 return; 00864 emit q->colorDoubleClicked(mPalette->color(index), mPalette->name(index)); 00865 } 00866 00867 00868 void 00869 KColorTable::KColorTablePrivate::slotColorTextSelected(const QString &colorText) 00870 { 00871 emit q->colorSelected(m_namedColorMap[ colorText ], colorText); 00872 } 00873 00874 00875 void 00876 KColorTable::addToCustomColors(const QColor &color) 00877 { 00878 setColors(i18nc("palette name", colorCollectionName[customColorIndex].m_displayName)); 00879 d->mPalette->addColor(color); 00880 d->mPalette->save(); 00881 delete d->mPalette; 00882 d->mPalette = 0; 00883 setColors(i18nc("palette name", colorCollectionName[customColorIndex].m_displayName)); 00884 } 00885 00886 void 00887 KColorTable::addToRecentColors(const QColor &color) 00888 { 00889 // 00890 // 2000-02-12 Espen Sand. 00891 // The 'mPalette' is always 0 when current mode is i18n_namedColors 00892 // 00893 bool recentIsSelected = false; 00894 if (d->mPalette && d->mPalette->name() == colorCollectionName[ recentColorIndex ].m_fileName) { 00895 delete d->mPalette; 00896 d->mPalette = 0; 00897 recentIsSelected = true; 00898 } 00899 KColorCollection *recentPal = new KColorCollection(colorCollectionName[ recentColorIndex ].m_fileName); 00900 if (recentPal->findColor(color) == -1) { 00901 recentPal->addColor(color); 00902 recentPal->save(); 00903 } 00904 delete recentPal; 00905 if (recentIsSelected) 00906 setColors(i18nc("palette name", colorCollectionName[ recentColorIndex ].m_displayName)); 00907 } 00908 00909 class KCDPickerFilter; 00910 00911 class KColorDialog::KColorDialogPrivate 00912 { 00913 public: 00914 KColorDialogPrivate(KColorDialog *q): q(q) {} 00915 00916 void setRgbEdit(const QColor &col); 00917 void setHsvEdit(const QColor &col); 00918 void setHtmlEdit(const QColor &col); 00919 void _setColor(const QColor &col, const QString &name = QString()); 00920 void showColor(const QColor &color, const QString &name); 00921 00922 void slotRGBChanged(void); 00923 void slotAlphaChanged(void); 00924 void slotHSVChanged(void); 00925 void slotHtmlChanged(void); 00926 void slotHSChanged(int, int); 00927 void slotVChanged(int); 00928 void slotAChanged(int); 00929 void slotModeChanged(int); 00930 00931 void slotColorSelected(const QColor &col); 00932 void slotColorSelected(const QColor &col, const QString &name); 00933 void slotColorDoubleClicked(const QColor &col, const QString &name); 00934 void slotColorPicker(); 00935 void slotAddToCustomColors(); 00936 void slotDefaultColorClicked(); 00940 void slotWriteSettings(); 00941 00945 KColorChooserMode chooserMode(); 00946 00950 void setChooserMode(KColorChooserMode c); 00951 00952 KColorDialog *q; 00953 KColorTable *table; 00954 QString originalPalette; 00955 bool bRecursion; 00956 bool bEditRgb; 00957 bool bEditHsv; 00958 bool bEditHtml; 00959 bool bColorPicking; 00960 bool bAlphaEnabled; 00961 QLabel *colorName; 00962 KLineEdit *htmlName; 00963 KIntSpinBox *hedit; 00964 KIntSpinBox *sedit; 00965 KIntSpinBox *vedit; 00966 KIntSpinBox *redit; 00967 KIntSpinBox *gedit; 00968 KIntSpinBox *bedit; 00969 QWidget *alphaLabel; 00970 KIntSpinBox *aedit; 00971 00972 KColorPatch *patch; 00973 KColorPatch *comparePatch; 00974 00975 KColorChooserMode _mode; 00976 QButtonGroup *modeGroup; 00977 00978 KHueSaturationSelector *hsSelector; 00979 KColorCollection *palette; 00980 KColorValueSelector *valuePal; 00981 KGradientSelector *alphaSelector; 00982 QVBoxLayout* l_right; 00983 QGridLayout* tl_layout; 00984 QCheckBox *cbDefaultColor; 00985 QColor defaultColor; 00986 QColor selColor; 00987 #ifdef Q_WS_X11 00988 KCDPickerFilter* filter; 00989 #endif 00990 }; 00991 00992 #ifdef Q_WS_X11 00993 class KCDPickerFilter: public QWidget 00994 { 00995 public: 00996 KCDPickerFilter(QWidget* parent): QWidget(parent) {} 00997 00998 virtual bool x11Event(XEvent* event) { 00999 if (event->type == ButtonRelease) { 01000 QMouseEvent e(QEvent::MouseButtonRelease, QPoint(), 01001 QPoint(event->xmotion.x_root, event->xmotion.y_root) , Qt::NoButton, Qt::NoButton, Qt::NoModifier); 01002 QApplication::sendEvent(parentWidget(), &e); 01003 return true; 01004 } else return false; 01005 } 01006 }; 01007 01008 #endif 01009 01010 01011 KColorDialog::KColorDialog(QWidget *parent, bool modal) 01012 : KDialog(parent), d(new KColorDialogPrivate(this)) 01013 { 01014 setCaption(i18n("Select Color")); 01015 setButtons(modal ? Ok | Cancel : Close); 01016 setModal(modal); 01017 d->bRecursion = true; 01018 d->bColorPicking = false; 01019 d->bAlphaEnabled = false; 01020 #ifdef Q_WS_X11 01021 d->filter = 0; 01022 #endif 01023 d->cbDefaultColor = 0L; 01024 d->_mode = ChooserClassic; 01025 connect(this, SIGNAL(okClicked(void)), this, SLOT(slotWriteSettings(void))); 01026 connect(this, SIGNAL(closeClicked(void)), this, SLOT(slotWriteSettings(void))); 01027 01028 QLabel *label; 01029 01030 // 01031 // Create the top level page and its layout 01032 // 01033 QWidget *page = new QWidget(this); 01034 setMainWidget(page); 01035 01036 QGridLayout *tl_layout = new QGridLayout(page); 01037 tl_layout->setMargin(0); 01038 d->tl_layout = tl_layout; 01039 tl_layout->addItem(new QSpacerItem(spacingHint()*2, 0), 0, 1); 01040 01041 // 01042 // the more complicated part: the left side 01043 // add a V-box 01044 // 01045 QVBoxLayout *l_left = new QVBoxLayout(); 01046 tl_layout->addLayout(l_left, 0, 0); 01047 01048 // 01049 // add a H-Box for the XY-Selector and a grid for the 01050 // entry fields 01051 // 01052 QHBoxLayout *l_ltop = new QHBoxLayout(); 01053 l_left->addLayout(l_ltop); 01054 01055 // 01056 // the palette and value selector go into the H-box 01057 // 01058 d->hsSelector = new KHueSaturationSelector(page); 01059 d->hsSelector->setMinimumSize(256, 256); 01060 l_ltop->addWidget(d->hsSelector, 8); 01061 connect(d->hsSelector, SIGNAL(valueChanged(int, int)), 01062 SLOT(slotHSChanged(int, int))); 01063 01064 d->valuePal = new KColorValueSelector(page); 01065 d->valuePal->setMinimumSize(26, 70); 01066 d->valuePal->setIndent(false); 01067 d->valuePal->setArrowDirection(Qt::RightArrow); 01068 l_ltop->addWidget(d->valuePal, 1); 01069 connect(d->valuePal, SIGNAL(valueChanged(int)), 01070 SLOT(slotVChanged(int))); 01071 01072 d->alphaSelector = new KGradientSelector(Qt::Horizontal, page); 01073 d->alphaSelector->setFixedSize(256, 26); 01074 d->alphaSelector->setIndent(false); 01075 d->alphaSelector->setArrowDirection(Qt::DownArrow); 01076 d->alphaSelector->setRange(0, 255); 01077 l_left->addWidget(d->alphaSelector, 1); 01078 connect(d->alphaSelector, SIGNAL(valueChanged(int)), 01079 SLOT(slotAChanged(int))); 01080 01081 // a little space between 01082 l_left->addSpacing(10); // FIXME: remove hardcoded values 01083 01084 QGridLayout *l_lbot = new QGridLayout(); 01085 l_left->addLayout(l_lbot); 01086 01087 // button group that manages the radio buttons 01088 QRadioButton *modeButton; 01089 d->modeGroup = new QButtonGroup(page); 01090 connect(d->modeGroup, SIGNAL(buttonClicked(int)), SLOT(slotModeChanged(int))); 01091 01092 // 01093 // add the HSV fields 01094 // 01095 l_lbot->setColumnStretch(2, 10); 01096 01097 modeButton = new QRadioButton(i18n("Hue:"), page); 01098 l_lbot->addWidget(modeButton, 0, 0); 01099 d->modeGroup->addButton(modeButton, ChooserHue); 01100 01101 d->hedit = new KIntSpinBox(page); 01102 d->hedit->setMaximum(359); 01103 d->hedit->setSuffix(i18nc("The angular degree unit (for hue)", "\302\260")); // U+00B0 DEGREE SIGN 01104 l_lbot->addWidget(d->hedit, 0, 1); 01105 connect(d->hedit, SIGNAL(valueChanged(int)), 01106 SLOT(slotHSVChanged())); 01107 01108 modeButton = new QRadioButton(i18n("Saturation:"), page); 01109 l_lbot->addWidget(modeButton, 1, 0); 01110 d->modeGroup->addButton(modeButton, ChooserSaturation); 01111 01112 d->sedit = new KIntSpinBox(page); 01113 d->sedit->setMaximum(255); 01114 l_lbot->addWidget(d->sedit, 1, 1); 01115 connect(d->sedit, SIGNAL(valueChanged(int)), 01116 SLOT(slotHSVChanged())); 01117 01118 modeButton = new QRadioButton(i18nc("This is the V of HSV", "Value:"), page); 01119 l_lbot->addWidget(modeButton, 2, 0); 01120 d->modeGroup->addButton(modeButton, ChooserValue); 01121 01122 d->vedit = new KIntSpinBox(page); 01123 d->vedit->setMaximum(255); 01124 l_lbot->addWidget(d->vedit, 2, 1); 01125 connect(d->vedit, SIGNAL(valueChanged(int)), 01126 SLOT(slotHSVChanged())); 01127 01128 01129 // 01130 // add the RGB fields 01131 // 01132 modeButton = new QRadioButton(i18n("Red:"), page); 01133 l_lbot->addWidget(modeButton, 0, 3); 01134 d->modeGroup->addButton(modeButton, ChooserRed); 01135 01136 d->redit = new KIntSpinBox(page); 01137 d->redit->setMaximum(255); 01138 l_lbot->addWidget(d->redit, 0, 4); 01139 connect(d->redit, SIGNAL(valueChanged(int)), 01140 SLOT(slotRGBChanged())); 01141 01142 modeButton = new QRadioButton(i18n("Green:"), page); 01143 l_lbot->addWidget(modeButton, 1, 3); 01144 d->modeGroup->addButton(modeButton, ChooserGreen); 01145 01146 d->gedit = new KIntSpinBox(page); 01147 d->gedit->setMaximum(255); 01148 l_lbot->addWidget(d->gedit, 1, 4); 01149 connect(d->gedit, SIGNAL(valueChanged(int)), 01150 SLOT(slotRGBChanged())); 01151 01152 modeButton = new QRadioButton(i18n("Blue:"), page); 01153 l_lbot->addWidget(modeButton, 2, 3); 01154 d->modeGroup->addButton(modeButton, ChooserBlue); 01155 01156 d->bedit = new KIntSpinBox(page); 01157 d->bedit->setMaximum(255); 01158 l_lbot->addWidget(d->bedit, 2, 4); 01159 connect(d->bedit, SIGNAL(valueChanged(int)), 01160 SLOT(slotRGBChanged())); 01161 01162 d->alphaLabel = new KHBox(page); 01163 QWidget *spacer = new QWidget(d->alphaLabel); 01164 label = new QLabel(i18n("Alpha:"), d->alphaLabel); 01165 QStyleOptionButton option; 01166 option.initFrom(modeButton); 01167 QRect labelRect = modeButton->style()->subElementRect(QStyle::SE_RadioButtonContents, &option, modeButton); 01168 int indent = layoutDirection() == Qt::LeftToRight ? labelRect.left() : modeButton->geometry().right() - labelRect.right(); 01169 spacer->setFixedWidth(indent); 01170 l_lbot->addWidget(d->alphaLabel, 3, 3); 01171 01172 d->aedit = new KIntSpinBox(page); 01173 d->aedit->setMaximum(255); 01174 label->setBuddy(d->aedit); 01175 l_lbot->addWidget(d->aedit, 3, 4); 01176 connect(d->aedit, SIGNAL(valueChanged(int)), 01177 SLOT(slotAlphaChanged())); 01178 01179 d->aedit->setVisible(false); 01180 d->alphaLabel->setVisible(false); 01181 d->alphaSelector->setVisible(false); 01182 01183 // 01184 // add a layout for the right side 01185 // 01186 d->l_right = new QVBoxLayout; 01187 tl_layout->addLayout(d->l_right, 0, 2); 01188 01189 // 01190 // Add the palette table 01191 // 01192 d->table = new KColorTable(page); 01193 d->l_right->addWidget(d->table, 10); 01194 01195 connect(d->table, SIGNAL(colorSelected(const QColor &, const QString &)), 01196 SLOT(slotColorSelected(const QColor &, const QString &))); 01197 01198 connect( 01199 d->table, 01200 SIGNAL(colorDoubleClicked(const QColor &, const QString &)), 01201 SLOT(slotColorDoubleClicked(const QColor &, const QString &)) 01202 ); 01203 // Store the default value for saving time. 01204 d->originalPalette = d->table->name(); 01205 01206 // 01207 // a little space between 01208 // 01209 d->l_right->addSpacing(10); 01210 01211 QHBoxLayout *l_hbox = new QHBoxLayout(); 01212 d->l_right->addItem(l_hbox); 01213 01214 // 01215 // The add to custom colors button 01216 // 01217 QPushButton *addButton = new QPushButton(page); 01218 addButton->setText(i18n("&Add to Custom Colors")); 01219 l_hbox->addWidget(addButton, 0, Qt::AlignLeft); 01220 connect(addButton, SIGNAL(clicked()), SLOT(slotAddToCustomColors())); 01221 01222 // 01223 // The color picker button 01224 // 01225 QPushButton* button = new QPushButton(page); 01226 button->setIcon(KIcon("color-picker")); 01227 int commonHeight = addButton->sizeHint().height(); 01228 button->setFixedSize(commonHeight, commonHeight); 01229 l_hbox->addWidget(button, 0, Qt::AlignHCenter); 01230 connect(button, SIGNAL(clicked()), SLOT(slotColorPicker())); 01231 01232 // 01233 // a little space between 01234 // 01235 d->l_right->addSpacing(10); 01236 01237 // 01238 // and now the entry fields and the patch (=colored box) 01239 // 01240 QGridLayout *l_grid = new QGridLayout(); 01241 d->l_right->addLayout(l_grid); 01242 01243 l_grid->setColumnStretch(2, 1); 01244 01245 label = new QLabel(page); 01246 label->setText(i18n("Name:")); 01247 l_grid->addWidget(label, 0, 1, Qt::AlignLeft); 01248 01249 d->colorName = new QLabel(page); 01250 l_grid->addWidget(d->colorName, 0, 2, Qt::AlignLeft); 01251 01252 label = new QLabel(page); 01253 label->setText(i18n("HTML:")); 01254 l_grid->addWidget(label, 1, 1, Qt::AlignLeft); 01255 01256 d->htmlName = new KLineEdit(page); 01257 d->htmlName->setMaxLength(13); // Qt's QColor allows 12 hexa-digits 01258 d->htmlName->setText("#FFFFFF"); // But HTML uses only 6, so do not worry about the size 01259 int w = d->htmlName->fontMetrics().width(QLatin1String("#DDDDDDD")); 01260 d->htmlName->setFixedWidth(w); 01261 l_grid->addWidget(d->htmlName, 1, 2, Qt::AlignLeft); 01262 01263 connect(d->htmlName, SIGNAL(textChanged(const QString &)), 01264 SLOT(slotHtmlChanged())); 01265 01266 d->patch = new KColorPatch(page); 01267 d->patch->setFixedSize(48, 48); 01268 l_grid->addWidget(d->patch, 0, 0, 2, 1, Qt::AlignHCenter | Qt::AlignVCenter); 01269 connect(d->patch, SIGNAL(colorChanged(const QColor&)), 01270 SLOT(setColor(const QColor&))); 01271 01272 // 01273 // chain fields together 01274 // 01275 setTabOrder(d->hedit, d->sedit); 01276 setTabOrder(d->sedit, d->vedit); 01277 setTabOrder(d->vedit, d->redit); 01278 setTabOrder(d->redit, d->gedit); 01279 setTabOrder(d->gedit, d->bedit); 01280 setTabOrder(d->bedit, d->aedit); 01281 01282 tl_layout->activate(); 01283 page->setMinimumSize(page->sizeHint()); 01284 01285 readSettings(); 01286 d->bRecursion = false; 01287 d->bEditHsv = false; 01288 d->bEditRgb = false; 01289 d->bEditHtml = false; 01290 01291 setFixedSize(sizeHint()); 01292 QColor col; 01293 col.setHsv(0, 0, 255); 01294 d->_setColor(col); 01295 01296 // FIXME: with enabled event filters, it crashes after ever enter of a drag. 01297 // better disable drag and drop than crashing it... 01298 // d->htmlName->installEventFilter(this); 01299 // d->hsSelector->installEventFilter(this); 01300 d->hsSelector->setAcceptDrops(true); 01301 01302 d->setChooserMode(ChooserValue); 01303 } 01304 01305 KColorDialog::~KColorDialog() 01306 { 01307 #ifdef Q_WS_X11 01308 if (d->bColorPicking && kapp) 01309 kapp->removeX11EventFilter(d->filter); 01310 #endif 01311 delete d; 01312 } 01313 01314 bool 01315 KColorDialog::eventFilter(QObject *obj, QEvent *ev) 01316 { 01317 if ((obj == d->htmlName) || (obj == d->hsSelector)) 01318 switch (ev->type()) { 01319 case QEvent::DragEnter: 01320 case QEvent::DragMove: 01321 case QEvent::DragLeave: 01322 case QEvent::Drop: 01323 case QEvent::DragResponse: 01324 qApp->sendEvent(d->patch, ev); 01325 return true; 01326 default: 01327 break; 01328 } 01329 return KDialog::eventFilter(obj, ev); 01330 } 01331 01332 void 01333 KColorDialog::setDefaultColor(const QColor& col) 01334 { 01335 if (!d->cbDefaultColor) { 01336 // 01337 // a little space between 01338 // 01339 d->l_right->addSpacing(10); 01340 01341 // 01342 // and the "default color" checkbox, under all items on the right side 01343 // 01344 d->cbDefaultColor = new QCheckBox(i18n("Default color"), mainWidget()); 01345 01346 d->l_right->addWidget(d->cbDefaultColor); 01347 01348 mainWidget()->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); // cancel setFixedSize() 01349 d->tl_layout->activate(); 01350 mainWidget()->setMinimumSize(mainWidget()->sizeHint()); 01351 setFixedSize(sizeHint()); 01352 01353 connect(d->cbDefaultColor, SIGNAL(clicked()), SLOT(slotDefaultColorClicked())); 01354 } 01355 01356 d->defaultColor = col; 01357 01358 d->slotDefaultColorClicked(); 01359 } 01360 01361 QColor KColorDialog::defaultColor() const 01362 { 01363 return d->defaultColor; 01364 } 01365 01366 void KColorDialog::setAlphaChannelEnabled(bool alpha) 01367 { 01368 if (d->bAlphaEnabled != alpha) { 01369 d->bAlphaEnabled = alpha; 01370 d->aedit->setVisible(d->bAlphaEnabled); 01371 d->alphaLabel->setVisible(d->bAlphaEnabled); 01372 d->alphaSelector->setVisible(d->bAlphaEnabled); 01373 01374 mainWidget()->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); // cancel setFixedSize() 01375 d->tl_layout->activate(); 01376 mainWidget()->setMinimumSize(mainWidget()->sizeHint()); 01377 setFixedSize(sizeHint()); 01378 } 01379 } 01380 01381 bool KColorDialog::isAlphaChannelEnabled() const 01382 { 01383 return d->bAlphaEnabled; 01384 } 01385 01386 01387 void KColorDialog::KColorDialogPrivate::setChooserMode(KColorChooserMode c) 01388 { 01389 _mode = c; 01390 hsSelector->setChooserMode(c); 01391 valuePal->setChooserMode(c); 01392 01393 modeGroup->button(valuePal->chooserMode())->setChecked(true); 01394 valuePal->updateContents(); 01395 hsSelector->updateContents(); 01396 valuePal->update(); 01397 hsSelector->update(); 01398 slotHSVChanged(); 01399 } 01400 01401 01402 KColorChooserMode KColorDialog::KColorDialogPrivate::chooserMode() 01403 { 01404 return _mode; 01405 } 01406 01407 void KColorDialog::KColorDialogPrivate::slotDefaultColorClicked() 01408 { 01409 if (cbDefaultColor->isChecked()) { 01410 selColor = defaultColor; 01411 showColor(selColor, i18n("-default-")); 01412 } else { 01413 showColor(selColor, QString()); 01414 } 01415 emit q->colorSelected(selColor); 01416 } 01417 01418 void 01419 KColorDialog::KColorDialogPrivate::slotModeChanged(int id) 01420 { 01421 setChooserMode(KColorChooserMode(id)); 01422 } 01423 01424 void 01425 KColorDialog::readSettings() 01426 { 01427 KConfigGroup group(KGlobal::config(), "Colors"); 01428 01429 QString collectionName = group.readEntry("CurrentPalette"); 01430 if (collectionName.isEmpty()) { 01431 collectionName = i18nc("palette name", colorCollectionName[fortyColorIndex].m_displayName); 01432 } else { 01433 for (int i = 0; colorCollectionName[i].m_fileName; ++i) { 01434 if (collectionName == colorCollectionName[i].m_displayName) { 01435 collectionName = i18nc("palette name", colorCollectionName[i].m_displayName); 01436 break; 01437 } 01438 } 01439 } 01440 01441 d->table->setColors(collectionName); 01442 } 01443 01444 void 01445 KColorDialog::KColorDialogPrivate::slotWriteSettings() 01446 { 01447 KConfigGroup group(KGlobal::config(), "Colors"); 01448 01449 QString collectionName = table->name(); 01450 if (!group.hasDefault("CurrentPalette") && table->name() == originalPalette) { 01451 group.revertToDefault("CurrentPalette"); 01452 } else { 01453 QString collectionName(table->name()); 01454 for (int i = 0; colorCollectionName[i].m_fileName; ++i) { 01455 if (collectionName == i18nc("palette name", colorCollectionName[i].m_displayName)) { 01456 collectionName = colorCollectionName[i].m_displayName; 01457 break; 01458 } 01459 } 01460 group.writeEntry("CurrentPalette", collectionName); //Make sure the untranslated name is saved, assuming there is one 01461 } 01462 } 01463 01464 QColor 01465 KColorDialog::color() const 01466 { 01467 if (d->cbDefaultColor && d->cbDefaultColor->isChecked()) 01468 return QColor(); 01469 if (d->selColor.isValid()) 01470 d->table->addToRecentColors(d->selColor); 01471 return d->selColor; 01472 } 01473 01474 void KColorDialog::setColor(const QColor &col) 01475 { 01476 d->_setColor(col); 01477 } 01478 01479 // 01480 // static function to display dialog and return color 01481 // 01482 int KColorDialog::getColor(QColor &theColor, QWidget *parent) 01483 { 01484 KColorDialog dlg(parent, true); 01485 dlg.setObjectName("Color Selector"); 01486 if (theColor.isValid()) 01487 dlg.setColor(theColor); 01488 int result = dlg.exec(); 01489 01490 if (result == Accepted) { 01491 theColor = dlg.color(); 01492 } 01493 01494 return result; 01495 } 01496 01497 // 01498 // static function to display dialog and return color 01499 // 01500 int KColorDialog::getColor(QColor &theColor, const QColor& defaultCol, QWidget *parent) 01501 { 01502 KColorDialog dlg(parent, true); 01503 dlg.setObjectName("Color Selector"); 01504 dlg.setDefaultColor(defaultCol); 01505 dlg.setColor(theColor); 01506 int result = dlg.exec(); 01507 01508 if (result == Accepted) 01509 theColor = dlg.color(); 01510 01511 return result; 01512 } 01513 01514 void KColorDialog::KColorDialogPrivate::slotRGBChanged(void) 01515 { 01516 if (bRecursion) return; 01517 int red = redit->value(); 01518 int grn = gedit->value(); 01519 int blu = bedit->value(); 01520 01521 if (red > 255 || red < 0) return; 01522 if (grn > 255 || grn < 0) return; 01523 if (blu > 255 || blu < 0) return; 01524 01525 QColor col; 01526 col.setRgb(red, grn, blu, aedit->value()); 01527 bEditRgb = true; 01528 _setColor(col); 01529 bEditRgb = false; 01530 } 01531 01532 void KColorDialog::KColorDialogPrivate::slotAlphaChanged(void) 01533 { 01534 if (bRecursion) return; 01535 int alpha = aedit->value(); 01536 01537 if (alpha > 255 || alpha < 0) return; 01538 01539 QColor col = selColor; 01540 col.setAlpha(alpha); 01541 _setColor(col); 01542 } 01543 01544 void KColorDialog::KColorDialogPrivate::slotHtmlChanged(void) 01545 { 01546 if (bRecursion || htmlName->text().isEmpty()) return; 01547 01548 QString strColor(htmlName->text()); 01549 01550 // Assume that a user does not want to type the # all the time 01551 if (strColor[0] != '#') { 01552 bool signalsblocked = htmlName->blockSignals(true); 01553 strColor.prepend("#"); 01554 htmlName->setText(strColor); 01555 htmlName->blockSignals(signalsblocked); 01556 } 01557 01558 const QColor color(strColor); 01559 01560 if (color.isValid()) { 01561 QColor col(color); 01562 bEditHtml = true; 01563 _setColor(col); 01564 bEditHtml = false; 01565 } 01566 } 01567 01568 void KColorDialog::KColorDialogPrivate::slotHSVChanged(void) 01569 { 01570 if (bRecursion) return; 01571 int hue = hedit->value(); 01572 int sat = sedit->value(); 01573 int val = vedit->value(); 01574 01575 if (hue > 359 || hue < 0) return; 01576 if (sat > 255 || sat < 0) return; 01577 if (val > 255 || val < 0) return; 01578 01579 QColor col; 01580 col.setHsv(hue, sat, val, aedit->value()); 01581 bEditHsv = true; 01582 _setColor(col); 01583 bEditHsv = false; 01584 } 01585 01586 void KColorDialog::KColorDialogPrivate::slotHSChanged(int x, int y) 01587 { 01588 QColor col = selColor; 01589 KColorChooserMode xMode = chooserXMode(chooserMode()); 01590 KColorChooserMode yMode = chooserYMode(chooserMode()); 01591 setComponentValue(col, xMode, x / (xMode == ChooserHue ? 360.0 : 255.0)); 01592 setComponentValue(col, yMode, y / (yMode == ChooserHue ? 360.0 : 255.0)); 01593 _setColor(col); 01594 } 01595 01596 void KColorDialog::KColorDialogPrivate::slotVChanged(int v) 01597 { 01598 QColor col = selColor; 01599 setComponentValue(col, chooserMode(), v / (chooserMode() == ChooserHue ? 360.0 : 255.0)); 01600 _setColor(col); 01601 } 01602 01603 void KColorDialog::KColorDialogPrivate::slotAChanged(int value) 01604 { 01605 QColor col = selColor; 01606 col.setAlpha(value); 01607 _setColor(col); 01608 } 01609 01610 void KColorDialog::KColorDialogPrivate::slotColorSelected(const QColor &color) 01611 { 01612 _setColor(color); 01613 } 01614 01615 void KColorDialog::KColorDialogPrivate::slotAddToCustomColors() 01616 { 01617 table->addToCustomColors(selColor); 01618 } 01619 01620 void KColorDialog::KColorDialogPrivate::slotColorSelected(const QColor &color, const QString &name) 01621 { 01622 _setColor(color, name); 01623 } 01624 01625 void KColorDialog::KColorDialogPrivate::slotColorDoubleClicked 01626 ( 01627 const QColor & color, 01628 const QString & name 01629 ) 01630 { 01631 _setColor(color, name); 01632 q->accept(); 01633 } 01634 01635 void KColorDialog::KColorDialogPrivate::_setColor(const QColor &color, const QString &name) 01636 { 01637 if (color.isValid()) { 01638 if (cbDefaultColor && cbDefaultColor->isChecked()) 01639 cbDefaultColor->setChecked(false); 01640 selColor = color; 01641 } else { 01642 if (cbDefaultColor && cbDefaultColor->isChecked()) 01643 cbDefaultColor->setChecked(true); 01644 selColor = defaultColor; 01645 } 01646 01647 showColor(selColor, name); 01648 01649 emit q->colorSelected(selColor); 01650 } 01651 01652 // show but don't set into selColor, nor emit colorSelected 01653 void KColorDialog::KColorDialogPrivate::showColor(const QColor &color, const QString &name) 01654 { 01655 bRecursion = true; 01656 01657 if (name.isEmpty()) 01658 colorName->setText(i18n("-unnamed-")); 01659 else 01660 colorName->setText(name); 01661 01662 patch->setColor(color); 01663 01664 setRgbEdit(color); 01665 setHsvEdit(color); 01666 setHtmlEdit(color); 01667 aedit->setValue(color.alpha()); 01668 01669 QColor rgbColor = color.toRgb(); 01670 bool ltr = q->layoutDirection() == Qt::LeftToRight; 01671 rgbColor.setAlpha(ltr ? 0 : 255); 01672 alphaSelector->setFirstColor(rgbColor); 01673 rgbColor.setAlpha(ltr ? 255 : 0); 01674 alphaSelector->setSecondColor(rgbColor); 01675 alphaSelector->setValue(color.alpha()); 01676 01677 KColorChooserMode xMode = chooserXMode(chooserMode()); 01678 KColorChooserMode yMode = chooserYMode(chooserMode()); 01679 int xValue = qRound(getComponentValue(color, xMode) * (xMode == ChooserHue ? 360.0 : 255.0)); 01680 int yValue = qRound(getComponentValue(color, yMode) * (yMode == ChooserHue ? 360.0 : 255.0)); 01681 int value = qRound(getComponentValue(color, chooserMode()) * (chooserMode() == ChooserHue ? 360.0 : 255.0)); 01682 hsSelector->setValues(xValue, yValue); 01683 valuePal->setValue(value); 01684 01685 bool blocked = valuePal->blockSignals(true); 01686 01687 valuePal->setHue(color.hue()); 01688 valuePal->setSaturation(color.saturation()); 01689 valuePal->setColorValue(color.value()); 01690 valuePal->updateContents(); 01691 valuePal->blockSignals(blocked); 01692 valuePal->update(); 01693 01694 blocked = hsSelector->blockSignals(true); 01695 01696 hsSelector->setHue(color.hue()); 01697 hsSelector->setSaturation(color.saturation()); 01698 hsSelector->setColorValue(color.value()); 01699 hsSelector->updateContents(); 01700 hsSelector->blockSignals(blocked); 01701 hsSelector->update(); 01702 01703 bRecursion = false; 01704 } 01705 01706 01707 01708 void 01709 KColorDialog::KColorDialogPrivate::slotColorPicker() 01710 { 01711 bColorPicking = true; 01712 #ifdef Q_WS_X11 01713 filter = new KCDPickerFilter(q); 01714 kapp->installX11EventFilter(filter); 01715 #endif 01716 q->grabMouse(Qt::CrossCursor); 01717 q->grabKeyboard(); 01718 } 01719 01720 void 01721 KColorDialog::mouseMoveEvent(QMouseEvent *e) 01722 { 01723 if (d->bColorPicking) { 01724 d->_setColor(grabColor(e->globalPos())); 01725 return; 01726 } 01727 01728 KDialog::mouseMoveEvent(e); 01729 } 01730 01731 void 01732 KColorDialog::mouseReleaseEvent(QMouseEvent *e) 01733 { 01734 if (d->bColorPicking) { 01735 d->bColorPicking = false; 01736 #ifdef Q_WS_X11 01737 kapp->removeX11EventFilter(d->filter); 01738 delete d->filter; d->filter = 0; 01739 #endif 01740 releaseMouse(); 01741 releaseKeyboard(); 01742 d->_setColor(grabColor(e->globalPos())); 01743 return; 01744 } 01745 KDialog::mouseReleaseEvent(e); 01746 } 01747 01748 QColor 01749 KColorDialog::grabColor(const QPoint &p) 01750 { 01751 #ifdef Q_WS_X11 01752 // we use the X11 API directly in this case as we are not getting back a valid 01753 // return from QPixmap::grabWindow in the case where the application is using 01754 // an argb visual 01755 if( !qApp->desktop()->geometry().contains( p )) 01756 return QColor(); 01757 Window root = RootWindow(QX11Info::display(), QX11Info::appScreen()); 01758 XImage *ximg = XGetImage(QX11Info::display(), root, p.x(), p.y(), 1, 1, -1, ZPixmap); 01759 unsigned long xpixel = XGetPixel(ximg, 0, 0); 01760 XDestroyImage(ximg); 01761 XColor xcol; 01762 xcol.pixel = xpixel; 01763 xcol.flags = DoRed | DoGreen | DoBlue; 01764 XQueryColor(QX11Info::display(), 01765 DefaultColormap(QX11Info::display(), QX11Info::appScreen()), 01766 &xcol); 01767 return QColor::fromRgbF(xcol.red / 65535.0, xcol.green / 65535.0, xcol.blue / 65535.0); 01768 #else 01769 QWidget *desktop = QApplication::desktop(); 01770 QPixmap pm = QPixmap::grabWindow(desktop->winId(), p.x(), p.y(), 1, 1); 01771 QImage i = pm.toImage(); 01772 return i.pixel(0, 0); 01773 #endif 01774 } 01775 01776 void 01777 KColorDialog::keyPressEvent(QKeyEvent *e) 01778 { 01779 if (d->bColorPicking) { 01780 if (e->key() == Qt::Key_Escape) { 01781 d->bColorPicking = false; 01782 #ifdef Q_WS_X11 01783 kapp->removeX11EventFilter(d->filter); 01784 delete d->filter; d->filter = 0; 01785 #endif 01786 releaseMouse(); 01787 releaseKeyboard(); 01788 } 01789 e->accept(); 01790 return; 01791 } 01792 KDialog::keyPressEvent(e); 01793 } 01794 01795 void KColorDialog::KColorDialogPrivate::setRgbEdit(const QColor &col) 01796 { 01797 if (bEditRgb) return; 01798 int r, g, b; 01799 col.getRgb(&r, &g, &b); 01800 01801 redit->setValue(r); 01802 gedit->setValue(g); 01803 bedit->setValue(b); 01804 } 01805 01806 void KColorDialog::KColorDialogPrivate::setHtmlEdit(const QColor &col) 01807 { 01808 if (bEditHtml) return; 01809 int r, g, b; 01810 col.getRgb(&r, &g, &b); 01811 QString num; 01812 01813 num.sprintf("#%02X%02X%02X", r, g, b); 01814 htmlName->setText(num); 01815 } 01816 01817 01818 void KColorDialog::KColorDialogPrivate::setHsvEdit(const QColor &col) 01819 { 01820 if (bEditHsv) return; 01821 int h, s, v; 01822 col.getHsv(&h, &s, &v); 01823 01824 hedit->setValue(h); 01825 sedit->setValue(s); 01826 vedit->setValue(v); 01827 } 01828 01829 #include "kcolordialog.moc" 01830 #include "kcolordialog_p.moc"
KDE 4.6 API Reference