source: trunk/src/qt3support/network/q3localfs.cpp@ 846

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

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 10.8 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the Qt3Support module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "q3localfs.h"
43
44#ifndef QT_NO_NETWORKPROTOCOL
45
46#include "qfileinfo.h"
47#include "qfile.h"
48#include "q3url.h"
49#include "qurlinfo.h"
50#include "qapplication.h"
51#include "q3urloperator.h"
52#include "qpointer.h"
53#include "q3valuelist.h"
54
55QT_BEGIN_NAMESPACE
56
57//#define QLOCALFS_DEBUG
58
59
60/*!
61 \class Q3LocalFs
62 \brief The Q3LocalFs class is an implementation of a
63 QNetworkProtocol that works on the local file system.
64
65 \compat
66
67 This class is derived from QNetworkProtocol. Q3LocalFs is not
68 normally used directly, but rather through a QUrlOperator, for
69 example:
70 \snippet doc/src/snippets/code/src_qt3support_network_q3localfs.cpp 0
71
72 This code will only work if the Q3LocalFs class is registered; to
73 register the class, you must call qInitNetworkProtocols() before
74 using a QUrlOperator with Q3LocalFs.
75
76 If you really need to use Q3LocalFs directly, don't forget
77 to set its QUrlOperator with setUrl().
78
79 \sa Q3NetworkProtocol, Q3UrlOperator
80*/
81
82/*!
83 Constructor.
84*/
85
86Q3LocalFs::Q3LocalFs()
87 : Q3NetworkProtocol()
88{
89}
90
91static int convertPermissions(QFileInfo *fi)
92{
93 int p = 0;
94 if ( fi->permission( QFileInfo::ReadOwner ) )
95 p |= QUrlInfo::ReadOwner;
96 if ( fi->permission( QFileInfo::WriteOwner ) )
97 p |= QUrlInfo::WriteOwner;
98 if ( fi->permission( QFileInfo::ExeOwner ) )
99 p |= QUrlInfo::ExeOwner;
100 if ( fi->permission( QFileInfo::ReadGroup ) )
101 p |= QUrlInfo::ReadGroup;
102 if ( fi->permission( QFileInfo::WriteGroup ) )
103 p |= QUrlInfo::WriteGroup;
104 if ( fi->permission( QFileInfo::ExeGroup ) )
105 p |= QUrlInfo::ExeGroup;
106 if ( fi->permission( QFileInfo::ReadOther ) )
107 p |= QUrlInfo::ReadOther;
108 if ( fi->permission( QFileInfo::WriteOther ) )
109 p |= QUrlInfo::WriteOther;
110 if ( fi->permission( QFileInfo::ExeOther ) )
111 p |= QUrlInfo::ExeOther;
112 return p;
113}
114
115/*!
116 \reimp
117*/
118
119void Q3LocalFs::operationListChildren( Q3NetworkOperation *op )
120{
121#ifdef QLOCALFS_DEBUG
122 qDebug( "Q3LocalFs: operationListChildren" );
123#endif
124 op->setState( StInProgress );
125
126 dir = QDir( url()->path() );
127 dir.setNameFilter( url()->nameFilter() );
128 dir.setMatchAllDirs( true );
129 if ( !dir.isReadable() ) {
130 QString msg = tr( "Could not read directory\n%1" ).arg( url()->path() );
131 op->setState( StFailed );
132 op->setProtocolDetail( msg );
133 op->setErrorCode( (int)ErrListChildren );
134 emit finished( op );
135 return;
136 }
137
138 QFileInfoList filist = dir.entryInfoList(QDir::All | QDir::Hidden | QDir::System);
139 if ( filist.isEmpty() ) {
140 QString msg = tr( "Could not read directory\n%1" ).arg( url()->path() );
141 op->setState( StFailed );
142 op->setProtocolDetail( msg );
143 op->setErrorCode( (int)ErrListChildren );
144 emit finished( op );
145 return;
146 }
147
148 emit start( op );
149
150 Q3ValueList<QUrlInfo> infos;
151 for (int i = 0; i < filist.size(); ++i) {
152 QFileInfo fi = filist.at(i);
153 infos << QUrlInfo( fi.fileName(), convertPermissions(&fi), fi.owner(), fi.group(),
154 fi.size(), fi.lastModified(), fi.lastRead(), fi.isDir(), fi.isFile(),
155 fi.isSymLink(), fi.isWritable(), fi.isReadable(), fi.isExecutable() );
156 }
157 emit newChildren( infos, op );
158 op->setState( StDone );
159 emit finished( op );
160}
161
162/*!
163 \reimp
164*/
165
166void Q3LocalFs::operationMkDir( Q3NetworkOperation *op )
167{
168#ifdef QLOCALFS_DEBUG
169 qDebug( "Q3LocalFs: operationMkDir" );
170#endif
171 op->setState( StInProgress );
172 QString dirname = op->arg( 0 );
173
174 dir = QDir( url()->path() );
175 if ( dir.mkdir( dirname ) ) {
176 QFileInfo fi( dir, dirname );
177 QUrlInfo inf( fi.fileName(), convertPermissions(&fi), fi.owner(), fi.group(),
178 fi.size(), fi.lastModified(), fi.lastRead(), fi.isDir(), fi.isFile(),
179 fi.isSymLink(), fi.isWritable(), fi.isReadable(), fi.isExecutable() );
180 emit newChild( inf, op );
181 op->setState( StDone );
182 emit createdDirectory( inf, op );
183 emit finished( op );
184 } else {
185 QString msg = tr( "Could not create directory\n%1" ).arg( dirname );
186 op->setState( StFailed );
187 op->setProtocolDetail( msg );
188 op->setErrorCode( (int)ErrMkDir );
189 emit finished( op );
190 }
191}
192
193/*!
194 \reimp
195*/
196
197void Q3LocalFs::operationRemove( Q3NetworkOperation *op )
198{
199#ifdef QLOCALFS_DEBUG
200 qDebug( "Q3LocalFs: operationRemove" );
201#endif
202 op->setState( StInProgress );
203 QString name = Q3Url( op->arg( 0 ) ).path();
204 bool deleted = false;
205
206 dir = QDir( url()->path() );
207
208 QFileInfo fi( dir, name );
209 if ( fi.isDir() ) {
210 if ( dir.rmdir( name ) )
211 deleted = true;
212 }
213
214 if ( deleted || dir.remove( name ) ) {
215 op->setState( StDone );
216 emit removed( op );
217 emit finished( op );
218 } else {
219 QString msg = tr( "Could not remove file or directory\n%1" ).arg( name );
220 op->setState( StFailed );
221 op->setProtocolDetail( msg );
222 op->setErrorCode( (int)ErrRemove );
223 emit finished( op );
224 }
225}
226
227/*!
228 \reimp
229*/
230
231void Q3LocalFs::operationRename( Q3NetworkOperation *op )
232{
233#ifdef QLOCALFS_DEBUG
234 qDebug( "Q3LocalFs: operationRename" );
235#endif
236 op->setState( StInProgress );
237 QString oldname = op->arg( 0 );
238 QString newname = op->arg( 1 );
239
240 dir = QDir( url()->path() );
241 if ( dir.rename( oldname, newname ) ) {
242 op->setState( StDone );
243 emit itemChanged( op );
244 emit finished( op );
245 } else {
246 QString msg = tr( "Could not rename\n%1\nto\n%2" ).arg( oldname ).arg( newname );
247 op->setState( StFailed );
248 op->setProtocolDetail( msg );
249 op->setErrorCode( (int)ErrRename );
250 emit finished( op );
251 }
252}
253
254/*!
255 \reimp
256*/
257
258void Q3LocalFs::operationGet( Q3NetworkOperation *op )
259{
260#ifdef QLOCALFS_DEBUG
261 qDebug( "Q3LocalFs: operationGet" );
262#endif
263 op->setState( StInProgress );
264 QString from = Q3Url( op->arg( 0 ) ).path();
265
266 QFile f( from );
267 if ( !f.open( IO_ReadOnly ) ) {
268#ifdef QLOCALFS_DEBUG
269 qDebug( "Q3LocalFs: could not open %s", from.latin1() );
270#endif
271 QString msg = tr( "Could not open\n%1" ).arg( from );
272 op->setState( StFailed );
273 op->setProtocolDetail( msg );
274 op->setErrorCode( (int)ErrGet );
275 emit finished( op );
276 return;
277 }
278
279 QByteArray s;
280 emit dataTransferProgress( 0, f.size(), op );
281 if ( f.size() != 0 ) {
282 int blockSize = calcBlockSize( f.size() );
283 if ( (int)f.size() < blockSize ) {
284 s.resize( f.size() );
285 f.readBlock( s.data(), f.size() );
286 emit data( s, op );
287 emit dataTransferProgress( f.size(), f.size(), op );
288#ifdef QLOCALFS_DEBUG
289 qDebug( "Q3LocalFs: got all %d bytes at once", f.size() );
290#endif
291 } else {
292 s.resize( blockSize );
293 int remaining = f.size();
294 QPointer<QObject> that = this;
295 while ( that && remaining > 0 ) {
296 if ( operationInProgress() != op )
297 return;
298 if ( remaining >= blockSize ) {
299 f.readBlock( s.data(), blockSize );
300 emit data( s, op );
301 emit dataTransferProgress( f.size() - remaining, f.size(), op );
302 remaining -= blockSize;
303 } else {
304 s.resize( remaining );
305 f.readBlock( s.data(), remaining );
306 emit data( s, op );
307 emit dataTransferProgress( f.size() - remaining, f.size(), op );
308 remaining -= remaining;
309 }
310 qApp->processEvents();
311 }
312 if ( !that )
313 return;
314#ifdef QLOCALFS_DEBUG
315 qDebug( "Q3LocalFs: got all %d bytes step by step", f.size() );
316#endif
317 emit dataTransferProgress( f.size(), f.size(), op );
318 }
319 }
320 op->setState( StDone );
321 f.close();
322 emit finished( op );
323}
324
325/*!
326 \reimp
327*/
328
329void Q3LocalFs::operationPut( Q3NetworkOperation *op )
330{
331#ifdef QLOCALFS_DEBUG
332 qDebug( "Q3LocalFs: operationPut" );
333#endif
334 op->setState( StInProgress );
335 QString to = Q3Url( op->arg( 0 ) ).path();
336
337 QFile f( to );
338 if ( !f.open( IO_WriteOnly ) ) {
339 QString msg = tr( "Could not write\n%1" ).arg( to );
340 op->setState( StFailed );
341 op->setProtocolDetail( msg );
342 op->setErrorCode( (int)ErrPut );
343 emit finished( op );
344 return;
345 }
346
347 QByteArray ba( op->rawArg( 1 ) );
348 emit dataTransferProgress( 0, ba.size(), op );
349 int blockSize = calcBlockSize( ba.size() );
350 if ( (int)ba.size() < blockSize ) {
351 f.writeBlock( ba.data(), ba.size() );
352 emit dataTransferProgress( ba.size(), ba.size(), op );
353 } else {
354 int i = 0;
355 while ( i + blockSize < (int)ba.size() - 1 ) {
356 if ( operationInProgress() != op )
357 return;
358 f.writeBlock( &ba.data()[ i ], blockSize );
359 f.flush();
360 emit dataTransferProgress( i + blockSize, ba.size(), op );
361 i += blockSize;
362 QPointer<QObject> that = this;
363 qApp->processEvents();
364 if (!that)
365 return;
366 }
367 if ( i < (int)ba.size() - 1 )
368 f.writeBlock( &ba.data()[ i ], ba.size() - i );
369 emit dataTransferProgress( ba.size(), ba.size(), op );
370 }
371 op->setState( StDone );
372 f.close();
373 emit finished( op );
374}
375
376/*!
377 \reimp
378*/
379
380int Q3LocalFs::supportedOperations() const
381{
382 return OpListChildren | OpMkDir | OpRemove | OpRename | OpGet | OpPut;
383}
384
385/*!
386 \internal
387*/
388
389int Q3LocalFs::calcBlockSize( int totalSize ) const
390{
391 if ( totalSize == 0 )
392 return 1024;
393 int s = totalSize / 100;
394 // we want a block size between 1KB and 1MB
395 if ( s < 1024 )
396 s = 1024;
397 if ( s > 1048576 )
398 s = 1048576;
399 return s;
400}
401
402QT_END_NAMESPACE
403
404#endif // QT_NO_NETWORKPROTOCOL
Note: See TracBrowser for help on using the repository browser.