1 | /* |
2 | Copyright (c) 2007 Volker Krause <vkrause@kde.org> |
3 | |
4 | This library is free software; you can redistribute it and/or modify it |
5 | under the terms of the GNU Library General Public License as published by |
6 | the Free Software Foundation; either version 2 of the License, or (at your |
7 | option) any later version. |
8 | |
9 | This library is distributed in the hope that it will be useful, but WITHOUT |
10 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
11 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public |
12 | License for more details. |
13 | |
14 | You should have received a copy of the GNU Library General Public License |
15 | along with this library; see the file COPYING.LIB. If not, write to the |
16 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
17 | 02110-1301, USA. |
18 | */ |
19 | |
20 | #include "collectionpathresolver_p.h" |
21 | |
22 | #include "collectionfetchjob.h" |
23 | #include "job_p.h" |
24 | |
25 | #include <klocalizedstring.h> |
26 | |
27 | #include <QtCore/QStringList> |
28 | |
29 | using namespace Akonadi; |
30 | |
31 | //@cond PRIVATE |
32 | |
33 | class Akonadi::CollectionPathResolverPrivate : public JobPrivate |
34 | { |
35 | public: |
36 | CollectionPathResolverPrivate(CollectionPathResolver *parent) |
37 | : JobPrivate(parent) |
38 | , mColId(-1) |
39 | { |
40 | } |
41 | |
42 | void init(const QString &path, const Collection &rootCollection) |
43 | { |
44 | Q_Q(CollectionPathResolver); |
45 | |
46 | mPathToId = true; |
47 | mPath = path; |
48 | if (mPath.startsWith(q->pathDelimiter())) { |
49 | mPath = mPath.right(mPath.length() - q->pathDelimiter().length()); |
50 | } |
51 | if (mPath.endsWith(q->pathDelimiter())) { |
52 | mPath = mPath.left(mPath.length() - q->pathDelimiter().length()); |
53 | } |
54 | |
55 | mPathParts = splitPath(mPath); |
56 | mCurrentNode = rootCollection; |
57 | } |
58 | |
59 | void jobResult(KJob *); |
60 | |
61 | QStringList splitPath(const QString &path) |
62 | { |
63 | if (path.isEmpty()) { // path is normalized, so non-empty means at least one hit |
64 | return QStringList(); |
65 | } |
66 | |
67 | QStringList rv; |
68 | int begin = 0; |
69 | const int pathSize(path.size()); |
70 | for (int i = 0; i < pathSize; ++i) { |
71 | if (path[i] == QLatin1Char('/')) { |
72 | QString pathElement = path.mid(begin, i - begin); |
73 | pathElement = pathElement.replace(QLatin1String("\\/" ), QLatin1String("/" )); |
74 | rv.append(pathElement); |
75 | begin = i + 1; |
76 | } |
77 | if (i < path.size() - 2 && path[i] == QLatin1Char('\\') && path[i + 1] == QLatin1Char('/')) { |
78 | ++i; |
79 | } |
80 | } |
81 | QString pathElement = path.mid(begin); |
82 | pathElement = pathElement.replace(QLatin1String("\\/" ), QLatin1String("/" )); |
83 | rv.append(pathElement); |
84 | return rv; |
85 | } |
86 | |
87 | Q_DECLARE_PUBLIC(CollectionPathResolver) |
88 | |
89 | Collection::Id mColId; |
90 | QString mPath; |
91 | bool mPathToId; |
92 | QStringList mPathParts; |
93 | Collection mCurrentNode; |
94 | }; |
95 | |
96 | void CollectionPathResolverPrivate::jobResult(KJob *job) |
97 | { |
98 | if (job->error()) { |
99 | return; |
100 | } |
101 | |
102 | Q_Q(CollectionPathResolver); |
103 | |
104 | CollectionFetchJob *list = static_cast<CollectionFetchJob *>(job); |
105 | CollectionFetchJob *nextJob = 0; |
106 | const Collection::List cols = list->collections(); |
107 | if (cols.isEmpty()) { |
108 | mColId = -1; |
109 | q->setError(CollectionPathResolver::Unknown); |
110 | q->setErrorText(i18n("No such collection." )); |
111 | q->emitResult(); |
112 | return; |
113 | } |
114 | |
115 | if (mPathToId) { |
116 | const QString currentPart = mPathParts.takeFirst(); |
117 | bool found = false; |
118 | foreach (const Collection &c, cols) { |
119 | if (c.name() == currentPart) { |
120 | mCurrentNode = c; |
121 | found = true; |
122 | break; |
123 | } |
124 | } |
125 | if (!found) { |
126 | kWarning() << "No such collection" << currentPart << "with parent" << mCurrentNode.id(); |
127 | mColId = -1; |
128 | q->setError(CollectionPathResolver::Unknown); |
129 | q->setErrorText(i18n("No such collection." )); |
130 | q->emitResult(); |
131 | return; |
132 | } |
133 | if (mPathParts.isEmpty()) { |
134 | mColId = mCurrentNode.id(); |
135 | q->emitResult(); |
136 | return; |
137 | } |
138 | nextJob = new CollectionFetchJob(mCurrentNode, CollectionFetchJob::FirstLevel, q); |
139 | } else { |
140 | Collection col = list->collections().first(); |
141 | mCurrentNode = col.parentCollection(); |
142 | mPathParts.prepend(col.name()); |
143 | if (mCurrentNode == Collection::root()) { |
144 | q->emitResult(); |
145 | return; |
146 | } |
147 | nextJob = new CollectionFetchJob(mCurrentNode, CollectionFetchJob::Base, q); |
148 | } |
149 | q->connect(nextJob, SIGNAL(result(KJob*)), q, SLOT(jobResult(KJob*))); |
150 | } |
151 | |
152 | CollectionPathResolver::CollectionPathResolver(const QString &path, QObject *parent) |
153 | : Job(new CollectionPathResolverPrivate(this), parent) |
154 | { |
155 | Q_D(CollectionPathResolver); |
156 | d->init(path, Collection::root()); |
157 | } |
158 | |
159 | CollectionPathResolver::CollectionPathResolver(const QString &path, const Collection &parentCollection, QObject *parent) |
160 | : Job(new CollectionPathResolverPrivate(this), parent) |
161 | { |
162 | Q_D(CollectionPathResolver); |
163 | d->init(path, parentCollection); |
164 | } |
165 | |
166 | CollectionPathResolver::CollectionPathResolver(const Collection &collection, QObject *parent) |
167 | : Job(new CollectionPathResolverPrivate(this), parent) |
168 | { |
169 | Q_D(CollectionPathResolver); |
170 | |
171 | d->mPathToId = false; |
172 | d->mColId = collection.id(); |
173 | d->mCurrentNode = collection; |
174 | } |
175 | |
176 | CollectionPathResolver::~CollectionPathResolver() |
177 | { |
178 | } |
179 | |
180 | Collection::Id CollectionPathResolver::collection() const |
181 | { |
182 | Q_D(const CollectionPathResolver); |
183 | |
184 | return d->mColId; |
185 | } |
186 | |
187 | QString CollectionPathResolver::path() const |
188 | { |
189 | Q_D(const CollectionPathResolver); |
190 | |
191 | if (d->mPathToId) { |
192 | return d->mPath; |
193 | } |
194 | return d->mPathParts.join(pathDelimiter()); |
195 | } |
196 | |
197 | QString CollectionPathResolver::pathDelimiter() |
198 | { |
199 | return QLatin1String("/" ); |
200 | } |
201 | |
202 | void CollectionPathResolver::doStart() |
203 | { |
204 | Q_D(CollectionPathResolver); |
205 | |
206 | CollectionFetchJob *job = 0; |
207 | if (d->mPathToId) { |
208 | if (d->mPath.isEmpty()) { |
209 | d->mColId = Collection::root().id(); |
210 | emitResult(); |
211 | return; |
212 | } |
213 | job = new CollectionFetchJob(d->mCurrentNode, CollectionFetchJob::FirstLevel, this); |
214 | } else { |
215 | if (d->mColId == 0) { |
216 | d->mColId = Collection::root().id(); |
217 | emitResult(); |
218 | return; |
219 | } |
220 | job = new CollectionFetchJob(d->mCurrentNode, CollectionFetchJob::Base, this); |
221 | } |
222 | connect(job, SIGNAL(result(KJob*)), SLOT(jobResult(KJob*))); |
223 | } |
224 | |
225 | //@endcond |
226 | |
227 | #include "moc_collectionpathresolver_p.cpp" |
228 | |