Qt 4.8
qfileinfogatherer.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qfileinfogatherer_p.h"
43 #include <qdebug.h>
44 #include <qfsfileengine.h>
45 #include <qdiriterator.h>
46 #ifndef Q_OS_WIN
47 # include <unistd.h>
48 # include <sys/types.h>
49 #endif
50 #if defined(Q_OS_VXWORKS)
51 # include "qplatformdefs.h"
52 #endif
53 
55 
56 #ifndef QT_NO_FILESYSTEMMODEL
57 
58 #ifdef QT_BUILD_INTERNAL
59 static bool fetchedRoot = false;
60 Q_AUTOTEST_EXPORT void qt_test_resetFetchedRoot()
61 {
62  fetchedRoot = false;
63 }
64 
65 Q_AUTOTEST_EXPORT bool qt_test_isFetchedRoot()
66 {
67  return fetchedRoot;
68 }
69 #endif
70 
75  : QThread(parent), abort(false),
77  watcher(0),
78 #endif
79  m_resolveSymlinks(false), m_iconProvider(&defaultProvider)
80 {
81 #ifdef Q_OS_WIN
82  m_resolveSymlinks = true;
83 #elif !defined(Q_OS_INTEGRITY) && !defined(Q_OS_VXWORKS)
84  userId = getuid();
85  groupId = getgid();
86 #endif
87 #ifndef QT_NO_FILESYSTEMWATCHER
88  watcher = new QFileSystemWatcher(this);
89  connect(watcher, SIGNAL(directoryChanged(QString)), this, SLOT(list(QString)));
90  connect(watcher, SIGNAL(fileChanged(QString)), this, SLOT(updateFile(QString)));
91 #endif
93 }
94 
99 {
100  QMutexLocker locker(&mutex);
101  abort = true;
102  condition.wakeOne();
103  locker.unlock();
104  wait();
105 }
106 
108 {
109  Q_UNUSED(enable);
110 #ifdef Q_OS_WIN
111  QMutexLocker locker(&mutex);
112  m_resolveSymlinks = enable;
113 #endif
114 }
115 
117 {
118  return m_resolveSymlinks;
119 }
120 
122 {
123  QMutexLocker locker(&mutex);
124  m_iconProvider = provider;
125 }
126 
128 {
129  return m_iconProvider;
130 }
131 
138 {
139  QMutexLocker locker(&mutex);
140  // See if we already have this dir/file in our que
141  int loc = this->path.lastIndexOf(path);
142  while (loc > 0) {
143  if (this->files.at(loc) == files) {
144  return;
145  }
146  loc = this->path.lastIndexOf(path, loc - 1);
147  }
148  this->path.push(path);
149  this->files.push(files);
150  condition.wakeAll();
151 }
152 
159 {
160  QString dir = filePath.mid(0, filePath.lastIndexOf(QDir::separator()));
161  QString fileName = filePath.mid(dir.length() + 1);
162  fetchExtendedInformation(dir, QStringList(fileName));
163 }
164 
165 /*
166  List all files in \a directoryPath
167 
168  \sa listed()
169 */
171 {
172 #ifndef QT_NO_FILESYSTEMWATCHER
173  QMutexLocker locker(&mutex);
176 #endif
177 }
178 
179 /*
180  Remove a \a path from the watcher
181 
182  \sa listed()
183 */
185 {
186 #ifndef QT_NO_FILESYSTEMWATCHER
187  QMutexLocker locker(&mutex);
188  watcher->removePath(path);
189 #endif
190 }
191 
192 /*
193  List all files in \a directoryPath
194 
195  \sa listed()
196 */
197 void QFileInfoGatherer::list(const QString &directoryPath)
198 {
199  fetchExtendedInformation(directoryPath, QStringList());
200 }
201 
202 /*
203  Until aborted wait to fetch a directory or files
204 */
206 {
207  forever {
208  bool updateFiles = false;
209  QMutexLocker locker(&mutex);
210  if (abort) {
211  return;
212  }
213  if (this->path.isEmpty())
214  condition.wait(&mutex);
215  QString path;
217  if (!this->path.isEmpty()) {
218  path = this->path.first();
219  list = this->files.first();
220  this->path.pop_front();
221  this->files.pop_front();
222  updateFiles = true;
223  }
224  locker.unlock();
225  if (updateFiles)
226  getFileInfos(path, list);
227  }
228 }
229 
231 {
232  QExtendedInformation info(fileInfo);
233  info.icon = m_iconProvider->icon(fileInfo);
234  info.displayType = m_iconProvider->type(fileInfo);
235 #ifndef QT_NO_FILESYSTEMWATCHER
236  // ### Not ready to listen all modifications
237  #if 0
238  // Enable the next two commented out lines to get updates when the file sizes change...
239  if (!fileInfo.exists() && !fileInfo.isSymLink()) {
240  info.size = -1;
241  //watcher->removePath(fileInfo.absoluteFilePath());
242  } else {
243  if (!fileInfo.absoluteFilePath().isEmpty() && fileInfo.exists() && fileInfo.isReadable()
244  && !watcher->files().contains(fileInfo.absoluteFilePath())) {
245  //watcher->addPath(fileInfo.absoluteFilePath());
246  }
247  }
248  #endif
249 #endif
250 
251  if (m_resolveSymlinks && info.isSymLink(/* ignoreNtfsSymLinks = */ true)) {
252  QFileInfo resolvedInfo(fileInfo.symLinkTarget());
253  resolvedInfo = resolvedInfo.canonicalFilePath();
254  if (resolvedInfo.exists()) {
255  emit nameResolved(fileInfo.filePath(), resolvedInfo.fileName());
256  }
257  }
258  return info;
259 }
260 
262 {
263  QString driveName = drive.absoluteFilePath();
264 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
265  if (driveName.startsWith(QLatin1Char('/'))) // UNC host
266  return drive.fileName();
267 #endif
268 #if (defined(Q_OS_WIN) && !defined(Q_OS_WINCE)) || defined(Q_OS_SYMBIAN)
269  if (driveName.endsWith(QLatin1Char('/')))
270  driveName.chop(1);
271 #endif
272  return driveName;
273 }
274 
275 /*
276  Get specific file info's, batch the files so update when we have 100
277  items and every 200ms after that
278  */
280 {
281 #ifndef QT_NO_FILESYSTEMWATCHER
282  if (files.isEmpty()
283  && !watcher->directories().contains(path)
284  && !path.isEmpty()
285  && !path.startsWith(QLatin1String("//")) /*don't watch UNC path*/) {
286  watcher->addPath(path);
287  }
288 #endif
289 
290  // List drives
291  if (path.isEmpty()) {
292 #ifdef QT_BUILD_INTERNAL
293  fetchedRoot = true;
294 #endif
295  QFileInfoList infoList;
296  if (files.isEmpty()) {
297  infoList = QDir::drives();
298  } else {
299  for (int i = 0; i < files.count(); ++i)
300  infoList << QFileInfo(files.at(i));
301  }
302  for (int i = infoList.count() - 1; i >= 0; --i) {
303  QString driveName = translateDriveName(infoList.at(i));
304  QList<QPair<QString,QFileInfo> > updatedFiles;
305  updatedFiles.append(QPair<QString,QFileInfo>(driveName, infoList.at(i)));
306  emit updates(path, updatedFiles);
307  }
308  return;
309  }
310 
312  base.start();
313  QFileInfo fileInfo;
314  bool firstTime = true;
315  QList<QPair<QString, QFileInfo> > updatedFiles;
316  QStringList filesToCheck = files;
317 
318  QString itPath = QDir::fromNativeSeparators(files.isEmpty() ? path : QLatin1String(""));
320  QStringList allFiles;
321  while(!abort && dirIt.hasNext()) {
322  dirIt.next();
323  fileInfo = dirIt.fileInfo();
324  allFiles.append(fileInfo.fileName());
325  fetch(fileInfo, base, firstTime, updatedFiles, path);
326  }
327  if (!allFiles.isEmpty())
328  emit newListOfFiles(path, allFiles);
329 
330  QStringList::const_iterator filesIt = filesToCheck.constBegin();
331  while(!abort && filesIt != filesToCheck.constEnd()) {
332  fileInfo.setFile(path + QDir::separator() + *filesIt);
333  ++filesIt;
334  fetch(fileInfo, base, firstTime, updatedFiles, path);
335  }
336  if (!updatedFiles.isEmpty())
337  emit updates(path, updatedFiles);
338  emit directoryLoaded(path);
339 }
340 
341 void QFileInfoGatherer::fetch(const QFileInfo &fileInfo, QElapsedTimer &base, bool &firstTime, QList<QPair<QString, QFileInfo> > &updatedFiles, const QString &path) {
342  updatedFiles.append(QPair<QString, QFileInfo>(fileInfo.fileName(), fileInfo));
343  QElapsedTimer current;
344  current.start();
345  if ((firstTime && updatedFiles.count() > 100) || base.msecsTo(current) > 1000) {
346  emit updates(path, updatedFiles);
347  updatedFiles.clear();
348  base = current;
349  firstTime = false;
350  }
351 }
352 
353 #endif // QT_NO_FILESYSTEMMODEL
354 
void removePath(const QString &path)
void updateFile(const QString &path)
Fetch extended information for all filePath.
QStack< QStringList > files
static mach_timebase_info_data_t info
void pop_front()
This function is provided for STL compatibility.
Definition: qvector.h:284
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
void getFileInfos(const QString &path, const QStringList &files)
The QFileSystemWatcher class provides an interface for monitoring files and directories for modificat...
qint64 msecsTo(const QElapsedTimer &other) const
Returns the number of milliseconds between this QElapsedTimer and other.
void removePath(const QString &file)
Removes the specified path from the file system watcher.
T & first()
Returns a reference to the first item in the vector.
Definition: qvector.h:260
void chop(int n)
Removes n characters from the end of the string.
Definition: qstring.cpp:4623
int length() const
Returns the number of characters in this string.
Definition: qstring.h:696
#define SLOT(a)
Definition: qobjectdefs.h:226
void newListOfFiles(const QString &directory, const QStringList &listOfFiles) const
void setResolveSymlinks(bool enable)
void fetch(const QFileInfo &info, QElapsedTimer &base, bool &firstTime, QList< QPair< QString, QFileInfo > > &updatedFiles, const QString &path)
QString fileName() const
Returns the name of the file, excluding the path.
Definition: qfileinfo.cpp:726
virtual QIcon icon(IconType type) const
Returns an icon set for the given type.
void unlock()
Unlocks this mutex locker.
Definition: qmutex.h:117
void removePaths(const QStringList &files)
Removes the specified paths from the file system watcher.
const_iterator constBegin() const
Returns a const STL-style iterator pointing to the first item in the list.
Definition: qlist.h:269
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition: qstring.cpp:3734
QString absoluteFilePath() const
Returns an absolute path including the file name.
Definition: qfileinfo.cpp:534
QFileSystemWatcher * watcher
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
bool exists() const
Returns true if the file exists; otherwise returns false.
Definition: qfileinfo.cpp:675
int count(const T &t) const
Returns the number of occurrences of value in the list.
Definition: qlist.h:891
The QDirIterator class provides an iterator for directory entrylists.
Definition: qdiriterator.h:54
The QString class provides a Unicode character string.
Definition: qstring.h:83
QString translateDriveName(const QFileInfo &drive) const
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
static QChar separator()
Returns the native directory separator: "/" under Unix (including Mac OS X) and "\\" under Windows...
Definition: qdir.cpp:1831
The QElapsedTimer class provides a fast way to calculate elapsed times.
Definition: qelapsedtimer.h:53
static const uint base
Definition: qurl.cpp:268
virtual QString type(const QFileInfo &info) const
Returns the type of the file described by info.
bool isEmpty() const
Returns true if the list contains no items; otherwise returns false.
Definition: qlist.h:152
QFileInfoGatherer(QObject *parent=0)
Creates thread.
#define SIGNAL(a)
Definition: qobjectdefs.h:227
friend class const_iterator
Definition: qlist.h:264
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
QFileIconProvider * iconProvider() const
void fetchExtendedInformation(const QString &path, const QStringList &files)
Fetch extended information for all files in path.
static bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
Creates a connection of the given type from the signal in the sender object to the method in the rece...
Definition: qobject.cpp:2580
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
QStringList files() const
Returns a list of paths to files that are being watched.
~QFileInfoGatherer()
Destroys thread.
bool isSymLink(bool ignoreNtfsSymLinks=false) const
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
#define emit
Definition: qobjectdefs.h:76
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
QStack< QString > path
void setFile(const QString &file)
Sets the file that the QFileInfo provides information about to file.
Definition: qfileinfo.cpp:468
QString canonicalFilePath() const
Returns the canonical path including the file name, i.e.
Definition: qfileinfo.cpp:551
The QFileIconProvider class provides file icons for the QDirModel and the QFileSystemModel classes...
QExtendedInformation getInfo(const QFileInfo &info) const
QFileIconProvider * m_iconProvider
QBool contains(const QString &str, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the list contains the string str; otherwise returns false.
Definition: qstringlist.h:172
void updates(const QString &directory, const QList< QPair< QString, QFileInfo > > &updates)
static QFileInfoList drives()
Returns a list of the root directories on this system.
Definition: qdir.cpp:1812
void list(const QString &directoryPath)
QWaitCondition condition
bool wait(QMutex *mutex, unsigned long time=ULONG_MAX)
bool resolveSymlinks() const
QString mid(int position, int n=-1) const Q_REQUIRED_RESULT
Returns a string that contains n characters of this string, starting at the specified position index...
Definition: qstring.cpp:3706
The QMutexLocker class is a convenience class that simplifies locking and unlocking mutexes...
Definition: qmutex.h:101
QStringList directories() const
Returns a list of paths to directories that are being watched.
void start(Priority=InheritPriority)
Begins execution of the thread by calling run().
int lastIndexOf(QChar c, int from=-1, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.cpp:3000
void directoryLoaded(const QString &path)
#define QT_NO_FILESYSTEMWATCHER
bool wait(unsigned long time=ULONG_MAX)
Blocks the thread until either of these conditions is met:
void nameResolved(const QString &fileName, const QString &resolvedName) const
#define Q_AUTOTEST_EXPORT
Definition: qglobal.h:1510
QString symLinkTarget() const
Returns the absolute path to the file or directory a symlink (or shortcut on Windows) points to...
Definition: qfileinfo.h:121
void addPath(const QString &file)
Adds path to the file system watcher if path exists.
void run()
The starting point for the thread.
bool isEmpty() const
Returns true if the vector has size 0; otherwise returns false.
Definition: qvector.h:139
static QString fromNativeSeparators(const QString &pathName)
Returns pathName using &#39;/&#39; as file separator.
Definition: qdir.cpp:848
bool isReadable() const
Returns true if the user can read the file; otherwise returns false.
Definition: qfileinfo.cpp:896
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string ends with s; otherwise returns false.
Definition: qstring.cpp:3796
bool isSymLink() const
Returns true if this object points to a symbolic link (or to a shortcut on Windows); otherwise return...
Definition: qfileinfo.cpp:1044
The QFileInfo class provides system-independent file information.
Definition: qfileinfo.h:60
QString filePath() const
Returns the file name, including the path (which may be absolute or relative).
Definition: qfileinfo.cpp:707
The QThread class provides a platform-independent way to manage threads.
Definition: qthread.h:59
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
static QString fileName(const QString &fileUrl)
void start()
Starts this timer.
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
const_iterator constEnd() const
Returns a const STL-style iterator pointing to the imaginary item after the last item in the list...
Definition: qlist.h:272
void setIconProvider(QFileIconProvider *provider)
#define forever
This macro is provided for convenience for writing infinite loops.
Definition: qglobal.h:2452