File indexing completed on 2024-11-24 03:56:08
0001 /* 0002 * SPDX-FileCopyrightText: 2013-2023 Mattia Basaglia <dev@dragon.best> 0003 * 0004 * SPDX-License-Identifier: LGPL-3.0-or-later 0005 */ 0006 0007 #include "QtColorWidgets/swatch.hpp" 0008 #include "QtColorWidgets/qt_compatibility.hpp" 0009 0010 #include <cmath> 0011 #include <limits> 0012 #include <QPainter> 0013 #include <QMouseEvent> 0014 #include <QKeyEvent> 0015 #include <QApplication> 0016 #include <QDrag> 0017 #include <QMimeData> 0018 #include <QDropEvent> 0019 #include <QDragEnterEvent> 0020 #include <QStyleOption> 0021 #include <QToolTip> 0022 0023 namespace color_widgets { 0024 0025 class Swatch::Private 0026 { 0027 public: 0028 ColorPalette palette; ///< Palette with colors and related metadata 0029 int selected; ///< Current selection index (-1 for no selection) 0030 QSize color_size; ///< Preferred size for the color squares 0031 ColorSizePolicy size_policy; 0032 QPen border; 0033 QPen selected_pen{Qt::gray, 2, Qt::DotLine}; 0034 int forced_rows; 0035 int forced_columns; 0036 bool readonly; ///< Whether the palette can be modified via user interaction 0037 0038 QPoint drag_pos; ///< Point used to keep track of dragging 0039 int drag_index; ///< Index used by drags 0040 int drop_index; ///< Index for a requested drop 0041 QColor drop_color; ///< Dropped color 0042 bool drop_overwrite; ///< Whether the drop will overwrite an existing color 0043 0044 QSize max_color_size; ///< Mazimum size a color square can have 0045 0046 bool show_clear_color = false; 0047 0048 Swatch* owner; 0049 0050 Private(Swatch* owner) 0051 : selected(-1), 0052 color_size(16,16), 0053 size_policy(Hint), 0054 border(Qt::black, 1), 0055 forced_rows(0), 0056 forced_columns(0), 0057 readonly(false), 0058 drag_index(-1), 0059 drop_index(-1), 0060 drop_overwrite(false), 0061 max_color_size(96, 128), 0062 owner(owner) 0063 { 0064 // Ensure rectangle with 90 degree edges - default Qt::BevelJoin causes 0065 // rounded / flatted rectangle 0066 border.setJoinStyle(Qt::MiterJoin); 0067 selected_pen.setJoinStyle(Qt::MiterJoin); 0068 } 0069 0070 /** 0071 * \brief Number of rows/columns in the palette 0072 */ 0073 QSize rowcols() 0074 { 0075 int count = color_count(); 0076 0077 if ( count == 0 ) 0078 return QSize(); 0079 0080 if ( forced_rows ) 0081 return QSize(std::ceil( float(count) / forced_rows ), forced_rows); 0082 0083 int columns = palette.columns(); 0084 bool flexible_columns = false; 0085 0086 if ( forced_columns ) 0087 { 0088 columns = forced_columns; 0089 } 0090 else if ( columns == 0 ) 0091 { 0092 columns = qMin(count, (owner->width() - border.width()) / color_size.width()); 0093 flexible_columns = true; 0094 } 0095 0096 int rows = std::ceil( float(count) / columns ); 0097 0098 // Make nicer looking tables when we don't have many colors 0099 if ( flexible_columns && rows < 4 ) 0100 { 0101 int best_fit_rows = std::ceil(float(owner->height() - border.width()) / qMax(1, max_color_size.height())); 0102 if ( rows < best_fit_rows ) 0103 rows = best_fit_rows; 0104 0105 columns = std::ceil( float(count) / rows ); 0106 0107 // Avoid empty columns 0108 int avail_width = owner->width() - border.width(); 0109 if ( columns * max_color_size.width() < avail_width ) 0110 { 0111 columns = std::ceil(float(avail_width) / qMax(1, max_color_size.width())); 0112 rows = std::ceil( float(count) / columns ); 0113 } 0114 } 0115 0116 return QSize(columns, rows); 0117 } 0118 0119 int color_count() 0120 { 0121 int count = palette.count(); 0122 0123 if ( show_clear_color ) 0124 count++; 0125 0126 return count; 0127 } 0128 0129 /** 0130 * \brief Sets the drop properties 0131 */ 0132 void dropEvent(QDropEvent* event) 0133 { 0134 // Find the output location 0135 drop_index = indexAt(pos_wrap(event).toPoint()); 0136 if ( drop_index == -1 ) 0137 drop_index = palette.count(); 0138 0139 // Gather up the color 0140 if ( event->mimeData()->hasColor() ) 0141 { 0142 drop_color = event->mimeData()->colorData().value<QColor>(); 0143 drop_color.setAlpha(255); 0144 } 0145 else if ( event->mimeData()->hasText() ) 0146 { 0147 drop_color = QColor(event->mimeData()->text()); 0148 } 0149 0150 drop_overwrite = false; 0151 QRectF drop_rect = indexRect(drop_index); 0152 if ( drop_index < palette.count() && drop_rect.isValid() ) 0153 { 0154 // 1 column => vertical style 0155 if ( palette.columns() == 1 || forced_columns == 1 ) 0156 { 0157 // Dragged to the last quarter of the size of the square, add after 0158 if ( pos_wrap(event).y() >= drop_rect.top() + drop_rect.height() * 3.0 / 4 ) 0159 drop_index++; 0160 // Dragged to the middle of the square, overwrite existing color 0161 else if ( pos_wrap(event).x() > drop_rect.top() + drop_rect.height() / 4 && 0162 ( event->dropAction() != Qt::MoveAction || event->source() != owner ) ) 0163 drop_overwrite = true; 0164 } 0165 else 0166 { 0167 // Dragged to the last quarter of the size of the square, add after 0168 if ( pos_wrap(event).x() >= drop_rect.left() + drop_rect.width() * 3.0 / 4 ) 0169 drop_index++; 0170 // Dragged to the middle of the square, overwrite existing color 0171 else if ( pos_wrap(event).x() > drop_rect.left() + drop_rect.width() / 4 && 0172 ( event->dropAction() != Qt::MoveAction || event->source() != owner ) ) 0173 drop_overwrite = true; 0174 } 0175 } 0176 0177 owner->update(); 0178 } 0179 0180 /** 0181 * \brief Clears drop properties 0182 */ 0183 void clearDrop() 0184 { 0185 drop_index = -1; 0186 drop_color = QColor(); 0187 drop_overwrite = false; 0188 0189 owner->update(); 0190 } 0191 0192 /** 0193 * \brief Actual size of a color square 0194 */ 0195 QSizeF actualColorSize() 0196 { 0197 QSize rowcols = this->rowcols(); 0198 if ( !rowcols.isValid() ) 0199 return QSizeF(); 0200 return actualColorSize(rowcols); 0201 } 0202 0203 /** 0204 * \brief Actual size of a color square 0205 * \pre rowcols.isValid() and obtained via rowcols() 0206 */ 0207 QSizeF actualColorSize(const QSize& rowcols) 0208 { 0209 return QSizeF ( 0210 qMin(qreal(max_color_size.width()), qreal(owner->width() - border.width()) / rowcols.width()), 0211 qMin(qreal(max_color_size.height()), qreal(owner->height() - border.width()) / rowcols.height()) 0212 ); 0213 } 0214 0215 0216 /** 0217 * \brief Rectangle corresponding to the color at the given index 0218 * \pre rowcols.isValid() and obtained via rowcols() 0219 * \pre color_size obtained via rowlcols(rowcols) 0220 */ 0221 QRectF indexRect(int index, const QSize& rowcols, const QSizeF& color_size) 0222 { 0223 if ( index == -1 ) 0224 return QRectF(); 0225 0226 return QRectF( 0227 index % rowcols.width() * color_size.width() + border.width() / 2, 0228 index / rowcols.width() * color_size.height() + border.width() / 2, 0229 color_size.width(), 0230 color_size.height() 0231 ); 0232 } 0233 /** 0234 * \brief Rectangle corresponding to the color at the given index 0235 */ 0236 QRectF indexRect(int index) 0237 { 0238 QSize rc = rowcols(); 0239 if ( index == -1 || !rc.isValid() ) 0240 return QRectF(); 0241 return indexRect(index, rc, actualColorSize(rc)); 0242 } 0243 0244 int indexAt(const QPoint& pt, bool mark_clear = false) 0245 { 0246 QSize rowcols = this->rowcols(); 0247 if ( rowcols.isEmpty() ) 0248 return -1; 0249 0250 QSizeF color_size = actualColorSize(rowcols); 0251 0252 QPoint point( 0253 pt.x() / color_size.width(), 0254 pt.y() / color_size.height() 0255 ); 0256 0257 if ( point.x() < 0 || point.x() >= rowcols.width() || point.y() < 0 || point.y() >= rowcols.height() ) 0258 return -1; 0259 0260 int index = point.y() * rowcols.width() + point.x(); 0261 0262 if ( mark_clear && index == palette.count() && show_clear_color ) 0263 return -2; 0264 0265 if ( index >= palette.count() ) 0266 return -1; 0267 return index; 0268 } 0269 }; 0270 0271 Swatch::Swatch(QWidget* parent) 0272 : QWidget(parent), p(new Private(this)) 0273 { 0274 connect(&p->palette, &ColorPalette::colorsChanged, this, &Swatch::paletteModified); 0275 connect(&p->palette, &ColorPalette::colorAdded, this, &Swatch::paletteModified); 0276 connect(&p->palette, &ColorPalette::colorRemoved, this, &Swatch::paletteModified); 0277 connect(&p->palette, &ColorPalette::columnsChanged, this, (void(QWidget::*)())&QWidget::update); 0278 connect(&p->palette, &ColorPalette::colorsUpdated, this, (void(QWidget::*)())&QWidget::update); 0279 connect(&p->palette, &ColorPalette::colorChanged, [this](int index){ 0280 if ( index == p->selected ) 0281 Q_EMIT colorSelected( p->palette.colorAt(index) ); 0282 }); 0283 setFocusPolicy(Qt::StrongFocus); 0284 setAcceptDrops(true); 0285 setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); 0286 setAttribute(Qt::WA_Hover, true); 0287 } 0288 0289 Swatch::~Swatch() 0290 { 0291 delete p; 0292 } 0293 0294 QSize Swatch::sizeHint() const 0295 { 0296 QSize rowcols = p->rowcols(); 0297 0298 if ( !p->color_size.isValid() || !rowcols.isValid() ) 0299 return QSize(); 0300 0301 return QSize( 0302 p->color_size.width() * rowcols.width(), 0303 p->color_size.height() * rowcols.height() 0304 ); 0305 } 0306 0307 QSize Swatch::minimumSizeHint() const 0308 { 0309 if ( p->size_policy != Hint ) 0310 return sizeHint(); 0311 return QSize(); 0312 } 0313 0314 const ColorPalette& Swatch::palette() const 0315 { 0316 return p->palette; 0317 } 0318 0319 ColorPalette& Swatch::palette() 0320 { 0321 return p->palette; 0322 } 0323 0324 int Swatch::selected() const 0325 { 0326 return p->selected; 0327 } 0328 0329 QColor Swatch::selectedColor() const 0330 { 0331 return p->palette.colorAt(p->selected); 0332 } 0333 0334 int Swatch::indexAt(const QPoint& pt) 0335 { 0336 return p->indexAt(pt); 0337 } 0338 0339 QColor Swatch::colorAt(const QPoint& pt) 0340 { 0341 return p->palette.colorAt(indexAt(pt)); 0342 } 0343 0344 void Swatch::setPalette(const ColorPalette& palette) 0345 { 0346 clearSelection(); 0347 p->palette = palette; 0348 update(); 0349 Q_EMIT paletteChanged(p->palette); 0350 } 0351 0352 void Swatch::setSelected(int selected) 0353 { 0354 if ( selected < 0 || selected >= p->palette.count() ) 0355 selected = -1; 0356 0357 if ( selected != p->selected ) 0358 { 0359 Q_EMIT selectedChanged( p->selected = selected ); 0360 if ( selected != -1 ) 0361 Q_EMIT colorSelected( p->palette.colorAt(p->selected) ); 0362 } 0363 update(); 0364 } 0365 0366 0367 bool Swatch::setSelectedColor(const QColor& color) 0368 { 0369 for (int i = 0; i < p->palette.count(); i++) 0370 { 0371 if (p->palette.colorAt(i) == color) 0372 { 0373 setSelected(i); 0374 return true; 0375 } 0376 } 0377 0378 return false; 0379 } 0380 0381 void Swatch::clearSelection() 0382 { 0383 setSelected(-1); 0384 } 0385 0386 void Swatch::paintEvent(QPaintEvent* event) 0387 { 0388 Q_UNUSED(event) 0389 QSize rowcols = p->rowcols(); 0390 0391 QPainter painter(this); 0392 0393 QStyleOptionFrame panel; 0394 panel.initFrom(this); 0395 panel.lineWidth = 1; 0396 panel.midLineWidth = 0; 0397 panel.state |= QStyle::State_Sunken; 0398 style()->drawPrimitive(QStyle::PE_Frame, &panel, &painter, this); 0399 0400 if ( rowcols.isEmpty() ) 0401 return; 0402 0403 QSizeF color_size = p->actualColorSize(rowcols); 0404 QRect r = style()->subElementRect(QStyle::SE_FrameContents, &panel, this); 0405 painter.setClipRect(r); 0406 0407 int count = p->palette.count(); 0408 painter.setPen(p->border); 0409 for ( int y = 0, i = 0; i < count; y++ ) 0410 { 0411 for ( int x = 0; x < rowcols.width() && i < count; x++, i++ ) 0412 { 0413 painter.setBrush(p->palette.colorAt(i)); 0414 painter.drawRect(p->indexRect(i, rowcols, color_size)); 0415 } 0416 } 0417 0418 if ( p->show_clear_color ) 0419 { 0420 QRectF ir = p->indexRect(count, rowcols, color_size); 0421 painter.setBrush(QColor(255, 255, 255)); 0422 painter.drawRect(ir); 0423 painter.setPen(QPen(QColor(0xa40000), qBound(1., 5., color_size.width()/3))); 0424 painter.setBrush(Qt::NoBrush); 0425 painter.setClipRect(ir, Qt::IntersectClip); 0426 painter.setRenderHint(QPainter::Antialiasing); 0427 painter.drawLine(ir.topLeft(), ir.bottomRight()); 0428 painter.drawLine(ir.topRight(), ir.bottomLeft()); 0429 } 0430 0431 painter.setClipping(false); 0432 0433 if ( p->drop_index != -1 ) 0434 { 0435 QRectF drop_area = p->indexRect(p->drop_index, rowcols, color_size); 0436 if ( p->drop_overwrite ) 0437 { 0438 painter.setBrush(p->drop_color); 0439 painter.setPen(QPen(Qt::gray)); 0440 painter.drawRect(drop_area); 0441 } 0442 else if ( rowcols.width() == 1 ) 0443 { 0444 // 1 column => vertical style 0445 painter.setPen(QPen(p->drop_color, 2)); 0446 painter.setBrush(Qt::transparent); 0447 painter.drawLine(drop_area.topLeft(), drop_area.topRight()); 0448 } 0449 else 0450 { 0451 painter.setPen(QPen(p->drop_color, 2)); 0452 painter.setBrush(Qt::transparent); 0453 painter.drawLine(drop_area.topLeft(), drop_area.bottomLeft()); 0454 // Draw also on the previous line when the first item of a line is selected 0455 if ( p->drop_index % rowcols.width() == 0 && p->drop_index != 0 ) 0456 { 0457 drop_area = p->indexRect(p->drop_index-1, rowcols, color_size); 0458 drop_area.translate(color_size.width(), 0); 0459 painter.drawLine(drop_area.topLeft(), drop_area.bottomLeft()); 0460 } 0461 } 0462 } 0463 0464 if ( p->selected != -1 ) 0465 { 0466 QRectF rect = p->indexRect(p->selected, rowcols, color_size); 0467 int offset = p->border.width() / 2; 0468 rect.adjust(offset, offset, -offset, -offset); 0469 painter.setBrush(Qt::transparent); 0470 painter.setPen(p->selected_pen); 0471 painter.drawRect(rect); 0472 } 0473 } 0474 0475 void Swatch::keyPressEvent(QKeyEvent* event) 0476 { 0477 if ( p->palette.count() == 0 ) 0478 QWidget::keyPressEvent(event); 0479 0480 int selected = p->selected; 0481 int count = p->palette.count(); 0482 QSize rowcols = p->rowcols(); 0483 int columns = rowcols.width(); 0484 int rows = rowcols.height(); 0485 switch ( event->key() ) 0486 { 0487 default: 0488 QWidget::keyPressEvent(event); 0489 return; 0490 0491 case Qt::Key_Left: 0492 if ( selected == -1 ) 0493 selected = count - 1; 0494 else if ( selected > 0 ) 0495 selected--; 0496 break; 0497 0498 case Qt::Key_Right: 0499 if ( selected == -1 ) 0500 selected = 0; 0501 else if ( selected < count - 1 ) 0502 selected++; 0503 break; 0504 0505 case Qt::Key_Up: 0506 if ( selected == -1 ) 0507 selected = count - 1; 0508 else if ( selected >= columns ) 0509 selected -= columns; 0510 break; 0511 0512 case Qt::Key_Down: 0513 if ( selected == -1 ) 0514 selected = 0; 0515 else if ( selected < count - columns ) 0516 selected += columns; 0517 break; 0518 0519 case Qt::Key_Home: 0520 if ( event->modifiers() & Qt::ControlModifier ) 0521 selected = 0; 0522 else 0523 selected -= selected % columns; 0524 break; 0525 0526 case Qt::Key_End: 0527 if ( event->modifiers() & Qt::ControlModifier ) 0528 selected = count - 1; 0529 else 0530 selected += columns - (selected % columns) - 1; 0531 break; 0532 0533 case Qt::Key_Delete: 0534 removeSelected(); 0535 return; 0536 0537 case Qt::Key_Backspace: 0538 if (selected != -1 && !p->readonly ) 0539 { 0540 p->palette.eraseColor(selected); 0541 if ( p->palette.count() == 0 ) 0542 selected = -1; 0543 else 0544 selected = qMax(selected - 1, 0); 0545 } 0546 break; 0547 0548 case Qt::Key_PageUp: 0549 if ( selected == -1 ) 0550 selected = 0; 0551 else 0552 selected = selected % columns; 0553 break; 0554 case Qt::Key_PageDown: 0555 if ( selected == -1 ) 0556 { 0557 selected = count - 1; 0558 } 0559 else 0560 { 0561 selected = columns * (rows-1) + selected % columns; 0562 if ( selected >= count ) 0563 selected -= columns; 0564 } 0565 break; 0566 } 0567 setSelected(selected); 0568 } 0569 0570 void Swatch::removeSelected() 0571 { 0572 if (p->selected != -1 && !p->readonly ) 0573 { 0574 int selected = p->selected; 0575 p->palette.eraseColor(p->selected); 0576 setSelected(qMin(selected, p->palette.count() - 1)); 0577 } 0578 } 0579 0580 void Swatch::mousePressEvent(QMouseEvent *event) 0581 { 0582 if ( event->button() == Qt::LeftButton ) 0583 { 0584 int index = p->indexAt(event->pos(), true); 0585 setSelected(index); 0586 p->drag_pos = event->pos(); 0587 p->drag_index = index; 0588 if ( index == -2 ) 0589 Q_EMIT clicked(-1, event->modifiers()); 0590 else if ( index != -1 ) 0591 Q_EMIT clicked(index, event->modifiers()); 0592 } 0593 else if ( event->button() == Qt::RightButton ) 0594 { 0595 int index = p->indexAt(event->pos(), true); 0596 0597 if ( index == -2 ) 0598 Q_EMIT rightClicked(-1, event->modifiers()); 0599 else if ( index != -1 ) 0600 Q_EMIT rightClicked(index, event->modifiers()); 0601 } 0602 } 0603 0604 void Swatch::mouseMoveEvent(QMouseEvent *event) 0605 { 0606 if ( p->drag_index != -1 && (event->buttons() & Qt::LeftButton) && 0607 (p->drag_pos - event->pos()).manhattanLength() >= QApplication::startDragDistance() ) 0608 { 0609 QColor color = p->palette.colorAt(p->drag_index); 0610 0611 QPixmap preview(24,24); 0612 preview.fill(color); 0613 0614 QMimeData *mimedata = new QMimeData; 0615 mimedata->setColorData(color); 0616 mimedata->setText(p->palette.nameAt(p->drag_index)); 0617 0618 QDrag *drag = new QDrag(this); 0619 drag->setMimeData(mimedata); 0620 drag->setPixmap(preview); 0621 Qt::DropActions actions = Qt::CopyAction; 0622 if ( !p->readonly ) 0623 actions |= Qt::MoveAction; 0624 drag->exec(actions); 0625 } 0626 } 0627 0628 void Swatch::mouseReleaseEvent(QMouseEvent *event) 0629 { 0630 if ( event->button() == Qt::LeftButton ) 0631 { 0632 p->drag_index = -1; 0633 } 0634 } 0635 0636 void Swatch::mouseDoubleClickEvent(QMouseEvent *event) 0637 { 0638 if ( event->button() == Qt::LeftButton ) 0639 { 0640 int index = p->indexAt(event->pos(), true); 0641 0642 if ( index == -2 ) 0643 Q_EMIT doubleClicked(-1, event->modifiers()); 0644 else if ( index != -1 ) 0645 Q_EMIT doubleClicked(index, event->modifiers()); 0646 } 0647 } 0648 0649 void Swatch::wheelEvent(QWheelEvent* event) 0650 { 0651 if ( event->angleDelta().y() < 0 ) 0652 p->selected = qMin(p->selected + 1, p->palette.count() - 1); 0653 else if ( p->selected == -1 ) 0654 p->selected = p->palette.count() - 1; 0655 else if ( p->selected > 0 ) 0656 p->selected--; 0657 setSelected(p->selected); 0658 } 0659 0660 void Swatch::dragEnterEvent(QDragEnterEvent *event) 0661 { 0662 if ( p->readonly ) 0663 return; 0664 0665 p->dropEvent(event); 0666 0667 if ( p->drop_color.isValid() && p->drop_index != -1 ) 0668 { 0669 if ( event->proposedAction() == Qt::MoveAction && event->source() == this ) 0670 event->setDropAction(Qt::MoveAction); 0671 else 0672 event->setDropAction(Qt::CopyAction); 0673 0674 event->accept(); 0675 } 0676 } 0677 0678 void Swatch::dragMoveEvent(QDragMoveEvent* event) 0679 { 0680 if ( p->readonly ) 0681 return; 0682 p->dropEvent(event); 0683 } 0684 0685 void Swatch::dragLeaveEvent(QDragLeaveEvent *event) 0686 { 0687 Q_UNUSED(event) 0688 p->clearDrop(); 0689 } 0690 0691 void Swatch::dropEvent(QDropEvent *event) 0692 { 0693 if ( p->readonly ) 0694 return; 0695 0696 QString name; 0697 0698 // Gather up the color 0699 if ( event->mimeData()->hasColor() && event->mimeData()->hasText() ) 0700 name = event->mimeData()->text(); 0701 0702 // Not a color, discard 0703 if ( !p->drop_color.isValid() || p->drop_index == -1 ) 0704 return; 0705 0706 p->dropEvent(event); 0707 0708 // Move unto self 0709 if ( event->dropAction() == Qt::MoveAction && event->source() == this ) 0710 { 0711 // Not moved => noop 0712 if ( p->drop_index != p->drag_index && p->drop_index != p->drag_index + 1 ) 0713 { 0714 // Erase the old color 0715 p->palette.eraseColor(p->drag_index); 0716 if ( p->drop_index > p->drag_index ) 0717 p->drop_index--; 0718 p->selected = p->drop_index; 0719 // Insert the dropped color 0720 p->palette.insertColor(p->drop_index, p->drop_color, name); 0721 } 0722 } 0723 // Move into a color cell 0724 else if ( p->drop_overwrite ) 0725 { 0726 p->palette.setColorAt(p->drop_index, p->drop_color, name); 0727 } 0728 // Insert the dropped color 0729 else 0730 { 0731 p->palette.insertColor(p->drop_index, p->drop_color, name); 0732 } 0733 0734 // Finalize 0735 event->accept(); 0736 p->drag_index = -1; 0737 p->clearDrop(); 0738 } 0739 0740 void Swatch::paletteModified() 0741 { 0742 if ( p->selected >= p->palette.count() ) 0743 clearSelection(); 0744 0745 if ( p->size_policy != Hint ) 0746 { 0747 QSize size_hint = sizeHint(); 0748 0749 if ( size_hint.isValid() ) 0750 { 0751 if ( p->size_policy == Minimum ) 0752 setMinimumSize(size_hint); 0753 else if ( p->size_policy == Fixed ) 0754 setFixedSize(size_hint); 0755 } 0756 } 0757 0758 update(); 0759 } 0760 0761 QSize Swatch::colorSize() const 0762 { 0763 return p->color_size; 0764 } 0765 0766 void Swatch::setColorSize(const QSize& colorSize) 0767 { 0768 if ( p->color_size != colorSize ) 0769 Q_EMIT colorSizeChanged(p->color_size = colorSize); 0770 } 0771 0772 QSize Swatch::maxColorSize() const 0773 { 0774 return p->max_color_size; 0775 } 0776 0777 void Swatch::setMaxColorSize(const QSize& colorSize) 0778 { 0779 if ( p->max_color_size != colorSize ) 0780 Q_EMIT maxColorSizeChanged(p->max_color_size = colorSize); 0781 } 0782 0783 Swatch::ColorSizePolicy Swatch::colorSizePolicy() const 0784 { 0785 return p->size_policy; 0786 } 0787 0788 void Swatch::setColorSizePolicy(ColorSizePolicy colorSizePolicy) 0789 { 0790 if ( p->size_policy != colorSizePolicy ) 0791 { 0792 setMinimumSize(0,0); 0793 setFixedSize(QWIDGETSIZE_MAX,QWIDGETSIZE_MAX); 0794 Q_EMIT colorSizePolicyChanged(p->size_policy = colorSizePolicy); 0795 paletteModified(); 0796 } 0797 } 0798 0799 int Swatch::forcedColumns() const 0800 { 0801 return p->forced_columns; 0802 } 0803 0804 int Swatch::forcedRows() const 0805 { 0806 return p->forced_rows; 0807 } 0808 0809 void Swatch::setForcedColumns(int forcedColumns) 0810 { 0811 if ( forcedColumns <= 0 ) 0812 forcedColumns = 0; 0813 0814 if ( forcedColumns != p->forced_columns ) 0815 { 0816 Q_EMIT forcedColumnsChanged(p->forced_columns = forcedColumns); 0817 Q_EMIT forcedRowsChanged(p->forced_rows = 0); 0818 } 0819 } 0820 0821 void Swatch::setForcedRows(int forcedRows) 0822 { 0823 if ( forcedRows <= 0 ) 0824 forcedRows = 0; 0825 0826 if ( forcedRows != p->forced_rows ) 0827 { 0828 Q_EMIT forcedColumnsChanged(p->forced_columns = 0); 0829 Q_EMIT forcedRowsChanged(p->forced_rows = forcedRows); 0830 } 0831 } 0832 0833 bool Swatch::readOnly() const 0834 { 0835 return p->readonly; 0836 } 0837 0838 void Swatch::setReadOnly(bool readOnly) 0839 { 0840 if ( readOnly != p->readonly ) 0841 { 0842 Q_EMIT readOnlyChanged(p->readonly = readOnly); 0843 setAcceptDrops(!p->readonly); 0844 } 0845 } 0846 0847 bool Swatch::event(QEvent* event) 0848 { 0849 if(event->type() == QEvent::ToolTip) 0850 { 0851 QHelpEvent* help_ev = static_cast<QHelpEvent*>(event); 0852 int index = p->indexAt(help_ev->pos(), true); 0853 if ( index == -2 ) 0854 { 0855 QToolTip::showText(help_ev->globalPos(), tr("Clear Color"), this, p->indexRect(index).toRect()); 0856 event->accept(); 0857 } 0858 else if ( index != -1 ) 0859 { 0860 QColor color = p->palette.colorAt(index); 0861 QString name = p->palette.nameAt(index); 0862 QString message = color.name(); 0863 if ( !name.isEmpty() ) 0864 message = tr("%1 (%2)").arg(name).arg(message); 0865 message = QStringLiteral("<tt style='background-color:%1;color:%2;'>MM</tt> %3") 0866 .arg(color.name()) 0867 .arg(color.name()) 0868 .arg(message.toHtmlEscaped()); 0869 QToolTip::showText(help_ev->globalPos(), message, this, 0870 p->indexRect(index).toRect()); 0871 event->accept(); 0872 } 0873 else 0874 { 0875 QToolTip::hideText(); 0876 event->ignore(); 0877 } 0878 return true; 0879 } 0880 0881 return QWidget::event(event); 0882 } 0883 0884 QPen Swatch::border() const 0885 { 0886 return p->border; 0887 } 0888 0889 void Swatch::setBorder(const QPen& border) 0890 { 0891 if ( border != p->border ) 0892 { 0893 p->border = border; 0894 Q_EMIT borderChanged(border); 0895 update(); 0896 } 0897 } 0898 0899 0900 void Swatch::setSelectionPen(const QPen& selected) 0901 { 0902 if ( selected != p->selected_pen ) 0903 { 0904 p->selected_pen = selected; 0905 update(); 0906 } 0907 } 0908 0909 0910 QPen Swatch::selectionPen() const 0911 { 0912 return p->selected_pen; 0913 } 0914 0915 0916 bool Swatch::showClearColor() const 0917 { 0918 return p->show_clear_color; 0919 } 0920 0921 void Swatch::setShowClearColor(bool show) 0922 { 0923 if ( show != p->show_clear_color ) 0924 { 0925 Q_EMIT showClearColorChanged(p->show_clear_color = show); 0926 update(); 0927 } 0928 } 0929 0930 0931 } // namespace color_widgets