File indexing completed on 2024-05-12 04:44:31

0001 // SPDX-FileCopyrightText: Lukas Sommer <sommerluk@gmail.com>
0002 // SPDX-License-Identifier: BSD-2-Clause OR MIT
0003 
0004 #ifndef COLORPATCH_H
0005 #define COLORPATCH_H
0006 
0007 #include "abstractdiagram.h"
0008 #include "constpropagatinguniquepointer.h"
0009 #include "importexport.h"
0010 #include <qcolor.h>
0011 #include <qglobal.h>
0012 #include <qsize.h>
0013 class QDragEnterEvent;
0014 class QDropEvent;
0015 class QMouseEvent;
0016 class QResizeEvent;
0017 class QWidget;
0018 
0019 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
0020 #include <qtmetamacros.h>
0021 #else
0022 #include <qobjectdefs.h>
0023 #include <qstring.h>
0024 class QObject;
0025 #endif
0026 
0027 namespace PerceptualColor
0028 {
0029 class ColorPatchPrivate;
0030 
0031 /** @brief A color display widget.
0032  *
0033  * This widget simply displays a color. And it provides drag-and-drop support;
0034  * it emits also @ref colorChanged on drop events if the color has changed.
0035  * Useful for showing a given color. The instantiation and usage is simple.
0036  * Example:
0037  * @snippet testcolorpatch.cpp ColorPatch Create widget
0038  *
0039  * @image html ColorPatch.png "ColorPatch" width=50
0040  *
0041  * This widget is also able to display transparency (the pattern will be
0042  * mirrored on right-to-left layouts):
0043  *
0044  * @image html ColorPatchSemiTransparent.png "ColorPatch with 50% transparency" width=50
0045  *
0046  * There is also a simple representation
0047  * for <tt>QColor::isValid() == false</tt>:
0048  *
0049  * @image html ColorPatchInvalid.png "ColorPatch with invalid color" width=50
0050  *
0051  * The default minimum size of this widget is similar to a
0052  * <tt>QToolButton</tt>. Depending on your use case, you might
0053  * set a bigger minimum size:
0054  * @snippet testcolorpatch.cpp ColorPatch Bigger minimum size
0055  *
0056  * This class’s API is similar to KColorPatch’s API.
0057  *
0058  * @internal
0059  *
0060  * @note A similar functionality is available as KColorPatch, but this is
0061  * part of KDELibs4Support which is available in KF5 but should not be used
0062  * for new code, but only for legacy code. Also, depending on KDELibs4Support
0063  * would pull-in another dependency. Furthermore, KColorPatch has support for
0064  * drag-and-drop, which is not desirable for our use case. Therefore, with
0065  * @ref ColorPatch there is a lightweight alternative (that, by the way,
0066  * implements the full  API of KColorPatch).
0067  *
0068  * @note This class intentionally does not reimplement the paint event,
0069  * but uses a child QLabel to display the color. QLabel integrates by
0070  * default nicely with QStyle: Even round frames that are cutting slightly
0071  * the pixmap (like in the Breeze style), are possible. So we rely entirely
0072  * on QLabel for the actual display, and only implement @ref sizeHint() and
0073  * @ref minimumSizeHint() ourselves. */
0074 class PERCEPTUALCOLOR_IMPORTEXPORT ColorPatch : public AbstractDiagram
0075 {
0076     Q_OBJECT
0077 
0078     /** @brief The color that is displayed
0079      *
0080      * Default value is an invalid color.
0081      *
0082      * - If the color is invalid, nothing is displayed. The frame is empty:
0083      *   Only the default widget background is visible within the frame.
0084      * - If the color is valid, the widget frame is filled with this color.
0085      *   If this color is not fully opaque, the background behind the color
0086      *   will be a special background pattern (and <em>not</em> the default
0087      *   widget background).
0088      *
0089      * @note No color management is applied. The color is used as-is to
0090      * paint on the canvas provided by the operation system.
0091      *
0092      * @sa @ref color() const
0093      * @sa @ref setColor()
0094      * @sa @ref colorChanged() */
0095     Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
0096 
0097 public:
0098     Q_INVOKABLE explicit ColorPatch(QWidget *parent = nullptr);
0099     virtual ~ColorPatch() noexcept override;
0100     /** @brief Getter for property @ref color
0101      *  @returns the property @ref color */
0102     [[nodiscard]] QColor color() const;
0103     [[nodiscard]] virtual QSize minimumSizeHint() const override;
0104     [[nodiscard]] virtual QSize sizeHint() const override;
0105 
0106 public Q_SLOTS:
0107     void setColor(const QColor &newColor);
0108 
0109 Q_SIGNALS:
0110     /** @brief Notify signal for property @ref color.
0111      *
0112      * @param color the new color */
0113     void colorChanged(const QColor &color);
0114 
0115 protected:
0116     virtual void dragEnterEvent(QDragEnterEvent *event) override;
0117     virtual void dropEvent(QDropEvent *event) override;
0118     virtual void mouseMoveEvent(QMouseEvent *event) override;
0119     virtual void mousePressEvent(QMouseEvent *event) override;
0120     virtual void resizeEvent(QResizeEvent *event) override;
0121 
0122 private:
0123     Q_DISABLE_COPY(ColorPatch)
0124 
0125     /** @internal
0126      * @brief Declare the private implementation as friend class.
0127      *
0128      * This allows the private class to access the protected members and
0129      * functions of instances of <em>this</em> class. */
0130     friend class ColorPatchPrivate;
0131     /** @brief Pointer to implementation (pimpl) */
0132     ConstPropagatingUniquePointer<ColorPatchPrivate> d_pointer;
0133 
0134     /** @internal @brief Only for unit tests. */
0135     friend class TestColorPatch;
0136 };
0137 
0138 } // namespace PerceptualColor
0139 
0140 #endif // COLORPATCH_H