File indexing completed on 2024-05-12 05:10:36
0001 /****************************************************************************** 0002 * konsolekalendar.cpp * 0003 * * 0004 * KonsoleKalendar is a command line interface to KDE calendars * 0005 * SPDX-FileCopyrightText: 2002-2004 Tuukka Pasanen <illuusio@mailcity.com> * 0006 * SPDX-FileCopyrightText: 2003-2005 Allen Winter <winter@kde.org> * 0007 * * 0008 * SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0 * 0009 * * 0010 ******************************************************************************/ 0011 /** 0012 * @file konsolekalendar.cpp 0013 * Provides the KonsoleKalendar class definition. 0014 * @author Tuukka Pasanen 0015 * @author Allen Winter 0016 */ 0017 #include "konsolekalendar.h" 0018 #include "konsolekalendaradd.h" 0019 #include "konsolekalendarchange.h" 0020 #include "konsolekalendardelete.h" 0021 #include "konsolekalendarexports.h" 0022 0023 #include "konsolekalendar_debug.h" 0024 #include <KLocalizedString> 0025 0026 #include <Akonadi/AgentInstance> 0027 #include <Akonadi/AgentInstanceCreateJob> 0028 #include <Akonadi/AgentManager> 0029 #include <Akonadi/Collection> 0030 #include <Akonadi/CollectionFetchJob> 0031 #include <Akonadi/CollectionFetchScope> 0032 0033 #include <QDBusInterface> 0034 #include <QDBusReply> 0035 #include <QEventLoop> 0036 #include <QFile> 0037 #include <QFileInfo> 0038 #include <QTextStream> 0039 0040 #include <cstdio> 0041 #include <cstdlib> 0042 #include <iostream> 0043 0044 using namespace KCalendarCore; 0045 using namespace std; 0046 0047 KonsoleKalendar::KonsoleKalendar(KonsoleKalendarVariables *variables) 0048 { 0049 m_variables = variables; 0050 } 0051 0052 KonsoleKalendar::~KonsoleKalendar() = default; 0053 0054 bool KonsoleKalendar::importCalendar() 0055 { 0056 KonsoleKalendarAdd add(m_variables); 0057 0058 qCDebug(KONSOLEKALENDAR_LOG) << "konsolecalendar.cpp::importCalendar() | importing now!"; 0059 return add.addImportedCalendar(); 0060 } 0061 0062 bool KonsoleKalendar::printCalendarList() 0063 { 0064 auto job = new Akonadi::CollectionFetchJob(Akonadi::Collection::root(), Akonadi::CollectionFetchJob::Recursive); 0065 const QStringList mimeTypes = QStringList() << QStringLiteral("text/calendar") << KCalendarCore::Event::eventMimeType() 0066 << KCalendarCore::Todo::todoMimeType() << KCalendarCore::Journal::journalMimeType(); 0067 job->fetchScope().setContentMimeTypes(mimeTypes); 0068 QEventLoop loop; 0069 QObject::connect(job, &Akonadi::CollectionFetchJob::result, &loop, &QEventLoop::quit); 0070 job->start(); 0071 loop.exec(); 0072 0073 if (job->error() != 0) { 0074 return false; 0075 } 0076 0077 const Akonadi::Collection::List collections = job->collections(); 0078 0079 if (collections.isEmpty()) { 0080 cout << i18n("There are no calendars available.").toLocal8Bit().data() << endl; 0081 } else { 0082 cout << "--------------------------" << endl; 0083 auto mimeTypeSet = QSet<QString>(mimeTypes.begin(), mimeTypes.end()); // set changes by run method intersect 0084 for (const Akonadi::Collection &collection : collections) { 0085 const QStringList contentMimeTypes = collection.contentMimeTypes(); 0086 auto collectionMimeTypeSet = QSet<QString>(contentMimeTypes.begin(), contentMimeTypes.end()); 0087 0088 if (mimeTypeSet.intersects(collectionMimeTypeSet)) { 0089 QString colId = QString::number(collection.id()).leftJustified(6, QLatin1Char(' ')); 0090 colId += QLatin1StringView("- "); 0091 0092 bool readOnly = !(collection.rights() & Akonadi::Collection::CanCreateItem || collection.rights() & Akonadi::Collection::CanChangeItem 0093 || collection.rights() & Akonadi::Collection::CanDeleteItem); 0094 0095 QString readOnlyString = readOnly ? i18n("(Read only)") + QLatin1Char(' ') : QString(); 0096 0097 cout << colId.toLocal8Bit().data() << readOnlyString.toLocal8Bit().constData() << collection.displayName().toLocal8Bit().data() << endl; 0098 } 0099 } 0100 } 0101 0102 return true; 0103 } 0104 0105 bool KonsoleKalendar::createAkonadiResource(const QString &icalFileUri) 0106 { 0107 Akonadi::AgentType type = Akonadi::AgentManager::self()->type(QStringLiteral("akonadi_ical_resource")); 0108 auto job = new Akonadi::AgentInstanceCreateJob(type); 0109 QEventLoop loop; 0110 QObject::connect(job, &Akonadi::CollectionFetchJob::result, &loop, &QEventLoop::quit); 0111 job->start(); 0112 loop.exec(); 0113 if (job->error() != 0) { 0114 return false; 0115 } 0116 auto inst = job->instance(); 0117 inst.setName(QFileInfo(icalFileUri).baseName()); 0118 QDBusInterface iface(QStringLiteral("org.freedesktop.Akonadi.Resource.") + inst.identifier(), QStringLiteral("/Settings")); 0119 QDBusReply<void> reply = iface.call(QStringLiteral("setDisplayName"), QFileInfo(icalFileUri).baseName()); 0120 if (!reply.isValid()) { 0121 qCWarning(KONSOLEKALENDAR_LOG) << "Could not set setting 'name': " << reply.error().message(); 0122 return false; 0123 } 0124 reply = iface.call(QStringLiteral("setPath"), icalFileUri); 0125 if (!reply.isValid()) { 0126 qCWarning(KONSOLEKALENDAR_LOG) << "Could not set setting 'path': " << reply.error().message(); 0127 return false; 0128 } 0129 reply = iface.call(QStringLiteral("save")); 0130 if (!reply.isValid()) { 0131 qCWarning(KONSOLEKALENDAR_LOG) << "Could not save settings: " << reply.error().message(); 0132 return false; 0133 } 0134 inst.reconfigure(); 0135 return true; 0136 } 0137 0138 bool KonsoleKalendar::createCalendar() 0139 { 0140 bool status = false; 0141 0142 const QString filename = m_variables->getCalendarFile(); 0143 0144 if (m_variables->isDryRun()) { 0145 cout << i18n("Create Calendar <Dry Run>: %1", filename).toLocal8Bit().data() << endl; 0146 } else { 0147 qCDebug(KONSOLEKALENDAR_LOG) << "konsolekalendar.cpp::createCalendar() |" 0148 << "Creating calendar file: " << filename.toLocal8Bit().data(); 0149 0150 if (m_variables->isVerbose()) { 0151 cout << i18n("Create Calendar <Verbose>: %1", filename).toLocal8Bit().data() << endl; 0152 } 0153 0154 status = createAkonadiResource(QStringLiteral("file://%1").arg(filename)); 0155 } 0156 0157 return status; 0158 } 0159 0160 bool KonsoleKalendar::showInstance() 0161 { 0162 bool status = true; 0163 QFile f; 0164 QString title; 0165 Event::Ptr event; 0166 const auto timeZone = m_variables->getCalendar()->timeZone(); 0167 Akonadi::CalendarBase::Ptr calendar = m_variables->getCalendar(); 0168 0169 if (m_variables->isDryRun()) { 0170 cout << qPrintable(i18n("View Events <Dry Run>:")) << endl; 0171 printSpecs(); 0172 } else { 0173 qCDebug(KONSOLEKALENDAR_LOG) << "konsolekalendar.cpp::showInstance() |" 0174 << "open export file"; 0175 0176 if (m_variables->isExportFile()) { 0177 f.setFileName(m_variables->getExportFile()); 0178 if (!f.open(QIODevice::WriteOnly)) { 0179 status = false; 0180 qCDebug(KONSOLEKALENDAR_LOG) << "konsolekalendar.cpp::showInstance() |" 0181 << "unable to open export file" << m_variables->getExportFile(); 0182 } 0183 } else { 0184 f.open(stdout, QIODevice::WriteOnly); 0185 } 0186 0187 if (status) { 0188 qCDebug(KONSOLEKALENDAR_LOG) << "konsolekalendar.cpp::showInstance() |" 0189 << "opened successful"; 0190 0191 if (m_variables->isVerbose()) { 0192 cout << i18n("View Event <Verbose>:").toLocal8Bit().data() << endl; 0193 printSpecs(); 0194 } 0195 0196 QTextStream ts(&f); 0197 0198 if (m_variables->getAll()) { 0199 qCDebug(KONSOLEKALENDAR_LOG) << "konsolekalendar.cpp::showInstance() |" 0200 << "view all events sorted list"; 0201 0202 const Event::List sortedList = calendar->events(EventSortStartDate); 0203 qCDebug(KONSOLEKALENDAR_LOG) << "Found" << sortedList.count() << "events"; 0204 if (!sortedList.isEmpty()) { 0205 // The code that was here before the akonadi port was really slow with 200 events 0206 // this is much faster: 0207 for (const KCalendarCore::Event::Ptr &event : sortedList) { 0208 status &= printEvent(&ts, event, event->dtStart().date()); 0209 } 0210 } 0211 } else if (m_variables->isUID()) { 0212 qCDebug(KONSOLEKALENDAR_LOG) << "konsolekalendar.cpp::showInstance() |" 0213 << "view events by uid list"; 0214 // TODO: support a list of UIDs 0215 event = calendar->event(m_variables->getUID()); 0216 // If this UID represents a recurring Event, 0217 // only the first day of the Event will be printed 0218 status = printEvent(&ts, event, event->dtStart().date()); 0219 } else if (m_variables->isNext()) { 0220 qCDebug(KONSOLEKALENDAR_LOG) << "konsolekalendar.cpp::showInstance() |" 0221 << "Show next activity in calendar"; 0222 0223 QDateTime datetime = m_variables->getStartDateTime(); 0224 datetime = datetime.addDays(720); 0225 0226 QDate dt; 0227 for (dt = m_variables->getStartDateTime().date(); dt <= datetime.date(); dt = dt.addDays(1)) { 0228 Event::List events = calendar->events(dt, timeZone, EventSortStartDate, SortDirectionAscending); 0229 qCDebug(KONSOLEKALENDAR_LOG) << "2-Found" << events.count() << "events on date" << dt; 0230 // finished here when we get the next event 0231 if (!events.isEmpty()) { 0232 qCDebug(KONSOLEKALENDAR_LOG) << "konsolekalendar.cpp::showInstance() |" 0233 << "Got the next event"; 0234 printEvent(&ts, events.first(), dt); 0235 return true; 0236 } 0237 } 0238 } 0239 f.close(); 0240 } 0241 } 0242 return status; 0243 } 0244 0245 bool KonsoleKalendar::printEventList(QTextStream *ts, Event::List *eventList, QDate date) 0246 { 0247 bool status = true; 0248 0249 qCDebug(KONSOLEKALENDAR_LOG) << eventList->count(); 0250 if (!eventList->isEmpty()) { 0251 Event::Ptr singleEvent; 0252 Event::List::ConstIterator it; 0253 0254 for (it = eventList->constBegin(); it != eventList->constEnd() && status != false; ++it) { 0255 singleEvent = *it; 0256 0257 status = printEvent(ts, singleEvent, date); 0258 } 0259 } 0260 0261 return status; 0262 } 0263 0264 bool KonsoleKalendar::printEvent(QTextStream *ts, const Event::Ptr &event, QDate dt) 0265 { 0266 bool status = false; 0267 KonsoleKalendarExports exports; 0268 0269 if (event) { 0270 switch (m_variables->getExportType()) { 0271 case ExportTypeCSV: 0272 qCDebug(KONSOLEKALENDAR_LOG) << "konsolekalendar.cpp::printEvent() |" 0273 << "CSV export"; 0274 status = exports.exportAsCSV(ts, event, dt); 0275 break; 0276 0277 case ExportTypeTextShort: { 0278 qCDebug(KONSOLEKALENDAR_LOG) << "konsolekalendar.cpp::printEvent() |" 0279 << "TEXT-SHORT export"; 0280 bool sameDay = true; 0281 if (dt.daysTo(m_saveDate)) { 0282 sameDay = false; 0283 m_saveDate = dt; 0284 } 0285 status = exports.exportAsTxtShort(ts, event, dt, sameDay); 0286 } break; 0287 0288 default: // Default export-type is ExportTypeText 0289 qCDebug(KONSOLEKALENDAR_LOG) << "konsolekalendar.cpp::printEvent() |" 0290 << "TEXT export"; 0291 status = exports.exportAsTxt(ts, event, dt); 0292 break; 0293 } 0294 } 0295 return status; 0296 } 0297 0298 bool KonsoleKalendar::addEvent() 0299 { 0300 qCDebug(KONSOLEKALENDAR_LOG) << "konsolecalendar.cpp::addEvent() |" 0301 << "Create Adding"; 0302 KonsoleKalendarAdd add(m_variables); 0303 qCDebug(KONSOLEKALENDAR_LOG) << "konsolecalendar.cpp::addEvent() |" 0304 << "Adding Event now!"; 0305 return add.addEvent(); 0306 } 0307 0308 bool KonsoleKalendar::changeEvent() 0309 { 0310 qCDebug(KONSOLEKALENDAR_LOG) << "konsolecalendar.cpp::changeEvent() |" 0311 << "Create Changing"; 0312 KonsoleKalendarChange change(m_variables); 0313 qCDebug(KONSOLEKALENDAR_LOG) << "konsolecalendar.cpp::changeEvent() |" 0314 << "Changing Event now!"; 0315 return change.changeEvent(); 0316 } 0317 0318 bool KonsoleKalendar::deleteEvent() 0319 { 0320 qCDebug(KONSOLEKALENDAR_LOG) << "konsolecalendar.cpp::deleteEvent() |" 0321 << "Create Deleting"; 0322 KonsoleKalendarDelete del(m_variables); 0323 qCDebug(KONSOLEKALENDAR_LOG) << "konsolecalendar.cpp::deleteEvent() |" 0324 << "Deleting Event now!"; 0325 return del.deleteEvent(); 0326 } 0327 0328 bool KonsoleKalendar::isEvent(const QDateTime &startdate, const QDateTime &enddate, const QString &summary) 0329 { 0330 // Search for an event with specified start and end datetime stamp and summary 0331 0332 Event::Ptr event; 0333 Event::List::ConstIterator it; 0334 0335 bool found = false; 0336 0337 const auto timeZone = m_variables->getCalendar()->timeZone(); 0338 Event::List eventList(m_variables->getCalendar()->rawEventsForDate(startdate.date(), timeZone, EventSortStartDate, SortDirectionAscending)); 0339 for (it = eventList.constBegin(); it != eventList.constEnd(); ++it) { 0340 event = *it; 0341 if (event->dtEnd().toTimeZone(timeZone) == enddate && event->summary() == summary) { 0342 found = true; 0343 break; 0344 } 0345 } 0346 return found; 0347 } 0348 0349 void KonsoleKalendar::printSpecs() 0350 { 0351 cout << i18n(" What: %1", m_variables->getSummary()).toLocal8Bit().data() << endl; 0352 0353 cout << i18n(" Begin: %1", m_variables->getStartDateTime().toString(Qt::TextDate)).toLocal8Bit().data() << endl; 0354 0355 cout << i18n(" End: %1", m_variables->getEndDateTime().toString(Qt::TextDate)).toLocal8Bit().data() << endl; 0356 0357 if (m_variables->getFloating() == true) { 0358 cout << i18n(" No Time Associated with Event").toLocal8Bit().data() << endl; 0359 } 0360 0361 cout << i18n(" Desc: %1", m_variables->getDescription()).toLocal8Bit().data() << endl; 0362 0363 cout << i18n(" Location: %1", m_variables->getLocation()).toLocal8Bit().data() << endl; 0364 }