src/gui/dialogs/qfilesystemmodel_p.h
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    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 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #ifndef QFILESYSTEMMODEL_P_H
       
    43 #define QFILESYSTEMMODEL_P_H
       
    44 
       
    45 //
       
    46 //  W A R N I N G
       
    47 //  -------------
       
    48 //
       
    49 // This file is not part of the Qt API.  It exists purely as an
       
    50 // implementation detail.  This header file may change from version to
       
    51 // version without notice, or even be removed.
       
    52 //
       
    53 // We mean it.
       
    54 //
       
    55 
       
    56 #include "qfilesystemmodel.h"
       
    57 
       
    58 #ifndef QT_NO_FILESYSTEMMODEL
       
    59 
       
    60 #include <private/qabstractitemmodel_p.h>
       
    61 #include <qabstractitemmodel.h>
       
    62 #include "qfileinfogatherer_p.h"
       
    63 #include <qpair.h>
       
    64 #include <qdir.h>
       
    65 #include <qicon.h>
       
    66 #include <qdir.h>
       
    67 #include <qicon.h>
       
    68 #include <qfileinfo.h>
       
    69 #include <qtimer.h>
       
    70 #include <qhash.h>
       
    71 
       
    72 QT_BEGIN_NAMESPACE
       
    73 
       
    74 class ExtendedInformation;
       
    75 class QFileSystemModelPrivate;
       
    76 class QFileIconProvider;
       
    77 
       
    78 class Q_AUTOTEST_EXPORT QFileSystemModelPrivate : public QAbstractItemModelPrivate
       
    79 {
       
    80     Q_DECLARE_PUBLIC(QFileSystemModel)
       
    81 
       
    82 public:
       
    83     class QFileSystemNode
       
    84     {
       
    85     public:
       
    86         QFileSystemNode(const QString &filename = QString(), QFileSystemNode *p = 0)
       
    87             : fileName(filename), populatedChildren(false), isVisible(false), dirtyChildrenIndex(-1), parent(p), info(0) {}
       
    88         ~QFileSystemNode() {
       
    89             QHash<QString, QFileSystemNode*>::const_iterator i = children.constBegin();
       
    90             while (i != children.constEnd()) {
       
    91                     delete i.value();
       
    92                     ++i;
       
    93             }
       
    94             delete info;
       
    95             info = 0;
       
    96             parent = 0;
       
    97         }
       
    98 
       
    99         QString fileName;
       
   100 
       
   101         inline qint64 size() const { if (info && !info->isDir()) return info->size(); return 0; }
       
   102         inline QString type() const { if (info) return info->displayType; return QLatin1String(""); }
       
   103         inline QDateTime lastModified() const { if (info) return info->lastModified(); return QDateTime(); }
       
   104         inline QFile::Permissions permissions() const { if (info) return info->permissions(); return 0; }
       
   105         inline bool isReadable() const { return ((permissions() & QFile::ReadUser) != 0); }
       
   106         inline bool isWritable() const { return ((permissions() & QFile::WriteUser) != 0); }
       
   107         inline bool isExecutable() const { return ((permissions() & QFile::ExeUser) != 0); }
       
   108         inline bool isDir() const {
       
   109             if (info)
       
   110                 return info->isDir();
       
   111             if (children.count() > 0)
       
   112                 return true;
       
   113             return false;
       
   114         }
       
   115         inline bool isFile() const { if (info) return info->isFile(); return true; }
       
   116         inline bool isSystem() const { if (info) return info->isSystem(); return true; }
       
   117         inline bool isHidden() const { if (info) return info->isHidden(); return false; }
       
   118         inline bool isSymLink() const { if (info) return info->isSymLink(); return false; }
       
   119         inline bool caseSensitive() const { if (info) return info->isCaseSensitive(); return false; }
       
   120         inline QIcon icon() const { if (info) return info->icon; return QIcon(); }
       
   121 
       
   122         inline bool operator <(const QFileSystemNode &node) const {
       
   123             if (caseSensitive() || node.caseSensitive())
       
   124                 return fileName < node.fileName;
       
   125             return QString::compare(fileName, node.fileName, Qt::CaseInsensitive) < 0;
       
   126         }
       
   127         inline bool operator >(const QString &name) const {
       
   128             if (caseSensitive())
       
   129                 return fileName > name;
       
   130             return QString::compare(fileName, name, Qt::CaseInsensitive) > 0;
       
   131         }
       
   132         inline bool operator <(const QString &name) const {
       
   133             if (caseSensitive())
       
   134                 return fileName < name;
       
   135             return QString::compare(fileName, name, Qt::CaseInsensitive) < 0;
       
   136         }
       
   137         inline bool operator !=(const QExtendedInformation &fileInfo) const {
       
   138             return !operator==(fileInfo);
       
   139         }
       
   140         bool operator ==(const QString &name) const {
       
   141             if (caseSensitive())
       
   142                 return fileName == name;
       
   143             return QString::compare(fileName, name, Qt::CaseInsensitive) == 0;
       
   144         }
       
   145         bool operator ==(const QExtendedInformation &fileInfo) const {
       
   146             return info && (*info == fileInfo);
       
   147         }
       
   148 
       
   149         inline bool hasInformation() const { return info != 0; }
       
   150 
       
   151         void populate(const QExtendedInformation &fileInfo) {
       
   152             if (!info)
       
   153                 info = new QExtendedInformation(fileInfo.fileInfo());
       
   154             (*info) = fileInfo;
       
   155         }
       
   156 
       
   157         // children shouldn't normally be accessed directly, use node()
       
   158         inline int visibleLocation(QString childName) {
       
   159             return visibleChildren.indexOf(childName);
       
   160         }
       
   161         void updateIcon(QFileIconProvider *iconProvider, const QString &path) {
       
   162             if (info)
       
   163                 info->icon = iconProvider->icon(QFileInfo(path));
       
   164             QHash<QString, QFileSystemNode *>::const_iterator iterator;
       
   165             for(iterator = children.constBegin() ; iterator != children.constEnd() ; ++iterator) {
       
   166                 //On windows the root (My computer) has no path so we don't want to add a / for nothing (e.g. /C:/)
       
   167                 if (!path.isEmpty()) {
       
   168                     if (path.endsWith(QLatin1Char('/')))
       
   169                         iterator.value()->updateIcon(iconProvider, path + iterator.value()->fileName);
       
   170                     else
       
   171                         iterator.value()->updateIcon(iconProvider, path + QLatin1Char('/') + iterator.value()->fileName);
       
   172                 } else
       
   173                     iterator.value()->updateIcon(iconProvider, iterator.value()->fileName);
       
   174             }
       
   175         }
       
   176 
       
   177         void retranslateStrings(QFileIconProvider *iconProvider, const QString &path) {
       
   178             if (info)
       
   179                 info->displayType = iconProvider->type(QFileInfo(path));
       
   180             QHash<QString, QFileSystemNode *>::const_iterator iterator;
       
   181             for(iterator = children.constBegin() ; iterator != children.constEnd() ; ++iterator) {
       
   182                 //On windows the root (My computer) has no path so we don't want to add a / for nothing (e.g. /C:/)
       
   183                 if (!path.isEmpty()) {
       
   184                     if (path.endsWith(QLatin1Char('/')))
       
   185                         iterator.value()->retranslateStrings(iconProvider, path + iterator.value()->fileName);
       
   186                     else
       
   187                         iterator.value()->retranslateStrings(iconProvider, path + QLatin1Char('/') + iterator.value()->fileName);
       
   188                 } else
       
   189                     iterator.value()->retranslateStrings(iconProvider, iterator.value()->fileName);
       
   190             }
       
   191         }
       
   192 
       
   193         bool populatedChildren;
       
   194         bool isVisible;
       
   195         QHash<QString,QFileSystemNode *> children;
       
   196         QList<QString> visibleChildren;
       
   197         int dirtyChildrenIndex;
       
   198         QFileSystemNode *parent;
       
   199 
       
   200 
       
   201         QExtendedInformation *info;
       
   202 
       
   203     };
       
   204 
       
   205     QFileSystemModelPrivate() :
       
   206             forceSort(true),
       
   207             sortColumn(0),
       
   208             sortOrder(Qt::AscendingOrder),
       
   209             readOnly(true),
       
   210             setRootPath(false),
       
   211             filters(QDir::AllEntries | QDir::NoDotAndDotDot | QDir::AllDirs),
       
   212             nameFilterDisables(true), // false on windows, true on mac and unix
       
   213             disableRecursiveSort(false)
       
   214     {
       
   215         delayedSortTimer.setSingleShot(true);
       
   216     }
       
   217 
       
   218     void init();
       
   219     /*
       
   220       \internal
       
   221 
       
   222       Return true if index which is owned by node is hidden by the filter.
       
   223     */
       
   224     inline bool isHiddenByFilter(QFileSystemNode *indexNode, const QModelIndex &index) const
       
   225     {
       
   226        return (indexNode != &root && !index.isValid());
       
   227     }
       
   228     QFileSystemNode *node(const QModelIndex &index) const;
       
   229     QFileSystemNode *node(const QString &path, bool fetch = true) const;
       
   230     inline QModelIndex index(const QString &path) { return index(node(path)); }
       
   231     QModelIndex index(const QFileSystemNode *node) const;
       
   232     bool filtersAcceptsNode(const QFileSystemNode *node) const;
       
   233     bool passNameFilters(const QFileSystemNode *node) const;
       
   234     void removeNode(QFileSystemNode *parentNode, const QString &name);
       
   235     QFileSystemNode* addNode(QFileSystemNode *parentNode, const QString &fileName, const QFileInfo &info);
       
   236     void addVisibleFiles(QFileSystemNode *parentNode, const QStringList &newFiles);
       
   237     void removeVisibleFile(QFileSystemNode *parentNode, int visibleLocation);
       
   238     void sortChildren(int column, const QModelIndex &parent);
       
   239 
       
   240     inline int translateVisibleLocation(QFileSystemNode *parent, int row) const {
       
   241         if (sortOrder == Qt::AscendingOrder)
       
   242                 return row;
       
   243         if (parent->dirtyChildrenIndex == -1 || row < parent->dirtyChildrenIndex)
       
   244             if (parent->dirtyChildrenIndex != -1)
       
   245                 return parent->dirtyChildrenIndex - row - 1;
       
   246             else
       
   247                 return parent->visibleChildren.count() - row - 1;
       
   248         else
       
   249             return row;
       
   250     }
       
   251 
       
   252     inline static QString myComputer() {
       
   253         // ### TODO We should query the system to find out what the string should be
       
   254         // XP == "My Computer",
       
   255         // Vista == "Computer",
       
   256         // OS X == "Computer" (sometime user generated) "Benjamin's PowerBook G4"
       
   257 #ifdef Q_OS_WIN
       
   258         return QFileSystemModel::tr("My Computer");
       
   259 #else
       
   260         return QFileSystemModel::tr("Computer");
       
   261 #endif
       
   262     }
       
   263 
       
   264     inline void delayedSort() {
       
   265         if (!delayedSortTimer.isActive())
       
   266             delayedSortTimer.start(0);
       
   267     }
       
   268 
       
   269     static bool caseInsensitiveLessThan(const QString &s1, const QString &s2)
       
   270     {
       
   271        return QString::compare(s1, s2, Qt::CaseInsensitive) < 0;
       
   272     }
       
   273 
       
   274     static bool nodeCaseInsensitiveLessThan(const QFileSystemModelPrivate::QFileSystemNode &s1, const QFileSystemModelPrivate::QFileSystemNode &s2)
       
   275     {
       
   276        return QString::compare(s1.fileName, s2.fileName, Qt::CaseInsensitive) < 0;
       
   277     }
       
   278 
       
   279     QIcon icon(const QModelIndex &index) const;
       
   280     QString name(const QModelIndex &index) const;
       
   281     QString filePath(const QModelIndex &index) const;
       
   282     QString size(const QModelIndex &index) const;
       
   283     static QString size(qint64 bytes);
       
   284     QString type(const QModelIndex &index) const;
       
   285     QString time(const QModelIndex &index) const;
       
   286 
       
   287     void _q_directoryChanged(const QString &directory, const QStringList &list);
       
   288     void _q_performDelayedSort();
       
   289     void _q_fileSystemChanged(const QString &path, const QList<QPair<QString, QFileInfo> > &);
       
   290     void _q_resolvedName(const QString &fileName, const QString &resolvedName);
       
   291 
       
   292     static int naturalCompare(const QString &s1, const QString &s2, Qt::CaseSensitivity cs);
       
   293 
       
   294     QDir rootDir;
       
   295 #ifndef QT_NO_FILESYSTEMWATCHER
       
   296     QFileInfoGatherer fileInfoGatherer;
       
   297 #endif
       
   298     QTimer delayedSortTimer;
       
   299     bool forceSort;
       
   300     int sortColumn;
       
   301     Qt::SortOrder sortOrder;
       
   302     bool readOnly;
       
   303     bool setRootPath;
       
   304     QDir::Filters filters;
       
   305     QHash<const QFileSystemNode*, bool> bypassFilters;
       
   306     bool nameFilterDisables;
       
   307     //This flag is an optimization for the QFileDialog
       
   308     //It enable a sort which is not recursive, it means
       
   309     //we sort only what we see.
       
   310     bool disableRecursiveSort;
       
   311 #ifndef QT_NO_REGEXP
       
   312     QList<QRegExp> nameFilters;
       
   313 #endif
       
   314     // ### Qt 5: resolvedSymLinks goes away
       
   315     QHash<QString, QString> resolvedSymLinks;
       
   316 
       
   317     QFileSystemNode root;
       
   318 
       
   319     QBasicTimer fetchingTimer;
       
   320     struct Fetching {
       
   321         QString dir;
       
   322         QString file;
       
   323         const QFileSystemNode *node;
       
   324     };
       
   325     QList<Fetching> toFetch;
       
   326 
       
   327 };
       
   328 #endif // QT_NO_FILESYSTEMMODEL
       
   329 
       
   330 QT_END_NAMESPACE
       
   331 
       
   332 #endif
       
   333