File indexing completed on 2024-04-28 13:43:30
0001 /** 0002 * SPDX-FileCopyrightText: (C) 2005 Sébastien Laoût <slaout@linux62.org> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "kcolorcombo2.h" 0008 0009 #ifndef USE_OLD_KCOLORCOMBO 0010 0011 #include <QApplication> 0012 #include <QtGui/QBitmap> 0013 #include <QtGui/QPainter> 0014 #include <QtGui/QPixmap> 0015 0016 #include <QColorDialog> 0017 #include <QDesktopWidget> 0018 #include <QDrag> 0019 #include <QLocale> 0020 #include <QMimeData> 0021 #include <QtGui/QClipboard> 0022 #include <QtGui/QDragEnterEvent> 0023 #include <QtGui/QDropEvent> 0024 #include <QtGui/QKeyEvent> 0025 #include <QtGui/QMouseEvent> 0026 #include <QtGui/QPaintEvent> 0027 0028 #include <KLocalizedString> 0029 #include <KStandardShortcut> 0030 0031 //#define DEBUG_COLOR_ARRAY 0032 //#define OUTPUT_GIMP_PALETTE 0033 0034 /** class KColorPopup: */ 0035 0036 const int KColorPopup::MARGIN = 1; 0037 const int KColorPopup::FRAME_WIDTH = 1; 0038 0039 KColorPopup::KColorPopup(KColorCombo2 *parent) 0040 : QWidget(/*parent=*/nullptr, Qt::Popup) 0041 , m_selector(parent) 0042 , m_pixmap(nullptr) 0043 { 0044 hide(); 0045 setMouseTracking(true); 0046 // resize(20, 20); 0047 } 0048 0049 KColorPopup::~KColorPopup() 0050 { 0051 delete m_pixmap; 0052 } 0053 0054 #include <qcursor.h> 0055 0056 void KColorPopup::relayout() // FIXME: relayout should NOT redraw the pixmap! 0057 { 0058 int columnCount = m_selector->columnCount(); 0059 int rowCount = m_selector->rowCount(); 0060 int colorHeight = m_selector->colorRectHeight(); 0061 int colorWidth = m_selector->colorRectWidthForHeight(colorHeight); 0062 bool haveDefault = m_selector->defaultColor().isValid(); 0063 0064 int width = 2 + MARGIN + (colorWidth + MARGIN) * columnCount; 0065 int height = 2 + MARGIN + (colorHeight + MARGIN) * rowCount + (colorHeight + MARGIN); 0066 0067 resize(width, height); 0068 0069 // Initialize the pixmap: 0070 delete m_pixmap; 0071 m_pixmap = new QPixmap(width, height); 0072 QPainter painter(m_pixmap); 0073 painter.fillRect(0, 0, width, height, palette().color(QPalette::Base)); 0074 painter.setPen(palette().color(QPalette::Text)); 0075 painter.drawRect(0, 0, width, height); 0076 0077 // Needed to draw: 0078 int x, y; 0079 QRect selectionRect; 0080 0081 // Draw the color array: 0082 for (int i = 0; i < columnCount; ++i) { 0083 for (int j = 0; j < rowCount; ++j) { 0084 x = 1 + MARGIN + (colorWidth + MARGIN) * i; 0085 y = 1 + MARGIN + (colorHeight + MARGIN) * j; 0086 if (i == m_selectedColumn && j == m_selectedRow) { 0087 selectionRect = QRect(x - 2, y - 2, colorWidth + 4, colorHeight + 4); 0088 painter.fillRect(selectionRect, palette().color(QPalette::Highlight)); 0089 } 0090 m_selector->drawColorRect(painter, x, y, m_selector->colorAt(i, j), /*isDefault=*/false, colorWidth, colorHeight); 0091 } 0092 } 0093 0094 m_columnOther = (haveDefault ? columnCount / 2 : 0); // "(Default)" is allowed, paint "Other..." on the right 0095 int defaultCellWidth = (colorWidth + MARGIN) * m_columnOther; 0096 int otherCellWidth = (colorWidth + MARGIN) * (columnCount - m_columnOther); 0097 0098 // Draw the "(Default)" and "Other..." colors: 0099 y = height - (colorHeight + MARGIN) - 1; 0100 QColor textColor; 0101 if (m_selector->defaultColor().isValid()) { 0102 x = 1 + MARGIN; 0103 if (m_selectedColumn < m_columnOther && rowCount == m_selectedRow) { 0104 selectionRect = QRect(x - 2, y - 2, defaultCellWidth, colorHeight + 4); 0105 painter.fillRect(selectionRect, palette().color(QPalette::Highlight)); 0106 textColor = palette().color(QPalette::HighlightedText); 0107 } else 0108 textColor = palette().color(QPalette::Text); 0109 m_selector->drawColorRect(painter, x, y, m_selector->defaultColor(), /*isDefault=*/true, colorWidth, colorHeight); 0110 painter.setFont(m_selector->font()); 0111 painter.setPen(textColor); 0112 painter.drawText(x + 2 + colorWidth, y, /*width=*/5000, colorHeight, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextDontClip, i18n("(Default)")); 0113 } 0114 x = 1 + MARGIN + m_columnOther * (colorWidth + MARGIN); 0115 if (m_selectedColumn >= m_columnOther && rowCount == m_selectedRow) { 0116 selectionRect = QRect(x - 2, y - 2, otherCellWidth, colorHeight + 4); 0117 painter.fillRect(selectionRect, palette().color(QPalette::Highlight)); 0118 textColor = palette().color(QPalette::HighlightedText); 0119 } else 0120 textColor = palette().color(QPalette::Text); 0121 m_selector->drawColorRect(painter, x, y, m_otherColor, /*isDefault=*/false, colorWidth, colorHeight); 0122 painter.setFont(m_selector->font()); 0123 painter.setPen(textColor); 0124 painter.drawText(x + 2 + colorWidth, y, /*width=*/5000, colorHeight, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextDontClip, i18n("Other...")); 0125 0126 // QPoint pos = mapFromGlobal(QCursor::pos()); 0127 // painter.drawRect(pos.x(), pos.y(), 5000, 5000); 0128 } 0129 0130 void KColorPopup::updateCell(int column, int row) 0131 { 0132 int colorHeight = m_selector->colorRectHeight(); 0133 int colorWidth = m_selector->colorRectWidthForHeight(colorHeight); 0134 0135 int x = 1 + MARGIN + -2 + column * (colorWidth + MARGIN); 0136 int y = 1 + MARGIN + -2 + row * (colorHeight + MARGIN); 0137 int width = colorWidth + MARGIN; 0138 int height = colorHeight + MARGIN; 0139 0140 if (row == m_selector->rowCount()) { 0141 if (m_selectedColumn < m_columnOther) // The "(Default)" cell: 0142 width = (colorWidth + MARGIN) * m_columnOther; 0143 else // The "Other..." cell: 0144 width = (colorWidth + MARGIN) * (m_selector->columnCount() - m_columnOther); 0145 } 0146 0147 update(x, y, width, height); 0148 } 0149 0150 void KColorPopup::doSelection() 0151 { 0152 m_otherColor = QColor(); 0153 0154 // If the selected color is not the default one, try to find it in the array: 0155 if (m_selector->color().isValid()) { 0156 bool isInArray = false; 0157 for (int column = 0; column < m_selector->columnCount(); ++column) 0158 for (int row = 0; row < m_selector->rowCount(); ++row) 0159 if (m_selector->color() == m_selector->colorAt(column, row)) { 0160 m_selectedColumn = column; 0161 m_selectedRow = row; 0162 isInArray = true; 0163 } 0164 // If not found in array, it's another one: 0165 if (!isInArray) { 0166 m_selectedColumn = m_columnOther; 0167 m_selectedRow = m_selector->rowCount(); 0168 m_otherColor = m_selector->color(); 0169 } 0170 // If it's the default one: 0171 } else { 0172 m_selectedColumn = 0; 0173 m_selectedRow = m_selector->rowCount(); 0174 } 0175 } 0176 0177 void KColorPopup::validate() 0178 { 0179 hide(); 0180 close(); 0181 Q_EMIT closed(); 0182 0183 if (m_selectedRow != m_selector->rowCount()) // A normal row: 0184 m_selector->setColor(m_selector->colorAt(m_selectedColumn, m_selectedRow)); 0185 else if (m_selectedColumn < m_columnOther) // The default color: 0186 m_selector->setColor(QColor()); 0187 else { // The user want to choose one: 0188 QColor color = m_selector->effectiveColor(); 0189 color = QColorDialog::getColor(color, this); 0190 if (color.isValid()) 0191 m_selector->setColor(color); 0192 } 0193 } 0194 0195 void KColorPopup::mousePressEvent(QMouseEvent *event) 0196 { 0197 int x = event->pos().x(); 0198 int y = event->pos().y(); 0199 if (x < 0 || y < 0 || x >= width() || y >= height()) { 0200 hide(); 0201 close(); 0202 Q_EMIT closed(); 0203 } else 0204 validate(); 0205 0206 event->accept(); 0207 } 0208 0209 void KColorPopup::paintEvent(QPaintEvent *event) 0210 { 0211 QPainter painter(this); 0212 if (m_pixmap) 0213 painter.drawPixmap(0, 0, *m_pixmap); 0214 painter.setPen(Qt::black); 0215 painter.drawRect(event->rect()); 0216 } 0217 0218 void KColorPopup::mouseMoveEvent(QMouseEvent *event) 0219 { 0220 int x = event->pos().x(); 0221 int y = event->pos().y(); 0222 if (x < FRAME_WIDTH + 2 || y < FRAME_WIDTH + 2 || x > width() - 2 - 2 * FRAME_WIDTH || y > height() - 2 - 2 * FRAME_WIDTH) 0223 return; 0224 0225 int colorHeight = m_selector->colorRectHeight(); 0226 int colorWidth = m_selector->colorRectWidthForHeight(colorHeight); 0227 0228 // int oldSelectedColumn = m_selectedColumn; 0229 // int oldSelectedRow = m_selectedRow; 0230 m_selectedColumn = (x - FRAME_WIDTH - MARGIN + 2) / (colorWidth + MARGIN); 0231 m_selectedRow = (y - FRAME_WIDTH - MARGIN + 2) / (colorHeight + MARGIN); 0232 0233 relayout(); 0234 update(); 0235 } 0236 0237 void KColorPopup::keyPressEvent(QKeyEvent *event) 0238 { 0239 int column = m_selectedColumn; 0240 int row = m_selectedRow; 0241 int columnCount = m_selector->columnCount(); 0242 int rowCount = m_selector->rowCount(); 0243 0244 switch (event->key()) { 0245 case Qt::Key_Right: 0246 if (m_selectedRow != rowCount) // A normal row: 0247 column = (column + 1) % columnCount; 0248 else { 0249 // The last row, if there are two choices, switch. Else, do nothing: 0250 if (m_selector->defaultColor().isValid()) 0251 column = (m_selectedColumn < m_columnOther ? m_columnOther : 0); 0252 } 0253 break; 0254 case Qt::Key_Left: 0255 if (m_selectedRow != rowCount) { // A normal row: 0256 column = (column - 1); 0257 if (column < 0) 0258 column = columnCount - 1; 0259 } else { 0260 // The last row, if there are two choices, switch. Else, do nothing: 0261 if (m_selector->defaultColor().isValid()) 0262 column = (m_selectedColumn < m_columnOther ? m_columnOther : 0); 0263 } 0264 break; 0265 case Qt::Key_Up: 0266 row = (row - 1); 0267 if (row < 0) 0268 row = rowCount; 0269 break; 0270 case Qt::Key_Down: 0271 row = (row + 1) % (rowCount + 1); 0272 break; 0273 case Qt::Key_PageDown: 0274 row += 10; 0275 if (row > rowCount) 0276 row = rowCount; 0277 break; 0278 case Qt::Key_PageUp: 0279 row -= 10; 0280 if (row < 0) 0281 row = 0; 0282 break; 0283 case Qt::Key_Home: 0284 row = 0; 0285 column = 0; 0286 break; 0287 case Qt::Key_End: 0288 row = rowCount; 0289 column = columnCount - 1; 0290 break; 0291 case Qt::Key_Return: 0292 validate(); 0293 break; 0294 default: 0295 QWidget::keyPressEvent(event); 0296 } 0297 0298 if (row != m_selectedRow || column != m_selectedColumn) { 0299 m_selectedRow = row; 0300 m_selectedColumn = column; 0301 relayout(); 0302 update(); 0303 } 0304 } 0305 0306 /** Helper function: */ 0307 0308 QColor Tool_mixColors(const QColor &color1, const QColor &color2) 0309 { 0310 QColor mixedColor; 0311 mixedColor.setRgb((color1.red() + color2.red()) / 2, (color1.green() + color2.green()) / 2, (color1.blue() + color2.blue()) / 2); 0312 return mixedColor; 0313 } 0314 0315 /** class KColorCombo2Private */ 0316 0317 class KColorCombo2::KColorCombo2Private 0318 { 0319 }; 0320 0321 /** class KColorCombo2: */ 0322 0323 /* All code for the popup management (including the constructor, popup() and eventFilter()) 0324 * has been copied from the KDateEdit widget (in libkdepim). 0325 * 0326 * Some other piece of code comes from KColorButton (in libkdeui) to enable color drag, drop, copy and paste. 0327 */ 0328 0329 KColorCombo2::KColorCombo2(const QColor &color, const QColor &defaultColor, QWidget *parent) 0330 : KComboBox(parent) 0331 , m_color(color) 0332 , m_defaultColor(defaultColor) 0333 { 0334 setEditable(false); 0335 init(); 0336 } 0337 0338 KColorCombo2::KColorCombo2(const QColor &color, QWidget *parent) 0339 : KComboBox(parent) 0340 , m_color(color) 0341 , m_defaultColor() 0342 { 0343 setEditable(false); 0344 init(); 0345 } 0346 0347 void KColorCombo2::init() 0348 { 0349 m_colorArray = nullptr; 0350 d = new KColorCombo2Private(); 0351 0352 setDefaultColor(m_defaultColor); 0353 insertItem(/*index=*/0, QString()); 0354 updateComboBox(); // It need an item of index 0 to exists, so we created it. 0355 setAcceptDrops(true); 0356 0357 m_popup = new KColorPopup(this); 0358 m_popup->installEventFilter(this); 0359 connect(m_popup, &KColorPopup::closed, this, &KColorCombo2::popupClosed); 0360 0361 // By default, the array is filled with setRainbowPreset(). 0362 // But we allocate it on demand (the later as possible) to avoid performances issues if the developer set another array. 0363 // However, to keep columnCount() rowCount() const, we define theme here: 0364 m_columnCount = 13; 0365 m_rowCount = 9; 0366 } 0367 0368 KColorCombo2::~KColorCombo2() 0369 { 0370 deleteColorArray(); 0371 } 0372 0373 void KColorCombo2::setColor(const QColor &color) 0374 { 0375 // Do nothing if the color should be set to the default one and there is no such default color allowed: 0376 if (!color.isValid() && !m_defaultColor.isValid()) { 0377 // kdebug << this::FUNCTION << "Trying to assign the default color (an invalid one) whereas no such default color is allowed"; 0378 return; 0379 } 0380 0381 if (m_color != color) { 0382 m_color = color; 0383 updateComboBox(); 0384 Q_EMIT colorChanged(color); 0385 } 0386 } 0387 0388 QColor KColorCombo2::color() const 0389 { 0390 return m_color; 0391 } 0392 0393 QColor KColorCombo2::effectiveColor() const 0394 { 0395 if (m_color.isValid()) 0396 return m_color; 0397 else 0398 return m_defaultColor; 0399 } 0400 0401 void KColorCombo2::setRainbowPreset(int colorColumnCount, int lightRowCount, int darkRowCount, bool withGray) 0402 { 0403 // At least one row and one column: 0404 if (colorColumnCount < 1 - (withGray ? 1 : 0)) 0405 colorColumnCount = 1 - (withGray ? 1 : 0); 0406 if (lightRowCount < 0) 0407 lightRowCount = 0; 0408 if (darkRowCount < 0) 0409 darkRowCount = 0; 0410 0411 // Create the array: 0412 int columnCount = colorColumnCount + (withGray ? 1 : 0); 0413 int rowCount = lightRowCount + 1 + darkRowCount; 0414 newColorArray(columnCount, rowCount); 0415 0416 // Fill the array: 0417 for (int i = 0; i < colorColumnCount; ++i) { 0418 int hue = i * 360 / colorColumnCount; 0419 // With light colors: 0420 for (int j = 1; j <= lightRowCount; ++j) { // Start to 1 because we don't want a row full of white! 0421 int saturation = j * 255 / (lightRowCount + 1); 0422 setColorAt(i, j - 1, QColor::fromHsv(hue, saturation, 255)); 0423 } 0424 // With pure colors: 0425 setColorAt(i, lightRowCount, QColor::fromHsv(hue, 255, 255)); 0426 // With dark colors: 0427 for (int j = 1; j <= darkRowCount; ++j) { 0428 int value = 255 - j * 255 / (darkRowCount + 1); 0429 setColorAt(i, lightRowCount + j, QColor::fromHsv(hue, 255, value)); 0430 } 0431 } 0432 0433 // Fill the gray column: 0434 if (withGray) { 0435 for (int i = 0; i < rowCount; ++i) { 0436 int gray = (rowCount == 1 ? 128 : 255 - (i * 255 / (rowCount - 1))); 0437 setColorAt(columnCount - 1, i, QColor(gray, gray, gray)); 0438 } 0439 } 0440 0441 #ifdef DEBUG_COLOR_ARRAY 0442 qDebug() << "KColorCombo2::setColorPreset"; 0443 for (int j = 0; j < rowCount; ++j) { 0444 for (int i = 0; i < columnCount; ++i) { 0445 int h, s, v; 0446 m_colorArray[i][j].getHsv(&h, &s, &v); 0447 qDebug() << QString("(%1,%2,%3)").arg(h, 3).arg(s, 3).arg(v, 3); 0448 // qDebug() << colorArray[i][j].name() << " "; 0449 } 0450 qDebug(); 0451 } 0452 #endif 0453 #ifdef OUTPUT_GIMP_PALETTE 0454 qDebug() << "GIMP Palette"; 0455 for (int j = 0; j < rowCount; ++j) { 0456 for (int i = 0; i < columnCount; ++i) { 0457 qDebug() << QString("(%1,%2,%3)").arg(m_colorArray[i][j].red(), 3).arg(m_colorArray[i][j].green(), 3).arg(m_colorArray[i][j].blue(), 3); 0458 } 0459 } 0460 #endif 0461 } 0462 0463 int KColorCombo2::columnCount() const 0464 { 0465 return m_columnCount; 0466 } 0467 0468 int KColorCombo2::rowCount() const 0469 { 0470 return m_rowCount; 0471 } 0472 0473 QColor KColorCombo2::colorAt(int column, int row) /* const*/ 0474 { 0475 if (!m_colorArray) 0476 setRainbowPreset(); 0477 0478 if (column < 0 || row < 0 || column >= m_columnCount || row >= m_rowCount) 0479 return QColor(); 0480 0481 return m_colorArray[column][row]; 0482 } 0483 0484 QColor KColorCombo2::defaultColor() const 0485 { 0486 return m_defaultColor; 0487 } 0488 0489 void KColorCombo2::newColorArray(int columnCount, int rowCount) 0490 { 0491 if (columnCount <= 0 || rowCount <= 0) { 0492 // kdebug << this::FUNCTION << "Trying to create an empty new color array (with %d columns and %d rows)"; 0493 return; 0494 } 0495 0496 // Delete any previous array (if any): 0497 deleteColorArray(); 0498 0499 // Create a new array of the wanted dimensions: 0500 m_columnCount = columnCount; 0501 m_rowCount = rowCount; 0502 m_colorArray = new QColor *[columnCount]; 0503 for (int i = 0; i < columnCount; ++i) 0504 m_colorArray[i] = new QColor[rowCount]; 0505 } 0506 0507 void KColorCombo2::setColorAt(int column, int row, const QColor &color) 0508 { 0509 if (!m_colorArray) 0510 setRainbowPreset(); 0511 0512 if (column < 0 || row < 0 || column >= m_columnCount || row >= m_rowCount) { 0513 // kdebug << this::FUNCTION << "Trying to set a color at an invalid index (at column %d and row %d, whereas the array have %d columns and %d rows)"; 0514 return; 0515 } 0516 0517 m_colorArray[column][row] = color; 0518 } 0519 0520 void KColorCombo2::setDefaultColor(const QColor &color) 0521 { 0522 m_defaultColor = color; 0523 if (!m_defaultColor.isValid() && !m_color.isValid()) { 0524 m_color = Qt::white; // FIXME: Use the first one. 0525 Q_EMIT defaultColorChanged(color); 0526 } 0527 } 0528 0529 QPixmap KColorCombo2::colorRectPixmap(const QColor &color, bool isDefault, int width, int height) 0530 { 0531 // Prepare to draw: 0532 QPixmap pixmap(width, height); 0533 QBitmap mask(width, height); 0534 QPainter painter(&pixmap); 0535 QPainter maskPainter(&mask); 0536 0537 // Draw pixmap: 0538 drawColorRect(painter, 0, 0, color, isDefault, width, height); 0539 0540 // Draw mask (make the four corners transparent): 0541 maskPainter.fillRect(0, 0, width, height, Qt::color1); // opaque 0542 maskPainter.setPen(Qt::color0); // transparent 0543 maskPainter.drawPoint(0, 0); 0544 maskPainter.drawPoint(0, height - 1); 0545 maskPainter.drawPoint(width - 1, height - 1); 0546 maskPainter.drawPoint(width - 1, 0); 0547 0548 // Finish: 0549 painter.end(); 0550 maskPainter.end(); 0551 pixmap.setMask(mask); 0552 return pixmap; 0553 } 0554 0555 void KColorCombo2::drawColorRect(QPainter &painter, int x, int y, const QColor &color, bool isDefault, int width, int height) 0556 { 0557 // Fill: 0558 if (color.isValid()) 0559 painter.fillRect(x /*+ 1*/, y /*+ 1*/, width /*- 2*/, height /*- 2*/, color); 0560 else { 0561 // If it's an invalid color, it's for the "Other..." entry: draw a rainbow. 0562 // If it wasn't for the "Other..." entry, the programmer made a fault, so (s)he will be informed about that visually. 0563 for (int i = 0; i < width - 2; ++i) { 0564 int hue = i * 360 / (width - 2); 0565 for (int j = 0; j < height - 2; ++j) { 0566 int saturation = 255 - (j * 255 / (height - 2)); 0567 painter.setPen(QColor::fromHsv(hue, saturation, /*value=*/255)); 0568 painter.drawPoint(x + i + 1, y + j + 1); 0569 } 0570 } 0571 } 0572 0573 // Stroke: 0574 int dontCare, value; 0575 color.getHsv(/*hue:*/ &dontCare, /*saturation:*/ &dontCare, &value); 0576 QColor stroke = (color.isValid() ? color.darker(125) : palette().color(QPalette::Text)); 0577 painter.setPen(/*color);//*/ stroke); 0578 painter.drawLine(x + 1, y, x + width - 2, y); 0579 painter.drawLine(x, y + 1, x, y + height - 2); 0580 painter.drawLine(x + 1, y + height - 1, x + width - 2, y + height - 1); 0581 painter.drawLine(x + width - 1, y + 1, x + width - 1, y + height - 2); 0582 0583 // Round corners: 0584 QColor antialiasing; 0585 if (color.isValid()) { 0586 antialiasing = Tool_mixColors(color, stroke); 0587 painter.setPen(antialiasing); 0588 painter.drawPoint(x + 1, y + 1); 0589 painter.drawPoint(x + 1, y + height - 2); 0590 painter.drawPoint(x + width - 2, y + height - 2); 0591 painter.drawPoint(x + width - 2, y + 1); 0592 } else { 0593 // The two top corners: 0594 antialiasing = Tool_mixColors(Qt::red, stroke); 0595 painter.setPen(antialiasing); 0596 painter.drawPoint(x + 1, y + 1); 0597 painter.drawPoint(x + width - 2, y + 1); 0598 // The two bottom ones: 0599 antialiasing = Tool_mixColors(Qt::white, stroke); 0600 painter.setPen(antialiasing); 0601 painter.drawPoint(x + 1, y + height - 2); 0602 painter.drawPoint(x + width - 2, y + height - 2); 0603 } 0604 0605 // Mark default color: 0606 if (isDefault) { 0607 painter.setPen(stroke); 0608 painter.drawLine(x + 1, y + height - 2, x + width - 2, y + 1); 0609 } 0610 } 0611 0612 int KColorCombo2::colorRectHeight() const 0613 { 0614 return (fontMetrics().boundingRect(i18n("(Default)")).height() + 2) * 3 / 2; 0615 } 0616 0617 int KColorCombo2::colorRectWidthForHeight(int height) const 0618 { 0619 return height * 14 / 10; // 1.4 times the height, like A4 papers. 0620 } 0621 0622 void KColorCombo2::deleteColorArray() 0623 { 0624 if (m_colorArray) { 0625 for (int i = 0; i < m_columnCount; ++i) 0626 delete[] m_colorArray[i]; 0627 delete[] m_colorArray; 0628 m_colorArray = nullptr; 0629 } 0630 } 0631 0632 void KColorCombo2::updateComboBox() 0633 { 0634 int height = colorRectHeight() * 2 / 3; // fontMetrics().boundingRect(i18n("(Default)")).height() + 2 0635 QPixmap pixmap = colorRectPixmap(effectiveColor(), !m_color.isValid(), height, height); // TODO: isDefaultColorSelected() 0636 setItemIcon(/*index=*/0, pixmap); 0637 setItemText(/*index=*/0, (m_color.isValid() ? QString(i18n("R:%1, G:%2, B:%3", m_color.red(), m_color.green(), m_color.blue())) : i18nc("color", "(Default)"))); 0638 } 0639 0640 void KColorCombo2::showPopup() 0641 { 0642 if (!m_colorArray) 0643 setRainbowPreset(); 0644 0645 // Compute where to show the popup: 0646 QRect desk = qApp->desktop()->screenGeometry(this); 0647 0648 QPoint popupPoint = mapToGlobal(QPoint(0, 0)); 0649 0650 int popupHeight = m_popup->size().height(); 0651 if (popupPoint.y() + height() + popupHeight > desk.bottom()) 0652 popupPoint.setY(popupPoint.y() - popupHeight); 0653 else 0654 popupPoint.setY(popupPoint.y() + height()); 0655 0656 int popupWidth = m_popup->size().width(); 0657 if (popupPoint.x() + popupWidth > desk.right()) 0658 popupPoint.setX(desk.right() - popupWidth); 0659 0660 if (popupPoint.x() < desk.left()) 0661 popupPoint.setX(desk.left()); 0662 0663 if (popupPoint.y() < desk.top()) 0664 popupPoint.setY(desk.top()); 0665 0666 // Configure the popup: 0667 m_popup->move(popupPoint); 0668 // m_popup->setColor(m_color); 0669 m_popup->doSelection(); 0670 m_popup->relayout(); // FIXME: In aboutToShow() ? 0671 #if 0 0672 //#ifndef QT_NO_EFFECTS 0673 if (QApplication::isEffectEnabled(UI_AnimateCombo)) { 0674 if (m_popup->y() < mapToGlobal(QPoint(0, 0)).y()) 0675 qScrollEffect(m_popup, QEffects::UpScroll); 0676 else 0677 qScrollEffect(m_popup); 0678 } else 0679 #endif 0680 m_popup->show(); 0681 0682 // The combo box is now shown pressed. Make it show not pressed again 0683 // by causing its (invisible) list box to emit a 'selected' signal. 0684 // Simulate an Enter to unpress it: 0685 /*QListWidget *lb = listBox(); 0686 if (lb) { 0687 lb->setCurrentItem(0); 0688 QKeyEvent* keyEvent = new QKeyEvent(QEvent::KeyPress, Qt::Key_Enter, 0, 0); 0689 QApplication::postEvent(lb, keyEvent); 0690 }*/ 0691 } 0692 0693 void KColorCombo2::mouseMoveEvent(QMouseEvent *event) 0694 { 0695 if ((event->buttons() & Qt::LeftButton) && (event->pos() - m_dragStartPos).manhattanLength() > qApp->startDragDistance()) { 0696 // Drag color object: 0697 QMimeData *mimeData = new QMimeData; 0698 QDrag *colorDrag = new QDrag(this); 0699 mimeData->setColorData(effectiveColor()); 0700 // Replace the drag pixmap with our own rounded one, at the same position and dimensions: 0701 QPixmap pixmap = colorDrag->pixmap(); 0702 pixmap = colorRectPixmap(effectiveColor(), /*isDefault=*/false, pixmap.width(), pixmap.height()); 0703 colorDrag->setPixmap(pixmap); 0704 colorDrag->setHotSpot(colorDrag->hotSpot()); 0705 colorDrag->exec(Qt::CopyAction, Qt::CopyAction); 0706 // setDown(false); 0707 } 0708 } 0709 0710 void KColorCombo2::dragEnterEvent(QDragEnterEvent *event) 0711 { 0712 if (isEnabled() && event->mimeData()->hasColor()) 0713 event->accept(); 0714 } 0715 0716 void KColorCombo2::dropEvent(QDropEvent *event) 0717 { 0718 QColor color; 0719 color = qvariant_cast<QColor>(event->mimeData()->colorData()); 0720 if (color.isValid()) 0721 setColor(color); 0722 } 0723 0724 void KColorCombo2::keyPressEvent(QKeyEvent *event) 0725 { 0726 QKeySequence key(event->key()); 0727 0728 if (KStandardShortcut::copy().contains(key)) { 0729 QMimeData *mime = new QMimeData; 0730 mime->setColorData(effectiveColor()); 0731 QApplication::clipboard()->setMimeData(mime, QClipboard::Clipboard); 0732 } else if (KStandardShortcut::paste().contains(key)) { 0733 QColor color; 0734 color = qvariant_cast<QColor>(QApplication::clipboard()->mimeData(QClipboard::Clipboard)->colorData()); 0735 setColor(color); 0736 } else 0737 KComboBox::keyPressEvent(event); 0738 } 0739 0740 void KColorCombo2::fontChange(const QFont &) 0741 { 0742 // Since the color-rectangle is the same height of the text, we should resize it if the font change: 0743 updateComboBox(); 0744 } 0745 0746 void KColorCombo2::virtual_hook(int /*id*/, void * /*data*/) 0747 { 0748 /* KBASE::virtual_hook(id, data); */ 0749 } 0750 0751 void KColorCombo2::popupClosed() 0752 { 0753 hidePopup(); 0754 } 0755 0756 #include "moc_kcolorcombo2.cpp" 0757 0758 #endif // USE_OLD_KCOLORCOMBO