File indexing completed on 2024-05-12 05:13:15
0001 /* 0002 SPDX-FileCopyrightText: 2009, 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com> 0003 SPDX-FileContributor: Frank Osterfeld <osterfeld@kde.org> 0004 SPDX-FileContributor: Andras Mantia <andras@kdab.com> 0005 0006 SPDX-License-Identifier: GPL-2.0-or-later WITH Qt-Commercial-exception-1.0 0007 */ 0008 0009 #include "utils.h" 0010 #include "calendarsupport_debug.h" 0011 #include "kcalprefs.h" 0012 0013 #include <Akonadi/AgentInstance> 0014 #include <Akonadi/AgentManager> 0015 #include <Akonadi/CalendarUtils> 0016 #include <Akonadi/CollectionUtils> 0017 #include <Akonadi/EntityDisplayAttribute> 0018 #include <Akonadi/EntityTreeModel> 0019 0020 #include <Akonadi/CollectionDialog> 0021 0022 #include <Akonadi/BlockAlarmsAttribute> 0023 #include <Akonadi/ETMCalendar> 0024 0025 #include <KHolidays/HolidayRegion> 0026 0027 #include <KCalendarCore/CalFilter> 0028 #include <KCalendarCore/FileStorage> 0029 #include <KCalendarCore/FreeBusy> 0030 #include <KCalendarCore/MemoryCalendar> 0031 0032 #include <KCalUtils/DndFactory> 0033 #include <KCalUtils/ICalDrag> 0034 #include <KCalUtils/VCalDrag> 0035 0036 #include <KLocalizedString> 0037 0038 #include <QApplication> 0039 #include <QDrag> 0040 #include <QFile> 0041 #include <QMimeData> 0042 #include <QPointer> 0043 #include <QStyle> 0044 #include <QUrlQuery> 0045 0046 KCalendarCore::Event::Ptr CalendarSupport::event(const KCalendarCore::Incidence::Ptr &incidence) 0047 { 0048 if (hasEvent(incidence)) { 0049 return incidence.staticCast<KCalendarCore::Event>(); 0050 } 0051 return {}; 0052 } 0053 0054 KCalendarCore::Incidence::List CalendarSupport::incidencesFromItems(const Akonadi::Item::List &items) 0055 { 0056 KCalendarCore::Incidence::List incidences; 0057 for (const Akonadi::Item &item : items) { 0058 if (const KCalendarCore::Incidence::Ptr e = Akonadi::CalendarUtils::incidence(item)) { 0059 incidences.push_back(e); 0060 } 0061 } 0062 return incidences; 0063 } 0064 0065 KCalendarCore::Todo::Ptr CalendarSupport::todo(const KCalendarCore::Incidence::Ptr &incidence) 0066 { 0067 if (hasTodo(incidence)) { 0068 return incidence.staticCast<KCalendarCore::Todo>(); 0069 } 0070 return {}; 0071 } 0072 0073 KCalendarCore::Journal::Ptr CalendarSupport::journal(const KCalendarCore::Incidence::Ptr &incidence) 0074 { 0075 if (hasJournal(incidence)) { 0076 return incidence.staticCast<KCalendarCore::Journal>(); 0077 } 0078 return {}; 0079 } 0080 0081 bool CalendarSupport::hasIncidence(const Akonadi::Item &item) 0082 { 0083 return item.hasPayload<KCalendarCore::Incidence::Ptr>(); 0084 } 0085 0086 bool CalendarSupport::hasEvent(const Akonadi::Item &item) 0087 { 0088 return item.hasPayload<KCalendarCore::Event::Ptr>(); 0089 } 0090 0091 bool CalendarSupport::hasEvent(const KCalendarCore::Incidence::Ptr &incidence) 0092 { 0093 return incidence && incidence->type() == KCalendarCore::Incidence::TypeEvent; 0094 } 0095 0096 bool CalendarSupport::hasTodo(const Akonadi::Item &item) 0097 { 0098 return item.hasPayload<KCalendarCore::Todo::Ptr>(); 0099 } 0100 0101 bool CalendarSupport::hasTodo(const KCalendarCore::Incidence::Ptr &incidence) 0102 { 0103 return incidence && incidence->type() == KCalendarCore::Incidence::TypeTodo; 0104 } 0105 0106 bool CalendarSupport::hasJournal(const Akonadi::Item &item) 0107 { 0108 return item.hasPayload<KCalendarCore::Journal::Ptr>(); 0109 } 0110 0111 bool CalendarSupport::hasJournal(const KCalendarCore::Incidence::Ptr &incidence) 0112 { 0113 return incidence && incidence->type() == KCalendarCore::Incidence::TypeJournal; 0114 } 0115 0116 #ifndef QT_NO_DRAGANDDROP 0117 QDrag *CalendarSupport::createDrag(const Akonadi::Item &item, QObject *parent) 0118 { 0119 return createDrag(Akonadi::Item::List() << item, parent); 0120 } 0121 0122 #endif 0123 0124 static KCalendarCore::IncidenceBase::IncidenceType findMostCommonType(const Akonadi::Item::List &items) 0125 { 0126 KCalendarCore::IncidenceBase::IncidenceType prev = KCalendarCore::IncidenceBase::TypeUnknown; 0127 for (const Akonadi::Item &item : items) { 0128 if (!CalendarSupport::hasIncidence(item)) { 0129 continue; 0130 } 0131 const auto type = Akonadi::CalendarUtils::incidence(item)->type(); 0132 if (prev != KCalendarCore::IncidenceBase::TypeUnknown && type != prev) { 0133 return KCalendarCore::IncidenceBase::TypeUnknown; 0134 } 0135 prev = type; 0136 } 0137 return prev; 0138 } 0139 0140 #ifndef QT_NO_DRAGANDDROP 0141 QDrag *CalendarSupport::createDrag(const Akonadi::Item::List &items, QObject *parent) 0142 { 0143 std::unique_ptr<QDrag> drag(new QDrag(parent)); 0144 drag->setMimeData(Akonadi::CalendarUtils::createMimeData(items)); 0145 0146 const auto common = findMostCommonType(items); 0147 if (common == KCalendarCore::IncidenceBase::TypeEvent) { 0148 drag->setPixmap(QIcon::fromTheme(QStringLiteral("view-calendar-day")).pixmap(qApp->style()->pixelMetric(QStyle::PM_ToolBarIconSize))); 0149 } else if (common == KCalendarCore::IncidenceBase::TypeTodo) { 0150 drag->setPixmap(QIcon::fromTheme(QStringLiteral("view-calendar-tasks")).pixmap(qApp->style()->pixelMetric(QStyle::PM_ToolBarIconSize))); 0151 } 0152 0153 return drag.release(); 0154 } 0155 0156 #endif 0157 0158 static bool itemMatches(const Akonadi::Item &item, const KCalendarCore::CalFilter *filter) 0159 { 0160 assert(filter); 0161 KCalendarCore::Incidence::Ptr inc = Akonadi::CalendarUtils::incidence(item); 0162 if (!inc) { 0163 return false; 0164 } 0165 return filter->filterIncidence(inc); 0166 } 0167 0168 Akonadi::Item::List CalendarSupport::applyCalFilter(const Akonadi::Item::List &items_, const KCalendarCore::CalFilter *filter) 0169 { 0170 Q_ASSERT(filter); 0171 Akonadi::Item::List items(items_); 0172 items.erase(std::remove_if(items.begin(), 0173 items.end(), 0174 [filter](const Akonadi::Item &item) { 0175 return !itemMatches(item, filter); 0176 }), 0177 items.end()); 0178 return items; 0179 } 0180 0181 bool CalendarSupport::isValidIncidenceItemUrl(const QUrl &url, const QStringList &supportedMimeTypes) 0182 { 0183 if (!url.isValid()) { 0184 return false; 0185 } 0186 0187 if (url.scheme() != QLatin1StringView("akonadi")) { 0188 return false; 0189 } 0190 0191 return supportedMimeTypes.contains(QUrlQuery(url).queryItemValue(QStringLiteral("type"))); 0192 } 0193 0194 bool CalendarSupport::isValidIncidenceItemUrl(const QUrl &url) 0195 { 0196 return isValidIncidenceItemUrl(url, 0197 QStringList() << KCalendarCore::Event::eventMimeType() << KCalendarCore::Todo::todoMimeType() 0198 << KCalendarCore::Journal::journalMimeType() << KCalendarCore::FreeBusy::freeBusyMimeType()); 0199 } 0200 0201 static bool containsValidIncidenceItemUrl(const QList<QUrl> &urls) 0202 { 0203 return std::find_if(urls.begin(), 0204 urls.end(), 0205 [](const QUrl &url) { 0206 return CalendarSupport::isValidIncidenceItemUrl(url); 0207 }) 0208 != urls.constEnd(); 0209 } 0210 0211 bool CalendarSupport::canDecode(const QMimeData *md) 0212 { 0213 if (md) { 0214 return containsValidIncidenceItemUrl(md->urls()) || KCalUtils::ICalDrag::canDecode(md) || KCalUtils::VCalDrag::canDecode(md); 0215 } else { 0216 return false; 0217 } 0218 } 0219 0220 QList<QUrl> CalendarSupport::incidenceItemUrls(const QMimeData *mimeData) 0221 { 0222 QList<QUrl> urls; 0223 const QList<QUrl> urlsList = mimeData->urls(); 0224 for (const QUrl &i : urlsList) { 0225 if (isValidIncidenceItemUrl(i)) { 0226 urls.push_back(i); 0227 } 0228 } 0229 return urls; 0230 } 0231 0232 QList<QUrl> CalendarSupport::todoItemUrls(const QMimeData *mimeData) 0233 { 0234 QList<QUrl> urls; 0235 0236 const QList<QUrl> urlList = mimeData->urls(); 0237 for (const QUrl &i : urlList) { 0238 if (isValidIncidenceItemUrl(i, QStringList() << KCalendarCore::Todo::todoMimeType())) { 0239 urls.push_back(i); 0240 } 0241 } 0242 return urls; 0243 } 0244 0245 bool CalendarSupport::mimeDataHasIncidence(const QMimeData *mimeData) 0246 { 0247 return !incidenceItemUrls(mimeData).isEmpty() || !incidences(mimeData).isEmpty(); 0248 } 0249 0250 KCalendarCore::Todo::List CalendarSupport::todos(const QMimeData *mimeData) 0251 { 0252 KCalendarCore::Todo::List todos; 0253 0254 #ifndef QT_NO_DRAGANDDROP 0255 KCalendarCore::Calendar::Ptr cal(KCalUtils::DndFactory::createDropCalendar(mimeData)); 0256 if (cal) { 0257 const KCalendarCore::Todo::List calTodos = cal->todos(); 0258 todos.reserve(calTodos.count()); 0259 for (const KCalendarCore::Todo::Ptr &i : calTodos) { 0260 todos.push_back(KCalendarCore::Todo::Ptr(i->clone())); 0261 } 0262 } 0263 #endif 0264 0265 return todos; 0266 } 0267 0268 KCalendarCore::Incidence::List CalendarSupport::incidences(const QMimeData *mimeData) 0269 { 0270 KCalendarCore::Incidence::List incidences; 0271 0272 #ifndef QT_NO_DRAGANDDROP 0273 KCalendarCore::Calendar::Ptr cal(KCalUtils::DndFactory::createDropCalendar(mimeData)); 0274 if (cal) { 0275 const KCalendarCore::Incidence::List calIncidences = cal->incidences(); 0276 incidences.reserve(calIncidences.count()); 0277 for (const KCalendarCore::Incidence::Ptr &i : calIncidences) { 0278 incidences.push_back(KCalendarCore::Incidence::Ptr(i->clone())); 0279 } 0280 } 0281 #endif 0282 0283 return incidences; 0284 } 0285 0286 Akonadi::Collection CalendarSupport::selectCollection(QWidget *parent, int &dialogCode, const QStringList &mimeTypes, const Akonadi::Collection &defCollection) 0287 { 0288 QPointer<Akonadi::CollectionDialog> dlg(new Akonadi::CollectionDialog(parent)); 0289 dlg->setWindowTitle(i18nc("@title:window", "Select Calendar")); 0290 dlg->setDescription(i18n("Select the calendar where this item will be stored.")); 0291 dlg->changeCollectionDialogOptions(Akonadi::CollectionDialog::KeepTreeExpanded); 0292 qCDebug(CALENDARSUPPORT_LOG) << "selecting collections with mimeType in " << mimeTypes; 0293 0294 dlg->setMimeTypeFilter(mimeTypes); 0295 dlg->setAccessRightsFilter(Akonadi::Collection::CanCreateItem); 0296 if (defCollection.isValid()) { 0297 dlg->setDefaultCollection(defCollection); 0298 } 0299 Akonadi::Collection collection; 0300 0301 // FIXME: don't use exec. 0302 dialogCode = dlg->exec(); 0303 if (dlg && dialogCode == QDialog::Accepted) { 0304 collection = dlg->selectedCollection(); 0305 0306 if (!collection.isValid()) { 0307 qCWarning(CALENDARSUPPORT_LOG) << "An invalid collection was selected!"; 0308 } 0309 } 0310 delete dlg; 0311 return collection; 0312 } 0313 0314 Akonadi::Item CalendarSupport::itemFromIndex(const QModelIndex &idx) 0315 { 0316 auto item = idx.data(Akonadi::EntityTreeModel::ItemRole).value<Akonadi::Item>(); 0317 item.setParentCollection(idx.data(Akonadi::EntityTreeModel::ParentCollectionRole).value<Akonadi::Collection>()); 0318 return item; 0319 } 0320 0321 Akonadi::Collection::List CalendarSupport::collectionsFromModel(const QAbstractItemModel *model, const QModelIndex &parentIndex, int start, int end) 0322 { 0323 const int endRow = end >= 0 ? end : model->rowCount(parentIndex) - 1; 0324 Akonadi::Collection::List collections; 0325 int row = start; 0326 QModelIndex i = model->index(row, 0, parentIndex); 0327 while (row <= endRow) { 0328 const Akonadi::Collection collection = Akonadi::CollectionUtils::fromIndex(i); 0329 if (collection.isValid()) { 0330 collections << collection; 0331 QModelIndex childIndex = model->index(0, 0, i); 0332 if (childIndex.isValid()) { 0333 collections << collectionsFromModel(model, i); 0334 } 0335 } 0336 ++row; 0337 i = i.sibling(row, 0); 0338 } 0339 return collections; 0340 } 0341 0342 Akonadi::Item::List CalendarSupport::itemsFromModel(const QAbstractItemModel *model, const QModelIndex &parentIndex, int start, int end) 0343 { 0344 const int endRow = end >= 0 ? end : model->rowCount(parentIndex) - 1; 0345 Akonadi::Item::List items; 0346 int row = start; 0347 QModelIndex i = model->index(row, 0, parentIndex); 0348 while (row <= endRow) { 0349 const Akonadi::Item item = itemFromIndex(i); 0350 if (CalendarSupport::hasIncidence(item)) { 0351 items << item; 0352 } else { 0353 QModelIndex childIndex = model->index(0, 0, i); 0354 if (childIndex.isValid()) { 0355 items << itemsFromModel(model, i); 0356 } 0357 } 0358 ++row; 0359 i = i.sibling(row, 0); 0360 } 0361 return items; 0362 } 0363 0364 Akonadi::Collection::Id CalendarSupport::collectionIdFromIndex(const QModelIndex &index) 0365 { 0366 return index.data(Akonadi::EntityTreeModel::CollectionIdRole).value<Akonadi::Collection::Id>(); 0367 } 0368 0369 Akonadi::Collection::List CalendarSupport::collectionsFromIndexes(const QModelIndexList &indexes) 0370 { 0371 Akonadi::Collection::List l; 0372 l.reserve(indexes.count()); 0373 for (const QModelIndex &idx : indexes) { 0374 l.push_back(Akonadi::CollectionUtils::fromIndex(idx)); 0375 } 0376 return l; 0377 } 0378 0379 QString CalendarSupport::toolTipString(const Akonadi::Collection &coll, bool richText) 0380 { 0381 Q_UNUSED(richText) 0382 0383 QString str = QStringLiteral("<qt>"); 0384 0385 // Display Name 0386 QString displayName; 0387 if (coll.hasAttribute<Akonadi::EntityDisplayAttribute>()) { 0388 displayName = coll.attribute<Akonadi::EntityDisplayAttribute>()->displayName(); 0389 } 0390 0391 if (displayName.isEmpty()) { 0392 displayName = coll.name(); 0393 } 0394 if (coll.id() == CalendarSupport::KCalPrefs::instance()->defaultCalendarId()) { 0395 displayName = i18nc("this is the default calendar", "%1 (Default Calendar)", displayName); 0396 } 0397 str += QLatin1StringView("<b>") + displayName + QLatin1StringView("</b>"); 0398 str += QLatin1StringView("<hr>"); 0399 0400 // Calendar Type 0401 QString calendarType; 0402 if (!coll.isVirtual()) { 0403 const Akonadi::AgentInstance instance = Akonadi::AgentManager::self()->instance(coll.resource()); 0404 calendarType = instance.type().name(); 0405 } else { 0406 calendarType = i18nc("a virtual folder type", "Virtual"); 0407 } 0408 str += QLatin1StringView("<i>") + i18n("Folder type:") + QLatin1StringView("</i>"); 0409 str += QLatin1StringView(" ") + calendarType; 0410 0411 // Content Type 0412 QStringList mimeTypes = coll.contentMimeTypes(); 0413 mimeTypes.removeAll(QStringLiteral("inode/directory")); 0414 QString mimeTypeStr; 0415 if (!mimeTypes.isEmpty()) { 0416 mimeTypeStr = QLocale().createSeparatedList(mimeTypes.replaceInStrings(QStringLiteral("application/x-vnd.akonadi.calendar."), QString())); 0417 } else { 0418 mimeTypeStr = i18nc("collection has no mimetypes to show the user", "none"); 0419 } 0420 str += QLatin1StringView("<br>"); 0421 str += QLatin1StringView("<i>") + i18n("Content type:") + QLatin1StringView("</i>"); 0422 str += QLatin1StringView(" ") + mimeTypeStr; 0423 str += QLatin1StringView("</br>"); 0424 0425 // Read only? 0426 bool isReadOnly = !(coll.rights() & Akonadi::Collection::CanChangeItem); 0427 str += QLatin1StringView("<br>"); 0428 str += QLatin1StringView("<i>") + i18n("Rights:") + QLatin1StringView("</i>"); 0429 str += QLatin1StringView(" "); 0430 if (isReadOnly) { 0431 str += i18nc("the calendar is read-only", "read-only"); 0432 } else { 0433 str += i18nc("the calendar is read and write", "read+write"); 0434 } 0435 str += QLatin1StringView("</br>"); 0436 0437 // Blocking reminders? 0438 QStringList blockList; 0439 if (coll.hasAttribute<Akonadi::BlockAlarmsAttribute>()) { 0440 if (coll.attribute<Akonadi::BlockAlarmsAttribute>()->isEverythingBlocked()) { 0441 blockList << i18nc("blocking all reminders for this calendar", "all"); 0442 } else { 0443 if (coll.attribute<Akonadi::BlockAlarmsAttribute>()->isAlarmTypeBlocked(KCalendarCore::Alarm::Audio)) { 0444 blockList << i18nc("blocking audio reminders for this calendar", "audio"); 0445 } else if (coll.attribute<Akonadi::BlockAlarmsAttribute>()->isAlarmTypeBlocked(KCalendarCore::Alarm::Display)) { 0446 blockList << i18nc("blocking display pop-up dialog reminders for this calendar", "display"); 0447 } else if (coll.attribute<Akonadi::BlockAlarmsAttribute>()->isAlarmTypeBlocked(KCalendarCore::Alarm::Email)) { 0448 blockList << i18nc("blocking email reminders for this calendar", "email"); 0449 } else if (coll.attribute<Akonadi::BlockAlarmsAttribute>()->isAlarmTypeBlocked(KCalendarCore::Alarm::Procedure)) { 0450 blockList << i18nc("blocking run a command reminders for this calendar", "procedure"); 0451 } else { 0452 blockList << i18nc("blocking unknown type reminders for this calendar", "other"); 0453 } 0454 } 0455 } else { 0456 blockList << i18nc("not blocking any reminder types for this calendar", "none"); 0457 } 0458 str += QLatin1StringView("<br>"); 0459 str += QLatin1StringView("<i>") + i18n("Blocked Reminders:") + QLatin1StringView("</i>"); 0460 str += QLatin1StringView(" "); 0461 str += QLocale().createSeparatedList(blockList); 0462 str += QLatin1StringView("</br>"); 0463 0464 str += QLatin1StringView("</qt>"); 0465 return str; 0466 } 0467 0468 QString CalendarSupport::subMimeTypeForIncidence(const KCalendarCore::Incidence::Ptr &incidence) 0469 { 0470 return incidence->mimeType(); 0471 } 0472 0473 QList<QDate> CalendarSupport::workDays(QDate startDate, QDate endDate) 0474 { 0475 QList<QDate> result; 0476 0477 const int mask(~(KCalPrefs::instance()->mWorkWeekMask)); 0478 const int numDays = startDate.daysTo(endDate) + 1; 0479 0480 for (int i = 0; i < numDays; ++i) { 0481 const QDate date = startDate.addDays(i); 0482 if (!(mask & (1 << (date.dayOfWeek() - 1)))) { 0483 result.append(date); 0484 } 0485 } 0486 0487 if (KCalPrefs::instance()->mExcludeHolidays) { 0488 const QStringList holidays = KCalPrefs::instance()->mHolidays; 0489 for (const QString ®ionStr : holidays) { 0490 KHolidays::HolidayRegion region(regionStr); 0491 if (region.isValid()) { 0492 for (auto const &h : region.rawHolidaysWithAstroSeasons(startDate, endDate)) { 0493 if (h.dayType() == KHolidays::Holiday::NonWorkday) { 0494 for (int i = 0; i < h.duration(); i++) { 0495 result.removeOne(h.observedStartDate().addDays(i)); 0496 } 0497 } 0498 } 0499 } 0500 } 0501 } 0502 0503 return result; 0504 } 0505 0506 QStringList CalendarSupport::holiday(QDate date) 0507 { 0508 QStringList hdays; 0509 0510 bool showCountryCode = (KCalPrefs::instance()->mHolidays.count() > 1); 0511 const QStringList holidays = KCalPrefs::instance()->mHolidays; 0512 for (const QString ®ionStr : holidays) { 0513 KHolidays::HolidayRegion region(regionStr); 0514 if (region.isValid()) { 0515 const KHolidays::Holiday::List list = region.rawHolidaysWithAstroSeasons(date); 0516 const int listCount = list.count(); 0517 for (int i = 0; i < listCount; ++i) { 0518 // don't add duplicates. 0519 // TODO: won't find duplicates in different languages however. 0520 const QString name = list.at(i).name(); 0521 if (showCountryCode) { 0522 // If more than one holiday region, append the country code to the holiday 0523 // display name to help the user identify which region it belongs to. 0524 const QRegularExpression holidaySE(i18nc("search pattern for holidayname", "^%1", name)); 0525 if (hdays.filter(holidaySE).isEmpty()) { 0526 const QString pholiday = i18n("%1 (%2)", name, region.countryCode()); 0527 hdays.append(pholiday); 0528 } else { 0529 // More than 1 region has the same holiday => remove the country code 0530 // i.e don't show "Holiday (US)" and "Holiday(FR)"; just show "Holiday". 0531 const QRegularExpression holidayRE(i18nc("replace pattern for holidayname (countrycode)", "^%1 \\(.*\\)", name)); 0532 hdays.replaceInStrings(holidayRE, name); 0533 hdays.removeDuplicates(); 0534 } 0535 } else { 0536 if (!hdays.contains(name)) { 0537 hdays.append(name); 0538 } 0539 } 0540 } 0541 } 0542 } 0543 0544 return hdays; 0545 } 0546 0547 QStringList CalendarSupport::categories(const KCalendarCore::Incidence::List &incidences) 0548 { 0549 QStringList cats; 0550 QStringList thisCats; 0551 // @TODO: For now just iterate over all incidences. In the future, 0552 // the list of categories should be built when reading the file. 0553 for (const KCalendarCore::Incidence::Ptr &incidence : incidences) { 0554 thisCats = incidence->categories(); 0555 const QStringList::ConstIterator send(thisCats.constEnd()); 0556 for (QStringList::ConstIterator si = thisCats.constBegin(); si != send; ++si) { 0557 if (!cats.contains(*si)) { 0558 cats.append(*si); 0559 } 0560 } 0561 } 0562 return cats; 0563 } 0564 0565 bool CalendarSupport::mergeCalendar(const QString &srcFilename, const KCalendarCore::Calendar::Ptr &destCalendar) 0566 { 0567 if (srcFilename.isEmpty()) { 0568 qCCritical(CALENDARSUPPORT_LOG) << "Empty filename."; 0569 return false; 0570 } 0571 0572 if (!QFile::exists(srcFilename)) { 0573 qCCritical(CALENDARSUPPORT_LOG) << "File'" << srcFilename << "' doesn't exist."; 0574 } 0575 0576 // merge in a file 0577 destCalendar->startBatchAdding(); 0578 KCalendarCore::FileStorage storage(destCalendar); 0579 storage.setFileName(srcFilename); 0580 bool loadedSuccesfully = storage.load(); 0581 destCalendar->endBatchAdding(); 0582 0583 return loadedSuccesfully; 0584 } 0585 0586 void CalendarSupport::createAlarmReminder(const KCalendarCore::Alarm::Ptr &alarm, KCalendarCore::IncidenceBase::IncidenceType type) 0587 { 0588 int duration; // in secs 0589 switch (CalendarSupport::KCalPrefs::instance()->mReminderTimeUnits) { 0590 default: 0591 case 0: // mins 0592 duration = CalendarSupport::KCalPrefs::instance()->mReminderTime * 60; 0593 break; 0594 case 1: // hours 0595 duration = CalendarSupport::KCalPrefs::instance()->mReminderTime * 60 * 60; 0596 break; 0597 case 2: // days 0598 duration = CalendarSupport::KCalPrefs::instance()->mReminderTime * 60 * 60 * 24; 0599 break; 0600 } 0601 alarm->setType(KCalendarCore::Alarm::Display); 0602 alarm->setEnabled(true); 0603 if (type == KCalendarCore::Incidence::TypeEvent) { 0604 alarm->setStartOffset(KCalendarCore::Duration(-duration)); 0605 } else { 0606 alarm->setEndOffset(KCalendarCore::Duration(-duration)); 0607 } 0608 }