File indexing completed on 2024-05-05 03:52:17

0001 /*
0002     This file is part of the Nepomuk KDE project.
0003     SPDX-FileCopyrightText: 2010 Sebastian Trueg <trueg@kde.org>
0004 
0005     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0006 */
0007 
0008 #include "timelinetools.h"
0009 #include "kio_timeline_debug.h"
0010 
0011 #include <QRegularExpression>
0012 #include <QUrlQuery>
0013 
0014 namespace
0015 {
0016 QDate applyRelativeDateModificators(const QDate& date, const QMap<QString, QString>& modificators)
0017 {
0018     QDate newDate(date);
0019     const QString dayKey = QStringLiteral("relDays");
0020     const QString weekKey = QStringLiteral("relWeeks");
0021     const QString monthKey = QStringLiteral("relMonths");
0022     const QString yearKey = QStringLiteral("relYears");
0023     bool ok = false;
0024 
0025     if (modificators.contains(yearKey)) {
0026         int relYears = modificators[yearKey].toInt(&ok);
0027         if (ok) {
0028             newDate = newDate.addYears(relYears);
0029         }
0030     }
0031     if (modificators.contains(monthKey)) {
0032         int relMonths = modificators[monthKey].toInt(&ok);
0033         if (ok) {
0034             newDate = newDate.addMonths(relMonths);
0035         }
0036     }
0037     if (modificators.contains(weekKey)) {
0038         int relWeeks = modificators[weekKey].toInt(&ok);
0039         if (ok) {
0040             newDate = newDate.addDays(relWeeks * 7); // we assume weeks have 7 days everywhere. QDate seems to make that assumption too, should be OK.
0041         }
0042     }
0043     if (modificators.contains(dayKey)) {
0044         int relDays = modificators[dayKey].toInt(&ok);
0045         if (ok) {
0046             newDate = newDate.addDays(relDays);
0047         }
0048     }
0049     return newDate;
0050 }
0051 }
0052 
0053 QUrl Baloo::canonicalizeTimelineUrl(const QUrl& url) {
0054     QUrl newUrl = url;
0055     QString path = url.path();
0056     if (path.contains(QLatin1String("//"))) {
0057         QStringList sections = path.split(QLatin1Char('/'), Qt::SkipEmptyParts);
0058         path = QLatin1Char('/') + sections.join(QLatin1Char('/'));
0059         newUrl.setPath(path);
0060     }
0061     if ((path.size() > 1) && path.endsWith(QLatin1Char('/'))) {
0062         path.chop(1);
0063         newUrl.setPath(path);
0064     }
0065     if (!path.startsWith(QLatin1Char('/'))) {
0066         path = QLatin1Char('/') + path;
0067         newUrl.setPath(path);
0068     }
0069     return newUrl;
0070 }
0071 
0072 Baloo::TimelineFolderType Baloo::parseTimelineUrl(const QUrl& url, QDate* date, QString* filename)
0073 {
0074     qCDebug(KIO_TIMELINE) << url;
0075 
0076     static const QRegularExpression s_dateRegexp(
0077                     QRegularExpression::anchoredPattern(QStringLiteral("\\d{4}-\\d{2}(?:-(\\d{2}))?")));
0078 
0079     // reset
0080     *date = QDate();
0081 
0082     QString path = url.path();
0083     if (path.endsWith(QLatin1Char('/'))) {
0084         path.chop(1);
0085     }
0086 
0087     if (path.isEmpty()) {
0088         qCDebug(KIO_TIMELINE) << url << "is root folder";
0089         return RootFolder;
0090     } else if (path.startsWith(QLatin1String("/today"))) {
0091         *date = QDate::currentDate();
0092         if (filename) {
0093             *filename = path.mid(7);
0094         }
0095         qCDebug(KIO_TIMELINE) << url << "is today folder:" << *date;
0096         return DayFolder;
0097     } else if (path == QLatin1String("/calendar")) {
0098         qCDebug(KIO_TIMELINE) << url << "is calendar folder";
0099         return CalendarFolder;
0100     } else {
0101         QStringList sections = path.split(QStringLiteral("/"), Qt::SkipEmptyParts);
0102         QString dateString;
0103         QRegularExpressionMatch match = s_dateRegexp.match(sections.last());
0104         if (match.hasMatch()) {
0105             dateString = sections.last();
0106         } else if (sections.count() > 1
0107                    && (match = s_dateRegexp.match(sections[sections.count() - 2])).hasMatch()) {
0108             dateString = sections[sections.count() - 2];
0109             if (filename) {
0110                 *filename = sections.last();
0111             }
0112         } else {
0113             qCWarning(KIO_TIMELINE) << url << "COULD NOT PARSE";
0114             return NoFolder;
0115         }
0116 
0117         if (match.captured(1).isEmpty()) {
0118             // no day -> month listing
0119             qCDebug(KIO_TIMELINE) << "parsing " << dateString;
0120             *date = QDate::fromString(dateString, QStringLiteral("yyyy-MM"));
0121             qCDebug(KIO_TIMELINE) << url << "is month folder:" << date->month() << date->year();
0122             if (date->month() > 0 && date->year() > 0) {
0123                 return MonthFolder;
0124             }
0125         } else {
0126             qCDebug(KIO_TIMELINE) << "parsing " << dateString;
0127             typedef QPair<QString, QString> StringPair;
0128             QUrlQuery query(url);
0129             const QList<StringPair> queryItems = query.queryItems();
0130             QMap<QString, QString> map;
0131             for (const StringPair& pair : queryItems) {
0132                 map.insert(pair.first, pair.second);
0133             }
0134 
0135             *date = applyRelativeDateModificators(QDate::fromString(dateString, QStringLiteral("yyyy-MM-dd")), map);
0136             // only in day folders we can have filenames
0137             qCDebug(KIO_TIMELINE) << url << "is day folder:" << *date;
0138             if (date->isValid()) {
0139                 return DayFolder;
0140             }
0141         }
0142     }
0143 
0144     return NoFolder;
0145 }