source: trunk/src/kernel/qurloperator.cpp@ 8

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

Imported xplatform parts of the official release 3.3.1 from Trolltech

  • Property svn:keywords set to Id
File size: 37.7 KB
Line 
1/****************************************************************************
2** $Id: qurloperator.cpp 2 2005-11-16 15:49:26Z dmik $
3**
4** Implementation of QUrlOperator class
5**
6** Created : 950429
7**
8** Copyright (C) 1992-2000 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 "qurloperator.h"
39
40#ifndef QT_NO_NETWORKPROTOCOL
41
42#include "qurlinfo.h"
43#include "qnetworkprotocol.h"
44#include "qmap.h"
45#include "qdir.h"
46#include "qptrdict.h"
47#include "qguardedptr.h"
48
49//#define QURLOPERATOR_DEBUG
50
51class QUrlOperatorPrivate
52{
53public:
54 QUrlOperatorPrivate()
55 {
56 oldOps.setAutoDelete( FALSE );
57 networkProtocol = 0;
58 nameFilter = "*";
59 currPut = 0;
60 }
61
62 ~QUrlOperatorPrivate()
63 {
64 delete networkProtocol;
65 while ( oldOps.first() ) {
66 oldOps.first()->free();
67 oldOps.removeFirst();
68 }
69 }
70
71 QMap<QString, QUrlInfo> entryMap;
72 QNetworkProtocol *networkProtocol;
73 QString nameFilter;
74 QDir dir;
75
76 // maps needed for copy/move operations
77 QPtrDict<QNetworkOperation> getOpPutOpMap;
78 QPtrDict<QNetworkProtocol> getOpPutProtMap;
79 QPtrDict<QNetworkProtocol> getOpGetProtMap;
80 QPtrDict<QNetworkOperation> getOpRemoveOpMap;
81 QGuardedPtr<QNetworkProtocol> currPut;
82 QStringList waitingCopies;
83 QString waitingCopiesDest;
84 bool waitingCopiesMove;
85 QPtrList< QNetworkOperation > oldOps;
86};
87
88/*!
89 \class QUrlOperator qurloperator.h
90
91 \brief The QUrlOperator class provides common operations on URLs.
92\if defined(commercial)
93 It is part of the <a href="commercialeditions.html">Qt Enterprise Edition</a>.
94\endif
95
96 \ingroup io
97 \ingroup misc
98 \mainclass
99
100 \module network
101
102 This class operates on hierarchical structures (such as
103 filesystems) using URLs. Its API facilitates all the common
104 operations:
105 \table
106 \header \i Operation \i Function
107 \row \i List files \i \l listChildren()
108 \row \i Make a directory \i \l mkdir()
109 \row \i Remove a file \i \l remove()
110 \row \i Rename a file \i \l rename()
111 \row \i Get a file \i \l get()
112 \row \i Put a file \i \l put()
113 \row \i Copy a file \i \l copy()
114 \endtable
115
116 You can obtain additional information about the URL with isDir()
117 and info(). If a directory is to be traversed using
118 listChildren(), a name filter can be set with setNameFilter().
119
120 A QUrlOperator can be used like this, for example to download a
121 file (and assuming that the FTP protocol is \link
122 qInitNetworkProtocols() registered\endlink):
123 \code
124 QUrlOperator *op = new QUrlOperator();
125 op->copy( QString("ftp://ftp.trolltech.com/qt/source/qt-2.1.0.tar.gz"),
126 "file:/tmp" );
127 \endcode
128
129 If you want to be notified about success/failure, progress, etc.,
130 you can connect to QUrlOperator's signals, e.g. to start(),
131 newChildren(), createdDirectory(), removed(), data(),
132 dataTransferProgress(), startedNextCopy(),
133 connectionStateChanged(), finished(), etc. A network operation can
134 be stopped with stop().
135
136 The class uses the functionality of registered network protocols
137 to perform these operations. Depending of the protocol of the URL,
138 it uses an appropriate network protocol class for the operations.
139 Each of the operation functions of QUrlOperator creates a
140 QNetworkOperation object that describes the operation and puts it
141 into the operation queue for the network protocol used. If no
142 suitable protocol could be found (because no implementation of the
143 necessary network protocol is registered), the URL operator emits
144 errors. Not every protocol supports every operation, but error
145 handling deals with this problem.
146
147 To register the available network protocols, use the
148 qInitNetworkProtocols() function. The protocols currently
149 supported are:
150 \list
151 \i \link QFtp FTP\endlink,
152 \i \link QHttp HTTP\endlink,
153 \i \link QLocalFs local file system\endlink.
154 \endlist
155
156 For more information about the Qt Network Architecture see the
157 \link network.html Qt Network Documentation\endlink.
158
159 \sa QNetworkProtocol, QNetworkOperation
160*/
161
162/*!
163 \fn void QUrlOperator::newChildren( const QValueList<QUrlInfo> &i, QNetworkOperation *op )
164
165 This signal is emitted after listChildren() was called and new
166 children (i.e. files) have been read from a list of files. \a i
167 holds the information about the new files. \a op is a pointer
168 to the operation object which contains all the information about
169 the operation, including the state.
170
171 \sa QNetworkOperation, QNetworkProtocol
172*/
173
174
175/*!
176 \fn void QUrlOperator::finished( QNetworkOperation *op )
177
178 This signal is emitted when an operation of some sort finishes,
179 whether with success or failure. \a op is a pointer to the
180 operation object, which contains all the information, including
181 the state, of the operation which has been finished. Check the
182 state and error code of the operation object to see whether or not
183 the operation was successful.
184
185 \sa QNetworkOperation, QNetworkProtocol
186*/
187
188/*!
189 \fn void QUrlOperator::start( QNetworkOperation *op )
190
191 Some operations (such as listChildren()) emit this signal when
192 they start processing the operation. \a op is a pointer to the
193 operation object which contains all the information about the
194 operation, including the state.
195
196 \sa QNetworkOperation, QNetworkProtocol
197*/
198
199/*!
200 \fn void QUrlOperator::createdDirectory( const QUrlInfo &i, QNetworkOperation *op )
201
202 This signal is emitted when mkdir() succeeds and the directory has
203 been created. \a i holds the information about the new directory.
204
205 \a op is a pointer to the operation object, which contains all the
206 information about the operation, including the state.
207 \c op->arg(0) holds the new directory's name.
208
209 \sa QNetworkOperation, QNetworkProtocol
210*/
211
212/*!
213 \fn void QUrlOperator::removed( QNetworkOperation *op )
214
215 This signal is emitted when remove() has been succesful and the
216 file has been removed.
217
218 \a op is a pointer to the operation object which contains all the
219 information about the operation, including the state.
220 \c op->arg(0) holds the name of the file that was removed.
221
222 \sa QNetworkOperation, QNetworkProtocol
223*/
224
225/*!
226 \fn void QUrlOperator::itemChanged( QNetworkOperation *op )
227
228 This signal is emitted whenever a file which is a child of the URL
229 has been changed, for example by successfully calling rename().
230 \a op is a pointer to the operation object which contains all the
231 information about the operation, including the state.
232 \c op->arg(0) holds the original file name and \c op->arg(1) holds
233 the new file name (if it was changed).
234
235 \sa QNetworkOperation, QNetworkProtocol
236*/
237
238/*!
239 \fn void QUrlOperator::data( const QByteArray &data, QNetworkOperation *op )
240
241 This signal is emitted when new \a data has been received after calling
242 get() or put().
243 \a op is a pointer to the operation object which contains all
244 the information about the operation, including the state.
245 \c op->arg(0) holds the name of the file whose data is retrieved
246 and op->rawArg(1) holds the (raw) data.
247
248 \sa QNetworkOperation, QNetworkProtocol
249*/
250
251/*!
252 \fn void QUrlOperator::dataTransferProgress( int bytesDone, int bytesTotal, QNetworkOperation *op )
253
254 This signal is emitted during data transfer (using put() or
255 get()). \a bytesDone specifies how many bytes of \a bytesTotal have
256 been transferred. More information about the operation is stored in
257 \a op, a pointer to the network operation that is processed.
258 \a bytesTotal may be -1, which means that the total number of bytes
259 is not known.
260
261 \sa QNetworkOperation, QNetworkProtocol
262*/
263
264/*!
265 \fn void QUrlOperator::startedNextCopy( const QPtrList<QNetworkOperation> &lst )
266
267 This signal is emitted if copy() starts a new copy operation. \a
268 lst contains all QNetworkOperations related to this copy
269 operation.
270
271 \sa copy()
272*/
273
274/*!
275 \fn void QUrlOperator::connectionStateChanged( int state, const QString &data )
276
277 This signal is emitted whenever the URL operator's connection
278 state changes. \a state describes the new state, which is a
279 \l{QNetworkProtocol::ConnectionState} value.
280
281 \a data is a string that describes the change of the connection.
282 This can be used to display a message to the user.
283*/
284
285/*!
286 Constructs a QUrlOperator with an empty (i.e. invalid) URL.
287*/
288
289QUrlOperator::QUrlOperator()
290 : QUrl()
291{
292#ifdef QURLOPERATOR_DEBUG
293 qDebug( "QUrlOperator: cstr 1" );
294#endif
295 d = new QUrlOperatorPrivate;
296}
297
298/*!
299 Constructs a QUrlOperator using \a url and parses this string.
300
301 If you pass strings like "/home/qt" the "file" protocol is
302 assumed.
303*/
304
305QUrlOperator::QUrlOperator( const QString &url )
306 : QUrl( url )
307{
308#ifdef QURLOPERATOR_DEBUG
309 qDebug( "QUrlOperator: cstr 2" );
310#endif
311 d = new QUrlOperatorPrivate;
312 getNetworkProtocol();
313}
314
315/*!
316 Constructs a copy of \a url.
317*/
318
319QUrlOperator::QUrlOperator( const QUrlOperator& url )
320 : QObject(), QUrl( url )
321{
322#ifdef QURLOPERATOR_DEBUG
323 qDebug( "QUrlOperator: cstr 3" );
324#endif
325 d = new QUrlOperatorPrivate;
326 *d = *url.d;
327
328 d->networkProtocol = 0;
329 getNetworkProtocol();
330 d->nameFilter = "*";
331 d->currPut = 0;
332}
333
334/*!
335 Constructs a QUrlOperator. The URL on which this QUrlOperator
336 operates is constructed out of the arguments \a url, \a relUrl and
337 \a checkSlash: see the corresponding QUrl constructor for an
338 explanation of these arguments.
339*/
340
341QUrlOperator::QUrlOperator( const QUrlOperator& url, const QString& relUrl, bool checkSlash )
342 : QUrl( url, relUrl, checkSlash )
343{
344#ifdef QURLOPERATOR_DEBUG
345 qDebug( "QUrlOperator: cstr 4" );
346#endif
347 d = new QUrlOperatorPrivate;
348 if ( relUrl == "." )
349 *d = *url.d;
350
351 d->networkProtocol = 0;
352 getNetworkProtocol();
353 d->currPut = 0;
354}
355
356/*!
357 Destructor.
358*/
359
360QUrlOperator::~QUrlOperator()
361{
362#ifdef QURLOPERATOR_DEBUG
363 qDebug( "QUrlOperator: dstr" );
364#endif
365 delete d;
366}
367
368/*!
369 This private function is used by the simple operation functions,
370 i.e. listChildren(), mkdir(), remove(), rename(), get() and put(),
371 to really start the operation. \a op is a pointer to the network
372 operation that should be started. Returns \a op on success;
373 otherwise returns 0.
374*/
375const QNetworkOperation *QUrlOperator::startOperation( QNetworkOperation *op )
376{
377 if ( d->networkProtocol && (d->networkProtocol->supportedOperations()&op->operation()) ) {
378 d->networkProtocol->addOperation( op );
379 if ( op->operation() == QNetworkProtocol::OpListChildren )
380 clearEntries();
381 return op;
382 }
383
384 // error
385 QString msg;
386 if ( !d->networkProtocol ) {
387 msg = tr( "The protocol `%1' is not supported" ).arg( protocol() );
388 } else {
389 switch ( op->operation() ) {
390 case QNetworkProtocol::OpListChildren:
391 msg = tr( "The protocol `%1' does not support listing directories" ).arg( protocol() );
392 break;
393 case QNetworkProtocol::OpMkDir:
394 msg = tr( "The protocol `%1' does not support creating new directories" ).arg( protocol() );
395 break;
396 case QNetworkProtocol::OpRemove:
397 msg = tr( "The protocol `%1' does not support removing files or directories" ).arg( protocol() );
398 break;
399 case QNetworkProtocol::OpRename:
400 msg = tr( "The protocol `%1' does not support renaming files or directories" ).arg( protocol() );
401 break;
402 case QNetworkProtocol::OpGet:
403 msg = tr( "The protocol `%1' does not support getting files" ).arg( protocol() );
404 break;
405 case QNetworkProtocol::OpPut:
406 msg = tr( "The protocol `%1' does not support putting files" ).arg( protocol() );
407 break;
408 default:
409 // this should never happen
410 break;
411 }
412 }
413 op->setState( QNetworkProtocol::StFailed );
414 op->setProtocolDetail( msg );
415 op->setErrorCode( (int)QNetworkProtocol::ErrUnsupported );
416 emit finished( op );
417 deleteOperation( op );
418 return 0;
419}
420
421/*!
422 Starts listing the children of this URL (e.g. the files in the
423 directory). The start() signal is emitted before the first entry
424 is listed and finished() is emitted after the last one. The
425 newChildren() signal is emitted for each list of new entries. If
426 an error occurs, the signal finished() is emitted, so be sure to
427 check the state of the network operation pointer.
428
429 Because the operation may not be executed immediately, a pointer
430 to the QNetworkOperation object created by this function is
431 returned. This object contains all the data about the operation
432 and is used to refer to this operation later (e.g. in the signals
433 that are emitted by the QUrlOperator). The return value can also
434 be 0 if the operation object couldn't be created.
435
436 The path of this QUrlOperator must to point to a directory
437 (because the children of this directory will be listed), not to a
438 file.
439*/
440
441const QNetworkOperation *QUrlOperator::listChildren()
442{
443 if ( !checkValid() )
444 return 0;
445
446 QNetworkOperation *res = new QNetworkOperation( QNetworkProtocol::OpListChildren, QString::null, QString::null, QString::null );
447 return startOperation( res );
448}
449
450/*!
451 Tries to create a directory (child) with the name \a dirname. If
452 it is successful, a newChildren() signal with the new child is
453 emitted, and the createdDirectory() signal with the information
454 about the new child is also emitted. The finished() signal (with
455 success or failure) is emitted after the operation has been
456 processed, so check the state of the network operation object to
457 see whether or not the operation was successful.
458
459 Because the operation will not be executed immediately, a pointer
460 to the QNetworkOperation object created by this function is
461 returned. This object contains all the data about the operation
462 and is used to refer to this operation later (e.g. in the signals
463 that are emitted by the QUrlOperator). The return value can also
464 be 0 if the operation object couldn't be created.
465
466 The path of this QUrlOperator must to point to a directory (not a
467 file) because the new directory will be created in this path.
468*/
469
470const QNetworkOperation *QUrlOperator::mkdir( const QString &dirname )
471{
472 if ( !checkValid() )
473 return 0;
474
475 QNetworkOperation *res = new QNetworkOperation( QNetworkProtocol::OpMkDir, dirname, QString::null, QString::null );
476 return startOperation( res );
477}
478
479/*!
480 Tries to remove the file (child) \a filename. If it succeeds the
481 removed() signal is emitted. finished() (with success or failure)
482 is also emitted after the operation has been processed, so check
483 the state of the network operation object to see whether or not
484 the operation was successful.
485
486 Because the operation will not be executed immediately, a pointer
487 to the QNetworkOperation object created by this function is
488 returned. This object contains all the data about the operation
489 and is used to refer to this operation later (e.g. in the signals
490 that are emitted by the QUrlOperator). The return value can also
491 be 0 if the operation object couldn't be created.
492
493 The path of this QUrlOperator must point to a directory; because
494 if \a filename is relative, it will try to remove it in this
495 directory.
496*/
497
498const QNetworkOperation *QUrlOperator::remove( const QString &filename )
499{
500 if ( !checkValid() )
501 return 0;
502
503 QNetworkOperation *res = new QNetworkOperation( QNetworkProtocol::OpRemove, filename, QString::null, QString::null );
504 return startOperation( res );
505}
506
507/*!
508 Tries to rename the file (child) called \a oldname to \a newname.
509 If it succeeds, the itemChanged() signal is emitted. finished()
510 (with success or failure) is also emitted after the operation has
511 been processed, so check the state of the network operation object
512 to see whether or not the operation was successful.
513
514 Because the operation may not be executed immediately, a pointer
515 to the QNetworkOperation object created by this function is
516 returned. This object contains all the data about the operation
517 and is used to refer to this operation later (e.g. in the signals
518 that are emitted by the QUrlOperator). The return value can also
519 be 0 if the operation object couldn't be created.
520
521 This path of this QUrlOperator must to point to a directory
522 because \a oldname and \a newname are handled relative to this
523 directory.
524*/
525
526const QNetworkOperation *QUrlOperator::rename( const QString &oldname, const QString &newname )
527{
528 if ( !checkValid() )
529 return 0;
530
531 QNetworkOperation *res = new QNetworkOperation( QNetworkProtocol::OpRename, oldname, newname, QString::null );
532 return startOperation( res );
533}
534
535/*!
536 Copies the file \a from to \a to. If \a move is TRUE, the file is
537 moved (copied and removed). \a from must point to a file and \a to
538 must point to a directory (into which \a from is copied) unless \a
539 toPath is set to FALSE. If \a toPath is set to FALSE then the \a
540 to variable is assumed to be the absolute file path (destination
541 file path + file name). The copying is done using the get() and
542 put() operations. If you want to be notified about the progress of
543 the operation, connect to the dataTransferProgress() signal. Bear
544 in mind that the get() and put() operations emit this signal
545 through the QUrlOperator. The number of transferred bytes and the
546 total bytes that you receive as arguments in this signal do not
547 relate to the the whole copy operation; they relate first to the
548 get() and then to the put() operation. Always check what type of
549 operation the signal comes from; this is given in the signal's
550 last argument.
551
552 At the end, finished() (with success or failure) is emitted, so
553 check the state of the network operation object to see whether or
554 not the operation was successful.
555
556 Because a move or copy operation consists of multiple operations
557 (get(), put() and maybe remove()), this function doesn't return a
558 single QNetworkOperation, but rather a list of them. They are in
559 the order: get(), put() and (if applicable) remove().
560
561 \sa get(), put()
562*/
563
564QPtrList<QNetworkOperation> QUrlOperator::copy( const QString &from, const QString &to, bool move, bool toPath )
565{
566#ifdef QURLOPERATOR_DEBUG
567 qDebug( "QUrlOperator: copy %s %s %d", from.latin1(), to.latin1(), move );
568#endif
569
570 QPtrList<QNetworkOperation> ops;
571 ops.setAutoDelete( FALSE );
572
573 QUrlOperator *uFrom = new QUrlOperator( *this, from );
574 QUrlOperator *uTo = new QUrlOperator( to );
575
576 // prepare some string for later usage
577 QString frm = *uFrom;
578 QString file = uFrom->fileName();
579 file.prepend( "/" );
580
581 // uFrom and uTo are deleted when the QNetworkProtocol deletes itself via
582 // autodelete
583 uFrom->getNetworkProtocol();
584 uTo->getNetworkProtocol();
585 QNetworkProtocol *gProt = uFrom->d->networkProtocol;
586 QNetworkProtocol *pProt = uTo->d->networkProtocol;
587
588 uFrom->setPath( uFrom->dirPath() );
589
590 if ( gProt && (gProt->supportedOperations()&QNetworkProtocol::OpGet) &&
591 pProt && (pProt->supportedOperations()&QNetworkProtocol::OpPut) ) {
592
593 connect( gProt, SIGNAL( data(const QByteArray&,QNetworkOperation*) ),
594 this, SLOT( copyGotData(const QByteArray&,QNetworkOperation*) ) );
595 connect( gProt, SIGNAL( dataTransferProgress(int,int,QNetworkOperation*) ),
596 this, SIGNAL( dataTransferProgress(int,int,QNetworkOperation*) ) );
597 connect( gProt, SIGNAL( finished(QNetworkOperation*) ),
598 this, SLOT( continueCopy(QNetworkOperation*) ) );
599 connect( gProt, SIGNAL( finished(QNetworkOperation*) ),
600 this, SIGNAL( finished(QNetworkOperation*) ) );
601 connect( gProt, SIGNAL( connectionStateChanged(int,const QString&) ),
602 this, SIGNAL( connectionStateChanged(int,const QString&) ) );
603
604 connect( pProt, SIGNAL( dataTransferProgress(int,int,QNetworkOperation*) ),
605 this, SIGNAL( dataTransferProgress(int,int,QNetworkOperation*) ) );
606 connect( pProt, SIGNAL( finished(QNetworkOperation*) ),
607 this, SIGNAL( finished(QNetworkOperation*) ) );
608 connect( pProt, SIGNAL( finished(QNetworkOperation*) ),
609 this, SLOT( finishedCopy() ) );
610
611 QNetworkOperation *opGet = new QNetworkOperation( QNetworkProtocol::OpGet, frm, QString::null, QString::null );
612 ops.append( opGet );
613 gProt->addOperation( opGet );
614
615
616 QString toFile = to + file;
617 if (!toPath)
618 toFile = to;
619
620 QNetworkOperation *opPut = new QNetworkOperation( QNetworkProtocol::OpPut, toFile, QString::null, QString::null );
621 ops.append( opPut );
622
623 d->getOpPutProtMap.insert( (void*)opGet, pProt );
624 d->getOpGetProtMap.insert( (void*)opGet, gProt );
625 d->getOpPutOpMap.insert( (void*)opGet, opPut );
626
627 if ( move && (gProt->supportedOperations()&QNetworkProtocol::OpRemove) ) {
628 gProt->setAutoDelete( FALSE );
629
630 QNetworkOperation *opRm = new QNetworkOperation( QNetworkProtocol::OpRemove, frm, QString::null, QString::null );
631 ops.append( opRm );
632 d->getOpRemoveOpMap.insert( (void*)opGet, opRm );
633 } else {
634 gProt->setAutoDelete( TRUE );
635 }
636#ifdef QURLOPERATOR_DEBUG
637 qDebug( "QUrlOperator: copy operation should start now..." );
638#endif
639 return ops;
640 } else {
641 QString msg;
642 if ( !gProt ) {
643 msg = tr( "The protocol `%1' is not supported" ).arg( uFrom->protocol() );
644 } else if ( gProt->supportedOperations() & QNetworkProtocol::OpGet ) {
645 msg = tr( "The protocol `%1' does not support copying or moving files or directories" ).arg( uFrom->protocol() );
646 } else if ( !pProt ) {
647 msg = tr( "The protocol `%1' is not supported" ).arg( uTo->protocol() );
648 } else {
649 msg = tr( "The protocol `%1' does not support copying or moving files or directories" ).arg( uTo->protocol() );
650 }
651 delete uFrom;
652 delete uTo;
653 QNetworkOperation *res = new QNetworkOperation( QNetworkProtocol::OpGet, frm, to, QString::null );
654 res->setState( QNetworkProtocol::StFailed );
655 res->setProtocolDetail( msg );
656 res->setErrorCode( (int)QNetworkProtocol::ErrUnsupported );
657 emit finished( res );
658 deleteOperation( res );
659 }
660
661 return ops;
662}
663
664/*!
665 \overload
666
667 Copies the \a files to the directory \a dest. If \a move is TRUE
668 the files are moved, not copied. \a dest must point to a
669 directory.
670
671 This function calls copy() for each entry in \a files in turn. You
672 don't get a result from this function; each time a new copy
673 begins, startedNextCopy() is emitted, with a list of
674 QNetworkOperations that describe the new copy operation.
675*/
676
677void QUrlOperator::copy( const QStringList &files, const QString &dest,
678 bool move )
679{
680 d->waitingCopies = files;
681 d->waitingCopiesDest = dest;
682 d->waitingCopiesMove = move;
683
684 finishedCopy();
685}
686
687/*!
688 Returns TRUE if the URL is a directory; otherwise returns FALSE.
689 This may not always work correctly, if the protocol of the URL is
690 something other than file (local filesystem). If you pass a bool
691 pointer as the \a ok argument, \a *ok is set to TRUE if the result
692 of this function is known to be correct, and to FALSE otherwise.
693*/
694
695bool QUrlOperator::isDir( bool *ok )
696{
697 if ( ok )
698 *ok = TRUE;
699 if ( isLocalFile() ) {
700 if ( QFileInfo( path() ).isDir() )
701 return TRUE;
702 else
703 return FALSE;
704 }
705
706 if ( d->entryMap.contains( "." ) ) {
707 return d->entryMap[ "." ].isDir();
708 }
709 // #### can assume that we are a directory?
710 if ( ok )
711 *ok = FALSE;
712 return TRUE;
713}
714
715/*!
716 Tells the network protocol to get data from \a location or, if
717 this is QString::null, to get data from the location to which this
718 URL points (see QUrl::fileName() and QUrl::encodedPathAndQuery()).
719 What happens then depends on the network protocol. The data()
720 signal is emitted when data comes in. Because it's unlikely that
721 all data will come in at once, it is common for multiple data()
722 signals to be emitted. The dataTransferProgress() signal is
723 emitted while processing the operation. At the end, finished()
724 (with success or failure) is emitted, so check the state of the
725 network operation object to see whether or not the operation was
726 successful.
727
728 If \a location is QString::null, the path of this QUrlOperator
729 should point to a file when you use this operation. If \a location
730 is not empty, it can be a relative URL (a child of the path to
731 which the QUrlOperator points) or an absolute URL.
732
733 For example, to get a web page you might do something like this:
734
735 \code
736 QUrlOperator op( "http://www.whatever.org/cgi-bin/search.pl?cmd=Hello" );
737 op.get();
738 \endcode
739
740 For most other operations, the path of the QUrlOperator must point
741 to a directory. If you want to download a file you could do the
742 following:
743
744 \code
745 QUrlOperator op( "ftp://ftp.whatever.org/pub" );
746 // do some other stuff like op.listChildren() or op.mkdir( "new_dir" )
747 op.get( "a_file.txt" );
748 \endcode
749
750 This will get the data of ftp://ftp.whatever.org/pub/a_file.txt.
751
752 \e Never do anything like this:
753 \code
754 QUrlOperator op( "http://www.whatever.org/cgi-bin" );
755 op.get( "search.pl?cmd=Hello" ); // WRONG!
756 \endcode
757
758 If \a location is not empty and relative it must not contain any
759 queries or references, just the name of a child. So if you need to
760 specify a query or reference, do it as shown in the first example
761 or specify the full URL (such as
762 http://www.whatever.org/cgi-bin/search.pl?cmd=Hello) as \a location.
763
764 \sa copy()
765*/
766
767const QNetworkOperation *QUrlOperator::get( const QString &location )
768{
769 QUrl u( *this );
770 if ( !location.isEmpty() )
771 u = QUrl( *this, location );
772
773 if ( !u.isValid() )
774 return 0;
775
776 if ( !d->networkProtocol ) {
777 setProtocol( u.protocol() );
778 getNetworkProtocol();
779 }
780
781 QNetworkOperation *res = new QNetworkOperation( QNetworkProtocol::OpGet, u, QString::null, QString::null );
782 return startOperation( res );
783}
784
785/*!
786 This function tells the network protocol to put \a data in \a
787 location. If \a location is empty (QString::null), it puts the \a
788 data in the location to which the URL points. What happens depends
789 on the network protocol. Depending on the network protocol, some
790 data might come back after putting data, in which case the data()
791 signal is emitted. The dataTransferProgress() signal is emitted
792 during processing of the operation. At the end, finished() (with
793 success or failure) is emitted, so check the state of the network
794 operation object to see whether or not the operation was
795 successful.
796
797 If \a location is QString::null, the path of this QUrlOperator
798 should point to a file when you use this operation. If \a location
799 is not empty, it can be a relative (a child of the path to which
800 the QUrlOperator points) or an absolute URL.
801
802 For putting some data to a file you can do the following:
803
804 \code
805 QUrlOperator op( "ftp://ftp.whatever.com/home/me/filename.dat" );
806 op.put( data );
807 \endcode
808
809 For most other operations, the path of the QUrlOperator must point
810 to a directory. If you want to upload data to a file you could do
811 the following:
812
813 \code
814 QUrlOperator op( "ftp://ftp.whatever.com/home/me" );
815 // do some other stuff like op.listChildren() or op.mkdir( "new_dir" )
816 op.put( data, "filename.dat" );
817 \endcode
818
819 This will upload the data to ftp://ftp.whatever.com/home/me/filename.dat.
820
821 \sa copy()
822*/
823
824const QNetworkOperation *QUrlOperator::put( const QByteArray &data, const QString &location )
825{
826 QUrl u( *this );
827 if ( !location.isEmpty() )
828 u = QUrl( *this, location );
829
830 if ( !u.isValid() )
831 return 0;
832
833 if ( !d->networkProtocol ) {
834 setProtocol( u.protocol() );
835 getNetworkProtocol();
836 }
837
838 QNetworkOperation *res = new QNetworkOperation( QNetworkProtocol::OpPut, u, QString::null, QString::null );
839 res->setRawArg( 1, data );
840 return startOperation( res );
841}
842
843/*!
844 Sets the name filter of the URL to \a nameFilter.
845
846 \sa QDir::setNameFilter()
847*/
848
849void QUrlOperator::setNameFilter( const QString &nameFilter )
850{
851 d->nameFilter = nameFilter;
852}
853
854/*!
855 Returns the name filter of the URL.
856
857 \sa QUrlOperator::setNameFilter() QDir::nameFilter()
858*/
859
860QString QUrlOperator::nameFilter() const
861{
862 return d->nameFilter;
863}
864
865/*!
866 Clears the cache of children.
867*/
868
869void QUrlOperator::clearEntries()
870{
871 d->entryMap.clear();
872}
873
874/*!
875 Adds an entry to the cache of children.
876*/
877
878void QUrlOperator::addEntry( const QValueList<QUrlInfo> &i )
879{
880 QValueList<QUrlInfo>::ConstIterator it = i.begin();
881 for ( ; it != i.end(); ++it )
882 d->entryMap[ ( *it ).name().stripWhiteSpace() ] = *it;
883}
884
885/*!
886 Returns the URL information for the child \a entry, or returns an
887 empty QUrlInfo object if there is no information available about
888 \a entry. Information about \a entry is only available after a successfully
889 finished listChildren() operation.
890*/
891
892QUrlInfo QUrlOperator::info( const QString &entry ) const
893{
894 if ( d->entryMap.contains( entry.stripWhiteSpace() ) ) {
895 return d->entryMap[ entry.stripWhiteSpace() ];
896 } else if ( entry == "." || entry == ".." ) {
897 // return a faked QUrlInfo
898 QUrlInfo inf;
899 inf.setName( entry );
900 inf.setDir( TRUE );
901 inf.setFile( FALSE );
902 inf.setSymLink( FALSE );
903 inf.setOwner( tr( "(unknown)" ) );
904 inf.setGroup( tr( "(unknown)" ) );
905 inf.setSize( 0 );
906 inf.setWritable( FALSE );
907 inf.setReadable( TRUE );
908 return inf;
909 }
910 return QUrlInfo();
911}
912
913/*!
914 Finds a network protocol for the URL and deletes the old network protocol.
915*/
916
917void QUrlOperator::getNetworkProtocol()
918{
919 delete d->networkProtocol;
920 QNetworkProtocol *p = QNetworkProtocol::getNetworkProtocol( protocol() );
921 if ( !p ) {
922 d->networkProtocol = 0;
923 return;
924 }
925
926 d->networkProtocol = (QNetworkProtocol *)p;
927 d->networkProtocol->setUrl( this );
928 connect( d->networkProtocol, SIGNAL( itemChanged(QNetworkOperation*) ),
929 this, SLOT( slotItemChanged(QNetworkOperation*) ) );
930}
931
932/*!
933 Deletes the currently used network protocol.
934*/
935
936void QUrlOperator::deleteNetworkProtocol()
937{
938 delete d->networkProtocol;
939 d->networkProtocol = 0;
940}
941
942/*!
943 \reimp
944*/
945
946void QUrlOperator::setPath( const QString& path )
947{
948 QUrl::setPath( path );
949 if ( d->networkProtocol )
950 d->networkProtocol->setUrl( this );
951}
952
953/*!
954 \reimp
955*/
956
957void QUrlOperator::reset()
958{
959 QUrl::reset();
960 deleteNetworkProtocol();
961 d->nameFilter = "*";
962}
963
964/*!
965 \reimp
966*/
967
968bool QUrlOperator::parse( const QString &url )
969{
970 bool b = QUrl::parse( url );
971 if ( !b ) {
972 return b;
973 }
974
975 getNetworkProtocol();
976
977 return b;
978}
979
980/*!
981 \reimp
982*/
983
984QUrlOperator& QUrlOperator::operator=( const QUrlOperator &url )
985{
986 deleteNetworkProtocol();
987 QUrl::operator=( url );
988
989 QPtrDict<QNetworkOperation> getOpPutOpMap = d->getOpPutOpMap;
990 QPtrDict<QNetworkProtocol> getOpPutProtMap = d->getOpPutProtMap;
991 QPtrDict<QNetworkProtocol> getOpGetProtMap = d->getOpGetProtMap;
992 QPtrDict<QNetworkOperation> getOpRemoveOpMap = d->getOpRemoveOpMap;
993
994 *d = *url.d;
995
996 d->oldOps.setAutoDelete( FALSE );
997 d->getOpPutOpMap = getOpPutOpMap;
998 d->getOpPutProtMap = getOpPutProtMap;
999 d->getOpGetProtMap = getOpGetProtMap;
1000 d->getOpRemoveOpMap = getOpRemoveOpMap;
1001
1002 d->networkProtocol = 0;
1003 getNetworkProtocol();
1004 return *this;
1005}
1006
1007/*!
1008 \reimp
1009*/
1010
1011QUrlOperator& QUrlOperator::operator=( const QString &url )
1012{
1013 deleteNetworkProtocol();
1014 QUrl::operator=( url );
1015 d->oldOps.setAutoDelete( FALSE );
1016 getNetworkProtocol();
1017 return *this;
1018}
1019
1020/*!
1021 \reimp
1022*/
1023
1024bool QUrlOperator::cdUp()
1025{
1026 bool b = QUrl::cdUp();
1027 if ( d->networkProtocol )
1028 d->networkProtocol->setUrl( this );
1029 return b;
1030}
1031
1032/*!
1033 \reimp
1034*/
1035
1036bool QUrlOperator::checkValid()
1037{
1038 // ######
1039 if ( !isValid() ) {
1040 //emit error( ErrValid, tr( "The entered URL is not valid!" ) );
1041 return FALSE;
1042 } else
1043 return TRUE;
1044}
1045
1046
1047/*!
1048 \internal
1049*/
1050
1051void QUrlOperator::copyGotData( const QByteArray &data_, QNetworkOperation *op )
1052{
1053#ifdef QURLOPERATOR_DEBUG
1054 qDebug( "QUrlOperator: copyGotData: %d new bytes", data_.size() );
1055#endif
1056 QNetworkOperation *put = d->getOpPutOpMap[ (void*)op ];
1057 if ( put ) {
1058 QByteArray &s = put->raw( 1 );
1059 int size = s.size();
1060 s.resize( size + data_.size() );
1061 memcpy( s.data() + size, data_.data(), data_.size() );
1062 }
1063 emit data( data_, op );
1064}
1065
1066/*!
1067 \internal
1068*/
1069
1070void QUrlOperator::continueCopy( QNetworkOperation *op )
1071{
1072 if ( op->operation() != QNetworkProtocol::OpGet )
1073 return;
1074 if ( op->state()!=QNetworkProtocol::StDone && op->state()!=QNetworkProtocol::StFailed ) {
1075 return;
1076 }
1077
1078#ifdef QURLOPERATOR_DEBUG
1079 if ( op->state() != QNetworkProtocol::StFailed ) {
1080 qDebug( "QUrlOperator: continue copy (get finished, put will start)" );
1081 }
1082#endif
1083
1084 QNetworkOperation *put = d->getOpPutOpMap[ (void*)op ];
1085 QNetworkProtocol *gProt = d->getOpGetProtMap[ (void*)op ];
1086 QNetworkProtocol *pProt = d->getOpPutProtMap[ (void*)op ];
1087 QNetworkOperation *rm = d->getOpRemoveOpMap[ (void*)op ];
1088 d->getOpPutOpMap.take( op );
1089 d->getOpGetProtMap.take( op );
1090 d->getOpPutProtMap.take( op );
1091 d->getOpRemoveOpMap.take( op );
1092 if ( pProt )
1093 pProt->setAutoDelete( TRUE );
1094 if ( put && pProt ) {
1095 if ( op->state() != QNetworkProtocol::StFailed ) {
1096 pProt->addOperation( put );
1097 d->currPut = pProt;
1098 } else {
1099 deleteOperation( put );
1100 }
1101 }
1102 if ( gProt ) {
1103 gProt->setAutoDelete( TRUE );
1104 }
1105 if ( rm && gProt ) {
1106 if ( op->state() != QNetworkProtocol::StFailed ) {
1107 gProt->addOperation( rm );
1108 } else {
1109 deleteOperation( rm );
1110 }
1111 }
1112 disconnect( gProt, SIGNAL( data(const QByteArray&,QNetworkOperation*) ),
1113 this, SLOT( copyGotData(const QByteArray&,QNetworkOperation*) ) );
1114 disconnect( gProt, SIGNAL( finished(QNetworkOperation*) ),
1115 this, SLOT( continueCopy(QNetworkOperation*) ) );
1116}
1117
1118/*!
1119 \internal
1120*/
1121
1122void QUrlOperator::finishedCopy()
1123{
1124#ifdef QURLOPERATOR_DEBUG
1125 qDebug( "QUrlOperator: finished copy (finished putting)" );
1126#endif
1127
1128 if ( d->waitingCopies.isEmpty() )
1129 return;
1130
1131 QString cp = d->waitingCopies.first();
1132 d->waitingCopies.remove( cp );
1133 QPtrList<QNetworkOperation> lst = copy( cp, d->waitingCopiesDest, d->waitingCopiesMove );
1134 emit startedNextCopy( lst );
1135}
1136
1137/*!
1138 Stops the current network operation and removes all this
1139 QUrlOperator's waiting network operations.
1140*/
1141
1142void QUrlOperator::stop()
1143{
1144 d->getOpPutOpMap.clear();
1145 d->getOpRemoveOpMap.clear();
1146 d->getOpGetProtMap.setAutoDelete( TRUE );
1147 d->getOpPutProtMap.setAutoDelete( TRUE );
1148 QPtrDictIterator<QNetworkProtocol> it( d->getOpPutProtMap );
1149 for ( ; it.current(); ++it )
1150 it.current()->stop();
1151 d->getOpPutProtMap.clear();
1152 it = QPtrDictIterator<QNetworkProtocol>( d->getOpGetProtMap );
1153 for ( ; it.current(); ++it )
1154 it.current()->stop();
1155 d->getOpGetProtMap.clear();
1156 if ( d->currPut ) {
1157 d->currPut->stop();
1158 delete (QNetworkProtocol *) d->currPut;
1159 d->currPut = 0;
1160 }
1161 d->waitingCopies.clear();
1162 if ( d->networkProtocol )
1163 d->networkProtocol->stop();
1164 getNetworkProtocol();
1165}
1166
1167/*!
1168 \internal
1169*/
1170
1171void QUrlOperator::deleteOperation( QNetworkOperation *op )
1172{
1173 if ( op )
1174 d->oldOps.append( op );
1175}
1176
1177/*!
1178 \internal
1179 updates the entryMap after a network operation finished
1180*/
1181
1182void QUrlOperator::slotItemChanged( QNetworkOperation *op )
1183{
1184 if ( !op )
1185 return;
1186
1187 switch ( op->operation() ) {
1188 case QNetworkProtocol::OpRename :
1189 {
1190 if ( op->arg( 0 ) == op->arg( 1 ) )
1191 return;
1192
1193 QMap<QString, QUrlInfo>::iterator mi = d->entryMap.find( op->arg( 0 ) );
1194 if ( mi != d->entryMap.end() ) {
1195 mi.data().setName( op->arg( 1 ) );
1196 d->entryMap[ op->arg( 1 ) ] = mi.data();
1197 d->entryMap.erase( mi );
1198 }
1199 break;
1200 }
1201 case QNetworkProtocol::OpRemove :
1202 {
1203 QMap<QString, QUrlInfo>::iterator mi = d->entryMap.find( op->arg( 0 ) );
1204 if ( mi != d->entryMap.end() )
1205 d->entryMap.erase( mi );
1206 break;
1207 }
1208 default:
1209 break;
1210 }
1211}
1212
1213
1214#endif // QT_NO_NETWORKPROTOCOL
Note: See TracBrowser for help on using the repository browser.