OSDN Git Service

Merge remote branch 'origin/2.1'
[qt-creator-jp/qt-creator-jp.git] / src / plugins / qmlprojectmanager / fileformat / filefilteritems.cpp
1 #include "filefilteritems.h"
2 #include <qdebug.h>
3 #include <QtGui/QImageReader>
4
5 namespace QmlProjectManager {
6
7 FileFilterBaseItem::FileFilterBaseItem(QObject *parent) :
8         QmlProjectContentItem(parent),
9         m_recurse(RecurseDefault)
10 {
11     connect(&m_dirWatcher, SIGNAL(directoryChanged(QString)), this, SLOT(updateFileList()));
12 }
13
14 QString FileFilterBaseItem::directory() const
15 {
16     return m_rootDir;
17 }
18
19 void FileFilterBaseItem::setDirectory(const QString &dirPath)
20 {
21     if (m_rootDir == dirPath)
22         return;
23     m_rootDir = dirPath;
24     emit directoryChanged();
25
26     updateFileList();
27 }
28
29 void FileFilterBaseItem::setDefaultDirectory(const QString &dirPath)
30 {
31     if (m_defaultDir == dirPath)
32         return;
33     m_defaultDir = dirPath;
34
35     updateFileList();
36 }
37
38 QString FileFilterBaseItem::filter() const
39 {
40     return m_filter;
41 }
42
43 void FileFilterBaseItem::setFilter(const QString &filter)
44 {
45     if (filter == m_filter)
46         return;
47     m_filter = filter;
48
49     m_regExpList.clear();
50     m_fileSuffixes.clear();
51
52     foreach (const QString &pattern, filter.split(QLatin1Char(';'))) {
53         if (pattern.isEmpty())
54             continue;
55         // decide if it's a canonical pattern like *.x
56         if (pattern.startsWith(QLatin1String("*."))) {
57             const QString suffix = pattern.right(pattern.size() - 1);
58             if (!suffix.contains(QLatin1Char('*'))
59                     && !suffix.contains(QLatin1Char('?'))
60                     && !suffix.contains(QLatin1Char('['))) {
61                 m_fileSuffixes << suffix;
62                 continue;
63             }
64         }
65         m_regExpList << QRegExp(pattern, Qt::CaseInsensitive, QRegExp::Wildcard);
66     }
67
68     updateFileList();
69 }
70
71 bool FileFilterBaseItem::recursive() const
72 {
73     bool recursive;
74     if (m_recurse == Recurse) {
75         recursive = true;
76     } else if (m_recurse == DoNotRecurse) {
77         recursive = false;
78     } else {  // RecurseDefault
79         if (m_explicitFiles.isEmpty()) {
80             recursive = true;
81         } else {
82             recursive = false;
83         }
84     }
85     return recursive;
86 }
87
88 void FileFilterBaseItem::setRecursive(bool recurse)
89 {
90     bool oldRecursive = recursive();
91
92     if (recurse) {
93         m_recurse = Recurse;
94     } else {
95             m_recurse = DoNotRecurse;
96     }
97
98     if (recurse != oldRecursive)
99         updateFileList();
100 }
101
102 QStringList FileFilterBaseItem::pathsProperty() const
103 {
104     return m_explicitFiles;
105 }
106
107 void FileFilterBaseItem::setPathsProperty(const QStringList &path)
108 {
109     m_explicitFiles = path;
110     updateFileList();
111 }
112
113 QStringList FileFilterBaseItem::files() const
114 {
115     return m_files.toList();
116 }
117
118 /**
119   Check whether filter matches a file path - regardless whether the file already exists or not.
120
121   @param filePath: absolute file path
122   */
123 bool FileFilterBaseItem::matchesFile(const QString &filePath) const
124 {
125     foreach (const QString &explicitFile, m_explicitFiles) {
126         if (absolutePath(explicitFile) == filePath)
127             return true;
128     }
129
130     const QString &fileName = QFileInfo(filePath).fileName();
131
132     if (!fileMatches(fileName))
133         return false;
134
135     const QDir fileDir = QFileInfo(filePath).absoluteDir();
136     foreach (const QString &watchedDirectory, m_dirWatcher.directories()) {
137         if (QDir(watchedDirectory) == fileDir)
138             return true;
139     }
140
141     return false;
142 }
143
144 QString FileFilterBaseItem::absolutePath(const QString &path) const
145 {
146     if (QFileInfo(path).isAbsolute())
147         return path;
148     return QDir(absoluteDir()).absoluteFilePath(path);
149 }
150
151 QString FileFilterBaseItem::absoluteDir() const
152 {
153     QString absoluteDir;
154     if (QFileInfo(m_rootDir).isAbsolute()) {
155         absoluteDir = m_rootDir;
156     } else if (!m_defaultDir.isEmpty()) {
157         absoluteDir = m_defaultDir + QLatin1Char('/') + m_rootDir;
158     }
159
160     return absoluteDir;
161 }
162
163 void FileFilterBaseItem::updateFileList()
164 {
165     const QString projectDir = absoluteDir();
166     if (projectDir.isEmpty())
167         return;
168
169     QSet<QString> dirsToBeWatched;
170     QSet<QString> newFiles;
171     foreach (const QString &explicitPath, m_explicitFiles) {
172         newFiles << absolutePath(explicitPath);
173     }
174     if ((!m_fileSuffixes.isEmpty() || !m_regExpList.isEmpty()) && m_explicitFiles.isEmpty())
175         newFiles += filesInSubTree(QDir(m_defaultDir), QDir(projectDir), &dirsToBeWatched);
176
177     if (newFiles != m_files) {
178         QSet<QString> addedFiles = newFiles;
179         QSet<QString> removedFiles = m_files;
180         QSet<QString> unchanged = newFiles;
181         unchanged.intersect(m_files);
182         addedFiles.subtract(unchanged);
183         removedFiles.subtract(unchanged);
184
185         m_files = newFiles;
186         emit filesChanged(addedFiles, removedFiles);
187     }
188
189     // update watched directories
190     const QSet<QString> oldDirs = m_dirWatcher.directories().toSet();
191     const QSet<QString> unwatchDirs = oldDirs - dirsToBeWatched;
192     const QSet<QString> watchDirs = dirsToBeWatched - oldDirs;
193
194     if (!unwatchDirs.isEmpty())
195         m_dirWatcher.removeDirectories(unwatchDirs.toList());
196     if (!watchDirs.isEmpty())
197         m_dirWatcher.addDirectories(watchDirs.toList());
198 }
199
200 bool FileFilterBaseItem::fileMatches(const QString &fileName) const
201 {
202     foreach (const QString &suffix, m_fileSuffixes) {
203         if (fileName.endsWith(suffix, Qt::CaseInsensitive)) {
204             return true;
205         }
206     }
207
208     foreach (const QRegExp &filter, m_regExpList) {
209         if (filter.exactMatch(fileName)) {
210             return true;
211         }
212     }
213
214     return false;
215 }
216
217 QSet<QString> FileFilterBaseItem::filesInSubTree(const QDir &rootDir, const QDir &dir, QSet<QString> *parsedDirs)
218 {
219     QSet<QString> fileSet;
220
221     if (parsedDirs)
222         parsedDirs->insert(dir.absolutePath());
223
224     foreach (const QFileInfo &file, dir.entryInfoList(QDir::Files)) {
225         const QString fileName = file.fileName();
226
227         if (fileMatches(fileName))
228             fileSet.insert(file.absoluteFilePath());
229     }
230
231     if (recursive()) {
232         foreach (const QFileInfo &subDir, dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot)) {
233             fileSet += filesInSubTree(rootDir, QDir(subDir.absoluteFilePath()), parsedDirs);
234         }
235     }
236     return fileSet;
237 }
238
239 QmlFileFilterItem::QmlFileFilterItem(QObject *parent)
240     : FileFilterBaseItem(parent)
241 {
242     setFilter(QLatin1String("*.qml"));
243 }
244
245 JsFileFilterItem::JsFileFilterItem(QObject *parent)
246     : FileFilterBaseItem(parent)
247 {
248     setFilter(QLatin1String("*.js"));
249 }
250
251 void JsFileFilterItem::setFilter(const QString &filter)
252 {
253     FileFilterBaseItem::setFilter(filter);
254     emit filterChanged();
255 }
256
257 ImageFileFilterItem::ImageFileFilterItem(QObject *parent)
258     : FileFilterBaseItem(parent)
259 {
260     QString filter;
261     // supported image formats according to
262     QList<QByteArray> extensions = QImageReader::supportedImageFormats();
263     foreach (const QByteArray &extension, extensions) {
264         filter.append(QString("*.%1;").arg(QString::fromAscii(extension)));
265     }
266     setFilter(filter);
267 }
268
269 void ImageFileFilterItem::setFilter(const QString &filter)
270 {
271     FileFilterBaseItem::setFilter(filter);
272     emit filterChanged();
273 }
274
275 CssFileFilterItem::CssFileFilterItem(QObject *parent)
276     : FileFilterBaseItem(parent)
277 {
278     setFilter(QLatin1String("*.css"));
279 }
280
281 void CssFileFilterItem::setFilter(const QString &filter)
282 {
283     FileFilterBaseItem::setFilter(filter);
284     emit filterChanged();
285 }
286
287 } // namespace QmlProjectManager
288