mirror of
https://bitbucket.org/smil3y/kde-playground.git
synced 2025-02-24 10:52:52 +00:00
251 lines
8.1 KiB
C++
251 lines
8.1 KiB
C++
/**
|
|
This file is part of the akonadi-calendar library.
|
|
|
|
Copyright (C) 2013 Sérgio Martins <iamsergio@gmail.com>
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Library General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Library General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public License
|
|
along with this library; see the file COPYING.LIB. If not, write to
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include "icalimporter.h"
|
|
#include "icalimporter_p.h"
|
|
#include "utils_p.h"
|
|
|
|
#include <akonadi/agentmanager.h>
|
|
#include <akonadi/agentinstancecreatejob.h>
|
|
|
|
#include <kcalcore/filestorage.h>
|
|
#include <kcalcore/memorycalendar.h>
|
|
#include <kcalcore/event.h>
|
|
#include <kcalcore/todo.h>
|
|
#include <kcalcore/journal.h>
|
|
|
|
#include <KJob>
|
|
#include <KLocalizedString>
|
|
#include <KDebug>
|
|
#include <KDateTime>
|
|
#include <KUrl>
|
|
#include <KIO/JobClasses>
|
|
#include <KIO/Scheduler>
|
|
#include <KTemporaryFile>
|
|
|
|
#include <QUrl>
|
|
#include <QFile>
|
|
#include <QDBusInterface>
|
|
|
|
using namespace KCalCore;
|
|
using namespace Akonadi;
|
|
|
|
ICalImporter::Private::Private(IncidenceChanger *changer,
|
|
ICalImporter *qq) : QObject(), q(qq)
|
|
, m_changer(changer)
|
|
, m_numIncidences(0)
|
|
, m_working(false)
|
|
, m_temporaryFile(0)
|
|
{
|
|
if (!changer) {
|
|
m_changer = new IncidenceChanger(q);
|
|
}
|
|
connect(m_changer, SIGNAL(createFinished(int,Akonadi::Item,Akonadi::IncidenceChanger::ResultCode,QString)),
|
|
SLOT(onIncidenceCreated(int,Akonadi::Item,Akonadi::IncidenceChanger::ResultCode,QString)));
|
|
|
|
}
|
|
|
|
ICalImporter::Private::~Private()
|
|
{
|
|
delete m_temporaryFile;
|
|
}
|
|
|
|
void ICalImporter::Private::onIncidenceCreated(int changeId,
|
|
const Akonadi::Item &,
|
|
Akonadi::IncidenceChanger::ResultCode resultCode,
|
|
const QString &errorString)
|
|
{
|
|
if (!m_pendingRequests.contains(changeId))
|
|
return; // Not ours
|
|
|
|
m_pendingRequests.removeAll(changeId);
|
|
|
|
if (resultCode != IncidenceChanger::ResultCodeSuccess) {
|
|
m_working = false;
|
|
setErrorMessage(errorString);
|
|
m_pendingRequests.clear();
|
|
emit q->importIntoExistingFinished(false, m_numIncidences);
|
|
} else if (m_pendingRequests.isEmpty()) {
|
|
m_working = false;
|
|
emit q->importIntoExistingFinished(true, m_numIncidences);
|
|
}
|
|
}
|
|
|
|
void ICalImporter::Private::setErrorMessage(const QString &message)
|
|
{
|
|
m_lastErrorMessage = message;
|
|
kError() << message;
|
|
}
|
|
|
|
void ICalImporter::Private::resourceCreated(KJob *job)
|
|
{
|
|
Akonadi::AgentInstanceCreateJob *createjob = qobject_cast<Akonadi::AgentInstanceCreateJob*>(job);
|
|
Q_ASSERT(createjob);
|
|
m_working = false;
|
|
if (createjob->error()) {
|
|
setErrorMessage(i18n("Error creating ical resource: %1", createjob->errorString()));
|
|
emit q->importIntoNewFinished(false);
|
|
return;
|
|
}
|
|
|
|
Akonadi::AgentInstance instance = createjob->instance();
|
|
QDBusInterface iface(QString::fromLatin1("org.freedesktop.Akonadi.Resource.%1").arg(instance.identifier()), QLatin1String("/Settings"));
|
|
|
|
if (!iface.isValid()) {
|
|
setErrorMessage(i18n("Failed to obtain D-Bus interface for remote configuration."));
|
|
emit q->importIntoNewFinished(false);
|
|
return;
|
|
}
|
|
|
|
const QString path = createjob->property("path").toString();
|
|
Q_ASSERT(!path.isEmpty());
|
|
|
|
iface.call(QLatin1String("setPath"), path);
|
|
instance.reconfigure();
|
|
|
|
emit q->importIntoNewFinished(true);
|
|
}
|
|
|
|
void ICalImporter::Private::remoteDownloadFinished(KIO::Job *job, const QByteArray &data)
|
|
{
|
|
const bool success = job->error() == 0;
|
|
m_working = false;
|
|
if (success) {
|
|
delete m_temporaryFile;
|
|
m_temporaryFile = new KTemporaryFile();
|
|
m_temporaryFile->write(data.constData(), data.count());
|
|
q->importIntoExistingResource(QUrl(m_temporaryFile->fileName()), m_collection);
|
|
} else {
|
|
setErrorMessage(i18n("Could not download remote file."));
|
|
emit q->importIntoExistingFinished(false, 0);
|
|
}
|
|
}
|
|
|
|
ICalImporter::ICalImporter(Akonadi::IncidenceChanger *changer,
|
|
QObject *parent) : QObject(parent)
|
|
, d(new Private(changer, this))
|
|
{
|
|
}
|
|
|
|
QString ICalImporter::errorMessage() const
|
|
{
|
|
return d->m_lastErrorMessage;
|
|
}
|
|
|
|
bool ICalImporter::importIntoNewResource(const QString &filename)
|
|
{
|
|
d->m_lastErrorMessage.clear();
|
|
|
|
if (d->m_working) {
|
|
d->setErrorMessage(i18n("An import task is already in progress."));
|
|
return false;
|
|
}
|
|
|
|
d->m_working = true;
|
|
|
|
Akonadi::AgentType type = Akonadi::AgentManager::self()->type(QLatin1String("akonadi_ical_resource"));
|
|
Akonadi::AgentInstanceCreateJob *job = new Akonadi::AgentInstanceCreateJob(type, this);
|
|
job->setProperty("path", filename);
|
|
connect(job, SIGNAL(result(KJob*)), d, SLOT(resourceCreated(KJob*)));
|
|
job->start();
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ICalImporter::importIntoExistingResource(const QUrl &url, Akonadi::Collection collection)
|
|
{
|
|
d->m_lastErrorMessage.clear();
|
|
|
|
if (d->m_working) {
|
|
d->setErrorMessage(i18n("An import task is already in progress."));
|
|
return false;
|
|
}
|
|
|
|
if (url.isEmpty()) {
|
|
d->setErrorMessage(i18n("Empty filename. Will not import ical file."));
|
|
return false;
|
|
}
|
|
|
|
if (!url.isValid()) {
|
|
d->setErrorMessage(i18n("Url to import is malformed."));
|
|
return false;
|
|
}
|
|
|
|
if (url.isLocalFile()) {
|
|
if (!QFile::exists(url.path())) {
|
|
d->setErrorMessage(i18n("The specified file doesn't exist, aborting import."));
|
|
return false;
|
|
}
|
|
MemoryCalendar::Ptr temporaryCalendar(new MemoryCalendar(KDateTime::LocalZone));
|
|
FileStorage storage(temporaryCalendar);
|
|
storage.setFileName(url.path());
|
|
bool success = storage.load();
|
|
if (!success) {
|
|
d->setErrorMessage(i18n("Failed to load ical file, check permissions."));
|
|
return false;
|
|
}
|
|
|
|
d->m_pendingRequests.clear();
|
|
Incidence::List incidences = temporaryCalendar->incidences();
|
|
|
|
if (incidences.isEmpty()) {
|
|
d->setErrorMessage(i18n("The ical file to merge is empty."));
|
|
return false;
|
|
}
|
|
|
|
if (!collection.isValid()) {
|
|
int dialogCode;
|
|
QStringList mimeTypes = QStringList() << KCalCore::Event::eventMimeType() << KCalCore::Todo::todoMimeType()
|
|
<< KCalCore::Journal::journalMimeType();
|
|
collection = CalendarUtils::selectCollection(0, dialogCode /*by-ref*/, mimeTypes);
|
|
}
|
|
|
|
if (!collection.isValid()) {
|
|
// user canceled
|
|
d->setErrorMessage(QString());
|
|
return false;
|
|
}
|
|
|
|
const IncidenceChanger::DestinationPolicy policySaved = d->m_changer->destinationPolicy();
|
|
d->m_changer->startAtomicOperation(i18n("Merge ical file into existing calendar."));
|
|
d->m_changer->setDestinationPolicy(IncidenceChanger::DestinationPolicyNeverAsk);
|
|
foreach(const Incidence::Ptr &incidence, incidences) {
|
|
Q_ASSERT(incidence);
|
|
if (!incidence)
|
|
continue;
|
|
const int requestId = d->m_changer->createIncidence(incidence, collection);
|
|
Q_ASSERT(requestId != -1); // -1 only happens with invalid incidences
|
|
if (requestId != -1)
|
|
d->m_pendingRequests << requestId;
|
|
}
|
|
d->m_changer->endAtomicOperation();
|
|
|
|
d->m_changer->setDestinationPolicy(policySaved); // restore
|
|
d->m_numIncidences = incidences.count();
|
|
} else {
|
|
d->m_collection = collection;
|
|
KIO::StoredTransferJob *job = KIO::storedGet(KUrl(url));
|
|
connect(job, SIGNAL(data(KIO::Job*,QByteArray)), d, SLOT(remoteDownloadFinished(KIO::Job*,QByteArray)));
|
|
}
|
|
|
|
d->m_working = true;
|
|
return true;
|
|
}
|