File indexing completed on 2024-04-21 04:57:26
0001 /* 0002 * SPDX-FileCopyrightText: 2012-2016 Ivan Cukic <ivan.cukic@kde.org> 0003 * SPDX-FileCopyrightText: 2022 Harald Sitter <sitter@kde.org> 0004 * 0005 * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0006 */ 0007 0008 #include "KioActivities.h" 0009 #include "KioActivitiesApi.h" 0010 0011 #include <QCoreApplication> 0012 0013 #include <QByteArray> 0014 #include <QDebug> 0015 #include <QDir> 0016 #include <QFile> 0017 #include <QSqlDatabase> 0018 #include <QSqlDriver> 0019 #include <QSqlError> 0020 #include <QSqlField> 0021 #include <QSqlQuery> 0022 #include <QStandardPaths> 0023 0024 #include <KIO/Job> 0025 #include <KLocalizedString> 0026 #include <KUser> 0027 0028 #include <common/database/Database.h> 0029 #include <utils/d_ptr_implementation.h> 0030 #include <utils/qsqlquery_iterator.h> 0031 0032 #include <PlasmaActivities/Consumer> 0033 #include <PlasmaActivities/Info> 0034 0035 #include "KioActivitiesApi.h" 0036 #include <QProcess> 0037 0038 // Pseudo plugin class to embed meta data 0039 class KIOPluginForMetaData : public QObject 0040 { 0041 Q_OBJECT 0042 Q_PLUGIN_METADATA(IID "org.kde.kio.slave.activities" FILE "activities.json") 0043 }; 0044 0045 extern "C" int Q_DECL_EXPORT kdemain(int argc, char **argv) 0046 { 0047 // necessary to use other kio slaves 0048 QCoreApplication app(argc, argv); 0049 if (argc != 4) { 0050 fprintf(stderr, "Usage: kio_activities protocol domain-socket1 domain-socket2\n"); 0051 exit(-1); 0052 } 0053 // start the slave 0054 ActivitiesProtocol slave(argv[2], argv[3]); 0055 slave.dispatchLoop(); 0056 return 0; 0057 } 0058 0059 ActivitiesProtocol::ActivitiesProtocol(const QByteArray &poolSocket, const QByteArray &appSocket) 0060 : KIO::ForwardingWorkerBase("activities", poolSocket, appSocket) 0061 { 0062 } 0063 0064 ActivitiesProtocol::~ActivitiesProtocol() = default; 0065 0066 bool ActivitiesProtocol::rewriteUrl(const QUrl &url, QUrl &newUrl) 0067 { 0068 QString activity, path; 0069 switch (d->pathType(url, &activity, &path)) { 0070 case ActivitiesProtocolApi::RootItem: 0071 case ActivitiesProtocolApi::ActivityRootItem: 0072 if (activity == "current") { 0073 KActivities::Consumer activities; 0074 d->syncActivities(activities); 0075 newUrl = QUrl(QStringLiteral("activities:/") + activities.currentActivity()); 0076 return true; 0077 } 0078 return false; 0079 0080 case ActivitiesProtocolApi::ActivityPathItem: { 0081 // auto demangled = d->demangledPath(path); 0082 // QProcess::execute("kdialog", 0083 // { "--passivepopup", 0084 // path.midRef(1).toString() + "\n" + demangled }); 0085 0086 newUrl = QUrl::fromLocalFile(path); 0087 return true; 0088 } 0089 0090 default: 0091 return true; 0092 } 0093 } 0094 0095 KIO::WorkerResult ActivitiesProtocol::listDir(const QUrl &url) 0096 { 0097 KActivities::Consumer activities; 0098 d->syncActivities(activities); 0099 0100 QString activity, path; 0101 switch (d->pathType(url, &activity, &path)) { 0102 case ActivitiesProtocolApi::RootItem: { 0103 KIO::UDSEntryList udslist; 0104 0105 KIO::UDSEntry uds; 0106 uds.reserve(9); 0107 uds.fastInsert(KIO::UDSEntry::UDS_NAME, QStringLiteral("current")); 0108 uds.fastInsert(KIO::UDSEntry::UDS_DISPLAY_NAME, i18n("Current activity")); 0109 uds.fastInsert(KIO::UDSEntry::UDS_DISPLAY_TYPE, i18n("Activity")); 0110 uds.fastInsert(KIO::UDSEntry::UDS_ICON_NAME, QStringLiteral("activities")); 0111 uds.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); 0112 uds.fastInsert(KIO::UDSEntry::UDS_MIME_TYPE, QStringLiteral("inode/directory")); 0113 uds.fastInsert(KIO::UDSEntry::UDS_ACCESS, 0500); 0114 uds.fastInsert(KIO::UDSEntry::UDS_USER, KUser().loginName()); 0115 uds.fastInsert(KIO::UDSEntry::UDS_TARGET_URL, QStringLiteral("activities:/") + activities.currentActivity()); 0116 udslist << uds; 0117 0118 for (const auto &activity : activities.activities()) { 0119 udslist << d->activityEntry(activity); 0120 } 0121 0122 listEntries(udslist); 0123 return KIO::WorkerResult::pass(); 0124 } 0125 0126 case ActivitiesProtocolApi::ActivityRootItem: { 0127 KIO::UDSEntryList udslist; 0128 0129 auto database = Common::Database::instance(Common::Database::ResourcesDatabase, Common::Database::ReadOnly); 0130 0131 if (!database) { 0132 return KIO::WorkerResult::pass(); 0133 } 0134 0135 if (activity == "current") { 0136 activity = activities.currentActivity(); 0137 } 0138 0139 static const auto queryString = QStringLiteral( 0140 "SELECT targettedResource " 0141 "FROM ResourceLink " 0142 "WHERE usedActivity = '%1' " 0143 "AND initiatingAgent = \":global\" "); 0144 0145 auto query = database->execQuery(queryString.arg(activity)); 0146 0147 for (const auto &result : query) { 0148 auto path = result[0].toString(); 0149 0150 if (!QFile(path).exists()) 0151 continue; 0152 0153 KIO::UDSEntry uds; 0154 0155 udslist << d->filesystemEntry(path); 0156 } 0157 0158 listEntries(udslist); 0159 return KIO::WorkerResult::pass(); 0160 } 0161 0162 case ActivitiesProtocolApi::ActivityPathItem: 0163 return ForwardingWorkerBase::listDir(QUrl::fromLocalFile(path)); 0164 } 0165 0166 Q_UNREACHABLE(); 0167 return KIO::WorkerResult::fail(); 0168 } 0169 0170 KIO::WorkerResult ActivitiesProtocol::stat(const QUrl &url) 0171 { 0172 QString activity; 0173 0174 switch (d->pathType(url, &activity)) { 0175 case ActivitiesProtocolApi::RootItem: { 0176 QString dirName = i18n("Activities"); 0177 KIO::UDSEntry uds; 0178 uds.reserve(6); 0179 uds.fastInsert(KIO::UDSEntry::UDS_NAME, dirName); 0180 uds.fastInsert(KIO::UDSEntry::UDS_DISPLAY_NAME, dirName); 0181 uds.fastInsert(KIO::UDSEntry::UDS_DISPLAY_TYPE, dirName); 0182 uds.fastInsert(KIO::UDSEntry::UDS_ICON_NAME, QStringLiteral("activities")); 0183 uds.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); 0184 uds.fastInsert(KIO::UDSEntry::UDS_MIME_TYPE, QStringLiteral("inode/directory")); 0185 0186 statEntry(uds); 0187 0188 return KIO::WorkerResult::pass(); 0189 } 0190 0191 case ActivitiesProtocolApi::ActivityRootItem: { 0192 KActivities::Consumer activities; 0193 d->syncActivities(activities); 0194 0195 if (activity == "current") { 0196 activity = activities.currentActivity(); 0197 } 0198 0199 statEntry(d->activityEntry(activity)); 0200 0201 return KIO::WorkerResult::pass(); 0202 } 0203 0204 case ActivitiesProtocolApi::ActivityPathItem: 0205 return ForwardingWorkerBase::stat(url); 0206 } 0207 0208 Q_UNREACHABLE(); 0209 return KIO::WorkerResult::fail(); 0210 } 0211 0212 KIO::WorkerResult ActivitiesProtocol::mimetype(const QUrl &url) 0213 { 0214 switch (d->pathType(url)) { 0215 case ActivitiesProtocolApi::RootItem: 0216 case ActivitiesProtocolApi::ActivityRootItem: 0217 mimeType(QStringLiteral("inode/directory")); 0218 return KIO::WorkerResult::pass(); 0219 0220 case ActivitiesProtocolApi::ActivityPathItem: 0221 return ForwardingWorkerBase::mimetype(url); 0222 } 0223 0224 Q_UNREACHABLE(); 0225 return KIO::WorkerResult::fail(); 0226 } 0227 0228 #include "KioActivities.moc" 0229 #include "moc_KioActivities.cpp"