File indexing completed on 2024-05-12 17:07:26

0001 /*
0002     SPDX-FileCopyrightText: 2009 Ben Cooksley <ben@eclipse.endoftheinternet.org>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "SolidActionData.h"
0008 
0009 #include <QDirIterator>
0010 #include <QList>
0011 #include <QMetaProperty>
0012 #include <QRegularExpression>
0013 
0014 #include <KConfigGroup>
0015 #include <KDesktopFile>
0016 #include <KDesktopFileActions>
0017 #include <KFileUtils>
0018 #include <KStringHandler>
0019 
0020 #include <Solid/Battery>
0021 #include <Solid/Block>
0022 #include <Solid/Camera>
0023 #include <Solid/GenericInterface>
0024 #include <Solid/OpticalDisc>
0025 #include <Solid/OpticalDrive>
0026 #include <Solid/PortableMediaPlayer>
0027 #include <Solid/Processor>
0028 #include <Solid/StorageAccess>
0029 #include <Solid/StorageDrive>
0030 #include <Solid/StorageVolume>
0031 
0032 static SolidActionData *actData = nullptr;
0033 
0034 SolidActionData::SolidActionData(bool includeFiles)
0035 {
0036     const int propertyOffset = Solid::DeviceInterface::staticMetaObject.propertyOffset();
0037 
0038     const QList<QMetaObject> interfaceList = fillInterfaceList();
0039     for (const QMetaObject &interface : interfaceList) {
0040         QString ifaceName = interface.className();
0041         ifaceName.remove(0, ifaceName.lastIndexOf(':') + 1);
0042         Solid::DeviceInterface::Type ifaceDev = Solid::DeviceInterface::stringToType(ifaceName);
0043         const QString cleanName = Solid::DeviceInterface::typeDescription(ifaceDev);
0044         types.insert(ifaceDev, cleanName);
0045 
0046         QMap<QString, QString> deviceValues;
0047         for (int doneProps = propertyOffset; interface.propertyCount() > doneProps; doneProps = doneProps + 1) {
0048             QMetaProperty ifaceProp = interface.property(doneProps);
0049             deviceValues.insert(ifaceProp.name(), generateUserString(ifaceProp.name()));
0050         }
0051         values.insert(ifaceDev, deviceValues);
0052     }
0053 
0054     if (includeFiles) {
0055         // Fill the lists of possible device types / device values
0056         // List all the known device actions, then add their name and all values to the appropriate lists
0057 
0058         const QStringList dirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, //
0059                                                            QStringLiteral("/solid/devices/"),
0060                                                            QStandardPaths::LocateDirectory);
0061 
0062         const QStringList files = KFileUtils::findAllUniqueFiles(dirs, {QStringLiteral("*.desktop")});
0063 
0064         for (const QString &file : files) {
0065             KDesktopFile deviceFile(file);
0066             KConfigGroup deviceType = deviceFile.desktopGroup(); // Retrieve the configuration group where the user friendly name is
0067 
0068             const QString ifaceName = deviceType.readEntry("X-KDE-Solid-Actions-Type");
0069             Solid::DeviceInterface::Type ifaceDev = Solid::DeviceInterface::stringToType(ifaceName);
0070             const QString cleanName = Solid::DeviceInterface::typeDescription(ifaceDev);
0071 
0072             types.insert(ifaceDev, cleanName); // Read the user friendly name
0073 
0074             QMap<QString, QString> deviceValues = values.value(ifaceDev);
0075             const auto actions = deviceFile.readActions();
0076             for (const QString &text : actions) { // We want every single action
0077                 KConfigGroup actionType = deviceFile.actionGroup(text);
0078                 deviceValues.insert(text, actionType.readEntry("Name")); // Add to the type - actions map
0079             }
0080             values.insert(ifaceDev, deviceValues);
0081         }
0082     }
0083 }
0084 
0085 QList<QString> SolidActionData::propertyList(Solid::DeviceInterface::Type devInterface)
0086 {
0087     return values.value(devInterface).values();
0088 }
0089 
0090 QList<QString> SolidActionData::propertyInternalList(Solid::DeviceInterface::Type devInterface)
0091 {
0092     return values.value(devInterface).keys();
0093 }
0094 
0095 QString SolidActionData::propertyInternal(Solid::DeviceInterface::Type devInterface, QString property)
0096 {
0097     return values.value(devInterface).key(property);
0098 }
0099 
0100 QString SolidActionData::propertyName(Solid::DeviceInterface::Type devInterface, QString property)
0101 {
0102     return values.value(devInterface).value(property);
0103 }
0104 
0105 int SolidActionData::propertyPosition(Solid::DeviceInterface::Type devInterface, QString property)
0106 {
0107     return values.value(devInterface).keys().indexOf(property);
0108 }
0109 
0110 QList<QString> SolidActionData::interfaceList()
0111 {
0112     return types.values();
0113 }
0114 
0115 QList<Solid::DeviceInterface::Type> SolidActionData::interfaceTypeList()
0116 {
0117     return types.keys();
0118 }
0119 
0120 Solid::DeviceInterface::Type SolidActionData::interfaceFromName(const QString &name)
0121 {
0122     return types.key(name);
0123 }
0124 
0125 QString SolidActionData::nameFromInterface(Solid::DeviceInterface::Type devInterface)
0126 {
0127     return types.value(devInterface);
0128 }
0129 
0130 int SolidActionData::interfacePosition(Solid::DeviceInterface::Type devInterface)
0131 {
0132     return types.keys().indexOf(devInterface);
0133 }
0134 
0135 QString SolidActionData::generateUserString(QString className)
0136 {
0137     QString finalString;
0138     QRegularExpression camelCase(QStringLiteral("([A-Z])")); // Create the split regexp
0139 
0140     finalString = className.remove(0, className.lastIndexOf(':') + 1); // Remove any Class information
0141     finalString.replace(camelCase, QStringLiteral(" \\1")); // Use Camel Casing to add spaces
0142     finalString = KStringHandler::capwords(finalString); // Capitalize everything
0143     return finalString.trimmed();
0144 }
0145 
0146 SolidActionData *SolidActionData::instance()
0147 {
0148     if (actData == nullptr) {
0149         actData = new SolidActionData(true);
0150     }
0151     return actData;
0152 }
0153 
0154 QList<QMetaObject> SolidActionData::fillInterfaceList()
0155 {
0156     QList<QMetaObject> interfaces;
0157     interfaces.append(Solid::Battery::staticMetaObject);
0158     interfaces.append(Solid::Block::staticMetaObject);
0159     interfaces.append(Solid::Camera::staticMetaObject);
0160     interfaces.append(Solid::PortableMediaPlayer::staticMetaObject);
0161     interfaces.append(Solid::Processor::staticMetaObject);
0162     interfaces.append(Solid::StorageAccess::staticMetaObject);
0163     interfaces.append(Solid::StorageDrive::staticMetaObject);
0164     interfaces.append(Solid::OpticalDrive::staticMetaObject);
0165     interfaces.append(Solid::StorageVolume::staticMetaObject);
0166     interfaces.append(Solid::OpticalDisc::staticMetaObject);
0167     return interfaces;
0168 }