| 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 |  | 
|---|
| 51 | extern Q_EXPORT QNetworkProtocolDict *qNetworkProtocolRegister; | 
|---|
| 52 |  | 
|---|
| 53 | QNetworkProtocolDict *qNetworkProtocolRegister = 0; | 
|---|
| 54 |  | 
|---|
| 55 | class QNetworkProtocolPrivate | 
|---|
| 56 | { | 
|---|
| 57 | public: | 
|---|
| 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 |  | 
|---|
| 385 | QNetworkProtocol::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 |  | 
|---|
| 429 | QNetworkProtocol::~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 |  | 
|---|
| 447 | void 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 |  | 
|---|
| 522 | bool 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 |  | 
|---|
| 534 | int 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 |  | 
|---|
| 545 | void 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 |  | 
|---|
| 569 | void 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 |  | 
|---|
| 600 | QNetworkProtocol *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 |  | 
|---|
| 623 | bool 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 |  | 
|---|
| 640 | void 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 |  | 
|---|
| 655 | void 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 |  | 
|---|
| 700 | void 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 |  | 
|---|
| 722 | void 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 |  | 
|---|
| 744 | void 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 |  | 
|---|
| 766 | void 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 |  | 
|---|
| 788 | void 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 |  | 
|---|
| 810 | void QNetworkProtocol::operationPut( QNetworkOperation * ) | 
|---|
| 811 | { | 
|---|
| 812 | } | 
|---|
| 813 |  | 
|---|
| 814 | /*! \internal | 
|---|
| 815 | */ | 
|---|
| 816 |  | 
|---|
| 817 | void 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 |  | 
|---|
| 829 | void 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 |  | 
|---|
| 873 | QUrlOperator *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 |  | 
|---|
| 883 | QNetworkOperation *QNetworkProtocol::operationInProgress() const | 
|---|
| 884 | { | 
|---|
| 885 | return d->opInProgress; | 
|---|
| 886 | } | 
|---|
| 887 |  | 
|---|
| 888 | /*! | 
|---|
| 889 | Clears the operation queue. | 
|---|
| 890 | */ | 
|---|
| 891 |  | 
|---|
| 892 | void 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 |  | 
|---|
| 904 | void 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 |  | 
|---|
| 930 | void 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 |  | 
|---|
| 942 | bool QNetworkProtocol::autoDelete() const | 
|---|
| 943 | { | 
|---|
| 944 | return d->autoDelete; | 
|---|
| 945 | } | 
|---|
| 946 |  | 
|---|
| 947 | /*! | 
|---|
| 948 | \internal | 
|---|
| 949 | */ | 
|---|
| 950 |  | 
|---|
| 951 | void 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 |  | 
|---|
| 961 | void QNetworkProtocol::emitNewChildren( const QUrlInfo &i, QNetworkOperation *op ) | 
|---|
| 962 | { | 
|---|
| 963 | QValueList<QUrlInfo> lst; | 
|---|
| 964 | lst << i; | 
|---|
| 965 | emit newChildren( lst, op ); | 
|---|
| 966 | } | 
|---|
| 967 |  | 
|---|
| 968 | class QNetworkOperationPrivate | 
|---|
| 969 | { | 
|---|
| 970 | public: | 
|---|
| 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 |  | 
|---|
| 1010 | QNetworkOperation::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 |  | 
|---|
| 1039 | QNetworkOperation::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 |  | 
|---|
| 1063 | QNetworkOperation::~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 |  | 
|---|
| 1077 | void 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 |  | 
|---|
| 1091 | void 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 |  | 
|---|
| 1110 | void 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 |  | 
|---|
| 1123 | void 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 |  | 
|---|
| 1136 | void 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 |  | 
|---|
| 1149 | QNetworkProtocol::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 |  | 
|---|
| 1164 | QNetworkProtocol::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 |  | 
|---|
| 1178 | QString 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 |  | 
|---|
| 1192 | QByteArray 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 |  | 
|---|
| 1206 | QString 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 |  | 
|---|
| 1219 | int 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 |  | 
|---|
| 1232 | QByteArray& 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 |  | 
|---|
| 1253 | void QNetworkOperation::free() | 
|---|
| 1254 | { | 
|---|
| 1255 | d->deleteTimer->start( NETWORK_OP_DELAY ); | 
|---|
| 1256 | } | 
|---|
| 1257 |  | 
|---|
| 1258 | /*! | 
|---|
| 1259 | \internal | 
|---|
| 1260 | Internal slot for auto-deletion. | 
|---|
| 1261 | */ | 
|---|
| 1262 |  | 
|---|
| 1263 | void 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 | 
|---|