~ubuntu-branches/ubuntu/trusty/kdepimlibs/trusty

« back to all changes in this revision

Viewing changes to akonadi/calendar/icalimporter.cpp

  • Committer: Package Import Robot
  • Author(s): Rohan Garg, Rohan Garg, Philip Muškovac
  • Date: 2013-11-23 17:36:44 UTC
  • mfrom: (1.1.102)
  • Revision ID: package-import@ubuntu.com-20131123173644-p5ow94192ezsny8g
Tags: 4:4.11.80-0ubuntu1
[ Rohan Garg ]
* New upstream beta release
  - Bump akonadi requirement to 1.10.45
  - Update install files
  - Update symbols

[ Philip Muškovac ]
* kdepimlibs-dev/-dbg breaks/replaces kdepim-runtime/-dbg (<< 4:4.11.80)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
  This file is part of the akonadi-calendar library.
 
3
 
 
4
  Copyright (C) 2013 Sérgio Martins <iamsergio@gmail.com>
 
5
 
 
6
  This library is free software; you can redistribute it and/or
 
7
  modify it under the terms of the GNU Library General Public
 
8
  License as published by the Free Software Foundation; either
 
9
  version 2 of the License, or (at your option) any later version.
 
10
 
 
11
  This library is distributed in the hope that it will be useful,
 
12
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
14
  Library General Public License for more details.
 
15
 
 
16
  You should have received a copy of the GNU Library General Public License
 
17
  along with this library; see the file COPYING.LIB.  If not, write to
 
18
  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 
19
  Boston, MA 02110-1301, USA.
 
20
*/
 
21
 
 
22
#include "icalimporter.h"
 
23
#include "icalimporter_p.h"
 
24
#include "utils_p.h"
 
25
 
 
26
#include <akonadi/agentmanager.h>
 
27
#include <akonadi/agentinstancecreatejob.h>
 
28
 
 
29
#include <kcalcore/filestorage.h>
 
30
#include <kcalcore/memorycalendar.h>
 
31
#include <kcalcore/event.h>
 
32
#include <kcalcore/todo.h>
 
33
#include <kcalcore/journal.h>
 
34
 
 
35
#include <KJob>
 
36
#include <KLocale>
 
37
#include <KDebug>
 
38
#include <KDateTime>
 
39
#include <KUrl>
 
40
#include <KIO/JobClasses>
 
41
#include <KIO/Scheduler>
 
42
#include <KTemporaryFile>
 
43
 
 
44
#include <QUrl>
 
45
#include <QFile>
 
46
#include <QMetaObject>
 
47
#include <QDBusInterface>
 
48
 
 
49
using namespace KCalCore;
 
50
using namespace Akonadi;
 
51
 
 
52
ICalImporter::Private::Private(IncidenceChanger *changer,
 
53
                               ICalImporter *qq) : QObject(), q(qq)
 
54
                                                 , m_changer(changer)
 
55
                                                 , m_numIncidences(0)
 
56
                                                 , m_working(false)
 
57
                                                 , m_temporaryFile(0)
 
58
{
 
59
    if (!changer) {
 
60
        m_changer = new IncidenceChanger(q);
 
61
    }
 
62
    connect(m_changer, SIGNAL(createFinished(int,Akonadi::Item,Akonadi::IncidenceChanger::ResultCode,QString)),
 
63
                       SLOT(onIncidenceCreated(int,Akonadi::Item,Akonadi::IncidenceChanger::ResultCode,QString)) );
 
64
 
 
65
}
 
66
 
 
67
ICalImporter::Private::~Private()
 
68
{
 
69
    delete m_temporaryFile;
 
70
}
 
71
 
 
72
void ICalImporter::Private::onIncidenceCreated(int changeId,
 
73
                                               const Akonadi::Item &,
 
74
                                               Akonadi::IncidenceChanger::ResultCode resultCode,
 
75
                                               const QString &errorString)
 
76
{
 
77
    if (!m_pendingRequests.contains(changeId))
 
78
        return; // Not ours
 
79
 
 
80
    m_pendingRequests.removeAll(changeId);
 
81
 
 
82
    if (resultCode != IncidenceChanger::ResultCodeSuccess) {
 
83
        m_working = false;
 
84
        setErrorMessage(errorString);
 
85
        m_pendingRequests.clear();
 
86
        emit q->importIntoExistingFinished(false, m_numIncidences);
 
87
    } else if (m_pendingRequests.isEmpty()) {
 
88
        m_working = false;
 
89
        emit q->importIntoExistingFinished(true, m_numIncidences);
 
90
    }
 
91
}
 
92
 
 
93
void ICalImporter::Private::setErrorMessage(const QString &message)
 
94
{
 
95
    m_lastErrorMessage = message;
 
96
    kError() << message;
 
97
}
 
98
 
 
99
void ICalImporter::Private::resourceCreated(KJob *job)
 
100
{
 
101
    Akonadi::AgentInstanceCreateJob *createjob = qobject_cast<Akonadi::AgentInstanceCreateJob*>(job);
 
102
    Q_ASSERT(createjob);
 
103
    m_working = false;
 
104
    if (createjob->error()) {
 
105
        setErrorMessage(i18n("Error creating ical resource: %1", createjob->errorString()));
 
106
        emit q->importIntoNewFinished(false);
 
107
        return;
 
108
    }
 
109
 
 
110
    Akonadi::AgentInstance instance = createjob->instance();
 
111
    QDBusInterface iface(QString::fromLatin1("org.freedesktop.Akonadi.Resource.%1").arg(instance.identifier()), QLatin1String("/Settings"));
 
112
 
 
113
    if (!iface.isValid()) {
 
114
        setErrorMessage(i18n("Failed to obtain D-Bus interface for remote configuration."));
 
115
        emit q->importIntoNewFinished(false);
 
116
        return;
 
117
    }
 
118
 
 
119
    const QString path = createjob->property("path").toString();
 
120
    Q_ASSERT(!path.isEmpty());
 
121
 
 
122
    iface.call(QLatin1String("setPath"), path);
 
123
    instance.reconfigure();
 
124
 
 
125
    emit q->importIntoNewFinished(true);
 
126
}
 
127
 
 
128
void ICalImporter::Private::remoteDownloadFinished(KIO::Job *job, const QByteArray &data)
 
129
{
 
130
    const bool success = job->error() == 0;
 
131
    m_working = false;
 
132
    if (success) {
 
133
        delete m_temporaryFile;
 
134
        m_temporaryFile = new KTemporaryFile();
 
135
        m_temporaryFile->write(data.constData(), data.count());
 
136
        q->importIntoExistingResource(QUrl(m_temporaryFile->fileName()), m_collection);
 
137
    } else {
 
138
        setErrorMessage(i18n("Could not download remote file."));
 
139
        emit q->importIntoExistingFinished(false, 0);
 
140
    }
 
141
}
 
142
 
 
143
ICalImporter::ICalImporter(Akonadi::IncidenceChanger *changer,
 
144
                           QObject *parent) : QObject(parent)
 
145
                                            , d(new Private(changer, this))
 
146
{
 
147
}
 
148
 
 
149
QString ICalImporter::errorMessage() const
 
150
{
 
151
    return d->m_lastErrorMessage;
 
152
}
 
153
 
 
154
bool ICalImporter::importIntoNewResource(const QString &filename)
 
155
{
 
156
    d->m_lastErrorMessage.clear();
 
157
 
 
158
    if (d->m_working) {
 
159
        d->setErrorMessage(i18n("An import task is already in progress."));
 
160
        return false;
 
161
    }
 
162
 
 
163
    d->m_working = true;
 
164
 
 
165
    Akonadi::AgentType type = Akonadi::AgentManager::self()->type(QLatin1String("akonadi_ical_resource"));
 
166
    Akonadi::AgentInstanceCreateJob *job = new Akonadi::AgentInstanceCreateJob(type, this);
 
167
    job->setProperty("path", filename);
 
168
    connect(job, SIGNAL(result(KJob*)), d, SLOT(resourceCreated(KJob*)));
 
169
    job->start();
 
170
 
 
171
    return true;
 
172
}
 
173
 
 
174
bool ICalImporter::importIntoExistingResource(const QUrl &url, Akonadi::Collection collection)
 
175
{
 
176
    d->m_lastErrorMessage.clear();
 
177
 
 
178
    if (d->m_working) {
 
179
        d->setErrorMessage(i18n("An import task is already in progress."));
 
180
        return false;
 
181
    }
 
182
 
 
183
    if (url.isEmpty()) {
 
184
        d->setErrorMessage(i18n("Empty filename. Will not import ical file."));
 
185
        return false;
 
186
    }
 
187
 
 
188
    if (!url.isValid()) {
 
189
        d->setErrorMessage(i18n("Url to import is malformed."));
 
190
        return false;
 
191
    }
 
192
 
 
193
    if (url.isLocalFile()) {
 
194
        if (!QFile::exists(url.path())) {
 
195
            d->setErrorMessage(i18n("The specified file doesn't exist, aborting import."));
 
196
            return false;
 
197
        }
 
198
        MemoryCalendar::Ptr temporaryCalendar(new MemoryCalendar(KDateTime::LocalZone));
 
199
        FileStorage storage(temporaryCalendar);
 
200
        storage.setFileName(url.path());
 
201
        bool success = storage.load();
 
202
        if (!success) {
 
203
            d->setErrorMessage(i18n("Failed to load ical file, check permissions."));
 
204
            return false;
 
205
        }
 
206
 
 
207
        d->m_pendingRequests.clear();
 
208
        Incidence::List incidences = temporaryCalendar->incidences();
 
209
 
 
210
        if (incidences.isEmpty()) {
 
211
            d->setErrorMessage(i18n("The ical file to merge is empty."));
 
212
            return false;
 
213
        }
 
214
 
 
215
        if (!collection.isValid()) {
 
216
            int dialogCode;
 
217
            QStringList mimeTypes = QStringList() << KCalCore::Event::eventMimeType() << KCalCore::Todo::todoMimeType()
 
218
                                                  << KCalCore::Journal::journalMimeType();
 
219
            collection = CalendarUtils::selectCollection( 0, dialogCode /*by-ref*/, mimeTypes );
 
220
        }
 
221
 
 
222
        if (!collection.isValid()) {
 
223
            // user canceled
 
224
            d->setErrorMessage(QString());
 
225
            return false;
 
226
        }
 
227
 
 
228
        const IncidenceChanger::DestinationPolicy policySaved = d->m_changer->destinationPolicy();
 
229
        d->m_changer->startAtomicOperation(i18n("Merge ical file into existing calendar."));
 
230
        d->m_changer->setDestinationPolicy(IncidenceChanger::DestinationPolicyNeverAsk);
 
231
        foreach (const Incidence::Ptr &incidence, incidences) {
 
232
            Q_ASSERT(incidence);
 
233
            if (!incidence)
 
234
                continue;
 
235
            const int requestId = d->m_changer->createIncidence(incidence, collection);
 
236
            Q_ASSERT(requestId != -1); // -1 only happens with invalid incidences
 
237
            if (requestId != -1)
 
238
                d->m_pendingRequests << requestId;
 
239
        }
 
240
        d->m_changer->endAtomicOperation();
 
241
 
 
242
        d->m_changer->setDestinationPolicy(policySaved); // restore
 
243
        d->m_numIncidences = incidences.count();
 
244
    } else {
 
245
        d->m_collection = collection;
 
246
        KIO::StoredTransferJob *job = KIO::storedGet(KUrl(url));
 
247
        connect(job, SIGNAL(data(KIO::Job*,QByteArray)), d, SLOT(remoteDownloadFinished(KIO::Job*,QByteArray)));
 
248
    }
 
249
 
 
250
    d->m_working = true;
 
251
    return true;
 
252
}