OSDN Git Service

Changed creation of QFileSystemModel. Object will now be created when the user first...
[lamexp/LameXP.git] / src / Model_FileSystem.cpp
index 9194972..507967e 100644 (file)
 #include <QApplication>
 #include <QFileIconProvider>
 #include <QDesktopServices>
+#include <QLibrary>
 
 #define IS_DIR(ATTR) (((ATTR) & FILE_ATTRIBUTE_DIRECTORY) && (!((ATTR) & FILE_ATTRIBUTE_HIDDEN)))
 #define NO_DOT_OR_DOTDOT(STR) (wcscmp((STR), L".") && wcscmp((STR), L".."))
 
+typedef HANDLE (WINAPI *FindFirstFileExFun)(LPCWSTR lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, LPVOID lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, LPVOID lpSearchFilter, DWORD dwAdditionalFlags);
+
 ///////////////////////////////////////////////////////////////////////////////
 // Dummy QFileIconProvider class
 ///////////////////////////////////////////////////////////////////////////////
@@ -150,6 +153,7 @@ QFileSystemModelEx::QFileSystemModelEx()
 
 QFileSystemModelEx::~QFileSystemModelEx()
 {
+       removeAllFromCache();
        LAMEXP_DELETE(m_myIconProvider);
 }
 
@@ -157,64 +161,114 @@ bool QFileSystemModelEx::hasChildren(const QModelIndex &parent) const
 {
        if(parent.isValid())
        {
-               return (QFileSystemModel::rowCount(parent) > 0) || hasSubfoldersCached(filePath(parent));
+               return hasSubfoldersCached(filePath(parent).toLower()); //return (QDir(QFileSystemModel::filePath(parent)).entryList(QDir::Dirs | QDir::NoDotAndDotDot).count() > 0);
        }
-       
        return true;
 }
 
-int QFileSystemModelEx::rowCount(const QModelIndex &parent) const
+void QFileSystemModelEx::fetchMore(const QModelIndex &parent)
 {
        if(parent.isValid())
        {
-               removeFromCache(filePath(parent));
+               removeFromCache(filePath(parent).toLower());
        }
 
-       return QFileSystemModel::rowCount(parent);
+       QFileSystemModel::fetchMore(parent);
 }
 
-void QFileSystemModelEx::fetchMore(const QModelIndex &parent)
+QModelIndex QFileSystemModelEx::index(const QString &path, int column) const
 {
-       if(parent.isValid())
+       QFileInfo info(path);
+       if(info.exists() && info.isDir())
        {
-               removeFromCache(filePath(parent));
+               QString fullPath = QDir::fromNativeSeparators(info.canonicalFilePath());
+               QStringList parts = fullPath.split('/', QString::SkipEmptyParts);
+               for(int i = 2; i <= parts.count(); i++)
+               {
+                       QFileInfo currentPath(((QStringList) parts.mid(0, i)).join("/"));
+                       if((!currentPath.exists()) || (!currentPath.isDir()) || currentPath.isHidden())
+                       {
+                               return QModelIndex();
+                       }
+               }
+               QModelIndex index = QFileSystemModel::index(fullPath, column);
+               if(index.isValid())
+               {
+                       QModelIndex temp = index;
+                       while(temp.isValid())
+                       {
+                               removeFromCache(filePath(temp).toLower());
+                               temp = temp.parent();
+                       }
+                       return index;
+               }
        }
-
-       QFileSystemModel::fetchMore(parent);
+       return QModelIndex();
 }
 
+void QFileSystemModelEx::flushCache(void)
+{
+       removeAllFromCache();
+}
 
 /* ------------------------ */
 /*  STATIC FUNCTIONS BELOW  */
 /* ------------------------ */
 
-QHash<const QString, bool> QFileSystemModelEx::s_hasFolderCache;
-QMutex QFileSystemModelEx::s_hasFolderMutex;
+QHash<const QString, bool> QFileSystemModelEx::s_hasSubfolderCache;
+QMutex QFileSystemModelEx::s_hasSubfolderMutex;
+
+void *QFileSystemModelEx::FindFirstFileExPtr = NULL;
+bool QFileSystemModelEx::FindFirstFileExInitialized = false;
+bool QFileSystemModelEx::FindFirstFileExInfoBasicOK = false;
 
 bool QFileSystemModelEx::hasSubfoldersCached(const QString &path)
 {
-       QMutexLocker lock(&s_hasFolderMutex);
-       
-       if(s_hasFolderCache.contains(path))
+       QMutexLocker lock(&s_hasSubfolderMutex);
+
+       if(s_hasSubfolderCache.contains(path))
        {
-               return s_hasFolderCache.value(path);
+               return s_hasSubfolderCache.value(path);
        }
        
        bool bChildren = hasSubfolders(path);
-       s_hasFolderCache.insert(path, bChildren);
+       s_hasSubfolderCache.insert(path, bChildren);
        return bChildren;
 }
 
 void QFileSystemModelEx::removeFromCache(const QString &path)
 {
-       QMutexLocker lock(&s_hasFolderMutex);
-       s_hasFolderCache.remove(path);
+       QMutexLocker lock(&s_hasSubfolderMutex);
+       s_hasSubfolderCache.remove(path);
+}
+
+void QFileSystemModelEx::removeAllFromCache(void)
+{
+       QMutexLocker lock(&s_hasSubfolderMutex);
+       s_hasSubfolderCache.clear();
 }
 
 bool QFileSystemModelEx::hasSubfolders(const QString &path)
 {
-       bool bChildren = false; WIN32_FIND_DATAW findData;
-       HANDLE h = FindFirstFileW(QWCHAR(QDir::toNativeSeparators(path + "/*")), &findData);
+       if(!FindFirstFileExInitialized)
+       {
+               QLibrary kernel32Lib("kernel32.dll");
+               if(kernel32Lib.load())
+               {
+                       FindFirstFileExPtr = kernel32Lib.resolve("FindFirstFileExW");
+                       DWORD osVersionNo = lamexp_get_os_version();
+                       FindFirstFileExInfoBasicOK = LAMEXP_MIN_OS_VER(osVersionNo, 6, 1);
+               }
+               FindFirstFileExInitialized = true;
+       }
+
+       WIN32_FIND_DATAW findData;
+       bool bChildren = false;
+
+       HANDLE h = (FindFirstFileExPtr)
+               ? reinterpret_cast<FindFirstFileExFun>(FindFirstFileExPtr)(QWCHAR(QDir::toNativeSeparators(path + "/*")), (FindFirstFileExInfoBasicOK ? FindExInfoBasic : FindExInfoStandard), &findData, FindExSearchLimitToDirectories, NULL, 0)
+               : FindFirstFileW(QWCHAR(QDir::toNativeSeparators(path + "/*")), &findData);
+
        if(h != INVALID_HANDLE_VALUE)
        {
                if(NO_DOT_OR_DOTDOT(findData.cFileName))
@@ -230,5 +284,14 @@ bool QFileSystemModelEx::hasSubfolders(const QString &path)
                }
                FindClose(h);
        }
+       else
+       {
+               DWORD err = GetLastError();
+               if((err == ERROR_NOT_SUPPORTED) || (err == ERROR_INVALID_PARAMETER))
+               {
+                       qWarning("%s failed with error code #%u", FindFirstFileExPtr ? "FindFirstFileEx" : "FindFirstFile", err);
+               }
+       }
+
        return bChildren;
 }