Baloo

kio_timeline.cpp
1 /*
2  SPDX-FileCopyrightText: 2009-2010 Sebastian Trueg <[email protected]>
3  SPDX-FileCopyrightText: 2013 Vishesh Handa <[email protected]>
4  SPDX-FileCopyrightText: 2018-2020 Stefan BrĂ¼ns <[email protected]>
5 
6  SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
7 */
8 
9 #include "kio_timeline.h"
10 #include "timelinetools.h"
11 #include "query.h"
12 #include "resultiterator.h"
13 #include "../common/udstools.h"
14 #include <sys/stat.h>
15 
16 #include <QCoreApplication>
17 
18 #include <KUser>
19 #include <KFormat>
20 
21 #include <KLocalizedString>
22 
23 using namespace Baloo;
24 
25 // Pseudo plugin class to embed meta data
26 class KIOPluginForMetaData : public QObject
27 {
28  Q_OBJECT
29  Q_PLUGIN_METADATA(IID "org.kde.kio.worker.timeline" FILE "timeline.json")
30 };
31 
32 namespace
33 {
34 KIO::UDSEntry createFolderUDSEntry(const QString& name)
35 {
36  KIO::UDSEntry uds;
37  uds.reserve(5);
40  uds.fastInsert(KIO::UDSEntry::UDS_MIME_TYPE, QStringLiteral("inode/directory"));
41 #ifdef Q_OS_WIN
42  uds.fastInsert(KIO::UDSEntry::UDS_ACCESS, _S_IREAD );
43 #else
44  uds.fastInsert(KIO::UDSEntry::UDS_ACCESS, S_IRUSR | S_IXUSR);
45 #endif
46  uds.fastInsert(KIO::UDSEntry::UDS_USER, KUser().loginName());
47  return uds;
48 }
49 
50 KIO::UDSEntry createDateFolderUDSEntry(const QString& name, const QString& displayName, const QDate& date)
51 {
52  KIO::UDSEntry uds;
53  uds.reserve(8);
54  QDateTime dt(date, QTime(0, 0, 0));
58  uds.fastInsert(KIO::UDSEntry::UDS_MIME_TYPE, QStringLiteral("inode/directory"));
59  uds.fastInsert(KIO::UDSEntry::UDS_MODIFICATION_TIME, dt.toSecsSinceEpoch());
60  uds.fastInsert(KIO::UDSEntry::UDS_CREATION_TIME, dt.toSecsSinceEpoch());
61 #ifdef Q_OS_WIN
62  uds.fastInsert(KIO::UDSEntry::UDS_ACCESS, _S_IREAD );
63 #else
64  uds.fastInsert(KIO::UDSEntry::UDS_ACCESS, S_IRUSR | S_IXUSR);
65 #endif
66  uds.fastInsert(KIO::UDSEntry::UDS_USER, KUser().loginName());
67  return uds;
68 }
69 
70 KIO::UDSEntry createMonthUDSEntry(int month, int year)
71 {
72  QString dateString = QDate(year, month, 1).toString(
73  i18nc("Month and year used in a tree above the actual days. "
74  "Have a look at https://doc.qt.io/qt-5/qdate.html#toString "
75  "to see which variables you can use and ask [email protected] if you have "
76  "problems understanding how to translate this",
77  "MMMM yyyy"));
78  return createDateFolderUDSEntry(QDate(year, month, 1).toString(QStringLiteral("yyyy-MM")),
79  dateString,
80  QDate(year, month, 1));
81 }
82 
83 KIO::UDSEntry createDayUDSEntry(const QDate& date)
84 {
85  KIO::UDSEntry uds = createDateFolderUDSEntry(date.toString(QStringLiteral("yyyy-MM-dd")),
86  KFormat().formatRelativeDate(date, QLocale::LongFormat),
87  date);
88 
89  return uds;
90 }
91 
92 }
93 
94 TimelineProtocol::TimelineProtocol(const QByteArray& poolSocket, const QByteArray& appSocket)
95  : KIO::WorkerBase("timeline", poolSocket, appSocket)
96 {
97 }
98 
99 TimelineProtocol::~TimelineProtocol()
100 {
101 }
102 
103 KIO::WorkerResult TimelineProtocol::listDir(const QUrl& url)
104 {
105  QUrl canonicalUrl = canonicalizeTimelineUrl(url);
106  if (url != canonicalUrl) {
107  redirection(canonicalUrl);
108  return KIO::WorkerResult::pass();
109  }
110 
111  switch (parseTimelineUrl(url, &m_date, &m_filename)) {
112  case RootFolder:
113  listEntry(createFolderUDSEntry(QStringLiteral(".")));
114  listEntry(createDateFolderUDSEntry(QStringLiteral("today"), i18n("Today"), QDate::currentDate()));
115  listEntry(createDateFolderUDSEntry(QStringLiteral("calendar"), i18n("Calendar"), QDate::currentDate()));
116  break;
117 
118  case CalendarFolder:
119  listEntry(createFolderUDSEntry(QStringLiteral(".")));
120  listThisYearsMonths();
121  // TODO: add entry for previous years
122  break;
123 
124  case MonthFolder:
125  listEntry(createFolderUDSEntry(QStringLiteral(".")));
126  listDays(m_date.month(), m_date.year());
127  break;
128 
129  case DayFolder: {
130  listEntry(createFolderUDSEntry(QStringLiteral(".")));
131  Query query;
132  query.setDateFilter(m_date.year(), m_date.month(), m_date.day());
133  query.setSortingOption(Query::SortNone);
134 
135  UdsFactory udsf;
136 
137  ResultIterator it = query.exec();
138  while (it.next()) {
139  KIO::UDSEntry uds = udsf.createUdsEntry(it.filePath());
140  if (uds.count()) {
141  listEntry(uds);
142  }
143  }
144  break;
145  }
146 
147  case NoFolder:
148  return KIO::WorkerResult::fail(KIO::ERR_DOES_NOT_EXIST, url.toString());
149  }
150 
151  return KIO::WorkerResult::pass();
152 }
153 
154 KIO::WorkerResult TimelineProtocol::mimetype(const QUrl& url)
155 {
156  QUrl canonicalUrl = canonicalizeTimelineUrl(url);
157  if (url != canonicalUrl) {
158  redirection(canonicalUrl);
159  return KIO::WorkerResult::pass();
160  }
161 
162  switch (parseTimelineUrl(url, &m_date, &m_filename)) {
163  case RootFolder:
164  case CalendarFolder:
165  case MonthFolder:
166  case DayFolder:
167  mimetype(QUrl(QLatin1String("inode/directory")));
168  break;
169 
170  case NoFolder:
171  return KIO::WorkerResult::fail(KIO::ERR_DOES_NOT_EXIST, url.toString());
172  }
173 
174  return KIO::WorkerResult::pass();
175 }
176 
177 KIO::WorkerResult TimelineProtocol::stat(const QUrl& url)
178 {
179  QUrl canonicalUrl = canonicalizeTimelineUrl(url);
180  if (url != canonicalUrl) {
181  redirection(canonicalUrl);
182  return KIO::WorkerResult::pass();
183  }
184 
185  switch (parseTimelineUrl(url, &m_date, &m_filename)) {
186  case RootFolder: {
187  statEntry(createFolderUDSEntry(QStringLiteral("/")));
188  break;
189  }
190 
191  case CalendarFolder:
192  statEntry(createDateFolderUDSEntry(QStringLiteral("calendar"), i18n("Calendar"), QDate::currentDate()));
193  break;
194 
195  case MonthFolder:
196  statEntry(createMonthUDSEntry(m_date.month(), m_date.year()));
197  break;
198 
199  case DayFolder:
200  if (m_filename.isEmpty()) {
201  statEntry(createDayUDSEntry(m_date));
202  }
203  break;
204 
205  case NoFolder:
206  return KIO::WorkerResult::fail(KIO::ERR_DOES_NOT_EXIST, url.toString());
207  }
208 
209  return KIO::WorkerResult::pass();
210 }
211 
212 void TimelineProtocol::listDays(int month, int year)
213 {
214  const int days = QDate(year, month, 1).daysInMonth();
215  for (int day = 1; day <= days; ++day) {
216  QDate date(year, month, day);
217 
218  if (date <= QDate::currentDate() && filesInDate(date)) {
219  listEntry(createDayUDSEntry(date));
220  }
221  }
222 }
223 
224 bool TimelineProtocol::filesInDate(const QDate& date)
225 {
226  Query query;
227  query.setLimit(1);
228  query.setDateFilter(date.year(), date.month(), date.day());
229  query.setSortingOption(Query::SortNone);
230 
231  ResultIterator it = query.exec();
232  return it.next();
233 }
234 
235 void TimelineProtocol::listThisYearsMonths()
236 {
237  Query query;
238  query.setLimit(1);
239  query.setSortingOption(Query::SortNone);
240 
241  int year = QDate::currentDate().year();
242  int currentMonth = QDate::currentDate().month();
243  for (int month = 1; month <= currentMonth; ++month) {
244  query.setDateFilter(year, month);
245  ResultIterator it = query.exec();
246  if (it.next()) {
247  listEntry(createMonthUDSEntry(month, year));
248  }
249  }
250 }
251 
252 extern "C"
253 {
254  Q_DECL_EXPORT int kdemain(int argc, char** argv)
255  {
256  QCoreApplication app(argc, argv);
257  app.setApplicationName(QStringLiteral("kio_timeline"));
258  Baloo::TimelineProtocol worker(argv[2], argv[3]);
259  worker.dispatchLoop();
260  return 0;
261  }
262 }
263 
264 #include "kio_timeline.moc"
int count() const
int month() const const
static WorkerResult pass()
std::optional< QSqlQuery > query(const QString &queryStatement)
int year() const const
KIOCORE_EXPORT MimetypeJob * mimetype(const QUrl &url, JobFlags flags=DefaultFlags)
TimelineFolderType parseTimelineUrl(const QUrl &url, QDate *date, QString *filename=nullptr)
Parse a timeline URL like timeline:/today and return the type of folder it represents.
QString toString(QUrl::FormattingOptions options) const const
QString i18n(const char *text, const TYPE &arg...)
static WorkerResult fail(int _error=KIO::ERR_UNKNOWN, const QString &_errorString=QString())
Implements storage for docIds without any associated data Instantiated for:
Definition: coding.cpp:11
void reserve(int size)
QDate currentDate()
int daysInMonth() const const
void fastInsert(uint field, const QString &value)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QUrl canonicalizeTimelineUrl(const QUrl &url)
Remove any double slashes, remove any trailing slashes, and add an initial slash after the scheme.
QString toString(Qt::DateFormat format) const const
char * toString(const EngineQuery &query)
Helper for QTest.
Definition: enginequery.h:91
int day() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Wed Nov 29 2023 03:56:26 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.