File indexing completed on 2024-04-28 15:34:03
0001 /* 0002 SPDX-FileCopyrightText: 2013 Ivan Cukic <ivan.cukic(at)kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.1-or-later 0005 */ 0006 0007 #include "devices.h" 0008 #include "devices_p.h" 0009 0010 #include <solid/device.h> 0011 #include <solid/devicenotifier.h> 0012 #include <solid/genericinterface.h> 0013 0014 namespace Solid 0015 { 0016 // Maps queries to the handler objects 0017 QHash<QString, QWeakPointer<DevicesQueryPrivate>> DevicesQueryPrivate::handlers; 0018 0019 QSharedPointer<DevicesQueryPrivate> DevicesQueryPrivate::forQuery(const QString &query) 0020 { 0021 if (handlers.contains(query)) { 0022 return handlers[query].toStrongRef(); 0023 } 0024 0025 // Creating a new shared backend instance 0026 QSharedPointer<DevicesQueryPrivate> backend(new DevicesQueryPrivate(query)); 0027 0028 // Storing a weak pointer to the backend 0029 handlers[query] = backend; 0030 0031 // Returns the newly created backend 0032 // TODO: It would be nicer with std::move and STL's smart pointers, 0033 // but RVO should optimize this out. 0034 return backend; 0035 } 0036 0037 DevicesQueryPrivate::DevicesQueryPrivate(const QString &query) 0038 : query(query) 0039 , predicate(Solid::Predicate::fromString(query)) 0040 , notifier(Solid::DeviceNotifier::instance()) 0041 { 0042 connect(notifier, &Solid::DeviceNotifier::deviceAdded, this, &DevicesQueryPrivate::addDevice); 0043 connect(notifier, &Solid::DeviceNotifier::deviceRemoved, this, &DevicesQueryPrivate::removeDevice); 0044 0045 if (!query.isEmpty() && !predicate.isValid()) { 0046 return; 0047 } 0048 0049 const QList<Solid::Device> deviceList = Solid::Device::listFromQuery(predicate); 0050 for (const Solid::Device &device : deviceList) { 0051 matchingDevices << device.udi(); 0052 } 0053 } 0054 0055 DevicesQueryPrivate::~DevicesQueryPrivate() 0056 { 0057 handlers.remove(query); 0058 } 0059 0060 void DevicesQueryPrivate::addDevice(const QString &udi) 0061 { 0062 if (predicate.isValid() && predicate.matches(Solid::Device(udi))) { 0063 matchingDevices << udi; 0064 Q_EMIT deviceAdded(udi); 0065 } 0066 } 0067 0068 void DevicesQueryPrivate::removeDevice(const QString &udi) 0069 { 0070 if (predicate.isValid() && matchingDevices.contains(udi)) { 0071 matchingDevices.removeAll(udi); 0072 Q_EMIT deviceRemoved(udi); 0073 } 0074 } 0075 0076 const QStringList &DevicesQueryPrivate::devices() const 0077 { 0078 return matchingDevices; 0079 } 0080 0081 void Devices::initialize() const 0082 { 0083 if (m_backend) { 0084 return; 0085 } 0086 0087 m_backend = DevicesQueryPrivate::forQuery(m_query); 0088 0089 connect(m_backend.data(), &DevicesQueryPrivate::deviceAdded, this, &Devices::addDevice); 0090 connect(m_backend.data(), &DevicesQueryPrivate::deviceAdded, this, &Devices::addDevice); 0091 connect(m_backend.data(), &DevicesQueryPrivate::deviceRemoved, this, &Devices::removeDevice); 0092 0093 const int matchesCount = m_backend->devices().count(); 0094 0095 if (matchesCount != 0) { 0096 Q_EMIT emptyChanged(false); 0097 Q_EMIT countChanged(matchesCount); 0098 Q_EMIT devicesChanged(m_backend->devices()); 0099 } 0100 } 0101 0102 void Devices::reset() 0103 { 0104 if (!m_backend) { 0105 return; 0106 } 0107 0108 m_backend->disconnect(this); 0109 m_backend.reset(); 0110 0111 Q_EMIT emptyChanged(true); 0112 Q_EMIT countChanged(0); 0113 Q_EMIT devicesChanged(QStringList()); 0114 } 0115 0116 void Devices::addDevice(const QString &udi) 0117 { 0118 if (!m_backend) { 0119 return; 0120 } 0121 0122 const int count = m_backend->devices().count(); 0123 0124 if (count == 1) { 0125 Q_EMIT emptyChanged(false); 0126 } 0127 0128 Q_EMIT countChanged(count); 0129 Q_EMIT devicesChanged(m_backend->devices()); 0130 Q_EMIT deviceAdded(udi); 0131 } 0132 0133 void Devices::removeDevice(const QString &udi) 0134 { 0135 if (!m_backend) { 0136 return; 0137 } 0138 0139 const int count = m_backend->devices().count(); 0140 0141 if (count == 0) { 0142 Q_EMIT emptyChanged(true); 0143 } 0144 0145 Q_EMIT countChanged(count); 0146 Q_EMIT devicesChanged(m_backend->devices()); 0147 Q_EMIT deviceRemoved(udi); 0148 } 0149 0150 Devices::Devices(QObject *parent) 0151 : QObject(parent) 0152 { 0153 } 0154 0155 Devices::~Devices() 0156 { 0157 } 0158 0159 bool Devices::isEmpty() const 0160 { 0161 initialize(); 0162 return count() == 0; 0163 } 0164 0165 int Devices::count() const 0166 { 0167 initialize(); 0168 return devices().count(); 0169 } 0170 0171 QStringList Devices::devices() const 0172 { 0173 initialize(); 0174 return m_backend->devices(); 0175 } 0176 0177 QString Devices::query() const 0178 { 0179 return m_backend->query; 0180 } 0181 0182 void Devices::setQuery(const QString &query) 0183 { 0184 if (m_query == query) { 0185 return; 0186 } 0187 0188 m_query = query; 0189 0190 reset(); 0191 initialize(); 0192 0193 Q_EMIT queryChanged(query); 0194 } 0195 0196 QObject *Devices::device(const QString &udi, const QString &_type) 0197 { 0198 Solid::DeviceInterface::Type type = Solid::DeviceInterface::stringToType(_type); 0199 0200 return Solid::Device(udi).asDeviceInterface(type); 0201 } 0202 } // namespace Solid 0203 0204 #include "moc_devices.cpp" 0205 #include "moc_devices_p.cpp"