KDEUI
kcolorcombo.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 Pino Toscano (pino@kde.org) 00004 Copyright (c) 2007 David Jarvie (software@astrojar.org.uk) 00005 00006 This library is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU Library General Public 00008 License as published by the Free Software Foundation; either 00009 version 2 of the License, or (at your option) any later version. 00010 00011 This library is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 Library General Public License for more details. 00015 00016 You should have received a copy of the GNU Library General Public License 00017 along with this library; see the file COPYING.LIB. If not, write to 00018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00019 Boston, MA 02110-1301, USA. 00020 */ 00021 00022 #include "kcolorcombo.h" 00023 00024 #include <QtGui/QAbstractItemDelegate> 00025 #include <QtGui/QApplication> 00026 #include <QtGui/QStylePainter> 00027 00028 #include <klocale.h> 00029 00030 #include "kcolordialog.h" 00031 00032 class KColorComboDelegate : public QAbstractItemDelegate 00033 { 00034 public: 00035 enum ItemRoles { 00036 ColorRole = Qt::UserRole + 1 00037 }; 00038 00039 enum LayoutMetrics { 00040 FrameMargin = 3 00041 }; 00042 00043 KColorComboDelegate(QObject *parent = 0); 00044 virtual ~KColorComboDelegate(); 00045 00046 virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; 00047 virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; 00048 }; 00049 00050 static QBrush k_colorcombodelegate_brush(const QModelIndex &index, int role) 00051 { 00052 QBrush brush; 00053 QVariant v = index.data(role); 00054 if (v.type() == QVariant::Brush) { 00055 brush = v.value<QBrush>(); 00056 } else if (v.type() == QVariant::Color) { 00057 brush = QBrush(v.value<QColor>()); 00058 } 00059 return brush; 00060 } 00061 00062 KColorComboDelegate::KColorComboDelegate(QObject *parent) 00063 : QAbstractItemDelegate(parent) 00064 { 00065 } 00066 00067 KColorComboDelegate::~KColorComboDelegate() 00068 { 00069 } 00070 00071 void KColorComboDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const 00072 { 00073 // background 00074 QColor innercolor(Qt::white); 00075 bool isSelected = (option.state & QStyle::State_Selected); 00076 bool paletteBrush = (k_colorcombodelegate_brush(index, Qt::BackgroundRole).style() == Qt::NoBrush); 00077 if (isSelected) { 00078 innercolor = option.palette.color(QPalette::Highlight); 00079 } else { 00080 innercolor = option.palette.color(QPalette::Base); 00081 } 00082 // highlight selected item 00083 QStyleOptionViewItemV4 opt(option); 00084 opt.showDecorationSelected = true; 00085 QStyle *style = opt.widget ? opt.widget->style() : QApplication::style(); 00086 style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, opt.widget); 00087 QRect innerrect = option.rect.adjusted(FrameMargin, FrameMargin, -FrameMargin, -FrameMargin); 00088 // inner color 00089 QVariant cv = index.data(ColorRole); 00090 if (cv.type() == QVariant::Color) { 00091 QColor tmpcolor = cv.value<QColor>(); 00092 if (tmpcolor.isValid()) { 00093 innercolor = tmpcolor; 00094 paletteBrush = false; 00095 painter->setPen(Qt::transparent); 00096 painter->setBrush(innercolor); 00097 QPainter::RenderHints tmpHint = painter->renderHints(); 00098 painter->setRenderHint(QPainter::Antialiasing); 00099 painter->drawRoundedRect(innerrect, 2, 2); 00100 painter->setRenderHints(tmpHint); 00101 painter->setBrush(Qt::NoBrush); 00102 } 00103 } 00104 // text 00105 QVariant tv = index.data(Qt::DisplayRole); 00106 if (tv.type() == QVariant::String) { 00107 QString text = tv.toString(); 00108 QColor textColor; 00109 if (paletteBrush) { 00110 if (isSelected) { 00111 textColor = option.palette.color(QPalette::HighlightedText); 00112 } else { 00113 textColor = option.palette.color(QPalette::Text); 00114 } 00115 } else { 00116 int unused, v; 00117 innercolor.getHsv(&unused, &unused, &v); 00118 if (v > 128) { 00119 textColor = Qt::black; 00120 } else { 00121 textColor = Qt::white; 00122 } 00123 } 00124 painter->setPen(textColor); 00125 painter->drawText(innerrect.adjusted(1, 1, -1, -1), text); 00126 } 00127 } 00128 00129 QSize KColorComboDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const 00130 { 00131 Q_UNUSED(index) 00132 00133 // the width does not matter, as the view will always use the maximum width available 00134 return QSize(100, option.fontMetrics.height() + 2 * FrameMargin); 00135 } 00136 00137 00138 static const uchar standardPalette[][4] = { 00139 { 255, 255, 255 }, // white 00140 { 192, 192, 192 }, // light gray 00141 { 160, 160, 160 }, // gray 00142 { 128, 128, 128 }, // dark gray 00143 { 0, 0, 0 }, // black 00144 00145 { 255, 128, 128 }, //light red 00146 { 255, 192, 128 }, //light orange 00147 { 255, 255, 128 }, //light yellow 00148 { 128, 255, 128 }, //light green 00149 { 128, 255, 255 }, //cyan blue 00150 { 128, 128, 255 }, //light blue 00151 { 255, 128, 255 }, //light violet 00152 { 255, 0, 0 }, //red 00153 { 255, 128, 0 }, //orange 00154 { 255, 255, 0 }, //yellow 00155 { 0, 255, 0 }, //green 00156 { 0, 255, 255 }, //light blue 00157 { 0, 0, 255 }, //blue 00158 { 255, 0, 255 }, //violet 00159 { 128, 0, 0 }, //dark red 00160 { 128, 64, 0 }, //dark orange 00161 { 128, 128, 0 }, //dark yellow 00162 { 0, 128, 0 }, //dark green 00163 { 0, 128, 128 }, //dark light blue 00164 { 0, 0, 128 }, //dark blue 00165 { 128, 0, 128 } //dark violet 00166 }; 00167 00168 #define STANDARD_PALETTE_SIZE (int(sizeof(standardPalette) / sizeof(*standardPalette))) 00169 00170 static inline QColor standardColor(int i) 00171 { 00172 const uchar *entry = standardPalette[i]; 00173 return QColor(entry[0], entry[1], entry[2]); 00174 } 00175 00176 class KColorComboPrivate 00177 { 00178 public: 00179 KColorComboPrivate(KColorCombo *qq); 00180 00181 void addColors(); 00182 void setCustomColor(const QColor &color, bool lookupInPresets = true); 00183 00184 // slots 00185 void _k_slotActivated(int index); 00186 void _k_slotHighlighted(int index); 00187 00188 KColorCombo *q; 00189 QList<QColor> colorList; 00190 QColor customColor; 00191 QColor internalcolor; 00192 }; 00193 00194 KColorComboPrivate::KColorComboPrivate(KColorCombo *qq) 00195 : q(qq), customColor(Qt::white) 00196 { 00197 } 00198 00199 void KColorComboPrivate::setCustomColor(const QColor &color, bool lookupInPresets) 00200 { 00201 if (lookupInPresets) { 00202 if (colorList.isEmpty()) { 00203 for (int i = 0; i < STANDARD_PALETTE_SIZE; ++i) { 00204 if (standardColor(i) == color) { 00205 q->setCurrentIndex(i + 1); 00206 internalcolor = color; 00207 return; 00208 } 00209 } 00210 } else { 00211 int i = colorList.indexOf(color); 00212 if (i >= 0) { 00213 q->setCurrentIndex(i + 1); 00214 internalcolor = color; 00215 return; 00216 } 00217 } 00218 } 00219 00220 internalcolor = color; 00221 customColor = color; 00222 q->setItemData(0, customColor, KColorComboDelegate::ColorRole); 00223 } 00224 00225 00226 KColorCombo::KColorCombo( QWidget *parent ) 00227 : QComboBox(parent), d(new KColorComboPrivate(this)) 00228 { 00229 setItemDelegate(new KColorComboDelegate(this)); 00230 d->addColors(); 00231 00232 connect(this, SIGNAL(activated(int)), SLOT(_k_slotActivated(int))); 00233 connect(this, SIGNAL(highlighted(int)), SLOT(_k_slotHighlighted(int))); 00234 00235 // select the white color 00236 setCurrentIndex(1); 00237 d->_k_slotActivated(1); 00238 00239 setMaxVisibleItems(13); 00240 } 00241 00242 00243 KColorCombo::~KColorCombo() 00244 { 00245 delete d; 00246 } 00247 00248 void KColorCombo::setColors( const QList<QColor> &colors ) 00249 { 00250 clear(); 00251 d->colorList = colors; 00252 d->addColors(); 00253 } 00254 00255 QList<QColor> KColorCombo::colors() const 00256 { 00257 if (d->colorList.isEmpty()) { 00258 QList<QColor> list; 00259 for (int i = 0; i < STANDARD_PALETTE_SIZE; ++i) { 00260 list += standardColor(i); 00261 } 00262 return list; 00263 } else { 00264 return d->colorList; 00265 } 00266 } 00267 00271 void KColorCombo::setColor( const QColor &col ) 00272 { 00273 if (!col.isValid()) { 00274 return; 00275 } 00276 00277 if (count() == 0) { 00278 d->addColors(); 00279 } 00280 00281 d->setCustomColor(col, true); 00282 } 00283 00284 00288 QColor KColorCombo::color() const { 00289 return d->internalcolor; 00290 } 00291 00292 bool KColorCombo::isCustomColor() const 00293 { 00294 return d->internalcolor == d->customColor; 00295 } 00296 00297 void KColorCombo::paintEvent(QPaintEvent *event) 00298 { 00299 Q_UNUSED(event) 00300 QStylePainter painter(this); 00301 painter.setPen(palette().color(QPalette::Text)); 00302 00303 QStyleOptionComboBox opt; 00304 initStyleOption(&opt); 00305 painter.drawComplexControl(QStyle::CC_ComboBox, opt); 00306 00307 QRect frame = style()->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxEditField, this); 00308 painter.setRenderHint(QPainter::Antialiasing); 00309 painter.setPen(Qt::transparent); 00310 painter.setBrush(QBrush(d->internalcolor)); 00311 painter.drawRoundedRect(frame.adjusted(1, 1, -1, -1), 2, 2); 00312 } 00313 00317 void KColorCombo::showEmptyList() 00318 { 00319 clear(); 00320 } 00321 00322 void KColorComboPrivate::_k_slotActivated(int index) 00323 { 00324 if (index == 0) { 00325 if (KColorDialog::getColor(customColor, q) == QDialog::Accepted) { 00326 setCustomColor(customColor, false); 00327 } 00328 } else if (colorList.isEmpty()) { 00329 internalcolor = standardColor(index - 1); 00330 } else { 00331 internalcolor = colorList[index - 1]; 00332 } 00333 00334 emit q->activated(internalcolor); 00335 } 00336 00337 void KColorComboPrivate::_k_slotHighlighted(int index) 00338 { 00339 if (index == 0) { 00340 internalcolor = customColor; 00341 } else if (colorList.isEmpty()) { 00342 internalcolor = standardColor(index - 1); 00343 } else { 00344 internalcolor = colorList[index - 1]; 00345 } 00346 00347 emit q->highlighted(internalcolor); 00348 } 00349 00350 void KColorComboPrivate::addColors() 00351 { 00352 q->addItem(i18nc("Custom color", "Custom...")); 00353 00354 if (colorList.isEmpty()) { 00355 for (int i = 0; i < STANDARD_PALETTE_SIZE; ++i) { 00356 q->addItem(QString()); 00357 q->setItemData(i + 1, standardColor(i), KColorComboDelegate::ColorRole); 00358 } 00359 } else { 00360 for (int i = 0, count = colorList.count(); i < count; ++i) { 00361 q->addItem(QString()); 00362 q->setItemData(i + 1, colorList[i], KColorComboDelegate::ColorRole); 00363 } 00364 } 00365 } 00366 00367 #include "kcolorcombo.moc"
KDE 4.6 API Reference