8#include "swatchbook_p.h"
10#include "abstractdiagram.h"
11#include "constpropagatingrawpointer.h"
12#include "constpropagatinguniquepointer.h"
14#include "helpermath.h"
15#include "initializetranslation.h"
17#include "rgbcolorspace.h"
20#include <qapplication.h>
21#include <qcoreapplication.h>
22#include <qcoreevent.h>
24#include <qfontmetrics.h>
28#include <qnamespace.h>
30#include <qpainterpath.h>
34#include <qsharedpointer.h>
35#include <qsizepolicy.h>
36#include <qstringliteral.h>
38#include <qstyleoption.h>
39#include <qtransform.h>
42#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
43#include <qcontainerfwd.h>
45#include <qstringlist.h>
64void SwatchBookPrivate::retranslateUi()
92 auto ucs4 = translation.
toUcs4();
95 for (
int i = 0; okay && (i < ucs4.count()); ++i) {
96 okay = myFontMetrics.inFontUcs4(ucs4.at(i));
101 m_selectionMark = translation;
125 const Array2D<QColor> &swatches,
128 : AbstractDiagram(parent)
129 , d_pointer(new SwatchBookPrivate(this, swatches, wideSpacing))
131 d_pointer->m_rgbColorSpace = colorSpace;
133 setFocusPolicy(Qt::FocusPolicy::StrongFocus);
142 d_pointer->selectSwatch(8, 0);
149 std::optional<QStringList>());
150 d_pointer->retranslateUi();
154SwatchBook::~SwatchBook() noexcept
165SwatchBookPrivate::SwatchBookPrivate(SwatchBook *backLink,
const Array2D<QColor> &swatches,
Qt::Orientations wideSpacing)
166 : m_swatches(swatches)
167 , m_wideSpacing(wideSpacing)
168 , q_pointer(backLink)
179QSize SwatchBook::sizeHint()
const
181 return minimumSizeHint();
191QSize SwatchBook::minimumSizeHint()
const
195 d_pointer->initStyleOption(&myOption);
196 const auto contentSize = d_pointer->colorPatchesSizeWithMargin();
205 const auto lineWidth = myOption.lineWidth;
206 QMargins margins{lineWidth, lineWidth, lineWidth, lineWidth};
214QColor SwatchBook::currentColor()
const
216 return d_pointer->m_currentColor;
222void SwatchBook::setCurrentColor(
const QColor &newCurrentColor)
225 QColor temp = newCurrentColor;
229 if (temp.
spec() != QColor::Spec::Rgb) {
241 if (temp == d_pointer->m_currentColor) {
245 d_pointer->m_currentColor = temp;
247 bool colorFound =
false;
248 const qsizetype myColumnCount = d_pointer->m_swatches.iCount();
249 const qsizetype myRowCount = d_pointer->m_swatches.jCount();
252 for (columnIndex = 0;
253 columnIndex < myColumnCount;
255 for (rowIndex = 0; rowIndex < myRowCount; ++rowIndex) {
256 if (d_pointer->m_swatches.value(columnIndex, rowIndex) == temp) {
266 d_pointer->m_selectedColumn = columnIndex;
267 d_pointer->m_selectedRow = rowIndex;
269 d_pointer->m_selectedColumn = -1;
270 d_pointer->m_selectedRow = -1;
273 Q_EMIT currentColorChanged(temp);
290void SwatchBookPrivate::selectSwatch(QListSizeType newCurrentColomn, QListSizeType newCurrentRow)
292 const auto newColor = m_swatches.value(newCurrentColomn, newCurrentRow);
293 if (!newColor.isValid()) {
296 m_selectedColumn = newCurrentColomn;
297 m_selectedRow = newCurrentRow;
298 if (newColor != m_currentColor) {
299 m_currentColor = newColor;
300 Q_EMIT q_pointer->currentColorChanged(newColor);
312int SwatchBookPrivate::horizontalPatchSpacing()
const
314 if (m_wideSpacing.testFlag(Qt::Orientation::Horizontal)) {
315 return widePatchSpacing();
317 return normalPatchSpacing();
327int SwatchBookPrivate::widePatchSpacing()
const
335 int temp = q_pointer->style()->pixelMetric(
338 q_pointer.toPointerToConstObject());
346 temp = q_pointer->style()->pixelMetric(
349 q_pointer.toPointerToConstObject());
353 temp = q_pointer->style()->pixelMetric(
356 q_pointer.toPointerToConstObject());
359 return qMax(temp, 2);
368int SwatchBookPrivate::verticalPatchSpacing()
const
370 if (m_wideSpacing.testFlag(Qt::Orientation::Vertical)) {
371 return widePatchSpacing();
373 return normalPatchSpacing();
382int SwatchBookPrivate::normalPatchSpacing()
const
384 return qMax(widePatchSpacing() / 3,
400 if (option ==
nullptr) {
403 option->
initFrom(q_pointer.toPointerToConstObject());
404 option->lineWidth = q_pointer->style()->pixelMetric(
407 q_pointer.toPointerToConstObject());
408 option->midLineWidth = 0;
430 const QRectF frameContentRectangle = q_pointer->style()->subElementRect(
433 q_pointer.toPointerToConstObject());
434 const QSizeF swatchbookContentSize = colorPatchesSizeWithMargin();
447 frameOffset.
rx() -= swatchbookContentSize.
width() / 2.;
448 frameOffset.
ry() -= swatchbookContentSize.
height() / 2.;
450 return (frameOffset + innerMarginOffset).toPoint();
458void SwatchBook::mousePressEvent(
QMouseEvent *event)
471 const QSize myColorPatchSize = d_pointer->patchSizeOuter();
472 const int myPatchWidth = myColorPatchSize.
width();
473 const int myPatchHeight = myColorPatchSize.
height();
475 d_pointer->initStyleOption(&myFrameStyleOption);
476 const QPoint temp =
event->pos() - d_pointer->offset(myFrameStyleOption);
478 if ((temp.
x() < 0) || (temp.
y() < 0)) {
482 const auto columnWidth = myPatchWidth + d_pointer->horizontalPatchSpacing();
483 const int xWithinPatch = temp.
x() % columnWidth;
484 if (xWithinPatch >= myPatchWidth) {
488 const auto rowHeight = myPatchHeight + d_pointer->verticalPatchSpacing();
489 const int yWithinPatch = temp.
y() % rowHeight;
490 if (yWithinPatch >= myPatchHeight) {
494 const int rowIndex = temp.
y() / rowHeight;
495 if (!isInRange<qsizetype>(0, rowIndex, d_pointer->m_swatches.jCount() - 1)) {
502 const int visualColumnIndex = temp.
x() / columnWidth;
503 QListSizeType columnIndex;
504 if (layoutDirection() == Qt::LayoutDirection::LeftToRight) {
505 columnIndex = visualColumnIndex;
508 d_pointer->m_swatches.iCount() - 1 - visualColumnIndex;
510 if (!isInRange<qsizetype>(0, columnIndex, d_pointer->m_swatches.iCount() - 1)) {
519 d_pointer->selectSwatch(columnIndex, rowIndex);
530QSize SwatchBookPrivate::patchSizeOuter()
const
532 q_pointer->ensurePolished();
533 const QSize mySize = patchSizeInner();
535 myOptions.
initFrom(q_pointer.toPointerToConstObject());
536 myOptions.rect.setSize(mySize);
537 return q_pointer->style()->sizeFromContents(
541 q_pointer.toPointerToConstObject());
550QSize SwatchBookPrivate::patchSizeInner()
const
552 const int metric = q_pointer->style()->pixelMetric(
555 q_pointer.toPointerToConstObject());
556 const int size = std::max({metric,
557 horizontalPatchSpacing(),
558 verticalPatchSpacing()});
559 return QSize(size, size);
575 d_pointer->initStyleOption(&frameStyleOption);
576 const int horizontalSpacing = d_pointer->horizontalPatchSpacing();
577 const int verticalSpacing = d_pointer->verticalPatchSpacing();
578 const QSize patchSizeOuter = d_pointer->patchSizeOuter();
579 const int patchWidthOuter = patchSizeOuter.
width();
580 const int patchHeightOuter = patchSizeOuter.
height();
590 QStringLiteral(
"windowsvista"),
593 const int shrink = vistaStyle ? 1 : 0;
594 const QMargins margins(shrink, shrink, shrink, shrink);
595 auto shrunkFrameStyleOption = frameStyleOption;
596 shrunkFrameStyleOption.rect = frameStyleOption.rect - margins;
609 &shrunkFrameStyleOption,
615 const QPoint offset = d_pointer->offset(frameStyleOption);
616 const QListSizeType columnCount = d_pointer->m_swatches.iCount();
617 QListSizeType visualColumn;
618 for (
int columnIndex = 0; columnIndex < columnCount; ++columnIndex) {
620 row < d_pointer->m_swatches.jCount();
623 const auto swatchColor =
624 d_pointer->m_swatches.value(columnIndex, row);
625 if (swatchColor.isValid()) {
626 widgetPainter.setBrush(swatchColor);
628 if (layoutDirection() == Qt::LayoutDirection::LeftToRight) {
629 visualColumn = columnIndex;
631 visualColumn = columnCount - 1 - columnIndex;
633 widgetPainter.drawRect(
635 + (
static_cast<int>(visualColumn)
636 * (patchWidthOuter + horizontalSpacing)),
638 + row * (patchHeightOuter + verticalSpacing),
646 if (d_pointer->m_selectedColumn < 0 || d_pointer->m_selectedRow < 0) {
651 const QListSizeType visualSelectedColumnIndex =
652 (layoutDirection() == Qt::LayoutDirection::LeftToRight)
653 ? d_pointer->m_selectedColumn
654 : d_pointer->m_swatches.iCount() - 1 - d_pointer->m_selectedColumn;
655 const LchDouble colorCielchD50 =
656 d_pointer->m_rgbColorSpace->toCielchD50Double(
659 .value(d_pointer->m_selectedColumn, d_pointer->m_selectedRow)
662 const QColor selectionMarkColor =
663 handleColorFromBackgroundLightness(colorCielchD50.l);
666 + (
static_cast<int>(visualSelectedColumnIndex)
667 * (patchWidthOuter + horizontalSpacing)),
669 + (
static_cast<int>(d_pointer->m_selectedRow)
670 * (patchHeightOuter + verticalSpacing)));
671 const QSize patchSizeInner = d_pointer->patchSizeInner();
672 const int patchWidthInner = patchSizeInner.
width();
673 const int patchHeightInner = patchSizeInner.
height();
674 if (d_pointer->m_selectionMark.isEmpty()) {
677 const QSize sizeDifference = patchSizeOuter - patchSizeInner;
680 sizeDifference.
width() / 2.0,
681 sizeDifference.
height() / 2.0);
682 if (patchWidthInner > patchHeightInner) {
683 selectionMarkOffset.
rx() +=
684 ((patchWidthInner - patchHeightInner) / 2.0);
686 if (patchHeightInner > patchWidthInner) {
687 selectionMarkOffset.
ry() +=
688 ((patchHeightInner - patchWidthInner) / 2.0);
690 const int effectiveSquareSize = qMin(
693 qreal penWidth = effectiveSquareSize * 0.08;
698 widgetPainter.setPen(pen);
700 0.7 * effectiveSquareSize);
701 point1 += selectedPatchOffset + selectionMarkOffset;
702 QPointF point2(0.35 * effectiveSquareSize,
703 1 * effectiveSquareSize - penWidth);
704 point2 += selectedPatchOffset + selectionMarkOffset;
705 QPointF point3(1 * effectiveSquareSize - penWidth,
707 point3 += selectedPatchOffset + selectionMarkOffset;
708 widgetPainter.drawLine(
QLineF(point1, point2));
709 widgetPainter.drawLine(
QLineF(point2, point3));
713 textPath.
addText(0, 0, font(), d_pointer->m_selectionMark);
720 if (!boundingRectangleSize.
isEmpty()) {
726 selectedPatchOffset.
x()
727 + (patchWidthOuter - patchWidthInner) / 2,
729 selectedPatchOffset.
y()
730 + (patchHeightOuter - patchHeightInner) / 2);
733 const qreal scaleFactor = qMin(
735 patchWidthInner / boundingRectangleSize.
width(),
737 patchHeightInner / boundingRectangleSize.
height());
738 QSizeF scaledSelectionMarkSize =
739 boundingRectangleSize * scaleFactor;
741 (patchSizeInner - scaledSelectionMarkSize) / 2;
743 textTransform.
scale(scaleFactor, scaleFactor);
746 widgetPainter.setTransform(textTransform);
748 widgetPainter.setBrush(selectionMarkColor);
749 widgetPainter.drawPath(textPath);
767void SwatchBook::keyPressEvent(
QKeyEvent *event)
769 QListSizeType columnShift = 0;
770 QListSizeType rowShift = 0;
771 const int writingDirection =
775 switch (
event->key()) {
783 columnShift = -1 * writingDirection;
786 columnShift = 1 * writingDirection;
789 rowShift = (-1) * d_pointer->m_swatches.jCount();
792 rowShift = d_pointer->m_swatches.jCount();
795 columnShift = (-1) * d_pointer->m_swatches.iCount();
798 columnShift = d_pointer->m_swatches.iCount();
820 if ((d_pointer->m_selectedColumn < 0) && (d_pointer->m_selectedRow < 0)) {
821 d_pointer->selectSwatch(0, 0);
825 const int accelerationFactor = 2;
827 columnShift *= accelerationFactor;
828 rowShift *= accelerationFactor;
831 d_pointer->selectSwatch(
832 qBound<QListSizeType>(0,
833 d_pointer->m_selectedColumn + columnShift,
834 d_pointer->m_swatches.iCount() - 1),
835 qBound<QListSizeType>(0,
836 d_pointer->m_selectedRow + rowShift,
837 d_pointer->m_swatches.jCount() - 1));
847void SwatchBook::changeEvent(
QEvent *event)
856 d_pointer->retranslateUi();
866QSize SwatchBookPrivate::colorPatchesSizeWithMargin()
const
868 q_pointer->ensurePolished();
869 const QSize patchSize = patchSizeOuter();
870 const int columnCount =
static_cast<int>(m_swatches.iCount());
871 const int rowCount =
static_cast<int>(m_swatches.jCount());
874 + columnCount * patchSize.
width()
875 + (columnCount - 1) * horizontalPatchSpacing()
879 + rowCount * patchSize.
height()
880 + (rowCount - 1) * verticalPatchSpacing()
882 return QSize(width, height);
AKONADI_CALENDAR_EXPORT KCalendarCore::Event::Ptr event(const Akonadi::Item &item)
void update(Part *part, const QByteArray &data, qint64 dataSize)
The namespace of this library.
float alphaF() const const
float blueF() const const
QColor fromRgbF(float r, float g, float b, float a)
float greenF() const const
bool isValid() const const
QCoreApplication * instance()
QString tr(const char *sourceText, const char *disambiguation, int n)
void addText(const QPointF &point, const QFont &font, const QString &text)
QRectF boundingRect() const const
void translate(const QPointF &offset)
void setCapStyle(Qt::PenCapStyle style)
void setColor(const QColor &color)
void setWidthF(qreal width)
QPointF center() const const
QSizeF size() const const
QSize expandedTo(const QSize &otherSize) const const
QSize grownBy(QMargins margins) const const
qreal height() const const
bool isEmpty() const const
qreal width() const const
int compare(QLatin1StringView s1, const QString &s2, Qt::CaseSensitivity cs)
QList< uint > toUcs4() const const
PM_LayoutHorizontalSpacing
void initFrom(const QWidget *widget)