File indexing completed on 2024-06-09 04:20:41

0001 /*
0002  *  SPDX-FileCopyrightText: 2012 Daniel Nicoletti <dantti12@gmail.com>
0003  *  SPDX-FileCopyrightText: 2015 Boudewijn Rempt <boud@valdyas.org>
0004  *
0005  *  SPDX-License-Identifier: GPL-2.0-or-later
0006  */
0007 
0008 #include "KisColord.h"
0009 
0010 #include <klocalizedstring.h>
0011 #include <kis_debug.h>
0012 
0013 
0014 #include "CdInterface.h"
0015 #include "CdProfileInterface.h"
0016 #include "CdDeviceInterface.h"
0017 
0018 
0019 struct Profile {
0020     QString kind;
0021     QString filename;
0022     QString title;
0023     qulonglong created;
0024     QString colorspace;
0025 };
0026 
0027 struct Device {
0028 
0029     ~Device() {
0030         qDeleteAll(profiles);
0031         profiles.clear();
0032     }
0033 
0034     QString id;
0035     QString kind;
0036     QString model;
0037     QString vendor;
0038     QString colorspace;
0039 
0040     QList<Profile*> profiles;
0041 
0042 };
0043 
0044 KisColord::KisColord(QObject *parent)
0045     : QObject(parent)
0046 {
0047     //dbgKrita << "Creating KisColorD";
0048 
0049     m_cdInterface = new CdInterface(QLatin1String("org.freedesktop.ColorManager"),
0050                                     QLatin1String("/org/freedesktop/ColorManager"),
0051                                     QDBusConnection::systemBus(),
0052                                     this);
0053 
0054     // listen to colord for device events
0055     connect(m_cdInterface, SIGNAL(DeviceAdded(QDBusObjectPath)),
0056             this, SLOT(deviceAdded(QDBusObjectPath)));
0057     connect(m_cdInterface, SIGNAL(DeviceRemoved(QDBusObjectPath)),
0058             this, SLOT(deviceRemoved(QDBusObjectPath)));
0059     connect(m_cdInterface, SIGNAL(DeviceChanged(QDBusObjectPath)),
0060             this, SLOT(deviceChanged(QDBusObjectPath)));
0061 
0062     // Ask for devices
0063     QDBusPendingReply<QList<QDBusObjectPath> > async = m_cdInterface->GetDevices();
0064     QDBusPendingCallWatcher *displayWatcher = new QDBusPendingCallWatcher(async, this);
0065     connect(displayWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
0066             this, SLOT(gotDevices(QDBusPendingCallWatcher*)));
0067 
0068 
0069     // Make sure we know is colord is running
0070     QDBusServiceWatcher *watcher = new QDBusServiceWatcher("org.freedesktop.ColorManager",
0071                                                            QDBusConnection::systemBus(),
0072                                                            QDBusServiceWatcher::WatchForOwnerChange,
0073                                                            this);
0074 
0075     connect(watcher, SIGNAL(serviceOwnerChanged(QString,QString,QString)),
0076             this, SLOT(serviceOwnerChanged(QString,QString,QString)));
0077 }
0078 
0079 KisColord::~KisColord()
0080 {
0081     qDeleteAll(m_devices);
0082     m_devices.clear();
0083 }
0084 
0085 QStringList KisColord::devices(const QString &type) const
0086 {
0087     QStringList res;
0088     Q_FOREACH (Device *dev, m_devices.values()) {
0089         if (type == dev->kind) {
0090             res << dev->id;
0091         }
0092     }
0093     return res;
0094 }
0095 
0096 const QString KisColord::deviceName(const QString &id) const
0097 {
0098     QString res;
0099     Q_FOREACH (Device *dev, m_devices.values()) {
0100         if (dev->id == id) {
0101             res = dev->model + ", " + dev->vendor;
0102         }
0103     }
0104     return res;
0105 }
0106 
0107 QByteArray KisColord::deviceProfile(const QString &id, int p)
0108 {
0109     QByteArray ba;
0110     Device *dev = 0;
0111     Profile *profile = 0;
0112     Q_FOREACH (Device *d, m_devices.values()) {
0113         if (d->id == id) {
0114             dev = d;
0115             break;
0116         }
0117     }
0118 
0119     if (dev) {
0120         if (dev->profiles.size() > 0) {
0121             if (dev->profiles.size() < p) {
0122                 profile = dev->profiles[p];
0123             }
0124             else {
0125                 profile = dev->profiles[0];
0126             }
0127         }
0128 
0129         if (profile) {
0130             //dbgKrita << "profile filename" << profile->filename;
0131             QFile f(profile->filename);
0132             if (f.open(QFile::ReadOnly)) {
0133                 ba = f.readAll();
0134             }
0135             else {
0136                 dbgKrita << "Could not load profile" << profile->title << profile->filename;
0137             }
0138         }
0139     }
0140 
0141     return ba;
0142 }
0143 
0144 
0145 
0146 void KisColord::serviceOwnerChanged(const QString &serviceName, const QString &oldOwner, const QString &newOwner)
0147 {
0148     Q_UNUSED(serviceName);
0149     if (newOwner.isEmpty() || oldOwner != newOwner) {
0150         // colord has quit or restarted
0151         qDeleteAll(m_devices);
0152         m_devices.clear();
0153     }
0154     emit changed();
0155 }
0156 
0157 void KisColord::gotDevices(QDBusPendingCallWatcher *call)
0158 {
0159     //dbgKrita << "Got devices!!!";
0160 
0161     QDBusPendingReply<QList<QDBusObjectPath> > reply = *call;
0162     if (reply.isError()) {
0163         dbgKrita << "Unexpected message" << reply.error().message();
0164     } else {
0165         QList<QDBusObjectPath> devices = reply.argumentAt<0>();
0166         Q_FOREACH (const QDBusObjectPath &device, devices) {
0167             deviceAdded(device, false);
0168         }
0169         emit changed();
0170     }
0171     //dbgKrita << "gotDevices" << m_devices.count();
0172     call->deleteLater();
0173 }
0174 
0175 void KisColord::deviceChanged(const QDBusObjectPath &objectPath)
0176 {
0177     CdDeviceInterface device(QLatin1String("org.freedesktop.ColorManager"),
0178                              objectPath.path(),
0179                              QDBusConnection::systemBus());
0180     if (!device.isValid()) {
0181         return;
0182     }
0183 
0184     if (!m_devices.contains(objectPath)) {
0185         //dbgKrita << "deviceChanged for an unknown device" << objectPath.path();
0186         deviceAdded(objectPath, false);
0187         return;
0188     }
0189 
0190     QList<QDBusObjectPath> profiles = device.profiles();
0191 
0192     Device *dev = m_devices[objectPath];
0193     qDeleteAll(dev->profiles);
0194     dev->profiles.clear();
0195 
0196     addProfilesToDevice(dev, profiles);
0197 
0198     //dbgKrita << "deviceChanged" << dev->id << "with" << profiles.size() << "profiles";
0199 
0200     emit changed(dev->id);
0201 }
0202 
0203 void KisColord::deviceAdded(const QDBusObjectPath &objectPath, bool emitChanged)
0204 {
0205     if (m_devices.contains(objectPath)) {
0206         //dbgKrita << "Device is already on the list" << objectPath.path();
0207         return;
0208     }
0209 
0210     CdDeviceInterface device(QLatin1String("org.freedesktop.ColorManager"),
0211                              objectPath.path(),
0212                              QDBusConnection::systemBus());
0213     if (!device.isValid()) {
0214         dbgKrita << "Got an invalid device" << objectPath.path();
0215         return;
0216     }
0217 
0218     Device *dev = new Device;
0219 
0220     dev->id = device.deviceId();
0221     dev->kind = device.kind();
0222     dev->model = device.model();
0223     dev->vendor = device.vendor();
0224     dev->colorspace = device.colorspace();
0225 
0226     m_devices[objectPath] = dev;
0227 
0228     QList<QDBusObjectPath> profiles = device.profiles();
0229     addProfilesToDevice(dev, profiles);
0230 
0231 //    dbgKrita << "deviceAdded" << dev->id
0232 //             << dev->kind
0233 //             << dev->model
0234 //             << dev->vendor
0235 //             << "with" << profiles.size() << "profiles";
0236 
0237     if (emitChanged) {
0238         emit changed();
0239     }
0240 }
0241 
0242 void KisColord::deviceRemoved(const QDBusObjectPath &objectPath)
0243 {
0244     if (m_devices.contains(objectPath)) {
0245         delete m_devices.take(objectPath);
0246     }
0247     emit changed();
0248 }
0249 
0250 void KisColord::addProfilesToDevice(Device *dev, QList<QDBusObjectPath> profiles) const
0251 {
0252 
0253     Q_FOREACH (const QDBusObjectPath &profileObjectPath, profiles) {
0254 
0255         CdProfileInterface profile(QLatin1String("org.freedesktop.ColorManager"),
0256                                    profileObjectPath.path(),
0257                                    QDBusConnection::systemBus());
0258         if (!profile.isValid()) {
0259             return;
0260         }
0261 
0262 
0263         Profile *p = new Profile;
0264 
0265         p->kind = profile.kind();
0266         p->filename = profile.filename();
0267         p->title = profile.title();
0268         p->created = profile.created();
0269         p->colorspace = profile.colorspace();
0270 
0271         dev->profiles << p;
0272     }
0273 }
0274