source: trunk/src/qt3support/network/q3networkprotocol.cpp@ 561

Last change on this file since 561 was 561, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.1 sources.

File size: 36.6 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the Qt3Support module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "q3networkprotocol.h"
43
44#ifndef QT_NO_NETWORKPROTOCOL
45
46#include "q3localfs.h"
47#include "q3urloperator.h"
48#include "qtimer.h"
49#include "qmap.h"
50#include "q3ptrqueue.h"
51#include "q3valuelist.h"
52#include "qurlinfo.h"
53#include <private/qobject_p.h>
54
55QT_BEGIN_NAMESPACE
56
57//#define Q3NETWORKPROTOCOL_DEBUG
58#define NETWORK_OP_DELAY 1000
59
60extern Q_COMPAT_EXPORT Q3NetworkProtocolDict *q3networkProtocolRegister;
61
62Q3NetworkProtocolDict *q3networkProtocolRegister = 0;
63
64class Q3NetworkProtocolPrivate
65{
66public:
67 Q3NetworkProtocolPrivate( Q3NetworkProtocol *p )
68 {
69 url = 0;
70 opInProgress = 0;
71 opStartTimer = new QTimer( p );
72 removeTimer = new QTimer( p );
73 operationQueue.setAutoDelete( false );
74 autoDelete = false;
75 removeInterval = 10000;
76 oldOps.setAutoDelete( false );
77 }
78
79 ~Q3NetworkProtocolPrivate()
80 {
81 removeTimer->stop();
82 if ( opInProgress ) {
83 if ( opInProgress == operationQueue.head() )
84 operationQueue.dequeue();
85 opInProgress->free();
86 }
87 while ( operationQueue.head() ) {
88 operationQueue.head()->free();
89 operationQueue.dequeue();
90 }
91 while ( oldOps.first() ) {
92 oldOps.first()->free();
93 oldOps.removeFirst();
94 }
95 delete opStartTimer;
96 }
97
98 Q3UrlOperator *url;
99 Q3PtrQueue< Q3NetworkOperation > operationQueue;
100 Q3NetworkOperation *opInProgress;
101 QTimer *opStartTimer, *removeTimer;
102 int removeInterval;
103 bool autoDelete;
104 Q3PtrList< Q3NetworkOperation > oldOps;
105};
106
107/*!
108 \class Q3NetworkProtocol
109 \brief The Q3NetworkProtocol class provides a common API for network protocols.
110
111 \compat
112
113 This is a base class which should be used for network protocols
114 implementations that can then be used in Qt (e.g. in the file
115 dialog) together with the Q3UrlOperator.
116
117 The easiest way to implement a new network protocol is to
118 reimplement the operation*() methods, e.g. operationGet(), etc.
119 Only the supported operations should be reimplemented. To specify
120 which operations are supported, also reimplement
121 supportedOperations() and return an int that is OR'd together
122 using the supported operations from the \l
123 Q3NetworkProtocol::Operation enum.
124
125 When you implement a network protocol this way, it is important to
126 emit the correct signals. Also, always emit the finished() signal
127 when an operation is done (on success \e and on failure). Qt
128 relies on correctly emitted finished() signals.
129*/
130
131/*!
132 \fn void Q3NetworkProtocol::newChildren( const Q3ValueList<QUrlInfo> &i, Q3NetworkOperation *op )
133
134 This signal is emitted after listChildren() was called and new
135 children (files) have been read from the list of files. \a i holds
136 the information about the new children. \a op is the pointer to
137 the operation object which contains all the information about the
138 operation, including the state, etc.
139
140 When a protocol emits this signal, Q3NetworkProtocol is smart
141 enough to let the Q3UrlOperator, which is used by the network
142 protocol, emit its corresponding signal.
143
144 When implementing your own network protocol and reading children,
145 you usually don't read one child at once, but rather a list of
146 them. That's why this signal takes a list of QUrlInfo objects. If
147 you prefer to read just one child at a time you can use the
148 convenience signal newChild(), which takes a single QUrlInfo
149 object.
150*/
151
152/*!
153 \fn void Q3NetworkProtocol::newChild( const QUrlInfo &i, Q3NetworkOperation *op )
154
155 This signal is emitted if a new child (file) has been read.
156 Q3NetworkProtocol automatically connects it to a slot which creates
157 a list of QUrlInfo objects (with just one QUrlInfo \a i) and emits
158 the newChildren() signal with this list. \a op is the pointer to
159 the operation object which contains all the information about the
160 operation that has finished, including the state, etc.
161
162 This is just a convenience signal useful for implementing your own
163 network protocol. In all other cases connect to the newChildren()
164 signal with its list of QUrlInfo objects.
165*/
166
167/*!
168 \fn void Q3NetworkProtocol::finished( Q3NetworkOperation *op )
169
170 This signal is emitted when an operation finishes. This signal is
171 always emitted, for both success and failure. \a op is the pointer
172 to the operation object which contains all the information about
173 the operation, including the state, etc. Check the state and error
174 code of the operation object to determine whether or not the
175 operation was successful.
176
177 When a protocol emits this signal, Q3NetworkProtocol is smart
178 enough to let the Q3UrlOperator, which is used by the network
179 protocol, emit its corresponding signal.
180*/
181
182/*!
183 \fn void Q3NetworkProtocol::start( Q3NetworkOperation *op )
184
185 Some operations (such as listChildren()) emit this signal when
186 they start processing the operation. \a op is the pointer to the
187 operation object which contains all the information about the
188 operation, including the state, etc.
189
190 When a protocol emits this signal, Q3NetworkProtocol is smart
191 enough to let the Q3UrlOperator, which is used by the network
192 protocol, emit its corresponding signal.
193*/
194
195/*!
196 \fn void Q3NetworkProtocol::createdDirectory( const QUrlInfo &i, Q3NetworkOperation *op )
197
198 This signal is emitted when mkdir() has been successful and the
199 directory has been created. \a i holds the information about the
200 new directory. \a op is the pointer to the operation object which
201 contains all the information about the operation, including the
202 state, etc. Using op->arg( 0 ), you can get the file name of the
203 new directory.
204
205 When a protocol emits this signal, Q3NetworkProtocol is smart
206 enough to let the Q3UrlOperator, which is used by the network
207 protocol, emit its corresponding signal.
208*/
209
210/*!
211 \fn void Q3NetworkProtocol::removed( Q3NetworkOperation *op )
212
213 This signal is emitted when remove() has been succesiisful and the
214 file has been removed. \a op holds the file name of the removed
215 file in the first argument, accessible with op->arg( 0 ). \a op is
216 the pointer to the operation object which contains all the
217 information about the operation, including the state, etc.
218
219 When a protocol emits this signal, Q3NetworkProtocol is smart
220 enough to let the Q3UrlOperator, which is used by the network
221 protocol, emit its corresponding signal.
222*/
223
224/*!
225 \fn void Q3NetworkProtocol::itemChanged( Q3NetworkOperation *op )
226
227 This signal is emitted whenever a file which is a child of this
228 URL has been changed, e.g. by successfully calling rename(). \a op
229 holds the original and the new file names in the first and second
230 arguments, accessible with op->arg( 0 ) and op->arg( 1 )
231 respectively. \a op is the pointer to the operation object which
232 contains all the information about the operation, including the
233 state, etc.
234
235 When a protocol emits this signal, Q3NetworkProtocol is smart
236 enough to let the Q3UrlOperator, which is used by the network
237 protocol, emit its corresponding signal.
238*/
239
240/*!
241 \fn void Q3NetworkProtocol::data( const QByteArray &data,
242 Q3NetworkOperation *op )
243
244 This signal is emitted when new \a data has been received after
245 calling get() or put(). \a op holds the name of the file from
246 which data is retrieved or uploaded in its first argument, and the
247 (raw) data in its second argument. You can get them with
248 op->arg( 0 ) and op->rawArg( 1 ). \a op is the pointer to the
249 operation object, which contains all the information about the
250 operation, including the state, etc.
251
252 When a protocol emits this signal, Q3NetworkProtocol is smart
253 enough to let the Q3UrlOperator (which is used by the network
254 protocol) emit its corresponding signal.
255*/
256
257/*!
258 \fn void Q3NetworkProtocol::dataTransferProgress( int bytesDone, int bytesTotal, Q3NetworkOperation *op )
259
260 This signal is emitted during the transfer of data (using put() or
261 get()). \a bytesDone is how many bytes of \a bytesTotal have been
262 transferred. \a bytesTotal may be -1, which means that the total
263 number of bytes is not known. \a op is the pointer to the
264 operation object which contains all the information about the
265 operation, including the state, etc.
266
267 When a protocol emits this signal, Q3NetworkProtocol is smart
268 enough to let the Q3UrlOperator, which is used by the network
269 protocol, emit its corresponding signal.
270*/
271
272/*!
273 \fn void Q3NetworkProtocol::connectionStateChanged( int state, const QString &data )
274
275 This signal is emitted whenever the state of the connection of the
276 network protocol is changed. \a state describes the new state,
277 which is one of, \c ConHostFound, \c ConConnected or \c ConClosed.
278 \a data is a message text.
279*/
280
281/*!
282 \enum Q3NetworkProtocol::State
283
284 This enum contains the state that a Q3NetworkOperation can have.
285
286 \value StWaiting The operation is in the Q3NetworkProtocol's queue
287 waiting to be prcessed.
288
289 \value StInProgress The operation is being processed.
290
291 \value StDone The operation has been processed successfully.
292
293 \value StFailed The operation has been processed but an error occurred.
294
295 \value StStopped The operation has been processed but has been
296 stopped before it finished, and is waiting to be processed.
297
298*/
299
300/*!
301 \enum Q3NetworkProtocol::Operation
302
303 This enum lists the possible operations that a network protocol
304 can support. supportedOperations() returns an int of these that is
305 OR'd together. Also, the type() of a Q3NetworkOperation is always
306 one of these values.
307
308 \value OpListChildren List the children of a URL, e.g. of a directory.
309 \value OpMkDir Create a directory.
310 \value OpRemove Remove a child (e.g. a file).
311 \value OpRename Rename a child (e.g. a file).
312 \value OpGet Get data from a location.
313 \value OpPut Put data to a location.
314 \omitvalue OpMkdir
315*/
316
317/*!
318 \enum Q3NetworkProtocol::ConnectionState
319
320 When the connection state of a network protocol changes it emits
321 the signal connectionStateChanged(). The first argument is one of
322 the following values:
323
324 \value ConHostFound Host has been found.
325 \value ConConnected Connection to the host has been established.
326 \value ConClosed Connection has been closed.
327*/
328
329/*!
330 \enum Q3NetworkProtocol::Error
331
332 When an operation fails (finishes unsuccessfully), the
333 Q3NetworkOperation of the operation returns an error code which has
334 one of the following values:
335
336 \value NoError No error occurred.
337
338 \value ErrValid The URL you are operating on is not valid.
339
340 \value ErrUnknownProtocol There is no protocol implementation
341 available for the protocol of the URL you are operating on (e.g.
342 if the protocol is http and no http implementation has been
343 registered).
344
345 \value ErrUnsupported The operation is not supported by the
346 protocol.
347
348 \value ErrParse The URL could not be parsed correctly.
349
350 \value ErrLoginIncorrect You needed to login but the username
351 or password is wrong.
352
353 \value ErrHostNotFound The specified host (in the URL) couldn't
354 be found.
355
356 \value ErrListChildren An error occurred while listing the
357 children (files).
358
359 \value ErrMkDir An error occurred when creating a directory.
360
361 \value ErrRemove An error occurred when removing a child (file).
362
363 \value ErrRename An error occurred when renaming a child (file).
364
365 \value ErrGet An error occurred while getting (retrieving) data.
366
367 \value ErrPut An error occurred while putting (uploading) data.
368
369 \value ErrFileNotExisting A file which is needed by the operation
370 doesn't exist.
371
372 \value ErrPermissionDenied Permission for doing the operation has
373 been denied.
374 \omitvalue ErrMkdir
375 \omitvalue ErrListChlidren
376
377 You should also use these error codes when implementing custom
378 network protocols. If this is not possible, you can define your own
379 error codes by using integer values that don't conflict with any
380 of these values.
381*/
382
383/*!
384 Constructor of the network protocol base class. Does some
385 initialization and connecting of signals and slots.
386*/
387
388Q3NetworkProtocol::Q3NetworkProtocol()
389 : QObject()
390{
391 d = new Q3NetworkProtocolPrivate( this );
392
393 connect( d->opStartTimer, SIGNAL(timeout()),
394 this, SLOT(startOps()) );
395 connect( d->removeTimer, SIGNAL(timeout()),
396 this, SLOT(removeMe()) );
397
398 if ( url() ) {
399 connect( this, SIGNAL(data(QByteArray,Q3NetworkOperation*)),
400 url(), SIGNAL(data(QByteArray,Q3NetworkOperation*)) );
401 connect( this, SIGNAL(finished(Q3NetworkOperation*)),
402 url(), SIGNAL(finished(Q3NetworkOperation*)) );
403 connect( this, SIGNAL(start(Q3NetworkOperation*)),
404 url(), SIGNAL(start(Q3NetworkOperation*)) );
405 connect( this, SIGNAL(newChildren(Q3ValueList<QUrlInfo>,Q3NetworkOperation*)),
406 url(), SIGNAL(newChildren(Q3ValueList<QUrlInfo>,Q3NetworkOperation*)) );
407 connect( this, SIGNAL(newChildren(Q3ValueList<QUrlInfo>,Q3NetworkOperation*)),
408 url(), SLOT(addEntry(Q3ValueList<QUrlInfo>)) );
409 connect( this, SIGNAL(createdDirectory(QUrlInfo,Q3NetworkOperation*)),
410 url(), SIGNAL(createdDirectory(QUrlInfo,Q3NetworkOperation*)) );
411 connect( this, SIGNAL(removed(Q3NetworkOperation*)),
412 url(), SIGNAL(removed(Q3NetworkOperation*)) );
413 connect( this, SIGNAL(itemChanged(Q3NetworkOperation*)),
414 url(), SIGNAL(itemChanged(Q3NetworkOperation*)) );
415 connect( this, SIGNAL(dataTransferProgress(int,int,Q3NetworkOperation*)),
416 url(), SIGNAL(dataTransferProgress(int,int,Q3NetworkOperation*)) );
417 connect( this, SIGNAL(connectionStateChanged(int,QString)),
418 url(), SIGNAL(connectionStateChanged(int,QString)) );
419 }
420
421 connect( this, SIGNAL(finished(Q3NetworkOperation*)),
422 this, SLOT(processNextOperation(Q3NetworkOperation*)) );
423 connect( this, SIGNAL(newChild(QUrlInfo,Q3NetworkOperation*)),
424 this, SLOT(emitNewChildren(QUrlInfo,Q3NetworkOperation*)) );
425
426}
427
428/*!
429 Destructor.
430*/
431
432Q3NetworkProtocol::~Q3NetworkProtocol()
433{
434 delete d;
435}
436
437/*!
438 Sets the Q3UrlOperator, on which the protocol works, to \a u.
439
440 \sa Q3UrlOperator
441*/
442
443void Q3NetworkProtocol::setUrl( Q3UrlOperator *u )
444{
445 if ( url() ) {
446 disconnect( this, SIGNAL(data(QByteArray,Q3NetworkOperation*)),
447 url(), SIGNAL(data(QByteArray,Q3NetworkOperation*)) );
448 disconnect( this, SIGNAL(finished(Q3NetworkOperation*)),
449 url(), SIGNAL(finished(Q3NetworkOperation*)) );
450 disconnect( this, SIGNAL(start(Q3NetworkOperation*)),
451 url(), SIGNAL(start(Q3NetworkOperation*)) );
452 disconnect( this, SIGNAL(newChildren(Q3ValueList<QUrlInfo>,Q3NetworkOperation*)),
453 url(), SIGNAL(newChildren(Q3ValueList<QUrlInfo>,Q3NetworkOperation*)) );
454 disconnect( this, SIGNAL(newChildren(Q3ValueList<QUrlInfo>,Q3NetworkOperation*)),
455 url(), SLOT(addEntry(Q3ValueList<QUrlInfo>)) );
456 disconnect( this, SIGNAL(createdDirectory(QUrlInfo,Q3NetworkOperation*)),
457 url(), SIGNAL(createdDirectory(QUrlInfo,Q3NetworkOperation*)) );
458 disconnect( this, SIGNAL(removed(Q3NetworkOperation*)),
459 url(), SIGNAL(removed(Q3NetworkOperation*)) );
460 disconnect( this, SIGNAL(itemChanged(Q3NetworkOperation*)),
461 url(), SIGNAL(itemChanged(Q3NetworkOperation*)) );
462 disconnect( this, SIGNAL(dataTransferProgress(int,int,Q3NetworkOperation*)),
463 url(), SIGNAL(dataTransferProgress(int,int,Q3NetworkOperation*)) );
464 disconnect( this, SIGNAL(connectionStateChanged(int,QString)),
465 url(), SIGNAL(connectionStateChanged(int,QString)) );
466 }
467
468
469 // ### if autoDelete is true, we should delete the Q3UrlOperator (something
470 // like below; but that is not possible since it would delete this, too).
471 //if ( d->autoDelete && (d->url!=u) ) {
472 // delete d->url; // destructor deletes the network protocol
473 //}
474 d->url = u;
475
476 if ( url() ) {
477 connect( this, SIGNAL(data(QByteArray,Q3NetworkOperation*)),
478 url(), SIGNAL(data(QByteArray,Q3NetworkOperation*)) );
479 connect( this, SIGNAL(finished(Q3NetworkOperation*)),
480 url(), SIGNAL(finished(Q3NetworkOperation*)) );
481 connect( this, SIGNAL(start(Q3NetworkOperation*)),
482 url(), SIGNAL(start(Q3NetworkOperation*)) );
483 connect( this, SIGNAL(newChildren(Q3ValueList<QUrlInfo>,Q3NetworkOperation*)),
484 url(), SIGNAL(newChildren(Q3ValueList<QUrlInfo>,Q3NetworkOperation*)) );
485 connect( this, SIGNAL(newChildren(Q3ValueList<QUrlInfo>,Q3NetworkOperation*)),
486 url(), SLOT(addEntry(Q3ValueList<QUrlInfo>)) );
487 connect( this, SIGNAL(createdDirectory(QUrlInfo,Q3NetworkOperation*)),
488 url(), SIGNAL(createdDirectory(QUrlInfo,Q3NetworkOperation*)) );
489 connect( this, SIGNAL(removed(Q3NetworkOperation*)),
490 url(), SIGNAL(removed(Q3NetworkOperation*)) );
491 connect( this, SIGNAL(itemChanged(Q3NetworkOperation*)),
492 url(), SIGNAL(itemChanged(Q3NetworkOperation*)) );
493 connect( this, SIGNAL(dataTransferProgress(int,int,Q3NetworkOperation*)),
494 url(), SIGNAL(dataTransferProgress(int,int,Q3NetworkOperation*)) );
495 connect( this, SIGNAL(connectionStateChanged(int,QString)),
496 url(), SIGNAL(connectionStateChanged(int,QString)) );
497 }
498
499 if ( !d->opInProgress && !d->operationQueue.isEmpty() )
500 d->opStartTimer->start( 0, true );
501}
502
503/*!
504 For processing operations the network protocol base class calls
505 this method quite often. This should be reimplemented by new
506 network protocols. It should return true if the connection is OK
507 (open); otherwise it should return false. If the connection is not
508 open the protocol should open it.
509
510 If the connection can't be opened (e.g. because you already tried
511 but the host couldn't be found), set the state of \a op to
512 Q3NetworkProtocol::StFailed and emit the finished() signal with
513 this Q3NetworkOperation as argument.
514
515 \a op is the operation that needs an open connection.
516*/
517
518bool Q3NetworkProtocol::checkConnection( Q3NetworkOperation * )
519{
520 return true;
521}
522
523/*!
524 Returns an int that is OR'd together using the enum values of
525 \l{Q3NetworkProtocol::Operation}, which describes which operations
526 are supported by the network protocol. Should be reimplemented by
527 new network protocols.
528*/
529
530int Q3NetworkProtocol::supportedOperations() const
531{
532 return 0;
533}
534
535/*!
536 Adds the operation \a op to the operation queue. The operation
537 will be processed as soon as possible. This method returns
538 immediately.
539*/
540
541void Q3NetworkProtocol::addOperation( Q3NetworkOperation *op )
542{
543#ifdef Q3NETWORKPROTOCOL_DEBUG
544 qDebug( "Q3NetworkOperation: addOperation: %p %d", op, op->operation() );
545#endif
546 d->operationQueue.enqueue( op );
547 if ( !d->opInProgress )
548 d->opStartTimer->start( 0, true );
549}
550
551/*!
552 Static method to register a network protocol for Qt. For example,
553 if you have an implementation of NNTP (called Nntp) which is
554 derived from Q3NetworkProtocol, call:
555 \snippet doc/src/snippets/code/src_qt3support_network_q3networkprotocol.cpp 0
556 after which your implementation is registered for future nntp
557 operations.
558
559 The name of the protocol is given in \a protocol and a pointer to
560 the protocol factory is given in \a protocolFactory.
561*/
562
563void Q3NetworkProtocol::registerNetworkProtocol( const QString &protocol,
564 Q3NetworkProtocolFactoryBase *protocolFactory )
565{
566 if ( !q3networkProtocolRegister ) {
567 q3networkProtocolRegister = new Q3NetworkProtocolDict;
568 Q3NetworkProtocol::registerNetworkProtocol( QLatin1String("file"), new Q3NetworkProtocolFactory< Q3LocalFs > );
569 }
570
571 q3networkProtocolRegister->insert( protocol, protocolFactory );
572}
573
574/*!
575 Static method to get a new instance of the network protocol \a
576 protocol. For example, if you need to do some FTP operations, do
577 the following:
578 \snippet doc/src/snippets/code/src_qt3support_network_q3networkprotocol.cpp 1
579 This returns a pointer to a new instance of an ftp implementation
580 or null if no protocol for ftp was registered. The ownership of
581 the pointer is transferred to you, so you must delete it if you
582 don't need it anymore.
583
584 Normally you should not work directly with network protocols, so
585 you will not need to call this method yourself. Instead, use
586 Q3UrlOperator, which makes working with network protocols much more
587 convenient.
588
589 \sa Q3UrlOperator
590*/
591
592Q3NetworkProtocol *Q3NetworkProtocol::getNetworkProtocol( const QString &protocol )
593{
594 if ( !q3networkProtocolRegister ) {
595 q3networkProtocolRegister = new Q3NetworkProtocolDict;
596 Q3NetworkProtocol::registerNetworkProtocol( QLatin1String("file"), new Q3NetworkProtocolFactory< Q3LocalFs > );
597 }
598
599 if ( protocol.isNull() )
600 return 0;
601
602 Q3NetworkProtocolFactoryBase *factory = q3networkProtocolRegister->find( protocol );
603 if ( factory )
604 return factory->createObject();
605
606 return 0;
607}
608
609/*!
610 Returns true if the only protocol registered is for working on the
611 local filesystem; returns false if other network protocols are
612 also registered.
613*/
614
615bool Q3NetworkProtocol::hasOnlyLocalFileSystem()
616{
617 if ( !q3networkProtocolRegister )
618 return false;
619
620 Q3DictIterator< Q3NetworkProtocolFactoryBase > it( *q3networkProtocolRegister );
621 for ( ; it.current(); ++it )
622 if ( it.currentKey() != QLatin1String("file") )
623 return false;
624 return true;
625}
626
627/*!
628 \internal
629 Starts processing network operations.
630*/
631
632void Q3NetworkProtocol::startOps()
633{
634#ifdef Q3NETWORKPROTOCOL_DEBUG
635 qDebug( "Q3NetworkOperation: start processing operations" );
636#endif
637 processNextOperation( 0 );
638}
639
640/*!
641 \internal
642 Processes the operation \a op. It calls the
643 corresponding operation[something]( Q3NetworkOperation * )
644 methods.
645*/
646
647void Q3NetworkProtocol::processOperation( Q3NetworkOperation *op )
648{
649 if ( !op )
650 return;
651
652 switch ( op->operation() ) {
653 case OpListChildren:
654 operationListChildren( op );
655 break;
656 case OpMkDir:
657 operationMkDir( op );
658 break;
659 case OpRemove:
660 operationRemove( op );
661 break;
662 case OpRename:
663 operationRename( op );
664 break;
665 case OpGet:
666 operationGet( op );
667 break;
668 case OpPut:
669 operationPut( op );
670 break;
671 }
672}
673
674/*!
675 When implementing a new network protocol, this method should be
676 reimplemented if the protocol supports listing children (files);
677 this method should then process this Q3NetworkOperation.
678
679 \a op is the pointer to the operation object which contains all
680 the information on the operation that has finished, including the
681 state, etc.
682*/
683
684void Q3NetworkProtocol::operationListChildren( Q3NetworkOperation * )
685{
686}
687
688/*!
689 When implementing a new network protocol, this method should be
690 reimplemented if the protocol supports making directories; this
691 method should then process this Q3NetworkOperation.
692
693 \a op is the pointer to the operation object which contains all
694 the information on the operation that has finished, including the
695 state, etc.
696*/
697
698void Q3NetworkProtocol::operationMkDir( Q3NetworkOperation * )
699{
700}
701
702/*!
703 When implementing a new network protocol, this method should be
704 reimplemented if the protocol supports removing children (files);
705 this method should then process this Q3NetworkOperation.
706
707 \a op is the pointer to the operation object which contains all
708 the information on the operation that has finished, including the
709 state, etc.
710*/
711
712void Q3NetworkProtocol::operationRemove( Q3NetworkOperation * )
713{
714}
715
716/*!
717 When implementing a new network protocol, this method should be
718 reimplemented if the protocol supports renaming children (files);
719 this method should then process this Q3NetworkOperation.
720
721 \a op is the pointer to the operation object which contains all
722 the information on the operation that has finished, including the
723 state, etc.
724*/
725
726void Q3NetworkProtocol::operationRename( Q3NetworkOperation * )
727{
728}
729
730/*!
731 When implementing a new network protocol, this method should be
732 reimplemented if the protocol supports getting data; this method
733 should then process the Q3NetworkOperation.
734
735 \a op is the pointer to the operation object which contains all
736 the information on the operation that has finished, including the
737 state, etc.
738*/
739
740void Q3NetworkProtocol::operationGet( Q3NetworkOperation * )
741{
742}
743
744/*!
745 When implementing a new network protocol, this method should be
746 reimplemented if the protocol supports putting (uploading) data;
747 this method should then process the Q3NetworkOperation.
748
749 \a op is the pointer to the operation object which contains all
750 the information on the operation that has finished, including the
751 state, etc.
752*/
753
754void Q3NetworkProtocol::operationPut( Q3NetworkOperation * )
755{
756}
757
758/*! \internal
759*/
760
761void Q3NetworkProtocol::operationPutChunk( Q3NetworkOperation * )
762{
763}
764
765/*!
766 \internal
767 Handles operations. Deletes the previous operation object and
768 tries to process the next operation. It also checks the connection state
769 and only processes the next operation, if the connection of the protocol
770 is open. Otherwise it waits until the protocol opens the connection.
771*/
772
773void Q3NetworkProtocol::processNextOperation( Q3NetworkOperation *old )
774{
775#ifdef Q3NETWORKPROTOCOL_DEBUG
776 qDebug( "Q3NetworkOperation: process next operation, old: %p", old );
777#endif
778 d->removeTimer->stop();
779
780 if ( old )
781 d->oldOps.append( old );
782 if ( d->opInProgress && d->opInProgress!=old )
783 d->oldOps.append( d->opInProgress );
784
785 if ( d->operationQueue.isEmpty() ) {
786 d->opInProgress = 0;
787 if ( d->autoDelete )
788 d->removeTimer->start( d->removeInterval, true );
789 return;
790 }
791
792 Q3NetworkOperation *op = d->operationQueue.head();
793
794 d->opInProgress = op;
795
796 if ( !checkConnection( op ) ) {
797 if ( op->state() != Q3NetworkProtocol::StFailed ) {
798 d->opStartTimer->start( 0, true );
799 } else {
800 d->operationQueue.dequeue();
801 clearOperationQueue();
802 emit finished( op );
803 }
804
805 return;
806 }
807
808 d->opInProgress = op;
809 d->operationQueue.dequeue();
810 processOperation( op );
811}
812
813/*!
814 Returns the Q3UrlOperator on which the protocol works.
815*/
816
817Q3UrlOperator *Q3NetworkProtocol::url() const
818{
819 return d->url;
820}
821
822/*!
823 Returns the operation, which is being processed, or 0 of no
824 operation is being processed at the moment.
825*/
826
827Q3NetworkOperation *Q3NetworkProtocol::operationInProgress() const
828{
829 return d->opInProgress;
830}
831
832/*!
833 Clears the operation queue.
834*/
835
836void Q3NetworkProtocol::clearOperationQueue()
837{
838 d->operationQueue.dequeue();
839 d->operationQueue.setAutoDelete( true );
840 d->operationQueue.clear();
841}
842
843/*!
844 Stops the current operation that is being processed and clears all
845 waiting operations.
846*/
847
848void Q3NetworkProtocol::stop()
849{
850 Q3NetworkOperation *op = d->opInProgress;
851 clearOperationQueue();
852 if ( op ) {
853 op->setState( StStopped );
854 op->setProtocolDetail( tr( "Operation stopped by the user" ) );
855 emit finished( op );
856 setUrl( 0 );
857 op->free();
858 }
859}
860
861/*!
862 Because it's sometimes hard to take care of removing network
863 protocol instances, Q3NetworkProtocol provides an auto-delete
864 mechanism. If you set \a b to true, the network protocol instance
865 is removed after it has been inactive for \a i milliseconds (i.e.
866 \a i milliseconds after the last operation has been processed).
867 If you set \a b to false the auto-delete mechanism is switched
868 off.
869
870 If you switch on auto-delete, the Q3NetworkProtocol also deletes
871 its Q3UrlOperator.
872*/
873
874void Q3NetworkProtocol::setAutoDelete( bool b, int i )
875{
876 d->autoDelete = b;
877 d->removeInterval = i;
878}
879
880/*!
881 Returns true if auto-deleting is enabled; otherwise returns false.
882
883 \sa Q3NetworkProtocol::setAutoDelete()
884*/
885
886bool Q3NetworkProtocol::autoDelete() const
887{
888 return d->autoDelete;
889}
890
891/*!
892 \internal
893*/
894
895void Q3NetworkProtocol::removeMe()
896{
897 if ( d->autoDelete ) {
898#ifdef Q3NETWORKPROTOCOL_DEBUG
899 qDebug( "Q3NetworkOperation: autodelete of Q3NetworkProtocol %p", this );
900#endif
901 delete d->url; // destructor deletes the network protocol
902 }
903}
904
905void Q3NetworkProtocol::emitNewChildren( const QUrlInfo &i, Q3NetworkOperation *op )
906{
907 Q3ValueList<QUrlInfo> lst;
908 lst << i;
909 emit newChildren( lst, op );
910}
911
912class Q3NetworkOperationPrivate
913{
914public:
915 Q3NetworkProtocol::Operation operation;
916 Q3NetworkProtocol::State state;
917 QMap<int, QString> args;
918 QMap<int, QByteArray> rawArgs;
919 QString protocolDetail;
920 int errorCode;
921 QTimer *deleteTimer;
922};
923
924/*!
925 \class Q3NetworkOperation
926
927 \brief The Q3NetworkOperation class provides common operations for network protocols.
928
929 \compat
930
931 An object is created to describe the operation and the current
932 state for each operation that a network protocol should process.
933
934 \sa Q3NetworkProtocol
935*/
936
937/*!
938 Constructs a network operation object. \a operation is the type of
939 the operation, and \a arg0, \a arg1 and \a arg2 are the first
940 three arguments of the operation. The state is initialized to
941 Q3NetworkProtocol::StWaiting.
942
943 \sa Q3NetworkProtocol::Operation Q3NetworkProtocol::State
944*/
945
946Q3NetworkOperation::Q3NetworkOperation( Q3NetworkProtocol::Operation operation,
947 const QString &arg0, const QString &arg1,
948 const QString &arg2 )
949{
950 d = new Q3NetworkOperationPrivate;
951 d->deleteTimer = new QTimer( this );
952 connect( d->deleteTimer, SIGNAL(timeout()),
953 this, SLOT(deleteMe()) );
954 d->operation = operation;
955 d->state = Q3NetworkProtocol::StWaiting;
956 d->args[ 0 ] = arg0;
957 d->args[ 1 ] = arg1;
958 d->args[ 2 ] = arg2;
959 d->rawArgs[ 0 ] = QByteArray( 0 );
960 d->rawArgs[ 1 ] = QByteArray( 0 );
961 d->rawArgs[ 2 ] = QByteArray( 0 );
962 d->protocolDetail.clear();
963 d->errorCode = (int)Q3NetworkProtocol::NoError;
964}
965
966/*!
967 Constructs a network operation object. \a operation is the type of
968 the operation, and \a arg0, \a arg1 and \a arg2 are the first
969 three raw data arguments of the operation. The state is
970 initialized to Q3NetworkProtocol::StWaiting.
971
972 \sa Q3NetworkProtocol::Operation Q3NetworkProtocol::State
973*/
974
975Q3NetworkOperation::Q3NetworkOperation( Q3NetworkProtocol::Operation operation,
976 const QByteArray &arg0, const QByteArray &arg1,
977 const QByteArray &arg2 )
978{
979 d = new Q3NetworkOperationPrivate;
980 d->deleteTimer = new QTimer( this );
981 connect( d->deleteTimer, SIGNAL(timeout()),
982 this, SLOT(deleteMe()) );
983 d->operation = operation;
984 d->state = Q3NetworkProtocol::StWaiting;
985 d->args[ 0 ].clear();
986 d->args[ 1 ].clear();
987 d->args[ 2 ].clear();
988 d->rawArgs[ 0 ] = arg0;
989 d->rawArgs[ 1 ] = arg1;
990 d->rawArgs[ 2 ] = arg2;
991 d->protocolDetail.clear();
992 d->errorCode = (int)Q3NetworkProtocol::NoError;
993}
994
995/*!
996 Destructor.
997*/
998
999Q3NetworkOperation::~Q3NetworkOperation()
1000{
1001 qDeleteInEventHandler(d->deleteTimer);
1002 delete d;
1003}
1004
1005/*!
1006 Sets the \a state of the operation object. This should be done by
1007 the network protocol during processing; at the end it should be
1008 set to Q3NetworkProtocol::StDone or Q3NetworkProtocol::StFailed,
1009 depending on success or failure.
1010
1011 \sa Q3NetworkProtocol::State
1012*/
1013
1014void Q3NetworkOperation::setState( Q3NetworkProtocol::State state )
1015{
1016 if ( d->deleteTimer->isActive() ) {
1017 d->deleteTimer->stop();
1018 d->deleteTimer->start( NETWORK_OP_DELAY );
1019 }
1020 d->state = state;
1021}
1022
1023/*!
1024 If the operation failed, the error message can be specified as \a
1025 detail.
1026*/
1027
1028void Q3NetworkOperation::setProtocolDetail( const QString &detail )
1029{
1030 if ( d->deleteTimer->isActive() ) {
1031 d->deleteTimer->stop();
1032 d->deleteTimer->start( NETWORK_OP_DELAY );
1033 }
1034 d->protocolDetail = detail;
1035}
1036
1037/*!
1038 Sets the error code to \a ec.
1039
1040 If the operation failed, the protocol should set an error code to
1041 describe the error in more detail. If possible, one of the error
1042 codes defined in Q3NetworkProtocol should be used.
1043
1044 \sa setProtocolDetail() Q3NetworkProtocol::Error
1045*/
1046
1047void Q3NetworkOperation::setErrorCode( int ec )
1048{
1049 if ( d->deleteTimer->isActive() ) {
1050 d->deleteTimer->stop();
1051 d->deleteTimer->start( NETWORK_OP_DELAY );
1052 }
1053 d->errorCode = ec;
1054}
1055
1056/*!
1057 Sets the network operation's \a{num}-th argument to \a arg.
1058*/
1059
1060void Q3NetworkOperation::setArg( int num, const QString &arg )
1061{
1062 if ( d->deleteTimer->isActive() ) {
1063 d->deleteTimer->stop();
1064 d->deleteTimer->start( NETWORK_OP_DELAY );
1065 }
1066 d->args[ num ] = arg;
1067}
1068
1069/*!
1070 Sets the network operation's \a{num}-th raw data argument to \a arg.
1071*/
1072
1073void Q3NetworkOperation::setRawArg( int num, const QByteArray &arg )
1074{
1075 if ( d->deleteTimer->isActive() ) {
1076 d->deleteTimer->stop();
1077 d->deleteTimer->start( NETWORK_OP_DELAY );
1078 }
1079 d->rawArgs[ num ] = arg;
1080}
1081
1082/*!
1083 Returns the type of the operation.
1084*/
1085
1086Q3NetworkProtocol::Operation Q3NetworkOperation::operation() const
1087{
1088 if ( d->deleteTimer->isActive() ) {
1089 d->deleteTimer->stop();
1090 d->deleteTimer->start( NETWORK_OP_DELAY );
1091 }
1092 return d->operation;
1093}
1094
1095/*!
1096 Returns the state of the operation. You can determine whether an
1097 operation is still waiting to be processed, is being processed,
1098 has been processed successfully, or failed.
1099*/
1100
1101Q3NetworkProtocol::State Q3NetworkOperation::state() const
1102{
1103 if ( d->deleteTimer->isActive() ) {
1104 d->deleteTimer->stop();
1105 d->deleteTimer->start( NETWORK_OP_DELAY );
1106 }
1107 return d->state;
1108}
1109
1110/*!
1111 Returns the operation's \a{num}-th argument. If this argument was
1112 not already set, an empty string is returned.
1113*/
1114
1115QString Q3NetworkOperation::arg( int num ) const
1116{
1117 if ( d->deleteTimer->isActive() ) {
1118 d->deleteTimer->stop();
1119 d->deleteTimer->start( NETWORK_OP_DELAY );
1120 }
1121 return d->args[ num ];
1122}
1123
1124/*!
1125 Returns the operation's \a{num}-th raw data argument. If this
1126 argument was not already set, an empty bytearray is returned.
1127*/
1128
1129QByteArray Q3NetworkOperation::rawArg( int num ) const
1130{
1131 if ( d->deleteTimer->isActive() ) {
1132 d->deleteTimer->stop();
1133 d->deleteTimer->start( NETWORK_OP_DELAY );
1134 }
1135 return d->rawArgs[ num ];
1136}
1137
1138/*!
1139 Returns a detailed error message for the last error. This must
1140 have been set using setProtocolDetail().
1141*/
1142
1143QString Q3NetworkOperation::protocolDetail() const
1144{
1145 if ( d->deleteTimer->isActive() ) {
1146 d->deleteTimer->stop();
1147 d->deleteTimer->start( NETWORK_OP_DELAY );
1148 }
1149 return d->protocolDetail;
1150}
1151
1152/*!
1153 Returns the error code for the last error that occurred.
1154*/
1155
1156int Q3NetworkOperation::errorCode() const
1157{
1158 if ( d->deleteTimer->isActive() ) {
1159 d->deleteTimer->stop();
1160 d->deleteTimer->start( NETWORK_OP_DELAY );
1161 }
1162 return d->errorCode;
1163}
1164
1165/*!
1166 \internal
1167*/
1168
1169QByteArray& Q3NetworkOperation::raw( int num ) const
1170{
1171 if ( d->deleteTimer->isActive() ) {
1172 d->deleteTimer->stop();
1173 d->deleteTimer->start( NETWORK_OP_DELAY );
1174 }
1175 return d->rawArgs[ num ];
1176}
1177
1178/*!
1179 Sets this object to delete itself when it hasn't been used for one
1180 second.
1181
1182 Because Q3NetworkOperation pointers are passed around a lot the
1183 Q3NetworkProtocol generally does not have enough knowledge to
1184 delete these at the correct time. If a Q3NetworkProtocol doesn't
1185 need an operation any more it will call this function instead.
1186
1187 Note: you should never need to call the method yourself.
1188*/
1189
1190void Q3NetworkOperation::free()
1191{
1192 d->deleteTimer->start( NETWORK_OP_DELAY );
1193}
1194
1195/*!
1196 \internal
1197 Internal slot for auto-deletion.
1198*/
1199
1200void Q3NetworkOperation::deleteMe()
1201{
1202 delete this;
1203}
1204
1205QT_END_NAMESPACE
1206
1207#include "moc_q3networkprotocol.cpp"
1208
1209#endif
Note: See TracBrowser for help on using the repository browser.