source: trunk/src/kernel/qnetworkprotocol.cpp@ 64

Last change on this file since 64 was 8, checked in by dmik, 20 years ago

Transferred Qt for OS/2 version 3.3.1-rc5 sources from the CVS

  • Property svn:keywords set to Id
File size: 41.0 KB
Line 
1/****************************************************************************
2** $Id: qnetworkprotocol.cpp 8 2005-11-16 19:36:46Z dmik $
3**
4** Implementation of QNetworkProtocol class
5**
6** Created : 950429
7**
8** Copyright (C) 1992-2003 Trolltech AS. All rights reserved.
9**
10** This file is part of the kernel module of the Qt GUI Toolkit.
11**
12** This file may be distributed under the terms of the Q Public License
13** as defined by Trolltech AS of Norway and appearing in the file
14** LICENSE.QPL included in the packaging of this file.
15**
16** This file may be distributed and/or modified under the terms of the
17** GNU General Public License version 2 as published by the Free Software
18** Foundation and appearing in the file LICENSE.GPL included in the
19** packaging of this file.
20**
21** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
22** licenses may use this file in accordance with the Qt Commercial License
23** Agreement provided with the Software.
24**
25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27**
28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29** information about Qt Commercial License Agreements.
30** See http://www.trolltech.com/qpl/ for QPL licensing information.
31** See http://www.trolltech.com/gpl/ for GPL licensing information.
32**
33** Contact info@trolltech.com if any conditions of this licensing are
34** not clear to you.
35**
36**********************************************************************/
37
38#include "qnetworkprotocol.h"
39
40#ifndef QT_NO_NETWORKPROTOCOL
41
42#include "qlocalfs.h"
43#include "qurloperator.h"
44#include "qtimer.h"
45#include "qmap.h"
46#include "qptrqueue.h"
47
48//#define QNETWORKPROTOCOL_DEBUG
49#define NETWORK_OP_DELAY 1000
50
51extern Q_EXPORT QNetworkProtocolDict *qNetworkProtocolRegister;
52
53QNetworkProtocolDict *qNetworkProtocolRegister = 0;
54
55class QNetworkProtocolPrivate
56{
57public:
58 QNetworkProtocolPrivate( QNetworkProtocol *p )
59 {
60 url = 0;
61 opInProgress = 0;
62 opStartTimer = new QTimer( p );
63 removeTimer = new QTimer( p );
64 operationQueue.setAutoDelete( FALSE );
65 autoDelete = FALSE;
66 removeInterval = 10000;
67 oldOps.setAutoDelete( FALSE );
68 }
69
70 ~QNetworkProtocolPrivate()
71 {
72 removeTimer->stop();
73 if ( opInProgress ) {
74 if ( opInProgress == operationQueue.head() )
75 operationQueue.dequeue();
76 opInProgress->free();
77 }
78 while ( operationQueue.head() ) {
79 operationQueue.head()->free();
80 operationQueue.dequeue();
81 }
82 while ( oldOps.first() ) {
83 oldOps.first()->free();
84 oldOps.removeFirst();
85 }
86 }
87
88 QUrlOperator *url;
89 QPtrQueue< QNetworkOperation > operationQueue;
90 QNetworkOperation *opInProgress;
91 QTimer *opStartTimer, *removeTimer;
92 int removeInterval;
93 bool autoDelete;
94 QPtrList< QNetworkOperation > oldOps;
95};
96
97/*!
98 \class QNetworkProtocol qnetworkprotocol.h
99 \brief The QNetworkProtocol class provides a common API for network protocols.
100\if defined(commercial)
101 It is part of the <a href="commercialeditions.html">Qt Enterprise Edition</a>.
102\endif
103
104 \module network
105 \ingroup io
106 \module network
107 \mainclass
108
109 This is a base class which should be used for network protocols
110 implementations that can then be used in Qt (e.g. in the file
111 dialog) together with the QUrlOperator.
112
113 The easiest way to implement a new network protocol is to
114 reimplement the operation*() methods, e.g. operationGet(), etc.
115 Only the supported operations should be reimplemented. To specify
116 which operations are supported, also reimplement
117 supportedOperations() and return an int that is OR'd together
118 using the supported operations from the \l
119 QNetworkProtocol::Operation enum.
120
121 When you implement a network protocol this way, it is important to
122 emit the correct signals. Also, always emit the finished() signal
123 when an operation is done (on success \e and on failure). Qt
124 relies on correctly emitted finished() signals.
125
126 For a detailed description of the Qt Network Architecture and how
127 to implement and use network protocols in Qt, see the \link
128 network.html Qt Network Documentation\endlink.
129*/
130
131/*!
132 \fn void QNetworkProtocol::newChildren( const QValueList<QUrlInfo> &i, QNetworkOperation *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, QNetworkProtocol is smart
141 enough to let the QUrlOperator, 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 QNetworkProtocol::newChild( const QUrlInfo &i, QNetworkOperation *op )
154
155 This signal is emitted if a new child (file) has been read.
156 QNetworkProtocol 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 QNetworkProtocol::finished( QNetworkOperation *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, QNetworkProtocol is smart
178 enough to let the QUrlOperator, which is used by the network
179 protocol, emit its corresponding signal.
180*/
181
182/*!
183 \fn void QNetworkProtocol::start( QNetworkOperation *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, QNetworkProtocol is smart
191 enough to let the QUrlOperator, which is used by the network
192 protocol, emit its corresponding signal.
193*/
194
195/*!
196 \fn void QNetworkProtocol::createdDirectory( const QUrlInfo &i, QNetworkOperation *op )
197
198 This signal is emitted when mkdir() has been succesful 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, QNetworkProtocol is smart
206 enough to let the QUrlOperator, which is used by the network
207 protocol, emit its corresponding signal.
208*/
209
210/*!
211 \fn void QNetworkProtocol::removed( QNetworkOperation *op )
212
213 This signal is emitted when remove() has been succesful 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, QNetworkProtocol is smart
220 enough to let the QUrlOperator, which is used by the network
221 protocol, emit its corresponding signal.
222*/
223
224/*!
225 \fn void QNetworkProtocol::itemChanged( QNetworkOperation *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, QNetworkProtocol is smart
236 enough to let the QUrlOperator, which is used by the network
237 protocol, emit its corresponding signal.
238*/
239
240/*!
241 \fn void QNetworkProtocol::data( const QByteArray &data,
242 QNetworkOperation *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, QNetworkProtocol is smart
253 enough to let the QUrlOperator (which is used by the network
254 protocol) emit its corresponding signal.
255*/
256
257/*!
258 \fn void QNetworkProtocol::dataTransferProgress( int bytesDone, int bytesTotal, QNetworkOperation *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, QNetworkProtocol is smart
268 enough to let the QUrlOperator, which is used by the network
269 protocol, emit its corresponding signal.
270*/
271
272/*!
273 \fn void QNetworkProtocol::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 QNetworkProtocol::State
283
284 This enum contains the state that a QNetworkOperation can have.
285
286 \value StWaiting The operation is in the QNetworkProtocol'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 succesfully.
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 QNetworkProtocol::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 QNetworkOperation 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*/
315
316/*!
317 \enum QNetworkProtocol::ConnectionState
318
319 When the connection state of a network protocol changes it emits
320 the signal connectionStateChanged(). The first argument is one of
321 the following values:
322
323 \value ConHostFound Host has been found.
324 \value ConConnected Connection to the host has been established.
325 \value ConClosed Connection has been closed.
326*/
327
328/*!
329 \enum QNetworkProtocol::Error
330
331 When an operation fails (finishes unsuccessfully), the
332 QNetworkOperation of the operation returns an error code which has
333 one of the following values:
334
335 \value NoError No error occurred.
336
337 \value ErrValid The URL you are operating on is not valid.
338
339 \value ErrUnknownProtocol There is no protocol implementation
340 available for the protocol of the URL you are operating on (e.g.
341 if the protocol is http and no http implementation has been
342 registered).
343
344 \value ErrUnsupported The operation is not supported by the
345 protocol.
346
347 \value ErrParse The URL could not be parsed correctly.
348
349 \value ErrLoginIncorrect You needed to login but the username
350 or password is wrong.
351
352 \value ErrHostNotFound The specified host (in the URL) couldn't
353 be found.
354
355 \value ErrListChildren An error occurred while listing the
356 children (files).
357
358 \value ErrMkDir An error occurred when creating a directory.
359
360 \value ErrRemove An error occurred when removing a child (file).
361
362 \value ErrRename An error occurred when renaming a child (file).
363
364 \value ErrGet An error occurred while getting (retrieving) data.
365
366 \value ErrPut An error occurred while putting (uploading) data.
367
368 \value ErrFileNotExisting A file which is needed by the operation
369 doesn't exist.
370
371 \value ErrPermissionDenied Permission for doing the operation has
372 been denied.
373
374 You should also use these error codes when implementing custom
375 network protocols. If this is not possible, you can define your own
376 error codes by using integer values that don't conflict with any
377 of these values.
378*/
379
380/*!
381 Constructor of the network protocol base class. Does some
382 initialization and connecting of signals and slots.
383*/
384
385QNetworkProtocol::QNetworkProtocol()
386 : QObject()
387{
388 d = new QNetworkProtocolPrivate( this );
389
390 connect( d->opStartTimer, SIGNAL( timeout() ),
391 this, SLOT( startOps() ) );
392 connect( d->removeTimer, SIGNAL( timeout() ),
393 this, SLOT( removeMe() ) );
394
395 if ( url() ) {
396 connect( this, SIGNAL( data(const QByteArray&,QNetworkOperation*) ),
397 url(), SIGNAL( data(const QByteArray&,QNetworkOperation*) ) );
398 connect( this, SIGNAL( finished(QNetworkOperation*) ),
399 url(), SIGNAL( finished(QNetworkOperation*) ) );
400 connect( this, SIGNAL( start(QNetworkOperation*) ),
401 url(), SIGNAL( start(QNetworkOperation*) ) );
402 connect( this, SIGNAL( newChildren(const QValueList<QUrlInfo>&,QNetworkOperation*) ),
403 url(), SIGNAL( newChildren(const QValueList<QUrlInfo>&,QNetworkOperation*) ) );
404 connect( this, SIGNAL( newChildren(const QValueList<QUrlInfo>&,QNetworkOperation*) ),
405 url(), SLOT( addEntry(const QValueList<QUrlInfo>&) ) );
406 connect( this, SIGNAL( createdDirectory(const QUrlInfo&,QNetworkOperation*) ),
407 url(), SIGNAL( createdDirectory(const QUrlInfo&,QNetworkOperation*) ) );
408 connect( this, SIGNAL( removed(QNetworkOperation*) ),
409 url(), SIGNAL( removed(QNetworkOperation*) ) );
410 connect( this, SIGNAL( itemChanged(QNetworkOperation*) ),
411 url(), SIGNAL( itemChanged(QNetworkOperation*) ) );
412 connect( this, SIGNAL( dataTransferProgress(int,int,QNetworkOperation*) ),
413 url(), SIGNAL( dataTransferProgress(int,int,QNetworkOperation*) ) );
414 connect( this, SIGNAL( connectionStateChanged(int,const QString&) ),
415 url(), SIGNAL( connectionStateChanged(int,const QString&) ) );
416 }
417
418 connect( this, SIGNAL( finished(QNetworkOperation*) ),
419 this, SLOT( processNextOperation(QNetworkOperation*) ) );
420 connect( this, SIGNAL( newChild(const QUrlInfo&,QNetworkOperation*) ),
421 this, SLOT( emitNewChildren(const QUrlInfo&,QNetworkOperation*) ) );
422
423}
424
425/*!
426 Destructor.
427*/
428
429QNetworkProtocol::~QNetworkProtocol()
430{
431 QNetworkOperation *op = d->opInProgress;
432 if ( op ) {
433 op->setState( StStopped );
434 op->setProtocolDetail( tr( "Operation stopped by the user" ) );
435 emit finished( op );
436 // op->free() will be called by QNetworkOperationPrivate dtor below
437 }
438 delete d;
439}
440
441/*!
442 Sets the QUrlOperator, on which the protocol works, to \a u.
443
444 \sa QUrlOperator
445*/
446
447void QNetworkProtocol::setUrl( QUrlOperator *u )
448{
449 if ( url() ) {
450 disconnect( this, SIGNAL( data(const QByteArray&,QNetworkOperation*) ),
451 url(), SIGNAL( data(const QByteArray&,QNetworkOperation*) ) );
452 disconnect( this, SIGNAL( finished(QNetworkOperation*) ),
453 url(), SIGNAL( finished(QNetworkOperation*) ) );
454 disconnect( this, SIGNAL( start(QNetworkOperation*) ),
455 url(), SIGNAL( start(QNetworkOperation*) ) );
456 disconnect( this, SIGNAL( newChildren(const QValueList<QUrlInfo>&,QNetworkOperation*) ),
457 url(), SIGNAL( newChildren(const QValueList<QUrlInfo>&,QNetworkOperation*) ) );
458 disconnect( this, SIGNAL( newChildren(const QValueList<QUrlInfo>&,QNetworkOperation*) ),
459 url(), SLOT( addEntry(const QValueList<QUrlInfo>&) ) );
460 disconnect( this, SIGNAL( createdDirectory(const QUrlInfo&,QNetworkOperation*) ),
461 url(), SIGNAL( createdDirectory(const QUrlInfo&,QNetworkOperation*) ) );
462 disconnect( this, SIGNAL( removed(QNetworkOperation*) ),
463 url(), SIGNAL( removed(QNetworkOperation*) ) );
464 disconnect( this, SIGNAL( itemChanged(QNetworkOperation*) ),
465 url(), SIGNAL( itemChanged(QNetworkOperation*) ) );
466 disconnect( this, SIGNAL( dataTransferProgress(int,int,QNetworkOperation*) ),
467 url(), SIGNAL( dataTransferProgress(int,int,QNetworkOperation*) ) );
468 disconnect( this, SIGNAL( connectionStateChanged(int,const QString&) ),
469 url(), SIGNAL( connectionStateChanged(int,const QString&) ) );
470 }
471
472
473 // ### if autoDelete is TRUE, we should delete the QUrlOperator (something
474 // like below; but that is not possible since it would delete this, too).
475 //if ( d->autoDelete && (d->url!=u) ) {
476 // delete d->url; // destructor deletes the network protocol
477 //}
478 d->url = u;
479
480 if ( url() ) {
481 connect( this, SIGNAL( data(const QByteArray&,QNetworkOperation*) ),
482 url(), SIGNAL( data(const QByteArray&,QNetworkOperation*) ) );
483 connect( this, SIGNAL( finished(QNetworkOperation*) ),
484 url(), SIGNAL( finished(QNetworkOperation*) ) );
485 connect( this, SIGNAL( start(QNetworkOperation*) ),
486 url(), SIGNAL( start(QNetworkOperation*) ) );
487 connect( this, SIGNAL( newChildren(const QValueList<QUrlInfo>&,QNetworkOperation*) ),
488 url(), SIGNAL( newChildren(const QValueList<QUrlInfo>&,QNetworkOperation*) ) );
489 connect( this, SIGNAL( newChildren(const QValueList<QUrlInfo>&,QNetworkOperation*) ),
490 url(), SLOT( addEntry(const QValueList<QUrlInfo>&) ) );
491 connect( this, SIGNAL( createdDirectory(const QUrlInfo&,QNetworkOperation*) ),
492 url(), SIGNAL( createdDirectory(const QUrlInfo&,QNetworkOperation*) ) );
493 connect( this, SIGNAL( removed(QNetworkOperation*) ),
494 url(), SIGNAL( removed(QNetworkOperation*) ) );
495 connect( this, SIGNAL( itemChanged(QNetworkOperation*) ),
496 url(), SIGNAL( itemChanged(QNetworkOperation*) ) );
497 connect( this, SIGNAL( dataTransferProgress(int,int,QNetworkOperation*) ),
498 url(), SIGNAL( dataTransferProgress(int,int,QNetworkOperation*) ) );
499 connect( this, SIGNAL( connectionStateChanged(int,const QString&) ),
500 url(), SIGNAL( connectionStateChanged(int,const QString&) ) );
501 }
502
503 if ( !d->opInProgress && !d->operationQueue.isEmpty() )
504 d->opStartTimer->start( 0, TRUE );
505}
506
507/*!
508 For processing operations the network protocol base class calls
509 this method quite often. This should be reimplemented by new
510 network protocols. It should return TRUE if the connection is OK
511 (open); otherwise it should return FALSE. If the connection is not
512 open the protocol should open it.
513
514 If the connection can't be opened (e.g. because you already tried
515 but the host couldn't be found), set the state of \a op to
516 QNetworkProtocol::StFailed and emit the finished() signal with
517 this QNetworkOperation as argument.
518
519 \a op is the operation that needs an open connection.
520*/
521
522bool QNetworkProtocol::checkConnection( QNetworkOperation * )
523{
524 return TRUE;
525}
526
527/*!
528 Returns an int that is OR'd together using the enum values of
529 \l{QNetworkProtocol::Operation}, which describes which operations
530 are supported by the network protocol. Should be reimplemented by
531 new network protocols.
532*/
533
534int QNetworkProtocol::supportedOperations() const
535{
536 return 0;
537}
538
539/*!
540 Adds the operation \a op to the operation queue. The operation
541 will be processed as soon as possible. This method returns
542 immediately.
543*/
544
545void QNetworkProtocol::addOperation( QNetworkOperation *op )
546{
547#ifdef QNETWORKPROTOCOL_DEBUG
548 qDebug( "QNetworkOperation: addOperation: %p %d", op, op->operation() );
549#endif
550 d->operationQueue.enqueue( op );
551 if ( !d->opInProgress )
552 d->opStartTimer->start( 0, TRUE );
553}
554
555/*!
556 Static method to register a network protocol for Qt. For example,
557 if you have an implementation of NNTP (called Nntp) which is
558 derived from QNetworkProtocol, call:
559 \code
560 QNetworkProtocol::registerNetworkProtocol( "nntp", new QNetworkProtocolFactory<Nntp> );
561 \endcode
562 after which your implementation is registered for future nntp
563 operations.
564
565 The name of the protocol is given in \a protocol and a pointer to
566 the protocol factory is given in \a protocolFactory.
567*/
568
569void QNetworkProtocol::registerNetworkProtocol( const QString &protocol,
570 QNetworkProtocolFactoryBase *protocolFactory )
571{
572 if ( !qNetworkProtocolRegister ) {
573 qNetworkProtocolRegister = new QNetworkProtocolDict;
574 QNetworkProtocol::registerNetworkProtocol( "file", new QNetworkProtocolFactory< QLocalFs > );
575 }
576
577 qNetworkProtocolRegister->insert( protocol, protocolFactory );
578}
579
580/*!
581 Static method to get a new instance of the network protocol \a
582 protocol. For example, if you need to do some FTP operations, do
583 the following:
584 \code
585 QFtp *ftp = QNetworkProtocol::getNetworkProtocol( "ftp" );
586 \endcode
587 This returns a pointer to a new instance of an ftp implementation
588 or null if no protocol for ftp was registered. The ownership of
589 the pointer is transferred to you, so you must delete it if you
590 don't need it anymore.
591
592 Normally you should not work directly with network protocols, so
593 you will not need to call this method yourself. Instead, use
594 QUrlOperator, which makes working with network protocols much more
595 convenient.
596
597 \sa QUrlOperator
598*/
599
600QNetworkProtocol *QNetworkProtocol::getNetworkProtocol( const QString &protocol )
601{
602 if ( !qNetworkProtocolRegister ) {
603 qNetworkProtocolRegister = new QNetworkProtocolDict;
604 QNetworkProtocol::registerNetworkProtocol( "file", new QNetworkProtocolFactory< QLocalFs > );
605 }
606
607 if ( protocol.isNull() )
608 return 0;
609
610 QNetworkProtocolFactoryBase *factory = qNetworkProtocolRegister->find( protocol );
611 if ( factory )
612 return factory->createObject();
613
614 return 0;
615}
616
617/*!
618 Returns TRUE if the only protocol registered is for working on the
619 local filesystem; returns FALSE if other network protocols are
620 also registered.
621*/
622
623bool QNetworkProtocol::hasOnlyLocalFileSystem()
624{
625 if ( !qNetworkProtocolRegister )
626 return FALSE;
627
628 QDictIterator< QNetworkProtocolFactoryBase > it( *qNetworkProtocolRegister );
629 for ( ; it.current(); ++it )
630 if ( it.currentKey() != "file" )
631 return FALSE;
632 return TRUE;
633}
634
635/*!
636 \internal
637 Starts processing network operations.
638*/
639
640void QNetworkProtocol::startOps()
641{
642#ifdef QNETWORKPROTOCOL_DEBUG
643 qDebug( "QNetworkOperation: start processing operations" );
644#endif
645 processNextOperation( 0 );
646}
647
648/*!
649 \internal
650 Processes the operation \a op. It calls the
651 corresponding operation[something]( QNetworkOperation * )
652 methods.
653*/
654
655void QNetworkProtocol::processOperation( QNetworkOperation *op )
656{
657 if ( !op )
658 return;
659
660 switch ( op->operation() ) {
661 case OpListChildren:
662 operationListChildren( op );
663 break;
664 case OpMkDir:
665 operationMkDir( op );
666 break;
667 case OpRemove:
668 operationRemove( op );
669 break;
670 case OpRename:
671 operationRename( op );
672 break;
673 case OpGet:
674 operationGet( op );
675 break;
676 case OpPut:
677 operationPut( op );
678 break;
679 }
680}
681
682/*!
683 When implementing a new network protocol, this method should be
684 reimplemented if the protocol supports listing children (files);
685 this method should then process this QNetworkOperation.
686
687 When you reimplement this method it's very important that you emit
688 the correct signals at the correct time (especially the finished()
689 signal after processing an operation). Take a look at the \link
690 network.html Qt Network Documentation\endlink which describes in
691 detail how to reimplement this method. You may also want to look
692 at the example implementation in
693 examples/network/networkprotocol/nntp.cpp.
694
695 \a op is the pointer to the operation object which contains all
696 the information on the operation that has finished, including the
697 state, etc.
698*/
699
700void QNetworkProtocol::operationListChildren( QNetworkOperation * )
701{
702}
703
704/*!
705 When implementing a new network protocol, this method should be
706 reimplemented if the protocol supports making directories; this
707 method should then process this QNetworkOperation.
708
709 When you reimplement this method it's very important that you emit
710 the correct signals at the correct time (especially the finished()
711 signal after processing an operation). Take a look at the \link
712 network.html Qt Network Documentation\endlink which describes in
713 detail how to reimplement this method. You may also want to look
714 at the example implementation in
715 examples/network/networkprotocol/nntp.cpp.
716
717 \a op is the pointer to the operation object which contains all
718 the information on the operation that has finished, including the
719 state, etc.
720*/
721
722void QNetworkProtocol::operationMkDir( QNetworkOperation * )
723{
724}
725
726/*!
727 When implementing a new network protocol, this method should be
728 reimplemented if the protocol supports removing children (files);
729 this method should then process this QNetworkOperation.
730
731 When you reimplement this method it's very important that you emit
732 the correct signals at the correct time (especially the finished()
733 signal after processing an operation). Take a look at the \link
734 network.html Qt Network Documentation\endlink which is describes
735 in detail how to reimplement this method. You may also want to
736 look at the example implementation in
737 examples/network/networkprotocol/nntp.cpp.
738
739 \a op is the pointer to the operation object which contains all
740 the information on the operation that has finished, including the
741 state, etc.
742*/
743
744void QNetworkProtocol::operationRemove( QNetworkOperation * )
745{
746}
747
748/*!
749 When implementing a new newtork protocol, this method should be
750 reimplemented if the protocol supports renaming children (files);
751 this method should then process this QNetworkOperation.
752
753 When you reimplement this method it's very important that you emit
754 the correct signals at the correct time (especially the finished()
755 signal after processing an operation). Take a look at the \link
756 network.html Qt Network Documentation\endlink which describes in
757 detail how to reimplement this method. You may also want to look
758 at the example implementation in
759 examples/network/networkprotocol/nntp.cpp.
760
761 \a op is the pointer to the operation object which contains all
762 the information on the operation that has finished, including the
763 state, etc.
764*/
765
766void QNetworkProtocol::operationRename( QNetworkOperation * )
767{
768}
769
770/*!
771 When implementing a new network protocol, this method should be
772 reimplemented if the protocol supports getting data; this method
773 should then process the QNetworkOperation.
774
775 When you reimplement this method it's very important that you emit
776 the correct signals at the correct time (especially the finished()
777 signal after processing an operation). Take a look at the \link
778 network.html Qt Network Documentation\endlink which describes in
779 detail how to reimplement this method. You may also want to look
780 at the example implementation in
781 examples/network/networkprotocol/nntp.cpp.
782
783 \a op is the pointer to the operation object which contains all
784 the information on the operation that has finished, including the
785 state, etc.
786*/
787
788void QNetworkProtocol::operationGet( QNetworkOperation * )
789{
790}
791
792/*!
793 When implementing a new network protocol, this method should be
794 reimplemented if the protocol supports putting (uploading) data;
795 this method should then process the QNetworkOperation.
796
797 When you reimplement this method it's very important that you emit
798 the correct signals at the correct time (especially the finished()
799 signal after processing an operation). Take a look at the \link
800 network.html Qt Network Documentation\endlink which describes in
801 detail how to reimplement this method. You may also want to look
802 at the example implementation in
803 examples/network/networkprotocol/nntp.cpp.
804
805 \a op is the pointer to the operation object which contains all
806 the information on the operation that has finished, including the
807 state, etc.
808*/
809
810void QNetworkProtocol::operationPut( QNetworkOperation * )
811{
812}
813
814/*! \internal
815*/
816
817void QNetworkProtocol::operationPutChunk( QNetworkOperation * )
818{
819}
820
821/*!
822 \internal
823 Handles operations. Deletes the previous operation object and
824 tries to process the next operation. It also checks the connection state
825 and only processes the next operation, if the connection of the protocol
826 is open. Otherwise it waits until the protocol opens the connection.
827*/
828
829void QNetworkProtocol::processNextOperation( QNetworkOperation *old )
830{
831#ifdef QNETWORKPROTOCOL_DEBUG
832 qDebug( "QNetworkOperation: process next operation, old: %p", old );
833#endif
834 d->removeTimer->stop();
835
836 if ( old )
837 d->oldOps.append( old );
838 if ( d->opInProgress && d->opInProgress!=old )
839 d->oldOps.append( d->opInProgress );
840
841 if ( d->operationQueue.isEmpty() ) {
842 d->opInProgress = 0;
843 if ( d->autoDelete )
844 d->removeTimer->start( d->removeInterval, TRUE );
845 return;
846 }
847
848 QNetworkOperation *op = d->operationQueue.head();
849
850 d->opInProgress = op;
851
852 if ( !checkConnection( op ) ) {
853 if ( op->state() != QNetworkProtocol::StFailed ) {
854 d->opStartTimer->start( 0, TRUE );
855 } else {
856 d->operationQueue.dequeue();
857 clearOperationQueue();
858 emit finished( op );
859 }
860
861 return;
862 }
863
864 d->opInProgress = op;
865 d->operationQueue.dequeue();
866 processOperation( op );
867}
868
869/*!
870 Returns the QUrlOperator on which the protocol works.
871*/
872
873QUrlOperator *QNetworkProtocol::url() const
874{
875 return d->url;
876}
877
878/*!
879 Returns the operation, which is being processed, or 0 of no
880 operation is being processed at the moment.
881*/
882
883QNetworkOperation *QNetworkProtocol::operationInProgress() const
884{
885 return d->opInProgress;
886}
887
888/*!
889 Clears the operation queue.
890*/
891
892void QNetworkProtocol::clearOperationQueue()
893{
894 d->operationQueue.dequeue();
895 d->operationQueue.setAutoDelete( TRUE );
896 d->operationQueue.clear();
897}
898
899/*!
900 Stops the current operation that is being processed and clears all
901 waiting operations.
902*/
903
904void QNetworkProtocol::stop()
905{
906 QNetworkOperation *op = d->opInProgress;
907 clearOperationQueue();
908 if ( op ) {
909 op->setState( StStopped );
910 op->setProtocolDetail( tr( "Operation stopped by the user" ) );
911 emit finished( op );
912 setUrl( 0 );
913 op->free();
914 }
915}
916
917/*!
918 Because it's sometimes hard to take care of removing network
919 protocol instances, QNetworkProtocol provides an auto-delete
920 mechanism. If you set \a b to TRUE, the network protocol instance
921 is removed after it has been inactive for \a i milliseconds (i.e.
922 \a i milliseconds after the last operation has been processed).
923 If you set \a b to FALSE the auto-delete mechanism is switched
924 off.
925
926 If you switch on auto-delete, the QNetworkProtocol also deletes
927 its QUrlOperator.
928*/
929
930void QNetworkProtocol::setAutoDelete( bool b, int i )
931{
932 d->autoDelete = b;
933 d->removeInterval = i;
934}
935
936/*!
937 Returns TRUE if auto-deleting is enabled; otherwise returns FALSE.
938
939 \sa QNetworkProtocol::setAutoDelete()
940*/
941
942bool QNetworkProtocol::autoDelete() const
943{
944 return d->autoDelete;
945}
946
947/*!
948 \internal
949*/
950
951void QNetworkProtocol::removeMe()
952{
953 if ( d->autoDelete ) {
954#ifdef QNETWORKPROTOCOL_DEBUG
955 qDebug( "QNetworkOperation: autodelete of QNetworkProtocol %p", this );
956#endif
957 delete d->url; // destructor deletes the network protocol
958 }
959}
960
961void QNetworkProtocol::emitNewChildren( const QUrlInfo &i, QNetworkOperation *op )
962{
963 QValueList<QUrlInfo> lst;
964 lst << i;
965 emit newChildren( lst, op );
966}
967
968class QNetworkOperationPrivate
969{
970public:
971 QNetworkProtocol::Operation operation;
972 QNetworkProtocol::State state;
973 QMap<int, QString> args;
974 QMap<int, QByteArray> rawArgs;
975 QString protocolDetail;
976 int errorCode;
977 QTimer *deleteTimer;
978};
979
980/*!
981 \class QNetworkOperation
982
983 \brief The QNetworkOperation class provides common operations for network protocols.
984\if defined(commercial)
985 It is part of the <a href="commercialeditions.html">Qt Enterprise Edition</a>.
986\endif
987
988 \module network
989 \ingroup io
990
991 An object is created to describe the operation and the current
992 state for each operation that a network protocol should process.
993
994 For a detailed description of the Qt Network Architecture and how
995 to implement and use network protocols in Qt, see the \link
996 network.html Qt Network Documentation\endlink.
997
998 \sa QNetworkProtocol
999*/
1000
1001/*!
1002 Constructs a network operation object. \a operation is the type of
1003 the operation, and \a arg0, \a arg1 and \a arg2 are the first
1004 three arguments of the operation. The state is initialized to
1005 QNetworkProtocol::StWaiting.
1006
1007 \sa QNetworkProtocol::Operation QNetworkProtocol::State
1008*/
1009
1010QNetworkOperation::QNetworkOperation( QNetworkProtocol::Operation operation,
1011 const QString &arg0, const QString &arg1,
1012 const QString &arg2 )
1013{
1014 d = new QNetworkOperationPrivate;
1015 d->deleteTimer = new QTimer( this );
1016 connect( d->deleteTimer, SIGNAL( timeout() ),
1017 this, SLOT( deleteMe() ) );
1018 d->operation = operation;
1019 d->state = QNetworkProtocol::StWaiting;
1020 d->args[ 0 ] = arg0;
1021 d->args[ 1 ] = arg1;
1022 d->args[ 2 ] = arg2;
1023 d->rawArgs[ 0 ] = QByteArray( 0 );
1024 d->rawArgs[ 1 ] = QByteArray( 0 );
1025 d->rawArgs[ 2 ] = QByteArray( 0 );
1026 d->protocolDetail = QString::null;
1027 d->errorCode = (int)QNetworkProtocol::NoError;
1028}
1029
1030/*!
1031 Constructs a network operation object. \a operation is the type of
1032 the operation, and \a arg0, \a arg1 and \a arg2 are the first
1033 three raw data arguments of the operation. The state is
1034 initialized to QNetworkProtocol::StWaiting.
1035
1036 \sa QNetworkProtocol::Operation QNetworkProtocol::State
1037*/
1038
1039QNetworkOperation::QNetworkOperation( QNetworkProtocol::Operation operation,
1040 const QByteArray &arg0, const QByteArray &arg1,
1041 const QByteArray &arg2 )
1042{
1043 d = new QNetworkOperationPrivate;
1044 d->deleteTimer = new QTimer( this );
1045 connect( d->deleteTimer, SIGNAL( timeout() ),
1046 this, SLOT( deleteMe() ) );
1047 d->operation = operation;
1048 d->state = QNetworkProtocol::StWaiting;
1049 d->args[ 0 ] = QString::null;
1050 d->args[ 1 ] = QString::null;
1051 d->args[ 2 ] = QString::null;
1052 d->rawArgs[ 0 ] = arg0;
1053 d->rawArgs[ 1 ] = arg1;
1054 d->rawArgs[ 2 ] = arg2;
1055 d->protocolDetail = QString::null;
1056 d->errorCode = (int)QNetworkProtocol::NoError;
1057}
1058
1059/*!
1060 Destructor.
1061*/
1062
1063QNetworkOperation::~QNetworkOperation()
1064{
1065 delete d;
1066}
1067
1068/*!
1069 Sets the \a state of the operation object. This should be done by
1070 the network protocol during processing; at the end it should be
1071 set to QNetworkProtocol::StDone or QNetworkProtocol::StFailed,
1072 depending on success or failure.
1073
1074 \sa QNetworkProtocol::State
1075*/
1076
1077void QNetworkOperation::setState( QNetworkProtocol::State state )
1078{
1079 if ( d->deleteTimer->isActive() ) {
1080 d->deleteTimer->stop();
1081 d->deleteTimer->start( NETWORK_OP_DELAY );
1082 }
1083 d->state = state;
1084}
1085
1086/*!
1087 If the operation failed, the error message can be specified as \a
1088 detail.
1089*/
1090
1091void QNetworkOperation::setProtocolDetail( const QString &detail )
1092{
1093 if ( d->deleteTimer->isActive() ) {
1094 d->deleteTimer->stop();
1095 d->deleteTimer->start( NETWORK_OP_DELAY );
1096 }
1097 d->protocolDetail = detail;
1098}
1099
1100/*!
1101 Sets the error code to \a ec.
1102
1103 If the operation failed, the protocol should set an error code to
1104 describe the error in more detail. If possible, one of the error
1105 codes defined in QNetworkProtocol should be used.
1106
1107 \sa setProtocolDetail() QNetworkProtocol::Error
1108*/
1109
1110void QNetworkOperation::setErrorCode( int ec )
1111{
1112 if ( d->deleteTimer->isActive() ) {
1113 d->deleteTimer->stop();
1114 d->deleteTimer->start( NETWORK_OP_DELAY );
1115 }
1116 d->errorCode = ec;
1117}
1118
1119/*!
1120 Sets the network operation's \a{num}-th argument to \a arg.
1121*/
1122
1123void QNetworkOperation::setArg( int num, const QString &arg )
1124{
1125 if ( d->deleteTimer->isActive() ) {
1126 d->deleteTimer->stop();
1127 d->deleteTimer->start( NETWORK_OP_DELAY );
1128 }
1129 d->args[ num ] = arg;
1130}
1131
1132/*!
1133 Sets the network operation's \a{num}-th raw data argument to \a arg.
1134*/
1135
1136void QNetworkOperation::setRawArg( int num, const QByteArray &arg )
1137{
1138 if ( d->deleteTimer->isActive() ) {
1139 d->deleteTimer->stop();
1140 d->deleteTimer->start( NETWORK_OP_DELAY );
1141 }
1142 d->rawArgs[ num ] = arg;
1143}
1144
1145/*!
1146 Returns the type of the operation.
1147*/
1148
1149QNetworkProtocol::Operation QNetworkOperation::operation() const
1150{
1151 if ( d->deleteTimer->isActive() ) {
1152 d->deleteTimer->stop();
1153 d->deleteTimer->start( NETWORK_OP_DELAY );
1154 }
1155 return d->operation;
1156}
1157
1158/*!
1159 Returns the state of the operation. You can determine whether an
1160 operation is still waiting to be processed, is being processed,
1161 has been processed successfully, or failed.
1162*/
1163
1164QNetworkProtocol::State QNetworkOperation::state() const
1165{
1166 if ( d->deleteTimer->isActive() ) {
1167 d->deleteTimer->stop();
1168 d->deleteTimer->start( NETWORK_OP_DELAY );
1169 }
1170 return d->state;
1171}
1172
1173/*!
1174 Returns the operation's \a{num}-th argument. If this argument was
1175 not already set, an empty string is returned.
1176*/
1177
1178QString QNetworkOperation::arg( int num ) const
1179{
1180 if ( d->deleteTimer->isActive() ) {
1181 d->deleteTimer->stop();
1182 d->deleteTimer->start( NETWORK_OP_DELAY );
1183 }
1184 return d->args[ num ];
1185}
1186
1187/*!
1188 Returns the operation's \a{num}-th raw data argument. If this
1189 argument was not already set, an empty bytearray is returned.
1190*/
1191
1192QByteArray QNetworkOperation::rawArg( int num ) const
1193{
1194 if ( d->deleteTimer->isActive() ) {
1195 d->deleteTimer->stop();
1196 d->deleteTimer->start( NETWORK_OP_DELAY );
1197 }
1198 return d->rawArgs[ num ];
1199}
1200
1201/*!
1202 Returns a detailed error message for the last error. This must
1203 have been set using setProtocolDetail().
1204*/
1205
1206QString QNetworkOperation::protocolDetail() const
1207{
1208 if ( d->deleteTimer->isActive() ) {
1209 d->deleteTimer->stop();
1210 d->deleteTimer->start( NETWORK_OP_DELAY );
1211 }
1212 return d->protocolDetail;
1213}
1214
1215/*!
1216 Returns the error code for the last error that occurred.
1217*/
1218
1219int QNetworkOperation::errorCode() const
1220{
1221 if ( d->deleteTimer->isActive() ) {
1222 d->deleteTimer->stop();
1223 d->deleteTimer->start( NETWORK_OP_DELAY );
1224 }
1225 return d->errorCode;
1226}
1227
1228/*!
1229 \internal
1230*/
1231
1232QByteArray& QNetworkOperation::raw( int num ) const
1233{
1234 if ( d->deleteTimer->isActive() ) {
1235 d->deleteTimer->stop();
1236 d->deleteTimer->start( NETWORK_OP_DELAY );
1237 }
1238 return d->rawArgs[ num ];
1239}
1240
1241/*!
1242 Sets this object to delete itself when it hasn't been used for one
1243 second.
1244
1245 Because QNetworkOperation pointers are passed around a lot the
1246 QNetworkProtocol generally does not have enough knowledge to
1247 delete these at the correct time. If a QNetworkProtocol doesn't
1248 need an operation any more it will call this function instead.
1249
1250 Note: you should never need to call the method yourself.
1251*/
1252
1253void QNetworkOperation::free()
1254{
1255 d->deleteTimer->start( NETWORK_OP_DELAY );
1256}
1257
1258/*!
1259 \internal
1260 Internal slot for auto-deletion.
1261*/
1262
1263void QNetworkOperation::deleteMe()
1264{
1265 // ### A hackish workaround to prevent this op from being deleted during
1266 // the qApp->processEvents() call in QLocalFs::operationListChildren().
1267 // The proper way is to add something like QNetworkOperation::cancelFree()
1268 // to stop deleteTimer and make it a documented method.
1269 if ( !signalsBlocked() )
1270 delete this;
1271}
1272
1273#endif
Note: See TracBrowser for help on using the repository browser.