Commit 3958d25d authored by Carl Schwan's avatar Carl Schwan 🚴
Browse files

Use xdg-portal to implement color picker

parent a8828230
......@@ -28,7 +28,7 @@ ecm_setup_version(${PROJECT_VERSION}
)
################# Find dependencies #################
find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS Core Gui Qml QuickControls2 Svg Sql)
find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS Core Gui Qml QuickControls2 Svg Sql DBus)
find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS Kirigami2 I18n CoreAddons Declarative)
################# build and install #################
......
......@@ -6,6 +6,7 @@ add_executable(kontrast
target_link_libraries(kontrast
Qt5::Core
Qt5::DBus
Qt5::Gui
Qt5::Qml
Qt5::Quick
......
......@@ -10,7 +10,6 @@ import QtQuick.Controls 2.14 as QQC2
import QtQuick.Window 2.14
import QtQuick.Layouts 1.14
import org.kde.kontrast.private 1.0
import QtQuick.Dialogs 1.0
Kirigami.ScrollablePage {
id: mainPage
......@@ -20,20 +19,21 @@ Kirigami.ScrollablePage {
background: Rectangle {
color: Kontrast.backgroundColor
}
ColumnLayout {
ColorDialog {
id: colorDialog
property var target: "textColor";
title: i18n("Please choose a color")
onAccepted: {
if (target === "textColor") {
Kontrast.textColor = colorDialog.color;
} else {
Kontrast.backgroundColor = colorDialog.color;
}
Connections {
id: grabbedColorConnection
property string type: "text"
target: Kontrast
function onGrabbedColorChanged() {
if (type === "text") {
Kontrast.textColor = Kontrast.grabbedColor;
} else {
Kontrast.backgroundColor = Kontrast.grabbedColor;
}
}
}
ColumnLayout {
Text {
font.pointSize: mainPage.isMobile ? 20 : 40
font.bold: true
......@@ -89,9 +89,8 @@ Kirigami.ScrollablePage {
verticalCenter: parent.verticalCenter
}
onClicked: {
colorDialog.color = Kontrast.textColor
colorDialog.target = "textColor";
colorDialog.visible = true;
grabbedColorConnection.type = "text";
Kontrast.grabColor();
}
}
}
......@@ -170,9 +169,8 @@ Kirigami.ScrollablePage {
verticalCenter: parent.verticalCenter
}
onClicked: {
colorDialog.color = Kontrast.backgroundColor;
colorDialog.target = "backgroundColor";
colorDialog.visible = true;
grabbedColorConnection.type = "background";
Kontrast.grabColor();
}
}
}
......
/*
* SPDX-FileCopyrightText: (C) 2020 Carl Schwan <carl@carlschwan.eu>
*
*
* SPDX-LicenseRef: GPL-3.0-or-later
*/
#include "kontrast.h"
#include <QtMath>
#include <QRandomGenerator>
#include <QRandomGenerator>
#include <QDBusMessage>
#include <QDBusMetaType>
#include <QDBusPendingCall>
#include <QDBusPendingCallWatcher>
#include <QDBusPendingReply>
#include <QDBusObjectPath>
#include <QDBusConnection>
#include <QDebug>
QDBusArgument &operator <<(QDBusArgument &arg, const Kontrast::ColorRGB &color)
{
arg.beginStructure();
arg << color.red << color.green << color.blue;
arg.endStructure();
return arg;
}
const QDBusArgument &operator >>(const QDBusArgument &arg, Kontrast::ColorRGB &color)
{
double red, green, blue;
arg.beginStructure();
arg >> red >> green >> blue;
color.red = red;
color.green = green;
color.blue = blue;
arg.endStructure();
return arg;
}
Kontrast::Kontrast(KAboutData about, QObject *parent)
: QObject(parent)
, m_about(about)
{
setObjectName(QStringLiteral("Kontrast"));
qDBusRegisterMetaType<ColorRGB>();
}
QColor Kontrast::textColor() const
......@@ -26,7 +59,7 @@ void Kontrast::setTextColor(const QColor textColor)
if (textColor == m_textColor) {
return;
}
m_textColor = textColor;
Q_EMIT textColorChanged();
Q_EMIT contrastChanged();
......@@ -87,7 +120,7 @@ void Kontrast::setBackgroundColor(const QColor backgroundColor)
if (backgroundColor == m_backgroundColor) {
return;
}
m_backgroundColor = backgroundColor;
Q_EMIT backgroundColorChanged();
Q_EMIT contrastChanged();
......@@ -144,11 +177,11 @@ qreal luminosity(const QColor color)
const qreal red = color.redF();
const qreal green = color.greenF();
const qreal blue = color.blueF();
const qreal redLum = (red <= 0.03928) ? red / 12.92 : qPow(((red + 0.055) / 1.055), 2.4);
const qreal greenLum = (green <= 0.03928) ? green / 12.92 : qPow(((green + 0.055) / 1.055), 2.4);
const qreal blueLum = (blue <= 0.03928) ? blue / 12.92 : qPow(((blue + 0.055) / 1.055), 2.4);
return 0.2126 * redLum + 0.7152 * greenLum + 0.0722 * blueLum;
}
......@@ -156,11 +189,11 @@ qreal Kontrast::contrast() const
{
const qreal lum1 = luminosity(m_textColor);
const qreal lum2 = luminosity(m_backgroundColor);
if (lum1 > lum2) {
return (lum1 + 0.05) / (lum2 + 0.05);
}
return (lum2 + 0.05) / (lum1 + 0.05);
}
......@@ -190,7 +223,7 @@ QColor Kontrast::displayTextColor() const
if (contrast() > 3.0) {
return m_textColor;
}
if (luminosity(m_backgroundColor) > 0.5) {
return Qt::black;
}
......@@ -206,3 +239,46 @@ QColor Kontrast::pixelAt(const QImage &image, int x, int y) const
{
return image.pixelColor(x, y);
}
void Kontrast::grabColor()
{
QDBusMessage message = QDBusMessage::createMethodCall(QLatin1String("org.freedesktop.portal.Desktop"),
QLatin1String("/org/freedesktop/portal/desktop"),
QLatin1String("org.freedesktop.portal.Screenshot"),
QLatin1String("PickColor"));
message << QLatin1String("x11:") << QVariantMap{};
QDBusPendingCall pendingCall = QDBusConnection::sessionBus().asyncCall(message);
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall);
connect(watcher, &QDBusPendingCallWatcher::finished, [this] (QDBusPendingCallWatcher *watcher) {
QDBusPendingReply<QDBusObjectPath> reply = *watcher;
if (reply.isError()) {
qWarning() << "Couldn't get reply";
qWarning() << "Error: " << reply.error().message();
} else {
QDBusConnection::sessionBus().connect(QString(),
reply.value().path(),
QLatin1String("org.freedesktop.portal.Request"),
QLatin1String("Response"),
this,
SLOT(gotColorResponse(uint, QVariantMap)));
}
});
}
QColor Kontrast::grabbedColor() const
{
return m_grabbedColor;
}
void Kontrast::gotColorResponse(uint response, const QVariantMap& results)
{
if (!response) {
if (results.contains(QLatin1String("color"))) {
auto color = qdbus_cast<ColorRGB>(results.value(QLatin1String("color")));
m_grabbedColor = QColor(color.red * 256, color.green * 256, color.blue * 256);
emit grabbedColorChanged();
}
} else {
qWarning() << "Failed to take screenshot";
}
}
......@@ -40,9 +40,17 @@ class Kontrast : public QObject
Q_PROPERTY(KAboutData about READ about);
Q_PROPERTY(QColor grabbedColor READ grabbedColor NOTIFY grabbedColorChanged);
public:
Kontrast(KAboutData about, QObject *parent = nullptr);
virtual ~Kontrast() override = default;
struct ColorRGB {
double red;
double green;
double blue;
};
QColor textColor() const;
void setTextColor(const QColor textColor);
......@@ -73,19 +81,28 @@ public:
QColor displayTextColor() const;
KAboutData about() const;
QColor grabbedColor() const;
Q_INVOKABLE void random();
Q_INVOKABLE void reverse();
Q_INVOKABLE void grabColor();
Q_INVOKABLE QColor pixelAt(const QImage &image, int x, int y) const;
private Q_SLOTS:
void gotColorResponse(uint response, const QVariantMap &results);
Q_SIGNALS:
void textColorChanged();
void backgroundColorChanged();
void contrastChanged();
void grabbedColorChanged();
private:
QColor m_textColor;
QColor m_backgroundColor;
QColor m_grabbedColor;
KAboutData m_about;
};
Q_DECLARE_METATYPE(Kontrast::ColorRGB)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment