1/*
2 This file is part of KDE.
3
4 Copyright (c) 2008 Cornelius Schumacher <schumacher@kde.org>
5 Copyright (c) 2011 Laszlo Papp <djszapi@archlinux.us>
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) version 3, or any
11 later version accepted by the membership of KDE e.V. (or its
12 successor approved by the membership of KDE e.V.), which shall
13 act as a proxy defined in Section 6 of version 3 of the license.
14
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
19
20 You should have received a copy of the GNU Lesser General Public
21 License along with this library. If not, see <http://www.gnu.org/licenses/>.
22
23*/
24
25#ifndef ATTICA_PROVIDER_H
26#define ATTICA_PROVIDER_H
27
28#include <QtCore/QExplicitlySharedDataPointer>
29#include <QtCore/QSharedPointer>
30#include <QtCore/QString>
31#include <QtCore/QStringList>
32
33#include <QtCore/QUrl>
34
35#include "achievement.h"
36#include "atticaclient_export.h"
37#include "category.h"
38#include "forum.h"
39#include "itemjob.h"
40#include "listjob.h"
41#include "message.h"
42#include "comment.h"
43#include "distribution.h"
44#include "license.h"
45
46class QDate;
47class QUrl;
48
49namespace Attica {
50
51class PlatformDependent;
52
53class PostJobStatus;
54
55class AccountBalance;
56class Activity;
57class BuildServiceJobOutput;
58class BuildServiceJob;
59class BuildService;
60class PrivateData;
61class Content;
62class DownloadItem;
63class Distribution;
64class Event;
65class Folder;
66class HomePageType;
67class KnowledgeBaseEntry;
68class License;
69class Person;
70class PostJob;
71class Project;
72class Provider;
73class Publisher;
74class PublisherField;
75class RemoteAccount;
76
77
78/**
79 * The Provider class represents one Open Collaboration Service provider.
80 * Use the ProviderManager to instanciate a Provider.
81 *
82 * Accessing functions of the Provider returns a Job class that
83 * takes care of accessing the server and parsing the result.
84 *
85 * Provider files are xml of the form:
86 <pre>
87 <provider>
88 <id>opendesktop</id>
89 <location>https://api.opendesktop.org/v1/</location>
90 <name>openDesktop.org</name>
91 <icon></icon>
92 <termsofuse>https://opendesktop.org/terms/</termsofuse>
93 <register>https://opendesktop.org/usermanager/new.php</register>
94 <services>
95 <person ocsversion="1.3" />
96 <friend ocsversion="1.3" />
97 <message ocsversion="1.3" />
98 <activity ocsversion="1.3" />
99 <content ocsversion="1.3" />
100 <fan ocsversion="1.3" />
101 <knowledgebase ocsversion="1.3" />
102 <event ocsversion="1.3" />
103 <comment ocsversion="1.2" />
104 </services>
105</provider>
106 </pre>
107 * The server provides the services specified in the services section, not necessarily all of them.
108 */
109class ATTICA_EXPORT Provider
110{
111 public:
112 Provider();
113 Provider(const Provider& other);
114 Provider& operator=(const Provider& other);
115 ~Provider();
116
117 /**
118 Returns true if the provider has been set up and can be used.
119 */
120 bool isValid() const;
121
122 /**
123 Test if the provider is enabled by the settings.
124 The application can choose to ignore this, but the user settings should be respected.
125 */
126 bool isEnabled() const;
127 void setEnabled(bool enabled);
128
129 /**
130 A url that identifies this provider.
131 This should be used as identifier when referring to this provider but you don't want to use the full provider object.
132 */
133 QUrl baseUrl() const;
134
135 /**
136 A name for the provider that can be displayed to the user
137 */
138 QString name() const;
139
140 enum SortMode {
141 Newest,
142 Alphabetical,
143 Rating,
144 Downloads
145 };
146
147 /**
148 Test if the server supports the person part of the API
149 */
150 bool hasPersonService() const;
151 /**
152 Version of the person part of the API
153 */
154 QString personServiceVersion() const;
155
156 /**
157 Test if the server supports the friend part of the API
158 */
159 bool hasFriendService() const;
160
161 /**
162 Version of the friend part of the API
163 */
164 QString friendServiceVersion() const;
165
166 /**
167 Test if the server supports the message part of the API
168 */
169 bool hasMessageService() const;
170 /**
171 Version of the message part of the API
172 */
173 QString messageServiceVersion() const;
174
175 /**
176 Test if the server supports the achievement part of the API
177 */
178 bool hasAchievementService() const;
179 /**
180 Version of the achievement part of the API
181 */
182 QString achievementServiceVersion() const;
183
184 /**
185 Test if the server supports the activity part of the API
186 */
187 bool hasActivityService() const;
188 /**
189 Version of the activity part of the API
190 */
191 QString activityServiceVersion() const;
192
193 /**
194 Test if the server supports the content part of the API
195 */
196 bool hasContentService() const;
197 /**
198 Version of the content part of the API
199 */
200 QString contentServiceVersion() const;
201
202 /**
203 Test if the server supports the fan part of the API
204 */
205 bool hasFanService() const;
206 /**
207 Version of the fan part of the API
208 */
209 QString fanServiceVersion() const;
210
211 /**
212 Test if the server supports the forum part of the API
213 */
214 bool hasForumService() const;
215 /**
216 Version of the forum part of the API
217 */
218 QString forumServiceVersion() const;
219
220 /**
221 *
222 Test if the server supports the knowledgebase part of the API
223 */
224 bool hasKnowledgebaseService() const;
225 /**
226 Version of the knowledgebase part of the API
227 */
228 QString knowledgebaseServiceVersion() const;
229
230 /**
231 Test if the server supports the comments part of the API
232 */
233 bool hasCommentService() const;
234 /**
235 Version of the comments part of the API
236 */
237 QString commentServiceVersion() const;
238
239 /**
240 Test if the provider has user name/password available.
241 This does not yet open kwallet in case the KDE plugin is used.
242 @return true if the provider has login information
243 */
244 bool hasCredentials() const;
245 bool hasCredentials();
246
247 /**
248 Load user name and password from the store.
249 Attica will remember the loaded values and use them from this point on.
250 @param user reference that returns the user name
251 @param password reference that returns the password
252 @return if credentials could be loaded
253 */
254 bool loadCredentials(QString& user, QString& password);
255
256 /**
257 Sets (and remembers) user name and password for this provider.
258 To remove the data an empty username should be passed.
259 @param user the user (login) name
260 @param password the password
261 @return if credentials could be saved
262 */
263 bool saveCredentials(const QString& user, const QString& password);
264
265 /**
266 Test if the server accepts the login/password.
267 This function does not actually set the credentials. Use saveCredentials for that purpose.
268 @param user the user (login) name
269 @param password the password
270 @return the job that will contain the success of the login as metadata
271 */
272 PostJob* checkLogin(const QString& user, const QString& password);
273
274 // Person part of OCS
275
276 PostJob* registerAccount(const QString& id, const QString& password, const QString& mail, const QString& firstName, const QString& lastName);
277 ItemJob<Person>* requestPerson(const QString& id);
278 ItemJob<Person>* requestPersonSelf();
279 ItemJob<AccountBalance>* requestAccountBalance();
280 ListJob<Person>* requestPersonSearchByName(const QString& name);
281 ListJob<Person>* requestPersonSearchByLocation(qreal latitude, qreal longitude, qreal distance = 0.0, int page = 0, int pageSize = 20);
282 PostJob* postLocation(qreal latitude, qreal longitude, const QString& city = QString(), const QString& country = QString());
283
284 //////////////////////////
285 // PrivateData part of OCS
286
287 /**
288 * Fetches the a given attribute from an OCS-compliant server.
289 * @param app The application name
290 * @param key The key of the attribute to fetch (optional)
291 * @return The job that is responsible for fetching the data
292 */
293 ItemJob<PrivateData>* requestPrivateData(const QString& app, const QString& key = QString());
294
295 /**
296 * Fetches all stored private data.
297 * @return The job responsible for fetching data
298 */
299 ItemJob<PrivateData>* requestPrivateData() { return requestPrivateData(QString(), QString()); }
300
301 /**
302 * Sets the value of an attribute.
303 * @param app The application name
304 * @param key The key of the attribute
305 * @param value The new value of the attribute
306 * @return The job responsible for setting data
307 */
308 PostJob* setPrivateData(const QString &app, const QString &key, const QString &value);
309
310 // Friend part of OCS
311
312 ListJob<Person>* requestFriends(const QString& id, int page = 0, int pageSize = 20);
313 PostJob* postFriendInvitation(const QString& to, const QString& message);
314 ListJob<Person>* requestSentInvitations(int page = 0, int pageSize = 20);
315 ListJob<Person>* requestReceivedInvitations(int page = 0, int pageSize = 20);
316 PostJob* inviteFriend(const QString& to, const QString& message);
317 PostJob* approveFriendship(const QString& to);
318 PostJob* declineFriendship(const QString& to);
319 PostJob* cancelFriendship(const QString& to);
320
321 // Message part of OCS
322
323 ListJob<Folder>* requestFolders();
324 ListJob<Message>* requestMessages(const Folder& folder);
325 ListJob<Message>* requestMessages(const Folder& folder, Message::Status status);
326 ItemJob<Message>* requestMessage(const Folder& folder, const QString& id);
327 PostJob* postMessage(const Message& message);
328
329 // Achievement part of OCS
330 /**
331 * Get a list of achievements
332 * @return ListJob listing Achievements
333 */
334 ListJob<Achievement>* requestAchievements(const QString& contentId, const QString& achievementId, const QString& userId);
335
336 /** Add a new achievement.
337 * @param id id of the achievement entry
338 * @param achievement The new Achievement added
339 * @return item post job for adding the new achievement
340 */
341 ItemPostJob<Achievement>* addNewAchievement(const QString& id, const Achievement& newAchievement);
342
343 /**
344 * Post modifications to an Achievement on the server
345 * @param achievement Achievement to update on the server
346 */
347 PutJob* editAchievement(const QString& contentId, const QString& achievementId, const Achievement& achievement);
348
349 /**
350 * Deletes an achievement on the server. The achievement passed as an argument doesn't need complete
351 * information as just the id() is used.
352 * @param achievement Achievement to delete on the server.
353 */
354 DeleteJob* deleteAchievement(const QString& contentId, const QString& achievementId);
355
356 // PostJob* postAchievement(const Achievement& achievement);
357 PostJob* setAchievementProgress(const QString& id, const QVariant& progress, const QDateTime& timestamp);
358 DeleteJob* resetAchievementProgress(const QString& id);
359
360 // Activity part of OCS
361
362 ListJob<Activity>* requestActivities();
363 PostJob* postActivity(const QString& message);
364
365 // Project part of OCS
366 /**
367 * Get a list of build service projects
368 * @return ListJob listing Projects
369 */
370 ListJob<Project>* requestProjects();
371
372 /**
373 * Get a Project's data
374 * @return ItemJob receiving data
375 */
376 ItemJob<Project>* requestProject(const QString& id);
377
378 /**
379 * Post modifications to a Project on the server. The resulting project ID can be found in
380 * the Attica::MetaData of the finished() PostJob. You can retrieve it using
381 * Attica::MetaData::resultingProjectId().
382 * @param project Project to create on the server
383 */
384 PostJob* createProject(const Project& project);
385
386 /**
387 * Deletes a project on the server. The project passed as an argument doesn't need complete
388 * information as just the id() is used.
389 * @param project Project to delete on the server.
390 */
391 PostJob* deleteProject(const Project& project);
392
393 /**
394 * Post modifications to a Project on the server
395 * @param project Project to update on the server
396 */
397 PostJob* editProject(const Project& project);
398
399 // Buildservice part of OCS
400
401 /**
402 * Get the information for a specific build service instance.
403 * @return ItemJob receiving data
404 */
405 ItemJob<BuildService>* requestBuildService(const QString& id);
406
407 /**
408 * Get the information for a specific publisher.
409 * @return ItemJob receiving data
410 */
411 ItemJob<Publisher>* requestPublisher(const QString& id);
412
413 /**
414 * Save the value of a single publishing field
415 * @return PostJob*
416 */
417 PostJob* savePublisherField(const Project& project, const PublisherField& field);
418
419 /**
420 * Publish the result of a completed build job to a publisher.
421 * @return ItemJob receiving data
422 */
423 PostJob* publishBuildJob(const BuildServiceJob& buildjob, const Publisher& publisher);
424
425 /**
426 * Get the build output for a specific build service job
427 * @return ItemJob receiving and containing the output data
428 */
429 ItemJob<BuildServiceJobOutput>* requestBuildServiceJobOutput(const QString& id);
430
431 /**
432 * Get the information for a specific build service job, such as status and progress.
433 * @return ItemJob receiving and containing the data
434 */
435 ItemJob<BuildServiceJob>* requestBuildServiceJob(const QString& id);
436
437 /**
438 * Get a list of build service build services
439 * @return ListJob listing BuildServices
440 */
441 ListJob<BuildService>* requestBuildServices();
442
443 /**
444 * Get a list of publishers
445 * @return ListJob listing Publishers
446 */
447 ListJob<Publisher>* requestPublishers();
448
449 /**
450 * Get a list of build service projects
451 * @return ListJob listing BuildServiceJobs
452 */
453 ListJob<BuildServiceJob>* requestBuildServiceJobs(const Project &project);
454
455
456 /**
457 * Create a new job for a given project on a given buildservice for a given target.
458 * Those three items are mandatory for the job to succeed.
459 * @param job Buildservicejob to create on the server
460 */
461 PostJob* createBuildServiceJob(const BuildServiceJob& job);
462
463 /**
464 * Cancel a job.
465 * Setting the ID on the build service parameter is enough for it to work.
466 * @param job Buildservicejob to cancel on the server, needs at least id set.
467 */
468 PostJob* cancelBuildServiceJob(const BuildServiceJob& job);
469
470 /**
471 * Get a list of remote accounts, account for a build service instance
472 * which is stored in the OCS service in order to authenticate with the
473 * build service instance.
474 * @return ListJob listing RemoteAccounts
475 */
476 ListJob<RemoteAccount>* requestRemoteAccounts();
477
478 /**
479 * Deletes a remote account stored on the OCS server.
480 * @param id The ID of the remote account on the OCS instance.
481 */
482 PostJob* deleteRemoteAccount(const QString& id);
483
484 /**
485 * Create a new remote account, an account for a build service instance
486 * which is stored in the OCS service in order to authenticate with the
487 * build service instance.
488 * Type, Type ID, login and password are mandatory.
489 * @param account RemoteAccount to create on the server
490 */
491 PostJob* createRemoteAccount(const RemoteAccount& account);
492
493 /**
494 * Edit an existing remote account.
495 * @param account RemoteAccount to create on the server
496 */
497 PostJob* editRemoteAccount(const RemoteAccount& account);
498
499 /** Get a remote account by its ID.
500 * @param id The ID of the remote account
501 */
502 ItemJob<RemoteAccount>* requestRemoteAccount(const QString &id);
503
504 /** Upload a tarball to the buildservice.
505 * @param projectId The ID of the project this source file belongs to
506 * @param payload A reference tothe complete file data
507 * @return A postjob to keep keep track of the upload
508 */
509 Attica::PostJob* uploadTarballToBuildService(const QString& projectId, const QString& fileName, const QByteArray& payload);
510
511 // Content part of OCS
512
513 /**
514 * Get a list of categories (such as wallpaper)
515 * @return the categories of the server
516 */
517 ListJob<Category>* requestCategories();
518
519 /**
520 * Get a list of licenses (such as GPL)
521 * @return the licenses available from the server
522 */
523 ListJob<License>* requestLicenses();
524
525 /**
526 * Get a list of distributions (such as Ark, Debian)
527 * @return the licenses available from the server
528 */
529 ListJob<Distribution>* requestDistributions();
530
531 /**
532 * Get a list of home page types (such as blog, Facebook)
533 * @return the licenses available from the server
534 */
535 ListJob<HomePageType>* requestHomePageTypes();
536
537 /**
538 Request a list of Contents.
539 Note that @p categories is not optional. If left empty, no results will be returned.
540 An empty search string @p search returns the top n items.
541 @param categories categories to search in
542 @param search optional search string (in name/description of the content)
543 @param mode sorting mode
544 @param page request nth page in the list of results
545 @param pageSize requested size of pages when calculating the list of results
546 @return list job for the search results
547 */
548 ListJob<Content>* searchContents(const Category::List& categories, const QString& search = QString(), SortMode mode = Rating, uint page = 0, uint pageSize = 10);
549
550 /**
551 Request a list of Contents.
552 Like @see searchContents, but only contents created by one person.
553 @param person the person-id that created the contents.
554 */
555 ListJob<Content>* searchContentsByPerson(const Category::List& categories, const QString& person, const QString& search = QString(), SortMode mode = Rating, uint page = 0, uint pageSize = 10);
556
557 /**
558 Request a list of Contents. More complete version.
559 Note that @p categories is not optional. If left empty, no results will be returned.
560 An empty search string @p search returns the top n items.
561 @param categories categories to search in
562 @param person the person-id that created the contents
563 @param distributions list of distributions to filter by, if empty no filtering by distribution is done
564 @param licenses list of licenses to filter by, if empty no filtering by license is done
565 @param search optional search string (in name/description of the content)
566 @param mode sorting mode
567 @param page request nth page in the list of results
568 @param pageSize requested size of pages when calculating the list of results
569 @return list job for the search results
570 */
571 ListJob<Content>* searchContents(const Category::List& categories, const QString& person, const Distribution::List& distributions, const License::List& licenses, const QString& search = QString(), SortMode sortMode = Rating, uint page = 0, uint pageSize = 10);
572
573 /**
574 Retrieve a single content.
575 @param contentId the id of the content
576 @return job that retrieves the content object
577 */
578 ItemJob<Content>* requestContent(const QString& contentId);
579
580 ItemJob<DownloadItem>* downloadLink(const QString& contentId, const QString& itemId = QLatin1String("1"));
581
582 /** Vote for a content item
583 * This version is for the old OCS API < 1.6
584 * @param contentId the content which this voting is for
585 * @param positiveVote whether the voting is positive or negative
586 * @return the post job for this voting
587 */
588 Q_DECL_DEPRECATED PostJob* voteForContent(const QString& contentId, bool positiveVote);
589
590 /** Vote for a content item
591 * @param contentId the content which this voting is for
592 * @param rating - the rating, must be between 0 (bad) and 100 (good)
593 * @return the post job for this voting
594 */
595 PostJob* voteForContent(const QString& contentId, uint rating);
596
597 ItemPostJob<Content>* addNewContent(const Category& category, const Content& newContent);
598 ItemPostJob<Content>* editContent(const Category& updatedCategory, const QString& contentId, const Content& updatedContent);
599 PostJob* deleteContent(const QString& contentId);
600
601 PostJob* setDownloadFile(const QString& contentId, const QString& fileName, QIODevice* payload);
602 PostJob* setDownloadFile(const QString& contentId, const QString& fileName, const QByteArray& payload);
603 PostJob* deleteDownloadFile(const QString& contentId);
604
605 /**
606 * Upload an image file as preview for the content
607 * @param contentId
608 * @param previewId each content can have previews with the id 1,2 or 3
609 * @param payload the image file
610 */
611 PostJob* setPreviewImage(const QString& contentId, const QString& previewId, const QString& fileName, const QByteArray& image);
612 PostJob* deletePreviewImage(const QString& contentId, const QString& previewId);
613
614 // KnowledgeBase part of OCS
615
616 ItemJob<KnowledgeBaseEntry>* requestKnowledgeBaseEntry(const QString& id);
617 ListJob<KnowledgeBaseEntry>* searchKnowledgeBase(const Content& content, const QString& search, SortMode, int page, int pageSize);
618
619 // Event part of OCS
620
621 ItemJob<Event>* requestEvent(const QString& id);
622 ListJob<Event>* requestEvent(const QString& country, const QString& search, const QDate& startAt, SortMode mode, int page, int pageSize);
623
624 // Comment part of OCS
625 /** Request a list of comments for a content / forum / knowledgebase / event.
626 * @param comment::Type type of the comment @see Comment::Type (content / forum / knowledgebase / event)
627 * @param id id of the content entry where you want to get the comments is from
628 * @param id2 id of the content entry where you want to get the comments is from
629 * @param page request nth page in the list of results
630 * @param pageSize requested size of pages when calculating the list of results
631 * @return list job for the comments results
632 */
633 ListJob<Comment>* requestComments(const Comment::Type commentType, const QString& id, const QString& id2, int page, int pageSize);
634
635 /** Add a new comment.
636 * @param commentType type of the comment @see CommentType (content / forum / knowledgebase / event)
637 * @param id id of the content entry where you want to get the comments is from
638 * @param id2 id of the sub content entry where you want to get the comments is from
639 * @param parentId the id of the parent comment if the new comment is a reply
640 * @param subject title of the comment
641 * @param message text of the comment
642 * @return item post job for adding the new comment
643 */
644 ItemPostJob<Comment>* addNewComment(const Comment::Type commentType, const QString& id, const QString& id2, const QString& parentId, const QString &subject, const QString& message);
645
646 /** Vote a comment item
647 * @param id the comment id which this voting is for
648 * @param rating the rating, must be between 0 (bad) and 100 (good)
649 * @return the post job for this voting
650 */
651 PostJob* voteForComment(const QString & id, uint rating);
652
653 // Fan part of OCS
654
655 PostJob* becomeFan(const QString& contentId);
656 ListJob<Person>* requestFans(const QString& contentId, uint page = 0, uint pageSize = 10);
657
658 // Forum part of OCS
659 ListJob<Forum>* requestForums(uint page = 0, uint pageSize = 10);
660 ListJob<Topic>* requestTopics(const QString& forum, const QString& search, const QString& description, SortMode mode, int page, int pageSize);
661 PostJob* postTopic(const QString& forumId, const QString& subject, const QString& content);
662
663 const QString& getRegisterAccountUrl() const;
664
665 protected:
666 QUrl createUrl(const QString& path);
667 QNetworkRequest createRequest(const QUrl& url);
668 // Convenience overload
669 QNetworkRequest createRequest(const QString& path);
670
671 ItemJob<Person>* doRequestPerson(const QUrl& url);
672 ItemJob<AccountBalance>* doRequestAccountBalance(const QUrl& url);
673 ListJob<Person>* doRequestPersonList(const QUrl& url);
674 ListJob<Achievement>* doRequestAchievementList(const QUrl& url);
675 ListJob<Activity>* doRequestActivityList(const QUrl& url);
676 ListJob<Folder>* doRequestFolderList(const QUrl& url);
677 ListJob<Forum>* doRequestForumList(const QUrl& url);
678 ListJob<Topic>* doRequestTopicList(const QUrl& url);
679 ListJob<Message>* doRequestMessageList(const QUrl& url);
680
681 private:
682 class Private;
683 QExplicitlySharedDataPointer<Private> d;
684
685 Provider(PlatformDependent* internals, const QUrl& baseUrl, const QString& name, const QUrl& icon = QUrl());
686 Provider(PlatformDependent* internals, const QUrl& baseUrl, const QString& name, const QUrl& icon,
687 const QString& person, const QString& friendV, const QString& message, const QString& achievements,
688 const QString& activity, const QString& content, const QString& fan, const QString& forum,
689 const QString& knowledgebase, const QString& event, const QString& comment);
690 // kde-SC5: merge with the constructor above (i.e. remove the above one)
691 Provider(PlatformDependent* internals, const QUrl& baseUrl, const QString& name, const QUrl& icon,
692 const QString& person, const QString& friendV, const QString& message, const QString& achievements,
693 const QString& activity, const QString& content, const QString& fan, const QString& forum,
694 const QString& knowledgebase, const QString& event, const QString& comment, const QString& registerUrl);
695
696friend class ProviderManager;
697};
698}
699
700#endif
701