File indexing completed on 2024-05-12 08:42:14
0001 /* This file is part of the KDE libraries 0002 Copyright (C) 1997 Martin Jones (mjones@kde.org) 0003 Copyright (C) 2007 Pino Toscano (pino@kde.org) 0004 Copyright (c) 2007 David Jarvie (software@astrojar.org.uk) 0005 0006 This library is free software; you can redistribute it and/or 0007 modify it under the terms of the GNU Library General Public 0008 License as published by the Free Software Foundation; either 0009 version 2 of the License, or (at your option) any later version. 0010 0011 This library is distributed in the hope that it will be useful, 0012 but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 Library General Public License for more details. 0015 0016 You should have received a copy of the GNU Library General Public License 0017 along with this library; see the file COPYING.LIB. If not, write to 0018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0019 Boston, MA 02110-1301, USA. 0020 */ 0021 0022 #include "KColorCombo.h" 0023 0024 #include <QAbstractItemDelegate> 0025 #include <QApplication> 0026 #include <QColorDialog> 0027 #include <QStylePainter> 0028 0029 class KColorComboDelegate : public QAbstractItemDelegate 0030 { 0031 public: 0032 enum ItemRoles { 0033 ColorRole = Qt::UserRole + 1 0034 }; 0035 0036 enum LayoutMetrics { 0037 FrameMargin = 3 0038 }; 0039 0040 KColorComboDelegate(QObject *parent = 0); 0041 virtual ~KColorComboDelegate(); 0042 0043 void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; 0044 QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override; 0045 }; 0046 0047 static QBrush k_colorcombodelegate_brush(const QModelIndex &index, int role) 0048 { 0049 QBrush brush; 0050 QVariant v = index.data(role); 0051 if (v.type() == QVariant::Brush) { 0052 brush = v.value<QBrush>(); 0053 } else if (v.type() == QVariant::Color) { 0054 brush = QBrush(v.value<QColor>()); 0055 } 0056 return brush; 0057 } 0058 0059 KColorComboDelegate::KColorComboDelegate(QObject *parent) 0060 : QAbstractItemDelegate(parent) 0061 { 0062 } 0063 0064 KColorComboDelegate::~KColorComboDelegate() 0065 { 0066 } 0067 0068 void KColorComboDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const 0069 { 0070 // background 0071 QColor innercolor(Qt::white); 0072 bool isSelected = (option.state & QStyle::State_Selected); 0073 bool paletteBrush = (k_colorcombodelegate_brush(index, Qt::BackgroundRole).style() == Qt::NoBrush); 0074 if (isSelected) { 0075 innercolor = option.palette.color(QPalette::Highlight); 0076 } else { 0077 innercolor = option.palette.color(QPalette::Base); 0078 } 0079 // highlight selected item 0080 QStyleOptionViewItem opt(option); 0081 opt.showDecorationSelected = true; 0082 QStyle *style = opt.widget ? opt.widget->style() : QApplication::style(); 0083 style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, opt.widget); 0084 QRect innerrect = option.rect.adjusted(FrameMargin, FrameMargin, -FrameMargin, -FrameMargin); 0085 // inner color 0086 QVariant cv = index.data(ColorRole); 0087 if (cv.type() == QVariant::Color) { 0088 QColor tmpcolor = cv.value<QColor>(); 0089 if (tmpcolor.isValid()) { 0090 innercolor = tmpcolor; 0091 paletteBrush = false; 0092 painter->setPen(Qt::transparent); 0093 painter->setBrush(innercolor); 0094 QPainter::RenderHints tmpHint = painter->renderHints(); 0095 painter->setRenderHint(QPainter::Antialiasing); 0096 painter->drawRoundedRect(innerrect, 2, 2); 0097 painter->setRenderHints(tmpHint); 0098 painter->setBrush(Qt::NoBrush); 0099 } 0100 } 0101 // text 0102 QVariant tv = index.data(Qt::DisplayRole); 0103 if (tv.type() == QVariant::String) { 0104 QString text = tv.toString(); 0105 QColor textColor; 0106 if (paletteBrush) { 0107 if (isSelected) { 0108 textColor = option.palette.color(QPalette::HighlightedText); 0109 } else { 0110 textColor = option.palette.color(QPalette::Text); 0111 } 0112 } else { 0113 int unused, v; 0114 innercolor.getHsv(&unused, &unused, &v); 0115 if (v > 128) { 0116 textColor = Qt::black; 0117 } else { 0118 textColor = Qt::white; 0119 } 0120 } 0121 painter->setPen(textColor); 0122 painter->drawText(innerrect.adjusted(1, 1, -1, -1), text); 0123 } 0124 } 0125 0126 QSize KColorComboDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const 0127 { 0128 Q_UNUSED(index) 0129 0130 // the width does not matter, as the view will always use the maximum width available 0131 return QSize(100, option.fontMetrics.height() + 2 * FrameMargin); 0132 } 0133 0134 static const uchar standardPalette[][4] = { 0135 { 255, 255, 255 }, // white 0136 { 192, 192, 192 }, // light gray 0137 { 160, 160, 160 }, // gray 0138 { 128, 128, 128 }, // dark gray 0139 { 0, 0, 0 }, // black 0140 0141 { 255, 128, 128 }, //light red 0142 { 255, 192, 128 }, //light orange 0143 { 255, 255, 128 }, //light yellow 0144 { 128, 255, 128 }, //light green 0145 { 128, 255, 255 }, //cyan blue 0146 { 128, 128, 255 }, //light blue 0147 { 255, 128, 255 }, //light violet 0148 { 255, 0, 0 }, //red 0149 { 255, 128, 0 }, //orange 0150 { 255, 255, 0 }, //yellow 0151 { 0, 255, 0 }, //green 0152 { 0, 255, 255 }, //light blue 0153 { 0, 0, 255 }, //blue 0154 { 255, 0, 255 }, //violet 0155 { 128, 0, 0 }, //dark red 0156 { 128, 64, 0 }, //dark orange 0157 { 128, 128, 0 }, //dark yellow 0158 { 0, 128, 0 }, //dark green 0159 { 0, 128, 128 }, //dark light blue 0160 { 0, 0, 128 }, //dark blue 0161 { 128, 0, 128 } //dark violet 0162 }; 0163 0164 #define STANDARD_PALETTE_SIZE (int(sizeof(standardPalette) / sizeof(*standardPalette))) 0165 0166 static inline QColor standardColor(int i) 0167 { 0168 const uchar *entry = standardPalette[i]; 0169 return QColor(entry[0], entry[1], entry[2]); 0170 } 0171 0172 class KColorComboPrivate 0173 { 0174 public: 0175 KColorComboPrivate(KColorCombo *qq); 0176 0177 void addColors(); 0178 void setCustomColor(const QColor &color, bool lookupInPresets = true); 0179 0180 // slots 0181 void _k_slotActivated(int index); 0182 void _k_slotHighlighted(int index); 0183 0184 KColorCombo *q; 0185 QList<QColor> colorList; 0186 QColor customColor; 0187 QColor internalcolor; 0188 }; 0189 0190 KColorComboPrivate::KColorComboPrivate(KColorCombo *qq) 0191 : q(qq), customColor(Qt::white) 0192 { 0193 } 0194 0195 void KColorComboPrivate::setCustomColor(const QColor &color, bool lookupInPresets) 0196 { 0197 if (lookupInPresets) { 0198 if (colorList.isEmpty()) { 0199 for (int i = 0; i < STANDARD_PALETTE_SIZE; ++i) { 0200 if (standardColor(i) == color) { 0201 q->setCurrentIndex(i + 1); 0202 internalcolor = color; 0203 return; 0204 } 0205 } 0206 } else { 0207 int i = colorList.indexOf(color); 0208 if (i >= 0) { 0209 q->setCurrentIndex(i + 1); 0210 internalcolor = color; 0211 return; 0212 } 0213 } 0214 } 0215 0216 internalcolor = color; 0217 customColor = color; 0218 q->setItemData(0, customColor, KColorComboDelegate::ColorRole); 0219 } 0220 0221 KColorCombo::KColorCombo(QWidget *parent) 0222 : QComboBox(parent), d(new KColorComboPrivate(this)) 0223 { 0224 setItemDelegate(new KColorComboDelegate(this)); 0225 d->addColors(); 0226 0227 connect(this, SIGNAL(activated(int)), SLOT(_k_slotActivated(int))); 0228 connect(this, SIGNAL(highlighted(int)), SLOT(_k_slotHighlighted(int))); 0229 0230 // select the white color 0231 setCurrentIndex(1); 0232 d->_k_slotActivated(1); 0233 0234 setMaxVisibleItems(13); 0235 } 0236 0237 KColorCombo::~KColorCombo() 0238 { 0239 delete d; 0240 } 0241 0242 void KColorCombo::setColors(const QList<QColor> &colors) 0243 { 0244 clear(); 0245 d->colorList = colors; 0246 d->addColors(); 0247 } 0248 0249 QList<QColor> KColorCombo::colors() const 0250 { 0251 if (d->colorList.isEmpty()) { 0252 QList<QColor> list; 0253 for (int i = 0; i < STANDARD_PALETTE_SIZE; ++i) { 0254 list += standardColor(i); 0255 } 0256 return list; 0257 } else { 0258 return d->colorList; 0259 } 0260 } 0261 0262 void KColorCombo::setColor(const QColor &col) 0263 { 0264 if (!col.isValid()) { 0265 return; 0266 } 0267 0268 if (count() == 0) { 0269 d->addColors(); 0270 } 0271 0272 d->setCustomColor(col, true); 0273 } 0274 0275 QColor KColorCombo::color() const 0276 { 0277 return d->internalcolor; 0278 } 0279 0280 bool KColorCombo::isCustomColor() const 0281 { 0282 return d->internalcolor == d->customColor; 0283 } 0284 0285 void KColorCombo::paintEvent(QPaintEvent *event) 0286 { 0287 Q_UNUSED(event) 0288 QStylePainter painter(this); 0289 painter.setPen(palette().color(QPalette::Text)); 0290 0291 QStyleOptionComboBox opt; 0292 initStyleOption(&opt); 0293 painter.drawComplexControl(QStyle::CC_ComboBox, opt); 0294 0295 QRect frame = style()->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxEditField, this); 0296 painter.setRenderHint(QPainter::Antialiasing); 0297 painter.setPen(Qt::transparent); 0298 painter.setBrush(QBrush(d->internalcolor)); 0299 painter.drawRoundedRect(frame.adjusted(1, 1, -1, -1), 2, 2); 0300 } 0301 0302 void KColorCombo::showEmptyList() 0303 { 0304 clear(); 0305 } 0306 0307 void KColorComboPrivate::_k_slotActivated(int index) 0308 { 0309 if (index == 0) { 0310 QColor c = QColorDialog::getColor(customColor, q); 0311 if (c.isValid()) { 0312 customColor = c; 0313 setCustomColor(customColor, false); 0314 } 0315 } else if (colorList.isEmpty()) { 0316 internalcolor = standardColor(index - 1); 0317 } else { 0318 internalcolor = colorList[index - 1]; 0319 } 0320 0321 emit q->activated(internalcolor); 0322 } 0323 0324 void KColorComboPrivate::_k_slotHighlighted(int index) 0325 { 0326 if (index == 0) { 0327 internalcolor = customColor; 0328 } else if (colorList.isEmpty()) { 0329 internalcolor = standardColor(index - 1); 0330 } else { 0331 internalcolor = colorList[index - 1]; 0332 } 0333 0334 emit q->highlighted(internalcolor); 0335 } 0336 0337 void KColorComboPrivate::addColors() 0338 { 0339 q->addItem(KColorCombo::tr("Custom...", "Custom color")); 0340 0341 if (colorList.isEmpty()) { 0342 for (int i = 0; i < STANDARD_PALETTE_SIZE; ++i) { 0343 q->addItem(QString()); 0344 q->setItemData(i + 1, standardColor(i), KColorComboDelegate::ColorRole); 0345 } 0346 } else { 0347 for (int i = 0, count = colorList.count(); i < count; ++i) { 0348 q->addItem(QString()); 0349 q->setItemData(i + 1, colorList[i], KColorComboDelegate::ColorRole); 0350 } 0351 } 0352 } 0353 0354 #include "moc_KColorCombo.cpp"