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

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"

KDEUI

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal