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("&nbsp;") + 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("&nbsp;") + 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("&nbsp;");
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("&nbsp;");
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 &regionStr : 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 &regionStr : 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 }