[frameworks/kwidgetsaddons] src: KColorButton, KColorCombo: add contextmenu for Copy & Paste of color
Friedrich W. H. Kossebau <[email protected]>
| Newsgroups | gmane.comp.kde.cvs |
|---|---|
| Message-ID | <[email protected]> |
Git commit 00866bc50fa32c280db443fc14e5294dcabfdeb4 by Friedrich W. H. Kossebau.
Committed on 24/07/2026 at 20:47.
Pushed by kossebau into branch 'master'.
KColorButton, KColorCombo: add contextmenu for Copy & Paste of color
For KColorCombo also adds keyboard shortcuts on the widget itself.
Implementation is shared from both classes by introducing a new internal
class KAbstractColorEditPrivate, which provides the common features.
M +2 -0 src/CMakeLists.txt
A +108 -0 src/kabstractcoloredit.cpp [License: LGPL(v2.0+)]
A +40 -0 src/kabstractcoloredit_p.h [License: LGPL(v2.0+)]
M +40 -16 src/kcolorbutton.cpp
M +3 -0 src/kcolorbutton.h
M +39 -3 src/kcolorcombo.cpp
M +1 -0 src/kcolorcombo.h
https://invent.kde.org/frameworks/kwidgetsaddons/-/commit/00866bc50fa32c280db443fc14e5294dcabfdeb4
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index b8ebf8b7..c1936a29 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -17,6 +17,8 @@ target_sources(KF6WidgetsAddons PRIVATE
fonthelpers_p.h
highcontrasthelper.cpp
highcontrasthelper_p.h
+ kabstractcoloredit.cpp
+ kabstractcoloredit_p.h
kacceleratormanager.cpp
kacceleratormanager.h
kacceleratormanager_p.h
diff --git a/src/kabstractcoloredit.cpp b/src/kabstractcoloredit.cpp
new file mode 100644
index 00000000..badea602
--- /dev/null
+++ b/src/kabstractcoloredit.cpp
@@ -0,0 +1,108 @@
+/*
+ This file is part of the KDE libraries
+ SPDX-FileCopyrightText: 2026 Friedrich W. H. Kossebau <[email protected]>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#include "kabstractcoloredit_p.h"
+
+#include "kcolormimedata_p.h"
+
+#include <QAction>
+#include <QApplication>
+#include <QClipboard>
+#include <QGlobalStatic>
+#include <QIcon>
+#include <QMenu>
+#include <QMimeData>
+
+class KColorClipboardWatcher : public QObject
+{
+ Q_OBJECT
+
+public:
+ KColorClipboardWatcher();
+
+ bool isColorOnClipboardAvailable() const;
+
+Q_SIGNALS:
+ void colorOnClipboardAvailableChanged(bool available);
+
+private:
+ void updateState();
+
+private:
+ bool m_colorOnClipboardAvailable = false;
+};
+
+KColorClipboardWatcher::KColorClipboardWatcher()
+{
+ connect(QApplication::clipboard(), &QClipboard::dataChanged, this, &KColorClipboardWatcher::updateState);
+ const QMimeData *const mimeData = QApplication::clipboard()->mimeData(QClipboard::Clipboard);
+ m_colorOnClipboardAvailable = KColorMimeData::canDecode(mimeData);
+}
+
+bool KColorClipboardWatcher::isColorOnClipboardAvailable() const
+{
+ return m_colorOnClipboardAvailable;
+}
+
+void KColorClipboardWatcher::updateState()
+{
+ const QMimeData *const mimeData = QApplication::clipboard()->mimeData(QClipboard::Clipboard);
+ const bool colorOnClipboardAvailable = KColorMimeData::canDecode(mimeData);
+ if (colorOnClipboardAvailable == m_colorOnClipboardAvailable) {
+ return;
+ }
+ m_colorOnClipboardAvailable = colorOnClipboardAvailable;
+ Q_EMIT colorOnClipboardAvailableChanged(m_colorOnClipboardAvailable);
+}
+
+Q_GLOBAL_STATIC(KColorClipboardWatcher, globalClipboardWatcher)
+
+KAbstractColorEditPrivate::KAbstractColorEditPrivate(QWidget *qq)
+ : q_ptr(qq)
+{
+ Q_Q(QWidget);
+
+ copyAction =
+ new QAction(QIcon::fromTheme(QIcon::ThemeIcon::EditCopy), QCoreApplication::translate("KAbstractColorEdit", "Copy Color", "@action:inmenu"), q);
+ copyAction->setShortcut(QKeySequence::Copy);
+ copyAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+ QObject::connect(copyAction, &QAction::triggered, q, [this]() {
+ auto *const mimeData = new QMimeData;
+ KColorMimeData::populateMimeData(mimeData, color());
+ QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard);
+ });
+ q->addAction(copyAction); // register shortcuts
+
+ pasteAction =
+ new QAction(QIcon::fromTheme(QIcon::ThemeIcon::EditPaste), QCoreApplication::translate("KAbstractColorEdit", "Paste Color", "@action:inmenu"), q);
+ pasteAction->setShortcut(QKeySequence::Paste);
+ pasteAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+ QObject::connect(pasteAction, &QAction::triggered, q, [this]() {
+ const QColor color = KColorMimeData::fromMimeData(QApplication::clipboard()->mimeData(QClipboard::Clipboard));
+ if (color.isValid()) {
+ setColor(color);
+ }
+ });
+ pasteAction->setEnabled(globalClipboardWatcher()->isColorOnClipboardAvailable());
+ QObject::connect(globalClipboardWatcher(), &KColorClipboardWatcher::colorOnClipboardAvailableChanged, pasteAction, &QAction::setEnabled);
+ q->addAction(pasteAction); // register shortcuts
+}
+
+void KAbstractColorEditPrivate::showContextMenu(QPoint globalPos)
+{
+ Q_Q(QWidget);
+
+ auto menu = new QMenu(q);
+ menu->setAttribute(Qt::WA_DeleteOnClose);
+
+ menu->addAction(copyAction);
+ menu->addAction(pasteAction);
+
+ menu->popup(globalPos);
+}
+
+#include "kabstractcoloredit.moc"
diff --git a/src/kabstractcoloredit_p.h b/src/kabstractcoloredit_p.h
new file mode 100644
index 00000000..71223b0d
--- /dev/null
+++ b/src/kabstractcoloredit_p.h
@@ -0,0 +1,40 @@
+/*
+ This file is part of the KDE libraries
+ SPDX-FileCopyrightText: 2026 Friedrich W. H. Kossebau <[email protected]>
+
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#ifndef KABSTRACTCOLOREDIT_P_H
+#define KABSTRACTCOLOREDIT_P_H
+
+#include <QtClassHelperMacros>
+
+class QWidget;
+class QAction;
+class QColor;
+class QPoint;
+
+class KAbstractColorEditPrivate
+{
+ Q_DECLARE_PUBLIC(QWidget)
+
+public:
+ explicit KAbstractColorEditPrivate(QWidget *qq);
+ virtual ~KAbstractColorEditPrivate() = default;
+
+public: // API to implement
+ virtual QColor color() const = 0;
+ virtual void setColor(const QColor &color) = 0;
+
+public:
+ void showContextMenu(QPoint globalPos);
+
+public:
+ QWidget *const q_ptr;
+
+ QAction *copyAction;
+ QAction *pasteAction;
+};
+
+#endif
diff --git a/src/kcolorbutton.cpp b/src/kcolorbutton.cpp
index 5be3142f..56ad0b5e 100644
--- a/src/kcolorbutton.cpp
+++ b/src/kcolorbutton.cpp
@@ -8,10 +8,10 @@
#include "kcolorbutton.h"
+#include "kabstractcoloredit_p.h"
#include "kcolormimedata_p.h"
#include <QApplication>
-#include <QClipboard>
#include <QColorDialog>
#include <QDrag>
#include <QMimeData>
@@ -22,15 +22,19 @@
#include <QStyleOptionButton>
#include <qdrawutil.h>
-class KColorButtonPrivate
+class KColorButtonPrivate : public KAbstractColorEditPrivate
{
+ Q_DECLARE_PUBLIC(KColorButton)
+
public:
KColorButtonPrivate(KColorButton *qq);
+ QColor color() const override;
+ void setColor(const QColor &color) override;
+
void chooseColor();
void colorChosen();
- KColorButton *q;
QColor m_defaultColor;
bool m_bdefaultColor : 1;
bool m_alphaChannel : 1;
@@ -44,8 +48,10 @@ public:
};
KColorButtonPrivate::KColorButtonPrivate(KColorButton *qq)
- : q(qq)
+ : KAbstractColorEditPrivate(qq)
{
+ Q_Q(KColorButton);
+
m_bdefaultColor = false;
m_alphaChannel = false;
q->setAcceptDrops(true);
@@ -55,6 +61,20 @@ KColorButtonPrivate::KColorButtonPrivate(KColorButton *qq)
});
}
+QColor KColorButtonPrivate::color() const
+{
+ Q_Q(const KColorButton);
+
+ return q->color();
+}
+
+void KColorButtonPrivate::setColor(const QColor &color)
+{
+ Q_Q(KColorButton);
+
+ q->setColor(color);
+}
+
KColorButton::KColorButton(QWidget *parent)
: QPushButton(parent)
, d(new KColorButtonPrivate(this))
@@ -112,6 +132,8 @@ void KColorButton::setDefaultColor(const QColor &c)
void KColorButtonPrivate::initStyleOption(QStyleOptionButton *opt) const
{
+ Q_Q(const KColorButton);
+
opt->initFrom(q);
opt->state |= q->isDown() ? QStyle::State_Sunken : QStyle::State_Raised;
opt->features = QStyleOptionButton::None;
@@ -202,21 +224,12 @@ void KColorButton::dropEvent(QDropEvent *event)
}
}
+#if KWIDGETSADDONS_BUILD_DEPRECATED_SINCE(6, 29)
void KColorButton::keyPressEvent(QKeyEvent *e)
{
- int key = e->key() | e->modifiers();
-
- if (QKeySequence::keyBindings(QKeySequence::Copy).contains(key)) {
- QMimeData *mime = new QMimeData;
- KColorMimeData::populateMimeData(mime, color());
- QApplication::clipboard()->setMimeData(mime, QClipboard::Clipboard);
- } else if (QKeySequence::keyBindings(QKeySequence::Paste).contains(key)) {
- QColor color = KColorMimeData::fromMimeData(QApplication::clipboard()->mimeData(QClipboard::Clipboard));
- setColor(color);
- } else {
- QPushButton::keyPressEvent(e);
- }
+ QPushButton::keyPressEvent(e);
}
+#endif
void KColorButton::mousePressEvent(QMouseEvent *e)
{
@@ -232,8 +245,17 @@ void KColorButton::mouseMoveEvent(QMouseEvent *e)
}
}
+void KColorButton::contextMenuEvent(QContextMenuEvent *ev)
+{
+ ev->accept();
+
+ d->showContextMenu(ev->globalPos());
+}
+
void KColorButtonPrivate::chooseColor()
{
+ Q_Q(KColorButton);
+
QColorDialog *dialog = dialogPtr.data();
if (dialog) {
dialog->show();
@@ -255,6 +277,8 @@ void KColorButtonPrivate::chooseColor()
void KColorButtonPrivate::colorChosen()
{
+ Q_Q(KColorButton);
+
QColorDialog *dialog = dialogPtr.data();
if (!dialog) {
return;
diff --git a/src/kcolorbutton.h b/src/kcolorbutton.h
index 0ef7bb03..9f52cb53 100644
--- a/src/kcolorbutton.h
+++ b/src/kcolorbutton.h
@@ -113,7 +113,10 @@ protected:
void dropEvent(QDropEvent *) override;
void mousePressEvent(QMouseEvent *e) override;
void mouseMoveEvent(QMouseEvent *e) override;
+#if KWIDGETSADDONS_BUILD_DEPRECATED_SINCE(6, 29)
void keyPressEvent(QKeyEvent *e) override;
+#endif
+ void contextMenuEvent(QContextMenuEvent *) override;
private:
std::unique_ptr<class KColorButtonPrivate> const d;
diff --git a/src/kcolorcombo.cpp b/src/kcolorcombo.cpp
index 39012597..af457c60 100644
--- a/src/kcolorcombo.cpp
+++ b/src/kcolorcombo.cpp
@@ -9,9 +9,12 @@
#include "kcolorcombo.h"
+#include "kabstractcoloredit_p.h"
+
#include <QAbstractItemDelegate>
#include <QApplication>
#include <QColorDialog>
+#include <QContextMenuEvent>
#include <QStylePainter>
class KColorComboDelegate : public QAbstractItemDelegate
@@ -159,11 +162,16 @@ static inline QColor standardColor(int i)
return QColor(entry[0], entry[1], entry[2]);
}
-class KColorComboPrivate
+class KColorComboPrivate : public KAbstractColorEditPrivate
{
+ Q_DECLARE_PUBLIC(KColorCombo)
+
public:
KColorComboPrivate(KColorCombo *qq);
+ QColor color() const override;
+ void setColor(const QColor &color) override;
+
void addColors();
void setCustomColor(const QColor &color, bool lookupInPresets = true);
@@ -171,20 +179,35 @@ public:
void slotActivated(int index);
void slotHighlighted(int index);
- KColorCombo *q;
QList<QColor> colorList;
QColor customColor;
QColor internalcolor;
};
KColorComboPrivate::KColorComboPrivate(KColorCombo *qq)
- : q(qq)
+ : KAbstractColorEditPrivate(qq)
, customColor(Qt::white)
{
}
+QColor KColorComboPrivate::color() const
+{
+ Q_Q(const KColorCombo);
+
+ return q->color();
+}
+
+void KColorComboPrivate::setColor(const QColor &color)
+{
+ Q_Q(KColorCombo);
+
+ q->setColor(color);
+}
+
void KColorComboPrivate::setCustomColor(const QColor &color, bool lookupInPresets)
{
+ Q_Q(KColorCombo);
+
if (lookupInPresets) {
if (colorList.isEmpty()) {
for (int i = 0; i < STANDARD_PALETTE_SIZE; ++i) {
@@ -294,6 +317,13 @@ void KColorCombo::paintEvent(QPaintEvent *event)
painter.drawRoundedRect(frame.adjusted(1, 1, -1, -1), 2, 2);
}
+void KColorCombo::contextMenuEvent(QContextMenuEvent *ev)
+{
+ ev->accept();
+
+ d->showContextMenu(ev->globalPos());
+}
+
void KColorCombo::showEmptyList()
{
clear();
@@ -301,6 +331,8 @@ void KColorCombo::showEmptyList()
void KColorComboPrivate::slotActivated(int index)
{
+ Q_Q(KColorCombo);
+
if (index == 0) {
QColor c = QColorDialog::getColor(customColor, q);
if (c.isValid()) {
@@ -318,6 +350,8 @@ void KColorComboPrivate::slotActivated(int index)
void KColorComboPrivate::slotHighlighted(int index)
{
+ Q_Q(KColorCombo);
+
if (index == 0) {
internalcolor = customColor;
} else if (colorList.isEmpty()) {
@@ -331,6 +365,8 @@ void KColorComboPrivate::slotHighlighted(int index)
void KColorComboPrivate::addColors()
{
+ Q_Q(KColorCombo);
+
q->addItem(KColorCombo::tr("Custom…", "@item:inlistbox Custom color"));
if (colorList.isEmpty()) {
diff --git a/src/kcolorcombo.h b/src/kcolorcombo.h
index 505c3b7f..bf6f7dc6 100644
--- a/src/kcolorcombo.h
+++ b/src/kcolorcombo.h
@@ -100,6 +100,7 @@ Q_SIGNALS:
protected:
void paintEvent(QPaintEvent *event) override;
+ void contextMenuEvent(QContextMenuEvent *) override;
private:
friend class KColorComboPrivate;