File indexing completed on 2024-05-05 03:52:17
0001 /* 0002 SPDX-FileCopyrightText: 2009-2010 Sebastian Trueg <trueg@kde.org> 0003 SPDX-FileCopyrightText: 2013 Vishesh Handa <me@vhanda.in> 0004 SPDX-FileCopyrightText: 2018-2020 Stefan BrĂ¼ns <bruns@kde.org> 0005 0006 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0007 */ 0008 0009 #include "kio_timeline.h" 0010 #include "timelinetools.h" 0011 #include "query.h" 0012 #include "resultiterator.h" 0013 #include "../common/udstools.h" 0014 #include <sys/stat.h> 0015 0016 #include <QCoreApplication> 0017 0018 #include <KUser> 0019 #include <KFormat> 0020 0021 #include <KLocalizedString> 0022 0023 using namespace Baloo; 0024 0025 // Pseudo plugin class to embed meta data 0026 class KIOPluginForMetaData : public QObject 0027 { 0028 Q_OBJECT 0029 Q_PLUGIN_METADATA(IID "org.kde.kio.worker.timeline" FILE "timeline.json") 0030 }; 0031 0032 namespace 0033 { 0034 KIO::UDSEntry createFolderUDSEntry(const QString& name) 0035 { 0036 KIO::UDSEntry uds; 0037 uds.reserve(5); 0038 uds.fastInsert(KIO::UDSEntry::UDS_NAME, name); 0039 uds.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); 0040 uds.fastInsert(KIO::UDSEntry::UDS_MIME_TYPE, QStringLiteral("inode/directory")); 0041 #ifdef Q_OS_WIN 0042 uds.fastInsert(KIO::UDSEntry::UDS_ACCESS, _S_IREAD ); 0043 #else 0044 uds.fastInsert(KIO::UDSEntry::UDS_ACCESS, S_IRUSR | S_IXUSR); 0045 #endif 0046 uds.fastInsert(KIO::UDSEntry::UDS_USER, KUser().loginName()); 0047 return uds; 0048 } 0049 0050 KIO::UDSEntry createDateFolderUDSEntry(const QString& name, const QString& displayName, const QDate& date) 0051 { 0052 KIO::UDSEntry uds; 0053 uds.reserve(8); 0054 QDateTime dt(date, QTime(0, 0, 0)); 0055 uds.fastInsert(KIO::UDSEntry::UDS_NAME, name); 0056 uds.fastInsert(KIO::UDSEntry::UDS_DISPLAY_NAME, displayName); 0057 uds.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); 0058 uds.fastInsert(KIO::UDSEntry::UDS_MIME_TYPE, QStringLiteral("inode/directory")); 0059 uds.fastInsert(KIO::UDSEntry::UDS_MODIFICATION_TIME, dt.toSecsSinceEpoch()); 0060 uds.fastInsert(KIO::UDSEntry::UDS_CREATION_TIME, dt.toSecsSinceEpoch()); 0061 #ifdef Q_OS_WIN 0062 uds.fastInsert(KIO::UDSEntry::UDS_ACCESS, _S_IREAD ); 0063 #else 0064 uds.fastInsert(KIO::UDSEntry::UDS_ACCESS, S_IRUSR | S_IXUSR); 0065 #endif 0066 uds.fastInsert(KIO::UDSEntry::UDS_USER, KUser().loginName()); 0067 return uds; 0068 } 0069 0070 KIO::UDSEntry createMonthUDSEntry(int month, int year) 0071 { 0072 QString dateString = QDate(year, month, 1).toString( 0073 i18nc("Month and year used in a tree above the actual days. " 0074 "Have a look at https://doc.qt.io/qt-5/qdate.html#toString " 0075 "to see which variables you can use and ask kde-i18n-doc@kde.org if you have " 0076 "problems understanding how to translate this", 0077 "MMMM yyyy")); 0078 return createDateFolderUDSEntry(QDate(year, month, 1).toString(QStringLiteral("yyyy-MM")), 0079 dateString, 0080 QDate(year, month, 1)); 0081 } 0082 0083 KIO::UDSEntry createDayUDSEntry(const QDate& date) 0084 { 0085 KIO::UDSEntry uds = createDateFolderUDSEntry(date.toString(QStringLiteral("yyyy-MM-dd")), 0086 KFormat().formatRelativeDate(date, QLocale::LongFormat), 0087 date); 0088 0089 return uds; 0090 } 0091 0092 } 0093 0094 TimelineProtocol::TimelineProtocol(const QByteArray& poolSocket, const QByteArray& appSocket) 0095 : KIO::WorkerBase("timeline", poolSocket, appSocket) 0096 { 0097 } 0098 0099 TimelineProtocol::~TimelineProtocol() 0100 { 0101 } 0102 0103 KIO::WorkerResult TimelineProtocol::listDir(const QUrl& url) 0104 { 0105 QUrl canonicalUrl = canonicalizeTimelineUrl(url); 0106 if (url != canonicalUrl) { 0107 redirection(canonicalUrl); 0108 return KIO::WorkerResult::pass(); 0109 } 0110 0111 switch (parseTimelineUrl(url, &m_date, &m_filename)) { 0112 case RootFolder: 0113 listEntry(createFolderUDSEntry(QStringLiteral("."))); 0114 listEntry(createDateFolderUDSEntry(QStringLiteral("today"), i18n("Today"), QDate::currentDate())); 0115 listEntry(createDateFolderUDSEntry(QStringLiteral("calendar"), i18n("Calendar"), QDate::currentDate())); 0116 break; 0117 0118 case CalendarFolder: 0119 listEntry(createFolderUDSEntry(QStringLiteral("."))); 0120 listThisYearsMonths(); 0121 // TODO: add entry for previous years 0122 break; 0123 0124 case MonthFolder: 0125 listEntry(createFolderUDSEntry(QStringLiteral("."))); 0126 listDays(m_date.month(), m_date.year()); 0127 break; 0128 0129 case DayFolder: { 0130 listEntry(createFolderUDSEntry(QStringLiteral("."))); 0131 Query query; 0132 query.setDateFilter(m_date.year(), m_date.month(), m_date.day()); 0133 query.setSortingOption(Query::SortNone); 0134 0135 UdsFactory udsf; 0136 0137 ResultIterator it = query.exec(); 0138 while (it.next()) { 0139 KIO::UDSEntry uds = udsf.createUdsEntry(it.filePath()); 0140 if (uds.count()) { 0141 listEntry(uds); 0142 } 0143 } 0144 break; 0145 } 0146 0147 case NoFolder: 0148 return KIO::WorkerResult::fail(KIO::ERR_DOES_NOT_EXIST, url.toString()); 0149 } 0150 0151 return KIO::WorkerResult::pass(); 0152 } 0153 0154 KIO::WorkerResult TimelineProtocol::mimetype(const QUrl& url) 0155 { 0156 QUrl canonicalUrl = canonicalizeTimelineUrl(url); 0157 if (url != canonicalUrl) { 0158 redirection(canonicalUrl); 0159 return KIO::WorkerResult::pass(); 0160 } 0161 0162 switch (parseTimelineUrl(url, &m_date, &m_filename)) { 0163 case RootFolder: 0164 case CalendarFolder: 0165 case MonthFolder: 0166 case DayFolder: 0167 mimetype(QUrl(QLatin1String("inode/directory"))); 0168 break; 0169 0170 case NoFolder: 0171 return KIO::WorkerResult::fail(KIO::ERR_DOES_NOT_EXIST, url.toString()); 0172 } 0173 0174 return KIO::WorkerResult::pass(); 0175 } 0176 0177 KIO::WorkerResult TimelineProtocol::stat(const QUrl& url) 0178 { 0179 QUrl canonicalUrl = canonicalizeTimelineUrl(url); 0180 if (url != canonicalUrl) { 0181 redirection(canonicalUrl); 0182 return KIO::WorkerResult::pass(); 0183 } 0184 0185 switch (parseTimelineUrl(url, &m_date, &m_filename)) { 0186 case RootFolder: { 0187 statEntry(createFolderUDSEntry(QStringLiteral("/"))); 0188 break; 0189 } 0190 0191 case CalendarFolder: 0192 statEntry(createDateFolderUDSEntry(QStringLiteral("calendar"), i18n("Calendar"), QDate::currentDate())); 0193 break; 0194 0195 case MonthFolder: 0196 statEntry(createMonthUDSEntry(m_date.month(), m_date.year())); 0197 break; 0198 0199 case DayFolder: 0200 if (m_filename.isEmpty()) { 0201 statEntry(createDayUDSEntry(m_date)); 0202 } 0203 break; 0204 0205 case NoFolder: 0206 return KIO::WorkerResult::fail(KIO::ERR_DOES_NOT_EXIST, url.toString()); 0207 } 0208 0209 return KIO::WorkerResult::pass(); 0210 } 0211 0212 void TimelineProtocol::listDays(int month, int year) 0213 { 0214 const int days = QDate(year, month, 1).daysInMonth(); 0215 for (int day = 1; day <= days; ++day) { 0216 QDate date(year, month, day); 0217 0218 if (date <= QDate::currentDate() && filesInDate(date)) { 0219 listEntry(createDayUDSEntry(date)); 0220 } 0221 } 0222 } 0223 0224 bool TimelineProtocol::filesInDate(const QDate& date) 0225 { 0226 Query query; 0227 query.setLimit(1); 0228 query.setDateFilter(date.year(), date.month(), date.day()); 0229 query.setSortingOption(Query::SortNone); 0230 0231 ResultIterator it = query.exec(); 0232 return it.next(); 0233 } 0234 0235 void TimelineProtocol::listThisYearsMonths() 0236 { 0237 Query query; 0238 query.setLimit(1); 0239 query.setSortingOption(Query::SortNone); 0240 0241 int year = QDate::currentDate().year(); 0242 int currentMonth = QDate::currentDate().month(); 0243 for (int month = 1; month <= currentMonth; ++month) { 0244 query.setDateFilter(year, month); 0245 ResultIterator it = query.exec(); 0246 if (it.next()) { 0247 listEntry(createMonthUDSEntry(month, year)); 0248 } 0249 } 0250 } 0251 0252 extern "C" 0253 { 0254 Q_DECL_EXPORT int kdemain(int argc, char** argv) 0255 { 0256 QCoreApplication app(argc, argv); 0257 app.setApplicationName(QStringLiteral("kio_timeline")); 0258 Baloo::TimelineProtocol worker(argv[2], argv[3]); 0259 worker.dispatchLoop(); 0260 return 0; 0261 } 0262 } 0263 0264 #include "kio_timeline.moc"