Updated Web Updater binary. Now takes an additional "Checksum" argument.
[LameXP.git] / src / Model_FileSystem.cpp
blob0bc9368fb3ad76533bad8b5a57329fdc3b0a5bd6
1 ///////////////////////////////////////////////////////////////////////////////
2 // LameXP - Audio Encoder Front-End
3 // Copyright (C) 2004-2015 LoRd_MuldeR <MuldeR2@GMX.de>
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version, but always including the *additional*
9 // restrictions defined in the "License.txt" file.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License along
17 // with this program; if not, write to the Free Software Foundation, Inc.,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 // http://www.gnu.org/licenses/gpl-2.0.txt
21 ///////////////////////////////////////////////////////////////////////////////
23 #include "Model_FileSystem.h"
25 //Internal
26 #include "Global.h"
28 //MUtils
29 #include <MUtils/Global.h>
30 #include <MUtils/OSSupport.h>
32 //Qt
33 #include <QApplication>
34 #include <QFileIconProvider>
35 #include <QDesktopServices>
36 #include <QLibrary>
38 //Windows includes
39 #define NOMINMAX
40 #define WIN32_LEAN_AND_MEAN
41 #include <Windows.h>
43 #define IS_DIR(ATTR) (((ATTR) & FILE_ATTRIBUTE_DIRECTORY) && (!((ATTR) & FILE_ATTRIBUTE_HIDDEN)))
44 #define NO_DOT_OR_DOTDOT(STR) (wcscmp((STR), L".") && wcscmp((STR), L".."))
46 ///////////////////////////////////////////////////////////////////////////////
47 // Dummy QFileIconProvider class
48 ///////////////////////////////////////////////////////////////////////////////
50 class QFileIconProviderEx : public QFileIconProvider
52 public:
53 QFileIconProviderEx();
54 virtual QIcon icon(IconType type) const { return (type == Drive) ? m_driveIcon : m_folderIcon; }
55 virtual QIcon icon(const QFileInfo &info) const;
56 virtual QString type (const QFileInfo &info) const { return info.isDir() ? m_folderType : m_emptyType; }
58 private:
59 const QIcon m_driveIcon;
60 const QIcon m_cdromIcon;
61 const QIcon m_networkIcon;
62 const QIcon m_floppyIcon;
63 const QIcon m_folderIcon;
64 const QIcon m_homeIcon;
65 const QIcon m_desktopIcon;
66 const QIcon m_musicIcon;
67 const QIcon m_moviesIcon;
68 const QIcon m_picturesIcon;
69 const QIcon m_heartIcon;
70 const QIcon m_emptyIcon;
71 const QString m_folderType;
72 const QString m_emptyType;
73 const QString m_homeDir;
74 const QString m_desktopDir;
75 const QString m_musicDir;
76 const QString m_moviesDir;
77 const QString m_picturesDir;
78 const QString m_installDir;
81 QFileIconProviderEx::QFileIconProviderEx()
83 m_folderIcon(":/icons/folder.png"),
84 m_driveIcon(":/icons/drive.png"),
85 m_cdromIcon(":/icons/drive_cd.png"),
86 m_networkIcon(":/icons/drive_link.png"),
87 m_floppyIcon(":/icons/drive_disk.png"),
88 m_homeIcon(":/icons/house.png"),
89 m_desktopIcon(":/icons/monitor.png"),
90 m_musicIcon(":/icons/music.png"),
91 m_moviesIcon(":/icons/film.png"),
92 m_picturesIcon(":/icons/picture.png"),
93 m_heartIcon(":/icons/heart.png"),
94 m_homeDir(QDir::fromNativeSeparators(QDesktopServices::storageLocation(QDesktopServices::HomeLocation))),
95 m_desktopDir(QDir::fromNativeSeparators(QDesktopServices::storageLocation(QDesktopServices::DesktopLocation))),
96 m_musicDir(QDir::fromNativeSeparators(QDesktopServices::storageLocation(QDesktopServices::MusicLocation))),
97 m_moviesDir(QDir::fromNativeSeparators(QDesktopServices::storageLocation(QDesktopServices::MoviesLocation))),
98 m_picturesDir(QDir::fromNativeSeparators(QDesktopServices::storageLocation(QDesktopServices::PicturesLocation))),
99 m_installDir(QDir::fromNativeSeparators(qApp->applicationDirPath())),
100 m_folderType("Folder")
102 /*nothing to do*/
105 QIcon QFileIconProviderEx::icon(const QFileInfo &info) const
107 if(info.isFile())
109 return m_emptyIcon;
111 else if(info.isRoot())
113 switch(GetDriveType(MUTILS_WCHR(QDir::toNativeSeparators(info.absoluteFilePath()))))
115 case DRIVE_CDROM:
116 return m_cdromIcon;
117 break;
118 case DRIVE_REMOVABLE:
119 return m_floppyIcon;
120 break;
121 case DRIVE_REMOTE:
122 return m_networkIcon;
123 break;
124 default:
125 return m_driveIcon;
126 break;
129 else
131 const QString filePath = info.filePath();
132 if(m_homeDir.compare(filePath, Qt::CaseInsensitive) == 0)
134 return m_homeIcon;
136 else if(m_desktopDir.compare(filePath, Qt::CaseInsensitive) == 0)
138 return m_desktopIcon;
140 else if(m_musicDir.compare(filePath, Qt::CaseInsensitive) == 0)
142 return m_musicIcon;
144 else if(m_moviesDir.compare(filePath, Qt::CaseInsensitive) == 0)
146 return m_moviesIcon;
148 else if(m_picturesDir.compare(filePath, Qt::CaseInsensitive) == 0)
150 return m_picturesIcon;
152 else if(m_installDir.compare(filePath, Qt::CaseInsensitive) == 0)
154 return m_heartIcon;
156 else
158 return m_folderIcon;
163 ///////////////////////////////////////////////////////////////////////////////
164 // Modified QFileSystemModel class
165 ///////////////////////////////////////////////////////////////////////////////
167 QFileSystemModelEx::QFileSystemModelEx()
169 QFileSystemModel()
171 this->m_myIconProvider = new QFileIconProviderEx();
172 this->setIconProvider(m_myIconProvider);
173 this->setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
174 this->setNameFilterDisables(false);
177 QFileSystemModelEx::~QFileSystemModelEx()
179 removeAllFromCache();
180 MUTILS_DELETE(m_myIconProvider);
183 bool QFileSystemModelEx::hasChildren(const QModelIndex &parent) const
185 if(parent.isValid())
187 return hasSubfoldersCached(filePath(parent).toLower()); //return (QDir(QFileSystemModel::filePath(parent)).entryList(QDir::Dirs | QDir::NoDotAndDotDot).count() > 0);
189 return true;
192 void QFileSystemModelEx::fetchMore(const QModelIndex &parent)
194 if(parent.isValid())
196 removeFromCache(filePath(parent).toLower());
199 QFileSystemModel::fetchMore(parent);
202 QModelIndex QFileSystemModelEx::index(const QString &path, int column) const
204 QFileInfo info(path);
205 if(info.exists() && info.isDir())
207 QString fullPath = QDir::fromNativeSeparators(info.canonicalFilePath());
208 QStringList parts = fullPath.split('/', QString::SkipEmptyParts);
209 for(int i = 2; i <= parts.count(); i++)
211 QFileInfo currentPath(((QStringList) parts.mid(0, i)).join("/"));
212 if((!currentPath.exists()) || (!currentPath.isDir()) || currentPath.isHidden())
214 return QModelIndex();
217 QModelIndex index = QFileSystemModel::index(fullPath, column);
218 if(index.isValid())
220 QModelIndex temp = index;
221 while(temp.isValid())
223 removeFromCache(filePath(temp).toLower());
224 temp = temp.parent();
226 return index;
229 return QModelIndex();
232 void QFileSystemModelEx::flushCache(void)
234 removeAllFromCache();
237 /* ------------------------ */
238 /* STATIC FUNCTIONS BELOW */
239 /* ------------------------ */
241 QHash<const QString, bool> QFileSystemModelEx::s_hasSubfolderCache;
242 QMutex QFileSystemModelEx::s_hasSubfolderMutex;
243 int QFileSystemModelEx::s_findFirstFileExInfoLevel = INT_MAX;
245 bool QFileSystemModelEx::hasSubfoldersCached(const QString &path)
247 QMutexLocker lock(&s_hasSubfolderMutex);
249 if(s_hasSubfolderCache.contains(path))
251 return s_hasSubfolderCache.value(path);
254 bool bChildren = hasSubfolders(path);
255 s_hasSubfolderCache.insert(path, bChildren);
256 return bChildren;
259 void QFileSystemModelEx::removeFromCache(const QString &path)
261 QMutexLocker lock(&s_hasSubfolderMutex);
262 s_hasSubfolderCache.remove(path);
265 void QFileSystemModelEx::removeAllFromCache(void)
267 QMutexLocker lock(&s_hasSubfolderMutex);
268 s_hasSubfolderCache.clear();
271 bool QFileSystemModelEx::hasSubfolders(const QString &path)
273 if(s_findFirstFileExInfoLevel == INT_MAX)
275 const MUtils::OS::Version::os_version_t &osVersion = MUtils::OS::os_version();
276 s_findFirstFileExInfoLevel = (osVersion >= MUtils::OS::Version::WINDOWS_WIN70) ? FindExInfoBasic : FindExInfoStandard;
279 WIN32_FIND_DATAW findData;
280 bool bChildren = false;
282 HANDLE h = FindFirstFileEx(MUTILS_WCHR(QDir::toNativeSeparators(path + "/*")), ((FINDEX_INFO_LEVELS)s_findFirstFileExInfoLevel), &findData, FindExSearchLimitToDirectories, NULL, 0);
284 if(h != INVALID_HANDLE_VALUE)
286 if(NO_DOT_OR_DOTDOT(findData.cFileName))
288 bChildren = IS_DIR(findData.dwFileAttributes);
290 while((!bChildren) && FindNextFile(h, &findData))
292 if(NO_DOT_OR_DOTDOT(findData.cFileName))
294 bChildren = IS_DIR(findData.dwFileAttributes);
297 FindClose(h);
299 else
301 DWORD err = GetLastError();
302 if((err == ERROR_NOT_SUPPORTED) || (err == ERROR_INVALID_PARAMETER))
304 qWarning("FindFirstFileEx failed with error code #%u", err);
308 return bChildren;