source: trunk/src/qt3support/network/q3urloperator.cpp@ 98

Last change on this file since 98 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

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