-
Notifications
You must be signed in to change notification settings - Fork 0
/
qtflickr.h
450 lines (416 loc) · 12.2 KB
/
qtflickr.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
/******************************************************************************
* Copyright (C) 2009 by Evgeni Gordejev *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Library Lesser General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or (at your option) any later version. *
* *
* This program 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 Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Library Lesser General Public *
* License along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
******************************************************************************/
#ifndef QTFLICKR_H
#define QTFLICKR_H
#include <QtCore>
#include <QObject>
#include <QXmlStreamReader>
class QNetworkAccessManager;
class QNetworkReply;
/**
* Flickr errors. Find more about flickr errors on http://www.flickr.com/services/api/
* page
*/
struct ErrorData
{
/**
* error codes:<br>
* <ul><li>0 - No errors</li>
* </ul>
*/
int code;
/**
* Error string
*/
QString message;
};
/**
* tag struct
*/
struct TagData
{
/** Tag value */
QString value;
/** Tag attributes */
QMap<QString,QString> attributes;
};
/**
* @class Method
* Use this class to create method for accessing Flickr API<br>
* Example:
* @code
* Method method("flickr.photos.comments.addComment");
* method.addArgument("photo_id","87243209893");
* method.addArgument("comment_text","This comment was added through QtFlickr library :) ");
*
* QtFlickr qtFlickr("apiKey","apiSecret");
* qtFlickr.get(method);
* @endcode
*/
class Method
{
public:
/**
* @param method Flickr API valid method, for example "flickr.photos.setPerms"
*/
Method ( const QString &method )
{
map["method"] = method;
}
/**
* <b><i>Note: You don't have to provide api_key as argument.</i></b>
* @param argument name, for example "photo_id"
* @param value Value of the argument, for example "435834534"
*/
void addArgument ( const QString &argument, const QString &value )
{
map[argument] = value;
}
private:
friend class QtFlickr;
QMap<QString,QString> map;
};
/**
* @class Request
* Use this class to provide information for the XML parser, parser will
* search only those tags that you have been provided.<br>
* Example:
* @code
* <?xml version="1.0" encoding="utf-8" ?>
* <rsp stat="ok">
* <photos page="2" pages="89" perpage="10" total="881">
* <photo id="2636" owner="47058503995@N01"/>
* <photo id="2635" owner="47058503995@N01"/>
* </photos>
* </rsp>
* @endcode
* Let assume server response is a XML above and you want to get all id's and owner information for the
* photo list. The code will look like this:
* @code
* Request request("photo","id,owner");
*
* QtFlickr qtFlickr("apiKey","apiSecret");
* qtFlickr.get(Method("flickr.photos.getWithGeoData"),request);
* @endcode
*/
class Request
{
public:
/**
* Constructs empty request, this mean that you don't want any information to
* be parsed
*/
Request() {}
/**
* Construct request and adds one tag name to be parsed
* @param name tag name to be parsed
* @param attrs A comma-delimited list of attributes to be parsed within this tag name
*/
Request ( const QString &name, const QString &attrs = QString() )
{
addTag ( name,attrs );
}
/**
* Adds tag name to be parsed into request list
* @param name tag name to be parsed
* @param attrs A comma-delimited list of attributes to be parsed within this tag name
*/
void addTag ( const QString &name, const QString &attrs = QString() )
{
TagData tagData;
if ( !attrs.isEmpty() )
{
QStringList attrList = attrs.split ( "," );
for ( int i = 0; i < attrList.size(); ++i )
{
tagData.attributes.insert ( attrList.at ( i ),QString() );
}
}
map.insert ( name,tagData );
}
private:
friend class QtFlickr;
QMap<QString,TagData> map;
};
/**
* @class Photo
* This class is used when uploading or replacing photos.
* Similar to Method class
*/
class Photo
{
public:
/**
* Constructor
* @param file File to be uploaded
* @param photoId The ID of the photo to replace, do not set this
* value if you want just to upload photo
*/
Photo ( const QString &file,
const QString &photoId = QString() )
:file ( file ),
photoId ( photoId ) {}
/**
* Adds optional arguments
* @param argument The name of the argument, for example "title"
* @param value Value of the argument, for example "My photo"
*/
void addArgument ( const QString &argument, const QString &value )
{
map[argument] = value;
}
private:
friend class QtFlickr;
QString file;
QString photoId;
QMap<QString,QString> map;
};
/**
* @class Response
* Class is used to collect data from the parser,
* it will return only those values that has been setted with the Request object<br>
* Example:
* @code
* <?xml version="1.0" encoding="utf-8" ?>
* <rsp stat="ok">
* <photos page="2" pages="89" perpage="10" total="881">
* <photo id="2636" owner="47058503995@N01"/>
* <photo id="2635" owner="47058503995@N01"/>
* </photos>
* </rsp>
* @endcode
* If you want to get page number from XML above:
* @code
* QString page = response.attrValue("photos","page");
* qDebug()<<page //output: 2
* @endcode
*/
class Response
{
public:
Response() {}
/**
* @param tagName
* @return value of the tag
*/
QString tagValue ( const QString &tagName )
{
return map.value ( tagName ).value;
}
/**
* @param tagName
* @param attrName
* @return attribute value
*/
QString attrValue ( const QString &tagName, const QString &attrName )
{
return map.value ( tagName ).attributes.value ( attrName );
}
/**
* @param tagName
* @return list of values with this tag name
*/
QList<QString> tagValues ( const QString &tagName )
{
QList<TagData> tmp = map.values ( tagName );
QList<QString> res;
for ( int i = 0; i < tmp.size(); ++i )
{
res << tmp.at ( i ).value;
}
return res;
}
/**
* @param tagName
* @param attrName
* @return list of attribute values with this tag name
*/
QList<QString> attrValues ( const QString &tagName, const QString &attrName )
{
QList<TagData> tmp = map.values ( tagName );
QList<QString> res;
for ( int i = 0; i < tmp.size(); ++i )
{
res << tmp.at ( i ).attributes.value ( attrName );
}
return res;
}
private:
friend class QtFlickr;
QMap<QString,TagData> map;
};
/**
* @class QtFlickr
* Main class of QtFlickr APi<br>
* Authorization example:
* @code
* UIClass::UIClass
* {
* qtFlickr = new QtFlickr("xxxxxxxxx", "xxxxxxxxxxxxx", this);
* connect(qtFlickr,SIGNAL(requestFinished ( int, Response, ErrorData, void* )),
* this,SLOT(requestFinished ( int, Response, ErrorData, void* )));
*
* Method method("flickr.auth.getFrob");
* Request request("frob");
* frobRequest = qtFlickr->get(method,request);
* }
*
* void UIClass::requestFinished ( int reqId, Response data, ErrorData err, void* userData )
* {
* if(err.code != 0){
* if(reqId == frobRequest){
* QString frob = data.tagValue("frob");
* QUrl authUrl = qtFlickr->authorizationUrl(frob);
* QDesktopServices::openUrl ( authUrl );
*
* QMessageBox msgBox;
* msgBox.setText("Press Ok button when you have completed authorization through web browser")
* int result = msgBox.exec();
* if( result == QDialog::Accepted){
* Method method("flickr.auth.getToken");
* method.addArgument( "frob", frob );
* Request request("token");
* request.addTag("user","username,fullname");
* tokenRequest = qtFlickr->get(method, request);
* }
* }else if(reqId == tokenRequest){
* QString token = data.tagValue("token");
* QString username = data.attrValue("user", "username");
* QString fullname = data.attrValue("user", "fullname");
*
* qDebug()<<"Your username: "<<username;
* qDebug()<<"Your fullname: "<<fullname;
*
* qtFlickr->setToken(token);
* //Now you can call authorized calls with "write" permission
* }
* }else{
* qDebug()<<"Error: "<<err.message;
* }
* }
* @endcode
*/
class QtFlickr : public QObject
{
Q_OBJECT
public:
/**
* Constructor
* @param apiKey Flickr api key
* @param apiSecret Flickr api secret
* @param parent object
*/
QtFlickr ( const QString &apiKey,
const QString &apiSecret,
QObject *parent = 0 );
~QtFlickr();
/**
* Sets token for the QtFlickr API
* @param token
*/
void setToken ( const QString &token );
/**
* Returns authorization url for give frob
* @param frob
* @param perms "write", "read" or "delete"
*/
QUrl authorizationUrl ( const QString &frob, const QString &perms = "write" );
/**
* Fetches data from Flickr API with GET method
* @param method Flickr API method
* @param request XML request data
* @param userData user data to be transfered through signal/slots mechanism,
* this parametr has no effect on this function
* @return request id
*/
int get ( const Method &method,
const Request &request = Request(),
void* userData = 0 );
/**
* Fetches data from Flickr API with POST method
* @param method Flickr API method
* @param request XML request data
* @param userData user data to be transfered through signal/slots mechanism,
* this parametr has no effect on this function
* @return request id
*/
int post ( const Method &method,
const Request &request = Request(),
void* userData = 0 );
/**
* Uploads or replaces photo
* @param photo to be uploaded
* @param request XML request data
* @param userData user data to be transfered through signal/slots mechanism,
* this parametr has no effect on this function
* @return request id
*/
int upload ( const Photo &photo,
const Request &request = Request(),
void* userData = 0 );
signals:
/**
* Emitted after get(), post() and upload() functions
* @param reqId The request id
* @param data Response XML data
* @param err possible error
* @param userData user data transfered through signal/slots mechanism
*/
void requestFinished ( int reqId, Response data, ErrorData err, void* userData );
/**
* Emitted while photo uploading is in progress
* @param percent 0-100, returns -1 when cannot determine uploading
* progress.
*/
void uploadProgress ( int percent );
private slots:
void replyFinished ( QNetworkReply *reply );
void uploadProgress ( qint64 bytesSent, qint64 bytesTotal );
private:
QByteArray generateBoundary();
QByteArray constructField ( QString name,
QString content,
QByteArray boundary,
QString filename = QString() );
int request ( const Method &method, const Request &request, bool get, void* userData );
void parse ( const QByteArray &data, const QString &startTag, const QStringList &tags );
void readUnknownElement();
void readElements ( const QStringList &tags );
void readErrorElement( );
void readError();
void readData();
struct RequestData
{
void* userData;
QMap<QString,TagData> tagList;
};
QString md5 ( const QString &data );
QString apiKey;
QString apiSecret;
QString token;
QNetworkAccessManager *manager;
QXmlStreamReader xml;
QMap<QString,TagData> tagList;
QMap<QString,TagData> replyTagList;
Response req;
QMap<int,RequestData> requestDataMap;
ErrorData err;
};
#endif