1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). |
4 | ** Contact: http://www.qt-project.org/legal |
5 | ** |
6 | ** This file is part of the QtDocGallery module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and Digia. For licensing terms and |
14 | ** conditions see http://qt.digia.com/licensing. For further information |
15 | ** use the contact form at http://qt.digia.com/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 2.1 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 2.1 requirements |
23 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
24 | ** |
25 | ** In addition, as a special exception, Digia gives you certain additional |
26 | ** rights. These rights are described in the Digia Qt LGPL Exception |
27 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
28 | ** |
29 | ** GNU General Public License Usage |
30 | ** Alternatively, this file may be used under the terms of the GNU |
31 | ** General Public License version 3.0 as published by the Free Software |
32 | ** Foundation and appearing in the file LICENSE.GPL included in the |
33 | ** packaging of this file. Please review the following information to |
34 | ** ensure the GNU General Public License version 3.0 requirements will be |
35 | ** met: http://www.gnu.org/copyleft/gpl.html. |
36 | ** |
37 | ** |
38 | ** $QT_END_LICENSE$ |
39 | ** |
40 | ****************************************************************************/ |
41 | |
42 | #include <qgalleryabstractrequest.h> |
43 | #include "qgalleryabstractrequest_p.h" |
44 | #include <qabstractgallery.h> |
45 | |
46 | QT_BEGIN_NAMESPACE_DOCGALLERY |
47 | |
48 | void QGalleryAbstractRequestPrivate::_q_finished() |
49 | { |
50 | if (state == QGalleryAbstractRequest::Active |
51 | || state == QGalleryAbstractRequest::Canceling |
52 | || state == QGalleryAbstractRequest::Idle) { |
53 | if (response->error() != QGalleryAbstractRequest::NoError) { |
54 | error = response->error(); |
55 | errorString = response->errorString(); |
56 | |
57 | state = QGalleryAbstractRequest::Error; |
58 | |
59 | emit q_func()->error(error, errorString); |
60 | emit q_func()->errorChanged(); |
61 | emit q_func()->stateChanged(state); |
62 | } else if (state == QGalleryAbstractRequest::Idle) { |
63 | if (!response->isIdle()) { |
64 | state = QGalleryAbstractRequest::Finished; |
65 | |
66 | emit q_func()->stateChanged(state); |
67 | } |
68 | } else if (response->isIdle()) { |
69 | state = QGalleryAbstractRequest::Idle; |
70 | |
71 | if (!wasIdle) { |
72 | wasIdle = true; |
73 | |
74 | emit q_func()->finished(); |
75 | } |
76 | |
77 | emit q_func()->stateChanged(state); |
78 | } else if (!response->isActive()) { |
79 | state = QGalleryAbstractRequest::Finished; |
80 | |
81 | if (!wasIdle) |
82 | emit q_func()->finished(); |
83 | |
84 | emit q_func()->stateChanged(state); |
85 | } |
86 | } |
87 | } |
88 | |
89 | void QGalleryAbstractRequestPrivate::_q_canceled() |
90 | { |
91 | if (state == QGalleryAbstractRequest::Canceling) { |
92 | if (!wasIdle) { |
93 | state = QGalleryAbstractRequest::Canceled; |
94 | |
95 | emit q_func()->canceled(); |
96 | } else { |
97 | state = QGalleryAbstractRequest::Finished; |
98 | } |
99 | emit q_func()->stateChanged(state); |
100 | } |
101 | } |
102 | |
103 | void QGalleryAbstractRequestPrivate::_q_resumed() |
104 | { |
105 | if (state == QGalleryAbstractRequest::Idle && !response->isIdle()) { |
106 | state = QGalleryAbstractRequest::Active; |
107 | |
108 | emit q_func()->stateChanged(state); |
109 | } |
110 | } |
111 | |
112 | void QGalleryAbstractRequestPrivate::_q_progressChanged(int current, int maximum) |
113 | { |
114 | currentProgress = current; |
115 | maximumProgress = maximum; |
116 | |
117 | emit q_func()->progressChanged(current, maximum); |
118 | } |
119 | |
120 | /*! |
121 | \class QGalleryAbstractRequest |
122 | |
123 | \ingroup gallery |
124 | \ingroup gallery-requests |
125 | |
126 | \inmodule QtDocGallery |
127 | |
128 | \brief The QGalleryAbstractRequest class provides a base class for gallery |
129 | requests. |
130 | |
131 | Gallery requests are the interface through which clients can interact with |
132 | a gallery to execute queries or perform actions. QAbstractGalleryRequest |
133 | manages executing requests against a gallery and reporting the state of |
134 | responses. |
135 | |
136 | In order to execute a request it is first necessary to assign the \l gallery |
137 | to the request. If the request is supported by the gallery the \l supported |
138 | property will be true, otherwise if the request is not supported or no |
139 | gallery is assigned to the request \l supported will be false. |
140 | |
141 | Once a request has been assigned a gallery and its own arguments it can be |
142 | \l {execute()}{executed}. As requests are asynchronous results will not |
143 | be available immediately, instead the request will go into an \l Active |
144 | \l state until it is finished. If the request is successful the finished() |
145 | signal will be emitted and if not the error() signal will be emitted, in |
146 | both cases the stateChanged() signal will be emitted with the new state of |
147 | the request. |
148 | |
149 | Active requests can be canceled by calling the cancel() function. |
150 | Canceling a request can also be an asynchronous action and does not always |
151 | prevent a request from finishing successfully such as when the earliest |
152 | possible point to interrupt a request is on completion. If a canceled |
153 | request isn't aborted immediately it will go into the \l Canceling state |
154 | until it is aborted and enters the \l Canceled state or succeeds and enters |
155 | the \l Finished state. |
156 | |
157 | Some requests support automatically updating their results in response to |
158 | changes in their source data or some other event. A request that will |
159 | provide these sort of updates will enter the Idle state upon finishing |
160 | its initial request. From the \l Idle state a request may return to the |
161 | \l Active state itself to refresh its results or update it results |
162 | immeditately if a a new query is not required. Cancelling an idle request |
163 | will put it into the \l Finished state and prevent future updates. |
164 | |
165 | While requests are asynchronous it is possible to use them in a synchronous |
166 | manner by using the waitForFinished() function to block until the request |
167 | has finished. |
168 | */ |
169 | |
170 | /*! |
171 | \enum QGalleryAbstractRequest::State |
172 | |
173 | Identifies the state of a gallery request. |
174 | |
175 | \value Inactive The request has not been executed. |
176 | \value Active The request is currently executing. |
177 | \value Canceling The request was canceled, but hasn't yet reached the |
178 | Canceled state. |
179 | \value Canceled The request was canceled. |
180 | \value Idle The request has finished, but may return to the active state |
181 | in response to an internal event. |
182 | \value Finished The request is finished. |
183 | \value Error The request runs into an error. |
184 | */ |
185 | |
186 | /*! |
187 | \enum QGalleryAbstractRequest::RequestError |
188 | |
189 | \value NoError No error. |
190 | \value NoGallery No gallery found. |
191 | \value NotSupported Request is not supported. |
192 | \value GalleryError The gallery is wrong or corrupt. |
193 | */ |
194 | |
195 | /*! |
196 | \enum QGalleryAbstractRequest::RequestType |
197 | |
198 | Identifies the type of a request. |
199 | |
200 | \value QueryRequest The request is a QGalleryQueryRequest. |
201 | \value ItemRequest The request is a QGalleryItemRequest. |
202 | \value TypeRequest The request is a QGalleryTypeRequest |
203 | */ |
204 | |
205 | /*! |
206 | Constructs a new gallery \a type request. |
207 | |
208 | The \a parent is passed to QObject. |
209 | */ |
210 | |
211 | QGalleryAbstractRequest::QGalleryAbstractRequest(RequestType type, QObject *parent) |
212 | : QObject(parent) |
213 | , d_ptr(new QGalleryAbstractRequestPrivate(0, type)) |
214 | { |
215 | d_ptr->q_ptr = this; |
216 | } |
217 | |
218 | /*! |
219 | Constructs a new \a type request for the given \a gallery. |
220 | |
221 | The \a parent is passed to QObject. |
222 | */ |
223 | |
224 | QGalleryAbstractRequest::QGalleryAbstractRequest( |
225 | QAbstractGallery *gallery, RequestType type, QObject *parent) |
226 | : QObject(parent) |
227 | , d_ptr(new QGalleryAbstractRequestPrivate(gallery, type)) |
228 | { |
229 | d_ptr->q_ptr = this; |
230 | } |
231 | |
232 | /*! |
233 | \internal |
234 | */ |
235 | |
236 | QGalleryAbstractRequest::QGalleryAbstractRequest(QGalleryAbstractRequestPrivate &dd, QObject *parent) |
237 | : QObject(parent) |
238 | , d_ptr(&(dd)) |
239 | { |
240 | d_ptr->q_ptr = this; |
241 | } |
242 | |
243 | /*! |
244 | Destroys a gallery request. |
245 | */ |
246 | |
247 | QGalleryAbstractRequest::~QGalleryAbstractRequest() |
248 | { |
249 | } |
250 | |
251 | /*! |
252 | \property QGalleryAbstractRequest::gallery |
253 | |
254 | \brief The gallery service a request acts on. |
255 | */ |
256 | |
257 | QAbstractGallery *QGalleryAbstractRequest::gallery() const |
258 | { |
259 | return d_ptr->gallery.data(); |
260 | } |
261 | |
262 | void QGalleryAbstractRequest::setGallery(QAbstractGallery *gallery) |
263 | { |
264 | if (d_ptr->gallery.data() != gallery) { |
265 | d_ptr->gallery = gallery; |
266 | |
267 | emit galleryChanged(); |
268 | emit supportedChanged(); |
269 | } |
270 | } |
271 | |
272 | /*! |
273 | \fn QGalleryAbstractRequest::galleryChanged() |
274 | |
275 | Signals that the value of \l gallery has changed. |
276 | */ |
277 | |
278 | /*! |
279 | \property QGalleryAbstractRequest::supported |
280 | |
281 | \brief Whether a request is supported by its current \a gallery. |
282 | */ |
283 | |
284 | bool QGalleryAbstractRequest::isSupported() const |
285 | { |
286 | return d_ptr->gallery && d_ptr->gallery.data()->isRequestSupported(type: d_ptr->type); |
287 | } |
288 | |
289 | /*! |
290 | \fn QGalleryAbstractRequest::supportedChanged() |
291 | |
292 | Signals the \l supported property has changed. |
293 | */ |
294 | |
295 | |
296 | /*! |
297 | Returns the type of a request. |
298 | */ |
299 | QGalleryAbstractRequest::RequestType QGalleryAbstractRequest::type() const |
300 | { |
301 | return d_ptr->type; |
302 | } |
303 | |
304 | /*! |
305 | \property QGalleryAbstractRequest::state |
306 | |
307 | \brief The state of a request. |
308 | */ |
309 | |
310 | QGalleryAbstractRequest::State QGalleryAbstractRequest::state() const |
311 | { |
312 | return d_ptr->state; |
313 | } |
314 | |
315 | /*! |
316 | \property QGalleryAbstractRequest::error |
317 | |
318 | \brief The error encountered by an unsuccessful request. |
319 | |
320 | Common errors are defined in \l Error, more specific errors are defined by |
321 | the gallery implementations such as in QDocumentGallery::Error. |
322 | */ |
323 | |
324 | int QGalleryAbstractRequest::error() const |
325 | { |
326 | return d_ptr->error; |
327 | } |
328 | |
329 | /*! |
330 | \property QGalleryAbstractRequest::errorString |
331 | |
332 | \brief A string describing the cause of an \l error in more detail. |
333 | |
334 | This may be an empty string if more information is not known. |
335 | */ |
336 | |
337 | QString QGalleryAbstractRequest::errorString() const |
338 | { |
339 | return d_ptr->errorString; |
340 | } |
341 | |
342 | /*! |
343 | \fn QGalleryAbstractRequest::errorChanged() |
344 | |
345 | Signals that the \l error and \l errorString properties have changed. |
346 | */ |
347 | |
348 | /*! |
349 | \property QGalleryAbstractRequest::currentProgress |
350 | |
351 | \brief the current progress of a request. |
352 | */ |
353 | |
354 | int QGalleryAbstractRequest::currentProgress() const |
355 | { |
356 | return d_func()->currentProgress; |
357 | } |
358 | |
359 | /*! |
360 | \property QGalleryAbstractRequest::maximumProgress |
361 | |
362 | \brief the maximum value of \l currentProgress |
363 | */ |
364 | |
365 | int QGalleryAbstractRequest::maximumProgress() const |
366 | { |
367 | return d_func()->maximumProgress; |
368 | } |
369 | |
370 | /*! |
371 | \fn QGalleryAbstractRequest::progressChanged(int current, int maximum) |
372 | |
373 | Signals that the \a current or \a maximum progress value has changed. |
374 | */ |
375 | |
376 | /*! |
377 | Waits for \a msecs for the a request to finish. |
378 | |
379 | Returns true if the request has finished on return, and returns false if the |
380 | wait time expires or the request is inactive or idle. |
381 | */ |
382 | bool QGalleryAbstractRequest::waitForFinished(int msecs) |
383 | { |
384 | return d_ptr->response && d_ptr->state == Active |
385 | ? d_ptr->response->waitForFinished(msecs) |
386 | : true; |
387 | } |
388 | |
389 | /*! |
390 | Executes a request. |
391 | |
392 | \b {Note}: A valid \l gallery must be set before a request can be |
393 | executed. |
394 | */ |
395 | |
396 | void QGalleryAbstractRequest::execute() |
397 | { |
398 | const int oldError = d_ptr->error; |
399 | |
400 | d_ptr->error = NoError; |
401 | d_ptr->errorString = QString(); |
402 | |
403 | if (!d_ptr->gallery) { |
404 | d_ptr->state = Error; |
405 | d_ptr->error = NoGallery; |
406 | d_ptr->errorString = tr(s: "No gallery has been set on the %1." , c: "%1 = class name" ) |
407 | .arg(a: QString::fromLatin1(str: metaObject()->className())); |
408 | |
409 | if (d_ptr->response) { |
410 | QScopedPointer<QGalleryAbstractResponse> oldResponse(d_ptr->response.take()); |
411 | |
412 | Q_UNUSED(oldResponse); |
413 | |
414 | setResponse(0); |
415 | } |
416 | |
417 | emit error(error: d_ptr->error, errorString: d_ptr->errorString); |
418 | emit errorChanged(); |
419 | } else { |
420 | QScopedPointer<QGalleryAbstractResponse> oldResponse( |
421 | d_ptr->gallery.data()->createResponse(request: this)); |
422 | d_ptr->response.swap(other&: oldResponse); |
423 | |
424 | if (d_ptr->response) { |
425 | d_ptr->error = d_ptr->response->error(); |
426 | |
427 | if (d_ptr->error != NoError) { |
428 | d_ptr->errorString = d_ptr->response->errorString(); |
429 | d_ptr->state = Error; |
430 | |
431 | d_ptr->response.reset(); |
432 | |
433 | if (oldResponse) |
434 | setResponse(0); |
435 | |
436 | emit error(error: d_ptr->error, errorString: d_ptr->errorString); |
437 | emit errorChanged(); |
438 | } else { |
439 | if (d_ptr->response->isActive()) { |
440 | d_ptr->state = Active; |
441 | d_ptr->wasIdle = false; |
442 | } else if (d_ptr->response->isIdle()) { |
443 | d_ptr->state = Idle; |
444 | d_ptr->wasIdle = true; |
445 | } else { |
446 | d_ptr->state = Finished; |
447 | } |
448 | |
449 | connect(sender: d_ptr->response.data(), SIGNAL(finished()), receiver: this, SLOT(_q_finished())); |
450 | connect(sender: d_ptr->response.data(), SIGNAL(resumed()), receiver: this, SLOT(_q_resumed())); |
451 | connect(sender: d_ptr->response.data(), SIGNAL(canceled()), receiver: this, SLOT(_q_canceled())); |
452 | connect(sender: d_ptr->response.data(), SIGNAL(progressChanged(int,int)), |
453 | receiver: this, SLOT(_q_progressChanged(int,int))); |
454 | |
455 | setResponse(d_ptr->response.data()); |
456 | } |
457 | |
458 | oldResponse.reset(); |
459 | } else { |
460 | d_ptr->state = Error; |
461 | d_ptr->error = NotSupported; |
462 | d_ptr->errorString = tr( |
463 | s: "%1 is not supported by %2." , c: "%1 = interface, %2 = gallery implementation" ) |
464 | .arg(a: QString::fromLatin1(str: metaObject()->className())) |
465 | .arg(a: QString::fromLatin1(str: d_ptr->gallery.data()->metaObject()->className())); |
466 | |
467 | if (oldResponse) |
468 | setResponse(0); |
469 | |
470 | oldResponse.reset(); |
471 | |
472 | emit error(error: d_ptr->error, errorString: d_ptr->errorString); |
473 | emit errorChanged(); |
474 | } |
475 | |
476 | if (d_ptr->currentProgress != 0 || d_ptr->maximumProgress != 0) { |
477 | d_ptr->currentProgress = 0; |
478 | d_ptr->maximumProgress = 0; |
479 | |
480 | emit progressChanged(current: 0, maximum: 0); |
481 | } |
482 | |
483 | if (d_ptr->state == Finished || d_ptr->state == Idle) |
484 | emit finished(); |
485 | } |
486 | |
487 | if (oldError != NoError && d_ptr->error == NoError) |
488 | emit errorChanged(); |
489 | |
490 | emit stateChanged(state: d_ptr->state); |
491 | } |
492 | |
493 | /*! |
494 | Cancels the execution of a request. If the request is idle this will stop |
495 | any future updates. |
496 | */ |
497 | |
498 | void QGalleryAbstractRequest::cancel() |
499 | { |
500 | if (d_ptr->state == Active || d_ptr->state == Idle) { |
501 | d_ptr->state = Canceling; |
502 | d_ptr->response->cancel(); |
503 | |
504 | if (d_ptr->state == Canceling) |
505 | emit stateChanged(state: d_ptr->state); |
506 | } |
507 | } |
508 | |
509 | /*! |
510 | Clears the results of a request. |
511 | |
512 | If the request is active or idle it will be canceled. |
513 | */ |
514 | |
515 | void QGalleryAbstractRequest::clear() |
516 | { |
517 | const int oldError = d_ptr->error; |
518 | |
519 | d_ptr->error = NoError; |
520 | d_ptr->errorString = QString(); |
521 | |
522 | if (d_ptr->response) { |
523 | QScopedPointer<QGalleryAbstractResponse> oldResponse(d_ptr->response.take()); |
524 | |
525 | d_ptr->state = Inactive; |
526 | |
527 | setResponse(0); |
528 | |
529 | oldResponse.reset(); |
530 | |
531 | if (d_ptr->currentProgress != 0 || d_ptr->maximumProgress != 0) { |
532 | d_ptr->currentProgress = 0; |
533 | d_ptr->maximumProgress = 0; |
534 | |
535 | emit progressChanged(current: 0, maximum: 0); |
536 | } |
537 | |
538 | emit stateChanged(state: d_ptr->state); |
539 | } else if (d_ptr->state == Error) { |
540 | d_ptr->state = Inactive; |
541 | |
542 | emit stateChanged(state: d_ptr->state); |
543 | } |
544 | |
545 | if (oldError != NoError) |
546 | emit errorChanged(); |
547 | } |
548 | |
549 | /*! |
550 | \fn QGalleryAbstractRequest::finished() |
551 | |
552 | Signals that a request has finished. |
553 | */ |
554 | |
555 | /*! |
556 | \fn QGalleryAbstractRequest::canceled() |
557 | |
558 | Signals that a request was canceled before it could finish. |
559 | */ |
560 | |
561 | /*! |
562 | \fn QGalleryAbstractRequest::stateChanged(QGalleryAbstractRequest::State state) |
563 | |
564 | Signals that the \a state of a request has changed. |
565 | */ |
566 | |
567 | /*! |
568 | \fn QGalleryAbstractRequest::error(int error, const QString &errorString) |
569 | |
570 | Signals that a request failed with the given \a error. The \a errorString |
571 | may provide more detail. |
572 | */ |
573 | |
574 | /*! |
575 | \fn QGalleryAbstractRequest::setResponse(QGalleryAbstractResponse *response) |
576 | |
577 | Sets the \a response to an executed request. |
578 | */ |
579 | |
580 | #include "moc_qgalleryabstractrequest.cpp" |
581 | |
582 | QT_END_NAMESPACE_DOCGALLERY |
583 | |